Skip to content

Instantly share code, notes, and snippets.

@jczaplew
Last active December 28, 2015 22:39
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 jczaplew/7573392 to your computer and use it in GitHub Desktop.
Save jczaplew/7573392 to your computer and use it in GitHub Desktop.
Pole-wrapping geometry issue

These three maps demonstrate that under some conditions, the winding order of large polygons that wrap the poles is incorrectly guessed by D3. Converting to Topojson (topojson -o plates.topojson -p --no-stitch-poles -- plates.geojson) forces a consistent winding order (see https://github.com/mbostock/d3/wiki/Geo-Paths#wiki-_path), but in this case does not fix the problem.

It is also important to note that this error only throws an error in Chrome Canary and simply does not draw the problematic polygon, whereas in every other browser (Chrome Stable, Firefox, Safari) no error is thrown to the console and the problematic polygon is draw with the wrong winding order.

<!DOCTYPE html>
<html lang="en" xml:lang="en" xmlns= "http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8"/>
<meta http-equiv="Content-Language" content="en" />
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
<style>
#map {
height:500px;
}
.plates {
fill: #fff;
stroke:#000;
stroke-width:1px;
}
.leaflet-container {
background: #000;
}
</style>
</head>
<body>
<p>GeoJSON</p>
<div id="svgMap"></div>
<p>Topojson</p>
<div id="topoMap"></div>
<p>GeoJSON rendered by Leaflet</p>
<div id="map"></div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js" charset="utf-8"></script>
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
<script type="text/javascript">
var height = 500,
width = 960;
var projection = d3.geo.hammer()
.scale(165)
.translate([width / 2, height / 2])
.precision(.3);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("#svgMap")
.append("svg")
.attr("height", height)
.attr("width", width);
svg.append("defs").append("path")
.datum({type: "Sphere"})
.attr("id", "sphere")
.attr("d", path);
svg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
svg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
// Build the topojson map
var topoSvg = d3.select("#topoMap")
.append("svg")
.attr("height", height)
.attr("width", width);
topoSvg.append("defs").append("path")
.datum({type: "Sphere"})
.attr("id", "sphere")
.attr("d", path);
topoSvg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
topoSvg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
d3.json("plates.topojson", function(er, data) {
topoSvg.selectAll(".plates")
.data(topojson.feature(data, data.objects.plates).features)
.enter().append("path")
.attr("class", "plates")
.attr("id", function(d) { return d.properties.FEATURE_ID})
.attr("d", path);
});
var map = new L.map("map", {
maxZoom: 2,
scrollWheelZoom: false
});
d3.json("plates.geojson", function(er, result) {
svg.selectAll("lines")
.data(result.features)
.enter().append("path")
.attr("class", "plates")
.attr("d", path);
L.geoJson(result, {
style: {
"color": "#000",
"fillColor": "#FEFBFB",
"weight": 1,
"fillOpacity": 1
}
}).addTo(map);
map.fitWorld();
});
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment