Skip to content

Instantly share code, notes, and snippets.

@clhenrick

clhenrick/README.md

Last active Jul 29, 2020
Embed
What would you like to do?
Aligning GeoJSON data with us-atlas TopoJSON

This is a demonstartion of how to align arbitrary GeoJSON data to the us-atlas topojson data.

It's important to note that the TopoJSON from us-atlas has it's map projection, (d3.geoAlbersUsa), built into it. In other words, it is considered "projected" geographic data.

This is an important distinction from GeoJSON data which is most typically stored in the unprojected Coordinate Reference System WGS84, also commonly referred to as "lat, lon" (though coordinates are most often stored in the order longitude, latitude).

In order to properly align arbitrary GeoJSON data with us-atlas, we need to properly set the projection's scale and translate attributes to those used by us-atlas, which can be found in its prepublish script:

var projection = d3.geoAlbersUsa().scale(1280).translate([480, 300]);

This will give us correct SVG x, y coordinates from lon, lat coordinates. For instance:

projection([-122.41, 37.76]) 

// returns
Array [ 34.37093520874129, 257.47410484805755 ]

Otherwise, using d3.geoAlbersUsa alone will result in the GeoJSON data being mis-aligned with the map.

<!DOCTYPE html>
<style>
svg { border: 1px solid #333; }
</style>
<svg width="960" height="600" fill="none" stroke="#000" stroke-linejoin="round" stroke-linecap="round"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script>
var svg = d3.select("svg");
var path = d3.geoPath();
// define a projection function that matches the us-atlas projected topojson data
var projection = d3.geoAlbersUsa().scale(1280).translate([480, 300]);
d3.json("https://gist.githubusercontent.com/clhenrick/0323450eb5820ca49436adeb4428a239/raw/63ef6a2bc968779ff6a3e5f96583558196ac7fbb/ne_10m_populated_places_simple_filtered.json", function (error, places) {
if (error) throw error;
d3.json("https://unpkg.com/us-atlas@1/us/10m.json", function(error, us) {
if (error) throw error;
svg.append("path")
.attr("stroke-width", 0.5)
.attr("d", path(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; })));
svg.append("path")
.attr("d", path(topojson.feature(us, us.objects.nation)));
// add geojson data
svg.selectAll("circle")
.data(places.features)
.enter()
.append("circle")
.attr("cx", function(d) { return projection(d.geometry.coordinates)[0] })
.attr("cy", function(d) { return projection(d.geometry.coordinates)[1] })
.attr("r", 5)
.attr("fill", "red");
});
});
</script>
@Taulantvokshi

This comment has been minimized.

Copy link

@Taulantvokshi Taulantvokshi commented Jul 29, 2020

Good work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.