0

I want to create a map using sf and ggplot2 libraries in R and show point markers rotated by attribute value. Is there maybe a more simple way than doing it like this using geom_segment() and vector calculation using sin() and cos()?

# load necessary libraries
library(ggplot2)
library(sf)

# load csv data
photo_positions <- readr::read_csv("photos_hamburg.csv") |>
  sf::st_as_sf(coords=c('X', 'Y'))

# transform degrees to radians for orientation values
photo_positions[['orientation_rad']] = photo_positions[['orientation']] * pi / 180

# define the arrow length in decimal degrees
arrow_length <- 0.001

# test plot
ggplot(data = photo_positions) +
  
  # extract coordinates
  stat_sf_coordinates() +
  
  # draw arrows with orientation from attribute
  geom_segment(stat = "sf_coordinates", mapping = aes(geometry = geometry, x = after_stat(x), y = after_stat(y), xend = after_stat(x) + arrow_length * sin(photo_positions[['orientation_rad']]), yend = after_stat(y) + arrow_length * cos(photo_positions[['orientation_rad']])), arrow = arrow(), size = 2, color = "turquoise") +
  
  # draw circle markers
  geom_sf(stat = "sf_coordinates", mapping = aes(geometry = geometry, x = after_stat(x), y = after_stat(y)), size = 4, shape = 21, fill = "white") +
  
  # axis labels
  xlab("Longitude") + ylab("Latitude") +
  
  #map title
  ggtitle("Photos in Hamburg")

Here's a screenshot of the plot

I tested it in QGIS. Here's the result.

And here's a screenshot of a test in QGIS

And here's the CSV data used (imaginary photo spots including orientation):

X,Y,name,orientation
9.991293,53.55456,"Alster view 2",59
9.992967,53.550898,"Rathaus view 2",219
9.995563,53.556932,"Alster view 1",201
9.992591,53.551986,"Rathaus view 1",177
9.995724,53.552775,"Alster view 3",338

Any recommendations are highly appreciated!

EDIT: OK, it seems to be an appropriate solution. My only question is now: How do I add those arrows as a map legend with a horizontal arrow as example?

winnewoerp
  • 161
  • 6
  • OK, I see that it's maybe not clear why I posted a working solution and what I'm asking for exactly. Just for clarification: I'm new to R and just couldn't find out if aes() has a possible attribute that takes a value for symbol rotation directly instead of my chosen "detour". – winnewoerp Oct 08 '22 at 17:29
  • I think your solution is terrific! Other solution would be to draw a arrow from scratch, as a sf feature. Then you could place multiple arrows on top of the map and rotate them using affine transformations (https://r-spatial.github.io/sf/articles/sf3.html#affine-transformations). Cheers! – Arthur Welle Oct 08 '22 at 17:31
  • OK, thank you for your positive feedback and the link to the alternative solution! My only question is now: How do I add those arrows as a map legend with a horizontal arrow as example? (Added the question as an edit in the original post.) – winnewoerp Oct 08 '22 at 19:55
  • Take a look here: https://stackoverflow.com/a/57205560/11628460 – Arthur Welle Oct 08 '22 at 20:20
  • Thank you! I'm sure that I can solve it with the link you provided. – winnewoerp Oct 09 '22 at 04:33
  • 1
    I found another approach and solved it using the answers provided here: [How to get a geom_segment show a legend?](https://stackoverflow.com/questions/14771546/remove-legend-title-in-ggplot) and [Remove legend title in ggplot](https://stackoverflow.com/questions/14771546/remove-legend-title-in-ggplot) – winnewoerp Oct 22 '22 at 02:32

0 Answers0