Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value Remapping

Processing has a great function I use all the time:

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

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

It remaps value (that has an expected range of low1 to high1) into a target range of low2 to high2).

I want to understand the math behind it so I can use it in other languages. Anyone want to throw me a bone and help me reverse engineer it? I understand that it's a lerp that's been re-scaled and re-offset... feeling brain dead this morning.

like image 708
ack Avatar asked Aug 10 '10 17:08

ack


3 Answers

From your description, it ought to be doing this, right?

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

Find how far you are into the first range, scale that distance by the ratio of sizes of the ranges, and that's how far you should be into the second range.

like image 103
Cascabel Avatar answered Oct 12 '22 10:10

Cascabel


Processing is open-source. You can view the map() function here.

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;
  }

Specifically, you're looking for this line of code:

float outgoing =
      start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
like image 29
Kevin Workman Avatar answered Oct 12 '22 12:10

Kevin Workman


I would like to add that is sometimes useful to find the factor between the low1 and high1 so that you can modulate it with a curve before using the factor as a LERP's t.

So, t = (value-low1)/(high1-low1) to get the relative position of value in the line low1 to high1.

Then you can modulate t with some curve filter for example, gamma, bias, gain, etc As also clamp the t between 0 and 1 if you to restrict values that go over the set lows and highs.

And then use the t for the LERP between low2 and high2 like: finalvalue = low2*(1-t) + high2*t

like image 26
probiner Avatar answered Oct 12 '22 11:10

probiner