<Back

//Aaron Koblin
//Design for Interactive Media 157A
//11/29/04

//Weavograph is a generative piece designed for 
//printmaking using the Adobe Illustrator format. 




int stagex = 400;  //stage width
int stagey = 400;  //steage height

AIExport ai;


int angle,speed, radius1, radius2;  //radius is a distance per vert seed
int centery, centerx, counter;

float[] centersx = new float[10]; 
float[] centersy = new float[10]; 
float[] spritesx = new float[10]; 
float[] spritesy = new float[10]; 
float[] speeds = new float[10]; 

boolean flag1, drawing;

BImage brush1,brush2,sc1,sc2,sc3,sc4,sc5;


 
void setup(){
   ai = new AIExport( this, 10 );
   ai.turnTransparencyOn();
   ai.setFileName("test4.ai");
   ai.setLineWeight( 0.25);
    
  framerate(20);
  counter = 0;
  background(255);
  size(stagex, stagey);  
  centerx = stagex/2;
  centery = stagey/2;
  centerverts();   //plots the centers for each sprite in a circle;
  drawing = true;
  }
void loop(){
      ai.run();
   if (drawing){
   if (counter > 100){
   counter = 0;
      }
  if (counter > 50){
        flag1 = true;
        counter ++;
   }else{
     if(counter < 100){
       flag1 = false;
       counter ++;
   }
   
   }
  
  if(flag1){
     
     plotsprites(); 
  } else  plotsprites2(); 
 
  drawpattern();
  angle++;
  if(angle > 360){   //prevents overflow after long run-time
    angle = 1; 
    setspeeds();   
  }
  radius1 = mouseX/1;
  radius2 = mouseX/2;
 }
}

void setspeeds(){
  for(int x = 0;x<10;x++){
    speeds[x] = mouseX/6+(9*x);  // setup a speed for the rotation of each vert
  } 
}

void centerverts(){                        
    
  for(int x=0;x< centersx.length ;x++){
    angle = 0; 
    angle = 36 * x;  
    centersx[x] = centerx + (cos(angle*3.14/180)*radius1);
    centersy[x] = centery + (sin(angle*3.14/180)*radius1);
    }
}

void plotsprites(){
  for(int x=0;x< spritesx.length ;x++){
    spritesx[x] = centersx[x] + (tan((angle*speeds[x])*3.14/180)*radius2);
    spritesy[x] = centersy[x] + (sin((angle*speeds[x])*3.14/180)*radius2);

     }
}

void plotsprites2(){
  for(int x=0;x< spritesx.length ;x++){
    spritesx[x] = centersx[x] + (tan((angle*speeds[x])*3.14/180)*radius2);
    spritesy[x] = centersy[x] + (cos((angle*speeds[x])*3.14/180)*radius2);
    }
}
void drawpattern(){
 
 for(int x=0;x< spritesx.length;x++){
        rotate((PI/180)*speeds[x]);
        ai.ai_fill(int(speeds[x])*2+50, int(speeds[x])*2+50,100,160);
            if(x<5){
         ai.ai_rect(spritesx[x], spritesy[x], 30, int(speeds[x]/12)+2); 
          }
        if(x>5){
       ai.ai_rect(spritesx[x], spritesy[x], 30, int(speeds[x]/12)+2); 
 
       }
      }
}

void mousePressed() 
{
  setup();
}


void keyPressed(){
if( key=='e' ) ai.exportOneFrame();
      if( key=='s' ) ai.takeSnapShot();
      if( key=='d' ) ai.dumpSnapShots();
      if( key=='r' ) ai.toggleContinuousRecording();

}

/*
 * Created on Jun 4, 2004
 * 
 * TODO To change the template for this generated file go to Window -
 * Preferences - Java - Code Generation - Code and Comments
 */
/**
 * @author William
 * 
 * TODO To change the template for this generated type comment go to Window -
 * Preferences - Java - Code Generation - Code and Comments
 */

//********************************************************************************************
//
// Export class for Adobe Illustrator (*.ai) files
// version 0.1a
// build 000005
//
// Exports version 8.0/10.0 Adobe Illustrator files.
//
// Distributed under the GNU lesser public license without implied 
// or explicit warrantees of any kind, including, but not limited 
// to, the implied warrantee of MERCHANTABILITY or FITNESS FOR 
// A PARTICULAR PURPOSE.
//
// by Allan William Martin
//
// ********************************************************************************************

public class AIExport {
    
    //  Constructor.  Sets the bApplet, layers, and defaults for rectMode and ellipseMode.
    public AIExport(BApplet bApplet, int nLayers) {  
        this.bApplet = bApplet;
        setNumberOfLayers(nLayers);
        ai_rectMode(BConstants.CORNER);
        ai_ellipseMode(BConstants.CORNER);
    }

    private BApplet bApplet;

    final int START_LINES = 100;

    int NUM_LAYERS = 5; // Five default layers.

    final int IDLE = 0;
    final int WRITING = 1;

    int stage = IDLE;
    boolean writeAIFile = false;
    boolean continuousRecording = false;
    boolean snapShot = false;
    boolean dump = false;

    int snapShotNum = 1;
    int group = 0;

    String[][] layers = null;

    int[] nLines;

    int currentLayer = 1;
    int currentRectMode;
    int currentEllipseMode;
    int currentShapeMode;

    int shapeStage = 0;
    int shapeCycle = 0;

    float[] shapeFirstVertex = new float[3];

    float currentLineWeight = 1.0f;

    boolean transparency = false;
    
    String strokeFillTagClosed = "b";
    String strokeFillTagOpen = "B";
    String fileName = "AI_output.ai";

    /**
     * Functions that actually write the Illustrator file begin here;
     */

    private void setNumberOfLayers(int nLayers) {
        if (nLayers < 1) nLayers = 1;

        NUM_LAYERS = nLayers;
        nLines = new int[NUM_LAYERS];

        for (int i = 0; i < NUM_LAYERS; i++)
            nLines[i] = 0;
    }

    void setFileName(String fileName) {
        this.fileName = fileName;
    }

    private void setDefaults() {
        setLayer(1);
        currentLineWeight = 1.0f;
    }

    public void run() {
        if ((stage == WRITING && (!continuousRecording && !snapShot)) || dump) {
            dump = false;

            // Load the blank Illustrator prototype.

            String[][] aiHeader = new String[2][];
            aiHeader[0] = bApplet.loadStrings("AIHeader1.txt");
            aiHeader[1] = bApplet.loadStrings("AIHeader2.txt");

            String[][] aiLayer = new String[2][];
            aiLayer[0] = bApplet.loadStrings("AILayer1.txt");
            aiLayer[1] = bApplet.loadStrings("AILayer2.txt");

            String[] aiEOF;
            aiEOF = bApplet.loadStrings("AIEOF.txt");

            // Calculate the anticipated file length.

            int fileLength = 0;
            fileLength += aiHeader[0].length + 1;
            fileLength += aiHeader[1].length;
            fileLength += (NUM_LAYERS - 1) * (aiLayer[0].length + 1);
            fileLength += (NUM_LAYERS - 1) * aiLayer[1].length;
            fileLength += aiEOF.length;
            for (int i = 0; i < NUM_LAYERS; i++)
                fileLength += nLines[i];

            String[] aiLines = new String[fileLength];

            int currentLine = 0; // Keeps track of where we're writing in the
                                 // file.

            // Write the header and specify the number of layers.
            System.arraycopy(aiHeader[0], 0, aiLines, currentLine,
                    aiHeader[0].length);
            currentLine += aiHeader[0].length;
            aiLines[currentLine] = "%AI5_NumLayers: " + NUM_LAYERS;
            currentLine++;
            System.arraycopy(aiHeader[1], 0, aiLines, currentLine,
                    aiHeader[1].length);
            currentLine += aiHeader[1].length;

            // Write the layers.
            for (int i = 1; i <= NUM_LAYERS; i++) {
                // Write the graphical contents of the layer.
                if (layers[i - 1][0] != null) {
                    System.arraycopy(layers[i - 1], 0, aiLines, currentLine,
                            nLines[i - 1]);
                    currentLine += nLines[i - 1];
                }
                
                // Write the terminator for the current layer, the beginning of
                // the next layer, and the name and setup stuff for the next layer.
                // But the last end-of-layer command is in AIEOF.txt, so don't 
                // write this stuff on the last layer.

                if (i < NUM_LAYERS) {
                    System.arraycopy(aiLayer[0], 0, aiLines, currentLine,
                            aiLayer[0].length);
                    currentLine += aiLayer[0].length;
                    aiLines[currentLine] = "(Layer " + (i + 1) + ") Ln";
                    currentLine++;
                    System.arraycopy(aiLayer[1], 0, aiLines, currentLine,
                            aiLayer[1].length);
                    currentLine += aiLayer[1].length;
                }
            }
            // Write the end-of-file stuff.
            System.arraycopy(aiEOF, 0, aiLines, currentLine, aiEOF.length);

            // Write the file!
            bApplet.saveStrings(fileName, aiLines);

            setStage(IDLE);
            writeAIFile = false;
            bApplet.println("AIExport: Adobe Illustrator file " + fileName
                    + " written with " + aiLines.length + " lines.");
            
            layers = null;
            for (int i = 0; i < NUM_LAYERS; i++)
                nLines[i] = 0;
            
            return;
        }
        
        // If done recording the snapshot, don't write the file, but set
        // the stage back to idle.
        if (stage == WRITING && snapShot) {
            setStage(IDLE);
        }
        
        // If writing is triggered and you're writing a snapshot or
        // recording one frame, set the stage to writing to record
        // the upcoming frame.
        if (writeAIFile && (!continuousRecording || snapShot)) {
            setStage(WRITING);
            writeAIFile = false;
        }
        
        // If writing is triggered and you're recording continuously,
        // set the stage to writing to record the upcoming frame and
        // trigger writing again so the next frame is recorded, too.
        if (writeAIFile && continuousRecording) {
            setStage(WRITING);
            writeAIFile = true;
        }
        
        // Set the default Illustrator-specific variables, and write the
        // stroke and fill at the beginning before recording the frame.
        setDefaults();
        if (stage == WRITING) {
            writeCurrentStroke();
            writeCurrentFill();
        }
    }

