11

给定具有高程数据的 GIS 栅格,如何在 D3js 中设计地形图?

有没有使用 D3js 制作的耕地地形图的例子?


不工作:我探索了.tif > gdal_contour.py > .shp > topojson > d3js没有成功的可能性。

使用包含我所有命令的生成文件。由于我感兴趣的区域(法国)是一片土地,因此该gdal_contour.py方法会生成不会创建封闭多边形的断开等值线。此外,SVG 最终结果失败。我所知道的 D3 地形图的唯一示例是关于冰岛的,作为一个岛屿,冰岛避免了这个问题:将这个国家从世界中剔除不会导致等值线断裂。

在此处输入图像描述

注意:这个项目是#Wikipedia #wikimaps 项目的一部分。

4

2 回答 2

27

地形图现在在 D3js 上,具有完整的 makefile 工作流程!请参阅http://bl.ocks.org/hugolpz/6279966(<=旧代码,与此处比较)

0.要求:

  • 地理区域:您可以通过在 2 个文件中的每一个中编辑一行来自定义您感兴趣的地理区域:makefile#boxing 和 html#Geo-frame_borders 使用您自己的 W、N、E、S 边界的十进制坐标,例如:

    var WNES = {“目标”:“法国”,“W”:-5.3,“N”:51.6,“E”:10.2,“S”:41.0 };

  • 软件: make , curl, unzip, gdal(包括ogr, gdal_calc.py, gdal_polygonize.py), nodejs, topojson. 有帮助:touch。然后,makefile 设法下载源代码,处理它们,并输出提供的 D3js 代码可以使用的单个 topojson 文件。

1. 保存到文件夹名称:/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 (@hugo_lz) 

2.通过运行 makfile 创建数据:

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

3. 自动对焦的 D3js & HTML 代码:

<!-- 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>⇩&lt;/big> Download</a> -- Works on Chrome. Feedback me for others web browsers ?
</div>
<br />
</body>
</html>

4. 结果将是这样的:(适用于您感兴趣的领域)

在此处输入图像描述

如果您在线发布地图,请分享链接:)

注意:鼓励 +1 欢迎。

于 2013-08-20T11:38:08.683 回答
1

如果有人正在寻找更新,这是我今天运行的构建代码。要求我手动下载 .zip 文件并将其移动到 topo_map 目录,然后进行一些更改(以粗体表示):

# 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) 
于 2016-12-20T19:23:04.353 回答