Создание инструмента-скрипта, который создаст копию класса объектов и сместит его на заданное расстояние, используя ArcPy?

9

Я хочу продублировать класс объектов полигонов и сместить все полигоны примерно на 10 футов в направлениях x и y. Я спросил, есть ли какой-нибудь способ сделать это на прошлой неделе, и мне сообщили, что мне, скорее всего, нужно будет сделать свой собственный скрипт на python, используя arcpy. Я сделал свой собственный скрипт с использованием arcpy, но он не работает:

import arcpy
from arcpy import env
import os

env.overwriteOutput = True

# Get arguments: 
#   Input polygon feature class
#   Output polygon feature class
#
inputFeatureClass = arcpy.GetParameterAsText(0)
outputFeatureClass = arcpy.GetParameterAsText(1)
xShift = arcpy.GetParameterAsText(2)
yShift = arcpy.GetParameterAsText(3)

shapeName = arcpy.Describe(inputFeatureClass).shapeFieldName

# Create the output feature class with the same fields and spatial reference as the input feature class
arcpy.CreateFeatureclass_management(os.path.dirname(outputFeatureClass), os.path.basename(outputFeatureClass), "POLYGON", inputFeatureClass, "", "", inputFeatureClass)

# Create a search cursor to iterate through each row of the input feature class
inrows = arcpy.SearchCursor(inputFeatureClass)
# Create an insert cursor to insert rows into the output feature class
outrows = arcpy.InsertCursor(outputFeatureClass)

# Create empty Point and Array objects
pntArray = arcpy.Array()
partArray = arcpy.Array()

# Loop through each row/feature
for row in inrows:
    # Create the geometry object
    feature = row.getValue(shapeName)

    partnum = 0

    # Count the total number of points in the current multipart feature
    partcount = feature.partCount


    while partnum < partcount:
        part = feature.getPart(partnum)
        pnt = part.next()
        pntcount = 0

        # Enter while loop for each vertex
        #
        while pnt:

            pnt = part.next()
            shiftedPoint = arcpy.Point()
            try:
                shiftedPoint.ID = pnt.ID
                shiftedPoint.X = pnt.X + float(xShift)
                shiftedPoint.Y = pnt.Y + float(yShift)
            except AttributeError:
                continue
            #shiftedPoint = arcpy.Point(float(pnt.X) + float(xShift), float(pnt.Y) + float(yShift))
            pntArray.add(shiftedPoint)
            pntcount += 1

            # If pnt is null, either the part is finished or there is an 
            #   interior ring
            #
            if not pnt: 
                pnt = part.next()
                if pnt:
                    arcpy.AddMessage("Interior Ring:")
        # Create a polygon using the array of points
        polygon = arcpy.Polygon(pntArray)

        # Empty the array for the next run through the loop
        pntArray.removeAll()

        # Add the polygons (or 'parts') to an array. This is necessary for multipart features, or those with holes cut in them
        partArray.add(polygon)
        arcpy.AddMessage("Added a polygon to the partArray!")
        partnum += 1

    # Create a new row object that will be inserted into the ouput feature class. Set newRow = row so that it has the same attributes
    # Set newRow.shape = partArray so that the only thing different about this new feature is that its geometry is different (shifted)
    newRow = row
    newRow.shape = partArray

    outrows.insertRow(newRow)

    # Empy the array for the next run through the loop
    partArray.removeAll()

del inrows, outrows

Я продолжаю получать эту ошибку в строке 70

<type 'exceptions.ValueError'>: Array: Add input not point nor array object

Я не могу понять, почему это дает мне эту ошибку, так как я определил входные данные как массив.

Кто-нибудь знает, почему я получаю эту ошибку?

дубильщик
источник

Ответы:

14

Вместо того, чтобы создавать и пытаться добавить полигон в ваш массив, добавьте ваш массив точек в массив частей. Изменить это:

