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 › editable shape database
Page Index Toggle Pages: 1
editable shape database (Read 1485 times)
editable shape database
Apr 17th, 2010, 8:21am
 
Hi guys (& girls!!),

I've been playing around with a very simple parametric drawing app, but I want to make sure I get started off on the right foot. I'm new to OOP, so I'd appreciate your help on this.

I want the user to be able to draw inter-dependent shape objects, such as the "pointObject" and "lineObject" classes in the current app (linked below). I'm assuming that the list of objects would be achieved with an Arraylist, but beyond that I'm not quite sure how to handle it, since I'm likely to have lots of different types of shapes. Can an Arraylist handle multiple classes of object, or do the objects within an Arraylist have to be all of the same type?

Thanks a ton for your help! Here's the (very basic) app:

http://adam.theoherns.com/applets/interfaceFun_v002/

Re: editable shape database
Reply #1 - Apr 17th, 2010, 9:52am
 
AdamTheNoob wrote on Apr 17th, 2010, 8:21am:
Can an Arraylist handle multiple classes of object, or do the objects within an Arraylist have to be all of the same type

Yes to the first question, but it is better to have related objects in a collection.
A good way to relate different objects is to define an interface, or a base abstract class, and to derive your objects from this base.
Thus you define the collection of the base type, and can call methods defined in the interface/abstract class, like update(), display(), etc.
Ie. you are sure the objects, whatever their exact type, will answer a base contract about the behavior of the objects.
Re: editable shape database
Reply #2 - Apr 17th, 2010, 11:14am
 
That sounds exactly like the kind of information I need!

Before I think I can fully understand your answer, I'm going to have to dig into Java collections a bit. For anyone who's curious, I found this:

http://java.sun.com/docs/books/tutorial/collections/

When I understand your answer better, I'll probably have more questions! Smiley Thanks!
Re: editable shape database
Reply #3 - Apr 17th, 2010, 11:29am
 
PhiLho  wrote on Apr 17th, 2010, 9:52am:
A good way to relate different objects is to define an interface, or a base abstract class, and to derive your objects from this base.
Thus you define the collection of the base type, and can call methods defined in the interface/abstract class, like update(), display(), etc.
Ie. you are sure the objects, whatever their exact type, will answer a base contract about the behavior of the objects.


If I understand you correctly, you might define:

Code:

void draw() {
 objectsCollection.display();
}

class objectsCollection() {
 ...
 void display() {
   for(int i=0; i<geometricObjects.size(); i++) {
geometricObject.get(i).display();
}
 }
 ...
}
class geometricObject() {...}
class lineObject extends geometricObject() {...}
class pointObject extends geometricObject() {...}


Does that make sense?
Re: editable shape database
Reply #4 - Apr 17th, 2010, 1:35pm
 
Yes, that's a way to do it (but no () in class definition!).
Re: editable shape database
Reply #5 - Apr 17th, 2010, 2:22pm
 
Haha, oh yeah. Duh Smiley I'll do it right in the real program! Thanks again.
Re: editable shape database
Reply #6 - Apr 17th, 2010, 9:55pm
 
Here's what I ended up with. I'm using java.awt.Polygon to find out when I mouse over the interior of the shape, but I haven't rigged it up to update when you drag the vertices yet. Other than that it seems to be peachy!


Code:
import controlP5.*;
objectsCollection objects;
int clickTolerance = 5;

void setup() {
 size(400,400); smooth();
 objects = new objectsCollection();
 objects.spawnTriangle();
}

void draw() {
 background(255);
 objects.display();
}

void mousePressed() {
 objects.pressedMouse();
}

void mouseDragged() {
 objects.draggedMouse();
}

void mouseReleased() {
 objects.releasedMouse();
}


class objectsCollection {
 ArrayList theObjects;
 int serialIDCounter = 0;
 
 objectsCollection() {
   theObjects = new ArrayList();
 }
 
 void display() {
   if(!theObjects.isEmpty()) {
for(int i=0; i<theObjects.size(); i++) {
 geomObject theObject = (geomObject)theObjects.get(i);
 theObject.display();
}
   }
 }
 
