Sepho – Interruptions

  1. the artwork is square.
  2. the work is made of many small black lines on a white background.
  3. the lines are of the same length.
  4. the lines are all turned at different angles.
  5. the lines slightly intersect occasionally.
  6. there are occasional gaps in the lines.
  7. the lines do not touch the edge of the page
  8. most of the lines point in the same direction.
  9. the lines seem to almost be in a grid pattern with a few exceptions.
  10. there are occasionally multiple lines coming from the same point

////// based on Starter Code for "Embedded Iteration + Randomness"
var boolDoRefresh;
 
function setup() {
  createCanvas(720, 720);
  background(255,255,255)
  noStroke();
  boolDoRefresh = true;
}
 
var length = 25;
var gridSize = 15;
var lines = []
var gaps = []

//adds gaps in the lines
function addGap(gaps, x ,y){
  print(x);
  var r = random(100 * noise(x,y));
  gaps.push([x,y,r]);
}
            
function distance(x1,y1,x2,y2){
    return sqrt(sq(x2-x1) + sq(y2-y1));
  }
  

function addLine(lines, x1, y1){
  var theta = random(360);
  var x2 = x1 + (cos(theta) * length);
  var y2 = y1 + (sin(theta) * length);
  lines.push([x1,y1,x2,y2]);
}


function draw() {
  if (boolDoRefresh) {
    // DRAW STUFF HERE....
    boolDoRefresh = false;
    background(255,255,255)
    lines = [];
    gaps = [];
    fill(255,0,0);
    
	//creates new gaps on each click
    for(var x = gridSize; x <= width - gridSize; x += gridSize){
      for(var y = gridSize; y <= height - gridSize; y += gridSize){ if(noise(x,y) > 0.82 && random(4) > 3){
        	addGap(gaps,x,y);
        }
      }
    }
    
    strokeWeight(1.5);
    stroke(0);
    
  //creates and draws new lines on each click
    for(var x1 = gridSize; x1 <= width - gridSize; x1 += gridSize){
      for(var y1 = gridSize; y1 <= height - gridSize; y1 += gridSize){
        var isInGap = false;
        for(var i = 0; i < gaps.length; i++){
          if(distance(x1,y1,gaps[i][0],gaps[i][1]) < random(50,70)){
            isInGap = true;
          }
        }
        if(!isInGap){
        	var theta = random(360);
  				var x2 = x1 + (cos(theta) * length);
  				var y2 = y1 + (sin(theta) * length);
       		line(x1,y1,x2,y2);
        }
      }
    }
    
    
    
  }
}
 
function mousePressed() {
  boolDoRefresh = true;
}
  1. In an attempt to replicate this piece I first started with a grid of dots and then I drew short lines coming from those dots at various angles. I then used the noise() function to try and make a Perlin-noise like gap in the lines. For me the hardest part about replicating this work was the grid-like but not perfect grid that she managed to create and also a very kind of natural and abstract way of creating gaps in her lines. Additionally her lines really only intercept each other ever so slightly while mine can completely cross each other. Overall it was way more challenging to recreate this piece than I initially thought.

airsun-Interruptions

This project is tricky at first because I was not really sure about how to use the concept of noise as a primary function in accomplishing the assignment. It was interesting to really understand this concept throughout the project. And it is also interesting to see how some basic math concepts such as cosine and sine were also part of the knowledge we may need for the assignment. Moreover, the finishing product can be very artistic or rational based on individual choices, with all the lines bending and connecting each other like hairs or strictly similar to the original one.

//Clair(sijing) Sun
//sijings@andrew.cmu.edu


// Starter Code for "Embedded Iteration + Randomness"


var boolDoRefresh;
var n=0;
var randomD;
var gridSize = 9;
var degreeR;
var lineLength=17;
var xoff=0.5;
var poff=0.01;

function setup() {
    createCanvas(480, 480);
    boolDoRefresh = false;
    
}