    private void addLine(String lineContents) {
        if (continuousRecording && (bApplet.frame % frameRate) != 0) return;
        if (layers == null) {
            layers = new String[NUM_LAYERS][START_LINES];
        }

        // Expand the array if it's suddenly larger than what's been allocated
        // so far (a multiple of START_LAYERS).
        if (nLines[currentLayer - 1] >= layers[currentLayer - 1].length) {
            String[][] newLayers = new String[NUM_LAYERS][nLines[currentLayer - 1]
                    + START_LINES];
            for (int i = 0; i < NUM_LAYERS; i++) {
                System.arraycopy(layers[i], 0, newLayers[i], 0,
                        nLines[currentLayer - 1]);
            }
            layers = newLayers;
        }

        layers[currentLayer - 1][nLines[currentLayer - 1]] = lineContents;
        nLines[currentLayer - 1]++;
    }

    // *****************************************************************************************
    // Functions for interface handling;

    int frameRate = 1;

    public void exportOneFrame(){
        beginWriting();
    }
    
    void beginWriting() {
        writeAIFile = true;
        bApplet.println("AIExport: Starting default export. Exporting the next frame.");
    }

    public void setContinuousRecordingFrameRate(int frameRate) {
        this.frameRate = frameRate;
    }

    public void toggleContinuousRecording() {
        continuousRecording = !continuousRecording;
        if (continuousRecording) {
            writeAIFile = true;
            bApplet.println("AIExport: Continuous recording started.");
        }
        if (!continuousRecording) {
            writeAIFile = false;
            bApplet.println("AIExport: Continuous recording terminated.");
        }
    }

    public void takeSnapShot() {
        snapShot = true;
        writeAIFile = true;
        bApplet.println("AIExport: Taking Illustrator snapshot #" + snapShotNum
                + ".");
        snapShotNum++;
    }

    public void dumpSnapShots() {
        dump = true;

        bApplet.println("AIExport: Dumping " + (snapShotNum - 1)
                + " Illustrator snapshots.");
        snapShotNum = 1;
    }

    private void setStage(int stage) {
        this.stage = stage;
    }

    // *****************************************************************************************
    // Functions that handle Illustrator-specific parameters;

    void setLayer(int layer) {
        if (layer >= 1 && layer <= NUM_LAYERS) currentLayer = layer;
        writeCurrentStroke();
        writeCurrentFill();
        writeCurrentLineWeight();
    }

    void setLineWeight(float lw) {
        currentLineWeight = lw;
        writeCurrentLineWeight();
    }
    
    private void writeCurrentLineWeight(){
        if (stage == WRITING) {
/*            int rememberCurrentLayer = currentLayer;
            for (int i = 1; i <= NUM_LAYERS; i++) {
                currentLayer = i;*/
                addLine(currentLineWeight + " w");
/*            }
            currentLayer = rememberCurrentLayer;*/
        }
    }

    void beginGroup() {
        if (stage == WRITING) {
            if (group == 0) addLine("u");
            group++;
        }
    }

    void endGroup() {
        if (stage == WRITING) {
            if (group > 0) group--;
            if (group == 0) addLine("U");
        }
    }

    // *****************************************************************************************
    // Processing variants to allow for .AI exporting start here;
    // The ones here handle stroke and fill;

    void turnTransparencyOn() {
        transparency = true;
    }

    void turnTransparencyOff() {
        transparency = false;
    }

    void ai_noFill() {
        bApplet.noFill();

        if (stage == WRITING) {
            if (transparency) addLine("0 1 0 0 0 Xy");
            if (bApplet.g._stroke) {
                strokeFillTagClosed = "s";
                strokeFillTagOpen = "S";
            } else {
                strokeFillTagClosed = "n";
                strokeFillTagOpen = "N";
            }
        }
    }

    void ai_fill(int arg0) {
        bApplet.fill(arg0);
        setFill();
    }

    void ai_fill(float arg0) {
        bApplet.fill(arg0);
        setFill();
    }

    void ai_fill(float arg0, float arg1) {
        bApplet.fill(arg0, arg1);
        setFill();
    }

    void ai_fill(float arg0, float arg1, float arg2) {
        bApplet.fill(arg0, arg1, arg2);
        setFill();
    }

    void ai_fill(float arg0, float arg1, float arg2, float arg3) {
        bApplet.fill(arg0, arg1, arg2, arg3);
        setFill();
    }

    private void setFill() {
        if (stage == WRITING) {
            if (bApplet.g._stroke) {
                strokeFillTagClosed = "b";
                strokeFillTagOpen = "B";
            } else {
                strokeFillTagClosed = "f";
                strokeFillTagOpen = "F";
            }

            writeCurrentFill();
        }
    }

