Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
278 views
in Technique[技术] by (71.8m points)

geojson - Shapefile to Topojson conversion

I am trying to convert the Ghana admin1 shapefile that can be found here. My end goal is to obtain a TopoJSON as described in this question. I have used this command on a Linux machine:

ogr2ogr -f GeoJSON GHA_adm1.json GHA_adm1.shp

And it returns this:

Unable to open datasource `GHA_adm1.shp' with the following drivers.
... here goes a long list of drivers...

I am I doing something wrong? Should I install other "drivers"? But how? Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Download the GIS source

GADM is the perfect source for administrative GIS files.

GADM.org > Download page : select your country and format "shapefile" > ok.

Or via terminal (replace New Ghana code GHA by your target country's iso code):

# prepare folder
mkdir -p ./map; cd ./map
curl http://d3js.org/d3.v3.min.js -O -J
curl http://d3js.org/topojson.v1.min.js -O -J
# download data
curl 
    -L -C - 'http://biogeo.ucdavis.edu/data/gadm2/shp/GHA_adm.zip' 
    -o ./GHA_adm.zip
unzip -n ./GHA_adm.zip -d ./

shp to topojson

Use topojson command line, it's more direct. If you want to keep all properties :

 topojson -q 1e4 
          -o out.json 
          -- in1.shp in2.shp

You can also select attributes from the shapfiles, and rename them on the go :

 topojson 
    --bbox 
    --id-property none 
    -p name=NAME_1 
    -p code=ID_1 
    -p L0=NAME_0 
    -q 1e4 
    --filter=small 
    -o GHA_adm_w.topo.json 
    -- admin_1=GHA_adm1.shp admin_2=GHA_adm2.shp

For GHA, there is no attribute in the .shp suitable for a good ID. NAME_1 have spaces which will give invalid id within your HTML.

enter image description here

Inspect json

Use http://jsoneditoronline.org . Inspecting your json will give you clues of what data is available, and where (dot notation path). The topojson distillery help to preview any topojson and if the code is correct.

D3js call

<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style>
.L1 {
    fill: #E0E0E0;
    stroke: #FFF;
    stroke-width:1px;
}
</style>
<body>
<script src="./d3.v3.min.js"></script>
<script src="./topojson.v1.min.js"></script>
<script>
var mapIt = function(width, url){
    console.log("mapIt(): start");
    var height = width/960*500;
    var svg = d3.select('body').append('svg')
        .attr('width', width)
        .attr('height', height);
    var projection = d3.geo.mercator()
          .scale(1)
          .translate([0, 0]);

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

    d3.json(url, function (error, json) {
        var admin_1 = topojson.feature(json, json.objects.admin_1);

        /* Autofocus code comes here ! */

        svg.selectAll("path")
            .data(admin_1.features)
          .enter().append("path")
            .attr('d', path)
            .attr('class', 'L1');
    });    
};
mapIt(960,"http://somesite.org/data/NZL_adm.topo.json");
</script>
</body>
</html>

Focus

A correct autofocus will need a small bit of code from Mike Bostocks, example here:

// Compute the bounds of a feature of interest, then derive scale & translate.
var b = path.bounds(admin_1),
    s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
    t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

// Update the projection to use computed scale & translate.
projection
    .scale(s)
    .translate(t);

EDIT: Should work now. Live demo: bl.ocks.org


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...