hrbrmstr / ggalt

:earth_americas: Extra Coordinate Systems, Geoms, Statistical Transformations & Scales for 'ggplot2'
https://cran.r-project.org/web/packages/ggalt/vignettes/ggalt_examples.html
Other
653 stars 100 forks source link

proj4 error (probably the coord munching around curvature) #21

Open mdsumner opened 7 years ago

mdsumner commented 7 years ago

Sorry to post this without a solution, but I have to leave it for now.

I get an error from proj4::project for (seemingly) identical inputs when used in coord_proj(), but not directly.

It's likely to do with the coord_munching which I haven't explored yet - these polygons are both stretched around the edges of the laea map with these parameters, and that would likely be true for different polygons and projection combos. (It might be true for the old mapproj idioms for ggplot, but I never learnt to use them).

I don't know if this is a munching problem for ggalt or ggplot2, but either way I'm happy to help. A general "topojson"-like solution would be good in R, etc. etc.

Preparation.

library(dplyr)

library(maptools)
data(wrld_simpl)
library(ggalt)
## either 24 or 175 triggers the problem, everything else is fine
ff <- fortify(wrld_simpl[24, ])
proj <- "+proj=laea +lat_0=-90 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
  1. Ggplot not ok.

ggplot(ff) + aes(x = long, y = lat, group = group) + geom_polygon() + 
  coord_proj(proj, inverse = FALSE, degrees = TRUE, 
             ellps.default = NA)
Error in proj4::project(list(x = df$x, y = df$y), proj = coord$proj, inverse = coord$inverse,  : 
                          tolerance condition error
  1. Cannot recreate error with direct call
df <- ff %>% mutate(x = long, y = lat)

## this shouldn't affect, seems not to
df$x <- ifelse(df$x <= -180, -179.99999999999, df$x)
df$x <- ifelse(df$x >= 180, 179.99999999999, df$x)
df$y <- ifelse(df$y <= -90, -89.99999999999, df$y)
df$y <- ifelse(df$y >= 90, 89.99999999999, df$y)

plot(proj4::project(list(x=df$long, y=df$lat),
                    proj = proj,
                    inverse = FALSE,
                    degrees  = TRUE, 
                    ellps.default = NA), pch = ".", asp = 1)
## how I found the offending objects 24 and 175
# for (i in seq_along(wrld_simpl$NAME)) {
# ff <- fortify(subset(wrld_simpl, NAME == wrld_simpl$NAME[i]))
# proj <- "+proj=laea +lat_0=-90 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
# 
# ## 
# print(
# ggplot(ff) + aes(x = long, y = lat, group = group) + geom_polygon() + 
#   coord_proj(proj, inverse = FALSE, degrees = TRUE, 
#              ellps.default = NA)
# )
# }
mdsumner commented 7 years ago

This works fine now in the new regime:

## new regime (github master branches 2017-02-15)
library(sf)
library(ggplot2)

ggplot(st_as_sf(wrld_simpl[24, ])) + geom_sf() + coord_sf(crs = proj)

ggplot(st_transform(st_as_sf(wrld_simpl[24, ]), proj)) + geom_sf() 
hrbrmstr commented 7 years ago

aye. gave a shout out to the sf ecosystem in the ggalt 0.4.0 blog announcement (shld be hitting rbloggers in the AM). Hope to retire coord_proj() soon ;-)

mdsumner commented 7 years ago

oh, but what about non-sf data?