I'm building a shapefile of states where Alaska and Hawaii are represented as being somewhere south of Texas, for ease of making an illustrative map. Using maptools package and some code from https://rud.is/b/2014/11/16/moving-the-earth-well-alaska-hawaii-with-r/, I have been able to do this with shapes from TIGER.
However, I am running into trouble now that I want to add cities to my map. Making my shapes into sp objects and then using maptools::elide works fine for Alaska before, but elide with scale doesn't work the same way on a collection of points so my cities wind up in the wrong place:
library(maptools)
library(sf)
library(tmap)
library(tidyverse)
library(tidygeocoder)
ak_city_sf <-
tribble(~city_name, ~city_search_string,
"Juneau", "Juneau, Alaska, United States",
"Anchorage", "Anchorage, Alaska, United States",
"Utqiagvik", "Utqiagvik, Alaska, United States",
"Scammon Bay", "Scammon Bay, Alaska, United States") %>%
geocode(city_search_string, method = 'osm', lat = latitude , long = longitude) %>%
st_as_sf(coords = c("longitude","latitude"))
st_crs(ak_city_sf) <- 4326
ak_city_sf <-
ak_city_sf %>%
st_transform(2163)
ak_state_sf <-
tigris::states(cb = T) %>%
filter(STUSPS == "AK") %>%
st_transform(2163)
# before transformation, everything looks fine...
tm_shape(ak_state_sf) +
tm_borders() +
tm_shape(ak_city_sf) +
tm_dots(size = .1) +
tm_text("city_name",
size = .5)
SCALE_FACTOR <- 10000
ak_state_sf_scaled <-
ak_state_sf %>%
as("Spatial") %>%
elide(scale = SCALE_FACTOR) %>%
st_as_sf()
st_crs(ak_state_sf_scaled) <- 2163
ak_city_sf_scaled <-
ak_city_sf %>%
as("Spatial") %>%
elide(scale = SCALE_FACTOR) %>%
st_as_sf()
st_crs(ak_city_sf_scaled) <- 2163
# after scaling, things don't look so good
tm_shape(ak_state_sf_scaled) +
tm_borders() +
tm_shape(ak_city_sf_scaled) +
tm_dots(size = .1) +
tm_text("city_name",
size = .5)
maptools::elide seems to be the best command for doing anything like this (even though it forces me to convert to an sp object). The documentation for scale doesn't mean much to me. (I don't think I can combine them in a single object because they are points for the cities and multipolygons for the state). How can I scale the points the same way I've scaled the state?
To scale or rotate two separate geometries so that they can be mapped together, it's necessary to define a centroid that both your state geometries and city geometries will be rotated or scaled around. This makes some logical sense, since scaling or rotating a collection of points (in this case representing cities) can't happen unless you define (implicitly or explicitly) the center of the scaling or rotating.
Once you've defined a common centroid (in my case, I just used the centroid of the states I was transforming), you can use the affine transformations shown here: https://geocompr.robinlovelace.net/geometric-operations.html#affine-transformations.