Select to view content in your preferred language

Convert shapefile polygons to polylines in Model Builder

196
3
3 weeks ago
Labels (1)
norcal916
New Contributor

I was wondering if there is a way to automate the following process in Model Builder: How To: Convert Shapefile Polygons to Polylines (esri.com)

I'm stuck on steps 9-14 in the ArcGIS Pro section of the linked page. 

I don't have an advanced license for ArcGIS Pro so I don't have access to the Feature to Polyline tool. 

 

0 Kudos
3 Replies
Matthew_Muehlhauser
New Contributor III

There's a pretty straightforward way that you could do this with Python, and you could convert it into a script tool as well to use going forward. Although, in my version I work mostly in a GDB.

 

 

import arcpy

# Gathering layer and field info
project = arcpy.mp.ArcGISProject("CURRENT")
mv = project.activeMap
lyr = mv.listLayers("POLY_LAYER_NAME")
desc = arcpy.Describe(lyr)
shape_name = desc.shapeFieldName
oid_name = desc.OIDFieldName
flds = [fld.name.replace(shape_name, "SHAPE@").replace(oid_name, "OID@") for fld in arcpy.ListFields(lyr) if "Shape_" not in fld.name]
shape_index = flds.index("SHAPE@")

#Create Empty Line Feature Class
workspace = lyr.connectionProperties["connection_info"]["database"]
result = arcpy.management.CreateFeatureclass(workspace, f"{lyr.name}_line", 'POLYLINE', lyr)
line_path = result.getOutput(0)

# Get the polygon features and convert to lines
features = [list(row) for row in arcpy.da.SearchCursor(lyr, flds)]
for ftr in features:
    geom = ftr[shape_index]
    ftr[shape_index] = arcpy.AsShape(geom.JSON.replace("rings", "paths").replace("Rings", "Paths"), True)

# Insert new line features into new Line Feature Class
with arcpy.da.InsertCursor(line_path, flds) as cursor:
    for ftr in features:
        cursor.insertRow(ftr)

 

 The reason I used the json for the geometry is because this version accounts for multipart features and curves just by changing the "rings" to "paths" and the "curveRings" to "curvePaths".

One other thing is that I did a bit of substitution to change the Shape field to "SHAPE@" and the OBJECTID to "OID@". "Shape@" and "OID@" are keywords for the different cursors and it's easier to work with those so you don't have to worry about the actual name, which can be apparent in the beginning where we get the names from the Describe object.

0 Kudos
norcal916
New Contributor

Thank you. I tried using the code you provided but I received the following error:

Traceback (most recent call last):
File "<string>", line 27, in <module>
TypeError: cannot alter multipart geometry type

0 Kudos
Matthew_Muehlhauser
New Contributor III

Did you end up making any changes to the script? It's hard to tell for sure without seeing your data, but based on the error, my guess is it has something to do with the fields not matching up exactly. I didn't do too much testing myself, so you might just need to try running the below lines and see what it gives you:

 

flds = [fld.name.replace(shape_name, "SHAPE@").replace(oid_name, "OID@") for fld in arcpy.ListFields(lyr) if "Shape_" not in fld.name]

 

And  then try comparing it to the result of:

 

[fld.name for fld in arcpy.ListFIelds("Line_Layer_Name")]

 

Keep in mind though that this second line doesn't replace the ID or shape fields with the "@" version, so there will be those two differences for sure.

If they are different, then you might need to find a way to account for that.

0 Kudos