# How to incorporate exponential curve with a specified limit?

Hello!
I’m playing with randomGaussians, and gradual transitions, trying to understand the concept, and I’ve hit a bit of a snag.
I’m hoping someone can help with the math involved.

I’m drawing simple squares in a grid pattern. I’d like the left side of the grid to be… “normal.”
All the squares are drawn as they should be, in a simple grid.
But as we get to the right side of the grid, I’d like square placement to become more “crazy.”

So this is what I’ve got so far.

``````size(800, 400);
int scale = 10;
background(0);
noStroke();
rectMode(CENTER);

for (int x = 0; x <= width; x += scale) {
for (int y = 0; y <= height; y += scale) {

float pDistribution = map(x, 0, width, 0, 15);

float xDrift = randomGaussian() * pDistribution;
float yDrift = randomGaussian() * pDistribution;

fill(200);
push();
translate(x, y);
rect(xDrift, yDrift, scale, scale);
pop();
}
}
``````

I’m proud of getting this far, because it’s doing essentially what I want.
The only thing is, I’d like the Gaussian Distribution to have a more exponential curve.
Hopefully, I’m using the correct terminology here.
Basically, I’d like the squares to be in their more “correct” spots a bit longer longer as we travel across x.
The squares on the far left and far right are exactly where I want them, but I’d like the middle to chill out a bit.

Because of the word “exponential”, I thought maybe `exp()` should go in there somewhere, but I don’t really understand how it would fit.

If I need to rephrase or clarify what I’m asking, please let me know!
Any advice would be greatly appreciated!

you can oppress this

``````    float pDistribution;
if (x<300) pDistribution = 0;
else pDistribution = map(x, 300, width, 0, 15);  // OR  map(x, 0, width, 0, 15);
``````

Hello leatherbird,

Cool project!

You are on the right track.
The problem with `exp()` is that it diverges wayyyyy too fast.

For example, exp(10) is a bit more than 22000.
Now let’s consider that `randomGaussian()` gives you a value between -3 and 3 to simplify things.
Then it means that when you are at your second square (so x = 10) your drifts value are between - 3 * 22000 and + 3 * 22000.
That’s quite a lot of pixels and that’s why you don’t get any squares on your screen.

So what you want is a function that behaves in the same way as you an exp() but with the max value when x = width being the 15 that you have in your linear mapping in your code.

A good way to think of it is to trace the function along the x axis on top of your graph. The Higher the value, the higher they will drift.

Here is an example with a sin():

``````void setup() {

size(800, 400);
int scale = 10;
background(0);
noStroke();
rectMode(CENTER);

for (int x = 0; x <= width; x += scale) {
float sinVal = 7.5 * (sin(0.03 * x) + 1);

for (int y = 0; y <= height; y += scale) {

float xDrift = randomGaussian() * sinVal;
float yDrift = randomGaussian() * sinVal;

fill(200);
push();
translate(x, y);
rect(xDrift, yDrift, scale, scale);
pop();
}
}

// Plot the sin
for (int x = 0; x <= width; x++) {
float sinVal = 7.5 * (sin(0.03 * x) + 1);
float yCoord = map(sinVal, 0, 15, height, 0);
fill(255, 0, 0);
noStroke();
ellipse(x, yCoord, 5, 5);
}
}
``````

Now for your function. You know that `exp(log(15)) = 15`. And you want you value to be 15 when x = width. So you can have `exp(log(15) * x / width)` being your function. Now it doesn’t start at 0 but at exp(0). So to compensate for that you can use `exp(log(15 + exp(0)) * x / width) - exp(0)`. So at the end you get:

``````void setup() {

size(800, 400);
int scale = 10;
background(0);
noStroke();
rectMode(CENTER);

for (int x = 0; x <= width; x += scale) {
float expVal = exp(log(15 + exp(0)) * x / width) - exp(0);

for (int y = 0; y <= height; y += scale) {

float xDrift = randomGaussian() * expVal;
float yDrift = randomGaussian() * expVal;

fill(200);
push();
translate(x, y);
rect(xDrift, yDrift, scale, scale);
pop();
}
}

// Plot the exp
for (int x = 0; x <= width; x++) {
float expVal = exp(log(15 + exp(0)) * x / width) - exp(0);
float yCoord = map(expVal, 0, 15, height, 0);
fill(255, 0, 0);
noStroke();
ellipse(x, yCoord, 5, 5);
}
}
``````

5 Likes

Thank you! This is exactly what I was attempting.
I guess I don’t fully understand what `log()` or `exp()` are doing.
I will have to research these further before I comprehend them well enough to control them.

But now I know what I need to study!
I’m grateful to you for pointing me in the right direction!
Thank you so much!

2 Likes

By the way, with your help I was able to get the look I wanted!
I’m so excited to keep playing with it!

6 Likes

Great write up @jb4x! I love the curve overlays.

1 Like