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.
Pages: 1 2 
Venn Diagram (Read 2133 times)
Venn Diagram
Jan 17th, 2010, 2:50am
 
Hi,

I need help to create a Venn diagram from two or more ellipse shapes, that I can also control the color in the overlap area while dragging one shape over the other.

Many thanks,

David.
Re: Venn Diagram
Reply #1 - Jan 17th, 2010, 3:56am
 
I think you're going to need to be a little bit more specific about what you want help with...  Drawing an ellipse surely isn't the problem here
Re: Venn Diagram
Reply #2 - Jan 17th, 2010, 4:56am
 
Hi,

The problem is to script the event when two ellipse collide and I need to control the overlapping area between them possibly as a new object, assigning a different color to this area. The overlapping area should be the only object to change color which will be assigned by the overlapping area size (or the distance between those ellipse).

Thanks,

David.
Re: Venn Diagram
Reply #3 - Jan 17th, 2010, 8:31am
 
This is a (very inefficient) way to draw a venn diagram where overlapping areas have different colors. It might give you some ideas.
It checks for each point on the screen in which ellipses it is located, and assigns a color given this information. Crude, but it works Smiley

A click of the mouse adds an ellipse.

Code:

int ellipseWidth = 150;
int ellipseHeight = 80;

float ellipseA = ellipseWidth/2.0f;
float ellipseB = ellipseHeight/2.0f;

ArrayList ellipses = new ArrayList();
ArrayList colors = new ArrayList();

void setup()
{
 size(500, 500);
 background(0);
 
 //Outside ellipses : black
 colors.add(color(0));
}

void draw()
{
 background(0);
 drawVennDiagram();
}

void mousePressed()
{
 //Add an ellipse
 ellipses.add(new PVector(mouseX, mouseY));
 
 //Double the amount of possible colors whenever we add an ellipse
 int nbOfColors = colors.size();
 for(int i = 0; i < nbOfColors; i++)
 {
   colors.add(randomColor());
 }
}

void drawVennDiagram()
{
 PVector mousePosition = new PVector(mouseX, mouseY);
 for(int i = 0; i < width; i++)
 {
   for(int j = 0; j < height; j++)
   {
     int index = 0;
     for(int e = ellipses.size()-1; e >= 0; e--)
     {
       PVector center = (PVector)ellipses.get(e);
       boolean inside = isInside(i, j, center, ellipseA, ellipseB);
       index = (index<<1) | (inside? 1:0);
     }
     stroke(getColor(index));
     point(i,j);
   }
 }
}

//Get a random color
color randomColor()
{
 return color(random(0, 255), random(0, 255), random(0, 255));
}

//Get the color at the given index in the colors array
color getColor(int index)
{
 return (Integer)colors.get(index);
}

/*Check if a point (x, y) is inside an ellipse defined by:
* the center of the ellipse
* a : width/2
* b : height/2
*/
boolean isInside(int x, int y, PVector center, float a, float b)
{
 float x1 = (x-center.x)/a;
 float y1 = (y-center.y)/b;
 return x1*x1 + y1*y1 < 1;
}
Re: Venn Diagram
Reply #4 - Jan 17th, 2010, 11:25pm
 
Thanks JR! Your script works, but it is also very slow and I can't use it on moving ellipse interactively...
Would it be more useful to use rectangles instead of ellipse, then create a new rectangles over the overlapping area as new objects?

David.
Re: Venn Diagram
Reply #5 - Jan 17th, 2010, 11:35pm
 
