{
const lines = [
[[430, 180], [500, 170]],
[[400, 300], [410, 200]],
[[500, 340], [420, 320]]
].map(line => line.map(([x, y]) => {
return [x / 954 * width, y];
}));
const svg = d3.select(DOM.svg(width, height));
const line = svg.append("g")
.attr("stroke", "#ccc")
.selectAll("line")
.data(lines)
.enter().append("line");
const lineSegment = svg.append("g")
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.selectAll("line")
.data(lines)
.enter().append("line");
const lineBisect = svg.append("g")
.selectAll("line")
.data([
[lines[0], lines[1], +1],
[lines[0], lines[2], +1],
[lines[1], lines[2], +1],
[lines[0], lines[1], -1],
[lines[0], lines[2], -1],
[lines[1], lines[2], -1]
])
.enter().append("line")
.attr("stroke", ([l0, l1, k]) => k > 0 ? "red" : "blue");
const circle = svg.append("g")
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.selectAll("circle")
.data([
[+1, +1],
[-1, +1],
[-1, -1],
[+1, -1]
])
.enter().append("circle");
const point = svg.append("g")
.attr("cursor", "move")
.attr("pointer-events", "all")
.attr("stroke", "transparent")
.attr("stroke-width", 30)
.selectAll("circle")
.data(d3.merge(lines))
.enter().append("circle")
.attr("r", 2.5)
.call(d3.drag()
.subject(([x, y]) => ({x, y}))
.on("drag", dragged));
update();
function dragged(d) {
d[0] = d3.event.x;
d[1] = d3.event.y;
update();
}
function update() {
point
.attr("cx", d => d[0])
.attr("cy", d => d[1]);
line.data(lines.map(l => lineExtend(...l)))
.attr("x1", d => d[0][0])
.attr("y1", d => d[0][1])
.attr("x2", d => d[1][0])
.attr("y2", d => d[1][1]);
lineSegment
.attr("x1", d => d[0][0])
.attr("y1", d => d[0][1])
.attr("x2", d => d[1][0])
.attr("y2", d => d[1][1]);
lineBisect.each(function([l0, l1, k]) {
const b01 = lineLineBisect(...l0, ...l1, k);
if (!b01) return;
const b = lineExtend(...b01);
d3.select(this)
.attr("x1", b[0][0])
.attr("y1", b[0][1])
.attr("x2", b[1][0])
.attr("y2", b[1][1]);
});
circle.each(function([k0, k1]) {
const b01 = lineLineBisect(...lines[0], ...lines[1], k0);
const b12 = lineLineBisect(...lines[1], ...lines[2], k1);
if (!b01 || !b12) return;
const b0 = lineExtend(...b01);
const b1 = lineExtend(...b12);
const [x, y] = lineLineIntersect(...b0, ...b1);
const r = Math.abs(pointLineDistance([x, y], ...lines[0]));
d3.select(this)
.attr("cx", x)
.attr("cy", y)
.attr("r", r);
});
}
return svg.node();
}