1

I have a group of points for London's train stations I've found through OSMdata:

library(osmdata)
library(tidyverse)

osm_points <- opq ('greater london uk') %>% 
      add_osm_feature("public_transport", "station") %>% 
      osmdata_sf()

I want to overlay London's train stations over a map of other cities: e.g. London's train station points, but instead of centred around central London, around the middle of Berlin instead. To do this I need to 'subtract' the lat/lon of London's tube locations from the centre of another city - but I'm not sure how to do this algorithmically.

Does anybody have any ideas?

1 Answer 1

2

The "subtracting" of lat - long values of London points to Berlin (or what not....) is an affine transformation of type shift.

The {sf} package has this implemented for class sfc (and not sf) requiring you to work on the geometry column, not full dataframe.

It can feel somewhat hacky, but it does work and returns the results you expect.

Let me illustrate on an example (I am lazy and not using the public transport, but only three semi-random London landmarks; please bear with me).

The trick is twofold:

  • you first calculate the difference between centroids of London and Berlin
  • then you add this offset to geometry column of all your landmarks

In the process you will likely destroy the CRS information of your spatial object, so you will have to reconstruct that.

library(sf)
library(dplyr)
library(nominatimlite)

# a set of semi-random London points via {nominatimlite}
london_landmarks <- c("Piccadilly Circus, London", "Leicester Square, London",
                      "London Bridge, London") %>% 
  geo_lite_sf(points_only = T)

# visual check - looks legit
mapview::mapview(london_landmarks)

enter image description here

# centroid of London
london_city <- "London, UK" %>% 
  geo_lite_sf(points_only = F) %>% 
  st_centroid()

# centroid of Berlin
berlin_city <- "Berlin, Germany" %>% 
  geo_lite_sf(points_only = F) %>% 
  st_centroid()

# calculate difference between centroids
offset <- st_geometry(berlin_city) - st_geometry(london_city)

# intiate resultset
berlin_landmarks <- london_landmarks

# perform affine transformation on geometry column; this will mess up CRS
st_geometry(berlin_landmarks) <- st_geometry(berlin_landmarks) + offset 

# repair CRS - it is the same as London landmarks
berlin_landmarks <- st_set_crs(berlin_landmarks, st_crs(london_landmarks))

# a visual check
mapview::mapview(berlin_landmarks)

enter image description here

1
  • 1
    Its not that it messes up the CRS, the real problem is that if you do a planar shift of projected coordinates you are going to mess up the relationship of the points - distances in particular could now be very wrong. Berlin is only a bit N or London so its not so obvious. You need to use lat-long and do rotations on the sphere if you want to preserve distances.
    – Spacedman
    Aug 8, 2022 at 10:05

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.