¿Crea una herramienta de script que creará una copia de la clase de entidad y la compensará por la distancia dada usando ArcPy?

9

Quiero duplicar una clase de entidad de polígono y compensar todos los polígonos en aproximadamente 10 pies en las direcciones x e y. Pregunté si había alguna forma de hacerlo la semana pasada, y me informaron que probablemente necesitaría hacer mi propio script de Python usando arcpy. Hice mi propio script usando arcpy, pero no funciona:

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

Sigo recibiendo este error en la línea 70

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

No puedo entender por qué me está dando este error, ya que definí la entrada como una matriz.

¿Alguien sabe por qué recibo este error?

Curtidor
fuente

Respuestas:

14

En lugar de crear e intentar agregar un polígono a su matriz, agregue su matriz de puntos a la matriz de partes. Cambia esto:

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

A esto:

partArray.add(pntArray)
pntArray.removeAll()

Además, hay un problema con su código que intenta insertar la fila. Debe usar su cursor de inserción para crear una nueva fila e insertarla. Comenzando en la línea 77 en su ejemplo de código original:

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

Editar : También debe mover el "pnt = part.next ()" en su bucle while interior por debajo de su bloque try / except para que no omita ningún punto y para que se ejecute el bloque if que prueba los anillos interiores. Como es, el código en su publicación no recogerá los anillos interiores. Aquí está todo después de todas las modificaciones que he descrito:

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
Derek Swingley
fuente
Acabo de descubrir que el guión cambia todo perfectamente, excepto las características que tienen 2 o más anillos interiores. Dejará líneas conectadas y distorsionará el polígono. ¿Sabes cómo dar cuenta de esto?
Tanner