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 & HelpPrograms › Mondrian painting program- Problems with pixel[]
Page Index Toggle Pages: 1
Mondrian painting program- Problems with pixel[] (Read 1049 times)
Mondrian painting program- Problems with pixel[]
Mar 20th, 2009, 1:06am
 
I am working on a few processing programs for a art show.  Im very new to processing and have been researching code generated art for about 2 months now.

The project i am currently working on is called 'Future Artist'.  It will be a 'Piet Mondrian' random painting simulator.  The paintings will resemble his compositions in red, yellow, and blue.

for visual reference:
http://en.wikipedia.org/wiki/File:Mondrian_CompRYB.jpg

At the moment i have constructed a program that will create the horizontal and vertical black lines. these lines will continue to draw until they run off the canvas  size.  I have attempted to add some simple collision detection for the canvas sides; now I would like to add collision detection to the lines themselves. Ex: If a line being drawn intercepts another line, then that line will stop.  I have attempted  to check for this using the pixel[] array. if the increasing coordinate value's color is black then it will not draw, if this color is white, that means the space is empty and it may continue drawling.


My first problem is that i run into a Index error, using pixel[y*width+x]   this is commented out in the drawLine() method of the Line class.  the error code is telling me i am trying to access a index of 160001,  well my canvas is 400x400 which = 160000,  so my guess is if the y variable generated 400 and was plugged in to the equation, what ever x is will throw us out of index.  I obtained this math from: http://processing.org/reference/pixels.html

y*width+x

My second problem: When pixel[y*width+x] actually returns a value to me the numbers make no since, I thought they were RGB color values, so i assumed they would be in a range of 0-255, i and receiving values of -1 to -16777216.  for the colors white and black respectively.

My third problem is that on some occasions, lines that have not intersected will stop drawing.  i have only attempted horizontal collisions, these if statements are commented out in the drawLine() method of the Line class
here is the code, it will parse:

int x, y;
int xo ,yo;
char dir;
ArrayList lines = new ArrayList();
int lineCount;

void setup(){
 size(400, 400);
 colorMode(RGB);
 smooth();
 frameRate(30);
 background(255);
 strokeCap(PROJECT);
 stroke(0);
 lineCount = int(random(1,15));

 for (int i = 0; i < lineCount; i++) {
   y = int(random(1, height));
   x = int(random(1, width));
   switch(int(random(0,2))){
   case 0:
     dir = 'H';
     break;
   case 1:
     dir = 'V';
     break;
   }
   // Line (int x1, int y1, int x2, int y2, int wweight, char HV)
   lines.add(new Line(x,y,int(random(2,15)),dir));
   //Line L = (Line) lines.get(i);// to cast the object coming out
 }
}
void draw(){

 background(255);
 for (int i = 0; i < lines.size(); i++) {
   Line L = (Line) lines.get(i);// to cast the object coming out
   L.drawLine(L.direction);
 }

}




class Line {
 int weight;
 int x;
 int y;
 int xo;
 int yo;
 int xx;
 int yy;
 int speedX;
 int speedY;
 int speedXX;
 int speedYY;
 char direction;

 Line (int x1, int y1, int wweight, char HV) {
   x = x1;
   xo = x1;
   xx = x1;
   y = y1;
   yo = y1;
   yy = y1;
   weight = wweight;
   direction = HV;
   speedX = int(random(1,4));
   speedY = int(random(1,4));
   speedXX = int(random(1,4));
   speedYY = int(random(1,4));
 }

