Skip to content
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

A geom similar to geom_text but curves in polar co-ordinates #5

Closed
AllanCameron opened this issue Nov 16, 2021 · 5 comments
Closed
Labels
enhancement New feature or request

Comments

@AllanCameron
Copy link
Owner

Consider the following example where we can't use geom_textpath because we only want labels at a single point rather than following a path:

df <- data.frame(region = c("North America", "South America", 
                            "Australasia", "Europe"), 
                 values = c(500, 200, 350, 600))

p <- ggplot(df, aes(region, values, fill = region)) + 
  geom_col(width = 0.5) + 
  lims(y = c(0, 750)) +
  labs(x = "") +
  theme_bw() +
  theme(legend.position = "none",
        axis.text.x = element_blank(),
        axis.ticks.length.x = unit(0, "mm"))

p1 <- p + geom_text(aes(label = region), size = 5, vjust = -1) 

p1

image

But if we switch to polar co-ordinates, the labels are of course straight:

p1 + coord_polar()

image

With what we have in place so far, it should be straightforward to define a new geom that acts as a drop-in for geom_text but bends in polar co-ordinates, so for example:

p2 <- p + geomtextpath:::geom_textpolar(aes(label = region), size = 5, vjust = -1) 

p2

image

and

p2 + coord_polar()

image

The implementation is something like this:

geom_textpolar <- function(
  mapping = NULL, data = NULL, stat = "identity",
  position = "identity", na.rm = FALSE, show.legend = NA,
  inherit.aes = TRUE,  ...
)
{
  layer(geom = GeomTextPolar, mapping = mapping, data = data, stat = stat,
        position = position, show.legend = show.legend,
        inherit.aes = inherit.aes,
        params = list(
          na.rm     = na.rm,
          ...
        ))
}

GeomTextPolar <- ggproto("GeomLine", GeomTextpath,
    extra_params = c("na.rm", "orientation"),

    setup_data = function(data, params) {
      data$linewidth <- 0
      data <- data[rep(seq(nrow(data)), each = 100),]
      if(!is.numeric(data$x)) data$x <- as.numeric(as.factor(data$x))

      text_width <- diff(range(data$x))/5
      range_seq <- seq(-text_width, text_width, length.out = 100)
      data$x <- data$x + range_seq

      data
    }
)

The questions are

  1. Is this something that people would use (I'm sure I have looked for something similar before)
  2. Do you immediately foresee any problems
  3. I'm not too happy with the name. Can you think of a better one?
@AllanCameron AllanCameron added the enhancement New feature or request label Nov 16, 2021
@teunbrand
Copy link
Collaborator

I think this is pretty nice and might have some use cases, but I'm questioning whether this should be a geom or a position adjustment. I don't foresee any problems that don't happen in Cartesian coordinates, but I do wonder if this only has a use case in non-Cartesian coordinates.

Similar to how geom_path() can be reparametrised into [x, y, xend, yend] in geom_segment() and vice versa, I do feel that alternative parametrisations might be useful in general. We could design some parametrisation that has a use cases in Cartesian coordinates too.

@AllanCameron
Copy link
Owner Author

You're right - it does only do something useful in polar co-ordinates. I do think there is an occasional need for something like this though - see for example this SO question and this other one. It would be great if we could get this to work as just a position adjustment, but I can't immediately see how that would work, since it involves passing row-wise data rather than vertically grouped data.

The implementation above is just a reparameterisation of geom_textpath, similar to the way that geom_line or geom_segment are created, but based on your comments I should probably focus on getting the main geom_textpath to work properly first, so that we can have something simple that works well and that we can build on.

@teunbrand
Copy link
Collaborator

I agree that it is useful to have, but I'm wondering whether there is an opportunity here to kill two birds with one stone. I haven't fully fleshed out anything yet, but I was thinking along the following lines.

  • We could make a geom_textsegment() for placing text on a line segment parametrised by [x, y, xend, yend].
  • We could also make a geom_textspoke() for placing text on some line segment parametrised by [x, y, angle, (length?)].

I imagine in both cases that the line pieces become curves in polar coordinates and because the line pieces are straight in cartesian coordinates, we can extend the hjust() parameters to beyond the [0, 1] interval as these are easily extrapolated (in contrast to non-straight curves).

The case you presented above would then be a geom_textspoke() wherein the (default) angle is 0.

@teunbrand
Copy link
Collaborator

Come to think of it, we could probably also make a geom_textspline() based on our answers here: https://stackoverflow.com/q/68786700/11374827.

@teunbrand teunbrand mentioned this issue Nov 18, 2021
8 tasks
@AllanCameron
Copy link
Owner Author

This enhancement is being archived as it forms part of a later thread, where it is linked for reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants