Sprawdź, czy punkt geograficzny znajduje się wewnątrz lub na zewnątrz wielokąta

Używam Pythona i zdefiniowałem szerokości i długości (w stopniach) wielokąta na mapie. Moim celem jest sprawdzenie, czy ogólny punkt P o współrzędnych x,y mieści się w takim wielokątu. Chciałbym więc mieć funkcję, która pozwoli mi sprawdzić taki warunek i zwrócić True lub False Jeśli punkt znajduje się wewnątrz lub na zewnątrz wielokąta.

Tutaj wpisz opis obrazka

W tym przykładzie punkt jest na zewnątrz, więc wynik byłby False

Pytanie: czy istnieje Biblioteka / pakiet, który pozwala osiągnąć mój cel? jeśli tak, który z nich polecasz? czy mógłbyś podać mały przykład, jak go używać?

Oto kod, który do tej pory napisałem:

import numpy as np

# Define vertices of polygon (lat/lon)
v0 = [7.5, -2.5] 
v1 = [2, 3.5]
v2 = [-2, 4]
v3 = [-5.5, -4]
v4 = [0, -10]
lats_vect = np.array([v0[0],v1[0],v2[0],v3[0],v4[0]])
lons_vect = np.array([v0[1],v1[1],v2[1],v3[1],v4[1]])

# Point of interest P
x, y = -6, 5 # x = Lat, y = Lon

## START MODIFYING FROM HERE; DO NOT MODIFY POLYGON VERTICES AND DATA TYPE
# Check if point of interest falls within polygon boundaries
# If yes, return True
# If no, return False

W celu wykreślenia wielokąta i punktu zainteresowania użyłem kartopii i napisałem następujące linie kodu:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.PlateCarree())
ax.stock_img() 

# Append first vertex to end of vector to close polygon when plotting
lats_vect = np.append(lats_vect, lats_vect[0])
lons_vect = np.append(lons_vect, lons_vect[0])
plt.plot([lons_vect[0:-1], lons_vect[1:]], [lats_vect[0:-1], lats_vect[1:]],
         color='black', linewidth=1, 
         transform=ccrs.Geodetic(),
         )   

plt.plot(y, x, 
        '*',          # marker shape
        color='blue',  # marker colour
        markersize=8  # marker size
        )  

plt.show()  

Uwaga :

  • punkty połączone są ze sobą wielkimi kółkami!
  • mam zbadałem w internt i znalazłem kilka podobnych pytań , takich jak ten , ale nie odniosłem sukcesu, ponieważ wszystkie używają plików .shp, których nie mam.
Author: Georgy, 2017-05-10

3 answers

Oto możliwe rozwiązanie mojego problemu.

  1. współrzędne geograficzne muszą być prawidłowo zapisane. Przykład np.array([[Lon_A, Lat_A], [Lon_B, Lat_B], [Lon_C, Lat_C]])
  2. Utwórz wielokąt
  3. Utwórz punkt do przetestowania
  4. Użyj polygon.contains(point), aby sprawdzić, czy punkt znajduje się wewnątrz (True) lub na zewnątrz (False) wielokąta.

Oto brakująca część kodu:

from shapely.geometry import Point
from shapely.geometry.polygon import Polygon

lons_lats_vect = np.column_stack((lons_vect, lats_vect)) # Reshape coordinates
polygon = Polygon(lons_lats_vect) # create polygon
point = Point(y,x) # create point
print(polygon.contains(point)) # check if polygon contains point
print(point.within(polygon)) # check if a point is in the polygon 

Uwaga : wielokąt nie uwzględnia wielkich okręgów, dlatego konieczne jest podzielenie krawędzi na wiele segmenty zwiększając tym samym liczbę wierzchołków.


przypadek szczególny: jeśli punkt leży na granicach wielokąta

Np. print(Polygon([(0, 0), (1, 0), (1, 1)]).contains(Point(0, 0))) zawiedzie

Więc można użyć

print(polygon.touches(point)) # check if point lies on border of polygon 
 34
Author: Federico Gentile,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-30 09:31:56

Istnieje również powstająca biblioteka Pythona turfpy. który jest używany do analizy geoprzestrzennej.

PyPI

Github

Przykład:

from turfpy.measurement import boolean_point_in_polygon
from geojson import Point, Polygon, Feature

point = Feature(geometry=Point((-46.6318, -23.5523)))
polygon = Polygon(
    [
        [
            (-46.653, -23.543),
            (-46.634, -23.5346),
            (-46.613, -23.543),
            (-46.614, -23.559),
            (-46.631, -23.567),
            (-46.653, -23.560),
            (-46.653, -23.543),
        ]
    ]
)
boolean_point_in_polygon(point, polygon)
 8
Author: Sachin Kharude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-26 09:16:26

Innym sposobem jest użycie algorytmu parzysto-nieparzystego wyjaśnionego w tym linku https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html Kod Pythona jest podany w Wikipedii https://en.wikipedia.org/wiki/Even-odd_rule

Ludzie, pamiętajcie, że kolejność punktów, które sprawiają, że wielokąt ma znaczenie! Różna kolejność skutkuje różnymi wielokątami.

 7
Author: lfvv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-22 18:03:42