"use strict" const ruleCTX = document.getElementById("rule").getContext("2d") const ruleWidth = document.getElementById("rule").width const ruleHeight = document.getElementById("rule").height const fillSelect = document.getElementById("fillSelect") fillSelect.addEventListener("change", RedoFill) const dataSelect = document.getElementById("dataSelect") dataSelect.addEventListener("change", ChangeDataset) const points1 = [[80,20], [80,180], [180,180], [180,60], [20,60], [20,160], [60,160], [60,110], [160,110], [160,140], [120,140], [120,20]] const points2 = [[100,20], [180,100], [20,130], [100,100], [180,180], [20,100]] let arrows = true let points = points1 function ChangeDataset() { switch(dataSelect.value) { case 'll': points = points1 arrows = true break; case 'bd': points = points2 arrows = true break; } RedoFill() } function RedoFill() { switch(fillSelect.value) { case "none": DrawShape('nonzero', false) break case "evenodd": DrawShape('evenodd') break case "nonzero": DrawShape('nonzero') break } } // this is not completely right, we will deal with that later. function DrawArrow(a,b) { let x1 = a[0] let y1 = a[1] let x2 = b[0] let y2 = b[1] // find the midpoint of the line let mpx = (x1+x2)/2 let mpy = (y1+y2)/2 // the length of the arrow // purely arbitrary, a very short side would goof this up. let dx = 5 let dy = 5 // save the color so you can put it back. let tmpStyle = ruleCTX.strokeStyle ruleCTX.strokeStyle = "red" ruleCTX.beginPath() // special cases, we could do this with trig too, but ... if (x1 == x2 ) { if(y1 < y2) { dy = -5 } ruleCTX.moveTo(mpx-dx, mpy+dy) ruleCTX.lineTo(mpx, mpy) ruleCTX.lineTo(mpx+dx, mpy+dy) } else { if (x1 < x2) { dx = -5 } ruleCTX.moveTo(mpx+dx, mpy-dy) ruleCTX.lineTo(mpx, mpy) ruleCTX.lineTo(mpx+dx, mpy+dy) } ruleCTX.stroke() ruleCTX.strokeStyle = tmpStyle } function DrawShape(rule, filled = true) { let i; ruleCTX.fillStyle = "white" ruleCTX.fillRect(0,0, ruleWidth, ruleHeight) ruleCTX.fillStyle = "green" ruleCTX.beginPath() // start at the first point ruleCTX.moveTo(points[0][0], points[0][1]) // draw to all points for(i=1;i<points.length; ++i) { ruleCTX.lineTo(points[i][0], points[i][1]) } // draw back to the first point. ruleCTX.lineTo(points[0][0], points[0][1]) // fill can take several parameters, // the first can ben an arry of points, or the fill rule // the fill rule is either nonzero or evenodd // These values are contained in the ui, which is confusing, if (filled) { ruleCTX.fill(rule) } ruleCTX.stroke() if (arrows) { for(i = 0; i < points.length-1; ++i) { DrawArrow(points[i], points[i+1]) } } } DrawShape('nonzero', false)