├── colourHoughBlog ├── sketch.properties └── colourHough01.pde ├── processingBlenderExport ├── bodyInteractions3DExport │ ├── sketch.properties │ ├── Square.pde │ ├── Circle.pde │ ├── bodyInteractions3DExport.pde │ ├── Body.pde │ └── System.pde └── bevelCurve.py ├── photoColourSort ├── data │ └── DSC035132.JPG └── photoColourSort.pde ├── README.md ├── .gitattributes ├── robotArtist01 └── robotArtist01.pde ├── robotArtist02 └── robotArtist02.pde └── .gitignore /colourHoughBlog/sketch.properties: -------------------------------------------------------------------------------- 1 | mode.id=processing.mode.java.JavaMode 2 | mode=Java 3 | -------------------------------------------------------------------------------- /processingBlenderExport/bodyInteractions3DExport/sketch.properties: -------------------------------------------------------------------------------- 1 | mode.id=processing.mode.java.JavaMode 2 | mode=Java 3 | -------------------------------------------------------------------------------- /photoColourSort/data/DSC035132.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justinpinkney/Processing/master/photoColourSort/data/DSC035132.JPG -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Processing 2 | ========== 3 | 4 | Code shared relating to [blog posts](http://www.cutsquash.com) on generative art type stuff I've done. 5 | Typically written for [Processing](http://www.processing.org). 6 | -------------------------------------------------------------------------------- /processingBlenderExport/bodyInteractions3DExport/Square.pde: -------------------------------------------------------------------------------- 1 | class Square extends Body { 2 | // not currently used 3 | float r; 4 | 5 | Square(PVector pos_, PVector speed_, PVector accln_, float mass_, float r_){ 6 | super(pos_, speed_, accln_, mass_); 7 | r = r_; 8 | } 9 | 10 | void render(){ 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /processingBlenderExport/bodyInteractions3DExport/Circle.pde: -------------------------------------------------------------------------------- 1 | class Circle extends Body { 2 | 3 | float r; 4 | 5 | Circle(PVector pos_, PVector speed_, PVector accln_, float mass_, float r_){ 6 | super(pos_, speed_, accln_, mass_); 7 | r = r_; 8 | } 9 | 10 | void render(){ 11 | noStroke(); 12 | fill(100); 13 | pushMatrix(); 14 | translate(pos.x,pos.y,t); 15 | sphere(r); 16 | popMatrix(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /processingBlenderExport/bodyInteractions3DExport/bodyInteractions3DExport.pde: -------------------------------------------------------------------------------- 1 | // Particle system generated 3D objects, export occurs via text file 2 | 3 | System particles; 4 | float t=0; 5 | PrintWriter output; 6 | 7 | void setup() { 8 | size(500, 500, P3D); 9 | output = createWriter("temp.txt"); 10 | background(0); 11 | 12 | // initialise particle system 13 | particles = new System(); 14 | 15 | //populate with particles 16 | for (int i=0;i<100;i++) { 17 | particles.addCircle(); 18 | }; 19 | 20 | // position the camera 21 | rotateX(-PI/1.5); 22 | lights(); 23 | 24 | // for each time step update the particle system 25 | for (int i=0; i<500; i++) { 26 | particles.interact(); 27 | particles.update(); 28 | t += 1; 29 | println(i); 30 | } 31 | 32 | // write particle positions to a text file 33 | particles.writePositions(); 34 | output.flush(); 35 | output.close(); 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /processingBlenderExport/bodyInteractions3DExport/Body.pde: -------------------------------------------------------------------------------- 1 | class Body { 2 | ArrayList history; // stores particle locations 3 | PVector pos, speed, accln; 4 | float mass; 5 | float drag = 0.99; 6 | int stepSize = 5; 7 | 8 | Body(PVector pos_, PVector speed_, PVector accln_, float mass_){ 9 | pos = pos_; 10 | speed = speed_; 11 | accln = accln_; 12 | mass = mass_; 13 | 14 | // initialise the history and add the initial position 15 | history = new ArrayList(); 16 | PVector hPos = pos.get(); 17 | hPos.z = t; 18 | history.add(hPos); 19 | } 20 | 21 | void update(){ 22 | speed.add(accln); 23 | pos.add(speed); 24 | speed.mult(drag); 25 | accln.set(0,0); 26 | PVector hPos = pos.get(); 27 | hPos.z = t; 28 | history.add(hPos); 29 | } 30 | 31 | void applyForce(PVector force){ 32 | force.mult(1/mass); 33 | accln.add(force); 34 | } 35 | 36 | void changeSpeed(PVector newSpeed){ 37 | speed = newSpeed; 38 | } 39 | 40 | void render(){ 41 | } 42 | 43 | void writePositions(){ 44 | for (int ii=0; ii= 0; i-- ) { 15 | Circle p = (Circle) circles.get(i); 16 | p.update(); 17 | p.render(); 18 | } 19 | } 20 | 21 | void interact(){ 22 | // self interact circles 23 | for (int i = circles.size() - 1; i >= 0; i-- ) { 24 | for (int j = i; j >= 0; j-- ) { 25 | Circle p = (Circle) circles.get(i); 26 | Circle q = (Circle) circles.get(j); 27 | PVector temp = PVector.sub(p.pos,q.pos); 28 | PVector temp2 = temp.get(); 29 | if (temp.mag()<50+t/10 & temp.mag()>20){ 30 | float d = temp.mag(); 31 | temp.normalize(); 32 | temp.rotate(0.01); 33 | temp.mult(-(500+t)/d/d); 34 | p.applyForce(temp); 35 | temp.mult(-1); 36 | //temp.rotate(1); 37 | q.applyForce(temp); 38 | } else if (temp.mag()<10){ 39 | temp.normalize(); 40 | temp.mult(0.01); 41 | p.applyForce(temp); 42 | temp.mult(-1); 43 | q.applyForce(temp); 44 | } 45 | //temp2.sub(new PVector(width/2,height/2)); 46 | // temp2.normalize(); 47 | // temp2.mult(-0.001); 48 | // temp2.rotate(PI/2); 49 | // p.applyForce(temp2); 50 | } 51 | } 52 | } 53 | 54 | void writePositions(){ 55 | for (int i = circles.size() - 1; i >= 0; i-- ) { 56 | Circle p = (Circle) circles.get(i); 57 | p.writePositions(); 58 | output.println(' '); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /robotArtist01/robotArtist01.pde: -------------------------------------------------------------------------------- 1 | PImage target; 2 | PGraphics pg; 3 | PGraphics canvas; 4 | int errInd; 5 | float nStroke = 0; 6 | int minErr = 100000000; 7 | 8 | void setup(){ 9 | size(600,500); 10 | background(255); 11 | pg = createGraphics(width,height); 12 | canvas = createGraphics(width,height); 13 | canvas.beginDraw(); 14 | canvas.background(255); 15 | canvas.endDraw(); 16 | target = loadImage("weathered-face2.jpg"); 17 | target.resize(width, height); 18 | frameRate(120); 19 | } 20 | 21 | void draw(){ 22 | // Try some possible strokes 23 | background(255); 24 | int errInd = -1; 25 | 26 | float[] x1 = new float[100]; 27 | float[] y1 = new float[100]; 28 | float[] x2 = new float[100]; 29 | float[] y2 = new float[100]; 30 | for (int i=0; i<100; i++) { 31 | x1[i] = random(width); 32 | y1[i] = random(height); 33 | x2[i] = x1[i] + random(-10,10); 34 | y2[i] = y1[i] + random(-10,10); 35 | } 36 | 37 | canvas.loadPixels(); 38 | 39 | for (int iStroke=0; iStroke<100; iStroke++){ 40 | // copy the current canvas 41 | // pg.loadPixels(); 42 | // pg.pixels = canvas.pixels; 43 | // pg.updatePixels(); 44 | pg.copy(canvas,0,0,width,height,0,0,width,height); 45 | pg.beginDraw(); 46 | pg.stroke(noise(0,0,nStroke*iStroke),100); 47 | pg.strokeWeight(2); 48 | pg.line(x1[iStroke],y1[iStroke],x2[iStroke],y2[iStroke]); 49 | pg.endDraw(); 50 | 51 | // calculate the error 52 | int totErr = 0; 53 | pg.loadPixels(); 54 | target.loadPixels(); 55 | for (int iPix=0; iPix-1){ 71 | println(minErr); 72 | 73 | // Render to screen 74 | canvas.beginDraw(); 75 | canvas.stroke(0,100); 76 | canvas.strokeWeight(2); 77 | canvas.stroke(noise(0,0,nStroke*errInd),100); 78 | canvas.line(x1[errInd],y1[errInd],x2[errInd],y2[errInd]); 79 | } else { 80 | println("skipping"); 81 | } 82 | canvas.endDraw(); 83 | if (keyPressed){ 84 | }else{ 85 | 86 | image(canvas,0,0); 87 | } 88 | nStroke+=random(100); 89 | } 90 | -------------------------------------------------------------------------------- /robotArtist02/robotArtist02.pde: -------------------------------------------------------------------------------- 1 | PImage target; 2 | PGraphics pg; 3 | PGraphics canvas; 4 | int errInd; 5 | float nStroke = 0; 6 | int minErr = 100000000; 7 | float px = random(width); 8 | float py = random(height); 9 | int skipCount = 0; 10 | 11 | void setup(){ 12 | size(960,540); 13 | background(255); 14 | pg = createGraphics(width,height); 15 | canvas = createGraphics(width,height); 16 | canvas.beginDraw(); 17 | canvas.background(255); 18 | canvas.endDraw(); 19 | target = loadImage("tokyo.jpg"); 20 | target.resize(width, height); 21 | frameRate(120); 22 | px = random(width); 23 | py = random(height); 24 | } 25 | 26 | void draw(){ 27 | // Try some possible strokes 28 | background(255); 29 | int errInd = -1; 30 | int nAng = 30; 31 | 32 | // float[] x1 = new float[100]; 33 | // float[] y1 = new float[100]; 34 | // float[] x2 = new float[100]; 35 | // float[] y2 = new float[100]; 36 | // for (int i=0; i<100; i++) { 37 | // x1[i] = random(width); 38 | // y1[i] = random(height); 39 | // x2[i] = x1[i] + random(-10,10); 40 | // y2[i] = y1[i] + random(-10,10); 41 | // } 42 | 43 | canvas.loadPixels(); 44 | 45 | for (int iStroke=0; iStroke-1){ 80 | println(minErr); 81 | 82 | // Render to screen 83 | canvas.beginDraw(); 84 | canvas.stroke(0,100); 85 | canvas.strokeWeight(2); 86 | canvas.stroke(noise(0,0,nStroke*errInd),100); 87 | float step = 5; 88 | float nx = px + step*cos(TWO_PI*errInd/nAng); 89 | float ny = py + step*sin(TWO_PI*errInd/nAng); 90 | canvas.line(px, py,nx,ny); 91 | px = nx; 92 | py = ny; 93 | } else { 94 | println("skipping"); 95 | skipCount++; 96 | } 97 | canvas.endDraw(); 98 | 99 | if (skipCount > 5){ 100 | px = random(width); 101 | py = random(height); 102 | skipCount = 0; 103 | } 104 | if (keyPressed){ 105 | }else{ 106 | 107 | image(canvas,0,0); 108 | } 109 | nStroke+=random(100); 110 | } 111 | -------------------------------------------------------------------------------- /colourHoughBlog/colourHough01.pde: -------------------------------------------------------------------------------- 1 | // Hough transform, but transfrom to mean colour rather than number of votes 2 | PImage photo; // photo to be transformed 3 | int rMax; 4 | int nSamples = 100; 5 | 6 | void setup(){ 7 | size(800,500); 8 | background(255); 9 | 10 | // load the image 11 | photo = loadImage("imageFileName.jpg"); 12 | 13 | // calculate the maximum radius needed 14 | rMax = ceil(sqrt(photo.width*photo.width + photo.height*photo.height)); 15 | 16 | // loop over r and theta 17 | for (int xPix=0;xPix 0 && x0 < photo.width){x[count] = x0; y[count] = 0; count++;} 39 | if (xMax > 0 && xMax < photo.width){x[count] = xMax; y[count] = photo.height; count++;} 40 | if (y0 > 0 && y0 < photo.height){x[count] = 0; y[count] = y0; count++;} 41 | if (yMax > 0 && yMax < photo.height){x[count] = photo.width; y[count] = yMax; count++;} 42 | 43 | // sample along the line 44 | color[] sampledCols = new color[nSamples]; 45 | for (int iSample=0; iSample0 && xCur 0 && yCur 0) { 69 | // check the min diff for each available space 70 | int bestj = 0; 71 | float bestDiff = 500000; 72 | for (int j=0; j>16 & 0xFF) + (check>>8 & 0xFF) + (check & 0xFF) == 0){ 102 | // and the cell isn't in the list already 103 | Boolean ok = true; 104 | for (int jj=0; jj>16 & 0xFF) - (c2>>16 & 0xFF); 145 | // float g = (c1>>8 & 0xFF) - (c2>>8 & 0xFF); 146 | // float b = (c1 & 0xFF) - (c2 & 0xFF); 147 | result = r*r + g*g + b*b; 148 | } 149 | else { 150 | float h = hue(c1) - hue(c2); 151 | float s = saturation(c1) - saturation(c2); 152 | float b = brightness(c1) - brightness(c2); 153 | result = h*h + s*s + b*b; 154 | } 155 | return result; 156 | } 157 | 158 | // gets the neighbors (3..8) of the given coordinate 159 | ArrayList getneighbours(PVector xy) { 160 | ArrayList ret = new ArrayList(); 161 | for (int dy = -1; dy <= 1; dy++) { 162 | if (xy.y + dy == -1 || xy.y + dy == height) { 163 | continue; 164 | } 165 | for (int dx = -1; dx <= 1; dx++) { 166 | if (xy.x + dx == -1 || xy.x + dx == width || (dx==0 && dy==0) ) { 167 | continue; 168 | } 169 | ret.add(new PVector(xy.x + dx, xy.y + dy)); 170 | } 171 | } 172 | return ret; 173 | } 174 | 175 | // calculates how well a color fits at a given coordinate 176 | float calcdiff(PVector xy, color c) { 177 | // get the diffs for each neighbor separately 178 | FloatList diffs = new FloatList(); 179 | ArrayList neighbours = getneighbours(xy); 180 | for (int i=0;i