    private void writeCurrentFill() {
        if (stage == WRITING && bApplet.g._fill) 
            addLine(bApplet.g.fillR + " " + bApplet.g.fillG + " "
                     + bApplet.g.fillB + " Xa");      
    }

    private void writeFillTransparency() {
        if (stage == WRITING && (transparency && bApplet.g._fill) )
                addLine("0 " + bApplet.g.fillA + " 0 0 0 Xy");
    }

    void ai_noStroke() {
        bApplet.noStroke();

        if (stage == WRITING) {
            if (transparency) addLine("0 1 0 0 0 Xy");
            if (bApplet.g._fill) {
                strokeFillTagClosed = "f";
                strokeFillTagOpen = "F";
            } else {
                strokeFillTagClosed = "n";
                strokeFillTagOpen = "N";
            }
        }
    }

    void ai_stroke(int arg0) {
        bApplet.stroke(arg0);
        setStroke();
    }

    void ai_stroke(float arg0) {
        bApplet.stroke(arg0);
        setStroke();
    }

    void ai_stroke(float arg0, float arg1) {
        bApplet.stroke(arg0, arg1);
        setStroke();
    }

    void ai_stroke(float arg0, float arg1, float arg2) {
        bApplet.stroke(arg0, arg1, arg2);
        setStroke();
    }

    void ai_stroke(float arg0, float arg1, float arg2, float arg3) {
        bApplet.stroke(arg0, arg1, arg2, arg3);
        setStroke();
    }

    private void setStroke() {
        if (stage == WRITING) {
            if (bApplet.g._fill) {
                strokeFillTagClosed = "b";
                strokeFillTagOpen = "B";
            } else {
                strokeFillTagClosed = "s";
                strokeFillTagOpen = "S";
            }

            writeCurrentStroke();
        }
    }

    private void writeCurrentStroke() {
        if (stage == WRITING && bApplet.g._stroke) 
            addLine(bApplet.g.strokeR + " " + bApplet.g.strokeG + " "
                    + bApplet.g.strokeB + " XA");
    }

    private void writeStrokeTransparency() {
        if (stage == WRITING && (transparency && bApplet.g._stroke) )
                addLine("0 " + bApplet.g.strokeA + " 0 0 0 Xy");
    }

    private boolean solid() {
        if (bApplet.g.strokeA > 254 && bApplet.g.fillA > 254) return true;
        return false;
    }

    // *****************************************************************************************
    // Below are the drawing functions;

    private float reflectedScreenY(float x, float y, float z) { 
    	// Illustrator's origin is the lower-left; this function
    	// compensates.
        return bApplet.height - bApplet.screenY(x, y, z);
    }

    int currentFontSize;

    int currentFontMode = BConstants.ALIGN_LEFT;

    void ai_textMode(int mode) {
        bApplet.textMode(mode);
        if (stage == WRITING) currentFontMode = mode;
    }

    void ai_textSize(int fontSize) {
        bApplet.textSize(fontSize);
        currentFontSize = fontSize;
    }

    void ai_textFont(BFont font, int fontSize) {
        bApplet.textFont(font, fontSize);
        currentFontSize = fontSize;
    }

    void ai_text(String context, float x, float y) {
        bApplet.text(context, x, y);

        if (stage == WRITING) {
            y += currentFontSize;
            if (currentFontMode == BConstants.ALIGN_CENTER)
                    x -= bApplet.width / 2;
            if (currentFontMode == BConstants.ALIGN_RIGHT) 
            		x -= bApplet.width;
            writeFillTransparency();
            addLine("1 To");
            addLine("1 0 0 1 1 1 0 Tp");
            addLine(bApplet.screenX(x, y, 0) + " " + reflectedScreenY(x, y, 0)
                    + " m");
            addLine((bApplet.screenX(x, y, 0) + bApplet.width) + " "
                    + reflectedScreenY(x, y, 0) + " L");
            addLine((bApplet.screenX(x, y, 0) + bApplet.width) + " "
                    + (reflectedScreenY(x, y, 0) + currentFontSize + 10) + " L");
            addLine(bApplet.screenX(x, y, 0) + " "
                    + (reflectedScreenY(x, y, 0) + currentFontSize + 10) + " L");
            addLine(bApplet.screenX(x, y, 0) + " " + reflectedScreenY(x, y, 0)
                    + " L");
            addLine("n");
            addLine("TP");
            addLine("0 Tr");
            if (currentFontMode == BConstants.ALIGN_LEFT) addLine("0 Ta");
            if (currentFontMode == BConstants.ALIGN_CENTER) addLine("1 Ta");
            if (currentFontMode == BConstants.ALIGN_RIGHT) addLine("2 Ta");
            addLine("/_Myriad-Roman " + currentFontSize + " 10.0439 -3 Tf");
            addLine("(" + context + ") Tx");
            addLine("TO");
        }
    }

    void ai_point(float x, float y) {
        ai_point(x, y, 0);
    }

