2013-08-18 8 views
8

Gegeben ein GIS Raster mit Höhendaten, Wie man eine topographische Karte in D3js entwirft?D3js: Wie werden topografische Karten entworfen?

Gibt es ein Beispiel für Relief/topographische Karten von Cropped Lands, die mit D3js erstellt wurden?


Problem: ich die posibility von .tif > gdal_contour.py > .shp > topojson > d3js ohne Erfolg untersucht.

I use a makefile die alle meine Befehle enthalten. Da mein Interessengebiet (Frankreich) eine Landfläche ist, erzeugt der gdal_contour.py Ansatz gebrochene Isolinien, die keine geschlossenen Polygone erzeugen. Außerdem schlägt das SVG-Endergebnis fehl. Das einzige Beispiel einer topografischen D3-Karte, die ich kenne is about Iceland, die als eine Insel, dieses Problem vermeiden: das Land aus der Welt zu schneiden führt nicht zu gebrochenen Isolinien.

enter image description here

nb: Dieses Projekt ist Teil des #Wikipedia #wikimaps Projekts.

Antwort

20

Topografische Karte jetzt auf D3js, mit vollem Makefile-Workflow! Siehe http://bl.ocks.org/hugolpz/6279966 (< = älteren Code, zu vergleichen, um hier auf SO)

0. Voraussetzungen:

  • geografisches Gebiet: Sie können Ihre interessierendes geographisches Gebiet anpassen, indem Sie eine Zeile in jedem der 2 Dateien: makefile # boxing und html # Geo-frame_borders mit eigenen Dezimalkoordinaten für W, N, E, S Grenzen, etwa:

    var WNES = {"target": "France", "W ": -5,3," N ": 51,6," E ": 10,2," S ": 41,0};

  • Software:make, curl, unzip, gdal (umfassen ogr, gdal_calc.py, gdal_polygonize.py), nodejs, topojson. Hilfreich: touch. Das Makefile verwaltet dann die Quellen, verarbeitet sie und gibt eine einzige Topojson-Datei aus, die der bereitgestellte D3js-Code verwenden kann.

1. Speichern in Ordnername: /topo_map/topo.mk

# topojsoning: 
final.json: levels.json 
    topojson --id-property none --simplify=0.5 -p name=elev -o final.json -- levels.json 
    # simplification approach to explore further. Feedbacks welcome. 

# shp2jsoning: 
levels.json: levels.shp 
    ogr2ogr -f GeoJSON -where "elev < 10000" levels.json levels.shp 

# merge 
levels.shp: level0001.shp level0050.shp level0100.shp level0200.shp level0500.shp level1000.shp level2000.shp level3000.shp level4000.shp level5000.shp 
    ogr2ogr levels.shp level0001.shp 
    ogr2ogr -update -append levels.shp level0050.shp 
    ogr2ogr -update -append levels.shp level0100.shp 
    ogr2ogr -update -append levels.shp level0200.shp 
    ogr2ogr -update -append levels.shp level0500.shp 
    ogr2ogr -update -append levels.shp level1000.shp 
    ogr2ogr -update -append levels.shp level2000.shp 
    ogr2ogr -update -append levels.shp level3000.shp 
    ogr2ogr -update -append levels.shp level4000.shp 
    ogr2ogr -update -append levels.shp level5000.shp 

# Polygonize slices: 
level0001.shp: level0001.tif 
    gdal_polygonize.py level0001.tif -f "ESRI Shapefile" level0001.shp level_0001 elev 
level0050.shp: level0050.tif 
    gdal_polygonize.py level0050.tif -f "ESRI Shapefile" level0050.shp level_0050 elev 
level0100.shp: level0100.tif 
    gdal_polygonize.py level0100.tif -f "ESRI Shapefile" level0100.shp level_0100 elev 
level0200.shp: level0200.tif 
    gdal_polygonize.py level0200.tif -f "ESRI Shapefile" level0200.shp level_0200 elev 
level0500.shp: level0500.tif 
    gdal_polygonize.py level0500.tif -f "ESRI Shapefile" level0500.shp level_0500 elev 
level1000.shp: level1000.tif 
    gdal_polygonize.py level1000.tif -f "ESRI Shapefile" level1000.shp level_1000 elev 
level2000.shp: level2000.tif 
    gdal_polygonize.py level2000.tif -f "ESRI Shapefile" level2000.shp level_2000 elev 
level3000.shp: level3000.tif 
    gdal_polygonize.py level3000.tif -f "ESRI Shapefile" level3000.shp level_3000 elev 
