[GIS] Either GeoJson to TopoJson conversion problem, or projection-issue with D3.js

d3qgistopojson

My 'handcrafted' cartogram (How to create contiguous area cartograms in QGIS or R?) is ready to embed in code – I want to present it online with D3.js.

Therefore I produced a topoJSON file of it – but all I get are weird shapes all around the globe.

Here is the (simplified) cartogram in geoJSON (file:removed) – it works perfectly with QGis. Also I checked the geometry in QGis and it doesn't display an error [Vector > Geometry Tools > Check geometry validity].

I tried both: From QGis > geoJSON > topoJSON (with topojson), and QGis > ESRI shapefile > geoJSON (with ogr2ogr) > topoJSON (with topojson).

Also I tried reprojection with ogr2ogr:

ogr2ogr "ESRI Shapefile" -t_srs EPSG:4326 outfile.shp infile.shp

And I did the whole thing with UTF-8 flag:

topojson --shapefile-encoding utf8 -o outfile.json infile.shp

Here is the (simplified) cartogram in topoJSON (file:removed), and it looks ok to me – even the json-validators are happy with it.

But my D3.js code just results in weird shapes and lines.

<head>
    <meta charset="utf-8">
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="http://d3js.org/topojson.v0.min.js"></script>
    <title></title>
    <style>

    .unit {
        fill: none;
        stroke: #111;
        stroke-linejoin: round;
    }

    </style>
</head>
<body>
<script>

    var width = 600,
        height = 600;

    var projection = d3.geo.albers() // also: orthographic & mercator wont work
        .rotate([0, 0])
        .center([8.43, 46.8]) // Switzerland
        .scale(100);

    var path = d3.geo.path()
        .projection(projection);

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

    d3.json("hexmap.json", function(error, hexm) {
        var units = topojson.object(hexm, hexm.objects.hexmap).geometries[25];

        svg.append("path")
           .datum(units)
           .attr("class", "unit")
           .attr("d", path);
    });

</script>
</body>

I just don't know where I am going wrong… Is it the projection? The conversion? Are the files ok?

EDIT – SOLUTION

  1. use a transferable projection in the first place.
  2. the correct ogr2ogr command:

     ogr2ogr "GEOJSON" -s_srs infile.prj -t_srs EPSG:4326 outfile.geojson infile.shp
    

alternative:

     ogr2ogr "GEOJSON" -s_srs EPSG:21781 -t_srs EPSG:4326 outfile.geojson infile.shp

Best Answer

You can only use ogr2ogr to reproject your shapefile if ogr2ogr knows the source projection, which is typically defined in "infile.prj" (assuming your shapefile is "infile.shp"). Your GeoJSON file does not include any embedded projection information, so trying to reproject as follows has no effect:

ogr2ogr -f 'GeoJSON' -t_srs 'EPSG:4326' hexmap-still-broken.geojson hexmap.geojson

If you look at the hexmap.geojson (or the hexmap-still-broken.geojson, which has the same problem), you'll see that the coordinates are obviously not in longitude and latitude:

[ 624601.329864838044159, 267651.03375 ], [ 623590.96689375618007, 265901.03375 ],
[ 621570.240951592335477, 265901.03375 ], [ 620559.877980510587804, 267651.03375 ],
[ 621570.240951592335477, 269401.03375 ], [ 623590.96689375618007, 269401.03375 ],
…

To reproject, you'll either need your input .prj file, or you must use the -s_srs argument to tell ogr2ogr the projection of the input.

Related Question