Issue with PGraphic and curveVertex

edited January 2018 in Questions about Code

Hello,

I have an issue with PGraphic. I try to test the color of an off screen PGraphic but it bounces back this error: 'ArrayIndexOutOfBoundsException: 1001'. I would really apreciate if someone can bring his fresh look and help me to solve this! Thank a lot in advance. Best, @lolonulu

int X_Step=1;
int Y_Step=10;
int X, Y;
float radiousForce =50;
float maxForce =5;

PVector [][] points;

PGraphics pg;
PFont f;
color textColor = color(245);

void setup() {
  size(1000, 1000, P2D);
  background(0);

  f= createFont ("ARIAL", 150);
  fill(textColor);
  textFont(f);
  beginShape();
  pg = createGraphics(width, height);
  pg.smooth();
  pg.beginDraw();
  pg.fill(textColor);
  pg.textFont(f);
  pg.text("LIOR", 150, height/2+50);
  pg.endDraw();


  stroke(255);
  noFill();
  X =  (width/X_Step) +1;
  Y = (height/ Y_Step) +1;
  points = new PVector[X][Y];
  for (int x = 0; x<X; x+=1) {
    for (int y=0; y<Y; y+=1) {

      points [x][y] = new PVector(x*X_Step, y*Y_Step);
    }
  }
}
void draw() {
  background(0);



  if (pg.pixels[(int)points[X][Y].y*width +(int)points[X][Y].x] == textColor) {
    for ( int y=0; y < Y; y+=1) {
      stroke(255);
      strokeWeight(1);

      beginShape();
      curveVertex(points[0][y].x, points[0][y].y);

      for (int x=0; x < X; x+=1) {
        curveVertex(points[x][y].x, points[x][y].y);
      }
      curveVertex(points [X-1][y].x, points [X-1][y].y);
      endShape();
    }
  }
  if (mousePressed) {
    PVector mouse = new PVector(mouseX, mouseY);
    for (int x=0; x<X; x+=1) {
      for (int y=0; y<Y; y+=1) {
        float d =PVector. dist(points[x][y], mouse);
        if (d < radiousForce) {
          PVector force= PVector.sub(points[x][y], mouse);
          force.normalize();
          force.mult(map(d, 0, radiousForce, maxForce, 0));
          points[x][y].add(force);
        }
      }
    }
  }
}

