« Back to Processing

Building blocks

| No Comments | Published on April 5, 2008
The content that follows was originally published on the Don Havey website at http://donhavey.com/blog/tutorials/building-blocks/

I’ve written a very brief introduction to Processing. Hopefully people found it so tantalizingly uninformative that they resolved to visit the Processing website and learn the basics of the language via the tutorials there.

Today, I introduce my generic classes: the building blocks on which I’ll be creating some exciting applets for your viewing pleasure. This will be a little boring. You can skip it if you want, but in order to understand the code in future examples, you’ll eventually need to understand what’s happening in these core classes.

Wait!

I need to define the word class for those not accustomed to object-oriented programming and who haven’t read the tutorials yet. A class defines a type of object that can replicated within an applet. As an example, if you were creating a digital garden of sorts, you might define a “flower” class. Each class has a constructor function, which, when called, creates a new instance of that class. So for your pretty flower garden, you would write:

class Flower{
  //initialize all variables that belong to the flower class
  int npetals;
  //the flower class constructor function
  //is called whenever you write "new Flower()"
  Flower(int $npetals){
    //assign values to this instance's variables
    petals = $petals;
  }
  //some other function of the flower class
  void look_pretty(){
    //do something to look pretty
  }
}
//somewhere else in our code, we can now create flowers:
//initiate an array to contain some flowers
int nflowers = 50;
Flower[] flowers = new Flower[nflowers];
//loop through the array and initiate that many new flowers
for(int i=0;i<nflowers;i++){
  flower[i] = new Flower(floor(random(5,12)));
}

Additionally, classes can be extended so that one class may inherit all of the methods and variables of another, and add some methods and variables of its own. More on that later.

Wait again!

Before I continue, I should admit that my coding style is a little nonconformist. I tend to write denser code than is recommended… less whitespace… and sometimes I’ll make two related statements share a line. This will make my code a little awkward to read for people who come from stricter programming backgrounds. Too bad. I like density. Less scrolling, less eye movement, less space. It’s an unbreakable habit! Sorry.

Proceed!

Getting back to the point….

This is an unintentional set of core classes. I did not sit down and think “I need core classes, maybe I’ll write some.” That would be a silly thing to think. You can already find many great pre-built classes on the Processing website. Rather, this set of classes evolved from many many projects, each of which required some addition to the classes I created for a simpler (previous) project… until I had a pretty comprehensive set of core classes, which I now reuse compulsively.

I am making these classes (and all the source code files I upload to this site) freely available. They can be modified and distributed at will, as long as the credits and statement at the top of each file remain intact. If you love them, you can use them for your own projects, but I’d recommend taking a look at the libraries available on the Processing website first. You can probably find a better set of classes available there.

If you really love these classes and are planning on using them in your own work, you could buy me a drink or something.

Download the classes

Click here to get the files.

You’ll need to open the files in Processing to take a look; I won’t be posting the entire source here. The Processing editor’s syntax highlighting makes the code much more legible than what I could offer you on this page. I’ll only be describing the classes and posting snippets of the supporting code here.

Without further ado…

The Global class

One thing you’ll notice about the way I structure my work is that it is very much Actionscript-influenced. Not because I am in love with Actionscript, but rather just because it was the first OOP language I learned.

That said, this first class is a straightforward imitation of the “_global” object in Flash. Its sole purpose is organizational: to hold a list of all generic objects in the applet. As such, it enables us to refer to an object within an array of its peers, which I find helpful for debugging and for retrieving general information about an applet.

The Global class also allows us to limit the number of allowable objects of a certain class that can be created. Although I’ve never used it for this purpose, it could be helpful in debugging situations where you know that a certain type of object should not exceed x many instances.

The Global class is used to create only one instance of itself. Whenever an object is constructed using one of the generic classes, it is registered in its appropriate array within this instance.

The Point class

The Point class is pretty self-explanatory. It creates point objects that contain an x, y, and z coordinate, and has methods allowing us to move it and direct it and get its distance from a given coordinate. More about the moving and directing of points later…

The Vector class

Vectors are a huge part of 3D anything. They make the mathematics of 3D computation much more concise. You can read more about vector math by Googling it. Only a few of these tutorials will actually use the Vector class, but it’s included nonetheless, along with a few appended functions that I use to handle dot products and cross products.

If you look closely at the Vector class, you’ll notice that it has two constructor functions: one that accepts an xyz value, and one that accepts a point. This is how you work around overloading in Java, that is, the creation of an object with multiple types or numbers of parameters. Here is an example of how you could use multiple constructor functions to create a “holder” object that imitates the flexible typing of Flash:

class holder{
  Point p; Vector v; Segment s; Line l; Polygon po;
  String type;
  holder(Point $p){
    p = $p;
    type = "point";
  }
  holder(Vector $v){
    v = $v;
    type = "vector";
  }
  holder(Line $l){
    l = $l;
    type = "line";
  }
  holder(Polygon $po){
    po = $po;
    type = "polygon";
  }
  String get_type(){
    return type;
  }
}

This would allow you to store a bunch of different object types within a single array of the type “holder”. I’ll write more on this later. Calling the stored objects is still messy, since you couldn’t define one function within this “holder” class to return any single type. Instead, you’d need to first test for the type of object stored (using the “get_type()” function above), and then call for the proper variable using a case/switch conditional.

For our Vector class, however, the purpose of the two constructors is simply to allow us a quick way of converting a Point object into a vector (from {0,0,0}), or to create a Vector from some other xyz coordinates.

The Segment class

I define a Segment object as the portion of a line between two points. So Segments are used to represent, for example, the sides of a Polygon.

Within the Segment class there are a number of methods (a method is a function that is specified within a class) that can be used to detect the intersection of segments and lines and rays. Let’s try and add a bit of code to the generics.pde file that will illustrate the different Segment methods:

import processing.opengl.*;

int frame = 0;

//---init test stuff---//
Segment seg1,seg2,seg3;
Point p1,p2,p3,p4,p5,p6;
//----------------//

void setup(){
  size(300,300,OPENGL);
  global = new Global();
  global.init();
  //---setup test stuff---//
  p1 = new Point(-100,50,0); p2 = new Point(100,0,0); p3 = new Point(0,-100,0);
  p4 = new Point(0,-100,0); p5 = new Point(0,-100,0); p6 = new Point(0,-100,0);
  seg1 = new Segment(p1,p2); seg2 = new Segment(p3,p4); seg3 = new Segment(p5,p6);
  //----------------//
}

void draw(){
  frame++;
  background(50);
  pushMatrix();
  translate(width/2,height/2,0);
  //---draw test stuff---//
  p4.move_to(mouseX-width/2,mouseY-height/2,0);
  p5.move_to(mouseX-width/2,mouseY-height/2,0);
  p6.match(seg1.get_closest_point(mouseX-width/2,mouseY-width/2));
  Point intersect = seg1.get_intersect_point(seg2);
  fill(255,50);
  strokeWeight(1);
  if(seg1.is_segment_intersecting(seg2,true)){
    strokeWeight(4);
  }
  stroke(150,255,150);
  seg1.render();
  strokeWeight(1);
  stroke(150,150,255);
  seg2.render();
  stroke(255,150,150);
  seg3.render();
  p6.render();
  stroke(255);
  intersect.render();
  //----------------//
  popMatrix();
}

So this will give us three segments: one defined between two arbitrary points (green), one between a third arbitrary point and the mouse (blue), and one that represents the shortest path between the mouse and the first segment (red). Additionally, the projected intersection between the first and third segments is rendered as a white point. If the blue and green segments are crossing, the green segment will be rendered a couple pixels fatter. Click here to see it in action.

On a side note, you’ll notice that I use Processing’s “translate” function to shift the origin of the applet to the center, rather than the upper left corner.

The Line class

Although a line and a segment are essentially treated the same way when doing simple math operations, I distinguish the two for clarity. A Line object contains a reference to a Segment (which stores the two Points used to define the Line), but rather than being defined solely by those two Points, a Line also contains two variables: “a” and “b” that relate to the equation for a line (“y = ax+b”). Other than that, it’s really a semantic class, used in functions like Polygon splitting, etc., where you wouldn’t want to use a Segment.

