Student Area

lsh-LostrittoReading

Lostritto tackles the question of “what is drawing?” in an interesting way. Defining the concept of drawing by its negative is fascinating, but in many ways also reflects the influence of architecture on the writing. Whereas artists tend to focus more on evaluating if a work is good art rather than the binary understanding of “art” or “not art,” the dialogue of what built structures get to call themselves architecture continues to this day. Nikolaus Pevsner famously said

A bicycle shed is a building; Lincoln Cathedral is a piece of architecture.

Lostritto even hits upon this issue, stating

without limits, it’s easy to see how almost anything can be a drawing.

Maybe almost anything can be a drawing.

lsh-PlotterSkimming

The Licia He article was particularly delightful. I resonated with the the “finding your way back” section, since sometimes these n day challenges can feel more like forcing out art than creating it. A theme I see across the articles is artists experimenting with process to find what toolkits allow themselves to express their ideas with the least friction.

lsh-LineExercises

I decided to do the following exercises in Rust as a technical challenge. This proved to be a little bit more of an undertaking than I expected, so here are some notes on some of the hurdles I ran into.

I decided to use nannou for most of the exercises, since I did not want to attempt implementing each interaction I needed in WGPU. Nannou seems incredibly powerful, but the guide left much to be desired (when they become more complete I will definitely come back for another look!). Figuring out registering the events I cared about took a significant amount of searching, since the guide did not seem to document it. Eventually I ended up using the all_functions example as a base and removing everything I didn’t care about. The second quirk that came up was nannou’s coordinate system, which puts the origin at the center of the screen. This proved to be problematic later on as I moved to SVG.

Rust also is completely opposed to implicit casts, which is fair, but also meant a lot of code was shifting between data structures. This was particularly apparent in managing the points for lines, which required taking the VecDeque.to_owned() each frame for drawing the polyline.

The SVG generation was its own ordeal. Nannou’s line builder seems to use the lyon package for SVG rendering. Lyon however does not allow actually exporting an SVG, so I ended up using the svg crate. It is also worth mentioning that the svg crate seems to be set up in a way which makes it hard to create SVGs programmatically. Specifically, I had to define the “Data” element mutable and constantly reassign it to the result of data.move_to() or data.line_to().

All in all, I would say the technical challenge was fun to play with, but I would not recommend this method over more mature frameworks like Processing or openFrameworks.

Feel free to check out the code behind the images above on GitHub.

grape – LineExercises

A.

/* Basically I used the example code from the lerp() page on Processing
 * but changed it so it would produce dotted lines for any random
 * pair of vectors
 * */
float dashed_length = 20;

void setup(){
  size(400, 400);
  background(100);
}

void draw(){
  background(255);
  int x1 = int(random(0,width));
  int x2 = int(random(0,width));
  int y1 = int(random(0,height));
  int y2 = int(random(0,height));
  
  float ydif = y2-y1;
  float xdif = x2-x1;
  float num_lines = sqrt(pow(ydif,2) + pow(xdif,2))/dashed_length;
  print(num_lines);
  
  for (int i = 0; i <= int(num_lines); i+=2) {
    float dx1 = lerp(x1, x2, i/num_lines) + num_lines;
    float dx2 = lerp(x1, x2, (i+1)/num_lines) + num_lines;
    float dy1 = lerp(y1, y2, i/num_lines);
    float dy2 = lerp(y1, y2, (i+1)/num_lines);
    line(dx1, dy1, dx2, dy2);
  }
  noLoop();
}

B.

C.

/**
 * I basically altered the brownian motion tutorial from Processing
 * to record mouseX, mouseY instead of random movement.
 */
 
int num = 100;
int range = 6;

float[] ax = new float[num];
float[] ay = new float[num]; 
float[] dx = new float[num];
float[] dy = new float[num];
// float[][] a = new float[num][2]; // LIVING LINE 2D ARRAY
// PVector[] a = new PVector[num]; // LIVING LINE PVECTORS
void setup() 
{
  size(640, 360);
  for(int i = 0; i < num; i++) {
    ax[i] = width/2;
    ay[i] = height/2;
    dx[i] = 0;
    dy[i] = 0;
  }
  /* LIVING LINE PVECTORS
  for(int i = 0; i < num; i++) {
    a[i] = new PVector();
    a[i].x = width/2;
    a[i].y = height/2;
  }
  */
  /* LIVING LINE 2D ARRAY
  for(int i = 0; i < num; i++){
    for(int j = 0; j < 2; j++){
      a[i][j] = width/2;
    }
  }
  */
  frameRate(30);
}

