移位数字范围的中点

时间:2018-07-04 16:28:07

标签: c# math

我有一个将任何数字范围归一化为新范围的功能。

例如
[123,456][0,10]

[-50,50][-1,1]

我需要帮助来移动新范围的中点。

我正在将它用于GUI滑块,其范围为[-100,100],但控制值为[-2,2]
GUI Slider的默认值为0,但默认值为1(无)。
我的程序是CLI的GUI,我无法将该程序的默认值更改为0

slider

Slider
-100 --------------||-------------- 100
                    0
Value
-2 |  |  | -1 |  |  0|  |  | 1  |  |  2

Shifted Value
-2 |  | -1 |  | 0 | 1|  |  |  |  |  | 2

归一化

https://dotnetfiddle.net/42jHvM

// Normalize Function
public static double Normalize(double val, double valmin, double valmax, double min, double max, double midpoint) 
{
    return (((val - valmin) / (valmax - valmin)) * (max - min)) + min;
}

double output = Normalize(  0, // slider input
                         -100, // input min
                          100, // input max
                           -2, // normalize min
                            2, // normalize max
                            1  // middle point
                         );

Shift Middle Point

在我的示例中,我使用[-100,100]转换为[-2,2]

input [-100,100]的中间点是0
但是我需要output [-2,2]拥有1而不是0的中间点。

因此它会偏斜,向-2方向变慢,向2方向变快。

示例我在photoshop中制作的图像使用渐变显示了中点偏移。

shift

轻松

我尝试使用Ease Out Tween来移动中间点,但是我不知道要使用什么值。
示例输出必须为Min: -2Mid: 1Max: 2

https://dotnetfiddle.net/nfNlBC

它使用:

//t: current time
//b: start value
//c: change in value
//d: duration

中点偏移后:

输入-100应该输出-2
输入-50应该输出-0.50
输入0应该输出1
输入50应该输出1.75
输入100应该输出2

之前

-100 | -50 | -25  |  0  |  25 |  50 | 100

 -2  | -1  | -0.5 |  0  | 0.5 |  1  |  2

之后 approximated

-100 | -50  | -25  |  0  |  25  |  50  | 100

 -2  |-0.50 | 0.25 |  1  | 1.25 | 1.75 |  2

问题

如何修改Normalize函数或通过新的Shift / Easing函数运行其输出以设置范围的新中点并重新调整数字?

2 个答案:

答案 0 :(得分:2)

有多种方法可以完成此操作,但是如果线性插值就足够了,那么您可以使用带有分段函数的输入参数进行一些简单的拉伸和压缩。

public static double Interpolate(double val, double valmin, double valmax, double min, double max)
{
    return (max - min) * (val - 0.5 * (valmax + valmin)) / (valmax - valmin) + 0.5 * (max + min);
}

public static double Normalize(double val, double valmin, double valmax, double min, double max, double midpoint)
{
    double m = Interpolate(midpoint, valmin, valmax, min, max);
    if (val < m) {
        return Interpolate(val, valmin, m, min, midpoint);
    } else if (val > m) {
        return Interpolate(val, m, valmax, midpoint, max);
    } else {
        return m;
    }
}

您应该能够用更高级的内容(例如您链接的一种缓动形式)替换Interpolate,并使用以下从您的参数名称到其参数名称的映射:

t = val - 0.5 * (valmax + valmin)
b = 0.5 * (max + min)
c = max - min
d = valmax - valmin

答案 1 :(得分:2)

我不明白您为什么需要这样的映射,但是要做的方法是:

public static double Normalize( double val, double valmin, double valmax, double min, double max, double midpoint )
{
  double mid = ( valmin + valmax ) / 2.0;
  if ( val < mid )
  {
    return ( val - valmin ) / ( mid - valmin ) * ( midpoint - min ) + min;
  }
  else
  {
    return ( val - mid ) / ( valmax - mid ) * ( max - midpoint ) + midpoint;
  }
}