teunbrand / ggh4x

ggplot extension: options for tailored facets, multiple colourscales and miscellaneous
https://teunbrand.github.io/ggh4x/
Other
534 stars 32 forks source link

Feature: Text on path #58

Closed teunbrand closed 2 years ago

teunbrand commented 2 years ago

Motivation from this SO question (with a great answer from Allan Cameron):

https://stackoverflow.com/questions/69867669/is-there-way-in-ggplot2-to-place-text-on-a-curved-path

There must be a way to do this systematically and capture the logic in a geom_pathtext().

Notes:

teunbrand commented 2 years ago

If I can't get the textshaping::shape_text() to work, I might be able to use {string2path} instead.

teunbrand commented 2 years ago

Allan Cameron has already started work on working out a path text geom here: https://github.com/AllanCameron/geomtextpath. So it doesn't really make sense to do the same thing here :)

AllanCameron commented 2 years ago

Some of the functionality is implemented in a very small package in my AllanCameron/geomtextpath repo, but I have no clear intention to submit this to CRAN any time soon, and you might want to think about incorporating it (or something similar) into ggh4x. It works by breaking a string down into characters, spacing them proportionately along a path based on their strwidth, and rotating each according to the angle of the path at that point. Each character gets its own grob in the grobtree.

This generates some pretty results when labelling lines via the "density" and "smooth" stats - examples shown on the main help page for geom_textpath. It also seems to work "for free" in coord_polar (i.e. straight text paths become curved with the correct angulation without me having purposefully implemented that)

I have written a fairly detailed help file for geom_textpath, but no readme as yet, and I need to tidy/comment the code properly. I was also thinking about how this could be expanded and made tidier. It still has a long way to go, but I think it's promising.

I'm not convinced that converting text to polygons is a great idea for text paths. Fonts contain hinting information that improves their appearance on screen (especially in small point sizes), and this is lost when text is converted to polygons.

I realise ggh4x is your baby, and you probably aren't looking to collaborate, but let me know if you would like to work on the textpath as a collaboration. Otherwise, feel free to take as much of it as you want into your own implementation.

teunbrand commented 2 years ago

Hi Allan,

I would be happy to collaborate, I think it is a very useful geom for people to have access to and kudos to you for getting it in working condition!

There are a few 'finnicky' bits about placing text on a path that I have some ideas about, in particular the calculation of the angle under deformation of the plot window / aspect ratio, and preserving the spacing of the letters versus distributing the letters along the path (in addition to the vjust/hjust/flip ideas in the first post of this thread).

If you're happy to collaborate, we can do one of two things:

Please let me know your thoughts :)

AllanCameron commented 2 years ago

Hi Teun

The implementation already preserves the spacing between the letters (at least to some extent) by getting the strwidth of each character, then normalising the cumulative sum of all the characters. The cumsum is multiplied by the character size to get the actual distance along the path. I think an important design decision is to try to keep the letters spaced together correctly. This means that for most short strings, the string will only take up a small proportion of the path, so we need an extra parameter to say where on the path the character should be located. Currently this is an extra parameter, but it should probably be mapped as an aesthetic.

You know more about the internals of ggplot and ggproto than I do, so it would be great to have your input. From looking again at ggh4x, I think it's a great package, and in particular the faceting functions are superb. I quite like the idea of packages addressing one type of task well, so my inclination would be to have a separate package that handles all the cases where curved text would be useful - this is likely to require a few different geoms and probably a new coord to allow curved axis labelling on polar plots.

I would therefore propose that we work on this as a separate package,with joint authorship. I will work on formatting and commenting the code today, so that you can pull this version and see what you think.

The key thing is that this is really for fun and interest, so there's no pressure either way.

Let me know if you're happy with this approach and I'll get started!

teunbrand commented 2 years ago

Hi Allan,

Yes that sounds great! We should probably continue any discussion at the relevant repo in that case.

So far I've only been experimenting with text on a path at the grid level, but that is nowhere near a user friendly state at the moment. Have a look at https://gist.github.com/teunbrand/c8fbba9be9917c0100646c0b2aa7d671 to see to what point I've gotten.

so we need an extra parameter to say where on the path the character should be located

That sounds a lot like the hjust parameter, except that it's on a path rather than the more typical string width.

I think an important design decision is to try to keep the letters spaced together correctly.

I think that is exactly where the {textshaping} package can help. Given a string, font family, size and resolution, it will return exactly where every character is located. It even has an option for text tracking.

The key thing is that this is really for fun and interest, so there's no pressure either way.

I heartily agree: it is not my job to maintain packages but to develop a new thing every once in a while can be a joy. If you feel your code is ready to be viewed, please feel free to let me know (no hurry or pressure whatsoever, it doesn't have to be soon!).

AllanCameron commented 2 years ago

Hi Teun

Great to know we have the same goals and approach. I agree completely with your sentiments.

I have committed a (sort-of) working version of geomtextpath that can be a starting point. I have added a readme, put your details in the author field and tidied the code with copious comments.

I have started a thread here with a bit more information, and some initial thoughts as to how we might proceed. Maybe the easiest thing to do first would be to pull the repo, install the package and play around with it for a while to see what it can do and whether you see any major problems.

I'm looking forward to hearing your thoughts.