Published
Edited
Nov 26, 2018
1 star
Insert cell
Insert cell
{
const context = DOM.context2d(width, width);
context.translate(width / 2, width / 2);

const lightGray = "rgba(100, 100, 100, 0.5)";
const darkGray = "rgba(50, 50, 50, 0.8)";

const center = [0, 0, 250];
circle(center, context, { fill: false });
const tangentPoints = [];
for (let i = 0; i < 4; ++i) {
tangentPoints.push(pointOnCircle(center, i * 90));
}

const tangentLines = tangentPoints.map((p, i) => {
const angle = getAlphaBetweenPoints(
p,
tangentPoints[(i + 1) % tangentPoints.length]
);
return lineThrough(p, (i - 1) * 90, context, { color: "blue" });
});

const points = tangentLines.map((l, i) => {
return intersectionLL(l, tangentLines[(i + 1) % tangentLines.length]);
});

const bisectors = points.map((point, i) => {
circle(point, context);
const nextPoint = points[(i + 1) % points.length];
const connection = line(point, nextPoint, context, { color: darkGray });
const centerPoint = pointOnLine(connection, 0.5);
circle([...centerPoint, 3], context);
const connectionAngle = getAlphaBetweenPoints(point, centerPoint);
return lineThrough(centerPoint, connectionAngle + 90, context, {
dash: [5, 10],
color: lightGray
});
});

const innerQuad = bisectors.map((bisector, i) => {
const nextBisector = bisectors[(i + 1) % bisectors.length];
const intersection = intersectionLL(bisector, nextBisector);
circle([...intersection, 3], context);
return intersection;
});

innerQuad.forEach((point, i) => {
const nextPoint = innerQuad[(i + 1) % innerQuad.length];
line(point, nextPoint, context);
});

const incenter = incenterConvexQuadr(innerQuad, context);
if (incenter) {
circle([...incenter, 3], context);

const incenters = points.map((p, i) => {
line(p, incenter, context, { color: darkGray });
const ic = incircleTriangle([
p,
points[(i + 1) % points.length],
incenter
]);
circle(ic, context, { fill: false, dash: [5, 10] });
circle([ic[0], ic[1], 3], context);
return ic;
});

const circumCenter = intersectionLL(
[incenters[0], incenters[2]],
[incenters[1], incenters[3]]
);

circle([...circumCenter, 3], context, { color: "red" });

const circumR = dist2D(incenters[0], circumCenter);
circle([...circumCenter, circumR], context, {
fill: false,
color: "red"
});
}

return context.canvas;
}
Insert cell
function incenterConvexQuadr([a, b, c, d]) {
const points = [a, b, c, d];
const halfDegs = [
halfDeg(a, b, d),
halfDeg(b, a, c),
halfDeg(c, b, d),
halfDeg(d, a, c)
];
const lines = halfDegs.map((hd, i) =>
lineThroughWithoutDrawing(points[i], hd)
);
const intersection = lines
.map((l, i) => intersectionLL(l, lines[(i + 1) % lines.length]))
.reduce((acc, intersection, i) => {
if (i === 0 || !Array.isArray(acc)) return intersection;
const [xa, ya] = acc;
const [xb, yb] = intersection;
return Math.floor(xa) === Math.floor(xb) &&
Math.floor(ya) === Math.floor(yb)
? intersection
: false;
});

return intersection;
}
Insert cell
function lineThroughWithoutDrawing(point, deg) {
const dist = 1000;
const p1 = coordsFromDeg(deg, dist, point);
const p2 = coordsFromDeg(deg, -dist, point);
return [p1, p2];
}
Insert cell
import {
circle,
line,
pointOnLine,
dist2D,
lineThrough,
getAlphaBetweenPoints,
intersectionLL,
halfDeg,
coordsFromDeg,
incircleTriangle,
pointOnCircle,
} from '@timhau/geometry'
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more