void draw() 
{
  background(255);
  
  // Shift all elements 1 place to the left
  for(int i = 1; i < num; i++) {
    dx[i-1] = dx[i];
    dy[i-1] = dy[i];
    ax[i-1] = ax[i];// + random(-range, range); SPICY LINE COMMENT
    ay[i-1] = ay[i];// + random(-range, range); SPICY LINE COMMENT
  }
  /* LIVING LINE PVECTORS
  for(int i = 1; i < num; i++) {
    a[i-1].x = a[i].x;
    a[i-1].y = a[i].y;
  }
  */
  /* // LIVING LINE 2D ARRAY
  for(int i = 1; i < num; i++){
    a[i-1][0] = a[i][0]; 
    a[i-1][1] = a[i][1];
  }
  */
  // Put a new value at the end of the array
  ax[num-1] = mouseX;
  ay[num-1] = mouseY;
  dx[num-1] = (ax[num-1] - ax[num-2]);
  dy[num-1] = (ay[num-1] - ay[num-2]);
  // a[num-1][0] = mouseX; // LIVING LINE 2D ARRAY
  // a[num-1][1] = mouseY; // LIVING LINE 2D ARRAY
  // a[num-1].x = mouseX; // LIVING LINE PVECTORS
  // a[num-1].y = mouseY; // LIVING LINE PVECTORS
  // Constrain all points to the screen
  //ax[num-1] = constrain(ax[num-1], 0, width);
  //ay[num-1] = constrain(ay[num-1], 0, height);
  
  // Draw a line connecting the points
  for(int i=1; i<num; i++) {    
    line(ax[i-1], ay[i-1], ax[i], ay[i]);
    // line(a[i-1].x, a[i-1].y, a[i].x, a[i].y); // LIVING LINE PVECTORS
    // line(a[i-1][0],a[i-1][1],a[i][0],a[i][1]); // LIVING LINE 2D ARRAY
  }
}

D.

E.

float r = 40;


void setup(){
  size(400, 400);
  background(100);
}

void draw(){
  background(255);
  translate(width/2, height/2);
  //trig_circle();
  trig_spiral();
  noLoop();
}

void trig_spiral(){
  beginShape();
  for(float i = 1; i < 40; i+=0.05){
    vertex(cos(i)*(r), sin(i)*(r));
    r+=0.2;
  }
  endShape();
}

void trig_circle(){
  beginShape();
  for(float i = 1; i < 360; i+=1){
    vertex(cos(i)*(r), sin(i)*(r));
  }
  endShape();
}

F. I got tired of math so I made a shitty offset curve – not parallel, just the normal vector of the slope

int num = 100;
int range = 6;

float[] ax = new float[num];
float[] ay = new float[num]; 
float[] dx = new float[num];
float[] dy = new float[num];
float[] ox = new float[num];
float[] oy = new float[num]; 
void setup() 
{
  size(640, 360);
  for(int i = 0; i < num; i++) {
    ax[i] = width/2;
    ay[i] = height/2;
    dx[i] = 0;
    dy[i] = 0;
    ox[i] = width/2;
    oy[i] = height/2;
  }
  frameRate(30);
}

void draw() 
{
  background(255);
  
  // Shift all elements 1 place to the left
  for(int i = 1; i < num; i++) {
    dx[i-1] = dx[i];
    dy[i-1] = dy[i];
    ax[i-1] = ax[i];
    ay[i-1] = ay[i];
    ox[i-1] = ox[i];
    oy[i-1] = oy[i];
  }
  // Put a new value at the end of the array
  ax[num-1] = mouseX;
  ay[num-1] = mouseY;
  dx[num-1] = (ax[num-1] - ax[num-2]);
  dy[num-1] = (ay[num-1] - ay[num-2]);
  //dksjfldkjslkdfjlsdj i hate this
  //ox[num-1] = 25/(1+pow((ay[num-1] + dx[num-1])/(ax[num-1] - dy[num-1]),2));
  //oy[num-1] = sqrt(25 - pow(ox[num-1],2));
  ox[num-1] = ax[num-1] - dy[num-1];
  oy[num-1] = ay[num-1] + dx[num-1];
  
  // Draw a line connecting the points
  for(int i=1; i<num; i++) {    
    //float val = float(i)/num * 204.0 + 51;
    //stroke(val);
    line(ax[i-1], ay[i-1], ax[i], ay[i]);
    //float dx = 25/(1+pow(ay[num-1] + dx[num-1]/ax[num-1] - dy[num-1]),2));
    //float dy = sqrt(25 - pow(dx,2));
    line(ox[i-1], oy[i-1], ox[i], oy[i]);
  }
}

