Tuesday 26 May 2015

Optimizing ArcPy code to cut polygon?


There is a lot of nested loops and wondering of ways I could speed up this code? Any ideas?


Note: This requires ArcMap 10.2


def cut_geometry(to_cut, cutter):

"""
Cut a feature by a line, splitting it into two geometries.
:param to_cut: The feature to cut.
:param cutter: The polyline to cut the feature by.
:return: The feature with the split geometry added to it.
"""
arcpy.AddField_management(to_cut, "SOURCE_OID", "LONG")
geometries = None
with arcpy.da.SearchCursor(cutter, "SHAPE@") as lines:
for line in lines:

with arcpy.da.UpdateCursor(to_cut, ["SHAPE@", "OID@"]) as polygons:
for polygon in polygons:
if line[0].disjoint(polygon[0]) == False:
geometries = polygon[0].cut(line[0])
polygons.deleteRow()
with arcpy.da.InsertCursor(to_cut, ["SHAPE@", "SOURCE_OID"]) as insert_cursor:
for geometry in geometries:
if geometry.area > 0:
insert_cursor.insertRow([geometry, polygon[1]])



I was able to move out the insert_cursor, by adding in code for an edit session. However can't figure out how to pull out the UpdateCursor without losing the functionality, since it's deleting and inserting rows back into the original feature it needs to get a new UpdateCursor each time.


def cut_geometry(to_cut, cutter):
"""
Cut a feature by a line, splitting it into its separate geometries.
:param to_cut: The feature to cut.
:param cutter: The polylines to cut the feature by.
:return: The feature with the split geometry added to it.
"""
arcpy.AddField_management(to_cut, "SOURCE_OID", "LONG")

geometries = None
polygon = None

edit = arcpy.da.Editor(os.path.dirname(to_cut))
edit.startEditing(False, False)

insert_cursor = arcpy.da.InsertCursor(to_cut, ["SHAPE@", "SOURCE_OID"])

with arcpy.da.SearchCursor(cutter, "SHAPE@") as lines:
for line in lines:

with arcpy.da.UpdateCursor(to_cut, ["SHAPE@", "OID@"]) as polygons:
for polygon in polygons:
if line[0].disjoint(polygon[0]) == False:
geometries = polygon[0].cut(line[0])
polygons.deleteRow()
for geometry in geometries:
if geometry.area > 0:
insert_cursor.insertRow([geometry, polygon[1]])

edit.stopEditing(True)


Answer



[UPDATED TO HANDLE INTERSECTING LINES]


Can also be download as a toolbox here: https://github.com/tforward/CutPolygonByLines


Split Polygon on Lines


import os

def cut_geometry(to_cut, cutter):
"""
Cut a feature by a line, splitting it into its separate geometries.
:param to_cut: The feature to cut.

:param cutter: The polylines to cut the feature by.
:return: The feature with the split geometry added to it.
"""
arcpy.AddField_management(to_cut, "SOURCE_OID", "LONG")
geometries = []
polygon = None

edit = arcpy.da.Editor(os.path.dirname(to_cut))
edit.startEditing(False, False)


insert_cursor = arcpy.da.InsertCursor(to_cut, ["SHAPE@", "SOURCE_OID"])

with arcpy.da.SearchCursor(cutter, "SHAPE@") as lines:
for line in lines:
with arcpy.da.UpdateCursor(to_cut, ["SHAPE@", "OID@", "SOURCE_OID"]) as polygons:
for polygon in polygons:
if line[0].disjoint(polygon[0]) == False:
if polygon[2] == None:
id = polygon[1]
# Remove previous geom if additional cuts are needed for intersecting lines

if len(geometries) > 1:
del geometries[0]
geometries.append([polygon[0].cut(line[0]), id])
polygons.deleteRow()
for geometryList in geometries:
for geometry in geometryList[0]:
if geometry.area > 0:
insert_cursor.insertRow([geometry, geometryList[1]])

edit.stopEditing(True)



cut_geometry(r"PATH_TO_POLY", r"PATH_TO_LINES")

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...