[GIS] D3 adding topojson – no data visible

d3jsonogr2ogropenlayers-2topojson

Yesterday I asked what would be the best method of creating an overlay in a web map that would allow for some interactivity.

Create interactive map with no server

Thanks to a variety of people who recommended I go down the D3 and Topojson route.

The example that looks like the perfect solution is http://bl.ocks.org/mbertrand/5218300

So I created a topojson from an ESRI Shapefile using the following command

topojson --id-property full_name -o southeast.json southeast.shp

I have since tried every possible permutation and example to try and get the topojson loaded and I have hit a brick wall. I just do not understand what I am doing wrong.

I have used the following examples

http://www.schneidy.com/Tutorials/MapsTutorial.html
https://stackoverflow.com/questions/14492284/center-a-map-in-d3-given-a-geojson-object
Conversion from Shapefile to TopoJSON format results in incorrect map when rendered using d3js
http://milkator.wordpress.com/2013/02/25/making-a-map-of-germany-with-topojson/

and Mike's original example

http://bost.ocks.org/mike/map/

Maybe it is because i am not using EPSG:4326, but this example says that you do not have to use a projection

http://bl.ocks.org/mbostock/5557726

The data can be found here – https://www.dropbox.com/s/dfxxi4xwrsdfa8t/southeast.json

And this is my code

<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>

var width = 500,
    height = 500;

//null projection as my ESPG is not supported
var path = d3.geo.path()
    .projection(null);

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

svg.append("rect").attr('width', width).attr('height', height)
    .style('stroke', 'black').style('fill', 'none');

//d3.json("southeast.json", function(error, south) {
  //console.log(south);
//});

d3.json("southeast.json", function(error, uk) {
  svg.append("path")
      .datum(topojson.feature(uk, uk.objects.southeast))
      .attr("d", d3.geo.path().projection(null));
});

I first tested with sending the data to the console and that worked fine and told me that the object is "southeast".

If I try this I get an n is not defined error in Firebug.

I then tried

// d3.json("southeast.json", function(error, south) {
//   svg.append("path")
//       .datum(topojson.feature(south, south.objects.southeast))
//       .attr("d", d3.geo.path().projection(null))
//       .style("fill", "red")
//       .style("stroke-width", "1")
//       .style("stroke", "black");
// });

Which seems to work as there are no Firebug errors, but no data is visible

Then I tried

// d3.json("southeast.json", function(error, uk) {
//   svg.selectAll(".southeast")
//       .data(topojson.feature(uk, uk.objects.southeast).features)
//     .enter().append("path")
//       .attr("d", path)
// });

And the same thing happens

With no errors I am struggling to understand what I have done wrong

If I could just make this example work in EPSG:27700 with my topojson it would be amazing
http://bl.ocks.org/mbertrand/5218300

Thanks

EDIT

One of the other answers was to use a simply getJSON function and add the data as geojson in OpenLayers. I have just tested it using the same topojson:

$.getJSON('southeast.json', function (data) {
            fusiegem = topojson.feature(data, data.objects.southeast);
            var geojson_format = new OpenLayers.Format.GeoJSON();
            var vector_layer = new OpenLayers.Layer.Vector();
            osMap.addLayer(vector_layer);
            vector_layer.addFeatures(geojson_format.read(fusiegem));
        });

And that successfully loaded, so it seems there is nothing wrong with my topojson file, it is the D3 bit that does not seem to work correctly

Best Answer

If I understand correctly (the file is not available anymore so I could not check), the problem is related to the projection.

In the http://bl.ocks.org/mbostock/5557726 example, a null projection can be used because the topojson file is already in screen coordinates thanks to the options: --width 960 --height 800 during the topjson file generation. In your case, since you didn't specify those options, you will likely need to define a projection (d3.geo.albers for example).