 void drawLine(char dire) {
   stroke(0);
   strokeWeight(weight);
   x+=speedX;
   y+=speedY;
   xx-=speedXX;
   yy-=speedYY;
loadPixels();
   switch(dire) {
   case 'H':
     line(x, yo, xo, yo); //horizontal right
     line(xo, yo, xx, yo); // horizontal left

     if (x > width){
       speedX*=0;
     }
     else if (x < 0){
       speedX*=0;
     }
     else if (xx > width){
       speedXX*=0;
     }
     else if (xx == 0){
       speedXX*=0;
     }
     
     if (pixels[yo*width+x] == -16777216){
       speedX*=0;
     }
     int index = int(yo*width+xx);
     if(index > 160000) {
      index = 160000;
     }
     if (pixels[index] == -16777216){
       speedXX*=0;
     }
     
     break;

   case 'V':
     line(xo, yy, xo, yo); //vertical up
     line(xo, yo, xo, y); //vertical down
     if (y > height){
       speedY*=0;
     }
     else if (y < 0){
       speedY *=0;
     }
     else if (yy > height){
       speedYY*=0;
     }
     else if (yy < 0){
       speedYY*=0;
     }
     break;      
   }
   
   println("x = " +x+ " yo = " +yo+ " xo = "+xo);
   println(yo*width+x);

   /*
   else if(pixels[yo*width+xx] == -16777216){
    speedXX*=0;
    }
   
    if (pixels[yo*width+x] == -16777216){
    speedX *=0;
    }*/

 }
}

// box structure for later.
class Box {
 
 Box(){
   
 }
 
void drawBox(){
   
 }
}

//Thank you for you time reading this and any possible help you can give!

Re: Mondrian painting program- Problems with pixel
Reply #1 - Mar 20th, 2009, 1:30pm
 
You need to make your x and y variables go form 0->width-1 (or 0->height-1) not 1-width, in a 400x400 image, one corner is 0,0 and the other is 399,399.
Re: Mondrian painting program- Problems with pixel
Reply #2 - Mar 20th, 2009, 3:25pm
 
Grail wrote on Mar 20th, 2009, 1:06am:
When pixel[y*width+x] actually returns a value to me the numbers make no since, I thought they were RGB color values, so i assumed they would be in a range of 0-255, i and receiving values of -1 to -16777216.  for the colors white and black respectively.

RGB values: each component (R, G and B) is in 0-255 range. They are combined into an int number: R*65536 + G*256 + B
Moreover, there is also transparency in Processing's colors, opaque being 255, full transparency being 0.
That's why numbers become negative (ints in Java are always signed).
You can check gray color by inspecting only a component. For example rgbColor & 0xFF will give you the blue component, 0 for black, 255 for white.
Re: Mondrian painting program- Problems with pixel
Reply #3 - Mar 20th, 2009, 6:21pm
 
Also, you might find it easier to use the PImage.get() method instead of the pixels[] array.  pixels[] is great if you need high performance of reading/writing large numbers of pixels across the whole image.  For what you're doing, I doubt you need that level of performance (indeed, on modern hardware I doubt you'll even notice the difference), but get() will make your code clearer and easier to work with.

Also, if memory serves, some decades ago a computer science researcher did a computer learning experiment where he fed all the real Mondrians to his program, which "learned" their salient features and properties, and could then output new random Mondrians.  Apparently, his results were so good that art experts had great difficulty picking out the "real" Mondrians from the synthetic ones in side-by-side tests.  I don't recall whether the researcher did it with a neural net or an expert system or what, but it might be worth looking up.
Re: Mondrian painting program- Problems with pixel
Reply #4 - Mar 20th, 2009, 11:46pm
 
Thank you for you replies.
JohnG:  I managed to fix that out of bounds error last night  by using your values. I forgot about the actual indexing of the screens coordinate system.

PhiLho: That really cleared it up for me.  Nothing I have found under pixels[] on the reference section describes in detail it actual contained values.  Then i went to the color variable description after reading what you replied.  This was very helpful.

cloister:  I saw that on the reference of get(),  i thought about using it, it does seem a lot easier.  I went over to complexification and checked out j.tarbells
box-fitting and saw that he was using brightness() and get() for collision detection.  It worked pretty well for my boxes of color.


This is what I came up with last night after my post.

http://www.brandonaphillips.com/processing/projects/PietMondrian/


My collision detection is still flawed, however; I am not totally worried about it.  Collisions are fairly random and it kinda adds to it.  Im going to take in this advice you guys gave and mess with it to see if i can make this a little more fluid.  Not too bad for my 2 or 3rd processing project i guess.  My artist statement still needs work too. I might condense it into the pure program functionality.

Re: Mondrian painting program- Problems with pixel
Reply #5 - Mar 21st, 2009, 9:55am
 
