Given a set of voronio centers (i.e. a list of center coordinates for each of them), we can calculate the area closest to each center:
area[i] = areaClosestTo(i,positions)
Suppose this is a little wrong, because we do not have centers in the right place. Thus, we can calculate the error in our current set by comparing the areas with ideal areas:
var areaIndexSq = 0; var desiredAreasMagSq = 0; for(var i = 0; i < areas.length; ++i) { var contrib = (areas[i] - desiredAreas[i]); areaIndexSq += contrib*contrib; desiredAreasMagSq += desiredAreas[i]*desiredAreas[i]; } var areaIndex = Math.sqrt(areaIndexSq/desiredAreasMagSq);
This is the vector norm of the vector of differences between regions and desired ones. Think of it as how good a line with least squares is.
We also need some kind of honeycomb template, so we can call it honeycombness(positions) and get a general assessment of the quality of the thing (it's just a starter, the weight or shape of this can be anything that the boat floats):
var overallMeasure = areaIndex + honeycombnessIndex;
Then we have a mechanism to know how bad the assumptions are, and we can combine this with a mechanism for changing positions; The easiest way is to simply add a random amount to the x and y coordinates of each center. Alternatively, you can try moving each point to neighboring areas with too high an area and away from those with too low an area.
This is not a direct solution, but it requires minimal mathematics, in addition to calculating the area closest to each point and accessible. The hard part can be recognized by local lows and deal with them.
By the way, it's easy enough to get the starting points for the process; pie centroids should not be too far from the truth.
A definite plus is that you could use intermediate calculations to animate the transition from pie to voronoi.