• The lines are black.
    • The lines are all of the same weight.
    • The background is white.
    • The lines appear to be arranged in relation to some sort of grid.
    • Most of the lines have angles close to 90° or 180°, but fewer of the lines have slopes that appear to be around 45°.
    • The lines are all of the same length.
    • The lines appear to be arranged in columns and rows with the same midpoint.
    • The blank spaces are created by the rotation of the line segments.
    • There are no missing line segments at each point of line midpoint on the grid except in large blobs.
    • There are lines missing in certain areas.

I created my "re-code" of Molnár's project by creating a grid of line segments rotated at random angles. To recreate the similarity between many of the lines (most are nearly vertical), I started with Perlin noise and added a random rotation deviation. I created gaps with a Perlin noise threshold. To randomize the gaps, I add a random value to the Perlin noise coordinates to act as a randomness "seed." My original solution was to subtract standard geometric shapes to create the spaces, but this did not yield the same "random blob" affect that Molnár achieved. I am impressed with how she created the empty swaths, as her work predates the publication of Perlin noise. She was also working with punch cards, an analog plotter, and very early, slow computers.

/* Sapeck    9/6/2017
60-212                        Carnegie Mellon University
Copyright (C) 2018-present  Sapeck
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
var SPACING_X = 18
var SPACING_Y = 18
var LENGTH = 30
// Based on starter Code for "Embedded Iteration + Randomness"
var boolDoRefresh;
function setup() {
  createCanvas(720, 720)
  boolDoRefresh = true
function draw() {
  if (boolDoRefresh) {
		var NOISEX_SEED = random(0, 20000)
		var NOISEY_SEED = random(0, 20000)
    let MAX_ROWS = (height-2*SPACING_Y) / SPACING_Y
    let MAX_COLS = (width-2*SPACING_X) / SPACING_X
    for (let col=1;col<MAX_COLS;col++) {
      for (let row=1;row<MAX_ROWS;row++) {
        m = noise(col/10, row/10)
        m += random(-2, 2)
        let x1 = col*SPACING_X + SPACING_X
        let y1 = row*SPACING_Y + SPACING_Y
        let g = noise(col/10+NOISEX_SEED, row/10+NOISEY_SEED)
        if (g > NOISE_THRESHOLD) {
          let x2 = x1 + LENGTH_HALF*cos(m)
          let y2 = y1 + LENGTH_HALF*sin(m)
          let x3 = x1 - LENGTH_HALF*cos(m)
          let y3 = y1 - LENGTH_HALF*sin(m)
          line(x1, y1, x2, y2)
          line(x1, y1, x3, y3)
  	boolDoRefresh = false
function mousePressed() {
  boolDoRefresh = true


This project was an interesting challenge because it forced me to evaluate the correctness of my work in an analogue as opposed to digital manner. By this I mean that I was not evaluating whether my project worked or not in absolute terms. Instead, I was observing its correctness in a fluid manner. There were many instances where I looked at it and thought, this almost seems right, but it isn't quite there yet. This is a workflow that I'm accustomed to in design classes but feels foreign in the context of a computationally based course. That being said, I really enjoyed working on this. In particular, computing line visibility on a grid taught me a new thing about Perlin noise. I've been using it for a few years but didn't fully understand how it worked until this project, which was really exciting.

var segs = [];
var margin = 20;
var segLength = 20;
var numSegs = 1500;
var clicked = false;
var segsSpacing = 13;
var xVisOff = 0.0;
var yVisOff = 0.0;
function setup() {
  createCanvas(555, 555);
function draw() {
    clicked = false;
function resetSegs(){
  segs = [];
  for(i = 0; i < sqrt(numSegs); i++){
    xVisOff = xVisOff + 0.2;
    yVisOff = 0.0
    for(j = 0; j < sqrt(numSegs); j++){
      yVisOff = yVisOff + 0.2;
      var x1 = i*segsSpacing + margin*1.5;
      var y1 = j*segsSpacing + margin;
      var secondPoint = setSecondPoint(x1, y1);
      var x2 = secondPoint[0];
      var y2 = secondPoint[1];  
      newSeg = new Segment(x1, x2, y1, y2, setVisibility());
//uses perlin noise to determine whether the line is visible or not
function setVisibility(){
  var opValue = noise(xVisOff, yVisOff);
  if(opValue > .3){
    return true;
    return false;
function drawSegs(){
  for(i = 0; i < numSegs; i++){
function mousePressed() {
  clicked = true;
function Segment(x1, x2, y1, y2, visibility){
  this.x1 = x1;
  this.x2 = x2;
  this.y1 = y1;
  this.y2 = y2;
  this.drawSeg = function(){
      line(this.x1, this.y1, this.x2, this.y2);      
  this.isVisible = visibility;
//Calculates the second point by selecting a point at the edge of a circle
//where the radius is the desired length of the lines and the center
//is the first point
function setSecondPoint(x1, y1){
  var angle = random(50, 150);
  var y2 = sin(angle) * segLength + y1;
  var x2 = cos(angle) * segLength + x1; 
  return [x2, y2];


  1. The artwork is square.
  2. There is a border of white along the edges.
  3. The lines all tend to have a bias toward vertical or horizontal in each piece, from a further away view.
  4. Very few individual lines are rotated anywhere near horizontal(for the vertically oriented pieces).
  5. Open areas between lines seem to have fairly uniform, if random shapes.
  6. The lines look like they line up in a grid, with each line rotated about its midpoint.
  7. The lines are all short and have the same length
  8. The lines are black. The background is white.
  9. The larger open spaces have irregular shapes and are fairly sparse.
  10. Some of the large open spaces occur at the 'edges' and there are no lines in that part of the edge.
  11. There are lots of small parallelograms, triangles, and sometimes pentagons formed by adjacent lines.
  12. There are at least fifty lines in a row/column.

var boolDoRefresh;
var boolDoRefresh;
var bkgrd = 255;
var canvasW = 650;
var canvasH = 650;
var border = 30;
var gridSize = 56;
var baseAngle = 90; //change to 0 for horizontal orientation
var lineRadius = 9;
function setup() {
  createCanvas(canvasW, canvasH);
  boolDoRefresh = true;
function draw() {
  if (boolDoRefresh) {
    boolDoRefresh = false;
function drawTheThing(){
  var div = (width - 2*border)/gridSize;
  var noiseVal;
  var noiseScale=0.01;
    for (var x = border; x &lt; width - border; x += div){
      for (var y = border; y &lt; width - border; y += div){ 
        noiseVal = noise((x) * noiseScale, (y) * noiseScale); 
        if(noiseVal &gt; 0.75) stroke(255);
        else stroke(0);
function drawLineCenteredAt(x,y){
  var angle, dx, dy, bias;
  bias = 65;
  angle = baseAngle - random(bias);
  var half = random(2);
  var neg;
  if (half &lt; 1) neg = -1;
  else neg = 1;
  dx = neg*lineRadius*cos(angle);
  dy = lineRadius*sin(angle);
  line(x+dx,y+dy, x-dx,y-dy);
function mousePressed() {
  boolDoRefresh = true;
Some Thoughts

I started with the general form, a grid of randomly rotated lines, then added in noise, then fine-tuned the lines' randomness. The vertical/horizontal bias was interesting. The angle rotated definitely had to be less than 90 degrees, but I wasn't sure if the angle deviation was constant or formed a kind of bell curve around a point(ultimately it made little difference).  The noise was also difficult because understanding what the different settings meant didn't translate to imagining what the overall effect would be, so it was a lot of testing and close comparison. I learned to appreciate examining an art piece in extremely great detail and seeing what kind of fiddling went into achieving that specific impression. I think I made a good copy at a glance, although I think the noise could have been less harsh.


// Starter Code for "Embedded Iteration + Randomness"
var boolDoRefresh;
function setup() {
  createCanvas(744, 744);
  boolDoRefresh = true;
function findpointcircle(i,j) {
    var margin=48
    var square=12
    var r = 8
    // console.log(i,j)
    var midx=margin+((j*square)-(0.5*square))
    var midy=margin+((i*square)-(0.5*square))
    var slope = map(i*j, 0,25,0,10)
    var deg = randomGaussian(2*PI, 0.7);
    var x = midx+(r*sin(deg))
    var y= midy+(r*cos(deg))
    //(x – h)2 + (y – k)2 = r2
    var endx = midx+(r*sin(deg+PI))
    var endy = midy+(r*cos(deg+PI))
    return [x, y, endx, endy]
function draw() {
  if (boolDoRefresh) {
    var size=56
    for (i=0; i&lt;size;i++) {
        for (j=0; j&lt;size;j++) { // noiseDetail(5,0.5); var blank = noise(i*0.1+10,j*0.1) var blank2 = noise(i*3+10,j*0.1) // console.log(i*0.02+10, j*0.02, blank) strokeWeight(1); var points =findpointcircle(i,j) if (blank&gt;0.32) {
								line(points[0], points[1], points[2], points[3])
          	else if (blank&lt;=0.25 &amp;&amp;blank2&lt;=0.5) {
              	line(points[0], points[1], points[2], points[3])
    boolDoRefresh = false;
function mousePressed() {
  boolDoRefresh = true;

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. It is 56 x 56 lines (I think)
5. The lines have varying random degrees of rotation
6. There is like 3-5% chance of no line drawn
7. The lines don't take up their own space, there is a lot of overlap
8. some of the artworks are "mostly vertical" lines and some are "mostly horizontal" lines
9. There are random blobs of blankness
10. There is a small gradation towards blankness


Gaussian distribution and perlin noise have been words I've been hearing around for a long time now, but have never understood. What was especially hard about this was getting the blanks in the Vera drawings correct. At the end, I still feel like my blanks are shaped a bit too be honest, I still don't really understand how the noise distributions are made. I spent a lot of time inserting random numbers as my "noise scale." I understand the general concept of noise, but will need to technically understand it more. Edit: After posting this, I actually realized that I had forgotten to make sure that the mean angle of the lines changes--every time, the lines in my piece are mostly vertical. However it was satisfying to see how Gaussian distributions are utilized.



  1. The artwork is in the shape of a square
  2. The artwork has a white background featuring many black lines.
  3. The center of each line seems to fall on the coordinates of a 56x56 unit grid
  4. The length of each line is equal to the lines spacing on the grid so that some of the lines intersect.
  5. Each line is set at a random angle. The angle of each line seems independent from the angles of the lines around it.
  6. Some spaces on the grid that you would expect to see a line are missing a line.
  7. The lines' angles seem to tend toward vertical.
  8. Theres an empty border around the lines.
  9. The randomness of the rotation of the lines seems independent from where lines are missing.
  10. The missing lines seem to be related to each other; there are "areas" on the grid where lines are missing or appear to be blown away.
  11. Even in places where there isn't a large area of lines missing, there are a few lines missing here and there.

The most challenging part about this piece was having to figure out the logic behind what seems like a chaotic image. While it looks very busy, the most defining features of this piece for me where the grid layout of the lines, the vertical-tending angled lines, and the large spaces where lines were missing. The large spaces of empty lines was the most difficult aspect to reproduce, followed by the angles of the lines. I chose to generate probability coefficients for each line using the noise() function. Because the noise() function used the row/column of each line, there were specific areas where lines were much  less likely to occur. T0 randomize the angle of the lines I first generated a random x-coordinate within the line's cell and made the end fall on that coordinate. This way there would be a higher probability of the line tending vertical. I enjoyed recreating this piece because it made me think about how to distinguish patterns and key characteristics of a seemingly random system. Having to break down the each element into basic properties to recreate was a fun exercise .





1. The artwork is square
2. The artwork is made of many short black lines of the same length
3. There are areas of the artwork where the lines are missing
4. The lines are angled randomly
5. The lines are distributed evenly
6. There are clusters of missing lines
7. Although the lines are angled randomly, they seem to tend towards vertical(at least in the first 3 images)
8. The lines can be sorted into a square grid, where the height of each row is shorter than the length of a black line
9. The lines overlap in places
10. Some columns seem to have more vertical-tending lines than others

One of the things I was stumped on with this project was how to create the clusters of missing lines (#6). Golan and Char helped me by telling me to look into perlin noise. At first, using perlin noise seemed no different from using randomness to determine if a line should be missing or not, but by looking at pictures of perlin noise I realized what the issue was. In order to get clusters that are large enough to be noticeable, the perlin noise needs to be scaled up. I achieved this effect by calling dividing my i and j by 80 in the call to noise(). This is also noted in the p5 documentation for noise(), where they state that "As a general rule the smaller the difference between coordinates, the smoother the resulting noise sequence will be."

Something interesting that I saw in this project was that using noise() instead of Math.random() to determine the angle of the lines resulted in the "tending-towards-vertical" property (#7). My guess is that that this is because Math.random() has a completely even distribution from 0 to 1, while noise() has less deviation from 0.5.

Also, I think that my observation #10 that "some columns have more vertical-tending lines than others" was completely wrong. Looking closer, it does not seem like column number has any effect on the number of vertical-tending lines. I think that maybe I tricked myself into believing this was true by seeking out some sort of pattern, but in the end it was replicated much better using just noise.

I think that my re-code was pretty successful, and I am glad that the result was simple to achieve. I toggled with values such as line count and length to try and match the original as best as I could.



  1. The artwork is square
  2. The artwork consists of many short black lines on a white backgrounds
  3. All of the lines have the same length
  4. The lines do not go off of the page
  5. There is a white border around the artwork
  6. There are random, small sections which do not have any lines
  7. The lines have an average direction, whether that be vertical or horizontal
  8. Very few lines do not touch another line
  9. There are sections of repeating patterns of lines
  10. The lines have roughly the same amount of space between them
  11. The lines which touch do so barely - they either just hit the edge of another line or cross over only slightly
  12. The lines appear to be in columns
  13. Lines intersect at most 3 other lines, most likely 2, and sometimes no other lines.

I started by placing the lines into a grid, but faced the problem of many overlapping "X's", so I wrote a function that found and removed them. This created the problem of too much space between lines, and it took bringing the image into Photoshop and plotting points to realize it was the midpoints that were on the grid, and not either endpoint.

This realization made the lines "fit together" properly, which is what I was finding most difficult to replicate. The noise function was used to generate values based on each line's coordinates, deleting those which were over a certain threshold to make gaps.

I now appreciate that generative art is not nearly as random as it initially appears, and that there are several layers of rules and calculations behind it. After many versions, I believe my replication is close, though hers may have nicer, more balanced empty sections.



  1. The lines have seemingly random angles with the square of the paper
  2. While the pattern seems random, the lines are evenly distributed on the paper
  3. Some lines intersect others
  4. There are some irregularly large white-spaces in the artwork where lines have been removed
  5. There is a white border around the edge of the artwork
  6. The lines tend to break into this border, preventing it from being a square
  7. The border's on the top, left and right are larger than the ones at the bottom
  8. There exists a signature at the bottom right corner
  9. Generally, most lines tend to bias verticality
  10. The lines seem to be part of a general grid system

I thought of this as a grid distortion process - where most lines in a column system get rotated by some kind of distribution. After the distortion, there is a sequential "culling" of lines, which is not random but happens in chunks or groups, so it can be thought of as culling blocks of grids instead of individual lines.

Initially, I used the P5.JS random function to generate the values that would rotate each line segment, but I quickly realized that Molnar's piece had some kind of specific mathematical distribution. After messing around with Perlin Noise, I used Gaussian Distribution to generate the rotation (seeing as most lines tend t0 be more vertical). I think the calibration of the distribution still needs some work - and so does the calibration of the culling of the "patches" in the grid.

This was quite an interesting process, learning to re-create a visual effect through code - the process involved a lot of educated guessing, which while tough, was an interesting experience because of its iterative nature.



  1. The background is white, all the lines are black
  2. Lines are arranged in a square lattice
  3. The lines are rotated around their centre point on the lattice
  4. The lattice is 56 x 56
  5. Some lines are missing
  6. If a line is missing, the probability that one of its neighbours is missing is high (Missing in groups)
  7. There are many more lines present than missing
  8. The length of each line is twice the distance between the centre points of each line on the lattice
  9. All the lines are the same length
  10. There is a margin around the piece
  11. The angles of rotation of the lines are within a rough normal distribution (the vast majority have only a small amount of rotation, and the more extreme the rotation the less of them there are)

I started out my figuring out how to formulate the lattice, starting with circles with their centre at the lattice points. This was done with a nested for loop. Once this was created, I set about replacing every circle with a vertical line with the appropriate pixel measurements/separations. At this point I had 56 vertical long lines. I then set about figuring out how to randomly rotate each of the lines. I initially just did this purely randomly, using random(). However, displeased by this I looked at possibilities for getting the rotations more normally distributed, and found randomGaussian(). Using this I was able to more normally distribute the angles. This was definitely a saving grace, and I massive appreciated it's existence, and it also alerted me to the extent of built in functions within p5.js.

I then set about working on the spaces, and felt that I would need two cases of probability of a space. My first probability was the base overall probability of their being a blank space, which I set to be relatively low. I then set about creating an array to store whether a line was there or not, with 0 representing the presence of a line and 1 being a blank space. Then with this, as the lines were created I checked whether a line's neighbour was blank (its left, above and left top angled neighbours). If this was the case the probability that it would be blank became higher. I then tinkered with both probabilities until I got a result that I felt resembled the original Interruptions.  Getting this element of the neighbours working was the most difficult element of the app for me, with the formatting of the neighbour checking proving challenging.



My observations:

  1. The lines are drawn in a square
  2. There are 55-60 lines per side
  3. Each line is the same length
  4. The lines can either intersect each other or not
  5. The lines that intersect only do so on each other's ends- they never cross in the middle
  6. The majority of the lines are vertical
  7. Non-vertical lines rotate several degrees left or right, but are never horizontal
  8. The lines are rotated about their ends middles
  9. There are sometimes white areas in the center of the square with no lines within
  10. The white areas account for ~0-10% of the total area

I started by creating a grid of lines. It seemed like the lines' spacing was more important than the number of lines, so I opted to base my for loops on padding values rather than by line number. Next I worked on creating the semi-random rotation values for the lines. I accomplished this by utilizing p5's built in vector object which I could use to create an angle for each by using the fromAngle constructor. For the angle values, I experimented with both the noise function and randomGaussian function before settling on the latter. A key feature of Molnár's work is that the lines are mostly vertical, and the randomGaussian function allowed me set the median to 90 degrees and then allow a certain amount of randomness by giving the function a standard deviation of around 30.

A problem I ran into at this point was that I was rotating the lines around the endpoints fixed to the grid and the lines were intersecting each other in the middles- something that does not happen in Molnár's work. I eventually found a solution to this by fixing the lines to the grid by their center points, thus ensuring that any overlapping only occurs on the ends of the line segments. After playing with the values, the result is quite close to the way that the lines in the reference works behave.

Finally, the white spaces. For these I used the noise function and took advantage of the double for loop to create a noise map in 2D space. I mapped the values on the range [0, 255] such that I could pick some arbitrary color of gray, say 155, and use that as a mask. Any time that the color value of the map goes above 155, no lines are drawn. With an appropriate offset value to keep the size and quantity of the holes correct, the result is somewhat similar to the random quality of Molnár's. However, hers is slightly different in that the holes are both small and large. Using this technique, I am not able to get the same effect because any offset value I choose will create a map with uniform variations. In other words, I can either get large or small holes, not both. This is definitely the main area to improve on. I'd be quite interested to see how she achieved this unique affect.