-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Implement geom_sf_label() and geom_sf_text() #2761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This PR is ready to review now. But, I don't see why Travis fails. especially, on R 3.1; it fails on |
The sf package is missing for 3.1. For the more recent releases, I have noticed that Travis seems to have network issues today. If you restart a failed build it may pass the next time. |
Thanks. Hmm, does absense of sf affects the function args? If so, I think I'm missing something. Anyway, will give it a try later. |
When sf package is not installed, test-function-args fails.
2228250
to
7111bf7
Compare
OK, I think I found the cause. I've made two mistakes below, both of which are not appropriate when sf package is not installed.
|
7111bf7
to
b444c24
Compare
b444c24
to
bfe7f3a
Compare
Confirmed the build on 3.1 passed! Thank you for your advice, Claus. (devel still fails due to the curl's "Connection timed out" error; I think I'm not lucky enough to let all 5 builds pass at the same time...) |
You can restart just one particular failed build by clicking on the reload icon to the right of it. In this way, you won't mess up the builds that already succeeded. I have a few comments/questions:
|
The icon doesn't show; it seems I don't have the permission, unfortunately. |
(Disclaimer: I'm not a GIS expert but a guy who just wants to add labels on
In sf package (and probably in simple feature access), they are always written as capital. So, I felt it's more natural to use capital letters for computed variables so that we can distinguish them from ggplot's coordinates. That said, I'm still wondering whether they are essentially the same thing,
Thanks, this sounds nice.
Different. As described above,
Your suggestion is about when the first step succeeds but doesn't return For example, consider we have a library(ggplot2)
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.2.3, proj.4 4.9.3
mat_poly_xy <- rbind(
c(1, 1), c(-1, 1), c(-1, -1), c(1, -1), c(1, 1)
)
poly_xy <- st_polygon(list(mat_poly_xy))
poly_xy
#> POLYGON ((1 1, -1 1, -1 -1, 1 -1, 1 1)) In this case, we can choose a point on the polygon by d_poly_xy <- st_sf(geometry = st_sfc(poly_xy))
d_pt_xy <- st_point_on_surface(d_poly_xy)
xy <- st_coordinates(d_pt_xy) So we can combine the coordinates with the original data cbind(d_pt_xy, xy)
#> Simple feature collection with 1 feature and 2 fields
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 0 ymin: 0 xmax: 0 ymax: 0
#> epsg (SRID): NA
#> proj4string: NA
#> X Y geometry
#> 1 0 0 POINT (0 0) But, if the polygon has mat_poly_xym <- cbind(mat_poly_xy, 1)
poly_xym <- st_polygon(list(mat_poly_xym), dim = "XYM")
poly_xym
#> POLYGON M ((1 1 1, -1 1 1, -1 -1 1, 1 -1 1, 1 1 1))
d_poly_xym <- st_sf(geometry = st_sfc(poly_xym))
st_point_on_surface(d_poly_xym)
#> Error in CPL_geos_op("point_on_surface", x, numeric(0), integer(0), numeric(0), : GEOS does not support XYM or XYZM geometries; use st_zm() to drop M |
Ah, in short, I commented about errors when Z and/or M are available, which is not always happy. Does my answer make sense? |
The Z and M issue still isn't entirely clear to me. Do I understand correctly that the default setup fails if the geometries contain Z or M coordinates? In this case, wouldn't it be better for the default to remove Z and M and then run #' @param fun.geometry
#' A function that takes a `sfc` object and returns a `sfc_POINT` with the
#' same length as the input. If `NULL`, `function(x) sf::st_point_on_surface(sf::st_zm(x))` will be
#' used. |
Generally, yes. (It may not fail depending on what Thanks,
Does this look better to you? |
I have no idea why the Travis build still fails, but it seems unrelated to this PR. |
Ah, do I have to wait for #2838 to be solved? |
I assume it's because of #2824. That needs to be resolved first. |
I got it, Sorry that I don't keep up the discussion... |
#2824 is now resolved. |
Yay, all checks passed! |
Looks good to me. @hadley, any concerns from your side? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of documentation style issues, and needs a news bullet; otherwise looks good!
R/sf.R
Outdated
@@ -6,6 +6,7 @@ | |||
#' an unusual geom because it will draw different geometric objects depending | |||
#' on what simple features are present in the data: you can get points, lines, | |||
#' or polygons. | |||
#' For texts and labels, you can use `geom_sf_text` and `geom_sf_label`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
text -> text; functions should have ()
after them
R/sf.R
Outdated
#' @rdname ggsf | ||
#' @inheritParams geom_label | ||
#' @inheritParams stat_sf_coordinates | ||
#' @seealso [stat_sf_coordinates()] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this seealso belongs in the documentation block above.
R/stat-sf-coordinates.R
Outdated
#' | ||
#' `stat_sf_coordinates()` extracts the coordinates from 'sf' objects and | ||
#' summarises them to one pair of coordinates (x and y) per geometry. This is | ||
#' convenient when you draw an sf object as geoms like texts and labels (so |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
texts -> text (English is weird)
Thanks! I was very anxious if my English is strange, so the comments are very helpful... For a news bullet, should I wait for the release of v3.0.1? |
No, please add the news bullet now. Thanks! |
Sure! |
Added a bullet. |
@clauswilke Could you merge this if this is OK? Then I can create another PR to improve the error message you commented :) |
Thanks! |
This is an extremely useful feature. Thanks!!! |
The merge broke the build. Could you look into what's going wrong? I'm in meetings all day. |
Hmm, sorry if this is my fault. I will investigate. |
Now it's all green. I definitely saw "error" status, but I can't find the errored build in the history. What happened...? |
Did I deleted my branch too early? |
Anyway, it seems alright now. |
This old issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with reprex) and link to this issue. https://reprex.tidyverse.org/ |
This PR closes #2742.
Background
It's very convenient that
geom_sf()
automatically chooses the proper geometries (point, line or polygon) based on the type of the simple feature in the data. But, we sometimes want to choose different type of geoms, for example, texts and labels.However, adding flexibility to
geom_sf()
(or underlyingsf::st_as_grob()
) leads to unmaintainable complexity as discussed in #2111. So, we need to implement it as separate geoms/stats for code simplicity. Here, I proposegeom_sf_label()
andgeom_sf_text()
, and their corresponding statstat_sf_coordinates()
.Design
StatSfCoordinates
Texts and labels need pairs of
x
andy
.StatSfCoordinates
is a stat to provide these via computed variablex
andy
(lower letters).stat_sf_coordinates()
is thestat_
function corresponding to this.X
andY
dimensions of asf
object can be retrieved bysf::st_coordinates()
. But, we cannot simply usesf::st_coordinates()
texts and labels require exactly one coordinate per geometry whereas it returns multiple locations for a polygon or a line. Instead, these two steps are needed:sf::st_centroid()
andsf::st_point_on_surface()
.sf::st_coordinates()
.For the first step, users can pass arbitrary function via parameter
fun.geometry
. By default,function(x) sf::st_point_on_surface(sf::st_zm(x))
is used; I thinksf::st_point_on_surface()
is more appropriate thansf::st_centroid()
since labels and texts usually are intended to be put within the polygon or the line.geom_sf_label()
andgeom_sf_text()
geom_sf_label()
andgeom_sf_text()
are basically same withgeom_label()
andgeom_text()
for each, except that:StatSfCoordinates
forstat
geometry
aesthetic automatically just asgeom_sf()
doesfun.geometry
argumentConsiderations
Z
andM
dimensionSimple feature objects may have
Z
and/orM
dimension in addition toX
andY
. These dimensions may be useful, but sometimes they are problematic:M
dimension makes functions likesf::st_point_on_surface()
andsf::st_centroid()
fail.Z
dimension may do no harm, butZ
dimension is not always available in the results.For simplicity, we simply drop
Z
andM
and use onlyX
andY
.Warning for longitude/latitude data
Functions that does calculation based on the distances may warn if the on data is in unprojected coordinate system. Though the warnings should not be suppressed, we need to be careful to use
geom_sf_label()
in examples. Otherwise, the tests fail.TODOs
stat_sf_coordinates()
fun.geometry
Z
andM
dimension? (no)Usages
Created on 2018-08-19 by the reprex package (v0.2.0).