G.

i was watching a lot of gordon ramsey

H.

“bears beets battlestar galactica”

import processing.svg.*;
int num = 1000;
int range = 6;

boolean record = false;

float[] ax = new float[num];
float[] ay = new float[num]; 
float[] dx = new float[num];
float[] dy = new float[num];
float[] ox = new float[num];
float[] oy = new float[num]; 

int num_lines = 5;
void setup() 
{
  size(640, 360);
  for(int i = 0; i < num; i++) {
    ax[i] = width/2;
    ay[i] = height/2;
    dx[i] = 0;
    dy[i] = 0;
    ox[i] = width/2;
    oy[i] = height/2;
  }
  frameRate(30);
}

void draw() 
{
  background(255);

  // Shift all elements 1 place to the left
  for(int i = 1; i < num; i++) {
    dx[i-1] = dx[i];
    dy[i-1] = dy[i];
    ax[i-1] = ax[i];
    ay[i-1] = ay[i];
    ox[i-1] = ox[i];
    oy[i-1] = oy[i];
  }
  // Put a new value at the end of the array
  ax[num-1] = mouseX;
  ay[num-1] = mouseY;
  dx[num-1] = (ax[num-1] - ax[num-2]);
  dy[num-1] = (ay[num-1] - ay[num-2]);
  
  // Draw a line connecting the points
  if(record){
    int now = millis();
    randomSeed(now);
    beginRecord(SVG, "foo_" + now + ".svg");
  }
  for(int i=1; i<num; i++) {    
    float mult = map(dx[i] + dy[i], 0, width+height, 1, 60);
    for(int j = 0; j < num_lines; j++){
      line(ax[i-1] - j*mult, ay[i-1], ax[i] - j*mult, ay[i]);
    }

  }
  if(record){
    endRecord();
    record = false;
  }
}

void keyPressed() {
  record = true;
}

BUT, then I added some perpendicular lines instead:

import processing.svg.*;
int num = 1500;
int range = 6;

boolean record = false;

float[] ax = new float[num];
float[] ay = new float[num]; 
float[] dx = new float[num];
float[] dy = new float[num];
float[] ox = new float[num];
float[] oy = new float[num]; 

int num_lines = 15;
void setup() 
{
  size(640, 640);
  for(int i = 0; i < num; i++) {
    ax[i] = width/2;
    ay[i] = height/2;
    dx[i] = 0;
    dy[i] = 0;
    ox[i] = width/2;
    oy[i] = height/2;
  }
  frameRate(30);
}

void draw() 
{
  background(255);

  // Shift all elements 1 place to the left
  for(int i = 1; i < num; i++) {
    dx[i-1] = dx[i];
    dy[i-1] = dy[i];
    ax[i-1] = ax[i];
    ay[i-1] = ay[i];
    ox[i-1] = ox[i];
    oy[i-1] = oy[i];
  }
  // Put a new value at the end of the array
  ax[num-1] = mouseX;
  ay[num-1] = mouseY;
  dx[num-1] = (ax[num-1] - ax[num-2]);
  dy[num-1] = (ay[num-1] - ay[num-2]);

  // Draw a line connecting the points
  if(record){
    int now = millis();
    randomSeed(now);
    beginRecord(SVG, "foo_" + now + ".svg");
  }
  for(int i=1; i<num; i++) {    
    float d_lines = int(map(dx[i] + dy[i],-200, 200, 0,num_lines));
    for(float j = 0; j < d_lines; j++){
      float multx1 = lerp(ax[i], ax[i-1], j/d_lines);
      float multx2 = lerp(ax[i]-dy[i], ax[i-1] - dy[i-1], j/d_lines);
      float multy1 = lerp(ay[i], ay[i-1], j/d_lines);
      float multy2 = lerp(ay[i] + dx[i], ay[i-1] + dx[i-1], j/d_lines);
      line(multx1, multy1, multx2, multy2);
    }
  }
  if(record){
    endRecord();
    record = false;
  }
}

void keyPressed() {
  record = true;
}

sweetcorn – LineExercises

int[] mouseCoordsX = new int[100];
int[] mouseCoordsY = new int[100];
PVector[] mouseCoords = new PVector[100];
PVector[] offsetCoords = new PVector[100];
int coordIndex = 0;
float growingNoise = 0;
boolean record;

import processing.svg.*;

void setup() {
  size(600, 600);
  stroke(255);
  strokeWeight(1);
  noFill();

  background(0);
}

void draw() {
}

void drawShakyLine() {
  growingNoise += 0.01;
  drawLivingLine(1, growingNoise);
}

void drawCircle(int mode) {
  float radius = (sqrt(pow(mouseX-(width/2), 2) + pow(mouseY - (height/2), 2)));

  if (mode == 0) {
    curveTightness(-0.7);
    beginShape();
    for (int i=0; i<2; i++) {
      curveVertex(radius + width/2, radius + height/2);
      curveVertex(radius + width/2, -radius + height/2);
      curveVertex(-radius + width/2, -radius + height/2);
      curveVertex(-radius + width/2, radius + height/2);
    }
    curveTightness(0);
    endShape();
  } else {
    push();
    translate(width/2 + 4*radius, height/2);
    float step = PI/12;
    for (float i=0; i<2*PI; i+=step) {
      rotate(step);
      translate(0, radius);
      line(0, 0, 0, -radius);
    }
    pop();
  }
}

void drawSpiral() {
  curveTightness(-0.7);
  beginShape();
  push();
  translate(width/2, height/2);
  float step = PI/12;
  for (float i=0; i<12*PI*mouseX/width; i+=step) {
    rotate(step);
    translate(0, i);
    line(0, 0, 0, -i);
  }
  pop();
}

void drawCalligraphicLine() {
  int lineSize = 10;

  beginShape();
  for (var i=lineSize; i<coordIndex-lineSize; i++) {

    float perpX = mouseCoords[i+lineSize].y - mouseCoords[i-lineSize].y;
    float perpY = mouseCoords[i-lineSize].x - mouseCoords[i+lineSize].x;

    float thickness = 200/sqrt(pow(perpX, 2) + pow(perpY, 2));

    float dist = sqrt(pow(perpX, 2) + pow(perpY, 2));

    perpX *= thickness/dist;
    perpY *= thickness/dist;

    offsetCoords[i] = new PVector(mouseCoords[i].x - perpX, mouseCoords[i].y - perpY);

    curveTightness(8);
    if (i%2 == 0) {
      curveVertex(offsetCoords[i].x, offsetCoords[i].y);
    } else {
      curveVertex(mouseCoords[i].x, mouseCoords[i].y);
    }
    curveTightness(0);
  }
  endShape();
}

void drawLineSeries() {
  push();
  translate(0, height/6);
  drawThickLine(1, width/6, 0, 5*width/6, 0);
  translate(0, height/6);
  drawThickLine(10, width/6, 0, 5*width/6, 0);
  translate(0, height/6);
  drawThickLine(20, width/6, 0, 5*width/6, 0);
  translate(0, height/6);
  drawThickLine(30, width/6, 0, 5*width/6, 0);
  translate(0, height/6);
  drawThickLine(40, width/6, 0, 5*width/6, 0);
  translate(0, height/6);
  drawThickLine(50, width/6, 0, 5*width/6, 0);
  pop();
}

void keyPressed() {
  if(key == 's') {
    record = true;
  }
}

void drawThickLine(int thickness, int x1, int y1, int x2, int y2) {
  int lineSize = 10;

  beginShape();
  for (var i=lineSize; i<coordIndex-lineSize; i++) {
    float perpX = mouseCoords[i+lineSize].y - mouseCoords[i-lineSize].y;
    float perpY = mouseCoords[i-lineSize].x - mouseCoords[i+lineSize].x;

    float dist = sqrt(pow(perpX, 2) + pow(perpY, 2));

    perpX *= thickness/dist;
    perpY *= thickness/dist;

    offsetCoords[i] = new PVector(mouseCoords[i].x - perpX, mouseCoords[i].y - perpY);

    curveTightness(8);
    if (i%2 == 0) {
      curveVertex(offsetCoords[i].x, offsetCoords[i].y);
    } else {
      curveVertex(mouseCoords[i].x, mouseCoords[i].y);
    }
    curveTightness(0);
  }
  endShape();
}

