import { Polygon, Point } from "./Polygon"; function inwardSpiral(input:Polygon, scalar:number, randomizeShrinkRate:number): Polygon { const output = new Polygon(); let a:Point; let b:Point; let cx: number; let cy: number; let rate:number; for(let i=0;i<input.length;i++) { rate = scalar; if(randomizeShrinkRate !== 0) { rate += randomizeShrinkRate * 2 * (Math.random() -0.5); rate = Math.min(0.9, Math.max(0, rate)); } a = input[i]; b = input[(i+1)%input.length]; cx = rate * (b.x - a.x) + a.x; cy = rate * (b.y - a.y) + a.y; output.push(new Point(cx, cy)); } return output; } function createInwardSpiral( input:Polygon, maxiterations:number, shrinkRate:number, randomizeShrinkRate:number, ): Polygon[] { const cycle:Polygon[] = [input]; let pNext:Polygon; for(let i=0;i<maxiterations;i++) { pNext = inwardSpiral(input, shrinkRate, randomizeShrinkRate); cycle.push(pNext); input = pNext; } return cycle; } function polygonToSvg( svgRootElement:SVGSVGElement, polygon:Polygon, { fill }:{fill:string | null}, ): SVGPolygonElement { // Note: it is not possible to create any svg element without the namespace. const polygonSvg = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); polygonSvg.style.fill = fill; for(const corner of polygon) { // This is the only way to create an SVGPoint: const point = svgRootElement.createSVGPoint(); point.x = corner.x; point.y = corner.y; polygonSvg.points.appendItem(point); } return polygonSvg; } function polygonStyle(strength:number) { return { fill: `rgb(0,0,${Math.floor(strength)})`, }; } export function fractalToSvg(fractal:Polygon[][], sideLength:number): SVGSVGElement { // Note: it is not possible to create any svg element without the namespace. const el = document.createElementNS("http://www.w3.org/2000/svg", "svg") as SVGSVGElement; el.width.baseVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PX, sideLength); el.height.baseVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PX, sideLength); el.style.fill = "none"; el.style.stroke = "purple"; el.style.strokeWidth = "1"; let colorStrength = 0; const initialColorStrength = 20; for(const segment of fractal) { colorStrength = initialColorStrength; for(const iteration of segment) { const p = polygonToSvg(el, iteration, polygonStyle(colorStrength)); el.appendChild(p); colorStrength += (255-initialColorStrength)/segment.length; } } return el; } export function createSquare(side:number): Polygon { const square = new Polygon(); square.push(new Point(0,0)); square.push(new Point(0,side)); square.push(new Point(side,side)); square.push(new Point(side,0)); return square; } export function inwardSpiralFractal(shape:Polygon, iterations:number, shrinkRate:number, randomize:number): Polygon[][] { const fractal = [ createInwardSpiral(shape, iterations, shrinkRate, randomize), ]; return fractal; }