We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › intersecting rects fill area with color
Page Index Toggle Pages: 1
intersecting rects fill area with color (Read 707 times)
intersecting rects fill area with color
Apr 18th, 2009, 5:08pm
 
hello all,

I was wondering how I would go about making overlaping rects, fill with a color at only the area which they intersect.  I am relatively new to programing and have thought about it and havent gotten a good answer (or ones that are just too stupid to consider).

I know ill probablly need some method which checks to see if they intersect, but I am unsure how to write it.

Thanks for reading and helping
Re: intersecting rects fill area with color
Reply #1 - Apr 18th, 2009, 8:26pm
 
i have written some code for you so you can have an example to work over.

the general idea is to create one boolean array for each rect. these arrays consist of the total number of pixels of the screen [width * height] and return true if the rect they refer to occupies one specific pixel and false if the rect does not occupy that pixel.

by checking the boolean arrays of two or more rects and comparing them to one another one can define which pixels are superimposed, thus defining the intersection between the rects and making it possible for you to do something with this area.

when implementing this you should consider creating a class that keeps track of each rect's boolean array, once this way it is easier to work with more than two rectangles. once i have used only two in the example i did not bother creating the class; but if you want i can help you with that.

i hope this helps.

in this code i have considered:
r1[0] to be the posX of rect1;
r1[1] to be the posY of rect1;
r1[2] to be the width of rect1;
r1[3] to be the height of rect1.
the same applies to r2[], in which r2[0] is the posX of rect2 and so forth.

Code:
boolean[] r1b, r2b;
int numPixels;
int currentX, currentY;
color thisC;
int[] r1 = {150, 100, 200, 200};
int[] r2 = {100, 200, 200, 200};

void setup()
{
 background(255);
 size(500, 500);
 numPixels = width * height;
 r1b = new boolean[numPixels];
 r2b = new boolean[numPixels];
 thisC = color(0);
}

void draw()
{
 background(255);
 //loadPixels();
 pushStyle();
 fill(128);
 noStroke();
 rect(r1[0], r1[1], r1[2], r1[3]);
 rect(r2[0], r2[1], r2[2], r2[3]);
 popStyle();
 
 loadPixels();
 
 for(int i = 0; i < numPixels; i ++)
 {
   if((i/width) > r1[1] && (i/width) < (r1[1] + r1[3])
      && (i%width) > r1[0] && (i%width) < (r1[0] + r1[2]))
   {
     r1b[i] = true;
   }
   else{r1b[i] = false;}
 }
 for(int x = 0; x < numPixels; x ++)
 {
   if((x/width) > r2[1] && (x/width) <  (r2[1] + r2[3])
      && (x%width) > r2[0] && (x%width) < (r2[0] + r2[2]))
   {
     r2b[x] = true;
   }
   else{r2b[x] = false;}
 }
 
 for(int y = 0; y < numPixels; y++)
 {
   if(r1b[y] == true && r2b[y] == true)
   {
     pixels[y] = thisC;
   }
 }
 
 updatePixels();
 

}
Re: intersecting rects fill area with color
Reply #2 - Apr 18th, 2009, 9:25pm
 
Hi,
Assuming that you know the coordinates associated with the rectangles, it may be easier to just work with those. In the following code each rectangle is defined by its two X values (leftmost and rightmost) and two Y values (uppermost and lowermost). You can then test for an overlap by testing the coordinate values only. Four IF statements can determine whether or not two rectangles overlap. In the following code, I test for the one case where the 2nd rectangle is below and to the right of the first rectangle and paints the intersection red.
Code:

int[] r1= {50,100,10,70}; // left x, right x, top y, bottom y
int[] r2= {80,120,50,90}; // left x, right x, top y, bottom y
void setup() {
 size(300,300); background(255);
 fill(0);
 rect(r1[0],r1[2], r1[1]-r1[0], r1[3]-r1[2]);
 fill(100);
 rect(r2[0],r2[2], r2[1]-r2[0], r2[3]-r2[2]);
 // test for overlap - case 1 of 4 possible cases
 if(r1[1] > r2[0] && r1[3] > r2[2]) {
   fill(255,0,0);
   rect(r2[0],r2[2], r1[1]-r2[0], r1[3]-r2[2]);
 }
}


