How to create a slider with a non-linear scale?

A good formula for the displayed value is a monotonous function such as a power curve, in the following form:

DisplayValue = A + B * Math.Exp(C * SliderValue);

The internal slider value (from 0 to 1 for instance) is obtained by inverting the formula:

SliderValue = Math.Log((DisplayValue - A) / B) / C;

Now how to obtain A, B and C? By using the three constraints you gave:

f(0.0) = 0
f(0.5) = 100
f(1.0) = 500

Three equations, three unknowns, this is solved using basic maths:

A + B = 0
A + B exp(C * 0.5) = 100
A + B exp(C) = 500

B (exp(C * 0.5) - 1) = 100
B (exp(C) - 1) = 500

exp(C) - 5 exp(C * 0.5) + 4 = 0  // this is a quadratic equation

exp(C * 0.5) = 4

C = log(16)
B = 100/3
A = -100/3

Yielding the following code:

double B = 100.0 / 3;
double C = Math.Log(16.0);
DisplayValue = B * (Math.Exp(C * SliderValue) - 1.0);

You can see that the display value is at 100 when the internal value is in the middle:

final curve

Edit: since a generic formula was requested, here it is. Given:

f(0.0) = x
f(0.5) = y
f(1.0) = z

The values for A, B and C are:

A = (xz - y²) / (x - 2y + z)
B = (y - x)² / (x - 2y + z)
C = 2 * log((z-y) / (y-x))

Note that if x - 2y + z or y - x is zero, there is no solution and you’ll get a division by zero. That’s because in this case, the scale is actually linear. You need to take care of that special case.


let the slider as it is and use a ValueConverter for your bindings. In the ValueConverter use the non-linear scaling to scale the value as you wish.

Tags:

C#

.Net

Wpf