Creating polygons from closed polylines with arcpy

1933
5
Jump to solution
05-28-2019 04:57 AM
RafaeldePedro
Occasional Contributor

Does anyone have any advice on how to invoke the "construct polygon" (I believe this lives in the Advance editing toolbar in Arcmap) on a python script?

I am currently trying to write a piece of code that will take in closed polylines which represent tree canopies, and convert them to polygons. I had tried using the tool Feature to Polygon in the Management toolbox, but it does not react well to closed polylines when they overlap each other as tree canopies do in real life. I am trying to get one polygon for each closed polyline, and the "construct polygon" tool seems to do the job, but I don't know how to call it on python. 

If anyone here can suggest a way (with "construct polygon" or otherwise) to achieve this it would be very much appreciated.

Thanks.

0 Kudos
1 Solution

Accepted Solutions
RafaeldePedro
Occasional Contributor

Hi Thomas,

The responses above set me on the right path to my solution. However my approach was in the end different. Here is a sample of the code that I used to "read" the original polyline's geometry, make it an array for each feature (in my case they were tree canopies) and use it to create a polygon feature in the destination feature class.

Sorry for the formatting of my code I simply copied and pasted and amended certain variable names. I hope it helps though

for row in arcpy.da.SearchCursor(infc, ["OID@", "SHAPE@"]):
      vertexArray = arcpy.Array()

      for part in row[1]:
            for pnt in part:
                  vertexArray.add(pnt)

      with arcpy.da.InsertCursor(outfc, ("SHAPE@",)) as cursor:
            feature = arcpy.Polygon(vertexArray, spatialRef)
            cursor.insertRow((feature,))

View solution in original post

5 Replies
JoshuaBixby
MVP Esteemed Contributor

I assume when you state, "they overlap each other," a given polyline does not overlap itself.

There is no direct way to run the toolbar command you want from Python.  If you were so inclined, you could use comtypes and call the underlying ArcObjects, but I think the simpler path would be to use a Search Cursor to retrieve the polyline objects from the feature class and then convert them to polygon objects and insert them into a new feature class.

Once you have the polyline object, converting to a polygon is straightforward using ArcPy.

>>> import arcpy
>>> pl = arcpy.FromWKT('LINESTRING(0 0, 10 0, 10 10, 0 10, 0 0)', arcpy.SpatialReference(3857))
>>> pl
<Polyline object at 0x19159987dd8[0x19159c5a210]>
>>>
>>> pg = arcpy.Polygon(pl.getPart(), pl.spatialReference)
>>> pg
<Polygon object at 0x19162933908[0x19159ef0aa8]>
>>>
LukeWebb
Occasional Contributor III

Joshuas answer seems the best way.  

Another take, is to use the tool you were doing, but only run it on 1 feature at a time, something like:

src_shp = r'a_shapfile'
result_fc = 'a_different_shapefile'


for row in arcpy.SearchCursor(src_shp):
    row_oid = row.getValue('OBJECTID')
    row_where = """ObjectID = %s""" % row_oid
    active_lyr = arcpy.MakeFeatureLayer(src_shp, where_clause=row_where)
    if arcpy.Exists(row_result):
        arcpy.Delete(row_result)
    row_result = Feature to Polygon (active_lyr,  temp_layer)
    append_management(row_result, result_fc)
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I imagine Joshuas approach above will perform much faster though!

RafaeldePedro
Occasional Contributor

Thank you both. Yes when I said 'overlap' I should have said 'cross', but since the polylines represent an actual area I used that word. I will experiment and see how far I get. Thanks again! 

0 Kudos
ThomasBlankinship
New Contributor

Did this work? I'm looking for a way to do the same thing.

0 Kudos
RafaeldePedro
Occasional Contributor

Hi Thomas,

The responses above set me on the right path to my solution. However my approach was in the end different. Here is a sample of the code that I used to "read" the original polyline's geometry, make it an array for each feature (in my case they were tree canopies) and use it to create a polygon feature in the destination feature class.

Sorry for the formatting of my code I simply copied and pasted and amended certain variable names. I hope it helps though

for row in arcpy.da.SearchCursor(infc, ["OID@", "SHAPE@"]):
      vertexArray = arcpy.Array()

      for part in row[1]:
            for pnt in part:
                  vertexArray.add(pnt)

      with arcpy.da.InsertCursor(outfc, ("SHAPE@",)) as cursor:
            feature = arcpy.Polygon(vertexArray, spatialRef)
            cursor.insertRow((feature,))