3

I'm using ArcGIS 10.3 (Desktop), and I'm trying to measure the distance between points following a path determined by a set of polylines. Hand measurement is not a viable option-- there are ~7500 points, and my polyline set is the global coastline. The ultimate goal is to get the spacing of these points along the polylines, so that I can analyze this with respect to a few other variables.

I can read python-- with a bit of effort-- but not write or edit it, so code-based solutions will not be particularly useful to me.

I have tried using the linear referencing tools-- I snapped the points to the lines, then transformed the polylines to routes and used 'locate features'-- but because my points are not (entirely) ordered along the path, using the difference between linear reference locations of subsequent points yields some fairly unlikely answers. In addition, spot checks of (hand-measured, using the built-in path length measuring tool) point-to-point along-polyline distance yield different answers than given by the corresponding linear references for the point pair. (Some of the answers were close enough that they could very well be measurement error on my part, but others were nearly 20%, despite my having zoomed in and snapped the measurement cursor to the polyline, proceeding vertex-to-vertex.)

Sorting first by linear distance seems to fix the first problem, but in light of the second one, I remain skeptical of this process.

I then tried simply splitting the polylines into segments ('split line at point') using the (snapped) points as the dividers, with the eventual goal of finding the segment length with the calculate geometry feature. This produced gibberish. I'm not sure what criteria ArcGIS used to split the lines, but it wasn't the point set I provided. Segments in the resulting shapefile ran right through tens of points, only to terminate at a place with no point. (Also, there were segments utterly empty of points...you get the gist.) I reiterate that the pointset was specifically snapped to the polylines, so this problem shouldn't be caused by excessive distance between the point and the polyline.

I'm at a bit of a loss, here: could someone point out where I might have gone astray and/or suggest a solution? Or, failing that, a new method that I could try? It seems like a fairly basic (not necessarily simple, but fundamental) analysis to do with geographic data, and I don't understand why it has presented so many difficulties.

0

2 Answers 2

7

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:

enter image description here

enter image description here

To get this:

enter image description here

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.

2

One possiblility would be to spend some time creating m aware geometry for your line feature. Search linear referencing. It is a fair amount of work.... I typically go with this option when the distance along the line question will be repeated regularly. The determination often also depends on network complexity and the format and content of the enquiry I receive. Some data and questions quite obviously fall into the linear referencing category once you are somewhat familiar with the concepts. My guess is that either the routing of the line event, or the interpretation of the output distance along line table is tripping you up.

Say for instance that point A is 5 kilometres along Smith Road from its beginning at the highway and point B is 5 kilometres up Smith Road to the intersection with 3rd Street where you turn left, follow 3rd for 10 kilometres and turn left again onto Bob Road and continue 3 kilometers to point B. Is the question is presented to you "How far from point a to B?"...or more like driving instructions from Google with each road named? Also with the table that would be output from this example you would have a bunch of start and end distances not lengths. Pretty simple math... But now line direction comes into play... Anyways.. It works good... But it takes some work to get set up properly

Your Answer

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

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