Converting Java code to Python for Dataviz

edited January 2016 in Python Mode

Hi, I'm currently reading the book "Getting Started with Processing" without using Java but Python instead and I'm trying to figure how to convert this piece of code into Python.

    Table stats;

    void setup() {
      stats = loadTable("ortiz.csv");
      for (int i = 0; i < stats.getRowCount(); i++) {
        // Gets an integer from row i, column 0 in the file
        int year = stats.getInt(i, 0);
        // Gets the integer from row i, column 1
        int homeRuns = stats.getInt(i, 1);   
        int rbi = stats.getInt(i, 2); 
        // Read a number that includes decimal points
        float average = stats.getFloat(i, 3); 
        println(year, homeRuns, rbi, average);
      }
    }

I've tried a way with importing the csv module and playing with that but I'm not sure that it's the same way as the book deal with.

Any help would be very appreciated! (Sorry for my skilless english) Thanks!

Answers

  • edited December 2015 Answer ✓

    I've tried a way with importing the csv module...

    Disclaimer: I just know Python by quick glances. Almost none! ~O)

    "Python Mode" is implemented in Jython: https://en.Wikipedia.org/wiki/Jython
    And it has full access to Java libraries + Processing framework: http://py.Processing.org/
    Therefore there's no need to look for Python libraries which are already present in "Python Mode".

    Even barely knowing any Python I was able to convert your "Java Mode" sketch to "Python Mode": :>

    # forum.Processing.org/two/discussion/14071/
    # converting-java-code-to-python-for-dataviz
    
    # 2015/Dec/18
    
    def setup():
    
        global stats
        stats = loadTable('ortiz.csv')
    
        for i in xrange(stats.getRowCount()):
    
            year = stats.getInt(i, 0)
            homeRuns = stats.getInt(i, 1)
            rbi = stats.getInt(i, 2)
            avr = stats.getFloat(i, 3)
    
            print year, homeRuns, rbi, avr
    
    
        exit()
    
  • It worked perfectly, many thanks for your help!

  • edited December 2015 Answer ✓

    A more comfy & clean way is to iterate over rows() in order to get each TableRow from Table: *-:)
    https://Processing.org/reference/Table_rows_.html
    https://Processing.org/reference/TableRow.html

    # forum.Processing.org/two/discussion/14071/
    # converting-java-code-to-python-for-dataviz
    
    # 2015/Dec/19
    
    def setup():
    
        global stats
        stats = loadTable('ortiz.csv')
    
        for row in stats.rows():
    
            year = row.getInt(0)
            homeRuns = row.getInt(1)
            rbi = row.getInt(2)
            avr = row.getFloat(3)
    
            print year, homeRuns, rbi, avr
    
    
        exit()
    
  • Yes much better way, thanks again!

  • Name Error: Pshader is not defined. while converting java code to python

    in Java: PShader sh;

    In python: sh=PShader()

  • edited February 2016

    @Prabhnith, just found out today, after converting a Java Mode sketch to Python Mode, that the latter doesn't seem to automatically import anything outside PApplet class! @-)

    https://forum.Processing.org/two/discussion/comment/61895/#Comment_61895

    And even many PApplet methods are missing as well.
    For example I had to import dataPath(): from processing.core.PApplet import dataPath
    And even worse, I had to pass this as an extra 1st argument for it to work: 3:-O
    path = dataPath(this, xml.getName() + '.xml')

    It's true dataPath() doesn't belong to the "official" Processing API.
    However I've found out that thread(""), which is listed in the API reference, got the same issue:
    https://Processing.org/reference/thread_.html

    I don't think any regular Python mode user gonna find out those import paths so easily.
    It's nowhere to be found in any regular reference. It's simply expected to just work w/o any imports! =;

    I wonder if all of that's unintended or it's an official stand for Processing.py? :|

  • edited February 2016

    @Prabhnith, I've just explained the situation but forgot to search for the solution! 8-}
    Class PShader belongs to package processing.opengl; therefore:

    from processing.opengl import PShader
    sh = PShader()
    

    Although its reference page strongly encourages loadShader() instead.
    Which in turn doesn't warrant any from ... import ... in order to be accessed at all: ;)

    https://Processing.org/reference/PShader.html
    https://Processing.org/reference/loadShader_.html

  • thankyou sir :)

  • sir in this code there is no error but it is not showing the correct output. Please review this code @GoToLoop https://github.com/jdf/processing.py/pull/183/files

    It is the converted example of the java mode. (Rotating Arcs)

  • edited May 2016

    Trying to clean up the code before attempting to convert it to Python mode: #:-S
    Watch it online: http://studio.ProcessingTogether.com/sp/pad/export/ro.9AqEIV-5Q9sCx

    /**
     * Rotating Arcs (v2.5.2)
     * by  Marius Watz
     * mod GoToLoop
     * 
     * Using sin/cos lookup tables, blends colors, and draws a series of
     * rotating arcs on the screen.
     *
     * GitHub.com/processing/processing-docs/blob/master/content/
     * examples/Demos/Graphics/RotatingArcs/RotatingArcs.pde
     *
     * forum.Processing.org/two/discussion/14071/
     * converting-java-code-to-python-for-dataviz#Item_11
     *
     * studio.ProcessingTogether.com/sp/pad/export/ro.9AqEIV-5Q9sCx
     */
    
    static final int ARC_LINES = 0, ARC_BARS = 1, ARC_SOLIDS = 2;
    static final int FPS = 60, SMOOTH = 2, NUM = 150, A = 210;
    static final float WEIGHT = 1.0, SIXTH_PI = THIRD_PI * .5;
    static final boolean ONLINE = 1/2 == 1/2.;
    
    // Trig lookup tables borrowed from Toxi; cryptic but effective.
    static final float PRECISION = 1.0, RADS = .5 * DEG_TO_RAD*PRECISION;
    static final int LENGTH = (int) (360/PRECISION), LUTS = LENGTH<<1;
    
    static final float[] COS_SIN = new float[LUTS];
    static // Comment this out for JS Mode!
    { // Fill the tables
      for (int i = 0; i < LUTS; i += 2) {
        COS_SIN[i]   = cos(RADS*i);
        COS_SIN[i+1] = sin(RADS*i);
      }
    }
    
    final float[] pt = new float[6*NUM]; // spd, rotX, rotY, deg, rad, width
    final int[] styles = new int[2*NUM]; // color, render styles
    
    int clockwise = 1;
    boolean paused;
    
    void setup() {
      size(800, 650, P3D);
      smooth(SMOOTH);
      frameRate(FPS);
      strokeWeight(WEIGHT);
      initArcShapes();
    }
    
    void draw() {
      background(0);
    
      translate(width>>1, height>>1);
      rotateX(SIXTH_PI);
      rotateY(SIXTH_PI);
    
      for (int idx = 0, i = 0; i < styles.length; idx += 6, i += 2) {
        pushMatrix();
    
        final float spd = clockwise * pt[idx]; // Rotation speed
        rotateX(pt[idx+1] += spd);
        rotateY(pt[idx+2] += spd * .5);
    
        final float deg = pt[idx+3], rad = pt[idx+4], w = pt[idx+5];
        final color c = styles[i];
    
        switch (styles[i+1]) {
        case ARC_LINES:
          stroke(c);
          noFill();
          arcLines(0, 0, deg, rad, w);
          break;
    
        case ARC_BARS:
          fill(c);
          noStroke();
          arcBars(0, 0, deg, rad, w);
          break;
    
        case ARC_SOLIDS:
          fill(c);
          noStroke();
          arcSolids(0, 0, deg, rad, w);
        }
    
        popMatrix();
      }
    
      if (!ONLINE)  frame.setTitle("FPS: " + round(frameRate));
    }
    
    void mousePressed() {
      switch (mouseButton) {
      case LEFT:
        clockwise *= -1;
        break;
    
      case RIGHT:
        if (paused ^= true)  noLoop();
        else                 loop();
        break;
    
      case CENTER:
        initArcShapes();
      }
    }
    
    // Draw arc lines:
    void arcLines(float x, float y, float deg, float rad, float w) {
      final int angs = min((int) (2.0/PRECISION*deg), LUTS-1);
      final int lines = (int) w >> 1;
    
      for (int j = 0; j < lines; rad += 2.0, ++j) {
        beginShape();
        for (int i = 0; i < angs; i += 2)
          vertex(x + rad*COS_SIN[i], y + rad*COS_SIN[i+1]);
        endShape();
      }
    }
    
    // Draw arc line with bars:
    void arcBars(float x, float y, float deg, float rad, float w) {
      final int angs = min((int) (.5/PRECISION*deg), LUTS-5);
      final float rdw = rad+w;
    
      beginShape(QUADS);
      for (int i = 0; i < angs; i += 8) {
        final float c1 = COS_SIN[i], s1 = COS_SIN[i+1];
        final float c2 = COS_SIN[i+4], s2 = COS_SIN[i+5];
    
        vertex(x + rad*c1, y + rad*s1);
        vertex(x + rdw*c1, y + rdw*s1);
        vertex(x + rdw*c2, y + rdw*s2);
        vertex(x + rad*c2, y + rad*s2);
      }
      endShape();
    }
    
    // Draw solid arc:
    void arcSolids(float x, float y, float deg, float rad, float w) {
      final int angs = min((int) (2.0/PRECISION*deg), LUTS-1);
      final float rdw = rad+w;
    
      beginShape(QUAD_STRIP);
      for (int i = 0; i < angs; i += 2) {
        final float c = COS_SIN[i], s = COS_SIN[i+1];
    
        vertex(x + rad*c, y + rad*s);
        vertex(x + rdw*c, y + rdw*s);
      }
      endShape();
    }
    
    // Get blend of two colors:
    color blendColors(float fract, 
      color r, color g, color b, 
      color rr, color gg, color bb, color a) {
    
      rr -= r;
      gg -= g;
      bb -= b;
    
      return color(r + rr*fract, g + gg*fract, b + bb*fract, a);
    }
    
    void initArcShapes() {
      for (int i = 0; i < pt.length; i += 6) { // Get spd, rotX, rotY, deg, rad, wdt:
        pt[i] = DEG_TO_RAD/50 * random(5, 30); // Speed of rotation
    
        pt[i+1] = random(TAU); // Random x axis rotation
        pt[i+2] = random(TAU); // Random Y axis rotation
    
        // Short to quarter-circle arcs:
        pt[i+3] = random(1) > .9? 10 * (int) random(8, 27) : random(60, 80);
    
        pt[i+4] = 5 * (int) random(2, 50); // Radius. (Space them out nicely)
    
        pt[i+5] = random(1) > .9? random(40, 60) : random(4, 32); // Width of band
      }
    
      for (int i = 0; i < styles.length; i += 2) { // Get colors
        final float rnd = random(1), f = random(1);
    
        if      (rnd < .3)  styles[i] = blendColors(f, 255, 0, 100, 255, 0, 0, A);
        else if (rnd < .5)  styles[i] = blendColors(f, 200, 255, 0, 50, 120, 0, A);
        else if (rnd < .7)  styles[i] = blendColors(f, 0, 153, 255, 170, 225, 255, A);
        else if (rnd < .9)  styles[i] = blendColors(f, 200, 255, 0, 150, 255, 0, A);
        else                styles[i] = 0xdcFFFFFF;
    
        styles[i+1] = (int) random(3); // Pick arc style
      }
    }
    
  • i think i should do the shorter examples first before going too further. :/

  • edited May 2016

    Finally Python Mode version is here. <:-P Although it's at least 30% slower: :o3

    """
     ' Rotating Arcs (v2.6)
     ' by  Marius Watz
     ' mod GoToLoop
     ' 
     ' Using sin/cos lookup tables, blends colors, and draws a series of
     ' rotating arcs on the screen.
     '
     ' GitHub.com/processing/processing-docs/blob/master/content/
     ' examples/Demos/Graphics/RotatingArcs/RotatingArcs.pde
     '
     ' forum.Processing.org/two/discussion/14071/
     ' converting-java-code-to-python-for-dataviz#Item_13
     '
     ' studio.ProcessingTogether.com/sp/pad/export/ro.9AqEIV-5Q9sCx
    """
    
    ARC_LINES, ARC_BARS, ARC_SOLIDS = range(3)
    FPS, SMOOTH, NUM = 60, 2, 100
    WEIGHT, SIXTH_PI = 1.0, THIRD_PI * .5
    
    PRECISION = 1.5; LENGTH = int(360//PRECISION)
    LUTS, RADS = LENGTH<<1, .5 * DEG_TO_RAD*PRECISION
    
    COS_SIN = tuple(sin(RADS*(i-1)) if i&1 else cos(RADS*i) for i in range(LUTS))
    
    # spd, rotX, rotY, deg, rad, width
    # color, render styles
    pt, styles = 6*NUM * [0.0], 2*NUM * [0]
    
    #from jarray import zeros
    #pt, styles = zeros(6*NUM, 'f'), zeros(2*NUM, 'i')
    
    clockwise, paused = 1, False
    
    def setup():
        size(800, 650, P3D)
        smooth(SMOOTH), frameRate(FPS), strokeWeight(WEIGHT)
        initArcShapes()
    
    
    def draw(i=0, idx=0, LEN=len(styles)):
        background(0)
    
        translate(width>>1, height>>1)
        rotateX(SIXTH_PI); rotateY(SIXTH_PI)
    
        while i < LEN:
            with pushMatrix():
                spd = clockwise * pt[idx] # Rotation speed
                rx = pt[idx+1]; ry = pt[idx+2]
                pt[idx+1] += spd; pt[idx+2] += spd * .5 # Increase rotations
    
                deg = pt[idx+3]; rad = pt[idx+4]; w = pt[idx+5]
                c = styles[i]; rend = styles[i+1]
    
                rotateX(rx); rotateY(ry)
    
                if rend == ARC_LINES:
                    stroke(c); noFill(); arcLines(0, 0, deg, rad, w)
                elif rend == ARC_BARS:
                    fill(c); noStroke(); arcBars(0, 0, deg, rad, w)
                else:
                    fill(c); noStroke(); arcSolids(0, 0, deg, rad, w)
    
            idx += 6; i += 2
    
        frame.setTitle('FPS: %i' % round(frameRate))
    
    
    def mousePressed():
        global clockwise, paused
    
        if   mouseButton == LEFT: clockwise *= -1
        elif mouseButton == CENTER: initArcShapes()
        else:
            paused ^= True
            noLoop() if paused else loop()
    
    
    # Draw arc lines:
    def arcLines(x, y, deg, rad, w):
        angs = min(int(2.0/PRECISION*deg), LUTS-1)
        j = i = 0; jlen = int(w) >> 1
    
        while j < jlen:
            with beginShape():
                while i < angs:
                    vertex(x + rad*COS_SIN[i], y + rad*COS_SIN[i+1])
                    i += 2
            i = 0; j += 1; rad += 2.0
    
    
    # Draw arc line with bars:
    def arcBars(x, y, deg, rad, w):
        angs = min(int(.5/PRECISION*deg), LUTS-5); rdw = rad+w; i = 0
    
        with beginShape(QUADS):
            while i < angs:
                c1 = COS_SIN[i];   s1 = COS_SIN[i+1]
                c2 = COS_SIN[i+4]; s2 = COS_SIN[i+5]
                i += 8
    
                vertex(x + rad*c1, y + rad*s1)
                vertex(x + rdw*c1, y + rdw*s1)
                vertex(x + rdw*c2, y + rdw*s2)
                vertex(x + rad*c2, y + rad*s2)
    
    
    # Draw solid arc:
    def arcSolids(x, y, deg, rad, w):
        angs = min(int(2.0/PRECISION*deg), LUTS-1); rdw = rad+w; i = 0
    
        with beginShape(QUAD_STRIP):
            while i < angs:
                c = COS_SIN[i]; s = COS_SIN[i+1]
                i += 2
    
                vertex(x + rad*c, y + rad*s)
                vertex(x + rdw*c, y + rdw*s)
    
    
    # Get blend of two colors:
    def blendColors(fract, r, g, b, rr, gg, bb, a=0xff):
        rr -= r; gg -= g; bb -= b
        return color(r + rr*fract, g + gg*fract, b + bb*fract, a)
    
    
    def initArcShapes(PT=tuple(range(0, len(pt), 6)),
                      ST=tuple(range(0, len(styles), 2)), A=210):
        for i in PT: # Get spd, rotX, rotY, deg, rad, width:
            pt[i] = DEG_TO_RAD/50 * random(5, 30) # Speed of rotation
    
            pt[i+1], pt[i+2] = random(TAU), random(TAU) # x & y axes' rotations
    
            # Short to quarter-circle arcs:
            pt[i+3] = 10 * int(random(8, 27)) if random(1) > .9 else random(60, 80)
    
            pt[i+4] = 5 * int(random(2, 50)) # Radius. (Space them out nicely)
    
            pt[i+5] = random(40, 60) if random(1) > .9 else random(4, 32) # W of band
    
        for i in ST: # Get colors:
            rnd, f = random(1), random(1)
    
            if   rnd < .3: styles[i] = blendColors(f, 255, 0, 100, 255, 0, 0, A)
            elif rnd < .5: styles[i] = blendColors(f, 200, 255, 0, 50, 120, 0, A)
            elif rnd < .7: styles[i] = blendColors(f, 0, 153, 255, 170, 225, 255, A)
            elif rnd < .9: styles[i] = blendColors(f, 200, 255, 0, 150, 255, 0, A)
            else:          styles[i] = 0xdcFFFFFF
    
            styles[i+1] = int(random(3)) # Pick arc style
    
  • edited April 2016

    @Prabhnith, I've adapted the "Wiggling Cube" example from:
    https://GitHub.com/processing/processing-docs/blob/master/content/examples/Demos/Graphics/Wiggling/Wiggling.pde

    For your pull request here: https://GitHub.com/jdf/processing.py/pull/182
    Below Java Mode's tweaked version: :ar!

    /**
     * Wiggling Cube (v1.0)
     * by  REAS & JakubValtar
     * mod GoToLoop (2016-Mar-02)
     * 
     * Hit 'W' to start wiggling and SPACE to restore original cube.
     * 'P' pauses/resumes. '1', '2', '3' change outline's stroke weight.
     * And ENTER switches clockwise rotation.
     *
     * GitHub.com/processing/processing-docs/blob/master/content/
     * examples/Demos/Graphics/Wiggling/Wiggling.pde
     *
     * forum.Processing.org/two/discussion/14071/
     * converting-java-code-to-python-for-dataviz#Item_14
     */
    
    static final short CUBE_DIAM = 320, CUBE_RAD = CUBE_DIAM >> 1;
    static final short CIRCLE_RAD = 100, CIRCLE_RES = 40;
    static final float CIRCLE_SLICE = TAU/CIRCLE_RES;
    static final float NOISE_MAG = 1.0, WIGGLING = NOISE_MAG * .5;
    
    static final short FACES = 6, SMOOTH = 4;
    static final float FPS = 60.0, BOLD = 1.5;
    static final color FILL = 0350, OUTLINE = #FF0000;
    
    final PVector vert = new PVector();
    PShape cube;
    
    float rotCounter, rotSpd = .01;
    boolean wiggling, paused;
    
    void setup() {
      size(800, 600, P3D);
      smooth(SMOOTH);
      frameRate(FPS);
      createCube();
    }
    
    void draw() {
      background(0);
    
      translate(width>>1, height>>1);
      rotateX(rotCounter += rotSpd);
      rotateY(rotCounter);
    
      if (wiggling)  wiggleCube();
      shape(cube);
    
      frame.setTitle("FPS: " + round(frameRate)
        + "    Wiggling: " + wiggling);
    }
    
    void keyPressed() {
      final int k = keyCode;
    
      if (k == 'P')
        if (paused ^= true)  noLoop();
        else                 loop();
      else if (k == ENTER | k == RETURN)  rotSpd *= -1;
      else if (k == 'W')  wiggling ^= true;
      else if (k == ' ')  restoreCube();
      else if (k == '1')  cube.setStrokeWeight(BOLD);
      else if (k == '2')  cube.setStrokeWeight(BOLD * 3.0);
      else if (k == '3')  cube.setStrokeWeight(BOLD * 6.0);
    }
    
    void mousePressed() {
      final int m = mouseButton;
    
      if (m == CENTER) {
        if (!(wiggling ^= true))  restoreCube();
      } else if (m == LEFT)  rotSpd *= -1;
      else if (paused ^= true)  noLoop();
      else                      loop();
    }
    
    void wiggleCube() {
      for (int i = 0; i < FACES; ++i) {
        final PShape face = cube.getChild(i);
        for (int j = 0, verts = face.getVertexCount(); j < verts; ++j) {
          face.getVertex(j, vert)
            .add(rndWiggle(), rndWiggle(), rndWiggle());
          face.setVertex(j, vert);
        }
      }
    }
    
    float rndWiggle() {
      return random(-WIGGLING, WIGGLING);
    }
    
    void createCube() {
      cube = createShape(GROUP);
    
      for (int i = 0; i < FACES; ++i) // Create all faces at front position
        cube.addChild(createHoledFace(createShape()));
    
      // Rotate all the faces to their positions
      // Front face - (Already correct!)
    
      cube.getChild(1).rotateY(PI);       // Back face
      cube.getChild(2).rotateY(HALF_PI);  // Right face
      cube.getChild(3).rotateY(-HALF_PI); // Left face
      cube.getChild(4).rotateX(HALF_PI);  // Top face
      cube.getChild(5).rotateX(-HALF_PI); // Bottom face
    }
    
    static final PShape createHoledFace(final PShape face) {
      face.beginShape(POLYGON);
    
      face.strokeWeight(BOLD);
      face.stroke(OUTLINE);
      face.fill(FILL);
    
      // Draw main shape clockwise:
      face.vertex(-CUBE_RAD, -CUBE_RAD, CUBE_RAD);
      face.vertex(+CUBE_RAD, -CUBE_RAD, CUBE_RAD);
      face.vertex(+CUBE_RAD, +CUBE_RAD, CUBE_RAD);
      face.vertex(-CUBE_RAD, +CUBE_RAD, CUBE_RAD);
    
      // Draw contour (hole) counter-clockwise:
      face.beginContour();
      contourHoledFace(face, false);
      face.endContour();
    
      face.endShape(CLOSE);
      return face;
    }
    
    void restoreCube() {
      // Rotation of faces is preserved, so we just reset them the same
      // way as the "front" face and they will stay rotated correctly:
      for (int i = 0; i < FACES; restoreHoledFace(cube.getChild(i++)));
    }
    
    static final PShape restoreHoledFace(final PShape face) {
      face.setVertex(0, -CUBE_RAD, -CUBE_RAD, CUBE_RAD);
      face.setVertex(1, +CUBE_RAD, -CUBE_RAD, CUBE_RAD);
      face.setVertex(2, +CUBE_RAD, +CUBE_RAD, CUBE_RAD);
      face.setVertex(3, -CUBE_RAD, +CUBE_RAD, CUBE_RAD);
    
      return contourHoledFace(face, true);
    }
    
    static final PShape contourHoledFace(
      final PShape face, final boolean restore)
    {
      for (int i = 0; i < CIRCLE_RES; ++i) {
        float ang = CIRCLE_SLICE * i;
        float x = CIRCLE_RAD * sin(ang);
        float y = CIRCLE_RAD * cos(ang);
    
        if (restore)  face.setVertex(4 + i, x, y, CUBE_RAD);
        else          face.vertex(x, y, CUBE_RAD);
      }
    
      return face;
    }
    
  • edited May 2016

    And finally the Python Mode version: :bz

    """
     ' Wiggling Cube (v1.0.4)
     ' by  REAS & JakubValtar
     ' mod GoToLoop (2016-Mar-02)
     ' 
     ' Hit 'W' to start wiggling and SPACE to restore original cube.
     ' 'P' pauses/resumes. '1', '2', '3' change outline's stroke weight.
     ' And ENTER switches clockwise rotation.
     '
     ' GitHub.com/processing/processing-docs/blob/master/content/
     ' examples/Demos/Graphics/Wiggling/Wiggling.pde
     '
     ' forum.Processing.org/two/discussion/14071/
     ' converting-java-code-to-python-for-dataviz#Item_15
    """
    
    CUBE_DIAM = 320
    CUBE_RAD = CUBE_DIAM >> 1
    
    CIRCLE_RAD, CIRCLE_RES = 100, 40
    CIRCLE_SLICE = TAU/CIRCLE_RES
    
    NOISE_MAG = 1.0
    WIGGLING = NOISE_MAG * .5
    
    FACES, SMOOTH, FPS, BOLD = 6, 4, 60.0, 1.5
    FILL, OUTLINE = 0350, 0xffFF0000
    
    FACE_RANGE, CIRCLE_RANGE = tuple(range(FACES)), tuple(range(CIRCLE_RES))
    
    rotCounter, rotSpd = 0.0, .01
    wiggling = paused = False
    
    def setup():
        size(800, 600, P3D)
        smooth(SMOOTH), frameRate(FPS)
        createCube()
    
    
    def draw():
        global rotCounter
        rotCounter += rotSpd
    
        background(0)
        translate(width>>1, height>>1)
        rotateX(rotCounter), rotateY(rotCounter)
    
        wiggling and wiggleCube()
        shape(cube)
    
        frame.setTitle("FPS: %i" % round(frameRate) +
                       "    Wiggling: %r" % wiggling)
    
    
    def keyPressed():
        global wiggling, paused, rotSpd
    
        #k = keyCode if key == CODED else key.upper()
        k = chr(keyCode) if key != CODED else keyCode
    
        if k == 'P':
            paused ^= True
            noLoop() if paused else loop()
        elif k == ENTER or k == RETURN: rotSpd *= -1
        elif k == 'W': wiggling ^= True
        elif k == ' ': restoreCube()
        elif k == '1': cube.setStrokeWeight(BOLD)
        elif k == '2': cube.setStrokeWeight(BOLD * 3.0)
        elif k == '3': cube.setStrokeWeight(BOLD * 6.0)
    
    
    def mousePressed():
        global wiggling, paused, rotSpd
        m = mouseButton
    
        if m == CENTER:
            wiggling ^= True
            wiggling or restoreCube()
        elif m == LEFT: rotSpd *= -1
        else:
            paused ^= True
            noLoop() if paused else loop()
    
    
    def wiggleCube(vert=PVector()):
        for i in FACE_RANGE:
            face = cube.getChild(i)
            for j in childrenRange:
                face.getVertex(j, vert)\
                    .add(rndRange(), rndRange(), rndRange())
                face.setVertex(j, vert)
    
    
    def rndRange(rnd=WIGGLING): return random(-rnd, rnd)
    
    
    def createCube():
        global cube, childrenRange
        cube = createShape(GROUP)
    
        for i in FACE_RANGE: # Create all faces at front position
            cube.addChild(createHoledFace(createShape()))
    
        # Rotate all the faces to their positions
        # Front face - (Already correct!)
    
        cube.getChild(1).rotateY(PI)        # Back face
        cube.getChild(2).rotateY(HALF_PI)   # Right face
        cube.getChild(3).rotateY(-HALF_PI)  # Left face
        cube.getChild(4).rotateX(HALF_PI)   # Top face
        cube.getChild(5).rotateX(-HALF_PI)  # Bottom face
    
        # Assuming each cube's face got same # of vertices:
        childrenRange = tuple(range(cube.getChild(0).getVertexCount()))
    
    
    def createHoledFace(face):
        face.beginShape(POLYGON)
        face.strokeWeight(BOLD), face.stroke(OUTLINE), face.fill(FILL)
    
        # Draw main shape clockwise:
        face.vertex(-CUBE_RAD, -CUBE_RAD, CUBE_RAD)
        face.vertex(+CUBE_RAD, -CUBE_RAD, CUBE_RAD)
        face.vertex(+CUBE_RAD, +CUBE_RAD, CUBE_RAD)
        face.vertex(-CUBE_RAD, +CUBE_RAD, CUBE_RAD)
    
        # Draw contour (hole) counter-clockwise:
        face.beginContour()
        contourHoledFace(face)
        face.endContour()
    
        face.endShape(CLOSE)
        return face
    
    
    def restoreCube():
        # Rotation of faces is preserved, so we just reset them the same
        # way as the "front" face and they will stay rotated correctly:
        for i in FACE_RANGE: restoreHoledFace(cube.getChild(i))
    
    
    def restoreHoledFace(face):
        face.setVertex(0, -CUBE_RAD, -CUBE_RAD, CUBE_RAD)
        face.setVertex(1, +CUBE_RAD, -CUBE_RAD, CUBE_RAD)
        face.setVertex(2, +CUBE_RAD, +CUBE_RAD, CUBE_RAD)
        face.setVertex(3, -CUBE_RAD, +CUBE_RAD, CUBE_RAD)
    
        return contourHoledFace(face, True)
    
    
    def contourHoledFace(face, restore=False):
        for i in CIRCLE_RANGE:
            ang = CIRCLE_SLICE * i
            x, y = CIRCLE_RAD * sin(ang), CIRCLE_RAD * cos(ang)
    
            face.setVertex(4 + i, x, y, CUBE_RAD) if restore else\
            face.vertex(x, y, CUBE_RAD)
    
        return face
    
  • Anything in the official Processing reference is meant to also be supported in Python Mode. If it isn't, that's a bug. Please file a bug: https://github.com/jdf/Processing.py-Bugs/issues

Sign In or Register to comment.