Запись геометрий

Используя курсоры вставки и обновления, вы можете использовать скрипты для создания объектов в классах объектов или для обновления существующих. С помощью скрипта можно задать пространственный объект Point, создав объект, заполнив его свойства и поместив его в Array. Затем массив можно использовать для задания геометрии пространственного объекта, используя классы геометрии Polygon, Polyline, PointGeometry или Multipoint.


import arcpy

fc = "c:/data/gdb.gdb/roads"
cursor = arcpy.da.InsertCursor(fc, ["SHAPE@"])
array = arcpy.Array(
    [arcpy.Point(-77.4349451, 37.5408265), arcpy.Point(-78.6384349, 35.7780943)]
)
spatial_reference = arcpy.SpatialReference(4326)
polyline = arcpy.Polyline(array, spatial_reference)

cursor.insertRow([polyline])

Как показано выше, простые участки геометрии определяются массивом точек. Аналогичным образом, с помощью того же курсора из массива массивов точек можно создать составной объект, как показано ниже.

import arcpy

first_part = arcpy.Array(
    [arcpy.Point(-77.4349451, 37.5408265), arcpy.Point(-78.6384349, 35.7780943)]
)
second_part = arcpy.Array(
    [arcpy.Point(-79.7910143, 36.0786785), arcpy.Point(-80.8546435, 35.2315402)]
)

array = arcpy.Array([first_part, second_part])
spatial_reference = arcpy.SpatialReference(4326)
multipart_feature = arcpy.Polyline(array, spatial_reference)

cursor.insertRow([multipart_feature])

При записи точечных объектов для задания геометрии точечного объекта используется только один объект точки. Более простой и более эффективный способ создания точек - с помощью токена SHAPE@XY (а также токенов SHAPE@M и SHAPE@Z, если необходимо).


import arcpy

# fc is a point feature class
fc = "c:/data/gdb.gdb/stops"
with arcpy.da.InsertCursor(fc, ["SHAPE@XY"]) as cursor:
    xy = (5997594.4753, 2069901.75682)

    cursor.insertRow([xy])

Кроме того, точки можно записывать с помощью токена SHAPE@.


import arcpy

with arcpy.da.UpdateCursor(
    "Shops", ["SHAPE@", "ST_ADDRESS", "ZIP"], where_clause="NAME = 'The Cupcakery'"
) as cursor:
    for row in cursor:
        pt = arcpy.Point(-117.18854177699995, 34.06044265100007)
        row = [pt, "540 W Stuart Ave", 92374]
        cursor.updateRow(row)

Все геометрии перед записью в качестве класса пространственного объекта проверяются. Такие проблемы, как неправильная ориентация кольца и самопересекающиеся полигоны, можно решить путем упрощения геометрии перед ее вставкой.

На следующем примере показано, как прочитать набор координат (заданный с помощью coords_list), содержащий несколько линейных координат, и использовать их для создания класса пространственных объектов:

# Create a new line feature class using a text file of coordinates.
# Each coordinate entry is semicolon delimited in the format of ID;X;Y
import arcpy
import os

# List of coordinates (ID, X, Y)
coords_list = [
    [1, -61845879.0968, 45047635.4861],
    [1, -3976119.96791, 46073695.0451],
    [1, 1154177.8272, -25134838.3511],
    [1, -62051091.0086, -26160897.9101],
    [2, 17365918.8598, 44431999.7507],
    [2, 39939229.1582, 45252847.3979],
    [2, 41170500.6291, 27194199.1591],
    [2, 17981554.5952, 27809834.8945],
    [3, 15519011.6535, 11598093.8619],
    [3, 52046731.9547, 13034577.2446],
    [3, 52867579.6019, -16105514.2317],
    [3, 17160706.948, -16515938.0553],
]

# The output feature class to be created
outFC = arcpy.GetParameterAsText(0)

# Get the template feature class
template = arcpy.GetParameterAsText(1)

