¿Existe la herramienta ArcPy para cambiar el tamaño de polígonos como la herramienta Escala de la barra de herramientas Edición avanzada en ArcMap?

17

Estoy escribiendo un script en python para ArcGIS 10.3. Conozco a Scale tool en la interfaz de ArcGIS pero no puedo encontrar dicho comando arcpy. Existe?

Como puede ver en la imagen, Scale tool funciona de manera diferente a Buffer tool : cambia la forma del polígono original. Así que la pregunta es:

¿Puedo usar Scale tool (disponible desde la interfaz de ArcGIS) usando arcpy?

    
pregunta Mr. Che 10.11.2015 - 13:39

1 respuesta

27

No tengo conocimiento de nada en la API de arcpy que haga el escalado por ti, pero escribir una función para hacerlo sería relativamente simple.

El siguiente código realiza el escalado de las funciones 2D y no tiene en cuenta los valores M o Z:

import arcpy
import math

def scale_geom(geom, scale, reference=None):
    """Returns geom scaled to scale %"""
    if geom is None: return None
    if reference is None:
        # we'll use the centroid if no reference point is given
        reference = geom.centroid

    refgeom = arcpy.PointGeometry(reference)
    newparts = []
    for pind in range(geom.partCount):
        part = geom.getPart(pind)
        newpart = []
        for ptind in range(part.count):
            apnt = part.getObject(ptind)
            if apnt is None:
                # polygon boundaries and holes are all returned in the same part.
                # A null point separates each ring, so just pass it on to
                # preserve the holes.
                newpart.append(apnt)
                continue
            bdist = refgeom.distanceTo(apnt)

            bpnt = arcpy.Point(reference.X + bdist, reference.Y)
            adist = refgeom.distanceTo(bpnt)
            cdist = arcpy.PointGeometry(apnt).distanceTo(bpnt)

            # Law of Cosines, angle of C given lengths of a, b and c
            angle = math.acos((adist**2 + bdist**2 - cdist**2) / (2 * adist * bdist))

            scaledist = bdist * scale

            # If the point is below the reference point then our angle
            # is actually negative
            if apnt.Y < reference.Y: angle = angle * -1

            # Create a new point that is scaledist from the origin 
            # along the x axis. Rotate that point the same amount 
            # as the original then translate it to the reference point
            scalex = scaledist * math.cos(angle) + reference.X
            scaley = scaledist * math.sin(angle) + reference.Y

            newpart.append(arcpy.Point(scalex, scaley))
        newparts.append(newpart)

    return arcpy.Geometry(geom.type, arcpy.Array(newparts), geom.spatialReference)

Puede llamarlo con un objeto de geometría, un factor de escala (1 = mismo tamaño, 0.5 = medio tamaño, 5 = 5 veces más grande, etc.), y un punto de referencia opcional:

scale_geom(some_geom, 1.5)

Use esto junto con los cursores para escalar una clase de entidad completa, asumiendo que la clase de entidad de destino ya existe:

incur = arcpy.da.SearchCursor('some_folder/a_fgdb.gdb/orig_fc', ['[email protected]','[email protected]'])
outcur = arcpy.da.InsertCursor('some_folder/a_fgdb.gdb/dest_fc', ['[email protected]'])

for row in incur:
    # Scale each feature by 0.5 and insert into dest_fc
    outcur.insertRow([scale_geom(row[1], 0.5)])
del incur
del outcur

edite: aquí hay un ejemplo que utiliza una aproximación de la geometría de su prueba, para 0.5 y 5 veces:

¡Tambiénprobadoconpolígonosdemúltiplesanillos(agujeros)!

Una explicación, según se solicita:

scale_geom toma un solo polígono y recorre cada vértice, midiendo la distancia desde él hasta un punto de referencia (por defecto, el centroide del polígono).
Esa distancia se escala según la escala dada para crear el nuevo vértice 'escalado'.

La escala se realiza esencialmente dibujando una línea en la longitud escalada desde el punto de referencia hasta el vértice original, con el final de la línea convirtiéndose en el vértice escalado. El ángulo y la rotación están ahí porque es más sencillo calcular la posición del final de la línea a lo largo de un solo eje y luego girarlo 'en su lugar'.

    
respondido por el Evil Genius 17.11.2015 - 15:20

Lea otras preguntas en las etiquetas