Lesen Sie die Hilfethemen...
1 Featureclass zu NumPy Array
FeatureClassToNumPyArray kann verwendet werden, um die Scheitelpunkte aus Geometrie-Features zu extrahieren. Wenn sie einteilig ohne Löcher sind, haben Sie eine exakte Darstellung, die zur Rekonstruktion der Eingaben verwendet werden kann. Wenn dies nicht der Fall ist, erfordert die Rekonstruktion etwas Arbeit (siehe https://github.com/Dan-Patterson/numpy_geometry für das `npg` Modul).
2 NumPy Array zu Featureclass
NumPyArrayToFeatureClass überschreibt keine vorhandene Feature-Class, auch wenn die overwriteOutput-Umgebung auf True gesetzt ist.
------------------------------
Schrittweise... ein Notebook ist angehängt
# ---- Importe
import arcpy
import numpy as np
from numpy.lib.recfunctions import structured_to_unstructured as stu
from numpy.lib.recfunctions import append_fields # wie arcpy ExtendTable
Ich gehe davon aus, dass Sie ein Notebook in ArcGIS Pro verwenden. Ich zeige eine einfache Umwandlung von Polygonen in alle Punkte. Die anderen Optionen können ebenfalls programmiert werden oder Sie kaufen einfach eine höhere Lizenzstufe von Pro.
Gehen Sie davon aus, dass Ihre Ebene in einer Karte ist. Geben Sie den Ebenennamen an und ob Sie zusätzliche Tabellenfelder übernehmen möchten.
# Geben Sie die zu verwendende Ebene für die Variable `lyr_name` an
# Dies funktioniert nur für Featureclasses... keine weitere Fehlerprüfung... der Druck ist hoch
#
lyr_name = 'sq3' # -- geben Sie den Namen der Featureclass ein
extra_fields = True # -- True behält alle zusätzlichen Felder, False sonst... nur einige? Schreiben Sie Ihre eigenen
Jetzt der große Schritt.
- prüfen Sie, ob die Ebene in der aktiven Karte existiert. Wenn ja, fahren Sie fort, andernfalls brechen Sie ab.
- die Datenquelle der Ebene und der räumliche Bezug werden ermittelt,
- eine Liste von Feldern zum Entfernen aus der Ausgabe (Zeilen 11-15)
- ein Array wird erstellt (Zeilen 16-21). Dies ist ein numpy-Array, das mit der arcpy.da-Funktion für diesen Zweck erzeugt wurde.
- es folgt eine Bereinigung, Ausgabefelder werden angegeben und zur Ausgabe hinzugefügt (falls vorhanden)
- die Ausgabefeatureclass wird erstellt (Zeile 36)
- und zur Karte hinzugefügt (Zeile 37)
# ---- Projekt-, Karten- und Ebenensammlung
# Das aktuelle Projekt mit der aktiven Karte wird auf den oben angegebenen Ebenennamen überprüft.
# Wenn es existiert, werden die Scheitelpunkte in eine Punkt-Featureclass umgewandelt.
#
aprx = arcpy.mp.ArcGISProject("CURRENT")
map_ = aprx.activeMap
lyrs = map_.listLayers(lyr_name)
if lyrs:
in_fc = lyrs[0].dataSource # -- Pfad zur Featureclass
SR = arcpy.Describe(in_fc).spatialReference
ignore_flds = ['OBJECTID', 'Shape', 'Shape_Area', 'Shape_Length'] # -- hinzufügen wenn gewünscht
keep_flds = ["OID@", "SHAPE@X", "SHAPE@Y"]
if extra_fields:
add_flds = [f.name for f in arcpy.ListFields(in_fc) if f.name not in ignore_flds]
keep_flds = keep_flds + add_flds
arr = arcpy.da.FeatureClassToNumPyArray(
in_fc,
field_names=keep_flds,
spatial_reference=SR,
explode_to_points=True
)
# -- Überprüfungen der Ausgabefeatureclass
out_fc = in_fc + "_pnts"
if arcpy.Exists(out_fc): # -- löschen falls vorhanden
arcpy.management.Delete(out_fc)
#
# -- Array-Überprüfungen und Kombinieren von Koordinatenwerten
dt_ = arr.dtype
dt_names = [(i[0].replace("@", "_"), i[1]) for i in arr.dtype.descr]
arr.dtype = dt_names
#
final_arr = append_fields(arr, ["Pnt_x", "Pnt_y"], [arr["SHAPE_X"], arr["SHAPE_Y"]])
print("\nAusgabefelder :\n{}".format(final_arr.dtype.names))
#
# -- Erzeugen der Ausgabe und Hinzufügen zur Karte.
arcpy.da.NumPyArrayToFeatureClass(final_arr, out_fc, ["SHAPE_X", "SHAPE_Y"], spatial_reference=SR)
map_.addDataFromPath(out_fc) # -- Ergebnisse zur Karte hinzufügen
#
else:
print("Keine Ebene namens {}".format(lyr_name))
Und die Ergebnisse sind
Ich erspare Ihnen den Tabelleninhalt, aber sie sind vorhanden.
--------------
Wenn Sie das Python-Fenster bevorzugen
import arcpy
import numpy as np
in_fc = r"C:\...Pfad zu Ihrer Ebene...\...layer_name..."
keep_flds = ["OID@", "SHAPE@X", "SHAPE@Y"]
SR = arcpy.Describe(in_fc).spatialReference
arr = arcpy.da.FeatureClassToNumPyArray(
in_fc,
field_names=keep_flds,
spatial_reference=SR,
explode_to_points=True
)
Dies zeigt das strukturierte Array-Datenformat. (aus Platzgründen gekürzt)
arr
array([(1, 300009. , 5000001. ), (1, 300000. , 5000000. ),
(1, 300002. , 5000008. ), (1, 300008. , 5000010. ),
... snip
(7, 300004. , 5000009. ), (7, 300002. , 5000009. ),
(7, 300002. , 5000011. )],
dtype=[('OID@', '<i4'), ('SHAPE@X', '<f8'), ('SHAPE@Y', '<f8')])
You can then split the array into its constituent shapes using the OID@ field. Basically determine the difference in the sequential id values, where they differ from 0, get the positional index to use for splitting.
spl = np.nonzero(np.diff(arr["OID@"]))[0] + 1
From there, you can produce subarrays
subs = np.array_split(arr, spl)
subs[0] # -- the first as an example
array([(1, 300009.000, 5000001.000), (1, 300000.000, 5000000.000),
(1, 300002.000, 5000008.000), (1, 300008.000, 5000010.000),
(1, 300010.000, 5000010.000), (1, 300010.000, 5000008.000),
(1, 300009.000, 5000001.000), (1, 300003.000, 5000003.000),
(1, 300007.000, 5000003.000), (1, 300005.000, 5000007.000),
(1, 300003.000, 5000003.000)],
dtype=[('OID@', '<i4'), ('SHAPE@X', '<f8'), ('SHAPE@Y', '<f8')])
From there you could process to just take the first or last point (one of the main tool options that requires and advanced licence).
frst = [i[0] for i in subs] # let's grab the first point of each shape
frst
[(1, 300009.000, 5000001.000),
(2, 300010.000, 5000008.000),
(3, 300008.000, 5000011.000),
(4, 300006.000, 5000012.000),
(5, 300002.500, 5000013.000),
(6, 300004.000, 5000012.500),
(7, 300002.000, 5000011.000)]
As a teaser, you can even place a point at a certain percentage along the polygon perimeter with a little numpy magic
from numpy.lib.recfunctions import structured_to_unstructured as stu
base = [stu(a[["SHAPE@X", "SHAPE@Y"]]) for a in subs]
halfway = [_percent_along_(a, percent=50) for a in base]
halfway
[array([ 300010.000, 5000009.950]),
array([ 300008.500, 5000012.000]),
array([ 300005.000, 5000010.310]),
array([ 300005.056, 5000014.972]),
array([ 300000.214, 5000010.643]),
array([ 300002.527, 5000012.991]),
array([ 300003.894, 5000009.000])]
and the function for placing the points
def _percent_along_(a, percent=0):
"""Add a point along a poly feature at a distance from the start point."""
# a = _base_(a)
if percent > 1.:
percent /= 100.
dxdy = a[1:, :] - a[:-1, :] # coordinate differences
leng = np.sqrt(np.einsum('ij,ij->i', dxdy, dxdy)) # segment lengths
cumleng = np.concatenate(([0], np.cumsum(leng)))
perleng = cumleng / cumleng[-1]
if percent <= 0: # check for faulty distance or start point
return a[0]
if percent >= perleng[-1]: # check for greater distance than cumulative
return a[-1]
_end_ = np.digitize(percent, perleng)
x1, y1 = a[_end_]
_start_ = _end_ - 1
x0, y0 = a[_start_]
t = percent - perleng[_start_]
xt = x0 * (1. - t) + (x1 * t)
yt = y0 * (1. - t) + (y1 * t)
return np.array([xt, yt])
Or you can 'arcpy' it if you prefer to crank up Pro.
So, basic functionality shouldn't be completely removed by license levels. If you have the need convert features to points, remember that tools are available within.