Harvey Project - Harvey as an Incomplete Mechanical Philosopher

InfoInfo
Search:    

Return to Main Page

    1. Feedback from 14 Jan 2009 meeting
    2. Feedback from 28 Jan 2009 Meeting
    3. Notes - Group Presentation - 25 February 2009
    4. Foam Heart
    5. Sample Code for Arduino
    6. Sample Code for Processing
    7. Sample Code for Processing Version 2

Krista's notes for meeting of 12 Nov 2008

Feedback

Feedback from 14 Jan 2009 meeting

-possibility of cutting nerf ball apart. —those near dollar store to look for cheap toys to test out.
-sensitivity levels, one side is stronger than the other.
-testing different heart shaped squeezeable interfaces
-hard outside, squishy stuff on the inside—material heart
-discussion of including the heart in a representation of the body.

Feedback from 28 Jan 2009 Meeting

-Problem of finding a foam ball addressed, this will eventually be turned into a more sophisticated model.
-Thicker foam on one side to deal with pressure.
-Slow vs. fast heart beat appearing on screen.
-Need to make sure that everyone in the group has something to work on, speak up if you feel you need more or less to do!

Notes - Group Presentation - 25 February 2009

-add a tactile element to the heart, a pager modem
-if possible make one button harder to push, harder foam or tighter spring
-aid to simulate the heartbeat
-add sound effect, when the heart dies
-include a flashier graph for the heart beat
-make the model more 3-D
-suggested sign "Keep it Alive"
-record or track the highest score
-consider the take away message, Harvey learned by experimentation
-suggested sign "Save the Heart."
Lois's notes.

Foam Heart

Wrapped wires.JPG Sensors in the foam ball.JPG Soldering I.JPG Pictures of the heart in progress.JPG
Heart of foam.JPG Sensors working before inserting in the foam ball.JPG Conception for the 2nd foam heart.JPG Soldering 2.JPG
Wires in the heart.JPG

Sample Code for Arduino


/////////////////////////////////////////////////////////////////////////////////////
// Program to track user inputs for a heart simulation
// Two FSRs are attached to pins 2 and 3 of the arduino
// when a FSR is pressed it triggers an interrupt for its respective pin
// the interrupts compare the timing and order of the FSR presses
// either a successful beat or error code is outputed depending on input



/////////////////////////////////////////////////////////////////////
/// Declare Variables and Constants
int SENSORPIN_1 = 2;     // select the input  pin for 1st sensor
int SENSORPIN_2 = 3;     // select the input  pin for 2nd sensor
int MOTORPIN_1 = 8;     // select the output pin for 1st motor
int MOTORPIN_2 = 9;     // select the output pin for 2nd motor
volatile boolean SENSOR1_PRESS = false;  //Track if sensor sucessfully pressed

volatile float SENSOR1_TIME = 0 ;     //Record time of sensor 1 pressed
volatile float SENSOR2_TIME = 0 ;    //Record time of sensor 2 pressed

volatile float SPIKE_TIME=300;  //time for spikes on sensor (ms)

volatile float BEAT_LOW = 750;  //Low end of range for time length of a good beat
volatile float BEAT_HIGH = 1500; //High end of range for time length of a good beat


///////////////////////////////////////////////////////////////////////
///Setup Arduino
void setup() {
  pinMode(SENSORPIN_1, INPUT);  // declare the sensor pin 1 as input
  pinMode(SENSORPIN_2, INPUT);  // declare the sensor pin 2 as input
  pinMode(MOTORPIN_1, OUTPUT);  // declare the motor pin 1 as output
  pinMode(MOTORPIN_2, OUTPUT);  // declare the motor pin 2 as output

  Serial.begin(9600);           //turn on serial Port
 attachInterrupt(0, SENSOR1_ISR, RISING); //Create an interrupt in pin 2 for sensor 1 on rising edge
 attachInterrupt(1, SENSOR2_ISR, RISING); //Create an interrupt in pin 3 for sensor 2 on rising edge
}

