Dieses Demo-Programm (bestimmt in einem IPython Notebook ausgeführt werden, Sie müssen matplotlib
, mpl_toolkits.basemap
, pyproj
und shapely
) soll immer größere Kreise auf der Oberfläche der Erde plotten . Es funktioniert korrekt, solange der Kreis einen der Pole nicht überquert. Wenn das passiert, ist das Ergebnis völliger Unsinn, wenn es auf einer Karte geplottet wird (siehe unten Zelle 2)Fix up formschön Polygon-Objekt, wenn diskontinuierlich nach Kartenprojektion
Wenn ich sie "in einer Lücke" anstatt auf einer Karte (siehe unten Zelle 3) plotten, sind die Ergebnisse in der Wenn Sie die horizontale Linie von +180 auf -180 Länge entfernen, würde der Rest der Kurve tatsächlich die Grenze zwischen dem Inneren und Äußeren des gewünschten Kreises begrenzen. Allerdings sind sie falsch in dem das Polygon ist ungültig (.is_valid
ist False), und viel wichtiger, die nicht-Null-Windungszahl Innenraum des Polygons tut nicht umschließen die richtige Region der Karte.
Ich glaube, das passiert, weil shapely.ops.transform
ist blind für die Koordinaten Singularität bei +180 == - 180 Länge. Die Frage ist, wie erkenne ich das Problem und das Polygon reparieren, so dass es den richtigen Bereich der Karte umschließt? In diesem Fall wäre eine angemessene Korrektur das Ersetzen des horizontalen Segments von (X, + 180) - (X, -180) durch drei Zeilen (X, + 180) - (+ 90, + 180) - (+ 90, -180) - (X, -180); aber beachte, dass, wenn der Kreis über die Süd Stange gegangen wäre, die Reparaturlinien stattdessen nach Süden gehen müssten. Und wenn der Kreis über beide Pole gegangen wäre, hätten wir wieder ein gültiges Polygon, aber sein Inneres wäre die Ergänzung dessen, was es sein sollte. Ich muss alle diese Fälle erkennen und sie richtig behandeln. Ich weiß auch nicht, wie man ein formschönes Geometrieobjekt "bearbeitet".
herunterladen Notebook: https://gist.github.com/zackw/e48cb1580ff37acfee4d0a7b1d43a037
## cell 1
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import pyproj
from shapely.geometry import Point, Polygon, MultiPolygon
from shapely.ops import transform as sh_transform
from functools import partial
wgs84_globe = pyproj.Proj(proj='latlong', ellps='WGS84')
def disk_on_globe(lat, lon, radius):
aeqd = pyproj.Proj(proj='aeqd', ellps='WGS84', datum='WGS84',
lat_0=lat, lon_0=lon)
return sh_transform(
partial(pyproj.transform, aeqd, wgs84_globe),
Point(0, 0).buffer(radius)
)
## cell 2
def plot_poly_on_map(map_, pol):
if isinstance(pol, Polygon):
map_.plot(*(pol.exterior.xy), '-', latlon=True)
else:
assert isinstance(pol, MultiPolygon)
for p in pol:
map_.plot(*(p.exterior.xy), '-', latlon=True)
plt.figure(figsize=(14, 12))
map_ = Basemap(projection='cyl', resolution='c')
map_.drawcoastlines(linewidth=0.25)
for rad in range(1,10):
plot_poly_on_map(
map_,
disk_on_globe(40.439, -79.976, rad * 1000 * 1000)
)
plt.show()
## cell 3
def plot_poly_in_void(pol):
if isinstance(pol, Polygon):
plt.plot(*(pol.exterior.xy), '-')
else:
assert isinstance(pol, MultiPolygon)
for p in pol:
plt.plot(*(p.exterior.xy), '-', latlon=True)
plt.figure()
for rad in range(1,10):
plot_poly_in_void(
disk_on_globe(40.439, -79.976, rad * 1000 * 1000)
)
plt.show()
(Die sonnigen Region beigezeigtist ein Beispiel dafür, was ein Kreis, der eine Stange kreuzt sollte aussehen, wenn auf eine equirectangular Karte projiziert wird, solange es heute kein Equinox.)
Dies ist keine triviale Frage, aber es scheint, Sie haben es fast geschafft. Manchmal wünschte ich nur, die Erde wäre flach, hahaha .. Du musst mit der Mehrdeutigkeit umgehen, indem du kontrollierst, ob der Puffer (das "Point (0, 0) .puffer (radius)" Polygon) in der azimutalen äquidistanten Projektion berührt einer der Pole. Wenn Sie das wissen, können Sie das vorgeschlagene Fixup für das neue Polygon in der WGS84-Projektion implementieren, bevor Sie versuchen, es zu plotten. Über die Unterschiede beim Plotten bei der Verwendung der Karte weiß ich nicht, aber ich stelle mir vor, dass das Problem verschwinden wird, wenn Sie nur mit dem fixierten Polygon umgehen. – eguaio