Polygon To Line (Data Management) on a Basic License with ArcPy

The Polygon to Line (Data Management) tool is only available in ArcGIS Pro with an Advanced license. You can check out the Esri documentation for this tool here. For now, we will omit the optional identifying neighbouring information and will revisit in the future. A little about this tool; for each input polygon, the boundary will be written out as an enclosed linear feature. A multipart polygon will become a multipart linear feature in the output feature class. The attributes of the input polygon features will be maintained and transferred to the output feature class with a new field add called ORIG_FID. The ORIG_FID will represent the original OID of the input polygon features.

Interested in learning ArcPy, check out our course page.

Here’s the syntax for the Polygon to Line (Data Management) tool.

arcpy.management.PolygonToLine(in_features, out_feature_class, {neighbor_option})

The ArcPy module is the only necessary one to recreate the tool.

import arcpy

Following the Esri documentation, there are two required parameters; in_features (type: Feature Layer) and out_feature_class (type: Feature Class), (and optionally neighbour_option which we are leaving out for now).

## polygon featurer class to convert boundaries to lines
in_features = arcpy.GetParameterAsText(0)

## output feature class filepath
out_feature_class = arcpy.GetParameterAsText(1)

Next, we will set in place the objects required for our tool. Each requirement is commented for more information.

## srs id of the in_features, this will be the srs for the out_feature_class
srs_id = arcpy.Describe(in_features).spatialReference.factoryCode

## this list will hold the names of the input fields in order
in_fld_names = [fld.name for fld in arcpy.ListFields(in_features) if fld.type != "OID"]

## we need the OID field to be able to create the ORIG_FID field in the output
oid_fld = [fld.name for fld in arcpy.ListFields(in_features) if fld.type=="OID"][0]
in_fld_names.insert(0, oid_fld)

## add field for accessing geometry
in_fld_names.append("SHAPE@")

## create a copy of the in_fld_name for the out_feature_class
out_fld_names = list(in_fld_names)
out_fld_names[0] = "ORIG_FID"

We will make use of the memory workspace and create a linear feature class using the input polygon feature class schema as a template and adding the ORIG_FID field.

## create a temporary linear feature class in the memory workspace.
temp_fc = arcpy.management.CreateFeatureclass("memory", "temp_vertices", "POLYLINE",
    in_features, "SAME_AS_TEMPLATE", "SAME_AS_TEMPLATE", srs_id)

## add field for ORIG_FID
arcpy.management.AddField(temp_fc, "ORIG_FID", field_type="LONG", field_is_nullable="NULLABLE")

Now we need to iterate through each polygon feature and convert the boundaries to polylines. If the input is a multipart polygon, the output is a multipart polyline. The attributes are maintained from the input to the output and we cater for the ORIG_FID.

arcpy.SetProgressorLabel("Converting polygon boundaries to lines.")

## use a search cursor to iterate through the polygons
with arcpy.da.SearchCursor(in_features, in_fld_names) as s_cursor:
    ## use an insert cursor to insect the linear features into the temp_fc
    with arcpy.da.InsertCursor(temp_fc, out_fld_names) as i_cursor:
        ## for each record in the polygon feature class
        for row in s_cursor:
            ## get all attributes, less the geometry as a list
            row_attributes = list(row[0:-1])

            ## create a list to hold all polylines that make up the
            ## polygon boundary
            polyline_list = []

            ## for each port in the polygon geometry
            for index, part in enumerate(row[-1]):
                ## at the part to the polyline_lst
                polyline_list.append(row[-1].getPart(index))

            ## create an arcpy Array from the polyline_lst
            pl_array = arcpy.Array(polyline_list)
            ## append the Polyline to the attributes
            row_attributes.append(arcpy.Polyline(pl_array))

            ## insert the record, attributes and linear geometry to the temp_fc
            i_cursor.insertRow(row_attributes)

arcpy.SetProgressorLabel("Finished converting polygon boundaries")

Write the temporary feature class in the memory workspace to disk…

arcpy.SetProgressorLabel("Writing output feature class")

## write the temp_fc to disk
arcpy.conversion.ExportFeatures(temp_fc, out_feature_class)

… and the clean-up the memory workspace by deleting the temporary feature class.

## clean us the memory workspace
arcpy.Delete_management(temp_fc)

Save your script and open up ArcGIS Pro. Right-click on your toolbox/toolset of choice and select New > Script. The New Script window will appear. In the General tab set Name to polygonToLineLabel to Polygon to Line (Basic), and the Description to Polygon to Line with a Basic License.

