0 1 2 3 4 5 6 DoIt
<html> <head> <script src="koch.js" defer></script> </head> <body> <h1> Koch Snowflake</h1> <canvas id="theCanvas" style="border:1px solid black;"></canvas> <p> <label for="0">0</label> <input type = "checkbox" id="0" name="0" checked/> <label for="1">1</label> <input type = "checkbox" id="1" name="1"/></input> <label for="2">2</label> <input type = "checkbox" id="2" name="2"/></input> <label for="3">3</label> <input type = "checkbox" id="3" name="3"/></input> <label for="4">4</label> <input type = "checkbox" id="4" name="4"/></input> <label for="5">5</label> <input type = "checkbox" id="5" name="5"/></input> <label for="6">6</label> <input type = "checkbox" id="6" name="6"/></input> <br> <button type="button" id="doIt"> DoIt </button> </body> </html>
"use strict" const canvas = document.getElementById("theCanvas"); canvas.width = 500; canvas.height = 500; const ctx = canvas.getContext('2d'); let colors=['black', 'green', 'red', 'blue', 'cyan', 'magenta', 'yellow']; let buttons = [true, false, false, false, false, false, false]; function Distance(p1, p2) { let dx = p2.x - p1.x; let dy = p2.y - p1.y; let d = Math.sqrt(dx*dx + dy*dy) return d; } function FindPerp(p1, p2, dist) { // need uint vectors for the perpendicular let dx = p2.x - p1.x; let dy = p1.y - p2.y; // make this line have length 1 let len = Distance(p1, p2); if (len > 0) { dx /= len; dy /= len; } let newPt = { x : p2.x + dy * dist, y : p2.y + dx * dist, } return newPt } function OnLine(p1, p2, length) { let dx = p2.x - p1.x; let dy = p2.y - p1.y; let newPoint = {x: p1.x + length * dx, y: p1.y + length * dy}; return newPoint } function FindHeight(length) { return length * Math.sqrt(3)/2; } function DoStep(p1, p2) { let rv = [] let A = OnLine(p1, p2, 1/3); let B = OnLine(p1, p2, 2/3); let mid = OnLine(p1, p2, 1/2); let length = Distance(p1, A); let C = FindPerp(p2, mid, FindHeight(length)) rv.push(A) rv.push(C) rv.push(B) return rv; } function DrawShape(shape) { let i = 1; ctx.beginPath(); if (shape.length > 0) { ctx.moveTo(shape[0].x, shape[0].y); } while (i < shape.length) { ctx.lineTo(shape[i].x, shape[i].y); i++; } if (shape.length > 0) { ctx.lineTo(shape[0].x, shape[0].y); } ctx.stroke(); } function DrawShapes() { for(let i =0; i < buttons.length; ++i) { if (buttons[i]) { ctx.strokeStyle = colors[i]; DrawShape(shapes[i]); } } } function Update() { ctx.fillStyle = "white"; ctx.fillRect(0,0, canvas.width, canvas.height); for(let i = 0; i < buttons.length; ++i) { let box = document.getElementById(i); console.dir(box); buttons[i] = box.checked; } DrawShapes(); } function DoKoch(shape) { if (shape.length > 1) { let newShape = []; let i = 1; while (i < shape.length) { newShape.push(shape[i-1]); let tmpShape = DoStep(shape[i-1],shape[i]) newShape = newShape.concat(tmpShape); i++; } newShape.push(shape[i-1]); newShape = newShape.concat(DoStep(shape[i-1],shape[0])); return newShape; } else { return shape; } } // all generations of the curve let shapes = []; // the current generation. let shape = []; // Generate an equlateral triangle /* let p1 = {x: -canvas.width / 3, y: 2 * canvas.height / 3}; let p2 = {x: canvas.width * 4 / 3, y: 2 * canvas.height / 3}; shape.push(p1); shape.push(p2); shape = DoKoch(shape).slice(1,4); */ /**/ // generate a square let width = canvas.width; let height = canvas.height; let scale = 0.23; let p1= {x: width * scale, y: height * scale}; let p2= {x: width * scale, y: canvas.height*(1-scale)}; let p3= {x:canvas.width *(1 - scale), y: canvas.height * (1 - scale)}; let p4= {x:canvas.width *(1 - scale), y: height * scale}; // change to 1 2 3 4 for an inside out square. shape.push(p1); shape.push(p2); shape.push(p3); shape.push(p4); /**/ // note this will do a "deep copy" // ... will serialize the values // and [] will create a new vector with these values. // but it is only a first level deep copy. // which is fine in this case. shapes.push([...shape]); for(let i = 1; i < colors.length; ++i){ shape = DoKoch(shape); shapes.push([...shape]); } DrawShapes(); let doItButton = document.getElementById("doIt") doItButton.addEventListener("click",Update);