///////////////////////////////////////////////////////////////////////
/// Main Loop
void loop() {




if (digitalRead(SENSORPIN_1)==HIGH) {
digitalWrite(MOTORPIN_1,HIGH);
}

if (digitalRead(SENSORPIN_1)==LOW) {
  digitalWrite(MOTORPIN_1,LOW);
}

if (digitalRead(SENSORPIN_2)==HIGH) {
digitalWrite(MOTORPIN_2,HIGH);
}

if (digitalRead(SENSORPIN_2)==LOW) {
  digitalWrite(MOTORPIN_2,LOW);
}


}

/////////////////////////////////////////////////////////
//Sensor 1 Interrupt
void SENSOR1_ISR()  {

//ensure this isnt a spike triggering extra interrupts
//do so by comparing time of this interrupt with last, if it is very small  it is likly a spike

if ( (millis() - SENSOR1_TIME)> SPIKE_TIME){

//Check to make sure user has not double pressed first sensor
//If They have return Error, else record press


  if (SENSOR1_PRESS== true){
    Serial.println("5"); //error signal
    SENSOR1_PRESS= false; //reset
   }


  else {

    SENSOR1_PRESS=true;
    SENSOR1_TIME= millis();
   }

  }
}


/////////////////////////////////////////////////////////////////
//Sensor 2 Interrupt
void SENSOR2_ISR()  {

//ensure this isnt a spike triggering extra interrupts
//do so by comparing time of this interrupt with last, if it is very small it is likly a spike

  if ( (millis() - SENSOR2_TIME)> SPIKE_TIME){

    SENSOR2_TIME=millis();

    //Check to make Sure Sensor 1 has been pressed, if not error
    if (SENSOR1_PRESS== false){
    Serial.println("4"); //error signal
    }

    //Check to make sure time between presses isnt too fast

    else if ( (SENSOR2_TIME - SENSOR1_TIME ) < BEAT_LOW) {
      Serial.println("2"); //error signal
      SENSOR1_PRESS= false;   //reset
    }

        //Check to make sure time between presses isnt too slow

    else if ( (SENSOR2_TIME - SENSOR1_TIME ) > BEAT_HIGH) {
      Serial.println("3"); //error signal
      SENSOR1_PRESS= false;   //reset
    }

    //output a good beat

    else {
      Serial.println("1");
      SENSOR1_PRESS= false; //reset
    }
  }
}


Sample Code for Processing

//import serial library
import processing.serial.*;
//create serial object
Serial sPort;

//variable to store read serial values
String Ard="0";

void setup(){
  size (500,500);
  String portName = "COM3";
  sPort = new Serial(this, portName, 9600);

  PFont font;
  font=loadFont("Arial.vlw");
  textFont(font);
}

void draw (){
      background(90);

  //If bytes sent in serial read and store in Ard
  if (sPort.available()>0){
    Ard=sPort.readString();

    //read only first character sent, processing appends extra characters onto value from arduino
    Ard=Ard.substring(0,1);
  }


  //Normal Beat
  if (Ard.equals("1")){
    DRAW_BEAT (0,250,250,250);
    DRAW_BEAT (250,250,250,250);
    text("--Normal Heart Beat", 90, 400);

  }

  //Fast Beat
  else if (Ard.equals("2")){
    DRAW_BEAT (0,250,100,250);
    DRAW_BEAT (250,250,100,250);
    line(100,250,250,250);
    line(350,250,500,250);
    text("--Too fast!", 90, 400);

  }

  //Slow Beat
  else if (Ard.equals("3")){
    DRAW_BEAT (0,250,250,50);
    DRAW_BEAT (250,250,250,50);
    text("--Too slow!", 90, 400);

  }
  //Dead Beat
  else {
    fill(220,0,0);
    text("THE HEART IS DEAD", 50, 400);
  }

}


 ////////////////////////////////////////////////////////////////////
 ///Function to Draw a heart beat
 //This defines what the new command or function in processing is
 //the function will not do anything unless it is called elsewhere in the program
 //X_START is the x location of the start of the left hand side of the curve
 //Y_START is the y location of the start of the left hand side of the curve
 //X_SIZE defines the x size of the curve (distance from starting to point to end point)
 //Y_SIZE defines the y size of the curve (distance from flat line to peak of R curve)
