Переназначение значений

У обработки есть отличная функция, которую я использую все время:

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

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

Он переназначает value (который имеет ожидаемый диапазон от low1 до high1) в целевой диапазон от low2 до high2).

Я хочу понять математику, стоящую за этим, чтобы использовать его на других языках. Кто-нибудь хочет бросить мне кость и помочь мне реконструировать ее? Я так понимаю, что это лерп, которого перемасштабировали и сместили... сегодня утром он чувствует себя мертвым.


person ack    schedule 10.08.2010    source источник


Ответы (4)


Судя по твоему описанию, так и должно быть, верно?

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

Найдите, как далеко вы находитесь в первом диапазоне, масштабируйте это расстояние по соотношению размеров диапазонов, и вот как далеко вы должны быть во втором диапазоне.

person Cascabel    schedule 10.08.2010

Обработка с открытым исходным кодом. Вы можете просмотреть функцию 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));
person Kevin Workman    schedule 02.04.2018

Я хотел бы добавить, что иногда полезно найти коэффициент между low1 и high1, чтобы вы могли модулировать его с помощью кривой, прежде чем использовать коэффициент в качестве t LERP.

Итак, t = (value-low1)/(high1-low1), чтобы получить относительное положение значения в строке от low1 до high1.

Затем вы можете модулировать t с помощью некоторого фильтра кривой, например, гаммы, смещения, усиления и т. Д. Также можно зафиксировать t между 0 и 1, если вы ограничиваете значения, превышающие установленные минимумы и максимумы.

А затем используйте t для LERP между low2 и high2, например: finalvalue = low2*(1-t) + high2*t

person probiner    schedule 16.11.2015

Всем, кто интересуется, есть ли версия без поплавка, которая сохраняет максимальную точность, я сделал это:

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, не тестировалось).

Идея заключается в том, чтобы увеличить исходное значение, используя более крупный тип, чтобы деление давало большие числа, что приводит к большей точности.

person Gizmo    schedule 25.05.2020