set values to match ellipse
in
Programming Questions
•
1 year ago
I posted this a long time ago.
Now i digged into it again, and instead of making a reply under it i choosed to edit the opening post to make things more clear.
Ok, this is not the most easy question so i hope someone can help.
Now i digged into it again, and instead of making a reply under it i choosed to edit the opening post to make things more clear.
Ok, this is not the most easy question so i hope someone can help.
Step 1 is storing noise values in a float[][] array which we call field.
Easy step, no problems.
Then i want to change the values so the match the image below:
So as you can see the outside is black in some kind of ellipse kind of way.
For now i want to use a perfect ellipse, later more something like this (image in topic):
https://forum.processing.org/topic/how-to-make-perlin-noise-loop
My idea is to get for each cell the distance from the center to the edge of a imaginary ellipse.
Like in the image below, if the distance from the center cell to the current cell if larger then the distance to the ellipse edge then multiply the noise value with 0 (area of red line).
If it's less then multiply based on the distance, so the closer to the center the more it will be multiplied with 1 and therefor is closer to the original value.
Here i illustrate my current state.
You can see the float[][] array, the index to each cell is above and on the left.
[0][0] is left top for example and [5][2] is the center.
The angles are calculated from the center to each cell (shown in red type), i only show to the corner and to the center of edges, this is also correct.
Then there is the part where the red line would intersect with the green ellipse line.
This is quite close, first one is correct but if you look at the second one, cell[5][0] it says it would hit at x 5.5 and y 5.0 but the y for it should be 0.0 as you can see on the image.
I hope someone can help.
(Note that the center value is also printed in console, so of cell[5][2])
- int xSteps = 11;
- int ySteps = 5;
- float[][] field;
- float perlinZoom = 0.2;
- void setup() {
- size(600, 300);
- smooth();
- field = createField(xSteps, ySteps);
- improveContrast(field, 0.0, 0.7);
- blurEdgesField(field);
- }
- // . . . . . . . . . . . . . . . . . . .
- void draw() {
- background(255);
- drawField();
- }
- // . . . . . . . . . . . . . . . . . . .
- float[][] createField(int xSteps, int ySteps) {
- float[][] field = new float[xSteps][ySteps];
- for (int x = 0; x < field.length; x++) {
- for (int y = 0; y < field[0].length; y++) {
- float n = noise(x*perlinZoom, y*perlinZoom);
- field[x][y] = n;
- }
- }
- return field;
- }
- // . . . . . . . . . . . . . . . . . . .
- void improveContrast(float[][] field, float perlinRemapMin, float perlinRemapMax) {
- float n;
- for (int x = 0; x < field.length; x++) {
- for (int y = 0; y < field[0].length; y++) {
- n = field[x][y];
- n = constrain(n, perlinRemapMin, perlinRemapMax);
- n = norm(n, perlinRemapMin, perlinRemapMax);
- field[x][y] = n;
- }
- }
- }
- // . . . . . . . . . . . . . . . . . . .
- void blurEdgesField(float[][] field) {
- // 0 = black
- // 1 = white
- float xSteps = field.length;
- float ySteps = field[0].length;
- // can be odd or even so we use float
- float centerX = xSteps/2;
- float centerY = ySteps/2;
- println("centerX: "+centerX);
- println("centerY: "+centerY);
- for (int yStep = 0; yStep < ySteps; yStep++) {
- for (int xStep = 0; xStep < xSteps; xStep++) {
- // we add 0.5 so it's the center of a cell
- // and not the left top corner of a cell
- float y = 0.5 + yStep;
- float x = 0.5 + xStep;
- float a = atan2(y - centerY, x - centerX);
- float cos_angle = abs(cos(a));
- float sin_angle = abs(sin(a));
- // maxDist goes from the center to the edge
- // of the vectorfield
- float maxDist;
- if (xSteps / 2 / cos_angle <= ySteps / 2 / sin_angle) {
- maxDist = abs(xSteps / 2 / cos_angle);
- }
- else {
- maxDist = ySteps / 2 / sin_angle;
- }
- // ------------------------------------------------------
- // calculate where the ellipse get's hit
- // this is where the red line intersects the green ellipse on
- // the image
- // i got the following code from:
- // https://forum.processing.org/topic/find-distance-to-edge#25080000001736579
- /*
- float x = (rectW/2 * rectH/2) / sqrt(sq(rectH/2) + sq(rectW/2)* sq(tan(a)));
- if (abs(a) > PI/2) {
- x *= -1;
- }
- float y = tan(a)*x;
- */
- // WRONG!
- float ex = (xSteps/2 * ySteps/2) / sqrt(sq(ySteps/2) + sq(xSteps/2)* sq(tan(a)));
- if (abs(a) > PI/2) {
- ex *= -1;
- }
- float ey = tan(a)*ex;
- ex += xSteps/2;
- ey += ySteps/2;
- // ------------------------------------------------------
- // print the values if it's a corner or the center of a edge
- // (prints also the total center)
- if (xStep == 0 || xStep == (xSteps-1)/2 || xStep == xSteps-1) {
- if (yStep == 0 || yStep == (ySteps-1)/2 || yStep == ySteps-1) {
- println(x+"\t"+y+"\t"+degrees(a)+"\t"+maxDist+"\t"+ex+"\t"+ey);
- }
- }
- /*
- float mul;
- // M-----------(x-y)--------EX-EY-------(x-y)-------CX-CY
- if (dist(x, y, centerX, centerY) < dist(ex, ey, centerX, centerY)) {
- // mul is multiply, if xy is inside the ellipse
- // then mul is 1 so inside the ellipse the value
- // stays unchanged
- mul = 1;
- }
- else {
- // if it's outside the ellipse then the value get's between
- // 0 and 1
- // where the edge of the vectorfield is 0
- // and the edge of the ellipse is 1
- // this way it should get black
- // closer to the edge
- float t = dist(x, y, centerX, centerY);
- float el = dist(ex, ey, centerX, centerY); // ellipse length
- //println(t+"\t"+el+"\t"+maxDist);
- mul = norm(t, maxDist, el);
- //mul = 0;
- }
- field[xStep][yStep] *= mul;
- */
- }
- }
- }
- // . . . . . . . . . . . . . . . . . . .
- void drawField() {
- float w = floor((float)width/xSteps);
- float h = floor((float)height/ySteps);
- noStroke();
- for (int x = 0; x < xSteps; x++) {
- for (int y = 0; y < ySteps; y++) {
- float xPos = x * w;
- float yPos = y * h;
- fill(field[x][y]*g.colorModeX);
- rect(xPos, yPos, w, h);
- }
- }
- }
1