void DRAW_BEAT(int X_START, int Y_START, int X_SIZE, int Y_SIZE){

  noFill();
  beginShape();

//Starting Flatline
vertex(X_START,Y_START);
vertex(X_START+(.15*X_SIZE),Y_START);

//p-curve
curveVertex(X_START+(.15*X_SIZE),Y_START);
curveVertex(X_START+(.24*X_SIZE), Y_START-(.125*Y_SIZE));
curveVertex(X_START+(.30*X_SIZE),Y_START);
curveVertex(X_START+(.30*X_SIZE),Y_START);

//pr-segment (straight line)
vertex(X_START+(.30*X_SIZE),Y_START);
vertex(X_START+(.42*X_SIZE),Y_START);

//Q line
vertex(X_START+(.44*X_SIZE),Y_START+(.125*Y_SIZE));

//R line
vertex(X_START+(.48*X_SIZE),Y_START-Y_SIZE);

//S-line
vertex(X_START+(.51*X_SIZE),Y_START+(.3*Y_SIZE));

//ST Segment
vertex(X_START+(.55*X_SIZE),Y_START);
vertex(X_START+(.69*X_SIZE),Y_START);

//T Curve
curveVertex(X_START+(.69*X_SIZE),Y_START);
curveVertex(X_START+(.80*X_SIZE),Y_START-(.2*Y_SIZE));
curveVertex(X_START+(.87*X_SIZE),Y_START);
curveVertex(X_START+(.87*X_SIZE),Y_START);

//end flatline
vertex(X_START+(.87*X_SIZE),Y_START);
vertex(X_START+X_SIZE,Y_START);
  endShape();
 }

Sample Code for Processing Version 2

//////////////////////////////////////////////////////////////////////////////////////////////////////
///Reads output from Arduino, draws a heart beat appropriate for user input

/////////////////////////////////////////////////////////////////////////////////////////////////////
//Updated from previous code
//straight lines drawn with rectangles instead of ellipses allowing for faster drawing
//updated drawing method for better continuity between sections of beat curve



//import serial library
import processing.serial.*;
//create serial object
Serial sPort;

//Everything is drawn in parametric terms
float sub_curve_percent=1.1; //How far along the beat curve we have drawn, it is a percent of a percent!, global variable
float sub_sub_curve_percent=0;//How far along the subsection of the beat curve we have drawn, it is a percent of a percent of a percent!


////Global Variables
float step_size = 0.002;  // How far each step travels (in percent)
float percent = 0.0;      // Current Location Percent (0 -> 1)
float draw_percent=0; //holds locations to draw current heart beat
String beat_type="a"; //stores type of beat to be drawn
float clear_box_x=0; //store where to draw clear box
int beat_count=0; //Counts total number of good beats in a row

//Default sizes for different beats
float fast_size=0.175;
float normal_size=0.25;
float slow_size=0.35;

//Size of ellipse used to draw curves
float x_ellip=6;
float y_ellip=6;



//variable to store read serial values
String Ard="0";

//for translations, used to store current end of curve as it is drawn, allows origin to be easily redefined to the end of the curve
float x_trans=0;
float y_trans=0;
float x_trans_2=0;
float y_trans_2=0;
float x_trans_3=0;
float y_trans_3=0;
float x_trans_4=0;
float y_trans_4=0;

