I'm using the sf package in R to simulate a sample of agents moving between different nodes in a network across space-time.
I'm currently puzzled though by some behavior from st_intersects
: I have the agents moving between nodes between each corner of the coordinate unit square as well as through the center at (.5,.5)
. However when I try to detect an agent at st_point(c(.1,.9))
intersecting with the geometry st_linestring(c(st_point(c(0,0)),st_point(c(0.5,0.5))))
I get an empty predicate return.
In contrast if I detect an agent moving along the x-axis or y-axis only, I am able to detect the point correctly. Why is this?
Minimum reproducible example in R v4.0.2:
library(sf)
l1 <- st_linestring(c(st_point(c(0,1)),st_point(c(0.5,0.5))))
p1 <- st_point(c(.1,.9)) ## on the line between (0,1) and (.5,.5); y=1-x x = f(t)
st_intersects(p1,l1) ## empty
#Sparse geometry binary predicate list of length 1, where the predicate was `intersects'
# 1: (empty)
## in contrast
l2 <- st_linestring(st_point(c(0,0)),st_point(c(1,0)))
p2 <- st_point(c(.1,0)) ## on the line between (0,0) and (1,0) ; y = 0; x = f(t)
st_intersects(p2,l2) ## returns 1 as I would expect
#Sparse geometry binary predicate list of length 1, where the predicate was `intersects'
# 1: 1
To elaborate a bit on the ege-rubak's answer: The point is off by tiny difference, most likely due to floating point math (which is inherently inaccurate).
As a workaround I suggest using sf::st_is_within_distance()
with a sufficiently small dist value to eliminate rounding differences without introducing false positives / may require some tuning depending on the data used.
Consider this code, originally posted on the RStudio Community forum (where this question seems to have been cross posted): https://community.rstudio.com/t/simple-st-intersect-gives-unexpected-result/108214/3?u=jlacko
library(sf)
l1 <- st_linestring(c(st_point(c(0,1)),
st_point(c(0.5,0.5))))
p1 <- st_point(c(.1,.9)) ## on the line between (0,1) and (.5,.5); y=1-x x = f(t)
st_distance(l1, p1)[1,1]
# [1] 1.962616e-17
st_is_within_distance(p1,l1, 1/1000)
# Sparse geometry binary predicate list of length 1, where the
# predicate was `is_within_distance'
# 1: 1