# Polygon scaling using arcpy

Is it possible to scale each polygon by a numeric value in an attribute table field using arcpy. I have updated the code from some previous excellent work done by Evil Genius

``````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)
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)

incur = arcpy.da.SearchCursor(r'D:\ZOC\POLYPGDIS_MASTER.shp', ['OID@','SHAPE@'])
outcur = arcpy.da.InsertCursor(r'D:\ZOC\POLYPGDIS_MASTER_1.shp', ['SHAPE@'])

for row in incur:
# Scale each feature by 0.5 and insert into dest_fc
outcur.insertRow([scale_geom(row, arcpy.da.SearchCursor(r'D:\ZOC\POLYPGDIS_MASTER.shp', ['Scale_Fact']))])
del incur
del outcur
``````
• What do you mean by "scale"? Can you provide a more specific example of what you're trying to do? Mar 15, 2016 at 16:06
• Of course it's possible, but not without code. In addition to scale, you'll need to have some way to choose the origin (basis of scaling), and then extract, alter, and either update or insert the resulting geometry. Mar 15, 2016 at 16:09
• I have numerous polygons in one shapefile that I need to scale up or down. Each row in the attribute table contains the numeric value by how much to scale the polygon. Hope this makes sense? Mar 15, 2016 at 16:12
• I seen this, which nearly does it for me: gis.stackexchange.com/questions/169694/… Mar 15, 2016 at 16:14
• So take the source from the other script, try modifying it to read both geometry and scale, and if it fails to work as intended, post the entire content here, with a link to the original in the body, then ask your question about the code you've modified, with details about the problem. Coding questions here in GIS SE are expected to have code. Mar 15, 2016 at 16:25

Going back to the referenced code that you say in the comments nearly does it for you, I think all you need to do is add your scale column to the input cursor.

``````incur = arcpy.da.SearchCursor('some_folder/a_fgdb.gdb/orig_fc', ['OID@','SHAPE@', 'Scale'])
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, row)])
del incur
del outcur
``````
• Thank you so much for this. I was getting completely bogged down. I cannot fully understand how arcpy.da.SearchCursor works with insertRow. But this is great. Thanks again Mar 16, 2016 at 8:54
• Think of the insert cursor as nesting inside the search cursor. As you iterate through each row of the search cursor, you insert a row into the output table based on the values from the search cursor row.
– RHB
Mar 16, 2016 at 14:35
• This is great, is it possible for the code to insert the new rows and populate the news rows with the old values from the attribute table. Currently, it inserts the new rows, but all values are 0. Thanks again Mar 23, 2016 at 15:49
• Yes, just add the columns you want to include the same way I added the Scale column, then add the corresponding row[x] to your insertRow statement. X = the column position of the column in the search cursor. As in my example, the Scale column is row.
– RHB
Mar 23, 2016 at 16:34
• Ok, so I do this: `incur = arcpy.da.SearchCursor(r'D:\ZOC\POLYPGDIS_MASTER.shp', ['OID@','SHAPE@','Scale_Fact','LOCX']) outcur = arcpy.da.InsertCursor(r'D:\ZOC\POLYPGDIS_MASTER_1.shp', ['SHAPE@']) for row in incur: # Scale each feature by 0.5 and insert into dest_fc outcur.insertRow([scale_geom(row, row), row])` and I get the error: sequence size must match size of the row Mar 23, 2016 at 16:42