Math with map() to get rising and falling numbers from an increasing value

I have an interesting math and coding question. I had no idea how to explain this in just the title.

I have int iValue = 0; and every second, iValue increases by one.

1  2  3  4  5  6  7  8  9  10  11 12  13  14  15  16  17  18  19  20 . . .

You get the idea.

So I want to get int newValue = 0 to increase, and then decrease, equally, when iValue increases. Let me show you an example so you can understand better.

In this example, iValue will start at 0, and will increase until it hits 21. When iValue hits 21, it resets to 0, and continues to increase to 21… This goes on while the program is running.

iValue: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 0 1 2 3 . . .

Now, newValue will rise and fall as iValue increases. newValue's min will be 0, and max 3. Let me show you both iValue and newValue together:
iValue: --1--2--3--4--5--6--7--8--9--10--11--12--13--14--15--16--17--18--19--20--21
newValue: 0--0--0--1--1--2--2--3--3---3---3---3---3---3---2---2---1---1---0---0---0

Alright, I hope the above example helped make sense. You may notice a few things though:

  • Not all the numbers were represented equally
  • 3s and 0s got more values and next to each other (because it repeats)

I will need to have enough flexibility to “squeeze” certain values tighter together, and to “spread” others out more over more time. “Squeeze” in the above example means show fewer values like the 1s and 2s. “Spread” in the above example means to cover more of a value like the 3s and 0s.

If none of that helped explain it, here is the real-life-example why I need something like this:

I am creating a day/night cycle on a planet. Now I say planet, because not all planets have the same day/night cycle. So I need a function (or several functions) that will help me be flexible enough between how long the day or night lasts, as well as how long the transition lasts between day/night (which is the “squeezed” values in my other example).

So that is my problem and the goal I hope to achieve in the end. I am sure if I thought more about it and if I had more math knowledge, I could explain it better.
Do you have any suggestions on how I could do this?

1 Like

Hello,

My exploration of this… :)

I start with simple and work from there; my mind is already working on cool embellishments.

Create a number of variables that were important to plotting the curve.

Join the points with line():
https://processing.org/reference/line_.html

I used map() to vary some of the data points to animate it.

I zeroed all the variables in the example below; that is left as an exercise if you so choose.

Example :

int hrsDaylight = 0;    //Daylight hours total 
int startDaylight = 0;  //Daylight hours start
int endDaylight = 0;    //Difference of above + ramps
int hrsRamp = 0;        //Ramp up and down
int hrsStart = 0;       //Start of day
int hrsEnd = 0;         //End of day

void setup() 
  {
  size(400, 200);
  }

void draw() 
  {
  background(0);
  
  startDaylight = int(map(mouseX, 0, width, 0, 0));
  hrsDaylight = int(map(mouseY, 0, width, 0, 0));
  
  stroke(255, 255, 0);
  strokeWeight(3);
  translate((width-240)/2, height/4);
  
  line(0,0, 0, 0);
  line(0,0, 0, 0);
  line(0,0, 0, 0);
  line(0,0, 0, 0);
  line(0,0, 0, 0);
  line(0,0, 0, 0);
  line(0,0, 0, 0);
  }

This was animated as I moved mouse along x and y:

image

image

:)

References:
https://processing.org/examples/pointslines.html
Many more at Processing website.

1 Like

First of all, generating a linear range using a parent range:

int ackados(int range1Max, int range2Max, float range1In) {
  float x = map(range1In, 0, range1Max, 0, 2*range2Max);
  float y = range2Max - abs(x % (2*range2Max) - range2Max); // triangle wave function
  return round(y);
}

void setup() {
  for (int i = 0; i <= 21; i++) {
    print(ackados(21, 3, i));
  }
}

Out:

0011112223333222111100

Not all the numbers were represented equally

To satisfy this, we need to make this range non-linear such it ramps up quickly towards the ceiling value of the range. A suitable function is e^x - 1.

int ackados(int range1Max, int range2Max, float range1In) {
  float x = map(range1In, 0, range1Max, 0, 2*range2Max);
  float y = range2Max - abs(x % (2*range2Max) - range2Max); // triangle wave function
  float z = map(y, 0, range2Max, 0, 1); // scale value down to range 0...1
  z = min(pow(exp(1), z) - 1, 1); // apply the function, cap at 1.0
  z*=range2Max; // scale back up
  return round(z);
}

void setup() {
  for (int i = 0; i <= 21; i++) {
    print(ackados(21, 3, i));
  }
}

Out:

0011122333333332211100

If you want adjust how long the transition lasts, then multiply z by a transtion factor. e.g. @ 2:
z = min(pow(exp(1), z*2) - 1, 1);

Out:

0112333333333333332110

e^x - 1:

1 Like

Are you only after generating the number sequence, or is this the description of the evolution of another parameter over time?

  • If the former, you should be able to express this deterministically using an analytical expression such as the square wave mentioned above. Or we can look for more custom functions together.

The example you gave:

could be described using the floor() of a well-chosen sin() so that you’re stalling close to the extremes and going faster in the ramp up/down phases. (Please let me know if I’m missing the point entirely).

  • If the latter, you could think of using some animation library such as Ani and use custom easing functions (Ani has a bunch of built-in functions but you can add your own too).