【问题标题】:Find in which polygon a GeoJSON point lies in, in NodeJS在 NodeJS 中查找 GeoJSON 点所在的多边形
【发布时间】:2021-04-23 22:56:54
【问题描述】:

给定一个已定义的(lat, lon) 地理点,我试图找出该点位于哪个多边形中。我认为迭代所有多边形效率不高。是否有任何适用于 NodeJS 的函数或库来执行此操作?

const polygon = getPolygonFromPoint(FeatureCollection, x, y);

没有重叠的多边形,实际上我是用它来检测定义的 GPS 坐标点位于某个国家的哪个地区。

【问题讨论】:

  • 缺少一些细节...例如,如果您有重叠的多边形,则一个点可能属于多个多边形
  • @MichaelRovinsky 感谢您的注意,我相应地更新了我的答案。没有重叠的多边形。
  • 你是否需要做不止一个点,例如很多积分?
  • @RobinMackenzie 不,只有一点

标签: node.js d3.js polygon r-tree point-in-polygon


【解决方案1】:

对于多边形测试中的一个简单点,您可以检查turf,它有一个booleanPointInPolygon。 Turf 在节点中工作,但您应该检查 v5 和 v6+ 之间关于如何相应地使用 npm 的差异。点应该是long/ lat(不是纬度/经度),而多边形可以是easily pulled,不在您的要素集合的要素几何中。

对于一个更复杂的用例,您有很多点和很多多边形可以在其中定位它们,您应该考虑使用rbush

请注意,rbush 库是根据多边形的边界框而不是多边形本身构建 r-tree,因此使用 r-tree 只是一种大大减少需要测试的多边形数量的方法booleanPointInPolygon.

rbush 的示例代码:

const RBush = require("rbush");
const turfBbox = require("@turf/bbox").default;

const geo = {} // your feature collection...
const maxEntriesPerNode = 50; // check the doco
const tree = new RBush(maxEntriesPerNode);
const bbox2Object = (keys, bbox) => ["minX", "minY", "maxX", "maxY"].reduce((o, k, i) => ({...o, [k]: bbox[i]}), {})

// create rtree from feature collection
geo.features.forEach(feature => {
  const leaf = bbox2Object(bboxKeys, turfBbox(feature)); // use bbox of feature
  leaf["id"] = feature.properties.SOME_ID; // add some custom properties
  tree.insert(leaf);
});

// test a random point from your data
const [x, y] = [123, 456]; // should be long, lat
const test = tree.search({minX: x, minY: y, maxX: x, maxY: y});
// test should have an array of leaves per the tree.insert above

然后您可以对这组缩减的多边形执行booleanPointInPolygon 测试。

【讨论】:

  • 请注意:这些方法考虑笛卡尔空间中的坐标,而 D3 将经纬度对视为球体上的 3 维点 - 因此 D3 使用大圆来连接多边形的顶点,这表示地理上位于多边形内的点可能会被上述方法遗漏,但由 D3 绘制在多边形内。 D3 确实包含 d3.geoContains 方法,该方法避免了这种情况以及任何反子午线问题,但在大多数情况下,将坐标视为笛卡尔坐标会产生准确的结果。
  • 感谢@AndrewReid,同意这一点很重要,假设您的意思是草皮功能?或者这也是指 rbush 吗?
  • turf 和 rbush 都在笛卡尔坐标空间而不是地理坐标空间中工作,两者都应该返回相同的结果,这可能在地理上不正确。错误结果的可能性取决于多边形段的长度、经度的跨度以及与两极的距离。 D3 的地理函数在使用球面数学(包括路径渲染)方面相对独特。
【解决方案2】:

我使用库 polygon-lookup 实现了这一点

const PolygonLookup = require('polygon-lookup')
const featureCollection = {
    type: 'FeatureCollection',
    features: [{
        type: 'Feature',
        properties: { id: 'bar' },
        geometry: {
            type: 'Polygon',
            coordinates: [ [ [ 0, 1 ], [ 2, 1 ], [ 3, 4 ], [ 1, 5 ] ] ]
        }
    }]
}
var lookup = new PolygonLookup(featureCollection)
var poly = lookup.search(1, 2)
console.log(poly.properties.id) // bar

【讨论】:

  • 我认为这是实用的解决方案。从理论上讲,该问题以“点位置”的名义处理。 en.wikipedia.org/wiki/Point_locationslab 分解方法是持久数据结构的起源(tarjan 等人)。平板分解是 log(n) - 包括完整的多边形测试,而 rtree 方法是 log(n) 用于边界框 + k * 多边形测试中的点。它假定不重叠。有趣的话题;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-22
  • 2015-08-22
  • 2011-07-01
  • 1970-01-01
  • 2011-11-06
  • 2012-02-18
相关资源
最近更新 更多