I know this is an old post, but I look at this and the first thing that comes to mind is sinuosity.
Sinuosity is defined by the length along a polyline divided by the shortest distance from start point to end point. This seems like a reasonable metric for determining the difference between the two lines.
There are several posts on this site which relate to sinuosity.
You can also read more about it on Wikipedia.
There is also a python toolbox for ArcGIS.
A straight feature will have an sinuosity index of 1. The more
indirect the feature, the closer to 0 the sinuosity index.
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
Just in case, you can use Snapping for snapping to the vertices/edges when using the Measure tool. This would not be very helpful though if you have long features with high density of vertices. You would still need to click through the feature, but at least your clicks will be snapped to the vertices or edges (which will increase the accuracy of measurements to some extent).
In case you need to perform multiple measurements, consider using Linear Referencing, see a good post here.
There is an idea on ArcGIS Ideas for introducing this functionality.
You could also write a simple Python add-in that would take two input points and perform the process you are doing manually now and open the message box with the calculated length.