View source
Pathogen · 72 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, 3200, 3200);
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
};
let field = Grid(200, 200, { xDim: 10, yDim: 10, outOfBounds: 'wrap' }) {|g|
g.fill {|row, col, center|
return calc(sin(row * 1.9 / g.rows) + cos(col * 5.3 / g.cols));
};
};
define PathLayer('flow-vectors') ${
stroke-width: 0.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.2124 0.0859 23.8 / 0.8);
fill: oklch(0.6269 0.2558 27.4 / 0.87);
};
for (i in 0..200) {
let x = randomRange(200, 1800);
let y = randomRange(200, 1800);
let start = Point(x, y);
let next = start;
for (k in 1..240) {
let angle = field.sampleBilinear(start.y, start.x);
next = start.polarTranslate(angle, 3.2);
drawingLayer.apply {
let diameter = calc(k * 1.5);
circle(start.x, start.y, diameter);
}
start = next;
}
}