18. November 2010
In this patch, the user can select a white field/frame to paint in. By clicking on the create button and trying different slider settings, the fractal image size is each time generated differently. All images are deleted by pressing the reset button. Remark: Due to time constraint, the left frame was supposed to be a preview of the created fractal. then with a push button, the user could paint his selected fractal in the chosen field. This is therefore not implemented. Sliders/Buttons were implemented from here The Fractal generator from here PS: There is also an mouse-over-triangle detection class not shown (but which is in the source code zip file). fractalPainting - source code GUI:/* ---------------------------------------------------------------------------- * codingSpace - 19 * ---------------------------------------------------------------------------- * fractal painter * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * ---------------------------------------------------------------------------- * 13.11.2010 */ PGraphics[] pg; PGraphics main; final int OFFSET = 300; final int OFFSET_MAIN = 100; final int QUADRANT =300; boolean drawMainPg = false; boolean drawMainOnce = true; boolean resetFlag = false; int QuadrantSelected; int fieldId=0; String radiusText, ellipseText; int mX; int mY; Field[] field; Button start, reset; Slider radius, ellipseRadius; Fractal fractal; float radiusFloat, ellipseFloat; void setup() //initialize { size(1200, 900); pg = new PGraphics[9]; QuadrantSelected = 0; field = new Field[9]; start = new Button(60, 300, 45, 20, "create"); reset = new Button(160, 300, 40, 20, "reset"); radius = new Slider(60,350,100,40,.5); ellipseRadius = new Slider(110, 350, 100, 40,0.5); radiusText = ""; ellipseText = ""; radiusFloat = 5; ellipseFloat = 8; for(int i=0; i<9; i++) { pg[i] = createGraphics((height/3),(height/3),JAVA2D); pg[i].beginDraw(); pg[i].fill(255, 255, 255, 255); pg[i].noStroke(); pg[i].rect(0,0, pg[i].width, pg[i].height); pg[i].endDraw(); } //inizialize the 9 pgraphics fields int j = 0; for(int i=0; i<3; i++) { for(int k=0; k<3; k++) { field[j]= new Field(OFFSET+(QUADRANT*i), k*QUADRANT, QUADRANT, j); j++; } } main = pg[fieldId]; } void draw() { background(0, 0, 0, 0); pushMatrix(); scale(0.70); translate(60,50); image(main, 0, 0); popMatrix(); //draw the 9 pgraphics field int j = 0; for(int i=0; i<3; i++) { for(int k=0; k<3; k++) { image(pg[j], OFFSET+(i*QUADRANT), k*QUADRANT); field[j].draw(); field[j].mouseOver(mouseX,mouseY); j++; } } //start button start.draw(); start.mouseOver(mouseX,mouseY); reset.draw(); reset.mouseOver(mouseX,mouseY); //radius of spiral slider radius.draw(); radius.mouseOver(mouseX, mouseY); text(radiusText, 70, 480); //ellipse (circle) radius slider ellipseRadius.draw(); ellipseRadius.mouseOver(mouseX, mouseY); text(ellipseText, 130, 480); //draw my (chosen) fractal in main window (draw flag is set in the mousePressed method) if(drawMainPg) { main = pg[fieldId]; fractal = new Fractal(main, radiusFloat, ellipseFloat); fractal.draw(); drawMainPg = false; } if(resetFlag) { int j2 = 0; for(int i=0; i<3; i++) { for(int k=0; k<3; k++) { pg[j2].beginDraw(); pg[j2].background(255); pg[j2].endDraw(); main.beginDraw(); main.background(255); main.endDraw(); j2++ ; } } resetFlag = false; } } void mousePressed() { start.mousePress(mouseX, mouseY); //start button 'pressed' reset.mousePress(mouseX, mouseY); //reset button 'pressed' radius.mousePos(mouseX,mouseY,true); ellipseRadius.mousePos(mouseX,mouseY,true); //do not turn red glow-around-field when button or sliders are pressed if(!start.isHit(mouseX, mouseY) && !radius.isHit(mouseX, mouseY) && !ellipseRadius.isHit(mouseX, mouseY) && !reset.isHit(mouseX, mouseY)) { for (int i=0; i<9; i++) field[i].setPressed(false); //if another field is pressed, deactivate the last red glow //check which field has been pressed and save field id for(int i=0; i<9; i++) { if(field[i].isHit(mouseX, mouseY)) { fieldId = field[i].mousePress(mouseX, mouseY); println("field id: "+fieldId); } } } //set draw flag to true when start is hit (field id is by then known) if(start.isHit(mouseX, mouseY)) { println("start id: "+fieldId +" " +radiusFloat +" " +ellipseFloat); drawMainPg = true; } //reset all fields if(reset.isHit(mouseX, mouseY)) { println("reset"); resetFlag = true; } } void mouseReleased() { } void mouseMoved() { } void mouseDragged() { radius.mousePos(mouseX,mouseY,true); radiusText = Float.toString(5+(radius.pos()*40.0)); radiusFloat = 5+(radius.pos()*40.0); ellipseRadius.mousePos(mouseX,mouseY,true); ellipseText = Float.toString(8+(ellipseRadius.pos()*128.0)); ellipseFloat = 8+(ellipseRadius.pos()*128.0); }Buton class:
/* ---------------------------------------------------------------------------- * codingSpace18 * ---------------------------------------------------------------------------- * Button * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * 13.11.2010 * ---------------------------------------------------------------------------- */ class Button { int x; int y; int w; int h; String txt; Button(int x,int y, int w, int h, String txt) { this.x = x; this.y = y; this.w = w; this.h = h; this.txt = txt; } boolean isHit(int x,int y) { if(x > this.x && x < this.x+this.w && y > this.y && y < this.y+this.h) { return true; } else { return false; } } void draw() { pushStyle(); drawButton(); popStyle(); } void drawButton() { fill(200, 200, 200); stroke(200, 50, 10); rect(x, y, w, h); fill(255, 255, 255); noStroke(); rect(this.x+2, this.y+2, this.w-4, this.h-4); fill(200, 50, 10); text(this.txt, this.x+7, this.y, this.w, this.h); } void mouseOver(int x, int y) { if(isHit(x,y)) { pushStyle(); noFill(); strokeWeight(2); stroke(255, 0, 0,255); rect(this.x-1, this.y-1, this.w+3, this.h+3); //text(this.txt, this.x+7, this.y, this.w, this.h); popStyle(); } } void mousePress(int x, int y) { if(isHit(x,y)) { pushStyle(); noFill(); rect(this.x-2, this.y-2, this.w+4, this.h+4); stroke(255); text(this.txt, this.x+7, this.y, this.w, this.h); popStyle(); } } }field class:
/* ---------------------------------------------------------------------------- * codingSpace18 * ---------------------------------------------------------------------------- * GUI - Slider * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * 13.11.2010 * ---------------------------------------------------------------------------- */ class Field { int x; int y; int dimX; int dimY; int dim; int id; boolean pressed; Field(int x,int y,int dim, int id) { this.x = x; this.y = y; this.dim = dim; this.dimX = x+dim; this.dimY = y+dim; this.id = id; this.pressed = false; } int getId(){ return id; } void setPressed(boolean state){ this.pressed = state; } boolean isHit(int x,int y) { if(x > this.x && x < dimX && y > this.y && y < dimY) { return true; } else { return false; } } void draw() { pushStyle(); if(pressed){ float al=100; al-= (millis()%1000/10.0); stroke(255, 0, 0,al); rect(this.x, this.y, dim, dim); } else drawField(); popStyle(); } void drawField() { noFill(); noStroke(); rect(x, y, dim, dim); } void mouseOver(int x, int y) { if(isHit(x,y)) { strokeWeight(2); stroke(255, 0, 0,180); noFill(); rect(this.x, this.y, dim, dim); } } int mousePress( int x, int y){ if(isHit(x,y)){ setPressed(true); return id; } return 9; } }slider class:
/* ---------------------------------------------------------------------------- * codingSpace18 * ---------------------------------------------------------------------------- * GUI - Slider * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * 13.11.2010 * ---------------------------------------------------------------------------- */ class Slider { PVector _p1; PVector _p2; float[] _a = new float[4]; int _w; int _h; float _pos; Slider(int x,int y,int h,int w,float pos) { _p1 = new PVector(x + w * 0.5, y); _p2 = new PVector(x + w *.5, y + h); _w = w; _h = h; _pos = pos; if(_pos > 1.0) _pos = 1.0; else if(_pos < 0.0) _pos = 0.0; } float pos() { return _pos; } //fill color void fillColor(float c1, float c2, float c3, float a) { _a[0] = c1; _a[1] = c2; _a[2] = c3; _a[3] = a; } boolean isHit(int x,int y) { if(x > _p1.x - 20 && x < _p1.x + 20 && y > _p1.y && y < _p2.y) { return true; } else { return false; } } void draw() { pushStyle(); drawSlider(); drawKnob(); popStyle(); } void drawSlider() { noFill(); stroke(255, 255,255, 255); smooth(); strokeWeight(2); bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/10.0), _p1.y + (_h/8.0), _p2.x-(_w/10.0), _p2.y-(_h/8.0), _p2.x-(_w/2.0), _p2.y); //left side bezier(_p1.x+(_w/2.0), _p1.y, _p1.x+(_w/10.0), _p1.y + (_h/8.0), _p2.x +(_w/10.0), _p2.y-(_h/8.0), _p2.x+(_w/2.0), _p2.y); //right side bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/2.0), _p1.y); //top bezier(_p2.x-(_w/2.0), _p2.y, _p2.x-(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/2.0), _p2.y); //bottom } void drawKnob() { stroke(255, 255,255, 255); PVector dir = PVector.sub(_p2,_p1); PVector pos = PVector.add( _p1, PVector.mult(dir,_pos)); noFill(); float bezier1= pos.x-(_w/10.0); float bezier2= pos.x+(_w/10.0); float bezier3= pos.x-(_w/10.0); float bezier4= pos.x+(_w/10.0); float bezier5= pos.y+(_h/20.0); float bezier6= pos.y-(_h/20.0); if(_pos >= 0.6) { bezier1 = map(_pos, 0.5, 1.0, pos.x-(_w/10.0), pos.x-(_w/3.0) ); //change bottom left side bezier2 = map(_pos, 0.5, 1.0, pos.x+(_w/10.0), pos.x+(_w/3.0) ); //change bottom right side bezier6 = map(_pos, 0.6, 0.0, pos.y+(_h/10.0), pos.y+(_h/3.0) ); //expand top middle } else bezier6= pos.y-(_h/20.0); if(_pos <= 0.6) { bezier3 = map(_pos, 0.5, 0.0, pos.x-(_w/10.0), pos.x-(_w/3.0)); //top left side bezier4 = map(_pos, 0.5, 0.0, pos.x+(_w/10.0), pos.x+(_w/3.0)); ///top right side bezier5 = map(_pos, 0.6, 1.0, pos.y-(_h/50.0), pos.y-(_h/3.0) ); //expand bottom middle } else bezier5= pos.y+(_h/20.0); rect(pos.x-3, pos.y-2, 6, 4); bezier(bezier3, pos.y-4, pos.x-(_w/15.0), bezier6, pos.x+(_w/15.0), bezier6, bezier4, pos.y-4); //top arc bezier(bezier1, pos.y+4, pos.x-(_w/15.0), bezier5, pos.x+(_w/15.0),bezier5, bezier2, pos.y+4); //bottom arc bezier(bezier3, pos.y-4, pos.x-(_w/10.0), pos.y-2, pos.x-(_w/10.0), pos.y+2, bezier1, pos.y+4); //left side arc bezier(bezier4, pos.y-4, pos.x+(_w/10.0), pos.y-2, pos.x+(_w/10.0), pos.y+2, bezier2, pos.y+4); //right side arc } void mousePos(int x,int y,boolean pressed) { if(pressed) { if(isHit(x,y)) { // move knob PVector dir = PVector.sub(_p1, _p2); //laenge der 2 punkte bestimmen _pos = 1.0 / dir.mag() * (y-_p1.y); //mapping im zahlenbereich (laenge in scalar) . mag (magnitude) berechnet die laenge in scalar (eine zahl) } } else { // mouse over } } void mouseOver(int x, int y) { if(isHit(x,y)) { pushStyle(); noFill(); int t = 10; strokeWeight(t ); //fade float al=100; al-= (millis()%1000/10.0); stroke(255, 255, 255, 100); //as drawn at the beginning (can be different) bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/10.0), _p1.y + (_h/8.0), _p2.x-(_w/10.0), _p2.y-(_h/8.0), _p2.x-(_w/2.0), _p2.y); //left side bezier(_p1.x+(_w/2.0), _p1.y, _p1.x+(_w/10.0), _p1.y + (_h/8.0), _p2.x +(_w/10.0), _p2.y-(_h/8.0), _p2.x+(_w/2.0), _p2.y); //right side bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/2.0), _p1.y); //top bezier(_p2.x-(_w/2.0), _p2.y, _p2.x-(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/2.0), _p2.y); //bottom popStyle(); } } }fractal class:
/* ---------------------------------------------------------------------------- * codingSpace - 19 * ---------------------------------------------------------------------------- * fractals * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * ---------------------------------------------------------------------------- * 09.11.2010 */ class Fractal { PGraphics pg; float radius; float eR; Fractal(PGraphics pg, float r, float eR) { this.pg = pg; this.radius = r; this.eR = eR; } void draw() { randomSeed(millis()); // seed random this.pg.beginDraw(); pushStyle(); this.pg.smooth(); // aktiviere antialiasing this.pg.strokeWeight(5); // linienbreite this.pg.pushMatrix(); this.pg.translate(this.pg.width *.5, this.pg.height -20); this.pg.stroke(2); wurzel(7); //this.pg.line(0,0, this.pg.width, this.pg.height); this.pg.popMatrix(); popStyle(); this.pg.endDraw(); } // funktion void wurzel(int tiefe) { int depth= 50; if(tiefe <=0) // teste ob das ende erreicht worden ist { // zeichen blueten pushStyle(); int clr = (int)random(100,255); figure(true, depth, 0.0, 0.0); popStyle(); return; } // zeichne zweige int x; int y; int count = (int)random(1,2); //tiefe for(int i = 0; i < count;i++) { x = (int)random(-100,100); y = -(int)random(10,150); this.pg.noFill(); //line(0,0,x,y); this.pg.pushMatrix(); this.pg.translate(x,y); this.pg.scale(random(.3,.95)); wurzel(tiefe-1); this.pg.popMatrix(); } } //parameter: [ellipse or line], [rekursiv deepnes], [start of older x & y value (needed for recursion)] void figure(boolean select, float depth, float x_old, float y_old) { float x=0; float y=0; float r = 0; //radius for(float theta=0; theta<50; theta+=0.1) { //incement angle r=theta*this.radius; //increase radius (multiplicator can be changed to in-/decrease spiral size) // Polar to Cartesian conversion x = (r * cos(theta)); //calculate x coordinate from radius r and angle y = (r * sin(theta)); //calculate x coordinate from radius r and angle if(select) { //true: then ellipse this.pg.ellipse(x, y, this.eR, this.eR); } else { //false: then point this.pg.point(x,y); } } //recursion if(depth>0) { rotate(PI/4.0); figure(false, depth-=1, depth*40.0*cos(depth),depth*40.0*sin(depth)); //recursive call } } }