Hope this helps.
Re: intersecting rects fill area with color
Reply #3 - Apr 18th, 2009, 10:31pm
 
Quote:
Hi,
Assuming that you know the coordinates associated with the rectangles, it may be easier to just work with those. In the following code each rectangle is defined by its two X values (leftmost and rightmost) and two Y values (uppermost and lowermost). You can then test for an overlap by testing the coordinate values only. Four IF statements can determine whether or not two rectangles overlap. In the following code, I test for the one case where the 2nd rectangle is below and to the right of the first rectangle and paints the intersection red.
Code:

int[] r1= {50,100,10,70}; // left x, right x, top y, bottom y
int[] r2= {80,120,50,90}; // left x, right x, top y, bottom y
void setup() {
 size(300,300); background(255);
 fill(0);
 rect(r1[0],r1[2], r1[1]-r1[0], r1[3]-r1[2]);
 fill(100);
 rect(r2[0],r2[2], r2[1]-r2[0], r2[3]-r2[2]);
 // test for overlap - case 1 of 4 possible cases
 if(r1[1] > r2[0] && r1[3] > r2[2]) {
   fill(255,0,0);
   rect(r2[0],r2[2], r1[1]-r2[0], r1[3]-r2[2]);
 }
}


Hope this helps.


i don't know if this would work, though, if you had one rect with no vertices inside the other, while a region of the rect still intersects with the other [ie. rect1 x100, y100, sizex100, sizey100 and rect2 x50, y150, sizex200, sizey200]. this way both intersect while the range covered by the four if statements would not consider any intersection at all. i could be wrong, but by reading it superficially this came to my mind, as it seems you only compare the vertices to check if at least one vertex of a rect is inside the other rect.
Re: intersecting rects fill area with color
Reply #4 - Apr 20th, 2009, 7:41am
 
hello again,

first off, thanks for helping me crunch this out, your suggestions and help is greatly appreciated.

Boolean array for each pixel was the approach I needed.

Your assumption that I eventually want more than 2 rects was correct.  I therefore have attempted to make a class for this but I ran into some early problems.  Here is my first attempt at it with help from your sample code:

Code:

//frames
//mad props to pedro veneroso to help me figuring this one out

boolean[] r1b, r2b;
int numPixels;
Frame[] framey;

void setup () {
 background(255);
 size(500, 500);
 numPixels = width * height;
 
 framey = new Frame[2];
 for(int i = 0; i < 2; i++) {
   framey[i] = new Frame(150, 100, 200, 200);
 }
}


void draw () {
 framey[0].display();
}


class Frame
{
 int rx,ry,rxsize,rysize;
 boolean[] r1b, r2b;
 int[] r1,r2;
 color thisC;

 Frame(int xx, int yy, int xsize, int ysize) {
   rx = xx;
   ry = yy;
   rxsize = xsize;
   rysize = ysize;
   //couldnt get these varibles to pass to int[] r1 here moved to display method
   //kept getting null pointer exception
   
   r1b = new boolean[numPixels];
   r2b = new boolean[numPixels];
   thisC = color(0);
 }

  void display () {
    pushStyle();
    fill(128);
    noStroke();
    int[] r1 = {rx,ry,rxsize,rysize};
    int[] r2 = {100,200,200,200};
 
    rect(r1[0], r1[1],r1[2], r1[3]);
    rect(r2[0], r2[1], r2[2], r2[3]);
    popStyle();
 
    loadPixels();
 
    for(int i = 0; i < numPixels; i ++)
    {
      if((i/width) > r1[1] && (i/width) < (r1[1] + r1[3])
         && (i%width) > r1[0] && (i%width) < (r1[0] + r1[2]))
      {
         r1b[i] = true;
      }
      else{r1b[i] = false;}
    }
    for(int x = 0; x < numPixels; x ++)
    {
      if((x/width) > r2[1] && (x/width) <  (r2[1] + r2[3])
         && (x%width) > r2[0] && (x%width) < (r2[0] + r2[2]))
      {
         r2b[x] = true;
      }
      else{r2b[x] = false;}
    }
 
    for(int y = 0; y < numPixels; y++)
    {
      if(r1b[y] == true && r2b[y] == true)
      {
         pixels[y] = thisC;
      }
    }
 
 updatePixels();
   
 }
}


like i mention in my code, i couldnt get the varibles (rx,ry,etc) to pass to the r1,r2 array in my arguments, which is where i thought that should go, but i guess not.

I only made 2 rects (like you had in the sample) because I wasnt sure how making multiple rects or an array of them would work with the meat of your code (for and if statements) which I am still trying to wrap my head around.

Eventually, I think I want my class just to make one rect, and then check the others already made for intersections, and fill them and so forth.

thanks again for your help!
Re: intersecting rects fill area with color
Reply #5 - Apr 20th, 2009, 9:01am
 
hi,
you are very welcome. i am glad that helped.

ok. back to the code. inside frame(){} you should create the r1 and r2 int arrays declaring how many indexes both must have. otherwise you won't be able to associate values for specific indexes, once it will return null pointer exception.

that could be done this way, for example:
r1 = new int[4];
r2 = new int[4];

and if you want multiple rects and multiple values for them i would recommend that you create an int[][] array: int[number_of_rects][4]
this way you could access a specific rect and a value like this array_of_rects[0][0] < it would get the value on the first index of the first rect.
Re: intersecting rects fill area with color
Reply #6 - Apr 20th, 2009, 11:42am
 
helloo

I got past the null, im just manually assigning the spots as values as so:
   r1[0] = xx;
   r1[1] = yy;
   r1[2] = xsize;
   r1[3] = ysize;

My real difficulty comes when trying to make this 2D array.
Should I create the 2D array in my class?  I was planing on making an array of Frame{}s and then using a for loop to display them.

Then how would I make the intersections apply to all the rects instead of specific ones.  Of course my initial thinking tells me a for loop, but I am unsure how to impliment within your if and fors.

drew
Re: intersecting rects fill area with color
Reply #7 - Apr 20th, 2009, 4:00pm
 
you can create this 2d array instead of declaring r1 and r2 as separate arrays. take a look:

Code:

class Frame
{
 int rx,ry,rxsize,rysize;
 boolean[] r1b, r2b;

 int[] r1,r2; // instead of doing this you could do this:
 int[][] rectsArray; // 2d array


 color thisC;

 Frame(int xx, int yy, int xsize, int ysize) {
   rx = xx;
   ry = yy;
   rxsize = xsize;
   rysize = ysize;
   
   r1b = new boolean[numPixels];
   r2b = new boolean[numPixels];


  //then here:
   r12 = new int[number_of_rectangles][4]; //running only when
// an object is created
   r12[0][0] = rx;
   r12[0][1] = ry; //et cetera



   thisC = color(0);
 }