void mouseMoved() {
  background(0);
  
  if (record) {
    // Note that #### will be replaced with the frame number. Fancy!
    beginRecord(SVG, "frame-####.svg");
  }

  //drawDashedLine(); // 1
  //drawLivingLine(0, 0); // 2.1
  //drawLivingLine(1, 0); // 2.2
  //drawShakyLine(); // 3
  //drawCircle(0); // 4.1
  //drawCircle(1); // 4.2
  //drawSpiral(); // 5
  //drawLivingLine(2, 0); // 6
  //drawThickLine(0, 50); // 7.1
  //drawThickLine(1, 50); // 7.2
  //drawCalligraphicLine(); // 8
  drawLineSeries();

  if (coordIndex < 99) {
    coordIndex++;
  }

  mouseCoordsX[coordIndex] = mouseX;
  mouseCoordsY[coordIndex] = mouseY;

  mouseCoords[coordIndex] = new PVector(mouseX, mouseY);

  for (var i=0; i<coordIndex; i++) {
    mouseCoordsX[i] = mouseCoordsX[i+1];
    mouseCoordsY[i] = mouseCoordsY[i+1];

    mouseCoords[i] = mouseCoords[i+1];
  }
  
  if (record) {
    endRecord();
    record = false;
  }
}

void drawLivingLine(int mode, float noise) {
  beginShape();
  if (mode == 0) {
    for (var i=0; i < coordIndex; i++) {
      vertex(mouseCoordsX[i] + noise*randomGaussian(), mouseCoordsY[i] + noise*randomGaussian());
    }
  } else if (mode == 1) {
    for (var i=0; i < coordIndex; i++) {
      vertex(mouseCoords[i].x + noise*randomGaussian(), mouseCoords[i].y + noise*randomGaussian());
    }
  } else if (mode == 2) {
    for (var i=0; i < coordIndex; i++) {
      vertex(mouseCoords[i].x + noise*randomGaussian(), mouseCoords[i].y + noise*randomGaussian());
    }
    endShape();
    beginShape();
    int offset = 100;
    int lineSize = 10;
    for (var i=lineSize; i < coordIndex-lineSize; i++) {
      float perpX = mouseCoords[i+lineSize].y - mouseCoords[i-lineSize].y;
      float perpY = mouseCoords[i-lineSize].x - mouseCoords[i+lineSize].x;

      float dist = sqrt(pow(perpX, 2) + pow(perpY, 2));

      perpX *= offset/dist;
      perpY *= offset/dist;

      vertex(mouseCoords[i].x - perpX, mouseCoords[i].y - perpY);
    }
  }
  endShape();
}

void drawThickLine(int mode, int thickness) {
  int lineSize = 10;

  beginShape();
  for (var i=lineSize; i<coordIndex-lineSize; i++) {
    float perpX = mouseCoords[i+lineSize].y - mouseCoords[i-lineSize].y;
    float perpY = mouseCoords[i-lineSize].x - mouseCoords[i+lineSize].x;

    float dist = sqrt(pow(perpX, 2) + pow(perpY, 2));

    perpX *= thickness/dist;
    perpY *= thickness/dist;

    offsetCoords[i] = new PVector(mouseCoords[i].x - perpX, mouseCoords[i].y - perpY);

    if (mode == 0) {
      curveTightness(8);
      if (i%2 == 0) {
        curveVertex(offsetCoords[i].x, offsetCoords[i].y);
      } else {
        curveVertex(mouseCoords[i].x, mouseCoords[i].y);
      }
      curveTightness(0);
    } else if (mode == 1) {
      for (int j=0; j<thickness; j+=thickness/20) {
        if (j%thickness/40 == 0) {
          vertex(offsetCoords[i].x + j, offsetCoords[i].y);
        } else {
          vertex(mouseCoords[i].x, mouseCoords[i].y);
        }
      }
    }
  }
  endShape();
}

void drawDashedLine() {
  push();
  rotate(atan2(mouseY, mouseX));
  for (var i=0; i<sqrt(pow(mouseY, 2) + pow(mouseX, 2)); i+=20) {
    line(i, 0, i+10, 0);
  }
  pop();
}

lemonbear—LostrittoReading

