Skip to content

Instantly share code, notes, and snippets.

@BriSeven
Created May 9, 2016 11:58
Show Gist options
  • Select an option

  • Save BriSeven/1d14ad2f69ef11743a5ac8f36af2fede to your computer and use it in GitHub Desktop.

Select an option

Save BriSeven/1d14ad2f69ef11743a5ac8f36af2fede to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex, nofollow">
<meta name="googlebot" content="noindex, nofollow">
/*
faulty input ranges for appolonius problem
Causes NaN or Infinity
{r1: "0.22", r2: "0.21", r3: "0.22", cur: "0.01"}
{r1: "0.36", r2: "0.21", r3: "0.36", cur: "0.15"}
{r1: "0.23", r2: "0.31", r3: "0.23", cur: "0.08"}
{r1: "0.24", r2: "0.41", r3: "0.24", cur: "0.17"}
whole range of NaNs:
{r1: "0.15", r2: "0.24", r3: "0.79", cur: "0.11"}
{r1: "0.15", r2: "0.25", r3: "0.79", cur: "0.11"}
{r1: "0.15", r2: "0", r3: "0.79", cur: "0.11"}
{r1: "0.15", r2: "0.28", r3: "0.81", cur: "0.11"}
{r1: "0.15", r2: "0.28", r3: "1", cur: "0.11"}
{r1: "0.15", r2: "0.28", r3: "0.79", cur: "0.08"}
{r1: "0.15", r2: "0.28", r3: "0.79", cur: "-0.1"}
outside of "parameters"
Object {r1: "0.5", r2: "0.57", r3: "0.79", cur: "0.29"}
*/
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/zepto/1.0rc1/zepto.min.js"></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<style type="text/css">
canvas {
border:solid black 1px;
}
</style>
<title></title>
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
var canvas = $("canvas")[0];
var ctx = canvas.getContext("2d");
var sqrt = Math.sqrt;
var min = Math.min;
var max = Math.max;
var abs = Math.abs;
var atan2 = Math.atan2;
var cos = Math.cos;
var sin = Math.sin;
var kappa = 4 * (sqrt(2) - 1) / 3;
var r1 = 0.4;
var r3 = 0.5;
var r2 = 0.2;
var cur=0.01;
var x1 = 1;
var y1 = 0;
var x2 = 0;
var y2 = 0;
var x3 = (x1+x2)/2+cur;
var y3 = (y1+y2)/2+cur;
$("[name=r1]").on("mousemove", function () {
r1 = +this.value;
recalc();
redraw(ctx);
})
$("[name=r2]").on("mousemove", function () {
r2 = +this.value;
recalc();
redraw(ctx);
})
$("[name=r3]").on("mousemove", function () {
r3 = +this.value;
recalc();
redraw(ctx);
})
$("[name=cur]").on("mousemove", function () {
cur = +this.value;
recalc();
redraw(ctx);
})
function coords(x, y, s) {
return {
x: (x * 100 + 250),
y: (-y * 100 + 250),
s: s * 100
};
}
function drawCircle(ctx, x, y, r) {
var c = coords(x, y, r);
ctx.beginPath();
ctx.arc(c.x, c.y, c.s, 0, 2 * Math.PI);
ctx.stroke();
}
function drawTan(ctx, x, y, m) {
var c = coords(x, y, 0);
var len = 0.3;
var x1 = x - len;
var x2 = x + len;
var y1 = y - (m * len);
var y2 = y + (m * len);
var c1 = coords(x1, y1, 0);
var c2 = coords(x2, y2, 0);
ctx.beginPath();
ctx.moveTo(c1.x, c1.y);
ctx.lineTo(c2.x, c2.y);
ctx.stroke();
}
function drawSquare(ctx, x, y, s) {
var c = coords(x, y, s);
ctx.beginPath();
ctx.rect(c.x - c.s, c.y - c.s, c.s * 2, c.s * 2);
ctx.stroke();
}
function appolonius(x1, y1, r1, x2, y2, r2, x3, y3, r3, s1, s2, s3) {
function calca(x, y) {
return 2 * y - 2 * x;
}
function calcc(r1, r2, s1, s2) {
return 2 * s2 * r2 - 2 * s1 * r1;
}
function calcd(x1, y1, r1, x2, y2, r2) {
return r2 * r2 - r1 * r1 + x1 * x1 - x2 * x2 + y1 * y1 - y2 * y2;
}
var a1, b1, c1, d1, a2, b2, c2, d2, w12, w13, w14, w22, w23, w24, P, Q, M, N, A, B, C, Rs;
a1 = calca(x1, x2);
b1 = calca(y1, y2);
c1 = calcc(r1, r2, s1, s2);
d1 = calcd(x1, y1, r1, x2, y2, r2);
a2 = calca(x2, x3);
b2 = calca(y2, y3);
c2 = calcc(r2, r3, s2, s3);
d2 = calcd(x2, y2, r2, x3, y3, r3);
w12 = b1 / a1;
w13 = d1 / a1;
w14 = c1 / a1;
w22 = b2 / a2 - w12;
w23 = d2 / a2 - w13;
w24 = c2 / a2 - w14;
P = -w23 / w22;
Q = w24 / w22;
M = -w12 * P - w13;
N = w14 - w12 * Q;
A = N * N + Q * Q - 1;
B = 2 * N * (M - x1) + 2 * Q * (P - y1) + 2 * s1 * r1;
C = M * M + x1 * x1 - 2 * M * x1 + P * P + y1 * y1 - 2 * P * y1 - r1 * r1;
Rs = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
return [M + N * Rs, P + Q * Rs, Math.abs(Rs)];
}
function touchpoint(x1, y1, r1, x2, y2, r2) {
var x = 0,
y = 0;
var dx = x1 - x2;
var dy = y1 - y2;
var l = sqrt(dx * dx + dy * dy);
var m = -dx / dy;
return [(dx / l) * r2 + x2, (dy / l) * r2 + y2, m];
}
function endpoint(x1, y1, x2, y2, xc, yc, s) {
var dx = x1 - xc;
var dy = y1 - yc;
var ex = x2 - xc;
var ey = y2 - yc;
var r = sqrt(dx * dx + dy * dy);
var a1 = atan2(dy, dx);
var a2 = atan2(ey, ex);
var a3 = (a1 + a2) / 2 + (((a1 - a2) > 0) ^ s ? Math.PI : 0);
var x = cos(a3) * r + xc;
var y = sin(a3) * r + yc;
var m = -cos(a3) / sin(a3)
return [x, y, m];
}
function intersectPoint(x1, y1, m1, x2, y2, m2) {
// m1*(x-x1) + y1 = y
// m2*(x-x2) + y2 = y
// m2*(x-x2) + y2 = m1*(x-x1) + y1;
// m2*(x-x2) + y2 - m1*(x-x1) - y1 = 0;
// (m2*x - m2*x2) + y2 - (m1*x - m1*x1) - y1 = 0;
// m2*x - m2*x2 + y2 - m1*x + m1*x1 - y1 = 0;
// m2*x - m2*x2 + y2 + m1*x1 - y1 = + m1*x
// - m2*x2 + y2 + m1*x1 - y1 = + m1*x - m2*x
// - m2*x2 + y2 + m1*x1 - y1 = x*(m1 - m2)
// (-m2*x2 + y2 + m1*x1 - y1)/(m1 - m2) = x
var x = (-m2 * x2 + y2 + m1 * x1 - y1) / (m1 - m2);
var y = m1 * (x - x1) + y1;
return [x, y]
}
function recalc() {
x3 = (x1+x2)/2;
y3 = (y1+y2)/2+cur;
r = appolonius(x1, y1, r1, x2, y2, r2, x3, y3, r3, 1, 1, 1);
rs = appolonius(x1, y1, r1, x2, y2, r2, x3, y3, r3, -1, -1, -1);
console.log(x1, y1, r1, x2, y2, r2, x3, y3, r3, -1, -1, -1)
; console.log(r,rs);
t1 = touchpoint(x1, y1, r1, r[0], r[1], r[2]);
t2 = touchpoint(x2, y2, r2, r[0], r[1], r[2]);
t3 = touchpoint(x1, y1, r1, rs[0], rs[1], rs[2]);
t4 = touchpoint(x2, y2, r2, rs[0], rs[1], rs[2]);
e1 = endpoint(t1[0], t1[1], t3[0], t3[1], x1, y1, 1);
e2 = endpoint(t2[0], t2[1], t4[0], t4[1], x2, y2, 0);
i1 = intersectPoint(t1[0], t1[1], t1[2], t2[0], t2[1], t2[2]);
i2 = intersectPoint(t1[0], t1[1], t1[2], e1[0], e1[1], e1[2]);
i3 = intersectPoint(e1[0], e1[1], e1[2], t3[0], t3[1], t3[2]);
i4 = intersectPoint(t3[0], t3[1], t3[2], t4[0], t4[1], t4[2]);
i5 = intersectPoint(t4[0], t4[1], t4[2], e2[0], e2[1], e2[2]);
i6 = intersectPoint(t2[0], t2[1], t2[2], e2[0], e2[1], e2[2]);
}
function redraw(ctx) {
ctx.clearRect(0, 0, 500, 500);
drawCircle(ctx, x1, y1, r1);
drawCircle(ctx, x2, y2, r2);
drawCircle(ctx, x3, y3, r3);
drawCircle(ctx, r[0], r[1], r[2]);
drawCircle(ctx, rs[0], rs[1], rs[2]);
drawSquare(ctx, i1[0], i1[1], 0.01);
drawSquare(ctx, i2[0], i2[1], 0.01);
drawSquare(ctx, i3[0], i3[1], 0.01);
drawSquare(ctx, i4[0], i4[1], 0.01);
drawSquare(ctx, i5[0], i5[1], 0.01);
drawSquare(ctx, i6[0], i6[1], 0.01);
drawTan(ctx, t1[0], t1[1], t1[2]);
drawTan(ctx, t2[0], t2[1], t2[2]);
drawTan(ctx, t3[0], t3[1], t3[2]);
drawTan(ctx, t4[0], t4[1], t4[2]);
drawTan(ctx, e1[0], e1[1], e1[2]);
drawTan(ctx, e2[0], e2[1], e2[2]);
drawCircle(ctx, t1[0], t1[1], 0.02);
drawCircle(ctx, t2[0], t2[1], 0.02);
drawCircle(ctx, t3[0], t3[1], 0.02);
drawCircle(ctx, t4[0], t4[1], 0.02);
drawCircle(ctx, e1[0], e1[1], 0.02);
drawCircle(ctx, e2[0], e2[1], 0.02);
}
recalc();
redraw(ctx);
}//]]>
</script>
</head>
<body>
<input type="range" min="0" max="1" name="r1" step="0.01">
<input type="range" min="0" max="1" name="r3" step="0.01">
<input type="range" min="0" max="1" name="r2" step="0.01">
<input type="range" min="-1" max="1" name="cur" step="0.01">
<canvas width=500 height=500></canvas>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment