• fullscreen
  • cFigure.pde
  • cShape.pde
  • pentaSpinner.pde
  • /**
      * cFigure
      * a collection of cShapes 
      * Square Crow, June 2010
      */
      
    /**
      LOG
      ===
      
      TO DO
      =====
    
      */
      
    class cFigure{
      float cenX; float cenY; // center of the figure
      float bearingAbs; // facing direction in rad, 0 == UP
      cShape[] pieces; // shapes in the collection
      float[][] template; // [vertexNumber][{dX, dY, radius, angle}]
      float[][] vertices; // last stored position
      float[] bearingRel;
      int index = 0; // for manual init of points
      
      cFigure(int numShapes, float iX, float iY){
        // contructor for manual init of shapes
        template = new float[numShapes][4];
        vertices = new float[numShapes][2];
        pieces = new cShape[numShapes];
        bearingRel = new float[numShapes];
        cenX = iX; cenY = iY;
        bearingAbs = 0;
      }
      
      void add_cShape(float dX, float dY, cShape cshpRef, float relBearing){
        if(index < template.length){
          template[index][0] = dX; template[index][1] = dY;
          // relative pos expressed as a vector
          template[index][2] = sqrt(pow(dX,2) + pow(dY,2)); // calc radius
          pieces[index] = cshpRef;
          bearingRel[index] = relBearing;
          float quadrant_offset = 0;
          float raw = atan(-dX/dY);
          if(dX > 0 && dY > 0){quadrant_offset = -PI;} else
          if(dX < 0 && dY > 0){quadrant_offset = PI;}
          template[index][3] = raw + quadrant_offset; // calc theta
          index++;
        } else {println("cFigure.add_cShape: attepted to add too many vertices!");}
      }
      
      void add_cShape_with_vector(float radius, float theta, cShape cshpRef, float relBearing){
        // In the case that it is easier to express vertices as a vertex from the center
        if(index < template.length){
          pieces[index] = cshpRef;
          bearingRel[index] = relBearing;
          template[index][0] = -1; template[index][1] = -1; //never used again
          // relative pos expressed as a vector
          template[index][2] = radius; 
          template[index][3] = theta;
          index++;
        } else {println("cShape.add_vertex_as_vector: attepted to add too many vertices!");}
      }
      
      void make_penta_pinwheel(float radius, float cWidth, float cHeight){
        // helper function makes a five-bladed pinwheel with rectangular blades
        // You must first instantiate a cFigure with 5 pieces
        cShape temp;
        for(int i = 0; i < 5; i++){
          temp = new cShape(4,0.0,0.0);
          temp.make_rect(cWidth,cHeight);
          add_cShape_with_vector(radius + cHeight/2.0, i*TWO_PI/5, temp, i*TWO_PI/5);
        }
      }
      
      float normalize_2PI(float raw){
        // Normalize bearing to range 0 - 2*PI
        float rtnBearing = 0;
        if(raw < 0){
          rtnBearing = 2*PI + raw;
        }else if(raw > 2*PI){
          rtnBearing = raw - 2*PI;
        }else{rtnBearing = raw;}
        return rtnBearing;
      }
      
      void set_bearing(float newTheta){
        // set bearing to a specified angle
        bearingAbs = normalize_2PI(newTheta);
        //calc_points();
      }
      
      void change_bearing(float dTheta){
        // change bearing by a specified amount
        bearingAbs = normalize_2PI(bearingAbs + dTheta);
        //calc_points();
      }
      
      void set_center(float iX, float iY){
        // set the absolute position of figure center
        cenX = iX; cenY = iY;
        calc_points();
      }
      
      void move(float dX, float dY){
        // move the figure center by a specified amount
        cenX += dX;
        cenY += dY;
      }
      
      void move_vector(float distance){
        // move the figure center in direction of bearing by amount
        cenX += distance * sin(bearingAbs);
        cenY += distance * cos(bearingAbs) * -1;
      }
      
      void calc_points(){
        // calculate and store absolute position of points in the shape
        for(int i = 0; i < template.length; i++){
          vertices[i][0] = cenX + template[i][2] * sin(bearingAbs+template[i][3]);
          vertices[i][1] = cenY + template[i][2] * cos(bearingAbs+template[i][3]) * -1;
        }
      }
      
      void set_color(int inColor){
        // Set the color for all cShapes in the cFigure
        // Note that it is possible to set the color of shapes individually
        for(int i = 0; i < template.length; i++){
          pieces[i].set_color(inColor);
          // Note that it is possible to set the color of shapes individually
        }
      }
      
      void paint(){
        calc_points();
        for(int i = 0; i < template.length; i++){ 
          // place cShapes and then paint each one
          pieces[i].set_center(vertices[i][0],vertices[i][1]);
          pieces[i].set_bearing(normalize_2PI(bearingAbs + bearingRel[i]));
          pieces[i].paint();
        }
      }
      
    }
    
    /**
      * cShape
      * custom shape class for use with sketches
      * Square Crow, June 2010
      */
    
    /**
      LOG
      ===
      2010-06-13: wrote normalize_2PI for DRY principle
      2010-06-13: wrote helper function make_rect() to simplify creating rectangles
      
      TO DO
      =====
      * Add ability to make curves in the figure
      * Add ability to scale a figure
      */
      
    // Special Shape Types
    public static int RECT = -1;
    
    class cShape{
      float cenX; float cenY; // center of the shape
      float bearing; // facing direction in rad, 0 == UP
      float[][] template; // [vertexNumber][{dX, dY, radius, angle}]
      float[][] vertices; // last stored position
      int index = 0; // for manual init of points
      int shapeColor = 255;
      
      cShape(int numPoints, float iX, float iY){
        // contructor for manual init of points
        template = new float[numPoints][4];
        vertices = new float[numPoints][2];
        cenX = iX; cenY = iY;
        bearing = 0;
      }
      
      void make_rect(float iWidth, float iHeight){
        // helper function makes rectangle iWidth by iHeight
        // You must first instantiate a cShape with 4 points
        add_vertex(-iWidth/2, -iHeight/2);
        add_vertex(iWidth/2, -iHeight/2);
        add_vertex(iWidth/2, iHeight/2);
        add_vertex(-iWidth/2, iHeight/2);
      }
      
      void add_vertex(float dX, float dY){
        if(index < template.length){
          template[index][0] = dX; template[index][1] = dY;
          // relative pos expressed as a vector
          template[index][2] = sqrt(pow(dX,2) + pow(dY,2)); // calc radius
          float quadrant_offset = 0;
          float raw = atan(-dX/dY);
          if(dX > 0 && dY > 0){quadrant_offset = -PI;} else
          if(dX < 0 && dY > 0){quadrant_offset = PI;}
          template[index][3] = raw + quadrant_offset; // calc theta
          index++;
        } else {println("cShape.add_vertex: attepted to add too many vertices!");}
      }
      
      void add_vertex_as_vector(float radius, float theta){
        // In the case that it is easier to express vertices as a vertex from the center
        if(index < template.length){
          template[index][0] = -1; template[index][1] = -1; //never used again
          // relative pos expressed as a vector
          template[index][2] = radius; 
          template[index][3] = theta;
          index++;
        } else {println("cShape.add_vertex_as_vector: attepted to add too many vertices!");}
      }
      
      void calc_points(){
        // calculate and store absolute position of points in the shape
        for(int i = 0; i < template.length; i++){
          vertices[i][0] = cenX + template[i][2] * sin(bearing+template[i][3]);
          vertices[i][1] = cenY + template[i][2] * cos(bearing+template[i][3]) * -1;
        }
      }
      
      void set_bearing(float newTheta){
        // set bearing to a specified angle
        bearing = normalize_2PI(newTheta);
        //calc_points();
      }
      
      void change_bearing(float dTheta){
        // change bearing by a specified amount
        bearing = normalize_2PI(bearing + dTheta);
        //calc_points();
      }
      
      void set_center(float iX, float iY){
        // set the absolute position of figure center
        cenX = iX; cenY = iY;
        calc_points();
      }
      
      void move(float dX, float dY){
        // move the figure center by a specified amount
        cenX += dX;
        cenY += dY;
      }
      
      void move_vector(float distance){
        // move the figure center in direction of bearing by amount
        cenX += distance * sin(bearing);
        cenY += distance * cos(bearing) * -1;
      }
      
      float normalize_2PI(float raw){
        // Normalize bearing to range 0 - 2*PI
        float rtnBearing = 0;
        if(raw < 0){
          rtnBearing = 2*PI + raw;
        }else if(raw > 2*PI){
          rtnBearing = raw - 2*PI;
        }else{rtnBearing = raw;}
        return rtnBearing;
      }
      
      void set_color(int inColor){
        shapeColor = inColor;
      }
      
      void paint(){
        calc_points(); // calculate any transformations made this frame
        fill(shapeColor);
        beginShape();
        for(int i = 0; i < template.length; i++){
          vertex(vertices[i][0],vertices[i][1]);
          //println(str(vertices[i][0]) + " , " + str(vertices[i][1]));
        }
        vertex(vertices[0][0],vertices[0][1]); // close the loop
        endShape();
        //println(template.length);
      }
    }
    
    /**
      * pentaSpinner
      * spinning stars move about the screen
      * Square Crow, June 2010
      */
      
    /**
      LOG
      ===
      2010-06-13: wrote cShape class as a workaround to the way Processing
                  handles rotations and translations, instead operating on
                  a shape-by-shape basis.  This class should be widely 
                  applicable to other sketches
      2010-06-27: wrote cFigure class to manipulate groups of cShapes as a unit
      
      TO DO
      =====
      * write a function to move pinwheels around in their orbits
      */
      
    // * Globals *
    int WINWIDTH = 400;  // = 400;
    int WINHEIGHT = 400; // = 400;
    
    
    // * Definitions *
    
    float normalize_2PI(float raw){
      // Normalize bearing to range 0 - 2*PI
      float rtnBearing = 0;
      if(raw < 0){
        rtnBearing = 2*PI + raw;
      }else if(raw > 2*PI){
        rtnBearing = raw - 2*PI;
      }else{rtnBearing = raw;}
      return rtnBearing;
    }
    
    void orbit_pinwheel(){
      for(int i = 0; i < 5; i++){
        //coords[cFigure][{radius, bearing, turn_rate, orbit_rate, center_x, center_y}]
        Pinwheels[i].change_bearing(coords[i][2]);
        if(i > 0){
          coords[i][1] = normalize_2PI(coords[i][1] + coords[i][3]);
          Pinwheels[i].set_center(coords[i][4] + coords[i][0] * sin(coords[i][1]), 
                                  coords[i][5] + coords[i][0] * cos(coords[i][1]) * -1);
        }
        Pinwheels[i].paint();
      }
    }
    
    // * Setup *
    //cShape dfFigure;
    //cFigure Assembly;
    //cShape square1;
    //cShape square2;
    //cShape square3;
    //cFigure Spinner;
    
    cFigure[] Pinwheels;
    float[][] coords;
    
    void setup(){
      size(WINWIDTH,WINHEIGHT);
      noStroke(); // no outlines
      //smooth(); //remove for faster performance
      frameRate(30);
      //noLoop(); // used only for static pictures
      rectMode(CENTER);
      float rad;
    //  dfFigure = new cShape(4,200.0,100.0); // quadrilateral cShape
    //  dfFigure.make_rect(40,40);
    //  Assembly = new cFigure(3,200.0,200.0);
    //  square1 = new cShape(4, 0.0, 0.0);
    //  square1.make_rect(40,40);
    //  square2 = new cShape(4, 0.0, 0.0);
    //  square2.make_rect(40,40);
    //  square3 = new cShape(4, 0.0, 0.0);
    //  square3.make_rect(40,40);
    //  Assembly.add_cShape(-30.0, -30.0, square1, 1*PI/16);
    //  Assembly.add_cShape(30.0, -30.0, square2, 2*PI/16);
    //  Assembly.add_cShape(-30.0, 30.0, square3, 3*PI/16);
    //  Spinner = new cFigure(5,200.0,200.0);
    //  rad = 100.0;
    //  Spinner.make_penta_pinwheel(rad, 2.0*rad*cos(TWO_PI/10.0), 2.5*rad);
      coords = new float[5][6]; // orbit all but the largest pinwheel
      //coords[cFigure][{radius, bearing, turn_rate, orbit_rate, center_x, center_y}]
      Pinwheels = new cFigure[5];
      float baseTurnRate = PI/50;
      for(int i = 5; i > 0; i--){
        Pinwheels[5 - i] = new cFigure(5, 200.0, 200.0 - (5 - i) * 20.0);
        //coords[cFigure][{radius, bearing, turn_rate, orbit_rate, center_x, center_y}]
        coords[5 - i] = new float[] {(5 - i) * 20.0, i*TWO_PI/5, (1-2*(i%2))*baseTurnRate, -(1-2*(i%2))*baseTurnRate, 200.0, 200.0};
        rad = 100.0 * i/5;
        Pinwheels[5 - i].make_penta_pinwheel(rad, 2.0*rad*cos(TWO_PI/10.0), 2.5*rad);
        Pinwheels[5 - i].set_color(255 * (i%2)); // alternate black and white
      }
    }
    
    // * Main Loop *
    
    void draw(){
      background(0); // repaint background, for animation
      //translate(width/2, height/2);
      //translate(100, 100);
      //rotate(PI/3.0);
      //rect(100, 100, 55, 55);
    //  dfFigure.change_bearing(PI/15);
    //  dfFigure.paint();
    //  Assembly.change_bearing(PI/30);
    //  Assembly.paint();
      orbit_pinwheel();
    //  Pinwheels[0].change_bearing(PI/30);
    //  Pinwheels[0].paint();
    }
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    Square Crow

    Penta-Spinner

    Add to Faves Me Likey@! 1
    You must login/register to add this sketch to your favorites.

    An animation of spinning pinwheels.

    I wrote some classes to help me manage moving shapes and groups of shapes, being frustrated with the way that transforms "stack". About halfway through I realized that this frustration probably comes from a lack of knowledge on how to use those functions properly, but I forged ahead with my own methods anyway.

    I expect to re-write this in a sane way.

    You need to login/register to comment.