d3.geoStitch 未定义

问题描述 投票:0回答:1

我正在尝试编写这个示例,使用 d3 作为节点脚本来可视化 TIFF 文件。

一切正常,直到

d3.geoStitch
,我的脚本输出
d3.geoStitch is undefined
geoStitch
功能是
d3-geo-projection
的一部分,我已经安装了:

{
  "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();

我怎样才能让

geoStitch
去工作?

javascript npm d3.js
1个回答
1
投票

问题出在导入 d3 上。

请使用下面更新的代码:

import * as fs from "fs";
import GeoTiff, { fromArrayBuffer, fromUrl, fromFile } from "geotiff";
import { scaleSequential } from "d3-scale";
const d3 = await Promise.all([
    import("d3-format"),
    import("d3-geo"),
    import("d3-geo-projection"),
    import("d3"),
  ]).then(d3 => Object.assign({}, ...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 = {};

    let 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();
© www.soinside.com 2019 - 2024. All rights reserved.