In the Parameters tab set as per below. Set the Filter for Input Features to Feature Type: Polygon, and Output Feature Class parameter Direction to Output and with a Filter of Feature Type: Polyline.

In the Execution tab, click the folder icon in the top-right corner and add your saved Python script, click OK and go test out the tool.

You can download the tool and other Advanced tools with a Basic license over on this page.

Here’s all the code…

import arcpy

################################################################################
## Esri Documentation:
##  https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/polygon-to-line.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/getparameterastext.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/describe.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/listfields.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/setprogressorlabel.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/data-access/searchcursor-class.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/classes/array.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/classes/polyline.htm
##  https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/create-feature-class.htm
##  https://pro.arcgis.com/en/pro-app/latest/help/analysis/geoprocessing/basics/the-in-memory-workspace.htm
##  https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/add-field.htm
##  https://pro.arcgis.com/en/pro-app/latest/arcpy/data-access/insertcursor-class.htm
##  https://pro.arcgis.com/en/pro-app/latest/tool-reference/conversion/export-features.htm
##  https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/delete.htm
##
## Syntax:
##     arcpy.management.PolygonToLine(in_features, out_feature_class, {neighbor_option})
##
## ArcGIS Pro Version: 3.1.0
##
################################################################################

################################################################################
## USER INPUTS #################################################################

## polygon featurer class to convert boundaries to lines
in_features = arcpy.GetParameterAsText(0)

## output feature class filepath
out_feature_class = arcpy.GetParameterAsText(1)

################################################################################
## TOOL OBJECT REQUIREMENTS ####################################################

## srs id of the in_features, this will be the srs for the out_feature_class
srs_id = arcpy.Describe(in_features).spatialReference.factoryCode

## this list will hold the names of the input fields in order
in_fld_names = [fld.name for fld in arcpy.ListFields(in_features) if fld.type != "OID"]

## we need the OID field to be able to create the ORIG_FID field in the output
oid_fld = [fld.name for fld in arcpy.ListFields(in_features) if fld.type=="OID"][0]
in_fld_names.insert(0, oid_fld)

## add field for accessing geometry
in_fld_names.append("SHAPE@")

## create a copy of the in_fld_name for the out_feature_class
out_fld_names = list(in_fld_names)
out_fld_names[0] = "ORIG_FID"

################################################################################
## CREATE OUPUT FEATURE CLASS ##################################################

## create a temporary linear feature class in the memory workspace.
temp_fc = arcpy.management.CreateFeatureclass("memory", "temp_vertices", "POLYLINE",
    in_features, "SAME_AS_TEMPLATE", "SAME_AS_TEMPLATE", srs_id)

## add field for ORIG_FID
arcpy.management.AddField(temp_fc, "ORIG_FID", field_type="LONG", field_is_nullable="NULLABLE")

################################################################################
## PROCESS POLYGONS TO LINES ###################################################

arcpy.SetProgressorLabel("Converting polygon boundaries to lines.")

## use a search cursor to iterate through the polygons
with arcpy.da.SearchCursor(in_features, in_fld_names) as s_cursor:
    ## use an insert cursor to insect the linear features into the temp_fc
    with arcpy.da.InsertCursor(temp_fc, out_fld_names) as i_cursor:
        ## for each record in the polygon feature class
        for row in s_cursor:
            ## get all attributes, less the geometry as a list
            row_attributes = list(row[0:-1])

            ## create a list to hold all polylines that make up the
            ## polygon boundary
            polyline_list = []

            ## for each port in the polygon geometry
            for index, part in enumerate(row[-1]):
                ## at the part to the polyline_lst
                polyline_list.append(row[-1].getPart(index))

            ## create an arcpy Array from the polyline_lst
            pl_array = arcpy.Array(polyline_list)
            ## append the Polyline to the attributes
            row_attributes.append(arcpy.Polyline(pl_array))

            ## insert the record, attributes and linear geometry to the temp_fc
            i_cursor.insertRow(row_attributes)

arcpy.SetProgressorLabel("Finished converting polygon boundaries")

################################################################################
## WRITE TO DISK ###############################################################

arcpy.SetProgressorLabel("Writing output feature class")

## write the temp_fc to disk
arcpy.conversion.ExportFeatures(temp_fc, out_feature_class)

################################################################################
## CLEAN UP ####################################################################

## clean us the memory workspace
arcpy.Delete_management(temp_fc)

################################################################################

Leave a Comment

Your email address will not be published. Required fields are marked *