Saya perhatikan bahwa garis lurus melengkung terhadap proyeksi, tetapi wilayah Voronoi berada dalam garis lurus.
Mungkinkah "memaksa" wilayah Voronoi juga dilengkungkan dan diterapkan pada proyeksi topojson seperti garis lurus dan koordinat lintang/bujur?
Peta asli: http://bl.ocks.org/mbostock/7608400
Bagian dari kode saya:
var projection = d3.geo.kavrayskiy7()
.center([center_lon, center_lat])
.scale(zoom)
.translate([width / 2, height / 2])
var graticule = d3.geo.graticule();
var path = d3.geo.path()
.projection(projection);
var voronoi = d3.geom.voronoi()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.clipExtent([[0, 0], [width, height]]);
var svg = d3.select(that.el).append("svg")
.attr("width", width)
.attr("height", height);
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
svg.append("path")
.datum(graticule.outline)
.attr("class", "graticule outline")
.attr("d", path);
d3.json("/static/app/custom_vizs/components/voronoi/readme-world.json", function(error, world) {
var countries = topojson.feature(world, world.objects.countries).features,
neighbors = topojson.neighbors(world.objects.countries.geometries);
svg.selectAll(".country")
.data(countries)
.enter().insert("path", ".graticule")
.attr("class", "country")
.attr("d", path);
var format = d3.format(",");
var get_points_by_id = d3.map(),
positions = [];
var src = _(data).chain().groupBy(src_field).each(function(v, k, o) { o[k] = v; }).value();
var dst = _(data).chain().groupBy(dst_field).each(function(v, k, o) { o[k] = v; }).value();
var uniques = _(dst).extend(src);
var max = 0;
var points = _(uniques).map(function(v, k) {
var o = {};
o.id = k;
o.value = _(v).pluck(count_field).reduce(function(memo, num) { return memo + parseFloat(num); }, 0);
max = Math.max(max, o.value);
if(v[0][src_field] === k) {
o.lat = v[0][src_lat_field];
o.lon = v[0][src_lon_field];
}
else {
o.lat = v[0][dst_lat_field];
o.lon = v[0][dst_lon_field];
}
return o;
});
points.forEach(function(d) {
get_points_by_id.set(d.id, d);
d.outgoing = [];
d.incoming = [];
});
data.forEach(function(connection) {
var source = get_points_by_id.get(connection[src_field]),
target = get_points_by_id.get(connection[dst_field]),
link = {source: source, target: target};
source.outgoing.push(link);
target.incoming.push(link);
});
points = points.filter(function(d) {
if (d.count = Math.max(d.incoming.length, d.outgoing.length)) {
d[0] = +d.lon;
d[1] = +d.lat;
var position = projection(d);
d.x = position[0];
d.y = position[1];
return true;
}
});
voronoi(points)
.forEach(function(d) { d.point.cell = d; });
var point = svg.append("g")
.attr("class", "points")
.selectAll("g")
.data(points.sort(function(a, b) { return b[count_field] - a[count_field]; }))
.enter().append("g")
.attr("class", "point");
point.append("path")
.attr("class", "point-cell")
.attr("d", function(d) { return d.cell.length ? "M" + d.cell.join("L") + "Z" : null; });
point.append("g")
.attr("class", "point-arcs")
.selectAll("path")
.data(function(d) { return d.outgoing; })
.enter().append("path")
.attr("d", function(d) { return path({type: "LineString", coordinates: [d.source, d.target]}); });
point.append("circle")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.attr("r", function(d, i) { return d.value/max*max_circle_size; });
point.append("title")
.text(function(d) {
return d.id + ": " +
format(d.outgoing.length) + " distinct outgoing, " +
format(d.incoming.length) + " distinct incoming, " +
format(d.value) + " total";
});
});