Like many of my classmates, I was particularly drawn to the claim that “When one marks on paper, for example, one can erase those marks, but that is actually another kind of marking that involves the interaction of material.” Lostritto makes the argument that physical drawings store a visual record of their entire history, as opposed to “drawing” in digital software, where lines and forms might be done and undone discreetly. Though I don’t entirely subscribe to the stark division between human-produced and computer-produced artwork, I like the questions which arise from viewing traditional work as a “drawing” and computed work as a “model”. What’s the difference between a model and its realization? For some media, like pen and paper, the distinction is slim. But for watercolor or acrylic, the analog-space randomness of the physical work manifests the model in novel ways, their physical properties producing inspiring aesthetics.

lemonbear-PlotterSkimming

I really liked Licia He’s article. One thing in particular that stuck out to me was the mentality of repetition and habit building that she acquired by doing her 300+ days of plotter art, and how she connected this mentality to the iteration and discipline inherent in plotter art itself. To get better at making a robot do a lot of precise tasks over and over again, you have to hone your skills by waking up and deciding to make art over and over again, and the parallelism of those acts was not lost on me.

stickz – LineWalk

 



I was interested in creating a line that expresses a human-like scribble that has the stroke appearance of a 0.5mm ball point pen. I messed around with sine and cosine functions that ended up creating anelliptical, vortex-like, scribble that has a direction that varies with noise, where a new drawing is constantly generated (hitting the spacebar starts and stops the generating of new drawings) 

 

//applies the noise function in creating randomness
// Uses https://github.com/zenozeng/p5.js-svg to export SVG.

var bExportSvg = false;
var runDrawing = true;

function setup() {
  createCanvas(600, 600, SVG);
}

function draw() {
  if (runDrawing == true) {
    background(230);
    if (bExportSvg) clear();
    strokeWeight(0.2);
    noFill();

    var cx = width / 2;
    var cy = height / 2;
    var px = cx;
    var py = cy;

    var direction = random(PI / 2, PI);

    beginShape();

    for (var i = 0; i < 2000; i++) {
      var increment = 3 + noise(i / 1000);
      var displacementX = px - cx;
      var displacementY = py - cy;
      var offset = max(3, sqrt(displacementX ** 2 + displacementY ** 2) / 20);
      increment *= 0.7 * offset;
      direction += radians(50 * (noise(i) - 10));

      px += 5 * noise(i) * increment * cos(200 * direction);
      py += 5 * noise(i) * increment * sin(200 * direction);

      var pointX = cx + displacementX * offset ** -0.8;
      var pointY = cy + displacementY * offset ** -0.8;

       
      vertex(pointX, pointY);
    }

    endShape();
    var seed = millis()**0.5;
    randomSeed(seed);
    noiseSeed(seed); //random noise value generated for each drawing coordinated with the seconds function, inspired by Golan Levin's Linewalk
    loop();
  }
  if (bExportSvg) {
    saveSVG("stickz_line_on_a_walk.svg");
    bExportSvg = false;
  } 
}

function keyPressed() {
  if (key == "s") {
    bExportSvg = true;
    loop();
  }
  if (keyCode === 32) { //if SPACEBAR is pressed, pause drawing
    if (runDrawing == false) runDrawing = true;
    else runDrawing = false;
  }
}
link to code

Stickz – LostrittoReading

I thought the way Lostritto defined drawing with anti-definitions was a unique and accurate way of describing the definition of drawing. For one thing, I liked how he made it clear that digital drawings should not be considered drawings, even if they are forms derived from digital paper and pen. The idea of perfecting “undoing” a drawn mark is not possible with physical drawing, which separates the physical practice from digital drawing. I also think the way he states how “computing technology can augment, but not replace, drawing technology” is another great point that distinguishes the characteristics of drawing, where the act of drawing will forever be a human task, even if machines can assist and do the work for us. I think the idea that drawing is done by humans will stick with me for the rest of the course, where I hope my drawings will keep the human characteristic and read as something created by myself, rather than one created by a machine.

Stickz – PlotterSkimming

In reading Tyler Hobb’s article 9 Tips to Execute Generative Art With a Plotter, I learned that he applies a “sorting algorithm” to increase the efficiency of plotting time, which I think is really interesting and another factor to consider when creating generative art with Axi-Draws.

In the reading “Pen Plotter Art & Algorithms”, by Matt Deslauriers, I found the convex-hull module to be a helpful tool used to create polygons, where it draws them based on a data set of points. I will definitely try this out and experiment with the convex-hull module in creating recursive drawings.