  void display () {
    pushStyle();
    fill(128);
    noStroke();


   int[] r1 = {rx,ry,rxsize,rysize}; //remove
    int[] r2 = {100,200,200,200}; // remove
 
// ...
// from here on you just have to correct your code substituting
// the old arrays for the new one

   }


when calling the r12[][] later you can just use it normally referring to r12[0][0] for the first rect's x pos, et cetera.

when you declare Frame(int xx, int yy, int xsize, int ysize) {} you could ask for a number of rects on screen and a number of properties for each rect that you can use when creating the array to make your code more flexible:
r12[number_of_rects][number_of_properties_for_each_rect];

i often create an initialize() method within every class to deal with associating variables to the objects which will be created. this runs only once inside setup(){}.

as for the boolean[]
you should create a boolean[][] 2d array as well: boolean[number_of_rects][number_of_pixels_on_the_screen]. then you will have to compare each rect to every other with two for iterations covering all the possible combinations. you can think of something to optimize it later.

the best idea would be to print every rect of the screen treating the whole set as one object. so, instead of dealing with each object from outside of your class you could analyze each rect, draw the intersections and draw the rects using methods you can develop for your class.
Re: intersecting rects fill area with color
Reply #8 - Apr 20th, 2009, 5:37pm
 
ok. i have done something you can take as a base. it will not work with more than 2 rects though.
Code:
intersections intersect;

int nRects;

void setup()
{
 background(255);
 size(400, 400);
 
 nRects = 2;
 intersect = new intersections(nRects, 4);
}

void draw()
{
 background(255);
 intersect.initializer();
 intersect.buildCheckInt();
 intersect.analyzeInt();
 intersect.drawScreen();
}


class intersections
{
 int numRects, numPixels, rectsIndexes, startAnalyse;
 boolean[][] checkInt;
 int[][] rects;
 PImage currentScreen;
 color thisColor;
 
 intersections(int nR, int rI)
 {
   numRects = nR;
   rectsIndexes = rI;
   numPixels = width * height;
   checkInt = new boolean[numRects][numPixels];
   rects = new int[numRects][rectsIndexes];
   currentScreen = createImage(width, height, RGB);
   startAnalyse = 0;
   thisColor = color(255, 0, 0);
 }
 
 void initializer()
 {
   
   rects[0][0] = 100;
   rects[0][1] = 100;
   rects[0][2] = 200;
   rects[0][3] = 200;
   rects[1][0] = 50;
   rects[1][1] = 150;
   rects[1][2] = 300;
   rects[1][3] = 200;

 }
 
 void buildCheckInt()
 {
   for(int x = 0; x < numRects; x ++)
   {
     for(int i = 0; i < numPixels; i ++)
     {
       if((i/width) > rects[x][1] &&
         (i/width) < (rects[x][1] + rects[x][3]) &&
         (i%width) > rects[x][0] &&
         (i%width) < (rects[x][0] + rects[x][2]))
       {
         checkInt[x][i] = true;
       }
       else{checkInt[x][i] = false;}
     }
   }
 }
 
 void analyzeInt()
 {
   startAnalyse = 0;
   for(int i = 0; i < numRects; i++)
   {
     for(int j = startAnalyse; j < numRects; j ++)
     {
       if(i != j)
       {
         for(int x = 0; x < numPixels; x ++)
         {
           if(checkInt[i][x] == true
             && checkInt[j][x] == true)
             {
               currentScreen.pixels[x] = thisColor;
             }
           else if(checkInt[i][x] == true
                    && checkInt[j][x] == false)
           {
             currentScreen.pixels[x] = 0;
           }
           else if(checkInt[i][x] == false
                   && checkInt[j][x] == true)
           {
             currentScreen.pixels[x] = 0;
           }
           else{currentScreen.pixels[x] = 0xFFFFFF;}
         }
       }
     }
     startAnalyse ++;
   }
 }
 
 void drawScreen()
 {
   image(currentScreen, 0, 0);
 }
 
}


the problem here is the analizeInt() method, because it keeps track only of the relations between 2 rects. this way if i drew a third rect when i call analizeInt() the interactions between the first two rects is reset. it would take some time to work further on the code to make it work and i am kind of busy right now working on a project. you can take this one as a basis and we can discuss further; i can aid you to get what you want, i just won't be able to write the whole code (:

let me know if you understand everything here; if you don't let me know and i can discuss specific issues with you for you to be able to modify it the way you want.

somethings you should consider:
the initialize() method could be used to generate the original coordinates for the rects to be draw.
as i don't actually draw any rect() on the screen it would be complicated to rotate them if you need this later for example [i am manipulating the array of pixels directly and creating the rects by doing so and not with the rect() function].
this software could get very complicated if you plan on making the interactions between rects more complex. maybe it would be better for me to know what you are planning to be able to help.

kind regards! pedro

ps. feel free to e-mail me if you want to discuss anything regarding these issues
Page Index Toggle Pages: 1