cur = None
try:
    # Create the output feature class
    arcpy.management.CreateFeatureclass(
        os.path.dirname(outFC), os.path.basename(outFC), "POLYLINE", template
    )

    # Access spatial reference of template to define spatial
    # reference of geometries
    spatial_reference = arcpy.Describe(template).spatialReference

    # Open an insert cursor for the new feature class
    cur = arcpy.da.InsertCursor(outFC, ["SHAPE@"])

    # Create an array object needed to create features
    array = arcpy.Array()

    # Initialize a variable for keeping track of a feature's ID.
    ID = -1
    for coords in coords_list:
        if ID == -1:
            ID = coords[0]

        # Add the point to the feature's array of points
        #   If the ID has changed, create a new feature
        if ID != coords[0]:
            cur.insertRow([arcpy.Polyline(array)])
            array.removeAll()
        array.add(arcpy.Point(coords[1], coords[2], ID=coords[0]))
        ID = coords[0]

    # Add the last feature
    polyline = arcpy.Polyline(array, spatial_reference)
    cur.insertRow([polyline])


except Exception as e:
    print(e)
finally:
    # Clean up the cursor if necessary
    if cur:
        del cur

В следующем примере существующий объект объединяется с новым объектом, и этот существующий ранее объект изменяется с помощью интегрированного объекта.


import arcpy

array = arcpy.Array(
    [
        arcpy.Point(-117.1723261, 34.0240298),
        arcpy.Point(-117.1722951, 34.0240060),
        arcpy.Point(-117.1719831, 34.0240465),
        arcpy.Point(-117.1716733, 34.0241251),
    ]
)

with arcpy.da.UpdateCursor(
    "HikingTrails", ["SHAPE@"], where_clause="TRAILNAME = 'Sunset Ridge Trail'"
) as cursor:
    for row in cursor:
        new_polyline = arcpy.Polyline(array)
        row[0] = row[0].union(new_polyline)
        cursor.updateRow(row)

Чтобы создать составные полигональные и полилинейные объекты, а также полигональные объекты с внутренними кольцами, сначала создайте массив массивов. Затем отправьте его в классы Polygon и Polyline.

Создание геометрии на основе списка координат

Геометрию объекта также можно создать на основе списка координат. Этот подход повышает производительность, так как позволяет избежать сложностей при создании геометрии объектов. Однако это работает только для объектов, состоящих из одной части и, в случае с полигонов, для объектов без «дырок» внутри. Используемые единицы должны соответствовать единицам пространственной привязки класса объектов.

В приведенном ниже примере один полилинейный объект создается из списка пар x, y.


import arcpy

coordinates = [
    (-117.2000424, 34.0555514),
    (-117.2000788, 34.0592066),
    (-117.1957315, 34.0592309),
    (-117.1956951, 34.0556001),
]

# Create a feature class with a spatial reference of GCS WGS 1984
result = arcpy.management.CreateFeatureclass(
    arcpy.env.scratchGDB, "esri_square", "POLYLINE", spatial_reference=4326
)
feature_class = result[0]

# Write feature to new feature class
with arcpy.da.InsertCursor(feature_class, ["SHAPE@"]) as cursor:
    cursor.insertRow([coordinates])

Аналогично, в приведенном ниже примере один 3D-полилинейный объект создается из списка координат x, y, z.


import arcpy

coordinates = [
    (-117.2000424, 34.0555514, 1),
    (-117.2000788, 34.0592066, 2),
    (-117.1957315, 34.0592309, 5),
    (-117.1956951, 34.0556001, 2),
]

# Create a feature class with a spatial reference of GCS WGS 1984
result = arcpy.management.CreateFeatureclass(
    arcpy.env.scratchGDB,
    "esri_square_z",
    "POLYLINE",
    has_z="ENABLED",
    spatial_reference=4326,
)
feature_class = result[0]

# Write feature to new feature class
with arcpy.da.InsertCursor(feature_class, ["SHAPE@"]) as cursor:
    cursor.insertRow([coordinates])