Harriss Spiral Using TurtleGraphics With Processing Arcs

The following source code will create a basic Harriss Spiral by using TurtleGraphics with Processing arcs.

//https://gist.githubusercontent.com/nataliefreed/8483050/raw/9e3f1d0f44bcb0c872762e4b984358d375e7b5fa/turtle.pde

// Turtle Graphics in Processing
// Natalie Freed, February 2013
// This program shows another way to think about moving
// through Processing's coordinate system. Instead of placing
// points on a grid, you can imagine yourself as being somewhere
// on the grid, facing a direction. You can move forward or turn.
// The drawn line follows behind you.

// Modified to use recursion September 2024
// Forward function modified to draw Processing arcs November 2024

PVector loc; //current location
float orientation; //current orientation

float h = 600; // scalable for different sized Harriss spirals
float w = (h/1.325)/1.325; // initial arc length

int rotation = -45; //initial rotation (outer arcs => inner inner arcs)
boolean showLines;

void harrissSpiral(int iteration) {
  if (iteration > 0) {
    iteration -= 1;
    showLines = false;
    forward(w,iteration); //go forward by w
    left(radians(90)); //turn x degrees to the left
    w = w/1.325;
    harrissSpiral(iteration);
  }
}

void setup() {
  size(700, 700);
  loc = new PVector(width/2 + 100, height/2 + 200); //starting position is near center
  orientation = radians(90); //starting orientation is at 90 degrees
  noLoop(); // Uses recursion
}

void draw() {
  harrissSpiral(7);
}

// ================= Turtle Graphics Functions ======================== //

//calculate positions when moving forward (modified to include arcs)
void forward(float w, int iteration) {
  PVector end = PVector.add(loc, polar(w, orientation));
  if(showLines){
   stroke(0); 
   strokeWeight(1);
   line(loc.x, loc.y, end.x, end.y);
  }
   noFill(); 
   stroke(0,0,255);
   strokeWeight(12);
   switch(iteration) { // 1.414 = sqrt(2)
     case 6: // Outer  
      arc(loc.x - w/2, loc.y - w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
     break;
    case 5:
      arc(loc.x - w/2, loc.y + w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
    break;
    case 4:
     arc(loc.x + w/2, loc.y + w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
    break; 
    case 3:
     arc(loc.x + w/2, loc.y - w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
    break;
    case 2:
     arc(loc.x - w/2, loc.y - w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
     break;
    case 1:
     arc(loc.x - w/2, loc.y + w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
     break;
    case 0: // Inner
     arc(loc.x + w/2, loc.y + w/2, w*1.414,w*1.414,radians(rotation),radians(rotation + 90));
    break; 
   }

  loc = end;
  rotation -= 90; // lines are drawn counter clockwise, arcs are drawn clockwise
}

//calculate new orientation
void left(float theta) {
  orientation += theta;
}

//calculate new orientation
void right(float theta) {
  orientation -= theta;
}

//converts an angle and radius into a vector
PVector polar(float r, float theta) {
  return new PVector(r*cos(theta), r*sin(-theta)); // negate y for left handed coordinate system
}

Output:

Design Pattern with Composite Spirals:

//https://gist.githubusercontent.com/nataliefreed/8483050/raw/9e3f1d0f44bcb0c872762e4b984358d375e7b5fa/turtle.pde

// Turtle Graphics in Processing
// Natalie Freed, February 2013

// Modified to use recursion September 2024
// Forward function modified to draw Processing arcs November 2024

PVector loc; //current location
float orientation; //current orientation
float h; // spiral size
float w; // arc length
int rotation;
boolean showLines;

int _wndW = 900; // Don't change these.
int _wndH = 700; // Will have to reposition spirals if you do.

void harrissSpiral(int iteration) {
  if (iteration > 0) {
    iteration -= 1;
    forward(w, iteration); //go forward by w
    left(radians(90)); //turn x degrees to the left
    w = w/1.325;
    harrissSpiral(iteration);
  }
}

void setup() {
  size(_wndW, _wndH);
  showLines = false;
  loc = new PVector(width/2 + 100, height/2 + 250); //starting position
  noLoop(); // Uses recursion
}

void draw() {
  // Base spiral
  h = 600; // scalable for different sized spirals
  w = (h/1.325)/1.325; // initial arc length
  rotation = -45; // initial rotation (outer arcs => inner inner arcs)
  orientation = radians(90); // starting orientation is at 90 degrees
  harrissSpiral(7);
  // Right upper spiral
  jumpTo(555, 265);
  h = 300; 
  w = (h/1.325)/1.325;
  orientation = radians(0); 
  rotation = 45;
  harrissSpiral(8);
  // Left upper spiral
  jumpTo(300, 250);
  h = 250;
  w = (h/1.325)/1.325;
  rotation = -45;
  orientation = radians(90);
  harrissSpiral(7);
  // Left lower spiral
  jumpTo(292, 453);
  h = 200;
  w = (h/1.325)/1.325;
  rotation = 225;
  orientation = radians(180);
  harrissSpiral(6);
  // Center lower spiral
  jumpTo(440, 453);
  h = 175;
  w = (h/1.325)/1.325;
  rotation = 135;
  orientation = radians(-90);
  harrissSpiral(5);
}

// **** Turtle Graphics Functions **** //

//calculate positions when moving forward (modified to include arcs)
void forward(float w, int iteration) {
  PVector end = PVector.add(loc, polar(w, orientation));
  if (showLines) {
    stroke(0);
    strokeWeight(1);
    line(loc.x, loc.y, end.x, end.y);
  }
  noFill();
  //stroke(0, 0, 255);
  stroke(random(255),0,random(255));
  strokeWeight(12);
  // 1.414 = sqrt(2)
  if ((iteration == 7) || (iteration == 3)) {
    arc(loc.x + w/2, loc.y - w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
  }
  if ((iteration == 6) || (iteration == 2)) {
    arc(loc.x - w/2, loc.y - w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
  }
  if ((iteration == 5) || (iteration == 1)) {
    arc(loc.x - w/2, loc.y + w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
  }
  if ((iteration == 4) || (iteration == 0)) {
    arc(loc.x + w/2, loc.y + w/2, w*1.414, w*1.414, radians(rotation), radians(rotation + 90));
  } 
  loc = end;
  rotation -= 90; // lines are drawn counter clockwise, arcs are drawn clockwise 
}

//calculate new orientation
void left(float theta) {
  orientation += theta;
}

//calculate new orientation
void right(float theta) {
  orientation -= theta;
}

//jump directly to a specific position
void jumpTo(int x, int y) {
  loc = new PVector(x, y);
}

//converts a radius and an angle into a vector
PVector polar(float r, float theta) {
  return new PVector(r*cos(theta), r*sin(-theta)); // negate y for left handed coordinate system
}

Output:

2 Likes