Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

Fractal Painter (GPraphics)

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
    }
  }
}