I try to divide a polygon into two straight polygons using a fixed point on one side.
The fixed point is where the dividing line will start and end at the opposite side of the polygon. The only condition is that the two new polygons should be the same in area.
In Pro (so I hope in arcmap), you can subdivide by area, but there is no mention of specifying a starting point
Subdivide Polygon (Data Management)—ArcGIS Pro | Documentation
I'm not clear on the requirement, but did you try the Divide tool found on the modify features pane?
https://pro.arcgis.com/en/pro-app/latest/help/editing/divide-a-polygon-by-a-value.htm
If you already know where the start and endpoints of the splitting line need to be, why won't Split work (also found on the modify features pane)?
https://pro.arcgis.com/en/pro-app/latest/help/editing/split-a-feature.htm
-Scott
So one point of the cutting line is defined and it should cut the polygon into equal areas. I doubt there's a tool for that (though I could be wrong).
This seems like a job for Python, so I took a stab at it. I can get it to work with very small relative differences between the polygon parts, but the computation time is still quite high...
import datetime
def cut_equally(polygon, point, max_increment=1, rel_err=0.01):
"""Cuts a polygon into equal parts, with one point of the cutting line predefined.
Returns a list of arcpy.PolygonGeometry, or an empty list if the target error
is too small or the maximum increment too big.
How it works:
1.) Create a buffer around the point, create a 1-dimensional intersection
of that buffer with the polygon.
1.a) If there is no such intersection, the buffer is too big, return an empty list.
2.) For each of the intersection of polygon and buffer, create a line between
that intersection and the point and cut the polygon.
3.) Calculate the relative error with
rel_err = abs(1 - area_1/area_2)
3.a) If rel_err is smaller than the target error, return the cut polygons.
4.) Increase the buffer distance. Small target errors need a very small
increment, which affects computing time massively. To alleviate that, the
increment is dynamic: it is the maximum of the current relative error and
a specified value.
5.) Repeat.
polygon: arcpy.PolygonGeometry, the polygon to be cut
point: arcpy.Point or arcpy.PointGeometry, the start point of the cutting line, must be on the polygon's edge
max_increment: the maximum increment to the buffer distance (see step 4)
rel_err: the target relative error (see step 3)
"""
# change point to point geometry
if not isinstance(point, arcpy.PointGeometry):
point = arcpy.PointGeometry(point)
# set start values for dist and curr_rel_err
dist = max_increment
curr_rel_err = max_increment
# loop
start_time = datetime.datetime.now()
while True:
# create a buffer and intersect with the polygon
point_buffer = point.buffer(dist)
intersect_points = polygon.intersect(point_buffer, 1)
# no intersection means the buffer is too big, return an empty list
if len(intersect_points) == 0:
print("Could not cut the polygon with the specified parameters.")
return []
for ip in intersect_points:
# create the cutting line
cut_line = arcpy.Polyline(arcpy.Array([point.firstPoint, ip]))
try:
# cut
poly_cuts = polygon.cut(cut_line)
# get the relative error
curr_rel_err = abs(1 - poly_cuts[0].area/poly_cuts[1].area)
# return if target error is met
if curr_rel_err <= rel_err:
print("area_1: {}, area_2: {}, rel_err: {}, time: {} seconds".format(int(poly_cuts[0].area), int(poly_cuts[1].area), curr_rel_err, (datetime.datetime.now() - start_time).seconds))
return poly_cuts
# these errors occur when the buffer is too small, ignore them
except (RuntimeError, ZeroDivisionError):
pass
# increase the buffer distance
dist += min(curr_rel_err, max_increment)
@DanPatterson & @Scott_Harris Yes, exactly, that’s the problem. Divide is excellent tool but I cannot add a point. I know is something very special that I ask.
And I think the Python is the answer.
@JohannesLindner I will give a try and I will come again back if works or not.
Thank you so much for your response guys