0

I have lines (edges) that have a starting lat/lon and an ending lat/lon. I also have a dataframe of many other points and I want to see whether they are on the line or not. For example, the beginning coordinate for my line is lon=-124.1637 and lat=40.80207 and the end is (-122.4199,37.77903). I want to verify if the point (-123.4167,39.50740) falls on the line created by the first two coordinate points. I am really not sure how to go about this. This is according to a projected coordinate system and they the points need to fall exactly on the line.

Ali Mroueh
  • 33
  • 4
  • Do you need it to fall exactly on the line? within some tolerance? and according to which model of the earth (projection/datum)? – Brian Apr 13 '20 at 17:07
  • Yes it needs to be exactly on the line, and it is according to a projected coordinate system. They should fall exactly on there because all the points are on a line segment, I just need to go through specific line segments to see which points are on it. – Ali Mroueh Apr 13 '20 at 17:51
  • 1
    It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. But trying to anything "exatly" with floating point numbers isn't going to turn out very well. You need to allow for some precision error. – MrFlick Apr 13 '20 at 18:24

2 Answers2

2

Maybe you can use approx (linear interpolation) to check if the point is on the line, e.g.,

> approx(df$lon,df$lat,-123.4167)$y==39.50740
[1] FALSE

DATA

df <- structure(list(lon = c(-124.1637, -122.4199), lat = c(40.80207, 
37.77903)), class = "data.frame", row.names = c(NA, -2L))

> df
        lon      lat
1 -124.1637 40.80207
2 -122.4199 37.77903
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
1
library(sf)
#> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
test_line <- st_linestring(
  matrix(
    c(-124.1637, 40.80207, -122.4199, 37.77903), 
    nrow = 2, byrow = T
    )
  ) %>% 
  st_sfc() %>% 
  st_set_crs(4326)

test_pt <- st_point(c(-123.4167, 39.50740)) %>% 
  st_sfc() %>% 
  st_set_crs(4326)

st_intersects(test_pt, test_line)
#> although coordinates are longitude/latitude, st_intersects assumes that they are planar
#> Sparse geometry binary predicate list of length 1, where the predicate was `intersects'
#>  1: (empty)

st_distance(test_pt, test_line)
#> Units: [m]
#>          [,1]
#> [1,] 1583.654

Created on 2020-04-13 by the reprex package (v0.3.0)

Arranging your points and lines into {sf}-geometry dataframes is a prerequisite for using the st_relate functions, but once you have them, it's straightforward to test if they intersect exactly, which they don't (empty set). Also, they will probably not ever, with a point on a line, unless it's one of the exact endpoints.

A smarter way is to test how far the point is from the line, here 1,584 meters, and filter out those that are above some threshhold (100 m? 10 m? 1 m? 0.1 m? Depends on your application).

To illustrate this point, here's a map of your test point and line, with the counties surrounding them. Visually, the point is certainly on the line, but mathematically, it is not.

enter image description here

Brian
  • 7,900
  • 1
  • 27
  • 41