    void ai_point(float x, float y, float z) {
        if( z==0 ) bApplet.point( x, y ); else bApplet.point(x, y, z);
        
        if (stage == WRITING) {
            writeStrokeTransparency();
            addLine((bApplet.screenX(x, y, z) - .1f) + " "
                    + (reflectedScreenY(x, y, z) - .1f) + " m");
            addLine((bApplet.screenX(x, y, z) + .1f) + " "
                    + (reflectedScreenY(x, y, z) - .1f) + " L");
            addLine((bApplet.screenX(x, y, z) + .1f) + " "
                    + (reflectedScreenY(x, y, z) + .1f) + " L");
            addLine((bApplet.screenX(x, y, z) - .1f) + " "
                    + (reflectedScreenY(x, y, z) + .1f) + " L");
            addLine((bApplet.screenX(x, y, z) - .1f) + " "
                    + (reflectedScreenY(x, y, z) - .1f) + " L");
            if (bApplet.g._stroke) {
                addLine("b");
            } else {
                addLine("n");
            }
        }
    }

    void ai_line(float x1, float y1, float x2, float y2) {
        bApplet.line(x1, y1, x2, y2);
        
        writeLine( x1, y1, 0, x2, y2, 0 );
    }

    void ai_line(float x1, float y1, float z1, float x2, float y2, float z2) {
        bApplet.line(x1, y1, z1, x2, y2, z2);
        
        writeLine( x1, y1, z1, x2, y2, z2 );
    }

    void ai_triangle(float x1, float y1, float x2, float y2, float x3, float y3) {
        bApplet.triangle(x1, y1, x2, y2, x3, y3);
        
        writeTri( x1, y1, 0, x2, y2, 0, x3, y3, 0 );
    }
    
