I am trying to draw realistic (non-straight) borders of randomly generated countries using d3.geoVoronoi and topojson.merge. This is what I am doing:
- I create 3 Voronoi diagrams, say A, B and C, respectively with 100, 1000, and 10000 cells.
- I merge the voronoi cells of B (1000 cells) if their centroid is contained in the same cell of A (100 cells). In this way I obtain B', with 100 cells having irregular borders.
- I repeat point 2, this time merging the cells of C (10000) if their centroid belongs to B'. I thus obtain B'', with 100 cells with even more realistic borders.
In principle the procedure could be repeated to obtain even more detailed borders, but I am already running into problems. When I draw B'' (black lines in the figures), it looks weird. Why? Does it have to do with the winding order of B'? How can I fix this?
Figures: Figure 1, Figure 2, Figure 3
const v_land = d3.geoVoronoi(land_Points);
let countries_polygons_land = v_land.polygons(land_Points);
const countries_topology2 = {
type: "Topology",
polygons: countries_polygons_land
};
const countries_topoJSON_land = topojson.topology(countries_topology2);
const countries_geojson_land = topojson.feature(countries_topoJSON_land, countries_topoJSON_land.objects.polygons);
// MERGE
let mergedGeoJSON = countries_geojson_land;
let featureCluster = create2DArray(mergedGeoJSON.features.length);
let newFeature;
for (let k=1; k<points.length; k++) {
// Merge smaller states within greater boundaries
for (let i=0; i < mergedGeoJSON.features.length; i++) {
for (let j=0; j < countries_geojson[k].features.length; j++) {
if(d3.geoContains(mergedGeoJSON.features[i], d3.geoCentroid(countries_geojson[k].features[j]))) {
featureCluster[i].push(countries_topoJSON[k].objects.polygons.geometries[j]);
}
}
}
// Create geoJSON
mergedGeoJSON = {
type: "FeatureCollection",
features: []
}
for (let i=0; i < featureCluster.length; i++) {
newFeature = {
type: "Feature",
geometry: topojson.merge(countries_topoJSON[k], featureCluster[i])
}
mergedGeoJSON.features.push(newFeature);
}
// Draw Polygons (realistic)
ctx.beginPath(),
path(mergedGeoJSON),
ctx.strokeStyle = `rgba(0, 0, 0, 1)`,
ctx.lineWidth = 0.5*k,
ctx.lineJoin = 'round',
ctx.stroke();
}