Je ne suis au courant de rien dans l'API arcpy qui fera la mise à l'échelle pour vous, mais écrire une fonction pour le faire serait relativement simple.
Le code ci-dessous effectue la mise à l'échelle des entités 2D et ne prend pas en compte les valeurs M ou 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)
Vous pouvez l'appeler avec un objet géométrique, un facteur d'échelle (1 = même taille, 0,5 = demi-taille, 5 = 5 fois plus grand, etc.) et un point de référence facultatif:
scale_geom(some_geom, 1.5)
Utilisez-le conjointement avec des curseurs pour mettre à l'échelle une classe d'entités entière, en supposant que la classe d'entités de destination existe déjà:
incur = arcpy.da.SearchCursor('some_folder/a_fgdb.gdb/orig_fc', ['OID@','SHAPE@'])
outcur = arcpy.da.InsertCursor('some_folder/a_fgdb.gdb/dest_fc', ['SHAPE@'])
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
edit: voici un exemple utilisant une approximation de votre géométrie de test, pour 0,5 et 5 fois:
Également testé avec des polygones multi-anneaux (trous)!
Une explication, comme demandé:
scale_geom
prend un seul polygone et boucle à travers chaque sommet, mesurant la distance de celui-ci à un point de référence (par défaut, le centroïde du polygone).
Cette distance est ensuite mise à l'échelle par l'échelle donnée pour créer le nouveau sommet «mis à l'échelle».
La mise à l'échelle se fait en traçant essentiellement une ligne à la longueur mise à l'échelle du point de référence à travers le sommet d'origine, la fin de la ligne devenant le sommet mis à l'échelle.
L'angle et la rotation sont là parce qu'il est plus simple de calculer la position de la fin de la ligne le long d'un seul axe, puis de la faire pivoter «en place».