/////////////////////////////////////////////////////////////////////////////////////////////
//Void setup
void setup() {


size (900,800);
noStroke();
smooth();


//Create Serial port class
String portName = "COM3";
sPort = new Serial(this, portName, 9600);

//import font
PFont font;
font=loadFont("Arial.vlw");
textFont(font);

//Draw initial square for whole screen
fill(85);//Draw Original Square
rect(0, 0,width,height);

//Draw initial square in middle
fill(20);//Draw Original Square
rect(0, height/4,width,height/2);//Only do for middle 1/2

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////Void Draw
 void draw(){

//Background at bottom and top
stroke(150,200,0);
fill(15,7);
rect(0, ((3*height)/4),width-1,(height/4)-1);
rect(0, 0,width-1,height/4);
noStroke();

//Title
textAlign(CENTER);
fill(150,200,0);
textSize(50);
text("William Harvey",width/2,height/12);
text("Mechanical Philosopher",width/2,height/6);

//Fixed Data headings
textAlign(LEFT);
fill(150,200,0);
textSize(30);
text("Previous Beat Type:", width/36 ,height/1.25);
text("Previous Error Type:", width/36 ,height/1.10);

textSize(30);
textAlign(CENTER);
text("Normal Beat Count", width/2+width/3 ,height/1.175);
textSize(45);
text(beat_count, width/2+width/3 ,height/1.10);
textAlign(LEFT);

//centre background
fill(55,7);//Draw in opaque background fading away
rect(0, height/4,width,height/2);//Only do for middle 1/2



//If bytes sent in serial read and store in Ard
  if (sPort.available()>0){
    Ard=sPort.readString();

    //read only first character sent, processing appends extra characters onto value from arduino
    Ard=Ard.substring(0,1);
}

  //Give error if user attempts input while drawing a heart beat

if ((sub_curve_percent<1.0)&&(Ard.equals("a")==false)){
  Ard="a";
  fill(55);//Draw Original Square

 rect(0, (height*3)/4,width,height/4);//Only do for bottom 1/4

     fill(150,255,0);
         textSize(30);
    text("Misbeat", width/3, height/1.10);
    beat_count=0;
   }



  /////////////////////////////////////////////
  //decide what to do with read data, if not while another curve is being drawn

if (sub_curve_percent>=1){  //make sure nothing else is being drawn

  //Config for normal beat
  if (Ard.equals("1")){
    draw_percent=percent;
    percent=percent+normal_size;

    //wrap around screen if percent greater than 1.0
    if (percent>=1.0){
      percent=percent-1.0;
    }

    beat_type="1";
    Ard="a";
    sub_curve_percent=0;

    //clear out top/bottom part of screen
   fill(55);//Draw Original Square
   rect(0, (height*3)/4,width,height/4);//Only do for bottom 1/4

    //write text
    fill(150,200,0);
    textSize(30);
    text("Normal", width/3, height/1.25);
    beat_count=beat_count+1;
  }

  //Config for fast beat
    if (Ard.equals("2")){
    draw_percent=percent;
    percent=percent+fast_size;

        //wrap around screen if percent greater than 1.0
    if (percent>=1.0){
      percent=percent-1.0;
    }

    beat_type="2";
    Ard="a";
    sub_curve_percent=0;

 //clear out top/bottom part of screen
 fill(55);//Draw Original Square
  rect(0, (height*3)/4,width,height/4);//Only do for bottom 1/4

    //write text
    fill(150,200,0);
    textSize(30);
    text("Fast", width/3, height/1.25);
    beat_count=0;
  }

    //Config for slow beat
    if (Ard.equals("3")){
    draw_percent=percent;
    percent=percent+slow_size;

    //wrap around screen if percent greater than 1.0
    if (percent>=1.0){
      percent=percent-1.0;
    }

    beat_type="3";
    Ard="a";
    sub_curve_percent=0;


 fill(55);//Draw Original Square
  rect(0, (height*3)/4,width,height/4);//Only do for bottom 1/4

    fill(150,200,0);
    textSize(30);
    text("Slow", width/3, height/1.25);
    beat_count=0;
  }

  //error if pressed in wrong order
        if (Ard.equals("4")){
              Ard="a";

  //clear out bottom part of screen
 fill(55);//Draw Original Square
 rect(0, (height*3)/4,width,height/4);//Only do for bottom 1/4


    fill(150,200,0);
    textSize(30);
    text("Wrong Chamber Order", width/3, height/1.10);
    beat_count=0;
        }

//Error if button 1 pressed twice in a row
        if (Ard.equals("5")){
              Ard="a";

  //clear out bottom part of screen
 fill(55);//Draw Original Square
 rect(0, (height*3)/4,width,height/4);//Only do for bottom 1/4

    fill(150,200,0);
    textSize(30);
    text("Double Left Chamber", width/3, height/1.10);
    beat_count=0;
        }
   }


 /////////////////////////////////////////
//////////Draw a heart beat if required


//If at the end of the screen reset
if(percent>=1.0){
  percent=-0.05;
  }


if (sub_curve_percent<1.0){

  //Draw Normal beat
  if (beat_type.equals("1")){
    draw_beat(draw_percent,0.0006,normal_size,.8,1.5);
  clear_box((clear_box_x+5));

    //wrap around if drawing at end of screen
    if ((draw_percent+(normal_size*sub_curve_percent))>=1.0){
      draw_percent=-(normal_size*sub_curve_percent);
    }

    }

    //fast beat
  if (beat_type.equals("2")){
    draw_beat(draw_percent,0.0006,fast_size,1.0,1);
  clear_box((clear_box_x+5));

      //wrap around if drawing at end of screen
    if ((draw_percent+(fast_size*sub_curve_percent))>=1.0){
      draw_percent=-(fast_size*sub_curve_percent);
    }

    }


   //Slow beat
   if (beat_type.equals("3")){
    draw_beat(draw_percent,0.0006,slow_size,.60,2);
  clear_box((clear_box_x+5));

      //wrap around if drawing at end of screen
    if ((draw_percent+(slow_size*sub_curve_percent))>=1.0){
      draw_percent=-(slow_size*sub_curve_percent);
    }

    }

}

//if not drawing a beat, draw a staight line
else{
  straight_line(percent);
  percent=percent+step_size;
  clear_box(percent*width);
}


}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Draws a box to clear screen ahead of cursor

 void clear_box(float x_location){

//draw rectangle to clear out things ahead
fill(55);//Draw Original Square
rect(x_location+5, (height/4)+2,width/12,(height/2-2));//Only do for middle 1/2
 }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Draws a beat using as ellipse or rectangle at the specified location on the screen, all variables passed are in terms of percent

 void draw_beat(float start_percent, float step_size_overall, float x_size, float y_size, float scale_factor){
    float x=0;  //Current X Location
    float y=0; //Current Y location
    float m=0; //Current slope
    float step_length = 0; //distance of step in x direction, untransformed

    float trans_angle=0;  //Stores calculated value of rotation
    float angle_distance=0;  //Stores length of angled lines when needed





   //calculate total number of steps within curve

  float sub_step_num= ((x_size)/step_size_overall);

  float sub_step_size= (1.0/sub_step_num);// initial step size




  /////////////////////////////////////////////////////////////////////////////////////////
  //Draw inital Flat line
  if ((sub_curve_percent>=0)&&(sub_curve_percent<0.15)) {

    sub_step_size=0.25/scale_factor;

   x= (width)*(start_percent + (x_size*0.16*sub_sub_curve_percent));
   y= (height/2);


 //Draw rectangle and update current locations
 fill(0,255,0);
 clear_box_x=x;
 rect(x-1, y-step_size*width, x_size*sub_step_size*width*.15+1, y_ellip);  //shift to fill gap





  //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location



  if   (sub_sub_curve_percent>=1.0){
    sub_curve_percent=0.15;
    sub_sub_curve_percent=0;
  }

    }
  /////////////////////////////////////////////////////////////////////////////////////////
 ///Draw  P Curve
  if ((sub_curve_percent>=.15)&&(sub_curve_percent<0.30)) {

        sub_step_size=0.05;


   x= (width)*(start_percent + 0.15*x_size + (x_size*0.15*sub_sub_curve_percent));
   y= (height/2) - ((height/4)*(y_size))*(0.075*sin((PI/2)*(sub_sub_curve_percent/.5)));

  //Draw ellipse and update current locations
 fill(0,255,0);
  clear_box_x=x;
 ellipse(x, y, x_ellip, y_ellip-1);

     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location



  if   (sub_sub_curve_percent>1.0){
    sub_curve_percent=.30;
    sub_sub_curve_percent=0;

  }


  }

 ////////////////////////////////////////////////////////////////////////////////////
 //////pr-segment (straight line)

     if ((sub_curve_percent>=.30)&&(sub_curve_percent<0.42)) {

             sub_step_size=0.125/scale_factor;

   x= (width)*(start_percent + 0.29*x_size + (x_size*0.13*sub_sub_curve_percent));
   y= (height/2);

 //Draw rectangle and update current locations
 fill(0,255,0);
 clear_box_x=x;
 rect(x-1, y-step_size*width, x_size*sub_step_size*width*.12+1, y_ellip);   //shift to fill gap


     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location

  if   (sub_sub_curve_percent>=1.0){
    sub_curve_percent=.42;
    sub_sub_curve_percent=0;
  }


 }



/////////////////////////////////////////////////////////////////////////////////////
//Q line
  if ((sub_curve_percent>=.42)&&(sub_curve_percent<0.44)) {

     sub_step_size=0.125/scale_factor;

//redefine origin using translation, at the current end of the curve to make calculating the equation of the line much easier, ie b=0 in y=mx +b
pushMatrix();
translate((width)*(start_percent + (x_size*.42))-x_ellip/2,(height/2)-y_ellip/2);

x= (width)*(start_percent + 0.42*x_size + (x_size*0.02*sub_sub_curve_percent))-((width)*(start_percent + (x_size*.42)));
y= (((height/4)*(y_size)*0.125))/((width)*(start_percent + (x_size*.44))-((width)*(start_percent + (x_size*.42))))*x;

m=(((height/4)*(y_size)*0.125))/((width)*(start_percent + (x_size*.44))-((width)*(start_percent + (x_size*.42))));

trans_angle=atan(m);
step_length= (.02*x_size*width)*sub_step_size;
angle_distance= step_length/cos(trans_angle);

rotate(trans_angle);

 //Draw rectangle and update current locations
fill(0,255,0);
rect(x/cos(trans_angle), -(y_ellip)/2, angle_distance, y_ellip);
popMatrix();


x_trans=x+(width)*(start_percent + (x_size*.42))-x_ellip/2;
y_trans=y+(height/2)-y_ellip/2;
clear_box_x=x_trans;

     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location

  if   (sub_sub_curve_percent>=1.0){
    sub_curve_percent=.44;
    sub_sub_curve_percent=0;

  }



}


/////////////////////////////////////////////////////////////////////////////////////
//R line
  if ((sub_curve_percent>=.44)&&(sub_curve_percent<0.48)) {

         sub_step_size=0.125/scale_factor;



//redefine origin using translation, at the current end of the curve to make calculating the equation of the line much easier, ie b=0 in y=mx +b
pushMatrix();
translate(x_trans,y_trans);
x= (width)*(start_percent + 0.44*x_size + (x_size*0.04*sub_sub_curve_percent))-((width)*(start_percent + (x_size*.44)));
y= -(((height/4)*(y_size)*1))/((width)*(start_percent + (x_size*.48))-((width)*(start_percent + (x_size*.44))))*x;

m= -(((height/4)*(y_size)*1))/((width)*(start_percent + (x_size*.48))-((width)*(start_percent + (x_size*.44))));

trans_angle=atan(m);
step_length= (.04*x_size*width)*sub_step_size;
angle_distance= step_length/cos(trans_angle);

rotate(trans_angle);

 //Draw rectangle and update current locations
fill(0,255,0);
rect(x/cos(trans_angle), -(y_ellip)/2, angle_distance, y_ellip);

popMatrix();
x_trans_2=x+x_trans;
y_trans_2=y+y_trans;
clear_box_x=x_trans_2;


     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location

  if   (sub_sub_curve_percent>=1.0){
    sub_curve_percent=.48;
    sub_sub_curve_percent=0;

  }



}


/////////////////////////////////////////////////////////////////////////////////////
//S line
  if ((sub_curve_percent>=.48)&&(sub_curve_percent<0.51)) {
    //Need smaller step size to draw

        sub_step_size=0.125/scale_factor;

//redefine origin using translation, at the current end of the curve to make calculating the equation of the line much easier, ie b=0 in y=mx +b
pushMatrix();
translate(x_trans_2,y_trans_2-y_ellip);
x= (width)*(start_percent + (0.48*x_size + (x_size*0.03*sub_sub_curve_percent)))-((width)*(start_percent + (x_size*.48)));
y= (((height/4)*(y_size)*1.3))/((width)*(start_percent + (x_size*.51))-((width)*(start_percent + (x_size*.48))))*x;
m=(((height/4)*(y_size)*1.3))/((width)*(start_percent + (x_size*.51))-((width)*(start_percent + (x_size*.48))));


trans_angle=atan(m);
step_length= (.03*x_size*width)*sub_step_size;
angle_distance= step_length/cos(trans_angle);

rotate(trans_angle);
 //Draw rectangle and update current locations
fill(0,255,0);
rect(x/cos(trans_angle), -(y_ellip)/2, angle_distance, y_ellip);

popMatrix();
x_trans_3=x+x_trans_2;
y_trans_3=y+y_trans_2;
clear_box_x=x_trans_3;

     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location

  if   (sub_sub_curve_percent>=1.0){
    sub_curve_percent=.51;
    sub_sub_curve_percent=0;

  }


}


/////////////////////////////////////////////////////////////////////////////////////
//S line back up
  if ((sub_curve_percent>=.51)&&(sub_curve_percent<0.55)) {
    //Need smaller step size to draw

       sub_step_size=0.125/scale_factor;

//redefine origin using translation, at the current end of the curve to make calculating the equation of the line much easier, ie b=0 in y=mx +b
pushMatrix();
translate(x_trans_3,y_trans_3);
x= (width)*(start_percent + (0.51*x_size + (x_size*0.04*sub_sub_curve_percent)))-((width)*(start_percent + (x_size*.51)));
y= -(y_trans_3-(height/2))/((width)*(start_percent + (x_size*.55))-((width)*(start_percent + (x_size*.51))))*x;
m=-(y_trans_3-(height/2))/((width)*(start_percent + (x_size*.55))-((width)*(start_percent + (x_size*.51))));

trans_angle=atan(m);
step_length= (.04*x_size*width)*sub_step_size;
angle_distance= step_length/cos(trans_angle);

rotate(trans_angle);
 //Draw rectangle and update current locations
fill(0,255,0);
rect(x/cos(trans_angle), (-y_ellip/2), angle_distance, y_ellip);

popMatrix();
clear_box_x=x+x_trans_3;

     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location

  if   (sub_sub_curve_percent>=.95){
    sub_curve_percent=.55;
    sub_sub_curve_percent=0;

  }



}


/////////////////////////////////////////////////////////////////////////////////////
//ST segment
  if ((sub_curve_percent>=.55)&&(sub_curve_percent<0.69)) {


  sub_step_size=0.125/scale_factor;
//redefine origin using translation, at the current end of the curve to make calculating the equation of the line much easier, ie b=0 in y=mx +b

   x=(width)*(start_percent + 0.55*x_size + (x_size*0.14*sub_sub_curve_percent));
   y= (height/2);


 //Draw rectangle and update current locations
fill(0,255,0);
rect(x-x_ellip, y-step_size*width,x_size*sub_step_size*width*.12+x_ellip, y_ellip);   //added small shift to fill in meetings of lines

     clear_box_x=x;


     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location

  if   (sub_sub_curve_percent>=1.0){
    sub_curve_percent=.69;
    sub_sub_curve_percent=0.0;

  }

}

/////////////////////////////////////////////////////////////////////////////////////
//T Curve
   if ((sub_curve_percent>=.69)&&(sub_curve_percent<0.87)) {
     sub_step_size=0.05;

   x= (width)*(start_percent + 0.69*x_size + (x_size*0.18*sub_sub_curve_percent));
   y= (height/2) - ((height/4)*(y_size))*(0.09*sin((PI/2)*((sub_sub_curve_percent/.5))));


  //Draw ellipse and update current locations
 fill(0,255,0);
 ellipse(x, y, x_ellip, y_ellip);



     clear_box_x=x;

     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location


  if   (sub_sub_curve_percent>=1.05){
    sub_curve_percent=.87;
    sub_sub_curve_percent=.05;


       }
  }


  /////////////////////////////////////////////////////////////////////////////////////////
  //Draw end Flat line
  if ((sub_curve_percent>=.87)&&(sub_curve_percent<1.0)) {
 sub_step_size=0.125/scale_factor;

   x= (width)*(start_percent + 0.86*x_size + (x_size*0.14*sub_sub_curve_percent));
   y= (height/2);
 //Draw rectangle and update current locations
 fill(0,255,0);
 rect(x-1, y-step_size*width, x_size*sub_step_size*width*.12+1, y_ellip);


      clear_box_x=x;

     //stitch curve together
  sub_sub_curve_percent=sub_sub_curve_percent+sub_step_size; //update draw location


  if   (sub_sub_curve_percent>=1.0){
    sub_curve_percent=1.0;
    sub_sub_curve_percent=0;
  }

  }



}





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Draws a straight line by drawing an ellipse at the specified location on the screen
 void straight_line(float current_percent){
    float x=0;  //Current X Location
    float y=0; //Current Y location

  x = (percent * width);
  y = (height/2);


 fill(0,255,0);
rect(x-1, y-step_size*width, step_size*width+1, y_ellip);

 }

This is a Wiki Spot wiki. Wiki Spot is a 501(c)3 non-profit organization that helps communities collaborate via wikis.