Open as new workspace
Experimenting with Grids 2 by Ryan

Experimenting with Grids 2

View source Pathogen · 77 lines
// Flow-field demo for the new Grid() constructor.
//
// Builds a 20x20 grid of angles via Grid().fill(), then draws an arrow
// at each cell center rotated by that angle. The arrowhead uses a
// context-stroke Marker so the marker color follows the line color.
//
// See docs/grid.md for the full Grid API reference.

define ViewBox(0, 0, 8000, 4800);

define default PathLayer('background') ${
  fill: Color('#fafafa');
  stroke-width: 0.2;
}

let arrow = @{
  m 0 0
  l 10 5
  l -10 5
  z
};

let arrowMarker = Marker('arrowhead', 10, 10) {|m|
  m.append(arrow, ${ fill: context-stroke; });
};

let arrowPB = @{
  m 0 0
  m -3 0
  h 6
  z
};

let field = Grid(320, 200, { xDim: 20, yDim: 8, outOfBounds: 'wrap' }) {|g|
  g.fill {|row, col, center|
    return calc(sin(row * 2.8 / g.rows) + cos(col * 7.7 / g.cols));
  };
};

// define PathLayer('flow-vectors') ${
//   stroke-width: 2;
//   stroke: Color('#0c0');
//   marker-end: arrowMarker;
// }

// layer('flow-vectors').apply {
//   field.forEach {|angle, row, col, center|
//     arrowPB.rotateAtVertexIndex(0, angle).drawTo(center.x, center.y);
//   };
// }

let drawingLayer = PathLayer('drawing-layer') ${
  stroke-width: 0.2;
  stroke: oklch(0.2197 0.0449 88.5 / 0.68);
  fill: oklch(0.7707 0.1575 89.5 / 0.87);
};

let itemLength = 480;
for (i in 0..240) {
  let x = randomRange(200, 6000);
  let y = randomRange(200, 2800);
  let start = Point(x, y);
  let next = start;
  for (k in 1..itemLength) {
    let angle = field.sampleBilinear(start.y, start.x);
    next = start.polarTranslate(angle, 3.6);
    drawingLayer.apply {
      let diameter = calc(k * 1.05);
      if (k > calc(itemLength / 2)) {
        diameter = calc((itemLength - k) * 1.04);
      }
      circle(start.x, start.y, diameter);
    }
    start = next;
  }
}