I've run across another limitation of the convex hull implementation of D3: it does not adjust to the size of the nodes. Well, I didn't expect that it would do so automatically, but this seems like a fairly standard aspect of the data visualizations people are using D3.js, so I expected to find a fix for it. I have not found such a fix.
One obvious and unsatisfactory solution is to find the size of the largest node of the group and set that as the stroke-width of the hull. Unfortunately that looks terrible then the node sizes are highly variable.
I've tried to extend the thinking of inserting fake points to account for groups with 1 or 2 members. In this case I added four points per node that are located at the N,S,E, and W boundaries of the node.
var groupPath = function(d) {
var fakePoints = []; // This adjusts convex hulls for groups with fewer than 3 nodes by adding virtual nodes.
if (d.length == 1 || d.length == 2) {
fakePoints = [ [d[0].x + 0.001, d[0].y - 0.001],
[d[0].x - 0.001, d[0].y + 0.001],
[d[0].x - 0.001, d[0].y + 0.001]]; }
return "M" +
d3.geom.hull(d.map(function(i) { return [
[(i.x), (i.y + (2 + (4 * i.propertyValue)))],
[(i.x + (2 + (4 * i.propertyValue))), (i.y)],
[(i.x), (i.y - (2 + (4 * i.propertyValue)))],
[(i.x - (2 + (4 * i.propertyValue))), (i.y) ]]; })
.concat(fakePoints)) //do not forget to append the fakePoints to the input data
.join("L")
+ "Z";
};
...in which (2 + (4 * i.propertyValue))
is the radius of the node. Then I made the the stroke width just the distance from the edge of the node to the outer edge of the convex hull...the padding. This seemed like a good idea, but it TOTALLY doesn't work. The result is very puzzling because it doesn't even create the convex hull of those points...and the order matters. You can see what it actually does in this JSFiddle.
I first thought the fakepoints were causing the problem, and maybe they are in some way, but if you remove them this the convex hull doesn't work for groups with 1 or 2 nodes...which is weird because I thought I was already adding 4 points to the input of the convex hull. One (likely) possibility is that I am not adding these four points in the right way, but I don't know what way, different from this, is the correct way.
Maybe there is an easy fix for this for somebody who better understands how D3 is creating the convex hulls. That is, maybe somebody can see what is wrong with my method and help me fix it, or maybe somebody already has a completely better way to do this.