    void ai_quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4 ) {
        bApplet.quad(x1, y1, x2, y2, x3, y3, x4, y4);

        writeQuad( x1, y1, 0, x2, y2, 0, x3, y3, 0, x4, y4, 0 );
    }

    void ai_ellipseMode(int mode) {
        currentEllipseMode = mode;
        bApplet.ellipseMode(mode);
    }

    void ai_ellipse(float a, float b, float c, float d) {
        bApplet.ellipse(a, b, c, d);

        if (stage == WRITING) {
            if (currentEllipseMode == BConstants.CENTER_DIAMETER) {
                a -= c / 2;
                b -= d / 2;
            }
            if (currentEllipseMode == BConstants.CENTER_RADIUS) {
                c *= 2;
                d *= 2;
                a -= c / 2;
                b -= d / 2;
            }
            if (currentEllipseMode == BConstants.CORNERS) {
                c -= a;
                d -= b;
            }
            if (transparency && bApplet.g._stroke && bApplet.g._fill && !solid())
                    beginGroup();
            for (int k = 0; k <= 1; k++) {
                if (!bApplet.g._fill && bApplet.g._stroke) k++;
                if (k == 0) writeFillTransparency();
                if (k == 1) writeStrokeTransparency();
                addLine(bApplet.screenX(a + c, b + d / 2, 0) + " "
                        + reflectedScreenY(a + c, b + d / 2, 0) + " m");
                addLine(bApplet.screenX(a + c, b + d / 2 - .276143f * d, 0)
                        + " "
                        + reflectedScreenY(a + c, b + d / 2 - .276143f * d, 0)
                        + " " + bApplet.screenX(a + c / 2 + .276143f * c, b, 0)
                        + " "
                        + reflectedScreenY(a + c / 2 + .276143f * c, b, 0)
                        + " " + bApplet.screenX(a + c / 2, b, 0) + " "
                        + reflectedScreenY(a + c / 2, b, 0) + " c");
                addLine(bApplet.screenX(a + c / 2 - .276143f * c, b, 0) + " "
                        + reflectedScreenY(a + c / 2 - .276143f * c, b, 0)
                        + " " + bApplet.screenX(a, b + d / 2 - .276143f * d, 0)
                        + " "
                        + reflectedScreenY(a, b + d / 2 - .276143f * d, 0)
                        + " " + bApplet.screenX(a, b + d / 2, 0) + " "
                        + reflectedScreenY(a, b + d / 2, 0) + " c ");
                addLine(bApplet.screenX(a, b + d / 2 + .276143f * d, 0) + " "
                        + reflectedScreenY(a, b + d / 2 + .276143f * d, 0)
                        + " "
                        + bApplet.screenX(a + c / 2 - .276143f * c, b + d, 0)
                        + " "
                        + reflectedScreenY(a + c / 2 - .276143f * c, b + d, 0)
                        + " " + bApplet.screenX(a + c / 2, b + d, 0) + " "
                        + reflectedScreenY(a + c / 2, b + d, 0) + " c");
                addLine(bApplet.screenX(a + c / 2 + .276143f * c, b + d, 0)
                        + " "
                        + reflectedScreenY(a + c / 2 + .276143f * c, b + d, 0)
                        + " "
                        + bApplet.screenX(a + c, b + d / 2 + .276143f * d, 0)
                        + " "
                        + reflectedScreenY(a + c, b + d / 2 + .276143f * d, 0)
                        + " " + bApplet.screenX(a + c, b + d / 2, 0) + " "
                        + reflectedScreenY(a + c, b + d / 2, 0) + " c");
                if (transparency) {
                    if (solid()) {
                        addLine(strokeFillTagClosed);
                        break;
                    }
                    if (k == 0 && bApplet.g._fill) addLine("f");
                    if (k == 1 && bApplet.g._stroke) addLine("s");
                    if (!bApplet.g._stroke || !bApplet.g._fill) break;
                    if (!bApplet.g._stroke && !bApplet.g._fill) {
                        addLine("n");
                        break;
                    }
                }
                if (!transparency) {
                    addLine(strokeFillTagClosed);
                    break;
                }
            }
            if (transparency && bApplet.g._stroke && bApplet.g._fill && !solid())
                    endGroup();
        }
    }

    void ai_rectMode(int mode) {
        currentRectMode = mode;
        bApplet.rectMode(mode);
    }

    void ai_rect(float a, float b, float c, float d) {
        bApplet.rect(a, b, c, d);

        if (stage == WRITING) {
            if (currentRectMode == BConstants.CENTER_DIAMETER) {
                a -= c / 2;
                b -= d / 2;
            }
            if (currentRectMode == BConstants.CORNERS) {
                c -= a;
                d -= b;
            }
            writeQuad( a, b, 0, a+c, b, 0, a+c, b+d, 0, a, b+d, 0 );
        }
    }

    void ai_bezier(float ax1, float ay1, float cx1, float cy1, float cx2,
            float cy2, float ax2, float ay2) {
        bApplet.bezier(ax1, ay1, cx1, cy1, cx2, cy2, ax2, ay2);

        if (stage == WRITING) {
            writeStrokeTransparency();
            addLine(bApplet.screenX(ax1, ay1, 0) + " "
                    + reflectedScreenY(ax1, ay1, 0) + " m");
            addLine(bApplet.screenX(cx1, cy1, 0) + " "
                    + reflectedScreenY(cx1, cy1, 0) + " "
                    + bApplet.screenX(cx2, cy2, 0) + " "
                    + reflectedScreenY(cx2, cy2, 0) + " "
                    + bApplet.screenX(ax2, ay2, 0) + " "
                    + reflectedScreenY(ax2, ay2, 0) + " c");
            if (bApplet.g._stroke) {
                addLine("S");
            } else {
                addLine("N");
            }
        }
    }

    void ai_box(float s) {
        ai_box(s, s, s);
    }

    void ai_box(float x, float y, float z) {
        bApplet.box(x, y, z);

        if (stage == WRITING) {
            float[][] corners = new float[8][3];
            int[][] faces = { { 0, 1, 3, 2}, { 2, 3, 7, 6}, { 6, 7, 5, 4},
                    { 0, 1, 5, 4}, { 1, 5, 7, 3}, { 0, 4, 6, 2}};

            int p = 0;
            for (float a = -1; a <= 1; a += 2) {
                for (float b = -1; b <= 1; b += 2) {
                    for (float c = -1; c <= 1; c += 2) {
                        corners[p][0] = a * (x / 2.0f);
                        corners[p][1] = b * (y / 2.0f);
                        corners[p][2] = c * (z / 2.0f);
                        p++;
                    }
                }
            }
            
            beginGroup();
            for (int i = 0; i < 6; i++) {
            	writeQuad( corners[faces[i][0]][0], corners[faces[i][0]][1], corners[faces[i][0]][2], 
            			corners[faces[i][1]][0], corners[faces[i][1]][1], corners[faces[i][1]][2], 
						corners[faces[i][2]][0], corners[faces[i][2]][1], corners[faces[i][2]][2], 
						corners[faces[i][3]][0], corners[faces[i][3]][1], corners[faces[i][3]][2] );
            }
            endGroup();
        }
    }
    
    private void writeVertex( float x, float y, float z, String tag ){
    	if( stage == WRITING ) addLine(bApplet.screenX(x, y, z) + " " + reflectedScreenY(x, y, z) + " " + tag );
    }
    
    int vertexCount = 0;
    
    void ai_beginShape(int mode) {
        bApplet.beginShape(mode);

        if( vertices == null ) for( int i=0;i<4;i++ ) for( int j=0;j<3;j++ ) vertices[i][j] = 0;
        
        vertexCount = 0;
        
        if (stage == WRITING) {
            currentShapeMode = mode;
            shapeStage = 0;
            firstBezierCurve = true;
            bezierCurves = false;
            
            if ((currentShapeMode == BConstants.LINE_STRIP || currentShapeMode == BConstants.LINE_LOOP) ||
            		(currentShapeMode == BConstants.TRIANGLE_STRIP || currentShapeMode == BConstants.QUAD_STRIP))
            	beginGroup();

            if (transparency && currentShapeMode == BConstants.POLYGON ){
                if (bApplet.g._fill) writeFillTransparency();
                else writeStrokeTransparency();
            }
        }
    }

    void ai_endShape() {
        bApplet.endShape();
        
        if( vertexCount == 0 ){
            shapeStage = 0;
            firstBezierCurve = true;
            bezierCurves = false;
            return;
        }
        
        vertexCount = 0;
        
        if (stage == WRITING) {
            firstBezierCurve = true;
            if (!bezierCurves) {
            	if( currentShapeMode == BConstants.LINE_STRIP )
                    endGroup();
            	
            	if( currentShapeMode == BConstants.LINE_LOOP ){
            		writeLine( vertices[0][0], vertices[0][1], vertices[0][2], 
            				shapeFirstVertex[0], shapeFirstVertex[1], shapeFirstVertex[2] );
                    endGroup();
            	}
                if (currentShapeMode == BConstants.TRIANGLE_STRIP || currentShapeMode == BConstants.QUAD_STRIP)
                	endGroup();
            	if( currentShapeMode == BConstants.POLYGON ){
            		writeVertex(shapeFirstVertex[0], shapeFirstVertex[1], shapeFirstVertex[2], "L");
            		addLine(strokeFillTagClosed);
            	}
            }
            if (bezierCurves) {
                if (currentShapeMode == BConstants.LINE_STRIP) {
                    if (bApplet.g._stroke) addLine("S");
                }
                if (currentShapeMode == BConstants.LINE_LOOP) {
                    addLine(bezierStart[0] + " " + bezierStart[1] + " L");
                    if (bApplet.g._stroke) addLine("s");
                }
                if (currentShapeMode == BConstants.POLYGON) {
                    addLine(bezierStart[0] + " " + bezierStart[1] + " L");
                    addLine(strokeFillTagClosed);
                }
                bezierCurves = false;
            }
        }
    }

    float[][] vertices = new float[4][3];
    
    private void writeLine( float x1, float y1, float z1, float x2, float y2, float z2 ){
        if (stage == WRITING) {
            writeStrokeTransparency();

            writeVertex( x1, y1, z1, "m" );
            writeVertex( x2, y2, z2, "L" );

            if (bApplet.g._stroke) {
                addLine("S");
            } else {
                addLine("N");
            }
        }
    }
    
    private void writeTri( float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3 ){
        if (stage == WRITING) {
            if (transparency && bApplet.g._stroke && bApplet.g._fill && !solid())
                    beginGroup();
            for (int k = 0; k <= 1; k++) {
                if (!bApplet.g._fill && bApplet.g._stroke) k++;
                if (k == 0) writeFillTransparency();
                if (k == 1) writeStrokeTransparency();
                writeVertex( x1, y1, z1, "m" );
                writeVertex( x2, y2, z2, "L" );
                writeVertex( x3, y3, z3, "L" );
                writeVertex( x1, y1, z1, "L" );
                if (transparency) {
                    if (solid()) {
                        addLine(strokeFillTagClosed);
                        break;
                    }
                    if (k == 0 && bApplet.g._fill) addLine("f");
                    if (k == 1 && bApplet.g._stroke) addLine("s");
                    if (!bApplet.g._stroke || !bApplet.g._fill) break;
                    if (!bApplet.g._stroke && !bApplet.g._fill) {
                        addLine("n");
                        break;
                    }
                }
                if (!transparency) {
                    addLine(strokeFillTagClosed);
                    break;
                }
            }
            if (transparency && bApplet.g._stroke && bApplet.g._fill && !solid())
                    endGroup();
        }
    }
    
    private void writeQuad( float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4 ){
        if (stage == WRITING) {
            if (transparency && bApplet.g._stroke && bApplet.g._fill && !solid())
                    beginGroup();
            for (int k = 0; k <= 1; k++) {
                if (!bApplet.g._fill && bApplet.g._stroke) k++;
                if (k == 0) writeFillTransparency();
                if (k == 1) writeStrokeTransparency();
                writeVertex( x1, y1, z1, "m" );
                writeVertex( x2, y2, z2, "L" );
                writeVertex( x3, y3, z3, "L" );
                writeVertex( x4, y4, z4, "L" );
                writeVertex( x1, y1, z1, "L" );
                if (transparency) {
                    if (solid()) {
                        addLine(strokeFillTagClosed);
                        break;
                    }
                    if (k == 0 && bApplet.g._fill) addLine("f");
                    if (k == 1 && bApplet.g._stroke) addLine("s");
                    if (!bApplet.g._stroke || !bApplet.g._fill) break;
                    if (!bApplet.g._stroke && !bApplet.g._fill) {
                        addLine("n");
                        break;
                    }
                }
                if (!transparency) {
                    addLine(strokeFillTagClosed);
                    break;
                }
            }
            if (transparency && bApplet.g._stroke && bApplet.g._fill && !solid())
                    endGroup();
        }
    }
    
    private void shiftVertices(){
    	for( int i=0;i<3;i++ ) {
    		vertices[0][i] = vertices[1][i];
    		vertices[1][i] = vertices[2][i];
    		vertices[2][i] = vertices[3][i];
    	}
    }
    
    void ai_vertex(float x, float y) {
        ai_vertex(x, y, 0);
    }

    void ai_vertex(float x, float y, float z) {
        if( z==0 ) bApplet.vertex(x, y); else bApplet.vertex(x, y, z);
        
        vertexCount++;

        if (stage == WRITING) {
            if (currentShapeMode == BConstants.POINTS) {
                ai_point(x, y, z);
                return;
            }
            
            vertices[ shapeStage ][0] = x;
            vertices[ shapeStage ][1] = y;
            vertices[ shapeStage ][2] = z;
            
            if (shapeStage == 0) {
                shapeFirstVertex[0] = x;
                shapeFirstVertex[1] = y;
                shapeFirstVertex[2] = z;
            }
            
            shapeStage++;
            
            if( shapeStage == 1 && currentShapeMode == BConstants.POLYGON )
            	writeVertex(x, y, z, "m");

            if( shapeStage > 1 && currentShapeMode == BConstants.POLYGON ){
            	writeVertex(x, y, z, "L");
            	shapeStage = 2;
        	}
            if( shapeStage == 2 && (currentShapeMode == BConstants.LINE_STRIP || 
            						currentShapeMode == BConstants.LINE_LOOP )){
            	writeLine( vertices[0][0], vertices[0][1], vertices[0][2], 
            				vertices[1][0], vertices[1][1], vertices[1][2] );
            	shiftVertices();
            	shapeStage = 1;
            }
            if( shapeStage == 2 && currentShapeMode == BConstants.LINES ){
            	writeLine( vertices[0][0], vertices[0][1], vertices[0][2],
            				vertices[1][0], vertices[1][1], vertices[1][2] );
            	shapeStage = 0;
            }
            if( shapeStage == 3 && currentShapeMode == BConstants.TRIANGLES ){
            	writeTri( vertices[0][0], vertices[0][1], vertices[0][2], 
            			vertices[1][0], vertices[1][1], vertices[1][2],
						vertices[2][0], vertices[2][1], vertices[2][2] );
            	shapeStage = 0;
            }
            if( shapeStage == 4 && currentShapeMode == BConstants.QUADS ){
            	writeQuad( vertices[0][0], vertices[0][1], vertices[0][2], 
            			vertices[1][0], vertices[1][1], vertices[1][2],
						vertices[2][0], vertices[2][1], vertices[2][2],
						vertices[3][0], vertices[3][1], vertices[3][2] );
            	shapeStage = 0;
            }
            if( shapeStage == 3 && currentShapeMode == BConstants.TRIANGLE_STRIP ){
            	writeTri( vertices[0][0], vertices[0][1], vertices[0][2], 
            			vertices[1][0], vertices[1][1], vertices[1][2],
						vertices[2][0], vertices[2][1], vertices[2][2] );
            	shiftVertices();
            	shapeStage = 2;
            }
            if( shapeStage == 4 && currentShapeMode == BConstants.QUAD_STRIP ){
            	writeQuad( vertices[0][0], vertices[0][1], vertices[0][2], 
            			vertices[1][0], vertices[1][1], vertices[1][2],
						vertices[2][0], vertices[2][1], vertices[2][2],
						vertices[3][0], vertices[3][1], vertices[3][2] );
            	shiftVertices();
            	shiftVertices();
            	shapeStage = 2;
            }
            
        }
    }

    float bezierCoordinates[][] = new float[4][2];
    float bezierStart[] = new float[2];
    boolean firstBezierCurve = true;
    boolean bezierCurves = false;

    void ai_bezierVertex(float x1, float y1) {
        ai_bezierVertex(x1, y1, 0);
    }

    void ai_bezierVertex(float x1, float y1, float z1) {
        bApplet.bezierVertex(x1, y1, z1);
        
        vertexCount++;

        if (stage == WRITING) {
            bezierCoordinates[shapeStage][0] = bApplet.screenX(x1, y1, z1);
            bezierCoordinates[shapeStage][1] = reflectedScreenY(x1, y1, z1);
            if (!bezierCurves) {
                bezierStart[0] = bezierCoordinates[0][0];
                bezierStart[1] = bezierCoordinates[0][1];
                bezierCurves = true;
            }
            if (shapeStage == 3) {
                if (firstBezierCurve) {
                    addLine(bezierCoordinates[0][0] + " "
                            + bezierCoordinates[0][1] + " m");
                    firstBezierCurve = false;
                } else {
                    addLine(bezierCoordinates[0][0] + " "
                            + bezierCoordinates[0][1] + " L");
                }
                addLine(bezierCoordinates[1][0] + " " + bezierCoordinates[1][1]
                        + " " + bezierCoordinates[2][0] + " "
                        + bezierCoordinates[2][1] + " "
                        + bezierCoordinates[3][0] + " "
                        + bezierCoordinates[3][1] + " c");
                shapeStage = -1;
            }

            shapeStage++;
        }
    }

}
        
Assignment: Convergence: Create two drawings, derived from the same algorithm, using your experience from Exercise D and G, Drawing/Gesture and Multiples.

Built with Processing