Answers

  • edited January 2018

    You have to call loadPixels() before accessing the pixels array. More info can be found in the reference.

  • You have a beginShape in setup(). Maybe that solves the issue?

    Kf

  • Hi guys, Thank you very much for replying and pointing out some mistakes. Though I still have the same error: 'ArrayIndexOutOfBoundsException: 1001'. Even if I use loadPixels() before accessing the pixels and changed beginShape by pg.beginDraw() in setup() :D

    I guess the problem is here: if (pg.pixels[(int)points[X][Y].y*width +(int)points[X][Y].x] == textColor)

    Do you suggest anything?! Thanks in advance.

  • You need to debug your code to understand what's going on. Split that line up into multiple steps. What is the value of X and Y when you get to that line? What are the dimensions of the pg.pixels array? Your error is telling you that you're trying to access an index that's larger than the size of the array. Work backwards from that to see how you're getting into that situation, and then you'll know how to fix your problem. Good luck.

  • Thank you very much Kevin for your answer and pedagogical approach. So let's answer : X = (width/X_Step) +1; Y = (height/ Y_Step) +1; so X=1001 Y=101 and for pg.pixels array: pg.pixels[ywidth+x]=500x500=250000 values It means that this line doesn't make sense : [(int)points[X][Y].ywidth +(int)points[X][Y].x] == textColor) since the value is by too far higher than the pg.pixels array,am I right?! Thank you very much for your help

  • I'm not sure I understand what you just said, but you're thinking about the right things. Try to answer all of these questions:

    When you get the error:

    • What is the value of X?
    • What is the value of Y?
    • What are the dimensions of the point array?
    • What is the output of this bit: (int)points[X][Y].y*width +(int)points[X][Y].x?
    • What are the dimensions of the pixels array?

    Break that line up into multiple steps and then use println() statements or the debugger to answer these questions. The answer to these questions will tell you what's going wrong, which will tell you what to fix.

  • Dear Kevin, this works with straight lines:

    int X_Step=1;
    int Y_Step=10;
    int X, Y;
    int x, y;
    float radiousForce =50;
    float maxForce =5;
    
    PVector [][] points;
    
    PGraphics pg;
    PFont f;
    color textColor = color(245);
    
    void setup() {
      size(1000, 1000);
      background(0);
    
      f= createFont ("ARIAL", 250);
      fill(textColor);
      textFont(f);
      beginShape();
      pg = createGraphics(width, height);
      pg.smooth();
      pg.beginDraw();
      pg.fill(textColor);
      pg.textFont(f);
      pg.text("LIOR", width/5, height/2);
      pg.endDraw();
    
    
      X = (width/X_Step) +1;
      Y = (height/ Y_Step) +1;
      points = new PVector[X][Y];
      for (int x = 0; x<X; x+=1) {
        for (int y=0; y<Y; y+=1) {
    
          points [x][y] = new PVector(x*X_Step, y*Y_Step);
        }
      }
    }
    void draw() {
      background(0);
    
      pg.loadPixels();  
      for ( int y=0; y < height; y+=5) {
        for ( int x=0; x < width; x++) {
          int loc = x+y*pg.width;
          color pix = pg.pixels[loc];
          if (pix == textColor) {
            strokeWeight(0.5);
            stroke(255);
            noFill();
            line(x, y, x+10, y+10);
          } else {
            strokeWeight(0.1);
            stroke(255, 0, 0);
            noFill();
            line(x, y, x+5, y+5);
          }
        }
      }
    
      /*
        for ( int y=0; y < Y; y+=1) {
       stroke(255);
       strokeWeight(1);
       noFill();
       beginShape();
       curveVertex(points[0][y].x, points[0][y].y);
    
       for (int x=0; x < X; x+=1) {
       curveVertex(points[x][y].x, points[x][y].y);
       println( points[x][y].y);
       }
       curveVertex(points [X-1][y].x, points [X-1][y].y);
       endShape();
       }
       */
      if (mousePressed) {
        PVector mouse = new PVector(mouseX, mouseY);
        for (int x=0; x<X; x+=1) {
          for (int y=0; y<Y; y+=1) {
            float d =PVector. dist(points[x][y], mouse);
            if (d < radiousForce) {
              PVector force= PVector.sub(points[x][y], mouse);
              force.normalize();
              force.mult(map(d, 0, radiousForce, maxForce, 0));
              points[x][y].add(force);
            }
          }
        }
      }
    }
    

    So now the problem is how to draw the curveVertex ?!! Sorry to be so slow to catch it, but I feel stuck. Thanks a lot for your help. best, @lolonulu

  • The best thing I can tell you to do is to debug your code and answer the questions I outlined above. That's exactly what you're asking us to do for you, so it's a good idea to get into the habit of debugging yourself.

  • @lolonulu

    I am just addressing your specific line where the error shows. I didn't look at the rest of your code. These are two things to consider:

    points = new PVector[int(X)][int(Y)];

    which means that the last item to access is

    println(points[int(X-1)][int(Y-1)].x,points[int(X-1)][int(Y-1)].y);

    Kf

  • Thank you very much Kevin, I'll debug my code later on, now I can't, but I am on the way. Thanks kfrajer I'll consider your suggestion. CU tomorrow. Thks guys!

  • Check the last section, Two-dimensional Arrays: https://processing.org/tutorials/arrays/

    I found your code to be a bit hard to read. Better to use explicit names of what you are doing. For instance, to access the last element:

    int[][] points={ {50, 0}, {61, 204}, {83, 51}, {69, 102}, {71, 0}, 
      {50, 153}, {29, 0}, {31, 51}, {17, 102}, {39, 204} };
    
    int lastx=points.length-1;
    int lasty=points[lastx].length-1;
    
    println(lastx,lasty,"Last element: ",points[lastx][lasty]);
    

    Kf

  • Hi guys,Here is an attempt to understand what's wrongin my code with the step by step debug proposed by @Kevin:
    
    
    int X_Step=1;
    int Y_Step=10;
    int X, Y;
    int x, y;
    float radiousForce =50;
    float maxForce =5;
    
    PVector [][] points;
    
    PGraphics pg;
    PFont f;
    color textColor = color(245);
    color c;
    
    void setup() {
      size(1000, 1000);
      background(0);
    
      f= createFont ("ARIAL", 250);
      fill(textColor);
      textFont(f);
      beginShape();
      pg = createGraphics(width, height);
      pg.smooth();
      pg.beginDraw();
      pg.fill(textColor);
      pg.textFont(f);
      pg.text("LIOR", width/5, height/2);
      pg.endDraw();
    
    
      X = int(width/X_Step) +1;
      Y = int(height/ Y_Step) +1;
      points = new PVector[X][Y];
      for (int x = 0; x<X; x+=1) {
        for (int y=0; y<Y; y+=1) {
    
          points [x][y] = new PVector(x*X_Step, y*Y_Step);
        }
      }
    }
    void draw() {
      background(0);
    
    ///////////////////////////////////////////////////////////////////////////
    
    // ANSWERS TO @KEVIN:
    
     // println("X"+"="+X);
      // Value of X = 1001;
    
      //println("Y"+"="+Y);
      // Value of Y = 101;
        ///////////////////////////////////////////////////////////////////////////
    
      // The dimensions of the points array is double. [X] stand for the simple array
      // of the x coordinates of my points and [Y] for the simple array of the y coordinates
      points = new PVector[X][Y];
    
    ///////////////////////////////////////////////////////////////////////////
    
      //break up the line into multiple steps:
    
     //println((int)points[X][Y].y*width +(int)points[X][Y].x);
      //ERROR : ArrayIndexOutOfBoundsException : 1001;
      points = new PVector[X][Y];
     //println(points[X][Y].y); 
     //ERROR : ArrayIndexOutOfBoundsException : 1001; 
     // println( points[X][Y].x);
       //ERROR : ArrayIndexOutOfBoundsException : 1001; 
       // same error each time since points[1001][101] this element is outside the array;
        ///////////////////////////////////////////////////////////////////////////
    
      // The dimension of the pixels array is 1D, to locate the pixels of an image you use this
      // formula :  
      // 1rst you load the pixels
      loadPixels(); 
      // Loop through every pixel column
    for (int x = 0; x < pg.width; x++) {
      // Loop through every pixel row
      for (int y = 0; y < pg.height; y++) {
       int loc = x + y * width;
       c = pg.pixels[loc];
       //Here compare c with textColor ?!!
    
    ///////////////////////////////////////////////////////////////////////////
    
        for ( int y=0; y < Y; y+=1) {
       stroke(255);
       strokeWeight(1);
       noFill();
       beginShape();
       curveVertex(points[0][y].x, points[0][y].y);
    
       for (int x=0; x < X; x+=1) {
       curveVertex(points[x][y].x, points[x][y].y);
    
       }
       curveVertex(points [X-1][y].x, points [X-1][y].y);
       endShape();
       }
    
      if (mousePressed) {
        PVector mouse = new PVector(mouseX, mouseY);
        for (int x=0; x<X; x+=1) {
          for (int y=0; y<Y; y+=1) {
            float d =PVector. dist(points[x][y], mouse);
            if (d < radiousForce) {
              PVector force= PVector.sub(points[x][y], mouse);
              force.normalize();
              force.mult(map(d, 0, radiousForce, maxForce, 0));
              points[x][y].add(force);
            }
          }
        }
      }
    }
    

    Thanks a lot for your help. No timeto go further today ;(

  • 82,98,108... you are using the same variable name (similar for y). You should provide better descriptive names. Think about what the variable does. Also, can you describe what you want to accomplish with your code? I can infer you are trying to match the color of some pixels to some text, but this is very vague and without knowing this, it is challenging understanding your code.

    Kf

  • Hi kfrajer, Yes you are true I'll change my variable names. What I want to accomplish is to show the lines drawn by the curveVertex in the shape of some text written in an off screen PGraphics (pg). You can see how it looks in this code:

    int X_Step=1;
    int Y_Step=10;
    int X, Y;
    int x, y;
    float radiousForce =50;
    float maxForce =5;
    
    PVector [][] points;
    
    PGraphics pg;
    PFont f;
    color textColor = color(245);
    
    void setup() {
      size(1000, 1000);
      background(0);
    
      f= createFont ("ARIAL", 250);
      fill(textColor);
      textFont(f);
      beginShape();
      pg = createGraphics(width, height);
      pg.smooth();
      pg.beginDraw();
      pg.fill(textColor);
      pg.textFont(f);
      pg.text("LIOR", width/5, height/2);
      pg.endDraw();
    
    
      X = (width/X_Step) +1;
      Y = (height/ Y_Step) +1;
      points = new PVector[X][Y];
      for (int x = 0; x<X; x+=1) {
        for (int y=0; y<Y; y+=1) {
    
          points [x][y] = new PVector(x*X_Step, y*Y_Step);
        }
      }
    }
    void draw() {
      background(0);
    
      pg.loadPixels();  
      for ( int y=0; y < height; y+=5) {
        for ( int x=0; x < width; x++) {
          int loc = x+y*pg.width;
          color pix = pg.pixels[loc];
          if (pix == textColor) {
            strokeWeight(0.5);
            stroke(255);
            noFill();
            line(x, y, x+10, y+10);
          } else {
            strokeWeight(0.1);
            stroke(255, 0, 0);
            noFill();
            line(x, y, x+5, y+5);
          }
        }
      }
    
      /*
        for ( int y=0; y < Y; y+=1) {
       stroke(255);
       strokeWeight(1);
       noFill();
       beginShape();
       curveVertex(points[0][y].x, points[0][y].y);
    
       for (int x=0; x < X; x+=1) {
       curveVertex(points[x][y].x, points[x][y].y);
       println( points[x][y].y);
       }
       curveVertex(points [X-1][y].x, points [X-1][y].y);
       endShape();
       }
       */
      if (mousePressed) {
        PVector mouse = new PVector(mouseX, mouseY);
        for (int x=0; x<X; x+=1) {
          for (int y=0; y<Y; y+=1) {
            float d =PVector. dist(points[x][y], mouse);
            if (d < radiousForce) {
              PVector force= PVector.sub(points[x][y], mouse);
              force.normalize();
              force.mult(map(d, 0, radiousForce, maxForce, 0));
              points[x][y].add(force);
            }
          }
        }
      }
    }
    

    Here I use classical lines and it works, my problem is how to draw curveVertex (here commented) when the pg.pixels match the text color?! Should I use other variable names when I review all my pixels in the for loops? for ( int y=0; y < height; y+=5) { for ( int x=0; x < width; x++) { int loc = x+y*pg.width; Thank you very much for your help. best, lolonulu

  • I'm not really sure what the state of this thread is. Are you still trying to solve the problem with the error your were getting, or did you fix that? What does this new bit of code have to do with the question?

    Please note that I wasn't really asking the questions because I needed to know the answer. I was asking them because you need to know the answer. This is how debugging works. You narrow the problem down and work backwards to figure out exactly what's going on.

    What exact line of code is giving you trouble?

  • Dear Kevin,

    I am sorry, I'm a newbie and I try my best, really. I perfectly know that you weren't asking the questions to know the answers, you obviously know them! I need to fix my problem, so here is what I did: I use the1D arrays of pixels of an image and test if it matches the textColor and it works,at lesat with straight lines.

    pg.loadPixels();  
      for ( int y=0; y < height; y+=5) {
        for ( int x=0; x < width; x++) {
          int loc = x+y*pg.width;
          color pix = pg.pixels[loc];
          if (pix == textColor) {
            strokeWeight(0.5);
            stroke(255);
            noFill();
            line(x, y, x+10, y+10);
          } else {
            strokeWeight(0.1);
            stroke(255, 0, 0);
            noFill();
            line(x, y, x+5, y+5);
          }
        }
      }
    

    what I don't know is how I can apply the same idea to these curveVertex, notably because the variables has the same names(x, y). Don't get where is my mistake...

    for ( int y=0; y < Y; y+=1) {
    

    stroke(255); strokeWeight(1); noFill(); beginShape(); curveVertex(points[0][y].x, points[0][y].y);

    for (int x=0; x < X; x+=1) { curveVertex(points[x][y].x, points[x][y].y); println( points[x][y].y); } curveVertex(points [X-1][y].x, points [X-1][y].y); endShape(); }

  • Hi, So basically I need to 'translate' the pixels' values from the 1D array of the pic: int loc = x+y*pg.width; into the 2D array of my 'canvas': points[x][y]?! Am I right?! So is that bit of code here below makes any sense (I can't test it now)?

     pg. loadPixels();
     pg.loadPixels();
    for ( int y=0; y < pg.height; y++) {
        for ( int x=0; x < pg.width; x++) {
          int loc = x+y*pg.width;
          color pix = pg.pixels[loc];
        points[x][y] = color(pg.pixels[loc]);
    if(points[x][y] == textColor){
    //DRAW CURVEVERTEX
    

    Thanks a lot guys for your help, I appreciate. best, @lolonulu

  • Answer ✓

    The following code is correct with a minor modification:

    pg.loadPixels();
    for ( int y=0; y < pg.height; y++) {
        for ( int x=0; x < pg.width; x++) {
          int loc = x+y*pg.width;
          color pix = pg.pixels[loc];
        points[x][y] = pix;   // MODIFIED: color(pg.pixels[loc]);
        if(points[x][y] == textColor){
         //DRAW CURVEVERTEX
    

    To clarify in this example, pos [x,y] inside the nested loop is similar to the value of loc. The former is used to access a 2D array and the later is used to access a 1D array. The former is use with functions like get() and set(), functions associated with PImage. the later is used with the pixels object.

    After working with your code, I did the following modification (plus added one of mine) to see the effect. I hope this helps.

    Kf

    int X_Step=1;
    int Y_Step=10;
    int X, Y;
    int x, y;
    float radiousForce =50;
    float maxForce =5;
    
    PVector [][] points;
    
    PGraphics pg;
    PFont f;
    final color textColor = color(245);
    
    void setup() {
      size(1000, 1000);
      background(0);
    
      f= createFont ("ARIAL", 250);
      fill(textColor);
      textFont(f);
    
      beginShape();
      pg = createGraphics(width, height);
      pg.smooth();
      pg.beginDraw();
      pg.fill(textColor);
      pg.textFont(f);
      pg.text("LIOR", width/5, height/2);
      pg.endDraw();
    
    
      X = (width/X_Step);// +1;
      Y = (height/ Y_Step);// +1;
    
      points = new PVector[X][Y];
      for (int x = 0; x<X; x+=1) {
        for (int y=0; y<Y; y+=1) {
    
          points [x][y] = new PVector(x*X_Step, y*Y_Step);
        }
      }
    }
    
    
    
    void draw() {
      background(0);
    
      pg.loadPixels(); 
    
    
      //for ( int y=0; y < height; y+=5) {
      //  for ( int x=0; x < width; x++) {
      //    int loc = x+y*pg.width;
      //    color pix = pg.pixels[loc];
      //    if (pix == textColor) {
      //      strokeWeight(2);
      //      stroke(255);
      //      noFill();
      //      line(x, y, x+10, y+10);
      //    } else {
      //      strokeWeight(1);
      //      stroke(255, 0, 0);
      //      noFill();
      //      line(x, y, x+5, y+5);
      //    }
      //  }
      //}
    
    
      for ( int y=0; y < Y; y+=1) {
        stroke(255);
        strokeWeight(1);
        noFill();
        beginShape();
        PVector pos0=points[0][y];
        curveVertex(pos0.x, pos0.y);
    
        for (int x=0; x < X; x+=1) {
          float fac=1.0;
          int loc = x*X_Step+y*Y_Step*pg.width;
          PVector pos1=points[x][y];
          if (pg.pixels[loc]==textColor)
            fac=random(-1.0, -0.5)*100;
          curveVertex(pos1.x, pos1.y+fac);
          //println( x, y);
        }
        PVector pos2=points[X-1][y];
        curveVertex(pos2.x, pos2.y);
        endShape();
      }
    
    
    
      if (mousePressed) {
        PVector mouse = new PVector(mouseX, mouseY);
        for (int x=0; x<X; x+=1) {
          for (int y=0; y<Y; y+=1) {
            float d =PVector. dist(points[x][y], mouse);
            if (d < radiousForce) {
              PVector force= PVector.sub(points[x][y], mouse);
              force.normalize();
              force.mult(map(d, 0, radiousForce, maxForce, 0));
              points[x][y].add(force);
            }
          }
        }
      }
    
      //image(pg,0,0);
    }
    
  • Dear kfrajer, Thank youuuuuuu so much, I did also the minor modification you did points[x][y] = pix; // MODIFIED: color(pg.pixels[loc]); and it worked also on my side after a lot of errors! But your added modification is really great: fac=random(-1.0, -0.5)*100; curveVertex(pos1.x, pos1.y+fac); And the fact you use PVector pos0,1,2 makes also much simpler the code.

    I really appreciate the way you helped me to understand where was the problem: the relation between 1D array of pixels and the 2D array of the pic. It was very pedagogic. Without you I would have turn around for a while ! Thanks a lot for your help. I'llcredit you if I manage to finish this project ;) best wishes,

    lolonulu

  • @lolonulu All the best!

    Kf

Sign In or Register to comment.