function draw(){
    background(250);
    for (var x = gridSize; x <= width - gridSize; x += gridSize) {
            for (var y = gridSize; y <= height - gridSize; y += gridSize) {
                angleMode(DEGREES);
                degreeR=noise(x*xoff,y*xoff);
                degreeR=degreeR*180;
                randomD=noise(x*poff,y*poff);
                if (randomD < 0.65){
                    line(x, y, x+cos(degreeR)*lineLength, y+sin(degreeR)*lineLength);  
                }

        }
    }
}


 
function mousePressed() {
    noiseSeed();
    redraw();
}
 


chaine-Interruptions

  1.  The lines' centers can be split into a grid system
  2.  All angles are randomized
  3.  White or light grayish background with black lines
  4. The overall shape of the canvas is a square but some lines may protrude a bit more
  5.  There are clutters of gaps that seem to happen in random locations
  6.  The gaps are usually clumped together and are missing more than one line per gap
  7.  Each gap seem to form into random shapes (not just a circle, square, etc.)
  8.  The gaps are of varying sizes
  9.  The length of each line is the same
  10.  There is a very small margin surrounding the lines

Image from Gyazo

 

var boolDoRefresh;
var size = 40;
var gridSpacing = 12; 
var lineLength = 20;
var angleList = [];
var startAngle = 0;
 
//Things to consider while creating "gaps":
//how many gaps?
//how large are the gaps?
//which row/col are the gaps located?
 
var gapList = [];
 
function setup(){
  createCanvas(720,720);
  boolDoRefresh = true;
  var slant = random(0,1);
  var isVertical = random(0,1);
  for (var i = 0; i &lt; width + lineLength; i += gridSpacing){
    for (var j = 0; j &lt; height + lineLength; j += gridSpacing){
    if (isVertical &lt; 0.5){
      append(angleList, random(-1*PI, PI)); //angle of line horizontal
    }
    else{
      append(angleList, random(-1*PI, PI) + (PI)); //angle of line vertical
    }
  }
  }
  createGaps();
}
 
function createGaps(){
  var gridSlots = sq(round(((width + lineLength + 1)/gridSpacing)))
  var numGap = int(random(3,15));
  for (var k = 0; k < numGap; k += 1){
    gapList = append(gapList, int(random(1, gridSlots)));
    gapSize = int(random(10,80));
    for (var m = 1; m < gapSize; m += 1){
      chance = random(0,1);
      if (random(0,1) < 0.8){
        if (chance < 0.4){
          append(gapList, gapList[m-1] + 1);
        }
        else{
          append(gapList, gapList[m-1] - 1);
        }
      }
      else{
        if (chance < 0.6){
          append(gapList, gapList[m-1] + 59);
        }
        else{
          append(gapList, gapList[m-1] - 59);
        }
      }
      for (var n = 0; n < gapList.length; n += 1){
        angleList[gapList[n]] = 1000;
      }
    }
    gapList = [];
  }
}
 
function draw(){
  if (boolDoRefresh){
    for (var i = lineLength; i &lt; width - lineLength; i += gridSpacing){
      for (var j = lineLength; j &lt; height - lineLength; j += gridSpacing){
        strokeWeight(1);
        //ellipse(i,j, 5,5);
        var angle = angleList[startAngle];
        if (angle &lt; 999){
          //I gave each line their own little "squares" on a grid of W x H
          //Each grid consists of two lines, one line is a reflection of the other line
          //Both lines start at the center of their "squares"
          //Thus, the two lines together look like one line
          line(i, j , i+(lineLength/2)*cos(angle), j+(lineLength/2)*sin(angle));
          line(i, j , i+(lineLength/2)*cos(angle+PI), j+(lineLength/2)*sin(angle+PI));
        }
        startAngle += 1;
      }
    }
  }
  boolDoRefresh = false;
}
 
function mousePressed(){
  boolDoRefresh = true;
  angleList = [];
  startAngle = 0;
  gapList = [];
  setup();
}

