Recently I've been looking at Povray, pyprocessing, and cfdg (version 3.0) as tools for creating digital images. I have branched two separate blogs where I mainly explore jruby + processing and processing.py

Sunday, 30 November 2008

Something We Can Aspire to

There is some amazing stuff being written in processing just check this out I think its absolutely brilliant.

http://www.robotacid.com/PBeta/physics_01/index.html

One for lazydog at least for the opengl.

NB: No less than 5 inner classes when converted to java, however from the programmers perspective dealt with by having separate *.pde files, so I think that must be the right approach...

PS: The inner class issue is dealt with in this part of the processing reference. In particular with reference to to the creation of static variables, which explains why my attempts to to create a move attribute for my 'Saucer' class failed previously.
The static variable cannot exist in an inner class, you could get round it programming in the java mode but that is not recommended (so I guess I will have to give it a go, I love a challenge). The non java solution is keep the static variable outside the inner class which is how my animated Saucer ended up.
Update (6 Dec 2008) just as an exercise:-
I used the netbeans refactor tool to create separate java classes for the worm program. The trick is to create a parent variable in each of the new separate classes requiring access to the code inherited by PApplet. Here is the the link to my re-factored worm it seems somewhat more lively than the original version.
The refactored version is now in a package monkstone, the Worm class (my PApplet class) is serializable, so I've added a serialVersionUID constant, which is supposed improve efficiency and parametrized a couple of Lists.
Update 9th January 2009 now refactored with a Point class that inherits from PVector.

Friday, 28 November 2008

Just Do It Style of Animation

Revision as of 16 February 2009
The animated Saucer class now uses PVector to store position, acceleration and velocity, however the outcome is still a bit crude. The Saucer is now has a center starting position, near to the focus of an animated starfield. Given an initial acceleration the Saucer picks up speed and travels in a linear direction to an arbitrary boundary, at the boundary the Saucer speed is killed and the acceleration is reversed. It is easier to see it than explain.
To view the simple applet animation follow this link. (path is now a bit more interesting)

I have also created alternative (mouse driven) interactive animation, where the saucer follows the mouse.
I have gone on to refactor this latter applet to create a java mode version which is now quite different, and features a saucer that tilts toward the direction it travels on the x-axis. The saucer is substantially refactored, it now implements my own HybridShape interface (revised as of 30 January 2009).

Wednesday, 26 November 2008

PShape class

Now that we are up to processing release version 1.0 we might expect developments in the PShape class as per this entry copied from http://dev.processing.org/reference/core/javadoc/processing/core/PShape.html:-

In-progress class to handle shape data, currently to be considered of alpha or beta quality. Major structural work may be performed on this class after the release of Processing 1.0. Such changes may include:

* addition of proper accessors to read shape vertex and coloring data (this is the second most important part of having a PShape class after all).
* a means of creating PShape objects ala beginShape() and endShape().
* load(), update(), and cache methods ala PImage, so that shapes can have renderer-specific optimizations, such as vertex arrays in OpenGL.
* splitting this class into multiple classes to handle different varieties of shape data (primitives vs collections of vertices vs paths)
* change of package declaration, for instance moving the code into package processing.shape (if the code grows too much).

For the time being, this class and its shape() and loadShape() friends in PApplet exist as placeholders for more exciting things to come. If you'd like to work with this class, make a subclass (see how PShapeSVG works) and you can play with its internal methods all you like.

Library developers are encouraged to create PShape objects when loading shape data, so that they can eventually hook into the bounty that will be the PShape interface, and the ease of loadShape().


Personally I,m not holding my breath, and for now at least I do not intend to inherit from this class, well unless Darrel thinks otherwise.

See my January posting to see my experiments with PShape and SVG.

Sunday, 23 November 2008

An Early Digital Artist?

More discussions with my artist friend this morning. One of his contemporaries Harold Cohen (b. 1928), had dropped painting in the conventional way, and apparently got into computing. I did a brief google search and found that he had developed a robotic artist Aaron. Heres it in action, with the "artist" beside it.



To find out more about Harold Cohen here is his biography and here is his web site.

