3

I'm working on a wildlife study, and hoping to calculate the distance from each of our trail camera locations to the nearest road in eight points of the compass. I used the Shape Tools Plugin to create lines of bearing for each camera point, and the Vector Overlay > Line Intersections tool to record the road intercepts on each bearing. The camera points are named A6, B4, B5, B6 etc., and each of the road intercepts are named for the camera point whose bearing they fall on.

The next step is where I am running into problems. I used the Distance Matrix tool, but it doesn't pair the camera location with the road intercepts on its bearing. I.e. if the nearest road intercept to camera A6 is a road intercept on the bearing generated from camera B5, then it records that distance, not the distance from the A6 camera - A6 road intercept.

If I use the Distance Matrix tool, but don't constrain it to only the nearest intercept then the values I'm interested in do get captured and I can go through manually to pull them out, but there are tens of thousands of other distances between unrelated points that I have to wade through.

Is there a way to pair the points in a distance calculation, e.g. so I only get the distance between the A6 camera point, and the nearest A6 road intercept?

Camera Locations (yellow) and Road Intercepts (Purple) on a 45 degree bearing

1
  • Can you please share your data with us for testing purposes?
    – Taras
    Feb 23, 2022 at 20:26

2 Answers 2

2

Have you tried the NNjoin plugin in QGIS? https://plugins.qgis.org/plugins/NNJoin/

I used previously on some work when I had to find the shortest distance to certain surficial geology features from outcrop locations. I found it quite helpful for finding the shortest distance from my outcrops (points) to the surficial geology features (lines). There were some helpful YouTube tutorials as well but I am unable to find the links now.

1
  • Thanks for the suggestion! I gave NNjoin a try just now, but was running into the same problem with it calculating the distances to points on bearings generated from other camera locations. But I sent the Distance Matrices with all of the distance permutations to my girlfriend, and she should be able to extract the distances I'm interested in using R. Feb 23, 2022 at 19:25
0

If you would like consider R as a tool, then below approach can be used:

First of all let's find some way and place for camera. I will use OSM data - finding bounding box and highways in my village.

library(osmdata)
library(tidyverse)
library(sf)

Lbb <- getbb("Lubnów, Oborniki Śląskie, Poland", format_out = "matrix")

highways <- opq (Lbb, timeout = 60) |> 
  add_osm_feature (key = "highway") |>
  osmdata_sf()

Let's prepare a plot area and plot the highways:

plot(x = Lbb[1], y = Lbb[2], type = "n", xlim = c(Lbb[1], Lbb[3]), ylim = c(Lbb[2], Lbb[4]))
plot(highways$osm_lines$geometry, add = TRUE)

Let's create our camera position (p1) and construct a line upwards (0 deg), where p2 is the line end point:

p1 <- st_point(x = c((Lbb[3]+Lbb[1])/2, (Lbb[4]+Lbb[2])/2))
p2 <- st_point(x = c(p1[1], Lbb[4]+1))

plot(p1, pch = 16, col = "red", add = TRUE)
l <- st_linestring(c(p1, p2))
plot(l, add = TRUE, col = "green")

Let's define rot function for line rotate (taken from sf vignette: https://r-spatial.github.io/sf/articles/sf3.html#affine-transformations) and create l2 which is rotated by 45 deg (pi/4)

rot = function(a) matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)

l2 <- (l-p1) * rot(pi/4) + p1
plot(l2, col = "orange", add = TRUE)

And finally, let's find all highways which are intersects by l2 (using st_join), find their intersections (st_intersection), calculate the distance to our camera (st_distance(P1, intersection point)), arrange them increasingly and take the first result head(1) as the closest one.

l2 <- st_as_sf(st_sfc(l2))
h <- st_as_sf(highways$osm_lines)
st_crs(l2) <- st_crs(h)
P1 <- st_as_sf(st_sfc(p1))
st_crs(P1) <- st_crs(h)

h |>
  st_join(l2, left = FALSE) |>
  select(osm_id, geometry) |>
  st_intersection(l2) |>
  rowwise() |>
  mutate(distance = mapply(function(x) st_distance(P1, x), st_as_sf(geometry))) |>
  arrange(distance) |>
  head(1)

which gives us:

#> Simple feature collection with 1 feature and 2 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 16.88842 ymin: 51.26244 xmax: 16.88842 ymax: 51.26244
#> Geodetic CRS:  WGS 84
#> # A tibble: 1 × 3
#> # Rowwise: 
#>   osm_id               geometry distance
#>   <chr>             <POINT [°]>    <dbl>
#> 1 105505165 (16.88842 51.26244)     50.0

and we can add it to plot

  [...] |>
  select(geometry) |>
  plot(add = TRUE)

Then it can be extended for all your cameras either in loop, or creating a function and applying it to them. If you have shp files, you can read them with st_read. Just make sure CRS systems of ways and camera positions are the same.

Hope it makes sense.

Created on 2022-02-23 by the reprex package (v2.0.1)

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.