I started this project by realizing that there was some sort of grid system with a randomized, angled line in each grid unit. I first decided to code the overall grid without any gaps, but realized that too many of the lines started to look like they were forming messy clusters. (e.g. one grid unit had a line pointing to the right and the very next grid unit to the right was pointing left and it just looked like two lines on top of each other) Therefore, I decided to give each line their own square "space" by drawing two lines to look like one. I first drew half of a line starting from the center of a grid unit and reflected it to draw the other half. That worked out much better. Meanwhile, for randomizing the gaps, I sketched out what I needed to know: how many gaps, how large each gap is, where the gap is. I learned that what I thought was random was clearly showing that it didn't feel as random in real life. There were sometimes columns of missing lines and I struggled to find the right proportion of hiding the aforementioned patterns. I learned through this that coding was a test of trial and error and logic. What may seem logically sound on paper may not look it in the actual product. The fact that Vera Molnár created this piece fascinated and inspired me, especially given the time period in which she created this.

 

shuann-Interruptions

  1. The artwork is square.
  2. The artwork consists of many short black lines, on a white background.
  3. The lines all have the same length.
  4. Overall there seems to be a general direction, horizontal or vertical, that all the lines follow (noise exists obviously)
  5. However each line by itself seems to have a somewhat random direction that it points to
  6. every line overlaps with the previous line at the half-point mark
  7. There are empty holes in the piece, where there are no lines
  8. The empty spots where lines are skipped are clustered together
  9. The exact positions of the holes seem random
  10. The size of the holes are also random

GIF:

Process:

I personally think the result is pretty satisfactory especially given the fact that I was able to really get a good understanding of what noise is and how to use it through the completion of this project. I started by creating an invisible grid system where each of the grid contains a simple straight line. Then I randomly rotate each lines separately using translate and push and pop. Lastly, to create the holes I had to understand noise which I found very challenging at first. Partly because the documentation on the p5.js site were not super great at explaining the concept in plain, understandable language. However, after learning it I realized how adaptive noise can be, and I can already see how it can be used in many other cases.

Spoon-Interruptions

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  var boolDoRefresh;
  const CANV_HEIGHT = 720;
  const CANV_WIDTH = 720;
  const H_MARGIN = CANV_WIDTH / 14;
  const V_MARGIN = CANV_HEIGHT / 14;
  const V_NUM_LINES = 56;
  const H_NUM_LINES = 56;
  const H_UNIT_SIZE = (CANV_WIDTH - (H_MARGIN * 2)) / H_NUM_LINES;
  const V_UNIT_SIZE = (CANV_HEIGHT - (V_MARGIN * 2)) / V_NUM_LINES;
  const LINE_LENGTH = H_UNIT_SIZE * 2;
  const HORIZONTAL_FREQ = 0.25;
 
  function setup() {
    createCanvas(720, 720);
    background('#EEEEEE');
    strokeWeight(0.75);
    boolDoRefresh = true;
  }
 
  function draw() {
    if(boolDoRefresh) {
      background('#EEEEEE');
      constructLines();
      boolDoRefresh = false;
    }
  }
 
  function mousePressed() {
    boolDoRefresh = true;
  }
 
  function constructLines() {
    var angleOff = random(0.2);
    var gapX = random(0.5);
    var gapY = random(0.5);
    var gapScale = 0.15;
    noiseSeed(random(100));
    var horizontal = random(1);
    for(var i = 0; i < H_NUM_LINES; i++) {
      for(var j = 0; j < V_NUM_LINES; j++) {
        angleOff += 0.1;
        gapX += i * gapScale;
        gapY += j * gapScale;
        if(noise((i * gapScale), (j * gapScale)) > 0.25) {
          var angle = random(noise(angleOff) * 90);
          centerLine(H_MARGIN + i * H_UNIT_SIZE, V_MARGIN + j * V_UNIT_SIZE, LINE_LENGTH, angle, horizontal);
        }
      }
    }
  }
 
  function centerLine(x, y, length, angle, horizontal) {
    angleMode(DEGREES);
    var randNum = random(2);
    var x1 = x + ((length / 2) * (horizontal < HORIZONTAL_FREQ ? cos(angle) : sin(angle)));
    var y1 = y + ((length / 2) * (horizontal < HORIZONTAL_FREQ ? sin(angle) : cos(angle)) * (randNum > 1 ? 1 : -1));
    var x2 = x - ((length / 2) * (horizontal < HORIZONTAL_FREQ ? cos(angle) : sin(angle)));
    var y2 = y + ((length / 2) * (horizontal < HORIZONTAL_FREQ ? sin(angle) : cos(angle)) * (randNum > 1 ? -1 : 1));
    line(x1, y1, x2, y2);
  }

 

