Verdichtung
Die Verdichtung von Polygongrenzen oder Polyliniensegmenten ist eine häufige Aufgabe.
In einer früheren Version habe ich über die Verdichtung von Geometrien basierend auf einem "Faktor" geschrieben, also das Doppelte, Dreifache... der Anzahl der Punkte entlang eines Segments.
Die planare Verdichtung kann mit den Bearbeitungswerkzeugen durchgeführt werden, mit mehreren Optionen. Sie ist nicht verfügbar aus irgendeinem Grund auf der Basic-Lizenzstufe.
Verdichten (Bearbeitung)—ArcGIS Pro | Dokumentation
Dieses Schreiben konzentriert sich auf die Verdichtung basierend auf einem planaren Abstandsschritt entlang der Linie/Umrandung. Es ist die gebräuchlichste Anwendung.
Es wird ein paar meiner Toolsets enthalten (unten aufgeführt).
Der Code veranschaulicht die Leistungsfähigkeit von numpy in der Geoverarbeitung.
def _pnts_on_line_(a, spacing=1, is_percent=False): # Verdichtung nach Entfernung
"""Fügt Punkte in einem festen Abstand zu einem Array hinzu, das eine Linie darstellt.
Parameter
----------
a : array
Eine Folge von `Punkten`, x,y-Paaren, die die Grenzen eines Polygons
oder eines Polylinienobjekts darstellen.
spacing : Zahl
Abstand zwischen den hinzuzufügenden Punkten auf der Linie.
is_percent : boolean
Gibt die Verdichtung als Prozentsatz der Gesamtlänge an.
"""
a = _get_base_(a)
N = len(a) - 1 # Segmente
dxdy = a[1:, :] - a[:-1, :] # Koordinatendifferenzen
leng = np.sqrt(np.einsum('ij,ij->i', dxdy, dxdy)) # Segmentlängen
if is_percent: # als Prozentsatz
spacing = abs(spacing)
spacing = min(spacing / 100, 1.)
steps = (sum(leng) * spacing) / leng # Schrittweite
else:
steps = leng / spacing # Schrittweite
deltas = dxdy / (steps.reshape(-1, 1)) # Koordinatenschritte
pnts = np.empty((N,), dtype='O') # Erstelle ein `O`-Array
for i in range(N): # durchlaufe die Segmente und erstelle
num = np.arange(steps[i]) # die neuen Punkte
pnts[i] = np.array((num, num)).T * deltas[i] + a[i]
a0 = a[-1].reshape(1, -1) # füge den letzten Punkt hinzu und verbinde alles
return np.concatenate((*pnts, a0), axis=0)
Ich denke, meine zwei Lieblingszeilen sind ...
dxdy = a[1:, :] - a[:-1, :] # Koordinatendifferenzen
leng = np.sqrt(np.einsum('ij,ij->i', dxdy, dxdy)) # Segmentlängen
Einstein war ein kluger Typ.
Seine Notationssyntax ist in vielen Sprachen implementiert und verursacht Gehirnverrenkungen, bis man sich daran gewöhnt hat (Stoff für einen anderen Blog).
Kurz gesagt, dxdy stellt die sequentiellen Differenzen in den Koordinaten eines Arrays dar (liest Polygon-/Polylinienkoordinaten).
Kein mühsames Lesen der Geometrie und Subtrahieren jeder x- und y-Koordinate einzeln. Eine Zeile und fertig.
Jetzt bedeutet a[1:, :] ab dem zweiten Koordinatenpaar und a[:-1, :] bedeutet vom ersten Koordinatenpaar bis zum vorletzten (Indexierung beginnt bei Null).
Kopfschmerzen? Du hast zu lange Pandas oder shapely benutzt.
So sieht ein einfaches Polygon aus, dargestellt als Array (sogar ein arcpy.Array)
a # ---- ein Array von x,y-Koordinaten... erster und letzter sind gleich
array([[ 0.00, 0.00],
[ 2.00, 8.00],
[ 8.00, 10.00],
[ 10.00, 10.00],
[ 10.00, 8.00],
[ 9.00, 1.00],
[ 0.00, 0.00]])
dxdy # ---- sequentielle Delta x und Delta y zwischen den Paaren
array([[ 2.00, 8.00],
[ 6.00, 2.00],
[ 2.00, 0.00],
[ 0.00, -2.00],
[ -1.00, -7.00],
[ -9.00, -1.00]])
leng # ---- Abstand zwischen den Punktpaaren
array([ 8.25, 6.32, 2.00, 2.00, 7.07, 9.06])
Nachdem die Magie vollbracht ist, besteht der Rest nur darin festzustellen, ob du basierend auf einer absoluten Entfernung oder als Prozentsatz der Gesamtdistanz verdichten möchtest.