You did quite a good job here, using classes and such.
I can make a number of minor remarks on the code, I will limit myself to some points.

- Lines like speedX*=0; are perplexing... speedX = 0; seems more logical! Wink
- L.drawLine(L.direction); could be just L.drawLine(); because the L object knows the direction value, no need to give it back.
- else if (xx >= width){ <== I think you should remove the else here, the test is unrelated to the previous one. Same for y.
- if (pixels[(yo*(width-1))+x] != -1){ should be [yo*width+x], the error might cumulate and be the reason why the lines stop early.



Re: Mondrian painting program- Problems with pixel
Reply #6 - Mar 21st, 2009, 5:40pm
 
Hi Grail,

Grail wrote on Mar 20th, 2009, 11:46pm:
This is what I came up with last night after my post.

http://www.brandonaphillips.com/processing/projects/PietMondrian/


Cool idea.

One thing that caught my eye and bugged me was the following code:
Code:

for (int i = 0; i < lines.size(); i++) {
Line L = (Line) lines.get(i);
L.drawLine();
}


The Line objects already exist inside the lines listarray so why should it be necessary to create yet another Line object just so you can call drawline()?  

I went through the Java doc trying to find an answer with no success. Googling didn't help either. Because the get() is returning an object reference that has to be downcast I tried several different casting methods so as to skip the explicit creation of Line L. I find that the following code works:

((Line)lines.get(i)).drawLine();

It's not at all intuitively obvious but it does free you from having to explicitly create another object.



Re: Mondrian painting program- Problems with pixel
Reply #7 - Mar 21st, 2009, 6:18pm
 
Jim, I fear you didn't understood fully how objects work. Smiley
No worries, it took me quite a while to grasp the concepts!

The line:
Line L = (Line) lines.get(i);
doesn't create a new object.

It declares a L variable of type Line. The assignment takes a reference to an existing line (which was created with new Line(...) and whose reference was stored in the ArrayList) and store it in L. So L only holds a reference, a 32bit (I think) integer, whatever the real size of the object.

Objects are created in the heap, with new, as we saw, and further assignments only manipulate the reference to these objects.

So your alternative is just a more concise, but less readable way of doing what Grail did. No more, no less.

That's a concept eluding lot of new comers to Java: when you do a Line lines = new Line[10]; you don't allocate the space for the objects, only for their references, which are null by default. You still have to loop and do new Line() for each entry.

:-D
Re: Mondrian painting program- Problems with pixel
Reply #8 - Mar 21st, 2009, 10:13pm
 
Hi PhiLho,

Thanks for that explanation. Always something new to learn.

Re: Mondrian painting program- Problems with pixel
Reply #9 - Mar 21st, 2009, 10:50pm
 
I made some of the adjustments you guys recommended.  However the lines still  don't collide properly sometimes.

I think this is because of 2 reasons.  The first is the speed. If the next coordinate leaps completely over a strokeWeight of a intersecting line, the collision is not noticed since the collision is checked at the next point only and only at the time they collide.  The second reason i think is the order in which the lines are drawn in the loop.  To the human eye it feels as if these processes are all happening at once but in reality each line of code is being executed in order. a line may draw at a point were the line WILL intersect, however the line it will intersect will be drawn after the collision check.

so i think it breaks down like this.  lets say we have 2 line objects on a 100,100 canvas.

line one is drawing horizontally on the y = 40
line 2's coordinates are  25,0, to  25, 49 (vertical)

line one draws before line 2,  line one checks for the collision at 25,40, since line 2 has not drawn,( that line of code has not executed) the check returns a white pixel reading.  so the line draws and continues on its way.

I thought of trying to alleviate this by not allowing the background to refresh, however when i do this the program seems to freeze,  but I think the collision checks just kill the speed variables.

Philho:  thats some pretty good insight on casting a object.  I knew it was something I should do but I didnt know why.  

Here is some minor revision. I still havn't had time to play with the brightness(); for collision detection on the lines.

http://www.brandonaphillips.com/processing/projects/PietMondrian/
Page Index Toggle Pages: 1