0

I get values in the Range of -360 to 360 that should be mapped to a sequence corresponding to fractions of 45. (Or any other value, Im really more interested in the mapping algorithm than the use case here).

IN -360 -315 -270 -225 -180 -135 -90 -45 0 45 90 135 180 225 270 325 360
STEP 0 1 0 -1 0 1 0 -1 0 1 0 -1 0 1 0 -1 0
OUT 0 45 0 -45 0 45 0 -45 0 45 0 -45 0 45 0 -45 0

Is there a linear Transformation I can/should use? Or how do I set up a mapping like:

var mapRange = function(base_range, target_range, s) {
  return target_range[0] + (s - base_range[0]) * (target_range[1] - target_range[0]) / (base_range[1] - base_range[0]);
};

for this?

edit: Added the desired output. Thought breaking it down to a -1 to 1 range would imply the trivial *45

D.icon
  • 396
  • 3
  • 14
  • You talking about mapping to *... a sequence corresponding to fractions of 45...* but I don't see that. I see inputs that differ by 45 being mapped to {-1, 0, 1} with the output a repeating pattern of 0, 1, 0, -1. – President James K. Polk Sep 27 '22 at 23:35
  • @PresidentJamesK.Polk edited for clarification. As I'm more interested in the method of mapping to sequences, I thought the *45 after the mapping step would be trivial. – D.icon Sep 27 '22 at 23:59

1 Answers1

2

What you are looking for is a triangle wave, which can be computed using this formula:

4 * a / p * abs(((i - p / 4) % p) - p / 2) - a

Note that % in the formula is modulo, not remainder, so in JavaScript we need to define a function to return the expected result (see the docs, and some sample functions here).

In your case, a (the amplitude) is 1, and p (the period) is 180. You can write a function to compute the value and then use it to compute individual values:

const mod = (n, m) => ((n % m) + m) % m

const triWave = (i, a, p) => 4 * a / p * Math.abs(mod(i - p / 4, p) - p / 2) - a

console.log(triWave(22.5, 1, 180))
console.log(triWave(-56.25, 1, 180))

const inp = Array.from({ length: 17 }, (_, i) => -360 + 45 * i)
const steps = inp.map(i => triWave(i, 1, 180))

console.log(steps)
Nick
  • 138,499
  • 22
  • 57
  • 95
  • That works for whole number dividents of 45. But as I need a mapping, the stepping is off for all other values. For Input: 22.5 I'd expect the output 0.5 in the [-1,1] range, stepping with your proposal would give 0.71 . Or another example: Input -56.25 should be mapped to -0.75, but the step sets it to -0.92 – D.icon Sep 28 '22 at 00:50
  • @D.icon ah... I just went from your sample data in the question. It wasn't clear that you wanted to interpolate linearly between those values as well. Give me a minute to edit... – Nick Sep 28 '22 at 00:53
  • @D.icon Sorry, got called away. please see my edit – Nick Sep 28 '22 at 01:44
  • perfect solution, especially that it is as versatile as I hoped! – D.icon Sep 28 '22 at 16:44
  • @D.icon good to hear. I'm glad I could help – Nick Sep 28 '22 at 22:19