You will also be interested in this site if you want to know more about Aaaron.

Update from my friend, it turns ca. fifty odd years ago Phil and his wife used to rent a room in a large Victorian house owned Harold Cohen and his brother. Neither of us are of the opinion that what the robot produces is art. Interestingly Cohens previous work was somewhat abstract (dots etc) so it is surprising how the robot seems to have developed a figurative bent! PS you can get a screensaver based on the Aaron program, I don't think I will bother. I reckon Cohen got taken up in all the early AI hype, although Aaron is coded in C, there is lisp interface, which chimes well with the AI community.

Saturday, 22 November 2008

Exploring Classes and Attributes in Processing

For my chunk I will be trying to consolidate the readers understanding of a class, by using a class for my Hybrid Shape. To explore the issues involved with processing and classes I have created a SimpleShape class (it's a square), defined using vertex (coordinates) within the beginShape() endShape() environment. The idea is my shape is symmetrical with a default center at (0,0) using cartesian coordinates. However the user of SimpleShape class can provide alternative coordinates to position the shape anywhere on the window (even off the window should they wish). The class also has a color attribute that can be set, the default color is white, with no transparency.
Now this is where I can see problems arising since processing uses 'color' as keyword, so anyone thinking too much in the java mould is apt to get it wrong, and the neat idea of classes having a capitalised first letter goes out the window. Using classes clearly can have their place within processing, even in my example its easy to see how the class acts as a factory and many instances can easily be created once the class has been built, it just seems to go against the grain a bit of the simplicity of the processing environment.
NB: the SimpleShape has a default size of 20 x 20, this can be scaled by entering a scale factor, there are no limits, perhaps I should have created some?
Here I chose to put class and the applet into different files this is how it looks on your ide:-



When the program is run this what you get:-



Here is the class code:-

   1:class SimpleShape {  
2: float xp, yp;
3: float myScale;
4: color c;
5: SimpleShape(){
6: xp = 0.0f;
7: yp = 0.0f;
8: myScale = 1.0f;
9: c = color(255);
10: }
11:
12: SimpleShape(float xpos, float ypos){
13: xp = xpos;
14: yp = ypos;
15: myScale = 1.0f;
16: c = color(255);
17: }
18:
19: void setScale(float myScale){
20: this.myScale =myScale;
21: }
22:
23: void setColor(int r, int g, int b){
24: setColor(r, g, b, 100);
25: }
26:
27: void setColor(int r, int g, int b, int trans){
28: this.c = color(r, g, b, trans);
29: }
30:
31: void drawSimpleShape(){
32: fill(c);
33: beginShape();
34: vertex((-10 * myScale) + xp, (-10 * myScale) + yp);
35: vertex((-10 * myScale) + xp, (10 * myScale) + yp);
36: vertex((-10 * myScale) + xp, (10 * myScale) + yp);
37: vertex((10 * myScale) + xp, (10 * myScale) + yp);
38: vertex((10 * myScale) + xp, (10 * myScale) + yp);
39: vertex((10 * myScale) + xp, (-10 * myScale) + yp);
40: vertex((10 * myScale) + xp, (-10 * myScale) + yp);
41: vertex((10 * myScale) + xp, (-10 * myScale) + yp);
42: vertex((-10 * myScale) + xp, (-10 * myScale) + yp);
43: endShape(CLOSE);
44: }
45:}


Here is the applet code:-
   1:void setup() {
2: size(600, 600);
3: SimpleShape shape = new SimpleShape(width/2, height/2);
4: shape.setScale(8);
5: shape.setColor(0, 255, 255);
6: shape.drawSimpleShape();
7: SimpleShape shape2 = new SimpleShape(width/3, height/3);
8: shape2.setColor(255,0,0, 100);
9: shape2.setScale(13);
10: shape2.drawSimpleShape();
11:}

Thursday, 20 November 2008

Creating A Simple Hybrid Shape

Earlier chapters should have introduce the usage of curves, for my fragment I've been asked to use classes to further consolidating the readers concepts of class. However I suspect there will also be a need to reinforce the readers understanding of the curve drawing capabilities of processing.
Here I present a simple example of a hybrid shape, combining a curve, generated by the use 4 curveVertex points and two straight lines either side (each defined using two vertex points).



The thick line represents the desired hybrid shape, the fainter line shows the data points required to define the curve between the two inner points (NB:these lines are not usually displayed, but given an insight into how the curve is defined).

   1:class HybridLine {
2:
3: private float k; // x coordinate shape center
4: private float t; // y coordinate shape center
5: /**
6: *
7: * @param xpos shape center
8: * @param ypos shape center
9: */
10:
11: HybridLine(float xpos, float ypos) {
12: k = xpos;
13: t = ypos;
14: }
15: /**
16: * default constructor
17: */
18: HybridLine() {
19: k = 0.0f;
20: t = 0.0f;
21: }
22:
23: /**
24: *
25: * @param x plus and minus parabola x coordinate
26: * @param y the y coordinate
27: * @param px plus and minus coordinate of line tangent
28: * @param py the y coordinate of line tangent
29: */
30: void drawCurve(float x, float y, float px, float py) {
31: curveVertex(k - px, t + py); // defines lh tangent
32: curveVertex(k - x, t + y); // is on curve and tangent
33: curveVertex(k + x, t + y); // is on curve and tangent
34: curveVertex(k + px, t + py); // defines rh tangent
35: }
36:
37: /**
38: * @param lx lhs x coordinate
39: * @param ly lhs y coordinate
40: * @param rx rhs x coordinate
41: * @param ry rhs y coordinate
42: */
43: void drawStraight(float lx, float ly, float rx, float ry) {
44: vertex(k + lx, t + ly);
45: vertex(k + rx, t + ry);
46: }
47:
48: /**
49: *
50: * @param x point on curve
51: * @param y point on curve
52: * @param px defines tangent
53: * @param py defines tangent
54: */
55: void drawTangent(float x, float y, float px, float py) {
56: line(k + px, t + py, k + x, t + y);
57: }
58:}
59:
60: void setup() {
61: size(400, 400);
62: float xpos = width / 2;
63: float ypos = height / 2 ;
64: HybridLine hline = new HybridLine(xpos, ypos);
65: strokeWeight(5);
66: noFill();
67: smooth();
68: beginShape();
69: hline.drawStraight(-150, -100, -80, -100);
70: hline.drawCurve(80, -100, 150, 300);
71: hline.drawStraight(80, -100, 150, -100);
72: endShape();
73: strokeWeight(1);
74: hline.drawTangent(-80, -100, -150, 300);
75: hline.drawTangent(80, -100, 150, 300);
76: }



I propose to create a flying saucer shape with a curved dome on the top of a solid shape.
NB: only if you want to complete ('an enclosing') shape should you endShape(CLOSE).

Monday, 17 November 2008

Separate files for classes?

Just a thought.
Does anyone know what is preferred in processing, is it like java where it is usual to put your classes in a separate file?
The ide handles it by displaying the separate files in tabs, which is pretty neat.

Update, I guess it doesn't matter, you can do what you like since when you export the PApplet the classes become "inner classes" of your PApplet class, see my later post "Inner Classes".

Sunday, 16 November 2008

Refactored Hybrid Shape

I can seriously recommend using netbeans to develop your processing code, this is my second refactored hybrid shape (see page 367 of the book Figure 9-20), in the first instance I 'functionalised' the code, in this second pass I have introduced a class. In both cases netbeans made the refactoring a cinch and its a doddle to convert the java code back to pde format.

Here is my refactored Gear class, another change I made was cut out the redundant conversion from degrees to radians, I believe the reader should get into radians rather have all the unnecessary and messy conversions (it would need to be introduced earlier in the book):

   1:import processing.core.*;
2:
3:void setup() {
4: size(600, 600);
5: strokeWeight(10);
6: int teeth = 8;
7: float rad1 = 250.0f;
8: fill(255);
9: Gear gear = new Gear(teeth, width / 2, height / 2, rad1);
10: gear.drawGear();
11:}
12:
13:class Gear {
14:
15: int cogs = 8;
16: int x = 0, y = 0;
17: float rad = 10;
18:
19: /**
20: * Constructor with arguments
21: */
22: Gear(int teeth, int xpos, int ypos, float radius) {
23: cogs = teeth;
24: x = xpos;
25: y = ypos;
26: rad = radius;
27: }
28:
29: /**
30: * Default Constructor
31: */
32: Gear() {
33: }
34:
35: /**
36: * creates a hybrid shape with
37: * @param sides int number of sides
38: * @param x int center position
39: * @param y int center position
40: * @param rad1 float radius curve
41: */
42: private void makeHybrid(int sides, int x, int y, float rad1) {
43: curveTightness(-0.8f);
44: smooth();
45: beginShape();
46: float[] cxy = new float[2];
47: float[] pxy = new float[2];
48: float angle = PI/sides;
49: float ang = TWO_PI / (sides + sides / 2.0f);
50: float ang2 = ang / 2.0f;
51: float rad2 = rad1 * 2.0f;
52: for (int i = 0; i < sides; i++) {
53: cxy = shapePosition(x, y, angle, rad2);
54: curveVertex(cxy[0], cxy[1]);
55: pxy = shapePosition(x, y, angle, rad1);
56: curveVertex(pxy[0], pxy[1]);
57: angle += ang;
58: pxy = shapePosition(x, y, angle, rad1);
59: curveVertex(pxy[0], pxy[1]);
60: cxy = shapePosition(x, y, angle, rad2);
61: curveVertex(cxy[0], cxy[1]);
62: pxy = shapePosition(x, y, angle, rad1);
63: vertex(pxy[0], pxy[1]);
64: angle += ang2;
65: pxy = shapePosition(x, y, angle, rad1);
66: vertex(pxy[0], pxy[1]);
67: }
68: endShape(CLOSE);
69: }
70:
71: /**
72: * Calculate shape coordinates from radius, angle and center coordinates
73: * and the angle and radius parameters
74: * @param x int center position
75: * @param y int center position
76: * @param angle radians
77: * @param radius float
78: * @return {xnew, ynew} float[]
79: */
80: private float[] shapePosition(int x, int y, float angle, float radius) {
81: x += cos(angle) * radius;
82: y += sin(angle) * radius;
83: float[] result = new float[2];
84: result[0] = x;
85: result[1] = y;
86: return result;
87: }
88:
89: /**
90: * public draw method
91: */
92: void drawGear() {
93: makeHybrid(cogs, x, y, rad);
94: noLoop();
95: }
96:}



For some reason both the original code and my refactored code produce extraneous bits off the gear outline, does this happen for anyone else?

Saturday, 15 November 2008

Chunk 68: Hybrid Shapes

I've chosen my chunk, and created a blog to cover it, however do not expect too much activity there while I continue to explore processing, albeit with a renewed focus. Not so much on complex shapes but more on how to create and use classes in processing. There is not much danger of me plagiarising Ira Greenberg, since his examples of hybrid shapes in chapter 9 look as though they have been written in a procedural language.

Friday, 14 November 2008

What is Art

I had a vigorous discussion this morning with my artist friend (Philip Sutton RA) about how I would define an artist. The discussion began after I told him about the "Wooden Mirror" by Daniel Rozin, you may have seen it on one of the OU podcasts. Phil is somewhat old school, he is 80 after all, and thinks such installations have gone from being art to being a performance. You can be sure he did not vote Tracey Emin to the academy (and she did not turn up for his 80th birthday bash at the academy).
Anyway it set me thinking about the following convoluted concept:-
Wouldn't it be cool to create a digital representation of the 'Wooden mirror' or 'Trash Mirror' using processing, conceptually it should be possible to display such an image that would respond to say webcam input?
Update 16 January 2009 Dan Schiffman describes how to implement a webcam mirror in his tutorial PartIII image processing.

Phils book is out now (but you've now missed his 80th birthday exhibitions).



One thing perhaps not unique to Phil is that he often decorates the frames, I was thinking of creating a Picture class for my "Mondrian", HAS_FRAME could be an attribute.

Wednesday, 12 November 2008

Art and The Golden Ratio

Next plan is to create a representation of a Mondrian painting (Composition in Red Yellow and Blue).

And to follow that by creating a golden spiral image:



Thus extending my theme of the golden ratio.
In my first quick and dirty go at the Mondrian, I used 'magic numbers' to define the rectangles sizes/positions. In the revised code presented here, all dimensions are relative to the 'baseLength' variable (width of the red rectangle). I am not sure about Mondrian and the golden ratio, but in my version the height of the window is in that ratio with the 'baseLength'.

   1:float PHI = (1 +sqrt(5))/2;
   2:int baseLength = 400; // alter this to scale image
   3:int stkwt = ceil (0.02333 * baseLength); // half stroke width
   4:int stkwt2 = stkwt * 2;
   5:int firstWidth = ceil(baseLength * 0.31);
   6:int secondWidth = ceil(baseLength * 0.69);
   7:int thirdWidth = baseLength - secondWidth - stkwt2;
   8:int windowHeight = ceil(baseLength * PHI);
   9:int redHeight = ceil(baseLength * 1.18); // height of red element
  10:int blueHeight = windowHeight - redHeight - stkwt2;
  11:int windowWidth = firstWidth + baseLength;
  12:String fake = "FAKE";
  13:PFont font;
  14:
  15:void setup(){
  16:  size(windowWidth, windowHeight);
  17:  strokeWeight(stkwt2);
  18:  rect(stkwt, stkwt, windowWidth - stkwt2, windowHeight - stkwt2);        
  19:  rect(stkwt, stkwt, firstWidth, windowHeight - stkwt2);
  20:  rect (stkwt, stkwt, firstWidth, firstWidth);
  21:  fill(255,0,0);
  22:  rect(firstWidth + stkwt, stkwt, baseLength - stkwt2, redHeight);
  23:  fill(255, 255, 255);        
  24:  rect(firstWidth + stkwt, redHeight +stkwt, secondWidth, blueHeight);
  25:  fill(255, 255, 3); //yellow
  26:  rect(firstWidth + secondWidth +  stkwt, redHeight + thirdWidth - stkwt, thirdWidth, blueHeight - thirdWidth +stkwt2);
  27:  fill(45, 15, 154);
  28:  rect (stkwt, redHeight +stkwt, firstWidth, blueHeight );  
  29:  font = createFont("Times New Roman", 96);  
  30:  textFont(font, 96);
  31:  fill(0);
  32:  smooth();
  33:  text(fake, 200, 200);      
  34:}



Here is my fake 'Mondrian' which is very approximate.



I have also converted the above script to display without a jvm see link requires support for the 'canvas' html element, and apparently the "fake" text will currently only display if are using a firefox 3.0 browser, see later posting for how its done using javascript. Revision as of 23 December 2008, I am not the first person to demonstrate processing using a Mondrian example heres a link to a random example I have found.

Update 12 May 2009 I am getting closer to implementing the golden spiral check out my chunk 42 and or ruby-processing blogs

Tuesday, 11 November 2008

Creating and using libraries

Its pretty easy to create your own java libraries and include them into your processing application. Continuing with my theme of φ the golden ratio I have created a library class with a static variable PHI. However the main purpose the class is to return a Dimension instance such that the ratio of width to height can be defined(eg as φ, π or sqrt(2)). To prevent the ratio collapsing for small values, I have set a minimum size of 10 for either width or height. Here is my java code.

   1:
2:/**
3: * The idea for this class is that it can return either
4: * width and height, or a Dimension instance, where the ratio
5: * of the two sides is special number eg phi, pi or root(2)
6: * The minimum size has been set to 10 pixels
7: * @author Martin Prout
8: */
9:public class SpecialDimension {
10:
11: public final int MINSIZE = 10;
12: // static constant
13: public static final double PHI = (1 + Math.sqrt(5)) / 2;
14: public java.awt.Dimension special;
15: /**
16: * A version where the width is set as a proportion of height
17: * using the ratio value typically PHI or PI or root 2
18: * Arbitary minimum value 10 x 10. Since ratio is typically an
19: * irrational number rounding is required
20: * @param height int base
21: * @param ratio double multiplier
22: */
23: public SpecialDimension(int height, double ratio) {
24: if (height < MINSIZE)
25: { height = MINSIZE;}
26: int width = (int)Math.ceil (ratio*height);
27: if (width < MINSIZE){ // then ratio < 1
28: width = MINSIZE;
29: height = (int)Math.ceil(MINSIZE/ratio);
30: }
31: special = new java.awt.Dimension (width, height);}
32: /**
33: *
34: * @return special width int
35: */
36: public int getWidth(){return special.width;}
37: /**
38: *
39: * @return special height int
40: */
41: public int getHeight(){
42: return special.height;
43: }
44: /**
45: *
46: * @return special Dimension
47: */
48: public java.awt.Dimension getSize(){
49: return special;
50: }
51:
52:}


To use this class as library for a processing application, compile it, archive it as jar file and place it in the 'code' folder.
Heres my processing code:

   1:SpecialDimension special = new SpecialDimension(400, SpecialDimension.PHI);
2:
3:final java.awt.Dimension WSIZE = special.getSize();
4:
5:void setup() {
6: size(WSIZE.width, WSIZE.height);
7: background(03366);
8: noLoop();
9:}


Displays OK for me as a blue window, default aspect ratio is landscape, a refinement would add a switch to the library class to create a portrait look (as per Mondrian).

Friday, 7 November 2008

Netbeans and Unit Testing

Heres an PApplet, I created in NetBeans6.5β with a view to exploring JUnit applied to a processing project. It is in need of refactoring to make it more testable, and to incorporate the @pre and @post conditions. Although I read somewhere that minimum size for the display window is 10 x 10, this is not forced with linux, you can even use negative numbers.

   1:import processing.core.PApplet;
2:
3:public class GoldenWindow extends PApplet {
4:
5: float PHI = (1 + sqrt(5)) / 2;
6: int maxheight = screen.height;
7: int maxwidth = screen.width;
8: int ht = maxheight / 2;
9: int wdth = floor(PHI * ht); // comment this line uncomment next to test
10: // int wdth = 5; test does fail, although applet runs OK
11:
12: /**
13: * pre: ((width && height >= 10) &&
14: * ((width <= maxwidth) && (height <= maxheight)))
15: * post: instance != null
16: */
17: @Override
18: public void setup() {
19: size(wdth, ht);
20: background(03366);
21: }
22:
23: /**
24: * pre: (instance != null)
25: */
26: @Override
27: public void draw() {
28: }
29:
30: /**
31: * Is the main method required in netbeans
32: * @param args
33: */
34: public static void main(String[] args) {
35: PApplet.main(new String[]{"GoldenWindow"});
36: }
37:}


The output looked pretty tidy to me so I proceeded to set up some tests (I'm no expert at this so I would welcome any comments). Although its pretty clear I should refactor the code to render it more testable, and to impose the pre and post conditions.

   1:import org.junit.Test;
2:import static org.junit.Assert.*;
3:
4:/**
5: *
6: * @author Martin Prout
7: */
8:public class GoldenWindowTest {
9:
10: public GoldenWindowTest() {
11: }
12:
13: /**
14: * Test of setup method, of class GoldenWindow.
15: */
16: @Test
17: public void testSetup() {
18: System.out.println("setup");
19: GoldenWindow instance = new GoldenWindow();
20: assertTrue("Dimension < min", ((instance.wdth >= 10) && (instance.ht >= 10)));
21: assertTrue("Dimension > max", (instance.wdth <= instance.maxwidth) && (instance.ht <= instance.maxheight));
22: }
23:
24: /**
25: * Test of draw method, of class GoldenWindow.
26: */
27: @Test
28: public void testDraw() {
29: GoldenWindow instance = new GoldenWindow();
30: System.out.println("draw");
31: assertNotNull(instance);
32: instance.draw();
33: }
34:}


Update on templates for netbeans check this out http://code.google.com/p/netbeans-processing-template/NB: make sure add the core processing library to your project (revised Sunday 9:15 pm)

Followers

Blog Archive

About Me

My photo
Pembrokeshire, United Kingdom
I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2