block by johnburnmurdoch 912c1406945031bbb6816de82ecfb030

Generative line intersections

Full Screen

Generates a random field of lines, each of which grows in a straight line until it encounters any other line, at which point it stops.

Phase one of a generative art project inspired by Jared Tarbell‘s Substrate project.

index.html

<!doctype html>
<html lang="">
<head>
  <meta charset="utf-8">
  <title>Intersections</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <script src="https://unpkg.com/d3/build/d3.min.js"></script>
  <style>
  body{ background: #ffffff }
  /*canvas{ background: #212121 }*/
  canvas{ background: #ffffff }
</style>
</head>
<body>
  <canvas></canvas>
  <script type='text/javascript'>
    let width = 500,
    height = 300,
    DPR = window.devicePixelRatio || 1,
    scaledWidth = width * DPR,
    scaledHeight = height * DPR,
    canvas = d3.select("canvas")
      .attr('width', scaledWidth)
      .attr('height', scaledHeight)
      .style('width', `${width}px`)
      .style('height', `${height}px`),
    ctx = canvas.node().getContext('2d'),
    timesUp = 10000,
    tickLength = 0.04,
    lines = [],
    intersects = [];
    
    ctx.scale(DPR, DPR);
    ctx.strokeStyle = '#000000';
    ctx.lineWidth = 0.5;

    const sameSign = (a, b) => (a * b) > 0;

    function intersect(a,b,c,d,p,q,r,s) {
      let det, gamma, lambda;
      det = (c - a) * (s - q) - (r - p) * (d - b);
      if (det === 0) {
        return false;
      } else {
        lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / det;
        gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / det;
        return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1);
      }
    }

    function addLine(id){
      let line = {
        id: id,
        intersects: [],
        start: [Math.random()*width, Math.random()*height],
        end: [0, 0],
         // slope: d3.format('.2f')(Math.random()) * Math.PI * 2 
         // slope: [0,Math.PI/2,Math.PI,Math.PI*3/2][Math.floor((Math.random()*4))] 
        slope: [0,Math.PI*0.333,Math.PI*0.666,Math.PI,Math.PI*1.333, Math.PI*1.666][Math.floor((Math.random()*6))]
        };
      lines.push(line);
    }

    d3.range(0,180).map((i) => addLine(i));

    function draw(t){
      let nLines = lines.length;
      let linesLeft = lines.filter(f => f.intersects.length == 0);
      linesLeft.forEach(l => {
        
        let to = l.end = [l.start[0]+Math.cos(l.slope)*t*tickLength,
          l.start[1]+Math.sin(l.slope)*t*tickLength];
          
        for(let index=0; index < lines.length; index++){
          let d = lines[index];
          if(intersect(...d.start, ...d.end, ...l.start, ...l.end) == 1 && intersects.indexOf([l.id,d.id].sort((a,b) => a-b).join('_')) < 0){
                  l.intersects.push(1);
                  intersects.push([l.id,d.id].sort((a,b) => a-b).join('_'));
                  break;
                }
        } 
        
        if(to[0] >= 0 && to[0] <= width && to[1] >= 0 && to[1] <= height && l.intersects.length == 0){
          /* ctx.fillRect(l.start[0]-2, l.start[1]-2, 4, 4) ;*/
          ctx.moveTo(...l.start);
          ctx.lineTo(...to);
          ctx.stroke();
        }else{
          /* console.log(`Line ${l.id} hit edge, ${lines.length} left`); */
          nLines -= 1;
        }
      })
      if(nLines == 0){
        console.log('CEASE')
        timer.stop();
      }
    }

    let timer = d3.interval(function(elapsed) {
      draw(elapsed);
      /* if (elapsed > timesUp) timer.stop(); */
    }, 25);
  </script>
</body>
</html>