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: