geoPHP点在多边形内的问题

5

我需要帮助,谷歌让我感到沮丧。

我有一个多边形http://geojson.io/#id=gist:anonymous/069b8a955897723ca256&map=4/58.75/48.03 它覆盖了很大的面积。 我有一个叫做geoPHP的库https://github.com/phayes/geoPHP 其中包含contains、covers、coveredBy等方法...

一切都正常,除了像74.224074, 96.428248这样的点总是对于这个多边形的 contains、coveredBy、covers等方法为false。但它必须是true。

请告诉我为什么。我头痛得要命。

或者

请告诉我,如何检查纬度和经度是否在多边形内。我尝试过3个Perl和PHP库,编写自己的代码等...但我只从Google的JavaScript containsLocation中得到正确的结果。但我必须在服务器端使用它,而不是在浏览器中。如果有任何机会在nodejs中使用containsLocation,那就太好了。

谢谢

A little code for geoPHP:
$a='JSON FROM LINK';
$b=geoPHP::load("POINT(74.224074 96.428248)","wkt");
$a=geoPHP::load($a, 'json');
$result=$a->contains($b);

var_dump($result);

而它将是错误的

编辑: 我想我明白了。 GeoJson以错误的方式制作坐标,即经度、纬度。但必须是纬度、经度。 会尝试并在此处编写是否有效

答案:

使用www.birdtheme.org/useful/v3tool.html在地图上绘制多边形。 它以正确的方式制作(纬度,经度)

geoPHP的工作代码:

    include_once('geoPHP.inc');
$addr=file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?address='.urlencode($_GET['address']).'&sensor=false');
foreach($addr->{results} as $addr1)
{
if(array_key_exists("geometry",$addr1)){
$lat=$addr1->{geometry}->{location}->{lat};
$lng=$addr1->{geometry}->{location}->{lng};



break;
}
}
$point1 = geoPHP::load("POINT($lat $lng)","wkt");

$ya200=geoPHP::load("POLYGON((41.51 12.3, 38.27 28.83, 32.55 41.84, 27.6 55.55, 29.54 71.37, 33.43 83.32, 36.6 94.92, 36.6 99.49, 35.17 111.45, 32.55 124.8, 35.17 130.78, 39.64 142.73, 43.58 152.58, 45.83 166.29, 56.17 163.83, 63.07 159.26, 68.66 154.69, 72.18 148.71, 75.93 140.63, 78.49 129.02, 80.3 114.26, 80.98 100.2, 81.2 87.54, 80.87 73.83, 79.62 59.41, 76.27 40.43, 71.07 28.13, 67.2 23.2, 63.55 20.04, 59.01 17.23, 54.16 15.12, 48.46 13.36,41.51 12.3))","wkt");


var_dump($ya200->contains($point1));
5个回答

11

我是geoPHP库(https://geophp.net)的维护者。你的纬度和经度混淆了。WKT规定先使用x,然后是y,最后(可选)是z。这是有道理的,因为我们通常按照XYZ顺序进行操作。

在数学中,水平轴通常被定义为X轴,垂直轴则被定义为Y轴。如果我们将地球仪覆盖在一个具有X和Y轴指定的图纸上,就可以看到经度是横轴,对应X轴,而纬度是竖轴,对应Y轴。因此,“经度,纬度”这样的阅读方式是非常合理的。

遗憾的是,这种合理的方法与历史上航海家和其他制图师描述地球仪坐标的方式相反。历史上它经常被描述为“纬度,经度”。

这种历史与数学惯例的冲突是不同系统使用不同约定的原因。在Google Maps API中,它是“纬度,经度”,而在OpenLayers中则是“经度,纬度”。

在这种特殊情况下,你正在使用WKT,它规定了“经度,纬度”的顺序。


我创建了另一个问题http://stackoverflow.com/questions/41459331/point-in-polygon-using-geophp。我尝试了这里的解决方案,但它不起作用。 - San

2

WKT格式需要 POINT(lon, lat),其中 lon 应该在前面。你把顺序搞错了。已经更正为:

geoPHP::load("POINT($lon $lat)","wkt");

2

我已经回答过几乎相同的问题,但不知道如何重新发布它,所以我在这里重复一遍(抱歉)

如果您使用这个 PHP 库(https://github.com/xopbatgh/sb-polygon-pointer),它可能会满足您的所有需求。

(但首先您需要将 GEOjson 坐标转换为纬度/经度)

计划执行以下操作:

  1. 将多边形的坐标插入数组中

  2. 询问库是否有任何纬度/经度在此多边形内的点

$polygonBox = [
    [55.761515, 37.600375],
    [55.759428, 37.651156],
    [55.737112, 37.649566],
    [55.737649, 37.597301],
];

$sbPolygonEngine = new sbPolygonEngine($polygonBox);

$isCrosses = $sbPolygonEngine->isCrossesWith(55.746768, 37.625605);

// $isCrosses is boolean


2
经过数小时的尝试,我无法让geoPHP的contains方法正常工作。正如这个SO响应所指出的那样,需要手动安装geos库(没有composer),但在阅读archive.org上的文档后,我无法使其正常工作。
作为替代方案,我发现mjaschen/phpgeo很容易使用来进行多边形包含点的计算。只需将您的纬度和经度加载到对象中,并按照文档中的说明调用包含方法即可。
$polygon = new Polygon();
$polygon->addPoint(new Coordinate(12.3, 41.51));
$polygon->addPoint(new Coordinate(28.83, 38.27));
$polygon->addPoint(new Coordinate(41.84, 32.55));

$point = new Coordinate(74.224074, 96.428248)

var_dump($polygon->contains($point))

1
所有geoPHP中的高级方法都需要安装GEOS。如果您无法安装它,但仍想使用点和多边形的相交测试,则我已经分叉了geoPHP并添加了Polygon->pointInPolygon和MultiPolygon->pointInPolygon方法以实现此目的。请查看: https://github.com/sookoll/geoPHP
$point = \geoPHP::load('POINT (x y)','wkt');
$polygon = \geoPHP::load('POLYGON ((x y...))','wkt');
$point_is_in_polygon = $polygon->pointInPolygon($point);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接