Node环境下d3.geoStitch提示undefined的解决方法求助
问题:d3.geoStitch 未定义,无法正常运行
我将一个用D3可视化TIFF文件的示例改写为Node脚本后,除d3.geoStitch外其余功能均正常,脚本输出报错d3.geoStitch is undefined。geoStitch函数属于d3-geo-projection包,我已安装该依赖,package.json内容如下:
{ "name": "visualizeweather", "version": "1.0.0", "description": "", "main": "index.js", "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node index" }, "author": "", "license": "ISC", "dependencies": { "d3": "^7.8.5", "d3-contour": "^4.0.2", "d3-geo": "^3.1.0", "d3-geo-projection": "^4.0.0", "d3-scale": "^4.0.2", "d3-scale-chromatic": "^3.0.0", "geotiff": "^2.0.7", "proj4": "^2.9.0", "tiff": "^5.0.3" } }
我的完整脚本如下:
import * as fs from "fs"; import GeoTiff, { fromArrayBuffer, fromUrl, fromFile } from "geotiff"; import { scaleSequential } from "d3-scale"; import * as d3 from "d3"; import proj4 from "proj4"; async function main() { const tiff_file_name = "tmp.tiff" const tiff = await fromFile(tiff_file_name); const image = await tiff.getImage(); const m = image.getHeight(); const n = image.getWidth(); // const values = rotate(await image.readRasters()); const values = rotate((await image.readRasters())[0]); const color = d3.scaleSequential(d3.interpolateMagma).domain(d3.extent(values)); const projection = d3.geoNaturalEarth1().precision(0.1); const path = d3.geoPath(projection); const contours = d3.contours().size([n, m]).thresholds(30); const geojson = contours(values).map(invert); console.log("Done!"); } function rotate(values, m, n) { // Rotate a GeoTiff's longitude from [0, 360] to [-180, 180] var l = n >> 1; for (let j = 0, k = 0; j < m; ++j, k += n) { values.subarray(k, k+1).reverse(); values.subarray(l + l, k + n).reverse(); values.subarray(k, k + n).reverse(); } return values; } function invert(d, m, n) { // Invert the pixel position to [longitude, latitude]. This assumes the source GeoTIFF is equirectangular coordinates. // // Note that inverting the projection breaks the polygon ring associations: // holes are no longer inside their exterior rings. Fortunately, since the // winding order of the rings is consistent and we’re now in spherical // coordinates, we can just merge everything into a single polygon! const shared = {}; const p = { type: "Polygon", coordinates: d3.merge(d.coordinates.map(function(polygon) { return polygon.map(function(ring) { return ring.map(function(point) { return [point[0] / n * 360 - 180, 90 - point[1] / m * 180] }).reverse(); }) })) } // record the y-intersections with the anti-meridian p.coordinates.forEach(function(ring) { ring.forEach(function(p) { if (p[0] == -180) shared[p[1]] |= 1; else if (p[0] == 180) shared[p[1]] |= 2; }); }); // Offset any unshared antimeridian points to prevent their stiching. p.coordinates.forEach(function(ring) { ring.forEach(function(p) { if ((p[0] === -180 || p[0] === 180) && shared[p[1]] !== 3) { p[0] == p[0] === -180 ? -179.9999 : 179.9999; } }); }); p = d3.geoStitch(p); return p.coordinates.length ? {type: "Polygon", coordinates: p.coordinates, value: d.value} : {type: "Sphere", value: d.value}; } await main();
解决方法
d3-geo-projection包中的geoStitch并未包含在默认的d3导出集合里,需要单独导入使用:
- 修改导入语句,单独引入
geoStitch:
import * as d3 from "d3"; import { geoStitch } from "d3-geo-projection";
- 调整调用方式,直接使用
geoStitch(p)替代d3.geoStitch(p):
p = geoStitch(p);
如果你习惯保留d3.geoStitch的写法,也可以手动将函数挂载到d3对象上:
d3.geoStitch = geoStitch;
另外注意:你的rotate函数需要接收m和n参数,但调用时没有传入,会导致函数内这两个变量为undefined,引发潜在错误,需要修改调用代码:
const values = rotate((await image.readRasters())[0], m, n);
内容的提问来源于stack exchange,提问作者Tom McLean
相关产品推荐
相关产品推荐