 void spawnPoint(float x, float y) {
   theObjects.add(new pointObject(serialIDCounter(),x,y));
 }
 
 void spawnLine(pointObject p1, pointObject p2) {
   theObjects.add(new lineObject(serialIDCounter(),p1,p2));
 }
 
 void spawnShape(ArrayList vertices) {
   theObjects.add(new shapeObject(vertices));
 }
 
 void spawnTriangle() {
   spawnPoint(width/2,height/2-50);
pointObject p1 = (pointObject) theObjects.get(latestIndex());
   spawnPoint(width/2-50,height/2+50);
pointObject p2 = (pointObject) theObjects.get(latestIndex());
   spawnPoint(width/2+50,height/2+50);
pointObject p3 = (pointObject) theObjects.get(latestIndex());

   ArrayList vertices = new ArrayList();
vertices.add(p1);
vertices.add(p2);
vertices.add(p3);
spawnShape(vertices);
   
   spawnLine(p1,p2);
   spawnLine(p2,p3);
   spawnLine(p3,p1);
 }
 
 int latestIndex() { return theObjects.size()-1; }
 
 int serialIDCounter() {
   serialIDCounter++;
   return serialIDCounter;
 }
 
 void pressedMouse() {
   for(int i=0; i<theObjects.size(); i++) {
geomObject theObject = (geomObject)theObjects.get(i);
theObject.pressedMouse();
   }
 }
 
 void draggedMouse() {
   for(int i=0; i<theObjects.size(); i++) {
geomObject theObject = (geomObject)theObjects.get(i);
theObject.draggedMouse();
   }
 }
 
 void releasedMouse() {
   for(int i=0; i<theObjects.size(); i++) {
geomObject theObject = (geomObject)theObjects.get(i);
theObject.releasedMouse();
   }
 }
}


class geomObject {
 int ID;
 String type = "";
 
 void setID(int i) {
   ID = i;
 }
 
 void display() {}
 
 void pressedMouse() {}
 
 void draggedMouse() {}
 
 void releasedMouse() {}
}



class lineObject extends geomObject {
 pointObject p1; pointObject p2;
 PVector mouseDatum = new PVector();
 boolean locked = false;
 
 lineObject(int IDi, pointObject p1i, pointObject p2i) {
   ID = IDi;
   p1 = p1i; p2 = p2i;
   type = "line";
 }
 
 void display() {
   noFill(); stroke(200); strokeWeight(1);
   if(bounds(mouseX,mouseY)) stroke(#ffcc00);
   line(p1.location.x,p1.location.y,p2.location.x,p2.location.y);
   
   p1.display();
   p2.display();
   
   if(bounds(mouseX,mouseY)) {
PVector mid = PVector.add(p1.location,p2.location); mid.div(2);
noFill(); stroke(200); strokeWeight(1);
ellipse(mid.x,mid.y,12,12);
   }
 }
 
 boolean clicked(float x, float y) {
   if (p1.bounds(x,y) || p2.bounds(x,y) || bounds(x,y)) return true;
   else return false;
 }
 
 void pressedMouse() {
   if(bounds(mouseX,mouseY)) {
locked = true;
mouseDatum.set(mouseX,mouseY,0);
   }
 }
 
 void draggedMouse() {
   if(locked) {
PVector mouse = new PVector(mouseX,mouseY);
mouseDatum.sub(mouse);
p1.location.sub(mouseDatum);
p2.location.sub(mouseDatum);
mouseDatum = mouse;
   }
 }
 
 void releasedMouse() {
   locked = false;
 }
 
 boolean bounds(float x, float y) {
   PVector mouse = new PVector(x,y);
   if(distFromSeg(p1.location,p2.location,mouse) < clickTolerance &&
lineSegRatio(p1.location,p2.location,mouse) < 1 &&
lineSegRatio(p1.location,p2.location,mouse) > 0 &&
!p1.bounds(mouseX,mouseY) && !p2.bounds(mouseX,mouseY))
return true;
else return false;
 }
 
 float distFromSeg(PVector p1, PVector p2, PVector outlier) {
   float g = PVector.dist(p1,p2);
   float a = PVector.dist(p1,outlier);
   float ratio = lineSegRatio(p1,p2,outlier);
   return sqrt( sq(a) - sq(ratio * g));
 }
 
 float lineSegRatio(PVector p1, PVector p2, PVector outlier) {
   float g = PVector.dist(p1,p2);
   float a = PVector.dist(p1,outlier);
   float b = PVector.dist(p2,outlier);
   return (sq(a) + sq(g) - sq(b))/(2*sq(g));
 }
 
 
}



class pointObject extends geomObject {
 PVector location;
 boolean locked = false;
 PVector mouseDatum = new PVector(0,0);

