匀称和matplotlib点在多边形与地理位置不准确

Chu*_*ung 8 python matplotlib point-in-polygon google-maps-api-3 shapely

我正在使用matplotlib和shapely测试多边形点函数.

这是一张包含百慕大三角形多边形的地图.

Google地图的多边形点函数清楚地表明,testsPointtestingPoint2位于多边形内部,这是正确的结果.

如果我在matplotlib中测试两个点并且形状合理,则只有point2通过测试.

In [1]: from matplotlib.path import Path

In [2]: p = Path([[25.774252, -80.190262], [18.466465, -66.118292], [32.321384, -64.75737]]) 

In [3]: p1=[27.254629577800088, -76.728515625]

In [4]: p2=[27.254629577800088, -74.928515625]

In [5]: p.contains_point(p1)
Out[5]: 0

In [6]: p.contains_point(p2)
Out[6]: 1
Run Code Online (Sandbox Code Playgroud)

形状上显示与matplotlib相同的结果.

In [1]: from shapely.geometry import Polygon, Point

In [2]: poly = Polygon(([25.774252, -80.190262], [18.466465, -66.118292], [32.321384, -64.75737]))

In [3]: p1=Point(27.254629577800088, -76.728515625)

In [4]: p2=Point(27.254629577800088, -74.928515625)

In [5]: poly.contains(p1)
Out[5]: False

In [6]: poly.contains(p2)
Out[6]: True
Run Code Online (Sandbox Code Playgroud)

这里到底发生了什么?谷歌的算法比那两个好吗?

谢谢

Mik*_*e T 10

记住:世界并不平坦!如果Google Maps的投影是您想要的答案,则需要将地理坐标投影到球形墨卡托以获得不同的X和Y坐标集.Pyproj可以帮助解决这个问题,只需确保在之前反转坐标轴(即:X,Y或经度,纬度).

import pyproj
from shapely.geometry import Polygon, Point
from shapely.ops import transform
from functools import partial

project = partial(
    pyproj.transform,
    pyproj.Proj(init='epsg:4326'),
    pyproj.Proj('+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs'))

poly = Polygon(([-80.190262, 25.774252], [-66.118292, 18.466465], [-64.75737, 32.321384]))
p1 = Point(-76.728515625, 27.254629577800088)

# Old answer, using long/lat coordinates
poly.contains(p1)  # False
poly.distance(p1)  # 0.01085626429747994 degrees

# Translate to spherical Mercator or Google projection
poly_g = transform(project, poly)
p1_g = transform(project, p1)

poly_g.contains(p1_g)  # True
poly_g.distance(p1_g)  # 0.0 meters
Run Code Online (Sandbox Code Playgroud)

似乎得到了正确的答案.


Sam*_*Rad 9

虽然你已经接受了答案,但除了@ MikeT的答案,我会加入这对于谁可能想要做同样的将来游客matplotlib底图mpl_toolkit:

from mpl_toolkits.basemap import Basemap
from matplotlib.path import Path


# Mercator Projection
# http://matplotlib.org/basemap/users/merc.html
m = Basemap(projection='merc', llcrnrlat=-80, urcrnrlat=80,
            llcrnrlon=-180, urcrnrlon=180, lat_ts=20, resolution='c')

# Poly vertices
p = [[25.774252, -80.190262], [18.466465, -66.118292], [32.321384, -64.75737]]

# Projected vertices
p_projected = [m(x[1], x[0]) for x in p]

# Create the Path
p_path = Path(p_projected)

# Test points
p1 = [27.254629577800088, -76.728515625]
p2 = [27.254629577800088, -74.928515625]

# Test point projection
p1_projected = m(p1[1], p1[0])
p2_projected = m(p2[1], p2[0])

if __name__ == '__main__':
    print(p_path.contains_point(p1_projected))  # Prints 1
    print(p_path.contains_point(p2_projected))  # Prints 1
Run Code Online (Sandbox Code Playgroud)