I have a polygon layer with many overlap polygons, each one have a time stamp.
I would like to create a "current status" polygon layer that will not have overlap and each polygon will be the latest.
Some polygons that have partially overlap will be changed.
For example I have one polygon from 2020 that have cross polygon from 2019 and anther cross polygon from 2021
The 2020 polygon will be cut by 2021 polygon but not by 2019 polygon.
The only way I could think about is to take the polygons from the original layer one by one the oldest to the newest, with each one to to an Erase and Append on the result layer.
Is there any better way?
Solved! Go to Solution.
That sketch helped alot.
It turns out to be relatively easy:
# parameters
polygon_fc = "TestPolygons"
id_field = "IntegerField"
date_field = "DateField"
out_path = "memory/CurrentState"
# copy the feature class
out_fc = arcpy.management.CopyFeatures(polygon_fc, out_path)
# read the input fc
fields = [id_field, date_field, "SHAPE@"]
polygons = [dict(zip(fields, row))
for row in arcpy.da.SearchCursor(polygon_fc, fields)
]
# get unique ids
unique_ids = {p[id_field]
for p in polygons
}
# iterate over the unique ids
for uid in unique_ids:
# get all states of that polygon, sort by date
states = [p
for p in polygons
if p[id_field] == uid
]
states.sort(key=lambda s: s[date_field])
# start updating the output fc for this id
with arcpy.da.UpdateCursor(out_fc, ["SHAPE@"], where_clause=f"{id_field} = {uid}", sql_clause=[None, f"ORDER BY {date_field}"]) as cursor:
# cursor and states are in the same order (oldest to newest)
for i, row in enumerate(cursor):
# get the geometry of this row
state_geometry = states[i]["SHAPE@"] # == row[0]
# erase/subtract each newer state
for k in range(i+1, len(states)):
newer_state_geometry = states[k]["SHAPE@"]
state_geometry -= newer_state_geometry # we can use "-" to get the difference between two polygons
# update the geometry
cursor.updateRow([state_geometry])
Original:
Current state:
You can probably whip up some Python script.
But this part is very unclear:
Some polygons that have partially overlap will be changed.
For example I have one polygon from 2020 that have cross polygon from 2019 and anther cross polygon from 2021
The 2020 polygon will be cut by 2021 polygon but not by 2019 polygon.
Can you clarify that, maybe with a sketch?
That sketch helped alot.
It turns out to be relatively easy:
# parameters
polygon_fc = "TestPolygons"
id_field = "IntegerField"
date_field = "DateField"
out_path = "memory/CurrentState"
# copy the feature class
out_fc = arcpy.management.CopyFeatures(polygon_fc, out_path)
# read the input fc
fields = [id_field, date_field, "SHAPE@"]
polygons = [dict(zip(fields, row))
for row in arcpy.da.SearchCursor(polygon_fc, fields)
]
# get unique ids
unique_ids = {p[id_field]
for p in polygons
}
# iterate over the unique ids
for uid in unique_ids:
# get all states of that polygon, sort by date
states = [p
for p in polygons
if p[id_field] == uid
]
states.sort(key=lambda s: s[date_field])
# start updating the output fc for this id
with arcpy.da.UpdateCursor(out_fc, ["SHAPE@"], where_clause=f"{id_field} = {uid}", sql_clause=[None, f"ORDER BY {date_field}"]) as cursor:
# cursor and states are in the same order (oldest to newest)
for i, row in enumerate(cursor):
# get the geometry of this row
state_geometry = states[i]["SHAPE@"] # == row[0]
# erase/subtract each newer state
for k in range(i+1, len(states)):
newer_state_geometry = states[k]["SHAPE@"]
state_geometry -= newer_state_geometry # we can use "-" to get the difference between two polygons
# update the geometry
cursor.updateRow([state_geometry])
Original:
Current state:
It is a nice code. I did not know I can use minus on geometry.
It is after all doing the erase and append that I suggested
Thanks