Linear reference should do the job, but can be bulky. This is why I am using this script:
# Import arcpy module
import arcpy, os, traceback, sys,time
from arcpy import env
env.overwriteOutput = True
infc = arcpy.GetParameterAsText(0)
routeid = arcpy.GetParameterAsText(1)
outfc=arcpy.GetParameterAsText(2)
fields = [f for f in arcpy.ListFields(infc)]
fieldNames = [f.name for f in arcpy.ListFields(infc)]
# define number of lines
result=arcpy.GetCount_management(infc)
nF=int(result.getOutput(0))
d=arcpy.Describe(outfc)
SR_p=d.spatialReference
d=arcpy.Describe(infc)
SR=d.spatialReference
if SR_p.name<>SR.name:
arcpy.AddError("\nDifferent projections. Quit\n")
raise SystemExit('Quit...')
## initial point layer clean-up
fieldsP = [f for f in arcpy.ListFields(outfc)]
fieldNamesP = [f.name for f in arcpy.ListFields(outfc)]
dToLine,dAlong="D_TO_LINE","D_ALONG"
for ent in [routeid,dToLine,dAlong]:
if ent in fieldNamesP:
arcpy.DeleteField_management(outfc, ent)
outFolder, theFile="in_memory","intLines"
env.workspace = outFolder
try:
def showPyMessage():
arcpy.AddMessage(str(time.ctime()) + " - " + message)
def CalcChainage():
pC,lineID,dToLine,Chainage=theRow
shp=dictFeatures[lineID]
theRow[2]=pC.distanceTo(shp)
theRow[3]=shp.measureOnLine(pC)
return
with arcpy.da.SearchCursor(infc, ("SHAPE@",routeid)) as rows:
dictFeatures = {}
for feat,theID in rows:
dictFeatures[theID]=(feat)
del rows
arcpy.SpatialJoin_analysis(outfc, infc, "theJoin", "JOIN_ONE_TO_ONE", "KEEP_ALL", "", "CLOSEST","",dToLine)
arcpy.AddField_management("theJoin", dAlong, "DOUBLE")
## calculate chainage
result=arcpy.GetCount_management("theJoin")
nF=int(result.getOutput(0))
arcpy.AddMessage("\nComputing chainage...")
arcpy.SetProgressor("step", "", 0, nF,1)
with arcpy.da.UpdateCursor("theJoin", ("SHAPE@",routeid,dToLine,dAlong)) as rows:
for theRow in rows:
CalcChainage()
rows.updateRow(theRow)
arcpy.SetProgressorPosition()
del rows
##defining the type of route id field
n=fieldNames.index(routeid)
fType=fields[n].type
fLength=fields[n].length
try:
if fType=="String":
arcpy.AddField_management(outfc, routeid, "TEXT","","",fLength)
if fType=="Integer":
arcpy.AddField_management(outfc, routeid, "LONG")
if fType=="SmallInteger":
arcpy.AddField_management(outfc, routeid, "SHORT")
except: pass
try:
arcpy.AddField_management(outfc, dToLine, "DOUBLE")
arcpy.AddField_management(outfc, dAlong, "DOUBLE")
except: pass
arcpy.AddMessage("Transferring calcs to points...\n")
vFT=arcpy.da.TableToNumPyArray("theJoin",(routeid,dToLine,dAlong))
arcpy.SetProgressor("step", "", 0, nF,1)
with arcpy.da.UpdateCursor(outfc,(routeid,dToLine,dAlong )) as rows:
n=0
for theRow in rows:
theRow=vFT[n]
rows.updateRow(theRow)
arcpy.SetProgressorPosition()
n+=1
del vFT, rows
except NameError, theMessage:
arcpy.AddMessage (theMessage)
except:
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
message = "Python Error Info: " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()
Script expects these parameters:
To get this:
Perhaps you'd like to merge (dissolve) your polylines into single line. Make sure it won't create multipart shape, i.e. ends of segments must be snapped.
Script tested on shapefiles.
Best Answer
To split multiple lines at a set distance using ArcGIS desktop (or ArcPro), the following two steps work:
Generate Points Along Lines tool. It's in the Data management toolbox under "sampling". You can set a specific distance between points along the lines.
Split Line at Point tool. It's in the Data Management toolbox under "Features". Use the points from the previous step to split your lines.
There is an easier and quicker way to do this in QGIS too.