I said it was _very_ inefficient Smiley
Quite a bit can be improved if you detail what it is you want your sketch to do. (e.g. you can store information when it isn't changing and recalculating it when it does)
Re: Venn Diagram
Reply #6 - Jan 17th, 2010, 11:58pm
 
The main idea is to visualize two (or more) objects which are colored independently by their information, but when you drag one over the other using your mouse the overlapping area between these objects changes color by the information they both share (like in a Venn diagram).
I think the information should be stored in a pre-calculated matrix with the shared and independent values which will be used to color the sketch when objects are moved around.
Re: Venn Diagram
Reply #7 - Jan 18th, 2010, 8:42am
 
Is there a maximum number of objects which will be placed in the sketch and which can overlap?
Re: Venn Diagram
Reply #8 - Jan 18th, 2010, 9:00am
 
I'm not very pleased with this code, but it seems to work...

(I'm not pleased because of the maxloop variable I had to add to prevent a hang, for reasons I do not really understand ... yet)

Code:

ArrayList rectangles = new ArrayList();
Rectangle draggedRectangle = null;

ArrayList intersectionList = new ArrayList();

class Rectangle
{
int x;
int y;
int width;
int height;
color colour;

//The set of parents of this rectangle
ArrayList parents = new ArrayList();

public Rectangle(int x, int y, int width, int height, color colour)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.colour = colour;
}

public Rectangle(int x, int y, int width, int height)
{
this(x, y, width, height, randomColor());
}

void drawBorder()
{
stroke(255);
noFill();
rect(x, y, width, height);
}

void addParents(Rectangle parent)
{
if(parent.parents.size() == 0)
{
parents.add(parent);
}
else
{
for(int i = 0; i < parent.parents.size(); i++)
{
Object o = parent.parents.get(i);
if(!parents.contains(o))
{
parents.add(o);
}
}
}
}

int right()
{
return x + width;
}

int bottom()
{
return y + height;
}

Rectangle createRectangle(int left, int top, int right, int bottom, color colour)
{
if(right < left || bottom < top) return null;

return new Rectangle(left, top, right-left, bottom-top, colour);
}

Rectangle getIntersection(Rectangle other)
{
Rectangle intersection = createRectangle(max(x, other.x),
max(y, other.y),
min(right(), other.right()),
min(bottom(), other.bottom()),
averageColor(colour, other.colour));

if(intersection != null)
{
intersection.addParents(this);
intersection.addParents(other);
}

return intersection;
}

boolean hasSameParents(Rectangle other)
{
if(other.parents.size() == 0 || parents.size() == 0) return false;

if(other.parents.size() != parents.size()) return false;

boolean sameParents = true;
Iterator it = parents.iterator();
while(it.hasNext() && sameParents)
{
sameParents &= other.parents.contains(it.next());
}

return sameParents;
}

void draw()
{
fill(colour);
noStroke();
rect(x, y, width, height);
}

float distance(int x, int y)
{
int x1 = x-this.x-width/2;
int y1 = y-this.y-height/2;
return sqrt(x1*x1 + y1*y1);
}

void move(int dx, int dy)
{
x += dx;
y += dy;
}

void print()
{
println("Time: " + millis() + " X: " + x + " Y: " + y + " Width: " + width + " Height: " + height + " # Parents: " + parents.size());
}
}

void setup()
{
size(500, 500);
frameRate(30);
rectangles.add(new Rectangle(50, 50, 100, 200));
rectangles.add(new Rectangle(99, 100, 200, 50));
rectangles.add(new Rectangle(200, 99, 100, 100));
rectangles.add(new Rectangle(60, 200, 80, 70));
rectangles.add(new Rectangle(200, 300, 100, 100));
updateIntersections();

}

void draw()
{
background(0);

//Draw all rectangles
for(int i = 0; i < rectangles.size(); i++)
{
Rectangle rect = (Rectangle)rectangles.get(i);
rect.draw();
}

//Draw intersections
drawIntersections();

if(draggedRectangle != null)
{
draggedRectangle.drawBorder();
}
}

void drawRectangles()
{
}

void drawIntersections()
{
for(int i = 0; i < intersectionList.size(); i++)
{
ArrayList intersections = (ArrayList)intersectionList.get(i);
for(int j = 0; j < intersections.size(); j++)
{
Rectangle intersection = (Rectangle)intersections.get(j);
intersection.draw();
}
}
}

//Draw intersections of rectangles, and return these intersections
ArrayList calculateIntersections(ArrayList rectangles)
{
//Draw all intersection of rectangles
ArrayList intersections = new ArrayList();
for(int i = 0; i < rectangles.size(); i++)
{
Rectangle recti = (Rectangle)rectangles.get(i);
for(int j = 0; j < i; j++)
{
Rectangle rectj = (Rectangle)rectangles.get(j);
//We don't want to add an intersection of 2 rectangles with the same parents
if(!rectj.hasSameParents(recti))
{
Rectangle intersection = rectj.getIntersection(recti);
if(intersection != null)
{
intersections.add(intersection);
//intersection.print();
}
}
}
}
return intersections;
}

void mousePressed()
{
selectClosestRectangle();
}

void mouseReleased()
{
draggedRectangle = null;
}

void mouseDragged()
{
if(draggedRectangle != null)
{
draggedRectangle.move(mouseX - pmouseX, mouseY - pmouseY);
updateIntersections();
}
}

void updateIntersections()
{
ArrayList newIntersectionList = new ArrayList();
ArrayList intersections = rectangles;

int maxloop = 3;
int c = 0;
while(intersections.size() != 0 && c++ < maxloop)
{
intersections = calculateIntersections(intersections);
newIntersectionList.add(intersections);
}
intersectionList = newIntersectionList;
}

//Select the closest rectangle to drag
void selectClosestRectangle()
{
float dist = Float.MAX_VALUE;
Rectangle rectangle = null;
for(int i = 0; i < rectangles.size(); i++)
{
Rectangle rect = (Rectangle)rectangles.get(i);
if(rect.distance(mouseX, mouseY) < dist)
{
rectangle = rect;
dist = rect.distance(mouseX, mouseY);
}
}
draggedRectangle = rectangle;
}

//Get a random color
color randomColor()
{
return color(random(0, 255), random(0, 255), random(0, 255));
}

//Average two colors
color averageColor(color color1, color color2)
{
return (color1+color2)/2;
}
Re: Venn Diagram
Reply #9 - Jan 18th, 2010, 1:28pm
 
Thank you JR! The code does exactly what I described, this is great help.
There is no maximum number of rectangles but there shouldn't be much more than 8 for practical reasons. I noticed it runs much slower when I increase this number of rectangles, but I am pleased with it.

Is there a possibility also to program the values that defines each intersection color?
Can I attach text to each rectangle with its name or ID code?
Re: Venn Diagram
Reply #10 - Jan 18th, 2010, 1:37pm
 
You can attach to rectangles whatever you want Smiley

Yeah, the efficiency still isn't superb, I'll see if I can optimize Smiley
Re: Venn Diagram
Reply #11 - Jan 18th, 2010, 2:03pm
 
Here is a better version using ellipses, it doesn't update realtime, only when you click the mouse.

Code:

ArrayList ellipses = new ArrayList();
PGraphics buffer;

int ellipseWidth = 150;
int ellipseHeight = 80;

class Ellipse
{
int x;
int y;
float a;
float b;
color colour;

public Ellipse(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
a = width/2.0;
b = height/2.0;
colour = randomColor();
}

void drawBorder()
{
noFill();
stroke(255);
ellipse(x, y, 2*a, 2*b);
}

/*
* Check if a point (x, y) is inside an ellipse
*/
boolean isInside(int x, int y)
{
float x1 = (x-this.x)/a;
float y1 = (y-this.y)/b;
return x1*x1 + y1*y1 < 1;
}
}

void setup()
{
size(500, 500);
background(0);

buffer = createGraphics(width, height, P2D);
}

void draw()
{
background(0);
drawVennDiagram();

Ellipse el = new Ellipse(mouseX, mouseY, ellipseWidth, ellipseHeight);
el.drawBorder();
}

void mousePressed()
{
//Add an ellipse
ellipses.add(new Ellipse(mouseX, mouseY, ellipseWidth, ellipseHeight));

updateVennDiagram();
}

void drawVennDiagram()
{
image(buffer, 0, 0);
}

void updateVennDiagram()
{
buffer.beginDraw();
buffer.background(0);
for(int i = 0; i < width; i++)
{
for(int j = 0; j < height; j++)
{
int index = 0;
long c = 0;
int nColors = 0;
for(int e = ellipses.size()-1; e >= 0; e--)
{
Ellipse ellipse = (Ellipse)ellipses.get(e);
if(ellipse.isInside(i, j))
{
c += ellipse.colour;
nColors++;
}
}
buffer.stroke((nColors==0)?0:(color)(c/nColors));
buffer.point(i,j);
}
}
buffer.endDraw();
}

//Get a random color
color randomColor()
{
return color(random(0, 255), random(0, 255), random(0, 255));
}
Re: Venn Diagram
Reply #12 - Jan 18th, 2010, 2:33pm
 
Thank you again JR, but I need to keep the interactivity with a predefined number of objects like in the rectangles code.

I had some trouble with the constructor to add object id name as text inside the rectangle probably since there is no name for the intersection rectangles, how can I fix this?
Re: Venn Diagram
Reply #13 - Jan 18th, 2010, 11:15pm
 
The intersection rectangles refer to their parent rectangles, surely you could use that information to know which specific intersection it is.
Re: Venn Diagram
Reply #14 - Jan 20th, 2010, 12:27am
 
Thanks JR, I figured out the text addition problem.
The code with the Venn rectangles is very useful.
Pages: 1 2