level4000.shp: level4000.tif 
    gdal_polygonize.py level4000.tif -f "ESRI Shapefile" level4000.shp level_4000 elev 
level5000.shp: level5000.tif 
    gdal_polygonize.py level5000.tif -f "ESRI Shapefile" level5000.shp level_5000 elev 

# Raster slicing: 
level0001.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0001.tif --calc="1*(A>0)"  --NoDataValue=0 
level0050.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0050.tif --calc="50*(A>50)"  --NoDataValue=0 
level0100.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0100.tif --calc="100*(A>100)"  --NoDataValue=0 
level0200.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0200.tif --calc="200*(A>200)"  --NoDataValue=0 
level0500.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0500.tif --calc="500*(A>500)"  --NoDataValue=0 
level1000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level1000.tif --calc="1000*(A>1000)"  --NoDataValue=0 
level2000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level2000.tif --calc="2000*(A>2000)"  --NoDataValue=0 
level3000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level3000.tif --calc="3000*(A>3000)"  --NoDataValue=0 
level4000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level4000.tif --calc="4000*(A>4000)"  --NoDataValue=0 
level5000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level5000.tif --calc="5000*(A>5000)"  --NoDataValue=0 

# boxing: 
crop.tif: ETOPO1_Ice_g_geotiff.tif 
    gdal_translate -projwin -5.3 41.0 10.2 51.6 ETOPO1_Ice_g_geotiff.tif crop.tif 
    # ulx uly lrx lry // W S E N 

# unzip: 
ETOPO1_Ice_g_geotiff.tif: ETOPO1.zip 
    unzip ETOPO1.zip 
    touch ETOPO1_Ice_g_geotiff.tif 

# download: 
ETOPO1.zip: 
    curl -o ETOPO1.zip 'http://www.ngdc.noaa.gov/mgg/global/relief/ETOPO1/data/ice_surface/grid_registered/georeferenced_tiff/ETOPO1_Ice_g_geotiff.zip' 

clean: 
    rm `ls | grep -v 'zip' | grep -v 'Makefile'` 
# Makefile v4b (@Lopez_lz) 

2. Daten erstellen durch die makfile ausgeführt wird:

cd ./topo_map 
make -f ./topo.mk 

3. D3js & HTML-Code mit Autofokus:

<!-- language: html --> 
<style> 
svg { border: 5px solid #333; background-color: #C6ECFF;} 

/* TOPO */ 
path.Topo_1 { fill:#ACD0A5; stroke: #0978AB; stroke-width: 1px; } 
path.Topo_50 {fill: #94BF8B; } 
path.Topo_100 {fill: #BDCC96; } 
path.Topo_200 {fill: #E1E4B5; } 
path.Topo_500 {fill: #DED6A3; } 
path.Topo_1000 {fill:#CAB982 ; } 
path.Topo_2000 {fill: #AA8753; } 
path.Topo_3000 {fill: #BAAE9A; } 
path.Topo_4000 {fill: #E0DED8 ; } 
path.Topo_5000 {fill: #FFFFFF ; } 
.download { 
    background: #333; 
    color: #FFF; 
    font-weight: 900; 
    border: 2px solid #B10000; 
    padding: 4px; 
    margin:4px; 
} 
</style> 
<body> 
<script src="http://code.jquery.com/jquery-2.0.2.min.js"></script> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script src="http://d3js.org/topojson.v1.min.js"></script> 
<script> 
// 1. -------------- SETTINGS ------------- // 
// Geo-frame_borders in decimal ⁰: France 
var WNES = { "W": -5.3, "N":51.6, "E": 10.2, "S": 41.0 }; 

// Geo values of interest : 
var latCenter = (WNES.S + WNES.N)/2, 
    lonCenter = (WNES.W + WNES.E)/2, 
    geo_width = (WNES.E - WNES.W), 
    geo_height= (WNES.N - WNES.S); 
// HTML expected frame dimensions 
var width = 600, 
    height = width * (geo_height/geo_width); 

// Projection: projection, reset scale and translate 
var projection = d3.geo.equirectangular() 
     .scale(1) 
     .translate([0, 0]); 

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

// Path 
var path = d3.geo.path() 
    .projection(projection) 
    .pointRadius(4); 

// Data (getJSON: TopoJSON) 
d3.json("final.json", showData); 

// 2. ---------- FUNCTION ------------- // 
function showData(error, fra) { 
    var Levels = topojson.feature(fra, fra.objects.levels); 

// Focus area box compute for derive scale & translate. 
// [​[left, bottom], [right, top]​] // E W N S 
var b = path.bounds(Levels), 
    s = 1/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]; 

// Projection update 
projection 
    .scale(s) 
    .translate(t); 

//Append Topo polygons 
    svg.append("path") 
     .datum(Levels) 
     .attr("d", path) 
    svg.selectAll(".levels") 
     .data(topojson.feature(fra, fra.objects.levels).features) 
     .enter().append("path") 
     .attr("class", function(d) { return "Topo_" + d.properties.name; }) 
     .attr("data-elev", function(d) { return d.properties.name; }) 
     .attr("d", path) 

} 
</script> 
<br /> 
<div> 
    <a class="download ac-icon-download" href="javascript:javascript: (function() { var e = document.createElement('script'); if (window.location.protocol === 'https:') { e.setAttribute('src', 'https://raw.github.com/NYTimes/svg-crowbar/gh-pages/svg-crowbar.js'); } else { e.setAttribute('src', 'http://nytimes.github.com/svg-crowbar/svg-crowbar.js'); } e.setAttribute('class', 'svg-crowbar'); document.body.appendChild(e); })();"><!--⤋--><big>⇩</big> Download</a> -- Works on Chrome. Feedback me for others web browsers ? 
</div> 
<br /> 
</body> 
</html> 

4.Ergebnis wird sein, genau so: (bezogen auf Ihr Interessengebiet)

enter image description here

Wenn Sie Karte veröffentlichen (s) online bitte auf den Link teilen up :)

Hinweis: Förderung +1 willkommen.

+0

Anforderungen # Softwares: Ich installierte diese Software eine Weile her, zu unterschiedlichen Zeiten. Wenn jemand seine/ihre Hände auf Teile oder alle 'sudo apt-get install'-Befehle zur Ausführung bringt, dank hier oder online freigeben :) – Hugolpz

+0

Ich sehe den folgenden Fehler, wenn ich das obige Makefile versuche: ' Input Dateigröße ist 21601, 10801 Berechnet -srcwin 10482 2940 930 -635 vom projizierten Fenster. Fehler: Berechnet -srcwin 10482 2940 930 -635 hat negative Breite und/oder Höhe. *** [crop.tif] Fehlercode 1' –

+0

Die Aufgabe 'crop.tif:' ist fehlgeschlagen. Scheint deine Breite und/oder Höhe ist negativ. Überprüfen Sie auch Ihre '-projwin' Werte und ihre Plätze in der Zeile' gdal_translate -projwin -5.3 41.0 10.2 51.6 ETOPO1_Ice_g_geotiff.tif crop.tif'. Die Reihenfolge ist West, Nord, Ost, Südgrenzen, aber möglicherweise eine Änderung erforderlich, wenn Sie den Pazifik zuordnen und den [180. Meridian] kreuzen (https://en.wikipedia.org/wiki/180th_meridian). – Hugolpz

1

Wenn jemand nach einem Update sucht, hier ist der Build-Code, den ich ab heute ausgeführt habe. Erforderlich ich manuell die ZIP-Datei herunterladen und in das topo_map Verzeichnis verschieben, und dann ein paar Änderungen (bemerkt fett):

# topojsoning (USE GEO2TOPO not TOPOJSON): 
final.json: levels.json 
    geo2topo --id-property none --simplify=0.5 -p name=elev -o final.json -- levels.json 
    # simplification approach to explore further. Feedbacks welcome. 

# shp2jsoning: 
levels.json: levels.shp 
    ogr2ogr -f GeoJSON -where "elev < 10000" levels.json levels.shp 

# merge 
levels.shp: level0001.shp level0050.shp level0100.shp level0200.shp level0500.shp level1000.shp level2000.shp level3000.shp level4000.shp level5000.shp 
    ogr2ogr levels.shp level0001.shp 
    ogr2ogr -update -append levels.shp level0050.shp 
    ogr2ogr -update -append levels.shp level0100.shp 
    ogr2ogr -update -append levels.shp level0200.shp 
    ogr2ogr -update -append levels.shp level0500.shp 
    ogr2ogr -update -append levels.shp level1000.shp 
    ogr2ogr -update -append levels.shp level2000.shp 
    ogr2ogr -update -append levels.shp level3000.shp 
    ogr2ogr -update -append levels.shp level4000.shp 
    ogr2ogr -update -append levels.shp level5000.shp 

# Polygonize slices: 
level0001.shp: level0001.tif 
    gdal_polygonize.py level0001.tif -f "ESRI Shapefile" level0001.shp level_0001 elev 
level0050.shp: level0050.tif 
    gdal_polygonize.py level0050.tif -f "ESRI Shapefile" level0050.shp level_0050 elev 
level0100.shp: level0100.tif 
    gdal_polygonize.py level0100.tif -f "ESRI Shapefile" level0100.shp level_0100 elev 
level0200.shp: level0200.tif 
    gdal_polygonize.py level0200.tif -f "ESRI Shapefile" level0200.shp level_0200 elev 
level0500.shp: level0500.tif 
    gdal_polygonize.py level0500.tif -f "ESRI Shapefile" level0500.shp level_0500 elev 
level1000.shp: level1000.tif 
    gdal_polygonize.py level1000.tif -f "ESRI Shapefile" level1000.shp level_1000 elev 
level2000.shp: level2000.tif 
    gdal_polygonize.py level2000.tif -f "ESRI Shapefile" level2000.shp level_2000 elev 
level3000.shp: level3000.tif 
    gdal_polygonize.py level3000.tif -f "ESRI Shapefile" level3000.shp level_3000 elev 
level4000.shp: level4000.tif 
    gdal_polygonize.py level4000.tif -f "ESRI Shapefile" level4000.shp level_4000 elev 
level5000.shp: level5000.tif 
    gdal_polygonize.py level5000.tif -f "ESRI Shapefile" level5000.shp level_5000 elev 

# Raster slicing: 
level0001.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0001.tif --calc="1*(A>0)"  --NoDataValue=0 
level0050.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0050.tif --calc="50*(A>50)"  --NoDataValue=0 
level0100.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0100.tif --calc="100*(A>100)"  --NoDataValue=0 
level0200.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0200.tif --calc="200*(A>200)"  --NoDataValue=0 
level0500.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level0500.tif --calc="500*(A>500)"  --NoDataValue=0 
level1000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level1000.tif --calc="1000*(A>1000)"  --NoDataValue=0 
level2000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level2000.tif --calc="2000*(A>2000)"  --NoDataValue=0 
level3000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level3000.tif --calc="3000*(A>3000)"  --NoDataValue=0 
level4000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level4000.tif --calc="4000*(A>4000)"  --NoDataValue=0 
level5000.tif: crop.tif 
    gdal_calc.py -A crop.tif --outfile=level5000.tif --calc="5000*(A>5000)"  --NoDataValue=0 

# boxing: 
crop.tif: ETOPO1_Ice_g_geotiff.tif 
    gdal_translate -projwin -84.9 47.0 -69.9 33.7 ETOPO1_Ice_g_geotiff.tif crop.tif 
    # ulx uly lrx lry // W N E S <- Coordinate order 
# unzip: 
ETOPO1_Ice_g_geotiff.tif: ETOPO1.zip 
    unzip ETOPO1.zip 
    touch ETOPO1_Ice_g_geotiff.tif 

# download: 
#ETOPO1.zip: 
# curl -o ETOPO1.zip 'http://www.ngdc.noaa.gov/mgg/global/relief/ETOPO1/data/ice_surface/grid_registered/georeferenced_tiff/ETOPO1_Ice_g_geotiff.zip' 

clean: 
    rm `ls | grep -v 'zip' | grep -v 'Makefile'` 
# Makefile v4b (@Lopez_lz) 
+0

Danke Nick. Die Unterschiede sind dort sichtbar https://www.diffchecker.com/lFTXbr1A. Können Sie erklären, warum diese Änderungen in Ihrer Antwort enthalten sind? Wie für den ** CLI-Befehl ** '' 'topojson''' =>' '' geo2json''', gab es einen CLI-Wechsel? Für die ** Download-URL **, im Idealfall, immer wenn die URL zur Verfügung gestellt fehlschlägt müssen Sie nur die URL innerhalb der Makefile finden und zu aktualisieren. Für das '' 'WSEN''' =>' '' WNES''' scheint das [gdal_translate-Handbuch] (http://gdal.org/gdal_translate.html) meine anfängliche Konfiguration zu bestätigen. Mit freundlichen Grüßen funktioniert auch, da Gdal ist klug :) – Hugolpz

+0

Ja, ich werde meine Antwort bearbeiten, um die Änderungen zu reflektieren. Es gibt zwei Hauptänderungen: topojson => geo2json und die Koordinatenreihenfolge für das Zuschneiden. –

Verwandte Themen