27

Processing 有一个很棒的功能,我一直在使用:

map(value, low1, high1, low2, high2)

http://processing.org/reference/map_.html

value它将(预期范围为low1to )重新映射high1到目标范围low2to high2)。

我想了解它背后的数学原理,以便可以在其他语言中使用它。有人想扔给我一根骨头并帮助我对其进行逆向工程吗?我知道这是一个被重新调整和重新抵消的 lerp……今天早上感觉脑死了。

4

4 回答 4

50

从你的描述来看,应该是这样吧?

low2 + (value - low1) * (high2 - low2) / (high1 - low1)

找出您在第一个范围内的距离,按范围大小的比例缩放该距离,这就是您应该在第二个范围内的距离。

于 2010-08-10T17:16:25.953 回答
8

处理是开源的。您可以在此处map()查看该功能。

static public final float map(float value,
                                float start1, float stop1,
                                float start2, float stop2) {
    float outgoing =
      start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
    String badness = null;
    if (outgoing != outgoing) {
      badness = "NaN (not a number)";

    } else if (outgoing == Float.NEGATIVE_INFINITY ||
               outgoing == Float.POSITIVE_INFINITY) {
      badness = "infinity";
    }
    if (badness != null) {
      final String msg =
        String.format("map(%s, %s, %s, %s, %s) called, which returns %s",
                      nf(value), nf(start1), nf(stop1),
                      nf(start2), nf(stop2), badness);
      PGraphics.showWarning(msg);
    }
    return outgoing;
  }

具体来说,您正在寻找这行代码:

float outgoing =
      start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
于 2018-04-02T21:59:49.133 回答
2

我想补充一点,有时这对于找到 low1 和 high1 之间的因子很有用,这样您就可以在将因子用作 LERP 的 t 之前用曲线对其进行调制。

因此,t = (value-low1)/(high1-low1) 得到值在行 low1 到 high1 中的相对位置。

然后,您可以使用一些曲线滤波器调制 t,例如伽马、偏置、增益等,如果您限制超过设定的低点和高点的值,也可以将 t 钳制在 0 和 1 之间。

然后将 t 用于 low2 和 high2 之间的 LERP,例如: finalvalue = low2*(1-t) + high2*t

于 2015-11-16T14:39:16.553 回答
1

有人想知道是否有一个无浮点版本可以保持尽可能高的精度,我做了这个:

int remap(int value, int input_min, int input_max, int output_min, int output_max)
{
    const long long factor = 1000000000;

    long long output_spread = output_max - output_min;
    long long input_spread = input_max - input_min;

    long long l_value = value;

    long long zero_value = value - input_min;
    zero_value *= factor;
    long long percentage = zero_value / input_spread;

    long long zero_output = percentage * output_spread / factor;

    long long result = output_min + zero_output;

    return (int)result;
}

似乎对我有用,没有经过广泛测试(例如 max 小于 min 未测试)。

背后的想法是通过使用更大的类型来扩大原始值,以便除法产生更大的数字——从而提高精度。

于 2020-05-25T01:50:58.807 回答