 pointObject(int IDi, float xi, float yi) {
   ID = IDi;
   location = new PVector(xi,yi);
   type = "point";
 }
 
 void display() {
   fill(0); noStroke();
   if(bounds(mouseX,mouseY)) fill(#ffcc00);
   ellipse(location.x,location.y,5,5);
   
   if(bounds(mouseX,mouseY)) {
noFill(); stroke(200); strokeWeight(1);
ellipse(location.x,location.y,12,12);
   }
 }
 
 boolean bounds(float x, float y) {
   PVector mouse = new PVector(x,y);
   if (PVector.dist(location,mouse) < clickTolerance) return true;
   else return false;
 }
 
 void pressedMouse() {
   if (bounds(mouseX,mouseY)) {
locked = true;
mouseDatum.set(mouseX,mouseY,0);
   }
 }
 
 void draggedMouse() {
   if(locked) {
PVector mouse = new PVector(mouseX,mouseY);
mouseDatum.sub(mouse);
location.sub(mouseDatum);
mouseDatum = mouse;
   }
 }
 
 void releasedMouse() {
   locked = false;
 }
}

// TRUNCATED. SEE NEXT POST.
Re: editable shape database
Reply #7 - Apr 17th, 2010, 9:56pm
 
Code:
class shapeObject extends geomObject {
ArrayList vertices;
Poly thePoly;

shapeObject(ArrayList pointObjects) {
type = "shape";
vertices = pointObjects;

int[] x = new int[vertices.size()];
int[] y = new int[vertices.size()];
for(int i=0; i<vertices.size(); i++) {
pointObject p = (pointObject) vertices.get(i);
x[i] = int(p.location.x);
y[i] = int(p.location.y);
}
thePoly = new Poly(x,y,vertices.size());
}

void display() {
if(thePoly.contains(mouseX,mouseY)) fill(#fff6d3); else fill(250);
noStroke();
beginShape();
for(int i=0; i<vertices.size(); i++) {
pointObject vert = (pointObject) vertices.get(i);
vertex(vert.location.x,vert.location.y);
}
endShape(CLOSE);
}
}

class Poly extends java.awt.Polygon {
public Poly(int[] x,int[] y, int n){
//call the java.awt.Polygon constructor
super(x,y,n);
}

void drawMe(){
beginShape();
for(int i=0;i<npoints;i++){
vertex(xpoints[i],ypoints[i]);
}
endShape();
}
}
Re: editable shape database
Reply #8 - Apr 18th, 2010, 4:18am
 
Very cool and instructive.

For sharing larger snippets of code you might consider
a) using the "copy for discourse" option in Processing (will give nicely coloured code in the forum)
b) storing/sharing the code via another site such as
http://openprocessing.org
Re: editable shape database
Reply #9 - Apr 18th, 2010, 7:09am
 
Bejoscha wrote on Apr 18th, 2010, 4:18am:
a) using the "copy for discourse" option in Processing (will give nicely coloured code in the forum)


Cool! I'll definitely keep that in mind!
Re: editable shape database
Reply #10 - Apr 18th, 2010, 10:35am
 
Thanks for the tip on openProcessing.org! Very cool site. I cleaned up the code quite a bit this morning. Here's the latest:

http://openprocessing.org/visuals/?visualID=8954
Page Index Toggle Pages: 1