Process/Reflection:

I dedicated a significant amount of my work on this project to my observations of Vera Molnár's Interruptions. I noted the following:

  • In each composition, all the lines are the same length.
  • Each line's center falls into a 56x56 grid.
  • Each line's length is twice the distance of the spacing on the grid (in other words, the endpoints of a fully vertical or horizontal line will intersect with the centerpoints of the lines immediately next to it)
  • While the lines' angles are random, they tend to point in a vertical direction on three of Molnár's compositions and in a horizontal direction on one composition
  • Not every line is present. There are gaps in each composition. While the location of the gaps seem random, missing lines tend to exist near other missing lines.
  • Gaps appear fairly infrequently
  • There is some slight variation in the background color, ranging from off-white to a mid-light grey.
  • There is a margin around each composition. Not all of the compositions are centered, but the most centered composition leaves a  margin of about 1/14th of the page around the composition.

As I was creating my own compositions in Javascript, I noticed that there was a considerable amount of care needed to produce a convincing randomness. I Perlin noise to create the gaps and the variation in line angles, something that did not exist in the time when the original compositions were created, to make a composition that was close to Molnár's. I think I was only mildly successful, though, as while the lines seem to have a similar character to the originals, the gaps do not. Their borders are too harsh and they are not quite the right shape. I think my line weight is a little off, as well.

Reproducing randomness is incredibly challenging without knowledge of the calculations that led to Molnár's compositions, and I now have a much greater appreciation for the work that goes into producing art with randomness as a factor.

yuvian-Interruptions

Observations:
- The artwork is square.
- The artwork consists of many short black lines, on a white background.
- The lines all have the same length.
- The artwork is basically composed of a 60 * 60 grid.
- Horizontal lines show up less frequently than vertical lines.
- Lines take up more than half of the space.

The most challenging part of this assignment was understanding Perlin noise. I've used it in the past but not much. The concept of noise and trigonometric functions in order to randomize the angles of the lines took a while for me to figure out. Something that I understood almost at once was the gridlike structure of Molnár's "Interruptions". I immediately noticed the 56X56 grid upon which the lines were fixed. I think I was generally successful at recreating the artist's work but my lines are not as randomized as the original. This is probably an easy fix as I would have to go back in and manipulate some of the variables within noise but for now, it is a close representation of Molnár's work. I appreciate how seemingly simple the original work appears at first when in actuality, it is a lot more complex than I had originally thought.

paukparl-Interruptions

observations:
1. Two colors are used: black and white.
2. The artwork is square.
3. There's a bit of margin on all sides
4. All lines are equal length.
5. The lines are rotated at random angles.
6. The center point of the lines are precisely positioned on a grid.
7. There are a total of 57x57 spots
8. There are empty spots. Some are small with just one or two lines missing. Some have grown bigger.
9. There is either a horizontal or vertical grain.
10. The length of each line is the twice that of the spacing between center points of adjacent lines (or maybe a bit shorter).

sketch:

 

var NOISE_SCALE = 0.13;
var NOISE_SCALE_ROT = 1;
var NOISE_THRESHOLD = 0.3;
var UNIT_SPACE;
 
var grains = ['H', 'V'];
var defaultRotation;
var justClicked = true;
var initialSeed;
 
 
function setup() {
  createCanvas(720, 720);
  UNIT_SPACE = width/61;
  stroke(0);
  strokeWeight(1);
  initialSeed = random(1000);
  noiseDetail(8, 0.5);
}
 
 
function draw() {
  if (justClicked) {
 
    // set grain between "horizontal" and "vertical"
    if (random(grains) === 'H') defaultRotation = 0;
    else defaultRotation = PI/2;
 
    // set a new noise seed value
    noiseSeed(initialSeed++);
 
    // draw pattern
    background(255);
    for (var y = 3; y &lt; 59; y++ ) {
       for (var x = 3; x &lt; 59; x++) { // generate noise var noiseValue = noise(NOISE_SCALE*x, NOISE_SCALE*y); // low-pass filter if (noiseValue &gt; NOISE_THRESHOLD) { 
 
           // draw individual line
           push();
           translate( x*UNIT_SPACE, y*UNIT_SPACE );
           rotate(defaultRotation);
 
           // apply noise to rotation
           rotate(map(noise(NOISE_SCALE_ROT*x, NOISE_SCALE_ROT*y), 0, 1, -PI/1.8, PI/1.8)); // rotate based on noise
           line( -0.95*UNIT_SPACE, 0, 0.95*UNIT_SPACE, 0 );
           pop();
         }
       }
    }
 
    justClicked = false;
  }
}
 
 
function mouseClicked() {
  justClicked = true;
}

