svg`<svg width="${w}" height="${h}">
<defs>
<mask id="Mask">
<rect x="0" y="0" width="${w}" height="${h}" fill="white" />
<rect x="${margin}" y="${margin}" width="${w - margin * 2}" height="${h - margin * 2}" fill="black" />
</mask>
</defs>
<rect x="0" y="0" width="${w}" height="${h}" fill="${palette[0]}" />
<g>
${(() => {
const segments = [
new Segment(PVector(margin, margin), PVector(w-margin, margin)),
new Segment(PVector(w-margin, margin), PVector(w-margin, h-margin)),
new Segment(PVector(w-margin, h-margin), PVector(margin, h-margin)),
new Segment(PVector(margin, h-margin), PVector(margin, margin))
]
array(n).forEach(i => {
const pos = PVector.random(PVector(margin, margin), PVector(w - margin, h - margin))
const angle = random() < .6 ? randInt(2) * Math.PI / 2 : random(Math.PI)
const dir = PVector.fromAngle(angle).setMag(h+w)
const segment = new Segment(pos.clone().add(dir), pos.clone().sub(dir))
const intersections = []
for (const s of segments) {
const intersection = segSegIntersection(segment, s)
if (intersection !== null) intersections.push(intersection)
}
intersections.sort((a, b) => a.distSq(segment.center) > b.distSq(segment.center) ? 1 : -1)
const nearest = getNearestIntersections(segment, intersections)
if(nearest !== null) segments.push(new Segment(nearest[0], nearest[1]))
})
return segments.map(s => `<line
clip-path="url(#clip)"
opacity="0.9"
stroke="${palette[randInt(1, palette.length)]}"
stroke-width="${randInt(5, 50)}"
x1="${s.a.x}" y1="${s.a.y}"
x2="${s.b.x}" y2="${s.b.y}"
/>`).join('\n') +
`<rect
x="0"
y="0"
width="${w}"
height="${h}"
stroke="none"
fill="${palette[0]}"
mask="url(#Mask)"
/>\n` +
segments.map(s => `<line
stroke="${palette[0]}"
stroke-width="1.5"
x1="${s.a.x}" y1="${s.a.y}"
x2="${s.b.x}" y2="${s.b.y}"
/>
`).join('\n')
})()}
</g>
</svg>`