Method to split line segments in a road network that are greater than X length into n smaller line segments using ArcGIS?
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?
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
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:Userse1b8DesktopE1B8WorkspaceWorkspace5.gdb estLines_split" #Full path to output line feature class outFc = r"C:Userse1b8DesktopE1B8WorkspaceWorkspace5.gdb estLines_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 = ["[email protected]"] #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 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  #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, "[email protected]") 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, "[email protected]") 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, "[email protected]") 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) else: rows += [row] #del cursor variable del cursor print 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 print "created:", outFc print 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:Userse1b8DesktopE1B8WorkspaceWorkspace5.gdb estLines_split2 done
In feature class:
Out feature class:
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: