score:4

This is an old question, but here is my solution. The idea is to draw the path connecting the nodes such that the end points are on the nodes' edges rather than at the nodes' centers. Starting from the Mobile Patent Suits example (http://bl.ocks.org/mbostock/1153292), I replaced the linkArc method with:

``````function drawCurve(d) {
var sourceX = d.source.x;
var sourceY = d.source.y;
var targetX = d.target.x;
var targetY = d.target.y;

var theta = Math.atan((targetX - sourceX) / (targetY - sourceY));
var phi = Math.atan((targetY - sourceY) / (targetX - sourceX));

var sinTheta = d.source.r * Math.sin(theta);
var cosTheta = d.source.r * Math.cos(theta);
var sinPhi = d.target.r * Math.sin(phi);
var cosPhi = d.target.r * Math.cos(phi);

// Set the position of the link's end point at the source node
// such that it is on the edge closest to the target node
if (d.target.y > d.source.y) {
sourceX = sourceX + sinTheta;
sourceY = sourceY + cosTheta;
}
else {
sourceX = sourceX - sinTheta;
sourceY = sourceY - cosTheta;
}

// Set the position of the link's end point at the target node
// such that it is on the edge closest to the source node
if (d.source.x > d.target.x) {
targetX = targetX + cosPhi;
targetY = targetY + sinPhi;
}
else {
targetX = targetX - cosPhi;
targetY = targetY - sinPhi;
}

// Draw an arc between the two calculated points
var dx = targetX - sourceX,
dy = targetY - sourceY,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + sourceX + "," + sourceY + "A" + dr + "," + dr + " 0 0,1 " + targetX + "," + targetY;
}
``````

Note that this code expects an "r," or radius, attribute to be in the node data. This would be equivalent to the size attribute in your jsfiddle. If you want to draw links as straight lines, you can return this string instead:

``````return "M" + sourceX + "," + sourceY + "L" + targetX + "," + targetY;
``````

To place the points of the arrows at the correct positions, I changed the refX and refY attributes so that the point of the arrow is at the edge of the node:

``````svg.append("defs").selectAll("marker")
.data(["suit", "licensing", "resolved"])
.enter().append("marker")
.attr("id", function(d) { return d; })
.attr("viewBox", "0 -5 10 10")
.attr("refX", 10)
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
``````