2

I am trying to find a way to calculate the horizontal distance from a point to a polyline. I am not looking the shortest distance. I have a point layer with over 10,000 points and line layer. I am looking the horizontal distance. In another word. I am looking to calculate the distance from a point to polyline at the latitude of point in polyline.

You can see in the picture. I have a green line. I have also green points. I want to get those horizontal distances showed on red. I have some point on the left side of the line and some points on the right side of the line. I want to get horizontal distance (red line) to the line.

I tried to use near tool but it gives shortest distance. I tried use generate near table with angle and tried to find the distance with appropriate angle but, my polyline has a lot of curves so I am not getting the one in same latitude. I am using ArcGIS 10.3.1

0

3 Answers 3

6

I suspect this can be streamlined, but here's how you can get to it using Python:

pt_fc = 'points' # points feature class
sr = arcpy.Describe(pt_fc).spatialReference # points spatial reference
dist_field = 'dist' # existing distance field, type double
line_fc = 'dist_lines' # lines feature class
search_dist = 10 # maximum search distance, in linear units of spatial reference
with arcpy.da.UpdateCursor(pt_fc,['SHAPE@',dist_field],spatial_reference=sr) as cursor: # loop through points
    for row in cursor:
        cur_pt = row[0].centroid # switch from point geometry to point object
        new_line = arcpy.Polyline(arcpy.Array([arcpy.Point(cur_pt.X-search_dist,cur_pt.Y),arcpy.Point(cur_pt.X+search_dist,cur_pt.Y)]),sr) # make horizontal line
        temp_lyr = arcpy.CopyFeatures_management(new_line,r'in_memory\line') # switch from geometry to feature layer
        int_pts = arcpy.Intersect_analysis([temp_lyr,line_fc],r'in_memory\int_pts',output_type='POINT') # intersect horizontal line with line feature class, return points
        min_dist = float('inf') # initialize minimum distance
        for int_pt in [row2[0] for row2 in arcpy.da.SearchCursor(int_pts,'SHAPE@',spatial_reference=sr)]: # loop through intersection points
            dist = row[0].distanceTo(int_pt) #calculate distance between points
            if dist < min_dist:
                min_dist = dist # set as minimum distance if appropriate 
        row[1] = min_dist # store distance in row
        cursor.updateRow(row) # update row
        arcpy.Delete_management("in_memory")

Basically, for each point, draw a horizontal line from the point, intersect it with the lines, and get the distance to the nearest intersection point.

Notes: if there are no intersections, this appears to return a value of exactly 1, but you can program around that if it's a problem. Also, you mention latitude which is generally measured in degrees. I took your use of latitude simply to mean 'Y-value'. This may not work properly (i.e. it may return distances in degrees) if you are using unprojected data. Project first.

2
  • Thank you so much. Code worked with couple editing. I changed max search distance to 10. It gave infinity when it was 1000. I added also delete memory line. Then it works. However it gave me distance in degree at then end. Are there anyway I can change it to km or miles after calculation distance in degrees?
    – Bilalce
    Commented Mar 15, 2017 at 15:46
  • No, I don't think there is an easy way to convert the distances after the fact. You should (must) project your data, then use the linear unit of the projection.
    – phloem
    Commented Mar 15, 2017 at 16:14
0

Raster solution using flow direction grid with 2 values of 1 and 16. Use it and points as inputs into cost path tool. Convert "streams" to features:

enter image description here

7
  • Does this work on more complex datasets, where you don't know beforehand which line is closest? How do you create the 1-16 raster?
    – phloem
    Commented Mar 16, 2017 at 16:14
  • Can be repeated for any number of lines and minimum distance taken. Part on the left of line has 1, on the right 16. It will get tricky if line extent doesn't contain points extent
    – FelixIP
    Commented Mar 16, 2017 at 18:57
  • I just don't see how you created the 1-16 raster. How did the left part know it should be 1, and right part know it should be 16?
    – phloem
    Commented Mar 16, 2017 at 19:51
  • Create envelop from line and split it by line. querypointandDistance on any point inside polygons (can be more than 2) will answer this (BTW one of the options to improve you code). FYI I upvoted your solution, because I was going through essentially the same answer as yours but got distracted. So I posted another one. This is a case when I like diversity
    – FelixIP
    Commented Mar 16, 2017 at 20:19
  • Sorry, really not trying to be combative, just trying to understand. Suppose there was another line running down the righthand side of your picture. I don't see how this method would either force the lines near the righthand side to run to the right, or alter the raster so that those points are on a raster attributed as 1.
    – phloem
    Commented Mar 16, 2017 at 23:48
0

Here's a really good plugin that exists for ArcGIS Desktop. Drawing perpendicular line segments between points to polylines:

https://www.arcgis.com/home/item.html?id=0a4892bd754146e48b87de2352cdf64d

It also includes ArcObjects and C# source code which could be used for further customization. Have used it for a cadastral project some time ago. Once the line segments are drawn, the length of the segments could be calculated using Add Geometry Attributes.

1
  • It is a good tool to have. But it is not doing what I want. It is drawing perpendicular lines to polyline. I am not looking for that. For my case, angle with the polyline can be anything as long as it is horizontal from point to polyline. However it is a good tool to have. Thanks
    – Bilalce
    Commented Mar 17, 2017 at 14:55

Your Answer

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

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