I'm using ArcGIS Desktop 10.2 and I'd like to take roads in a network greater than a certain length and split them into equal smaller pieces. I've noticed that splitting by percent can be achieved via the Editor Menu; however, it appears this must be done on a line-by-line basis.

Could you suggest ways of automating the process to split all roads over a certain length into smaller parts based on the percent of the original?

  • 1
    How many smaller pieces do you want to split the overshooting lines? A fixed number such as in half, in thirds? Or in a variable number of smaller pieces, such as in half/4ths/8ths... recursively until it meets your minimum distance?
    – John
    Commented Aug 25, 2015 at 16:01
  • Recursively until each piece is <= to a maximum distance. Commented Aug 25, 2015 at 16:03
  • I know there are several threads on splitting lines by a certain distance or by points. Can you try looking through this link, this thread, this thread or similar with "splitting" as a keyword. Specifically try using the "Densify" tool, then "Split Line at Points".
    – John
    Commented Aug 25, 2015 at 16:24

2 Answers 2


A little Python automation gets this job done. The basic steps:

  • Determine max distance in feature class's units with help from a spatial reference object (requires projected feature class I do believe)
  • Create a new, empty feature class with the input line feature class as its template
  • Iterate input feature class and check its line lengths
  • If the length is too long, continually split the line with the use of a while loop, position along line, and split line at point.
  • Once lines are shorter than the max length, add row object to a list
  • Insert all row objects into new feature class with an insert cursor


inFc: input line feature class

outFc: output feature class

dist: max distance in meters


#Full path to input line feature class
inFc = r"C:\Users\e1b8\Desktop\E1B8\Workspace\Workspace5.gdb\testLines_split"
#Full path to output line feature class
outFc = r"C:\Users\e1b8\Desktop\E1B8\Workspace\Workspace5.gdb\testLines_split2"

#Distance (meters)
dist = 15


import arcpy
import os

#overwrite outputs (optional)
arcpy.env.overwriteOutput = True

print "determining spatial reference info"
#Get spatial reference object
sr = arcpy.Describe (inFc).spatialReference
#meters conversion
metersPerUnit = sr.metersPerUnit
#Distance in feature class units
checkDistance = dist / metersPerUnit
print "max distance:", checkDistance

print "creating output feature class"
#Create out feature class
outPath = os.path.dirname (outFc)
outName = os.path.basename (outFc)
arcpy.CreateFeatureclass_management (outPath, outName, "POLYLINE", inFc, spatial_reference = sr)

#set workspace
arcpy.env.workspace = outPath

#list with geometry field
fields = ["SHAPE@"]

#Add feature class fields to list
fields += [f.name for f in arcpy.ListFields (inFc)]

#Get objectid field name
oidFld = arcpy.Describe (inFc).OIDFieldName

#Remove oid field from fields list
fields.remove (oidFld)

#empty list to have rows appended to
rows = []

print "iterating", arcpy.GetCount_management (inFc).getOutput (0), "rows"
i = 0
#cursor to iterate feature class
with arcpy.da.SearchCursor (inFc, fields) as cursor:
    #iterate rows
    for row in cursor:
        i += 1
        #get geometry object
        geometry = row [0]

        #get length
        length = geometry.length

        #check if length longer than limit
        if length > checkDistance:
            print "row", i
            print "line length:", length

            #empty list for intermediate date to be deleted
            garbage = []

            #create empty line fc for single feature
            split = arcpy.CreateUniqueName ("split")
            outPath = os.path.dirname (split)
            outName = os.path.basename (split)
            arcpy.CreateFeatureclass_management (outPath, outName, "POLYLINE", inFc, spatial_reference = sr)

            #insert feature in new fc
            with arcpy.da.InsertCursor (split, fields) as cur:
                cur.insertRow (row)
            del cur
            #add new fc to garbage
            garbage += [split]

            #create empty point fc for single feature
            midPnt = arcpy.CreateUniqueName ("point")
            outPath = os.path.dirname (midPnt)
            outName = os.path.basename (midPnt)
            arcpy.CreateFeatureclass_management (outPath, outName, "POINT", spatial_reference = sr)
            #Get midpoint
            pnt = geometry.positionAlongLine (.5, True)
            #insert point into new feature class
            with arcpy.da.InsertCursor (midPnt, "SHAPE@") as cur:
                cur.insertRow ((pnt,))
            del cur
            #add new fc to garbage
            garbage += [midPnt]

            #loop while length is greater than limit
            while length > checkDistance:

                #Split line at (mid)point
                newSplit = arcpy.CreateUniqueName("split")
                garbage += [newSplit]
                arcpy.SplitLineAtPoint_management (split, midPnt, newSplit)

                #Create new mid points
                midPnt = arcpy.CreateUniqueName ("point")
                garbage += [midPnt]
                outPath = os.path.dirname (midPnt)
                outName = os.path.basename (midPnt)
                arcpy.CreateFeatureclass_management (outPath, outName, "POINT", spatial_reference = sr)

                #empty list for new points
                pnts = []

                #iterate split line and get midpoints
                with arcpy.da.SearchCursor (newSplit, "SHAPE@") as cur:
                    for geom, in cur:
                        pnt = geom.positionAlongLine (.5, True)
                        pnts += [pnt]
                del cur

                #add midpoints to midpoint feature class
                with arcpy.da.InsertCursor (midPnt, "SHAPE@") as cur:
                    for pnt in pnts:
                        cur.insertRow ((pnt,))
                del cur

                #divide length variable by two
                length = length / 2
                print "line length:", length

                split = newSplit

            rows += [row for row in arcpy.da.SearchCursor (split, fields)]

            #clean up intermediate data
            for trash in garbage:
                arcpy.Delete_management (trash)

            rows += [row]

#del cursor variable
del cursor

print "inserting rows into new feature class"
#insert cursor new feature class with rows
with arcpy.da.InsertCursor (outFc, fields) as cursor:
    for row in rows:
        cursor.insertRow (row)

del cursor

print "created:", outFc
print "done"

Output looks something like this:

determining spatial reference info
max distance: 65.6166666667
creating output feature class

iterating 11 rows
row 4
line length: 90.6641581736
line length: 45.3320790868
row 6
line length: 81.7030489448
line length: 40.8515244724
row 7
line length: 82.7060163161
line length: 41.3530081581
row 9
line length: 97.005780961
line length: 48.5028904805
row 10
line length: 90.6565601113
line length: 45.3282800557

inserting rows into new feature class

created: C:\Users\e1b8\Desktop\E1B8\Workspace\Workspace5.gdb\testLines_split2


In feature class:


Out feature class:


  • I used this as a guide, what I've got now checks the network several times to see if there are any segments over 500m. I'll need to figure out how to implement an iterator to make the model more efficient though. Commented Sep 9, 2015 at 13:25

It is not exactly equivalent to the process you describe, but ArcGIS has the Dice tool to automatically split long lines into parts of X vertices. It doesn't use a percentage limit though, but merely a vertex limit. Still, if your only intention is to split the lines up in about equal sizes, it may be useful:


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.