18

I'm simply trying to convert a .shp file to a geoJSON format using:

ogr2ogr -f geoJSON output.json input.shp

After executing the command nothing seems to be wrong. Here's an excerpt from the output.json

    {
    "type": "FeatureCollection",
"features": [
{ "type": "Feature", 
"properties": { "ID_0": 86, "ISO": "DEU", "NAME_0": "Germany", "ID_1": 1, "NAME_1": "Baden-Württemberg", "NL_NAME_1": null, "VARNAME_1": null, "TYPE_1": "Land", "ENGTYPE_1": "State" }, 
"geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 8.708400940398242, 47.715581894910606 ], [ 8.713716147005524, 47.701734382960055 ], 

...

But when i try to use de JSON file in d3 (http://d3js.org/) to draw SVG polygons the output is just wrong. Since the shp files are displayed correctly in QGIS I think there has to be something wrong with the way i use ogr2ogr. The SVG I get is not completely wrong but there seems to be a detail I can't find. It seems like it has been turned upside down and somehow distorted into two separated parts.

Here's the JavaScript i used to generate the svg:

//dimensions
var w = 2000;
var h = 2000;

var svg = d3.select("#chart").append("svg") .attr("width", w) .attr("height", h);

d3.json(
"http://localhost:8888/data/data.json",
function (json) {

var path = d3.geo.path();

svg.append("g")
    .attr("class", "black")
    .selectAll("path")
    .data(json.features)
    .enter()
    .append("path")
    .attr("d", path);

Does anyone have an idea what went wrong here?

I also tried to convert the shp-file using QGIS and myGeodata (http://converter.mygeodata.eu/vector)but neither of them work the way they should.

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Flavio
  • 541
  • 1
  • 3
  • 10
  • have you tried specifying the correct EPSG code for your shapefile and GeoJSON output ? E.g.: ogr2ogr -f GeoJSON -s_srs EPSG:.... -t_srs EPSG:.... output.json input.shp – dmci Nov 05 '12 at 13:53
  • Probably there's the problem. I didn't specify anything Mostly because of lack of knowledge. But I found a workaround to my problem. I'll post it in a minute. – Flavio Nov 05 '12 at 15:18

2 Answers2

7

Playing around with different projections, scales and translations in d3 solved my problem. Since the default projection when using d3.geo.path() is albersUsa there was good reason to try some other projections. I suppose the problem could have been solved easier using the right EPSG specification when converting the shape file but these obscure numbers exceeded my knowledge.

So what I did in the end is simply using a mercator projection and bringing it into the svg-viewport with translate().

   d3.json(
    "http://localhost:8888/data/data.json",
    function (json) {
//dimensions
var w = 2000;
var h = 2000;

var svg = d3.select("#chart").append("svg")
.attr("width", w)
.attr("height", h);

//create geo.path object, set the projection to merator bring it to the svg-viewport
var path = d3.geo.path()
    .projection(d3.geo.mercator()
    .scale(20000)
    .translate([0, 3800]));

//draw svg lines of the boundries
svg.append("g")
    .attr("class", "black")
    .selectAll("path")
    .data(json.features)
    .enter()
    .append("path")
    .attr("d", path);
});

Here's a link to the shape files i used and the resulting geoJSON. To simplify the shapefiles, which I got from GADM, I used mapshaper.

I would still be interested in a less laborious and more flexible solution but for the moment I'm happy I can recognize the 16 Bundesländer of Germany!

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Flavio
  • 541
  • 1
  • 3
  • 10
3

You are right, for a map of germany you need to change the default projection as it fits for USA data. It is centered somewhere in Kansas and for a map of size 960xsomething.

The correct parameters of course also depend on your map dimensions.

If you want to use the d3.geo.albers projection (best for coropleth maps) here are my parameters:

var w = 415;
var h = 555;

var albers = d3.geo.albers()
    .origin([11, 51])
    .parallels([49, 53])
    .translate([230, 290])
    .scale(4000);

var path = d3.geo.path().projection(albers);
ahinrichs
  • 31
  • 2