d3.geoContains始终返回true:GeoJSON坐标包含判断异常排查
问题描述
我定义了一个GeoJSON文件,使用d3.geoContains()函数判断某坐标是否属于文件中的指定Feature,但无论传入什么坐标,返回值始终为true,明显不在多边形范围内的坐标也没有返回预期的false。
相关代码文件
geo.geojson
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "name": "test_region_name" }, "geometry": { "coordinates": [ [ [ -73.96200080026726, 40.82690844987039 ], [ -74.02402960789588, 40.823413089420626 ], [ -74.07813984433737, 40.760465102484545 ], [ -74.08143924899831, 40.6679333560935 ], [ -73.95606187187775, 40.66843387335888 ], [ -73.87357675535053, 40.70896329528995 ], [ -73.89733246891002, 40.79394487450159 ], [ -73.96200080026726, 40.82690844987039 ] ] ], "type": "Polygon" } } ] }
app.js
const d3 = require('d3-geo'); // version 2.0.2 const fs = require('fs'); async function test() { const coordinate = [40.73496919065889,-73.97519841891166] // 无论传入什么坐标,d3.geoContains()始终返回true fs.readFile("./geo.geojson", function(err, data) { if (err) throw err; const geojson = JSON.parse(data); for (const feature of geojson.features) { const inRegion = d3.geoContains(feature, coordinate) console.log(`coordinate is in region ${feature.properties.name}? ${inRegion}`) } }); } test()
问题原因与解决办法
核心原因
d3.geoContains()要求传入的坐标必须遵循**[经度, 纬度]的顺序,但代码中的coordinate是[纬度, 经度]**,顺序完全颠倒。这种情况下,d3会把错误的坐标解析到不符合预期的区域,甚至因为坐标顺序错误导致多边形判断逻辑反转,出现所有坐标都返回true的情况。
解决步骤
修正坐标顺序
将coordinate改为[-73.97519841891166, 40.73496919065889],即把经度放在前面,纬度放在后面。(可选)检查多边形顶点环绕方向
如果修正坐标顺序后仍有问题,需检查GeoJSON中多边形的顶点顺序:GeoJSON规定,多边形外部环顶点必须是逆时针方向,内部洞为顺时针方向。如果顺序反了,d3会把多边形的“外部”当成“内部”,导致不在多边形内的坐标被误判为在范围内。可使用d3.geoArea()辅助判断:若返回面积远大于预期(接近地球表面积),说明顶点顺序反了,需反转顶点数组。
修正后的app.js代码
const d3 = require('d3-geo'); // version 2.0.2 const fs = require('fs'); async function test() { // 修正为 [经度, 纬度] 的顺序 const coordinate = [-73.97519841891166, 40.73496919065889] fs.readFile("./geo.geojson", function(err, data) { if (err) throw err; const geojson = JSON.parse(data); for (const feature of geojson.features) { const inRegion = d3.geoContains(feature, coordinate) console.log(`coordinate is in region ${feature.properties.name}? ${inRegion}`) } }); } test()
内容的提问来源于stack exchange,提问作者nickcoding2
相关产品推荐
相关产品推荐

