text on curve

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

text on curve

Jinsong Zhao-2
Hi there,

I write a simple function that could place text along a curve. Since I am not familiar with the operation of rotating graphical elements, e.g., text, rectangle, etc., I hope you could give suggestions or hints on how to improve it. Thanks in advance.

# Here is the code:

getCurrentAspect <- function() {
   uy <- diff(grconvertY(1:2,"user","inches"))
   ux <- diff(grconvertX(1:2,"user","inches"))
   uy/ux
}

r.xy <- function(o.x, o.y, theta) {
   r.x <- o.x * cos(theta) - o.y * sin(theta)
   r.y <- o.x * sin(theta) + o.y * cos(theta)
   c(r.x, r.y)
}

text.on.curve <- function(x, y, x.s, str, ...) {

   l <- nchar(str)

   fun <- approxfun(x, y, rule = 2)

   for(i in 1:l) {
      w <- strwidth(substr(str, i, i))
      h <- strheight(substr(str, i, i))

      x.l <- x.s
      x.r <- x.s + w
      y.l <- fun(x.l)
      y.r <- fun(x.r)
      theta <- atan((y.r - y.l)/(x.r - x.l) * getCurrentAspect())

      lb.xy <- c(x.s, fun(x.s))
      rb.xy <- lb.xy + r.xy(w, 0, theta)
      lt.xy <- lb.xy + r.xy(0, h, theta)
      rt.xy <- lb.xy + r.xy(w, h, theta)
      c.xy <- lb.xy + r.xy(w/2, h/2, theta)

      while(i > 1 && lt.xy[1] < rt.xy.old[1]) {
         x.s <- x.s + 0.05 * w
         x.l <- x.s
         x.r <- x.s + w
         y.l <- fun(x.l)
         y.r <- fun(x.r)
         theta <- atan((y.r - y.l)/(x.r - x.l) * getCurrentAspect())

         lb.xy <- c(x.s, fun(x.s))
         rb.xy <- lb.xy + r.xy(w, 0, theta)
         lt.xy <- lb.xy + r.xy(0, h, theta)
         rt.xy <- lb.xy + r.xy(w, h, theta)
         c.xy <- lb.xy + r.xy(w/2, h/2, theta)
      }

      x.s <- rb.xy[1]
      rt.xy.old <- rt.xy

      text(c.xy[1], c.xy[2], substr(str, i, i), srt = theta * 180 / pi, ...)
   }
}

# A simple demo:

x <- seq(-5, 5, length.out = 100)
y <- x^2
plot(x,y, type = "l")
text.on.curve(x, y, -2 ,"a demo of text on curve", col = "red")

Best,
Jinsong
 
        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: text on curve

Jim Lemon-4
Hi Jinsong,
This is similar to the "arctext" function in plotrix. I don't want to
do all the trig right now, but I would suggest placing the characters
on the curve and then offsetting them a constant amount at right
angles to the slope of the curve at each letter. I would first try
having a "minspace" argument to deal with crowding at small radii and
you would probably have to start at the middle and work out to each
end. A tough problem and you have made a good start on it.  Check the
fragment below for a suggestion on how to avoid calling "substr"
repeatedly.

# get a vector of the characters in str
   # rather than call substr all the time
   strbits<-unlist(strsplit(str,""))

   for(i in 1:l) {
      w <- strwidth(strbits[i])
      h <- strheight(strbits[i])

Jim

On Tue, Sep 22, 2020 at 6:11 PM Jinsong Zhao <[hidden email]> wrote:

>
> Hi there,
>
> I write a simple function that could place text along a curve. Since I am not familiar with the operation of rotating graphical elements, e.g., text, rectangle, etc., I hope you could give suggestions or hints on how to improve it. Thanks in advance.
>
> # Here is the code:
>
> getCurrentAspect <- function() {
>    uy <- diff(grconvertY(1:2,"user","inches"))
>    ux <- diff(grconvertX(1:2,"user","inches"))
>    uy/ux
> }
>
> r.xy <- function(o.x, o.y, theta) {
>    r.x <- o.x * cos(theta) - o.y * sin(theta)
>    r.y <- o.x * sin(theta) + o.y * cos(theta)
>    c(r.x, r.y)
> }
>
> text.on.curve <- function(x, y, x.s, str, ...) {
>
>    l <- nchar(str)
>
>    fun <- approxfun(x, y, rule = 2)
>
>    for(i in 1:l) {
>       w <- strwidth(substr(str, i, i))
>       h <- strheight(substr(str, i, i))
>
>       x.l <- x.s
>       x.r <- x.s + w
>       y.l <- fun(x.l)
>       y.r <- fun(x.r)
>       theta <- atan((y.r - y.l)/(x.r - x.l) * getCurrentAspect())
>
>       lb.xy <- c(x.s, fun(x.s))
>       rb.xy <- lb.xy + r.xy(w, 0, theta)
>       lt.xy <- lb.xy + r.xy(0, h, theta)
>       rt.xy <- lb.xy + r.xy(w, h, theta)
>       c.xy <- lb.xy + r.xy(w/2, h/2, theta)
>
>       while(i > 1 && lt.xy[1] < rt.xy.old[1]) {
>          x.s <- x.s + 0.05 * w
>          x.l <- x.s
>          x.r <- x.s + w
>          y.l <- fun(x.l)
>          y.r <- fun(x.r)
>          theta <- atan((y.r - y.l)/(x.r - x.l) * getCurrentAspect())
>
>          lb.xy <- c(x.s, fun(x.s))
>          rb.xy <- lb.xy + r.xy(w, 0, theta)
>          lt.xy <- lb.xy + r.xy(0, h, theta)
>          rt.xy <- lb.xy + r.xy(w, h, theta)
>          c.xy <- lb.xy + r.xy(w/2, h/2, theta)
>       }
>
>       x.s <- rb.xy[1]
>       rt.xy.old <- rt.xy
>
>       text(c.xy[1], c.xy[2], substr(str, i, i), srt = theta * 180 / pi, ...)
>    }
> }
>
> # A simple demo:
>
> x <- seq(-5, 5, length.out = 100)
> y <- x^2
> plot(x,y, type = "l")
> text.on.curve(x, y, -2 ,"a demo of text on curve", col = "red")
>
> Best,
> Jinsong
>
>         [[alternative HTML version deleted]]
>
> ______________________________________________
> [hidden email] mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: text on curve

Berry, Charles-2
In reply to this post by Jinsong Zhao-2


> On Sep 22, 2020, at 1:10 AM, Jinsong Zhao <[hidden email]> wrote:
>
> Hi there,
>
> I write a simple function that could place text along a curve. Since I am not familiar with the operation of rotating graphical elements, e.g., text, rectangle, etc., I hope you could give suggestions or hints on how to improve it. Thanks in advance.
>
> # Here is the code:
>


[code deleted]

For this kind of operation you might want to use tikz.

R has the ability to produce tikz directives and to insert raw tikz into a 'tikzDevice'.

If you search rseek.org for 'tikz' you will get plenty of good hits.

The tikz/pgf manual has examples of flowing text, IIRC.

HTH,

Chuck

p.s. this is a plain text list. Do not submit html.
______________________________________________
[hidden email] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.