Skip to content

Instantly share code, notes, and snippets.

@emeeks
Last active August 29, 2015 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emeeks/10567716 to your computer and use it in GitHub Desktop.
Save emeeks/10567716 to your computer and use it in GitHub Desktop.
Merge Countries Based on Centroid

One of the advantages of topojson is the ability to merge polygons, but a topojson array doesn't consist of features. So if you wanted to merge features based on their geospatial attributes, you need to use topojson.features() in your filter of your topojson data array so that you can use d3.geo.centroid() or d3.geo.bounds()

In this example, all countries with a centroid that has an X position of less than 0 longitude are merged using the mergeAt() function.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Satellite Projection Explorer</title>
<meta charset="utf-8" />
</head>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="http://d3js.org/colorbrewer.v1.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<style>
</style>
<body onload="topoMerge();">
<div id="controls">
</div>
<div id="vizcontainer">
<svg style="width:500px;height:500px;border:1px lightgray solid;" />
<div style="position:absolute;top:30px;left:10px;" id="settings" />
</div>
<footer>
<script>
function topoMerge() {
d3.json("/emeeks/raw/9980626/world.json", createMap);
function createMap(countries1) {
var countries = topojson.feature(countries1, countries1.objects.countries)
width = 500;
height = 500;
projection = d3.geo.mollweide()
.scale(120)
.translate([width / 2, height / 2])
geoPath = d3.geo.path().projection(projection);
featureSize = d3.extent(countries.features, function(d) {return geoPath.area(d)});
countryColor = d3.scale.quantize().domain(featureSize).range(colorbrewer.Reds[7]);
var graticule = d3.geo.graticule();
d3.select("svg").append("path")
.datum(graticule)
.attr("class", "graticule line")
.attr("d", geoPath)
.style("fill", "none")
.style("stroke", "lightgray")
.style("stroke-width", "1px");
d3.select("svg").append("path")
.datum(graticule.outline)
.attr("class", "graticule outline")
.attr("d", geoPath)
.style("fill", "none")
.style("stroke", "black")
.style("stroke-width", "1px");
d3.select("svg").selectAll("path.countries").data(countries.features)
.enter()
.append("path")
.attr("d", geoPath)
.attr("class", "countries")
.style("fill", function(d) {return countryColor(geoPath.area(d))})
.style("stroke-width", 1)
.style("stroke", "black")
.style("opacity", .5)
mergeAt(0);
function mergeAt(boundingBox) {
var filteredCountries = countries1.objects.countries.geometries.filter(function(d) {
thisCenter = d3.geo.centroid(
topojson.feature(countries1, d)
);
return thisCenter[0] < boundingBox ? true : null;
}
)
d3.select("svg").append("g")
.datum(topojson.merge(countries1, filteredCountries))
.style("opacity", .7)
.append("path")
.style("fill", "darkgray")
.style("stroke", "black")
.style("stroke-width", "2px")
.attr("d", geoPath)
}
}
}
</script>
</footer>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment