{
const g = clone(kgSW);
const bendDivSW = 1 / bendySW;
const r = new Renderer(w, h, rType)
.pointSize(32)
.textAlign("middle")
.textBaseline("middle")
.textSize(16);
const toPoint = (n) => [n.x, n.y];
const toLine = (e) => [
[e.source.x, e.source.y],
[e.target.x, e.target.y]
];
const flowCurve = (e) => [
[e.source.x, e.source.y],
[
e.target.x - (e.source.y - e.target.y) / bendDivSW,
e.target.y + (e.source.x - e.target.x) / bendDivSW
],
[e.target.x, e.target.y],
[e.target.x, e.target.y]
];
const drawFrame = () => {
r.clear().stroke("black");
g.edges.forEach(
(e) => (picked >= 0 && (e.source == g.nodes[picked] || e.target == g.nodes[picked])) ?
r.strokeWidth(e.w).stroke("rgb(255,0,0)").fill("").bezier(flowCurve(e)) :
r.strokeWidth(e.w).stroke("rgb(0,0,0)").fill("").bezier(flowCurve(e))
);
g.nodes.forEach(
(n) => (picked >= 0 && g.nodes[picked] == n) ?
r.strokeWidth(2).stroke("rgb(255,0,0)").fill("rgb(220,140,95)").points([toPoint(n)]) :
r.strokeWidth(2).stroke("rgb(0,0,0)").fill("rgb(220,140,95)").points([toPoint(n)])
);
r.fill("black").stroke().textSize(8).textAlign("middle");
g.nodes.forEach((n) => r.text(n.name, n.x, n.y));
};
simSW.nodes(g.nodes).on("tick", drawFrame);
simSW.force("fEdge").links(g.edges);
let picked = -1;
r.addListener("mousedown", (ev) => {
let p = d3.pointer(ev);
for (let i=0; i<g.nodes.length; i++){
let dist = (p[0]-g.nodes[i].x)*(p[0]-g.nodes[i].x) + (p[1]-g.nodes[i].y)*(p[1]-g.nodes[i].y)
if (dist < 100){
picked = i;
drawFrame();
break;
}
}
});
r.addListener("mouseup", (ev) => {
picked = -1;
drawFrame();
});
r.addListener("mousemove", (ev) => {
if (picked >= 0){
g.nodes[picked].x = d3.pointer(ev)[0];
g.nodes[picked].y = d3.pointer(ev)[1];
drawFrame();
}
});
return r.render();
}