Problem with passing vectors to next

Hi,
I have been working on an idea a while ago and want to pick up where I left. What I want to create is some kind of self-generating irregular pattern, existing of different polygons.
I wrote the code for a random polygon, which worked.

Where I’m stuck is: I want to start the NEXT polygon in one of the corners of the previous one. So I need to pass those coordinates. I’m not succeeding in doing that.

The sketch is here: https://www.openprocessing.org/sketch/310023

There is another small problem, on OpenProcessing, the sketch works, but in Processing on my Mac, I get a NullPointerExeption for polygon.x (while that should have value 300??)

(j=0, so nextpolygon is assigned the value (300, 300). I added the print-statement to narrow down the problem, at first, the exception was in the next line with nextpolygon.x)

Polygon[] polygon = new Polygon[1];
PVector endcorner, nextpolygon;

int j=0;

void draw() {

  if (j==0) {                // the first time, when j=0, start at the center
    PVector nextpolygon = new PVector(300, 300);
  } else if (j>0) {              // after that, start
    PVector nextpolygon = polygon[j].endCorner();
  }

  println(nextpolygon.x);

I found that your code does not run in to an exception when I comment line 27, even though both endCorner and nextPolygon are already initialized

while (nextpolygon.x<width) {                     // stop drawing polygons when the edge of the screen is reached
    polygon[j] = new Polygon(nextpolygon);
    polygon[j].build();
    polygon[j].display();
    polygon = (Polygon[])expand(polygon, polygon.length+1);
    j++;
    //println(endcorner.x +" "+ nextpolygon.x + " " + " " +polygon.length);**
  }

I’m still working out a solution to get the polygons to reach the end of the screen, however

Edit: I found that if you initialize endcorner in setup, the code never finishes compiling and you just get a white screen

Hi BennyHacker,

Thank you for your help. I saw that I sometimes wrote “endCorner” and sometimes “endcorner”. I corrected that, but it didn’t solve the problem.

The error I got on OpenProcessing is “TypeError: endcorner is null”, but it draws a polygon (and prints “300” beneath the screen. When I comment 27 out, after a while I get the orange background and much polygons drawn on the same place.

In Processing the error is “NullPointerException”, and I only get an orange background and the sketch gets stuck. This is the same when I comment line 27 out.

“endcorner”= 0 because the returning doesn’t work. It never gets to line 65, because the println is not executed…

I’ll search further tomorrow!

Gladly! One other thing… I noticed the way you were going to be drawing these shapes seems kinda mathy and complex so I did a quick google search and apparently there’s a method called a Voronoi Diagram

The implementation in processing was actually very easy:

float radius;
ArrayList<Seed> seeds;
boolean hasWhite = false;
boolean update=true;
void setup() {
  size(600, 600);
  seeds = new ArrayList<Seed>();
  int r = 28;
  for (int i = 0; i < r; i++) {
    Seed s = new Seed();
    seeds.add(s);
  }
  background(255);
}
void mouseReleased() {
  seeds = new ArrayList<Seed>();
  update=true;
  int r = (int)random(15, 35);
  for (int i = 0; i < r; i++) {
    Seed s = new Seed();
    seeds.add(s);
  }
  radius=0;
  background(255);
}
void draw() {
  hasWhite=false;
  if (update) {
    //iterate through screen pixels
    for (int k = 0; k < width; k++) {
      for (int l = 0; l < height; l++) {
        //check if pixel is white
        if (get(k, l)==color(255)) {
          hasWhite=true;
          //if so, iterate through circles
          for (int i = 0; i < seeds.size(); i++) {
            //check if pixel is within the circle's radius
            if (dist(k, l, seeds.get(i).pos.x, seeds.get(i).pos.y)<radius) {
              //if so, give it a color
              set(k, l, seeds.get(i).c);
            }
          }
        }
      }
    }
    //increase radius every frame
    radius+=.25;
    //stop updating once all white pixels are gone
    update=hasWhite;
  }
}
class Seed {
  PVector pos = new PVector(random(width), random(height));
  color c = color(random(45, 245), random(45, 245), random(45, 245));
}

Although since you’re trying to make your own unique algorithm I encourage you to keep at it :stuck_out_tongue:

2 Likes

You’re declaring local variable nextpolygon inside the if () / else code block. :sweat:

It means that variable is scoped inside that curly braces block and ceases to exist once that block finishes! :cold_sweat:

2 Likes

That’s indeed interesting! But you’re also right: I want to create my own sketch :slight_smile: . It’s a bit different from that Voronoi diagram, I want the second polygon to start in a corner of the first polygon, and so on. If it’s possible that on more then one corner a new polygon starts.

So a next step will also be, avoiding that new polygons overlap with the existing ones.

(I’m not native English, is it a little understandable what I’m saying?)

I declare it in the setup, no? But indeed, I don’t give it a value. The whole purpose of this:

  if (j == 0) {                // the first time, when j=0, start at the center
    PVector nextpolygon = new PVector(300, 300);
  } else if (j > 0) {          // after that, start
    PVector nextpolygon = polygon[j].endCorner();
  }

Is to give a value on the first vector. Maybe it’s made to complex to achieve this?
EDIT:
Okay, to solve the problem, I changed the if/else if statement in an if statement, so I could move

PVector nextpolygon = polygon[j].endCorner();

outside that code block. But wherever I put it, it gives trouble.

Ok, I moved nextpolygon elsewhere, and I don’t have the NullPointException anymore. Now I get the message “The value of the local variable nextpolygon is not used”.

Polygon[] polygon = new Polygon[1];
PVector endcorner;
PVector nextpolygon = new PVector(300, 300);
int j=0;

void setup() {
  size(600, 600);
  background(204, 100, 30);
}

void draw() {
  
println(j);

  if (j>0) {
    PVector nextpolygon = polygon[j].endcorner();
  }

  while (nextpolygon.x<width) {                     // stop drawing polygons when the edge of the screen is reached
    polygon[j] = new Polygon(nextpolygon);
    polygon[j].build();
    polygon[j].display();
    polygon = (Polygon[])expand(polygon, polygon.length+1);
    j++;
   // println(endcorner.x +" "+ nextpolygon.x + " " + " " +polygon.length);
  }

  noLoop();
}

class Polygon {
  PVector endcorner = new PVector();
  PVector firstcorner = new PVector();
  PVector[] points;

  Polygon(PVector start) {
    firstcorner.set(start);
  }

  void build() {
    int numbercorners= int(random(3, 8));           // select number of corners between 3 and 8
    float t = 360/numbercorners;                    // = 120, 90, 72, 60, 51.x, 45
    points = new PVector[numbercorners];            // create an array to store the vectors of each corner
    float rotation = random(0, 2 * PI);             // = PI/5 = 36°
    points[0] = new PVector(firstcorner.x, firstcorner.y);
    for (int i=1; i < numbercorners; i++) {        // calculate the vectors for each corner of the polygon 
      // i * t would generate a regular polygon, therefor adding random amount 'rotation'
      float xcorner = firstcorner.x + cos((radians(i * t)+rotation)) * (random(12, 30)); // the random number is the length of a side
      float ycorner = firstcorner.y + sin((radians(i * t)+rotation)) * (random(12, 30));
      points[i] = new PVector(xcorner, ycorner);
    }
  }

  void display() {         // draw the polygon
    beginShape();
    for (int i = 0; i < points.length; i++) {
      vertex(points[i].x, points[i].y);
    }
    endShape(CLOSE);

    ellipse(points[points.length-1].x, points[points.length-1].y, 6, 6);   // this is temporary, to see the last corner
  }

  PVector endcorner() {             // pass the last vector to the next polygon
    int i = int(points.length-1);

    println(points[i].x+" "+" "+points[i].y);

    PVector endcorner = new PVector(points[i].x, points[i].y); // this passes the x and y values of the last point

    println(endcorner.x+" "+" "+endcorner.y);

    return endcorner;
  }
}

I don’t understand, in line 19 and 20, nextpolygon is used!

On line 16, similar to what GoToLoop said, try removing the PVector constructor and just write:

nextpolygon = polygon[j].endcorner();

@BennyHacker, that doesn’t work, the first time there is no endcorner.

I added some print-commands to see where it goed wrong and somehow the returning function never gets activated (or run or called).

Polygon[] polygon = new Polygon[1];
PVector endcorner;
PVector nextpolygon = new PVector(300, 300);
int j=0;

void setup() {
  size(600, 600);
  background(204, 100, 30);
}

void draw() {

  println(j);

  if (j>0) {
    PVector nextpolygon = polygon[j].endcorner();
  }

  while (nextpolygon.x<width) {                     // stop drawing polygons when the edge of the screen is reached
    println("Keep drawing polygons");
    polygon[j] = new Polygon(nextpolygon);
    polygon[j].build();
    polygon[j].display();
    polygon = (Polygon[])expand(polygon, polygon.length+1);
    j++;
    // println(endcorner.x +" "+ nextpolygon.x + " " + " " +polygon.length);
  }

  noLoop();
}

class Polygon {
  PVector endcorner = new PVector();
  PVector firstcorner = new PVector();
  PVector[] points;

  Polygon(PVector start) {
    firstcorner.set(start);
  }

  void build() {
    
    println("Building polygons");
    
    int numbercorners= int(random(3, 8));           // select number of corners between 3 and 8
    float t = 360/numbercorners;                    // = 120, 90, 72, 60, 51.x, 45
    points = new PVector[numbercorners];            // create an array to store the vectors of each corner
    float rotation = random(0, 2 * PI);             // = PI/5 = 36°
    points[0] = new PVector(firstcorner.x, firstcorner.y);
    for (int i=1; i < numbercorners; i++) {        // calculate the vectors for each corner of the polygon 
      // i * t would generate a regular polygon, therefor adding random amount 'rotation'
      float xcorner = firstcorner.x + cos((radians(i * t)+rotation)) * (random(12, 30)); // the random number is the length of a side
      float ycorner = firstcorner.y + sin((radians(i * t)+rotation)) * (random(12, 30));
      points[i] = new PVector(xcorner, ycorner);
    }
  }

  void display() {         // draw the polygon
  
    println("drawing polygons");
    
    beginShape();
    for (int i = 0; i < points.length; i++) {
      vertex(points[i].x, points[i].y);
    }
    endShape(CLOSE);

    ellipse(points[points.length-1].x, points[points.length-1].y, 6, 6);   // this is temporary, to see the last corner
  }

  PVector endcorner() {             // pass the last vector to the next polygon
  
    println("Passing vector");
    
    int i = int(points.length-1);

    println(points[i].x+" "+" "+points[i].y);

    PVector endcorner = new PVector(points[i].x, points[i].y); // this passes the x and y values of the last point

    println(endcorner.x+" "+" "+endcorner.y);

    return endcorner;
  }
}

I understand what you’re saying, but I’m trying like crazy and I can’t figure out to solve the problem! I need the if-statement to check if it’s the first polygon. Only when it’s not, I want to pass vector “endcorner” to “nextolygon”.
I tried putting the if-statement inside and around the while-statement, but that’s not the solution.

Declare that variable outside the if () / else code block scope.
Then you can assign a value to it inside the if () / else code block scope.

Processing.org/examples/variablescope.html

I thought I declared it at the top, before my setup().

If a variable is already declared as a global field, when we redeclare it in a local scope, we overshadow it in that scope! :grimacing:

2 Likes

I’m sorry, I was not at home and answered a little to soon, as I already mentioned, the NullPointException problem was already gone. I guess the declaration is OK like it is. The new trouble is that the variable is not used, while it is used 2 lines after the if-statement.

  • Maybe the scope of that variable is again the culprit? I tried declaring nextpolygon inside the void draw() but that didn’t help. Also putting the “while” part inside the “if” brackets didn’t work (it was worse).
  • Is it because I use nextpolygon.x in stead of the PVector? Then it is better to return nextpolygon.x and nextpolygon.y and then recompose the PVector. IF I have time tomorrow, I’ll test that.

Already a big thanx for your advice @GoToLoop and @BennyHacker

My advice is that you should stick to debug your sketch under PDE’s Java Mode. :coffee:
Debugging code under a browser, especially for a code transpiled from Java to JS, is much worse! :bug:

I’m working in Processing on my Macbook, the openprocessing sketch is just to share it.
Error mentioned: “The value of the local variable “nextpolygon” is not used”, line 16.

Console:

Keep drawing polygons
Building polygons
drawing polygons
Keep drawing polygons
Building polygons
drawing polygons
Keep drawing polygons
Building polygons
drawing polygons
Keep drawing polygons
Building polygons
drawing polygons
...

This is not an error but merely a warning! :warning:

However, since you had already declared variable nextpolygon as a global field, it should never be a local variable unless you redeclared it as a local variable (or as a function parameter) as well! :face_with_raised_eyebrow:

I removed the “while” statement to avoid variablescope problems there (I’ll add new statements to avoid drawing of-screen after this problem is solved).
Then I keep getting the “nextpolygon is not used” warning. I really don’t understand!! I use it clearly: " polygon[j] = new Polygon(nextpolygon);" and now it is in the same scope, so that’s not the trouble anymore.
Somehow the sketch never goes beyond j=1 either. For that, I removed the while and the endloop. But it didn’t solve the problem.

Polygon[] polygon = new Polygon[1];
PVector endcorner;
PVector nextpolygon = new PVector(300, 300);
int j=0;

void setup() {
  size(600, 600);
  background(204, 100, 30);
}

void draw() {

  if (j>0) {
    PVector nextpolygon = polygon[j].endcorner();   // give nextpolygon the value of the last vector "endcorner"
  }                                                 // this function is part of the Polygon-class

  println("nextpolygon="+nextpolygon);

  polygon[j] = new Polygon(nextpolygon);
  polygon[j].build();
  polygon[j].display();
  polygon = (Polygon[])expand(polygon, polygon.length+1);
  j++;

  println("j="+j);
}

class Polygon {
  PVector endcorner = new PVector();
  PVector firstcorner = new PVector();
  PVector[] points;

  Polygon(PVector start) {
    firstcorner.set(start);
  }

  void build() {

    println("Building polygon");

    int numbercorners= int(random(3, 8));           // select number of corners between 3 and 8
    float t = 360/numbercorners;                    // = 120, 90, 72, 60, 51.x, 45
    points = new PVector[numbercorners];            // create an array to store the vectors of each corner
    float rotation = random(0, 2 * PI);             // = PI/5 = 36°
    points[0] = new PVector(firstcorner.x, firstcorner.y);
    for (int i=1; i < numbercorners; i++) {         // calculate the vectors for each corner of the polygon 
      // i * t would generate a polygon with the same rotation between each corner,
      // therefor adding random amount 'rotation'
      // firstcorner is the center of a polygon
      float xcorner = firstcorner.x + cos((radians(i * t)+rotation)) * (random(12, 30)); // x= a + r.cosθ, y= b + rsinθ
      // r is the distance from the center to the corner, here: (random(12, 30)
      // a and b are coordinates of the center of the polygon
      float ycorner = firstcorner.y + sin((radians(i * t)+rotation)) * (random(12, 30)); // 
      points[i] = new PVector(xcorner, ycorner);
    }
  }

  void display() {         // draw the polygon

    println("drawing polygon");

    beginShape();
    for (int i = 0; i < points.length; i++) {
      vertex(points[i].x, points[i].y);
    }
    endShape(CLOSE);

    ellipse(points[points.length-1].x, points[points.length-1].y, 6, 6);   // this is temporary, to see the last corner
  }

  PVector endcorner() {             // pass the last vector to the next polygon

    println("Passing vector");

    int i = int(points.length-1);

    println(points[i].x+" "+" "+points[i].y);

    PVector endcorner = new PVector(points[i].x, points[i].y); // this passes the x and y values of the last point

    println(endcorner.x+" "+" "+endcorner.y);

    return endcorner;
  }
}

Second version, where I tried to initialize in the if/else statement, gives the nullpointexception error again. I don’t understand at all!

Polygon[] polygon = new Polygon[1];
PVector endcorner, nextpolygon;
int j=0;

void setup() {
  size(600, 600);
  background(204, 100, 30);
}

void draw() {

  if (j==0) {
    PVector nextpolygon = new PVector(300, 300);
  }   
  else {
    PVector nextpolygon = polygon[j].endcorner();   // give nextpolygon the value of the last vector "endcorner"
  }                                                 // this function is part of the Polygon-class

  println("nextpolygon="+nextpolygon);

  polygon[j] = new Polygon(nextpolygon);
  polygon[j].build();
  polygon[j].display();
  polygon = (Polygon[])expand(polygon, polygon.length+1);
  j++;

  println("j="+j);
}

class Polygon {
  PVector endcorner = new PVector();
  PVector firstcorner = new PVector();
  PVector[] points;

  Polygon(PVector start) {
    firstcorner.set(start);
  }

  void build() {

    println("Building polygon");

    int numbercorners= int(random(3, 8));           // select number of corners between 3 and 8
    float t = 360/numbercorners;                    // = 120, 90, 72, 60, 51.x, 45
    points = new PVector[numbercorners];            // create an array to store the vectors of each corner
    float rotation = random(0, 2 * PI);             // = PI/5 = 36°
    points[0] = new PVector(firstcorner.x, firstcorner.y);
    for (int i=1; i < numbercorners; i++) {         // calculate the vectors for each corner of the polygon 
      // i * t would generate a polygon with the same rotation between each corner,
      // therefor adding random amount 'rotation'
      // firstcorner is the center of a polygon
      float xcorner = firstcorner.x + cos((radians(i * t)+rotation)) * (random(12, 30)); // x= a + r.cosθ, y= b + rsinθ
      // r is the distance from the center to the corner, here: (random(12, 30)
      // a and b are coordinates of the center of the polygon
      float ycorner = firstcorner.y + sin((radians(i * t)+rotation)) * (random(12, 30)); // 
      points[i] = new PVector(xcorner, ycorner);
    }
  }

  void display() {         // draw the polygon

    println("drawing polygon");

    beginShape();
    for (int i = 0; i < points.length; i++) {
      vertex(points[i].x, points[i].y);
    }
    endShape(CLOSE);

    ellipse(points[points.length-1].x, points[points.length-1].y, 6, 6);   // this is temporary, to see the last corner
  }

  PVector endcorner() {             // pass the last vector to the next polygon

    println("Passing vector");

    int i = int(points.length-1);

    println(points[i].x+" "+" "+points[i].y);

    PVector endcorner = new PVector(points[i].x, points[i].y); // this passes the x and y values of the last point

    println(endcorner.x+" "+" "+endcorner.y);

    return endcorner;
  }
}

When a datatype (PVector in this case) is placed before a variable it is called a variable declaration. :face_with_monocle: