Browse Source

added circle events and parabola intersections

Brandon Wong 7 years ago
parent
commit
72ad6f91d2
1 changed files with 142 additions and 4 deletions
  1. 142 4
      voronoi.js

+ 142 - 4
voronoi.js

@@ -140,9 +140,9 @@ const sites = generateSites(50).map(function assignRandomColour(site) {
     return site;
 });
 
-sites.forEach(function renderSites(site) {
-    drawSite(site.x, site.y);
-});
+//sites.forEach(function renderSites(site) {
+//    drawSite(site.x, site.y);
+//});
 
 
 function bruteForceRow(row, sites) {
@@ -202,16 +202,23 @@ function parabola(focus, directrixY) {
     ctx.save();
     ctx.lineWidth = 1;
     ctx.strokeStyle = '#aaa';
+    //ctx.fillStyle = 'rgba(255,0,0,0.5)';
+    //ctx.fillStyle = 'white';
     ctx.beginPath();
     ctx.moveTo(start.x, start.y);
     ctx.quadraticCurveTo(control.x, control.y, end.x, end.y);
     ctx.stroke();
+    //ctx.fill();
     ctx.closePath()
     ctx.restore();
 }
 
 function demo(dirY) {
     ctx.clearRect(0,0,canvwidth,canvheight);
+    //ctx.save();
+    //ctx.fillStyle = 'rgba(255,0,0,0.5)';
+    //ctx.fillRect(0,0,canvwidth,canvheight);
+    //ctx.restore();
     sites.forEach(function parabolas(site) {
         if( site.y < dirY ) {
             parabola(site, dirY);
@@ -228,10 +235,141 @@ function demo(dirY) {
         console.log('done!');
     }
 }
-demo(0);
+//demo(0);
 
 //TODO
 // http://hotmath.com/hotmath_help/topics/finding-the-equation-of-a-parabola-given-focus-and-directrix.html
 // http://www.ams.org/samplings/feature-column/fcarc-voronoi
+// interactive: https://rosettacode.org/wiki/Voronoi_diagram#JavaScript
+// cell growth: http://www.raymondhill.net/voronoi/rhill-voronoi-demo5.html
+
+
+// modified from: http://stackoverflow.com/a/32863775
+// TODO: handle the situation where the two chosen points have the same Y
+function calculateCircleCenter(a, b, c) {
+    const yDelta_a = b.y - a.y,
+        xDelta_a = b.x - a.x,
+        yDelta_b = c.y - b.y,
+        xDelta_b = c.x - b.x;
+
+    const center = {};
+
+    const aSlope = yDelta_a / xDelta_a,
+        bSlope = yDelta_b / xDelta_b;
+
+    center.x = (aSlope*bSlope*(a.y - c.y) + bSlope*(a.x + b.x) - aSlope*(b.x+c.x) )/(2* (bSlope-aSlope) );
+    center.y = -1*(center.x - (a.x+b.x)/2)/aSlope +  (a.y+b.y)/2;
+    return center;
+}
+
+function circleEvent(a, b, c) {
+    const center = calculateCircleCenter(a, b, c),
+        radius = distance(center, a);
+    return {
+        center,
+        radius,
+        event: {
+            x: center.x,
+            y: center.y + radius,
+        },
+    };
+}
+
+//const circle = circleEvent(...circlePoints);
+//console.log('circle center', circle.center);
+//console.log('circle radius', circle.radius);
+//console.log('circle event', circle.event);
+//
+//ctx.save();
+//ctx.beginPath();
+//ctx.arc(circle.center.x, circle.center.y, circle.radius, 0, Math.PI * 2, false);
+//ctx.closePath();
+//ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
+//ctx.fill();
+//ctx.restore();
+//
+//drawSite(circle.center.x, circle.center.y, 'black');
+//drawSite(circle.event.x, circle.event.y, 'blue');
+
+const ss = generateSites(2),
+    directrix = Math.max(ss[0].y, ss[1].y) + Math.floor(Math.random() * 30) + 1;
+
+ss.forEach(function renderSites(site) {
+    drawSite(site.x, site.y);
+});
+drawLine(0, directrix, canvwidth, directrix);
+parabola(ss[0], directrix);
+parabola(ss[1], directrix);
+
+function incorrectParabolaIntersections(site1, site2, directrix) {
+    const a = directrix,
+        b = directrix,
+        X = site1.x - site2.x,
+        Y = site1.y - site2.y,
+        denom = 8 * a * (Math.pow(b, 2) - a);
+    if( denom === 0 ) {
+        console.log('zero!');
+        return [];
+    }
+    const a2 = Math.pow(a, 2),
+        a4 = Math.pow(a, 4),
+        b2 = Math.pow(b, 2),
+        Y2 = Math.pow(Y, 2),
+        first = -4 * a2 * Y,
+        second = Math.sqrt((16 * a4 * Y2) - (16 * a * (b2 - a) * ((4 * b2 * X) - (a * Y2))));
+
+    const option1 = (first - second) / denom,
+        option2 = (first + second) / denom;
+
+    console.log('a (d)', a, b);
+    console.log('X', X);
+    console.log('Y', Y);
+    console.log('1', (a * Y2));
+    console.log('2', (16 * a4 * Y2));
+    console.log('3', (16 * a * (b2 - a) * ((4 * b2 * X) - (a * Y2))));
+    console.log('4', ((16 * a4 * Y2) - (16 * a * (b2 - a) * ((4 * b2 * X) - (a * Y2)))));
+    console.log('first', first);
+    console.log('second', second);
+    console.log('denom', denom);
+    console.log('option1', option1);
+    console.log('option2', option2);
+}
+function parabolaIntersections(site1, site2, directrix) {
+    const a = site1.x,
+        b = site1.y,
+        c = site2.x,
+        e = site2.y,
+        d = directrix;
+    const denom = b - e;
+    if( denom === 0 ) {
+        console.log('zero.');
+        return [];
+    }
+    const a2 = Math.pow(a, 2),
+        b2 = Math.pow(b, 2),
+        c2 = Math.pow(c, 2),
+        e2 = Math.pow(e, 2),
+        d2 = Math.pow(d, 2),
+        first = (-b*d+b*e+d2-d*e),
+        second = a2 - 2*a*c + b2 - 2*b*e + c2 + e2,
+        fs = Math.sqrt(first * second),
+        third = a*d - a*e + b*c - c*d;
+    const option1 = (-fs + third) / denom,
+        option2 = (fs + third) / denom;
+    console.log('option1', option1);
+    console.log('option2', option2);
+    if( option1 === option2 ) {
+        return [option1];
+    }
+    return [option1, option2];
+}
+
+
+
+const inter = parabolaIntersections(...ss, directrix);
+inter.forEach(function (x) {
+    drawLine(x, 0, x, canvheight);
+});
+