thoughts:
Writing down the observations really helped me realize certain details that might have gone unnoticed such as the horizontal or vertical grain. The images also grew on me as I looked more at them. I set off to learn more about the Perlin noise. Soon I figured that the pattern of the empty spots and line rotations could be achieved with Perlin noise. I started coding right away, only to find out that I didn't understand Perlin noise correctly. So I took my time reading the p5 documentations and some texts on the mathematical foundation of Perlin noise. I was really surprised when I found out that Vera Molnar made Interruptions before Perlin noise was invented. If there was any particular difficulty with this sketch, it was trying to get both outcomes right--the empty patterns and line rotation--with the same parameters for the noiseDetail() function.

casher-interruptions

  1. All the lines are the same length.
  2. The lines are small.
  3. The lines are black and the background is white.
  4. Their placings seem to have some kind of pattern.
  5. There are holes where there aren't any lines.
  6. Some of the lines create triangles or other shapes.
  7. Not all of the lines intersect with another line.
  8. There are around 50-60 lines per side.
  9. Most of the lines are vertical.
  10. Each line is rotated around its center.

 

I started out by writing some pseudocode on paper. I knew the general steps were to 1) create a grid of many small lines, all equal in length, and then 2) rotate each line with some kind of randomly calculated value (which I would soon learn is noise). Next I took to the p5.js editor and re-purposed some of the logic from my Intersections code: using two nested for loops, I began to create some lines. Using the i and j indices as x1 and y1 values, and assigning modified versions of those values to x2 and y2, the lines could stay the same length.

After that point, I got stuck. I understood that the rotations of the lines were not totally random, in that they depended on some kind of mathematical pattern, so I called Char over. She introduced noise fields, explained noise them in depth, and outlined all of the constants, variables, and parameters that I would need when using one in my code. After a lot of toying around with values, I came up with this version of Interruptions. It is not terribly similar to Molnar's versions, but I believe it is equally interesting. By trudging through this activity, I've learned that noise fields are super fascinating when visualized in this way, and that Molnar was an incredibly epic woman.

 

rigatoni – Interruptions01

Since working on this project, I was left feeling hugely unsatisfied with the quality of my work. The morning session on Friday (7/9) helped me understand what this assignment was really about, make some fundamental observations about Vera's work and learn what Perlin noise was. Here is my second attempt at interruptions. My original attempt is still available towards the end of this post. Without further ado, Interruptions - The Sequel!

var interval
var lineSize
let redraw = true
function setup() {
  createCanvas(720, 720);
	//The grid in Vera's version was roughly 55x55
	interval = width/55
	lineSize = interval * .9
}
 
function draw() {
  if(redraw) {
  	background(200);
    GenerateLines()
    redraw=false
  }
}
 
function mouseClicked() {
	redraw = true 
}
 
// Helper Methods
function GenerateLines() {
  strokeWeight(1.5)
  noiseDetail(6, .65)
  noiseSeed(random(0, 1000))
  var noiseVal = -1
	for(var x=2*interval; x<width-2*interval; x+=interval) {
		for(var y=2*interval; y<width-2*interval; y+=interval) {
      noiseVal = noise(x/150,y/150)
      var midPoint = new Point(x,y)
      var startPoint = getRandomPointOnCircumference(midPoint, lineSize)
      //print(startPoint)
      var endPoint = getColinearEndPoint(startPoint, midPoint)
			var segment = new Segment(startPoint, endPoint)
      fill(noiseVal*255)
      // Uncomment this to see the noise values being generated per grid cell
      //rect(x,y,x+lineSize,y+lineSize)
      if(noiseVal>=.5) {
        segment.Draw() 
      }
    }
	}
}
 