polygon = arcpy.Polygon(pntArray)
pntArray.removeAll()
partArray.add(polygon)

К этому:

partArray.add(pntArray)
pntArray.removeAll()

Также есть проблема с вашим кодом, который пытается вставить строку. Вам нужно использовать курсор для вставки, чтобы создать новую строку и вставить ее. Начиная со строки 77 в исходном примере кода:

newRow = outrows.newRow()
newRow.shape = partArray
outrows.insertRow(newRow)

Изменить : Вы также должны переместить "pnt = part.next ()" в вашем внутреннем цикле while ниже вашего блока try / исключением, чтобы не пропустить ни одной точки и чтобы выполнялся блок if, который проверяет внутренние кольца. Так как код в вашем посте не подберет внутренние кольца. Вот все это после всех модификаций, которые я описал:

import arcpy
from arcpy import env
import os

env.overwriteOutput = True

# Get arguments: 
#   Input polygon feature class
#   Output polygon feature class
#
inputFeatureClass = arcpy.GetParameterAsText(0)
outputFeatureClass = arcpy.GetParameterAsText(1)
xShift = arcpy.GetParameterAsText(2)
yShift = arcpy.GetParameterAsText(3)
print '\nparams: ', inputFeatureClass, outputFeatureClass, xShift, yShift, '\n'

shapeName = arcpy.Describe(inputFeatureClass).shapeFieldName

# Create the output feature class with the same fields and spatial reference as the input feature class
if arcpy.Exists(outputFeatureClass):
    arcpy.Delete_management(outputFeatureClass)
arcpy.CreateFeatureclass_management(os.path.dirname(outputFeatureClass), os.path.basename(outputFeatureClass), "POLYGON", inputFeatureClass, "", "", inputFeatureClass)

# Create a search cursor to iterate through each row of the input feature class
inrows = arcpy.SearchCursor(inputFeatureClass)
# Create an insert cursor to insert rows into the output feature class
outrows = arcpy.InsertCursor(outputFeatureClass)

# Create empty Point and Array objects
pntArray = arcpy.Array()
partArray = arcpy.Array()

# Loop through each row/feature
for row in inrows:
    # Create the geometry object
    feature = row.getValue(shapeName)
    partnum = 0
    # Count the total number of points in the current multipart feature
    partcount = feature.partCount
    print 'num parts: ', partcount
    while partnum < partcount:
        part = feature.getPart(partnum)
        pnt = part.next()
        print 'outer while'
        pntcount = 0
        # Enter while loop for each vertex
        #
        while pnt:
            shiftedPoint = arcpy.Point()
            try:
                shiftedPoint.ID = pnt.ID
                shiftedPoint.X = pnt.X + float(xShift)
                shiftedPoint.Y = pnt.Y + float(yShift)
            except AttributeError:
                continue
            pntArray.add(shiftedPoint)
            pntcount += 1
            pnt = part.next()
            print 'pntcount: ', pntcount
            # If pnt is null, either the part is finished or there is an 
            #   interior ring
            if pnt is None: 
                pnt = part.next()
                if pnt:
                    arcpy.AddMessage("Interior Ring:")
        partArray.add(pntArray)
        pntArray.removeAll()
        arcpy.AddMessage("Added a polygon to the partArray!")
        partnum += 1
    # Create a new row object that will be inserted into the ouput feature class. Set newRow = row so that it has the same attributes
    # Set newRow.shape = partArray so that the only thing different about this new feature is that its geometry is different (shifted)
    newRow = outrows.newRow()
    newRow.shape = partArray
    outrows.insertRow(newRow)
    # Empy the array for the next run through the loop
    partArray.removeAll()
del inrows, outrows
Дерек Суингли
источник
Я только что обнаружил, что сценарий полностью меняет все, кроме функций, которые имеют 2 или более внутренних колец. Это оставит линии связанными и исказит многоугольник. Вы знаете, как объяснить это?
Таннер