2

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 Aug 25 '15 at 16:01
  • Recursively until each piece is <= to a maximum distance. – stanleykubrick Aug 25 '15 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 Aug 25 '15 at 16:24
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

Inputs:

inFc: input line feature class

outFc: output feature class

dist: max distance in meters

Code:

#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
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)

        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:\Users\e1b8\Desktop\E1B8\Workspace\Workspace5.gdb\testLines_split2

done

In feature class:

inFc

Out feature class:

outFc

  • 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. – stanleykubrick Sep 9 '15 at 13:25
0

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:

http://resources.arcgis.com/EN/HELP/MAIN/10.2/index.html#//001700000037000000

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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