The one interesting feature of the Line class is illustrated below. The shortest Segment between two Lines:

//---init test stuff---//
Segment seg1;
Point p1,p2,p3,p4;
Line line1,line2;
//----------------//
//---setup test stuff---//
p1 = new Point(-100,50,-30); p2 = new Point(100,0,30); p3 = new Point(0,-100,50); p4 = new Point(20,-120,0);
line1 = new Line(p1,p2); line2 = new Line(p3,p4);
//----------------//
//---draw test stuff---//
line2.s.p2.move_to(mouseX-width/2,mouseY-height/2,0);
seg1 = line1.get_segment_to_line(line2);
strokeWeight(1);
stroke(150,255,150);
seg1.render();
stroke(255);
line1.render();
line2.render();
//----------------//

Now obviously, if two non-parallel lines lie in the same plane, they intersect at a point. But if the lines are diverging in three dimensions, you may want to calculate the shortest path between them. It’s hard to see in this example because we’re not shown any indication of three dimensions, but the two Lines (rendered as segments here) are in different planes, and the green Segment represents the shortest distance between them. Click here to see what I’m talking about.

The Polyline class

This is a really simple class of objects whose sole purpose is to string together segments into a chain, similar to a pline in AutoCAD. No explanation necessary.

The Polygon class

The Polygon class is a good one. It takes turns a set of points into a closed shape, which can then be used and modified in a number of ways. I’m going to illustrate the two most important functions, starting with convex hulls:

//---init test stuff---//
Point[] ps = new Point[10];
Line line1;
Polygon pl1,pl2;
//----------------//
//---setup test stuff---//
for(int i=0;i<10;i++){
  ps[i] = new Point(random(-100,100),random(-100,100),0);
}
pl1 = new Polygon(ps);
line1 = new Line(zero_point,new Point(100,100,0));
//----------------//
//---draw test stuff---//
ps[0].move_to(mouseX-width/2,mouseY-height/2,0);
pl2 = pl1.get_convex_hull();
pl2.render();
for(int i=0;i<10;i++){
  ps[i].render();
}
//----------------//

A convex hull for a given set of points behaves like a rubber band. You’ll see what I mean when you click here to view the example. This is an important function when you require a simple polygon from a potentially complex sequence of points.

We can also split a Polygon into two:

//---init test stuff---//
Point[] ps = new Point[10];
Line line1;
Polygon pl1;
//----------------//
//---setup test stuff---//
for(int i=0;i<10;i++){
  ps[i] = new Point(random(-100,100),random(-100,100),0);
}
pl1 = new Polygon(ps);
pl1 = pl1.get_convex_hull();
//----------------//
//---draw test stuff---//
line1 = new Line(zero_point,new Point(mouseX-width/2,mouseY-height/2,0));
line1.crop();
stroke(255);
if(pl1.is_splittable(line1)){
  Polygon[] pls = pl1.split(line1);
  fill(255,150);
  pls[0].render();
  fill(255,50);
  pls[1].render();
}
stroke(255,150,150);
line1.render();
//----------------//

In each frame we split a predefined Polygon into two pieces and render each. This method will be at the core of the Voronoi diagram tutorial to come. Click here for the sample of Polygon splitting.

The Plane and Face classes

I’m not going to introduce these classes right now because (a) they’re a little complex, and (b) the first real tutorial will cover them in depth. They are both strictly 3D classes.

Go forth and code

That’s it for the introduction to my core classes. They are not perfect, as maybe you’ve noticed already. Some of them do not test for division-by-zero errors, some of them are redundant, some of them do things the hard way. Again, I’d recommend using the libraries available on the Processing website if you have trouble using or extending these.

I’d greatly appreciate any feedback on them as well. If you find bugs, email me.

From here on out, only exciting tutorials allowed…

Categories: Processing / Tutorials

Tags: / / /

Leave a Response

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>