function getRandomPointOnCircumference(center, radius) {
	var theta = random(0, TWO_PI)
  var x = sin(theta)*radius + center.x
  var y = cos(theta)*radius + center.y
  return new Point(x, y)
}
 
function getColinearEndPoint(startPoint, midPoint) {
	var endPoint = midPoint.Copy()
  var directionVector = midPoint.Copy()
  directionVector.Subtract(startPoint)
  endPoint.Add(directionVector)
  return endPoint
}
 
 
// Classes
function Point(x, y) {
  this.x = x
  this.y = y
  this.Add = function(addend) {
  	this.x += addend.x
    this.y += addend.y
  }
  this.Subtract = function(addend) {
		this.x -= addend.x
    this.y -= addend.y
  }
  this.Copy = function() {
		return new Point(this.x, this.y) 
  }
}
 
function Segment(startPoint, endPoint) {
	this.startPoint = startPoint
  this.endPoint = endPoint
  this.Draw = function() {
		line(startPoint.x, startPoint.y, endPoint.x, endPoint.y) 
  }
}
 
function LineGrid() {
	this.lines = []
  this.count = 0
  this.AddLine = function(_line) {
		this.lines.push(_line)
  }
  this.RemoveLine = function(_line) {
  	this.lines.pop(_line)
  }
}

Below you will find my original attempt at Interruptions.

via GIPHY

INITIAL OBSERVATIONS
(1) The lines are all roughly the same length
(2) There's patches where the lines don't appear
(3) The intersections of lines occur roughly towards the ends of the lines
(4) There's no real clumping/pattern; it seems random (as opposed to Perlin?)
(5) There are multiple hundreds of lines here
(6) There is no variance in thickness or transparency
(7) The compositions are all square
(8) Although there are gaps, the work is still densely populated
(9) Contrary to the gaps, there aren't areas that are MORE dense; only less
(10) The background isn't a full white, and that's less harsh on the eyes

Of course I realize now that (4) was flawed and I ended up needing Perlin noise after all. I barely scratched the surface though, and I think that would have been key to getting the look right. I wish I had given myself more time to actually figure out how noise works, as right now I am missing the gaps in the lines and the intersections aren't like what I observed in (3). After I was finished I checked out some of the other
attempts at replicating Interruptions and I was blown away by how much detail and level of control was achieved in some of them. I noticed other
people were making a conscientious effort to preserve the "randomness" and I plan to figure out how that is done next.

let redraw = true
function setup() {
  createCanvas(720, 720);
}
 
function draw() {
  if(redraw) {
    background(150);
    for(var i=0; i<3000; i++) {
      noiseSeed()
      var x1 = random(50, width-50)
    	var y1 = random(50, height-50)
      var x2 = (noise(x1)-.5)*200+x1
      var y2 = (noise(y1)-.5)*200+y1
      if(x2>50 && x2<width-50 && y2>50 && y2<height-50) {
      	line(x1, y1, x2, y2)
      }
    }
    redraw=false
  }
}
 
function mouseClicked() {
	redraw = true 
}

ocannoli-Interruptions.

  • The work is square
  • The work consists of various black lines on a white background
  • The lines are the same length
  • Many of the lines are at an angle
  • White spaces that lack black lines seem to occur to varying degrees
  • The lines are thin
  • The lines often touch one another to make diamond, square, and triangle shapesMany of the lines touch each other but not all
  • The lines seem random but also feel somewhat repetitive
  • The lines have a type of pattern involving either intersections, distance or the like

First I started with basic appearance based characteristics like the length of lines and colors. Then after some trial and error of creating random methods with the random function, I ended up creating a 50X50 grid of all lines then trying to accomplish their rotation. To figure out the rotation I ended up using perlin noise as the basis for that method. After tweaking some scaling, I attempted to add random spaces between the lines by skipping the creation of a line if the noise was in a certain small range. Although I did not complete it, at the end I was working on a method that would make sure all lines only intersected another line at its end point.