circular = {
const width = 400;
const height = 400;
const c = DOM.context2d(width, height);
const center = [150, 150];
const r = 120;
const tickSize = 3;
const rectX = 20;
const rectY = 20;
const rectW = 100;
const rectH = 100;
c.fillStyle = "rgba(200, 200, 200, 0.5)";
c.fillRect(rectX, rectY, rectW, rectH);
c.strokeStyle = "black";
c.beginPath();
c.moveTo(center[0], center[1] - tickSize);
c.lineTo(center[0], center[1] + tickSize);
c.closePath();
c.stroke();
c.beginPath();
c.moveTo(center[0] - tickSize, center[1]);
c.lineTo(center[0] + tickSize, center[1]);
c.closePath();
c.stroke();
c.fillStyle = "none";
c.strokeStyle = "black";
c.beginPath();
c.arc(center[0], center[1], r, Math.PI, (Math.PI * 3) / 2);
c.stroke();
c.closePath();
const findIntersections = (x1, y1, x2, y2, cx, cy, r) => {
let dx = x2 - cx - (x1 - cx);
let dy = y2 - cy - (y1 - cy);
let dr = Math.sqrt(dx * dx + dy * dy);
let dd = (x1 - cx) * (y2 - cy) - (x2 - cx) * (y1 - cy);
const sgn = (v) => {
return v < 0 ? -1 : 1;
};
let delta = r * r * dr * dr - dd * dd;
if (delta < 0) {
return [];
}
let ix1 =
(dd * dy + sgn(dy) * dx * Math.sqrt(r * r * dr * dr - dd * dd)) /
(dr * dr) +
cx;
let iy1 =
(-dd * dx + Math.abs(dy) * Math.sqrt(r * r * dr * dr - dd * dd)) /
(dr * dr) +
cy;
let ix2 =
(dd * dy - sgn(dy) * dx * Math.sqrt(r * r * dr * dr - dd * dd)) /
(dr * dr) +
cx;
let iy2 =
(-dd * dx - Math.abs(dy) * Math.sqrt(r * r * dr * dr - dd * dd)) /
(dr * dr) +
cy;
let intersections = [];
if (x1 <= ix1 && ix1 <= x2 && y1 <= iy1 && iy1 <= y2) {
intersections.push([ix1, iy1]);
}
if (x1 <= ix2 && ix2 <= x2 && y1 <= iy2 && iy2 <= y2) {
intersections.push([ix2, iy2]);
}
return intersections;
};
let edges = [
[rectX, rectY, rectX + rectW, rectY],
[rectX, rectY, rectX, rectY + rectH],
[rectX + rectW, rectY, rectX + rectW, rectY + rectH],
[rectX, rectY + rectH, rectX + rectW, rectY + rectH]
];
for (let edge of edges) {
const intersections = findIntersections(
edge[0],
edge[1],
edge[2],
edge[3],
center[0],
center[1],
r
);
for (let i of intersections) {
c.fillStyle = "red";
c.fillRect(i[0] - 2, i[1] - 2, 4, 4);
}
}
return c.canvas;
}