oswaldosantos / ggsn

R package to add north symbols and scale bars to maps created with ggplot or ggmap
http://oswaldosantos.github.io/ggsn/
GNU General Public License v2.0
161 stars 9 forks source link

Scalebar text overlaps scale bar #40

Closed mattbk closed 6 years ago

mattbk commented 6 years ago

I am trying to use ggsn::scalebar in a script that produces maps that could range in area. The default scalebar labels overlap the scalebar.

Is there a way to ensure that this doesn't happen? st.dist doesn't seem to fit what I am looking for, and it seems like avoiding overlap should be built in by default.

Examples:

 ggsn::scalebar(location="bottomleft",
                 dist = roundup(diff(xlim.set)/10)/1000, #minimum 1/10 of x limits, in km
                 x.min = xlim.set[1],
                 x.max = xlim.set[2],
                 y.min = ylim.set[1],
                 y.max = ylim.set[2],
                 dd2km = F,
                 dist_unit = "km")

image

  ggsn::scalebar(location="bottomleft",
                 dist = roundup(diff(xlim.set)/10)/1000, #minimum 1/10 of x limits, in km
                 x.min = xlim.set[1],
                 x.max = xlim.set[2],
                 y.min = ylim.set[1],
                 y.max = ylim.set[2],
                 dd2km = F,
                 dist_unit = "km",
                 st.bottom = F)

image

oswaldosantos commented 6 years ago

Post a reproducible example please

mattbk commented 6 years ago

It looks like a mismatch between this package and coord_sf() from ggplot2.

library(ggplot2)

x = c(1000:2000)
y = c(100:200)

data <- data.frame( x = rep( x, each=1 ),
                  y = rep( y,  length(x)),
                  z = rnorm( x ))

xlim.set<-range(data$x)
ylim.set<-range(data$y)

ggplot() +
  geom_tile(data=data,
            aes_string(x="x",
                       y="y",
                       fill="z")) +
  ggsn::scalebar(location="bottomleft",
                 dist = .2, #km
                 x.min = xlim.set[1],
                 x.max = xlim.set[2],
                 y.min = ylim.set[1],
                 y.max = ylim.set[2],
                 dd2km = F,
                 dist_unit = "m",
                 st.bottom = F) +
  coord_sf(datum = NA, #remove graticule per https://github.com/tidyverse/ggplot2/issues/2071
           xlim=xlim.set,
           ylim=ylim.set)

With coord_sf():

image

Without coord_sf():

image

oswaldosantos commented 6 years ago

Try with higher values for st.dist and height.

mattbk commented 6 years ago

So I should rename this issue "work with coord_sf()" then.

oswaldosantos commented 6 years ago

If there is a problem with scalebar() and coord_sf(), yes. However, you should provide a reproducible example and feedback for comments. The code you previously provided throw errors (Error in roundup(diff(xlim.set)/10) : could not find function "roundup" and Error in FUN(X[[i]], ...) : object 'value' not found) and does not has the code for the plots. Furthermore, you did not give any feedback about my comment, it did not work? Even after fixing the errors and writing the missing code for the plots, I got the expected behavior using height = .5 and st.dist = .7. Please provide a reproducible example a reply to comments to try to help you.

mattbk commented 6 years ago

I've updated the example to make it reproducible.

Manually adjusting height and st.dist will not work for my use case because I am generating multiple maps at once that potentially cover different extents and may have different amounts of aspect ratio modifications with coord_sf().

oswaldosantos commented 6 years ago

Compare the plot using coord_sf() with and without scalebar(). I do not see conflicts between the functions. scalebar() adds a scale bar with and height equal to a fraction hegiht of the y axis, and the text is away of the scale bar by a fraction st.dist of the y axis. If you generate multiple maps with different extents, height and st.dist will be a proportion relative to the each one of the particular extents (the proportion will be the same by the aboslute scale bar height and text distant will vary according to the extent).

ggplot() +
  geom_tile(data=data,
            aes_string(x="x",
                       y="y",
                       fill="z")) +
  coord_sf(datum = NA,
           xlim=xlim.set,
           ylim=ylim.set)

f1

ggplot() +
  geom_tile(data=data,
            aes_string(x="x",
                       y="y",
                       fill="z")) +
  ggsn::scalebar(location="bottomleft",
                 dist = .2, #km
                 x.min = xlim.set[1],
                 x.max = xlim.set[2],
                 y.min = ylim.set[1],
                 y.max = ylim.set[2],
                 dd2km = F,
                 dist_unit = "m",
                 st.bottom = F,
                 st.dist = .12,
                 height = .1) +
  coord_sf(datum = NA,
           xlim=xlim.set,
           ylim=ylim.set)

f2