简体   繁体   中英

How to draw a point in polar coordinates with negative r?

I am trying to draw two points in polar coordinates (r, theta), where r is a distance from the center, and theta the angle.

The current solution does not work because I don't have a unique "origin" of the axes. When using coord_plane , the origin of y is the center of the circle, but the origin of x seems to be the center of each radius.

What I am trying to do, is to plot in a system where the two points from the below example are symmetric with respect to the origin.

library(ggplot2)
ggplot(data.frame(r = c(-100, 100) , theta = c(1, 1)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi'))

在此输入图像描述

UPDATE:

While the system that coord_polar creates is probably not a "straight" polar systems, here is a quote from the grammar of graphics that in part explains in part the behavior of coord_polar , and the reason why I had to fix the limits of y :

We could treat polar coordinates as an exception to the way all other scales are handled in this system. That is, we could interpret angular values ab- solutely as radians. This would make sense if all our graphics were mathemat- ical or engineering applications involving radians. We have chosen not to do this, however, so that we can hide scaling details when doing coordinate con- versions. This makes it easy, for example, to represent yearly time in polar co- ordinates. In the polar coordinate conversion, therefore, we align 0 radians with the minimum scale value in data units (degrees, radians, proportions, etc.) and 2S radians with the maximum. The cycle parameter, together with min and max parameters in the scale functions allows us to create polar graphs with more than one revolution if we wish.

I don't fully understand what is your ultimate goal, but maybe the problem is that if you want r to represent distance to the origin, then it cannot be negative. What ggplot2 does with coord_polar() is just to deform the whole cartesian plane following polar coordinates. This results in a "zero" that is actually the lower limit of your "radial" coordinate. You can see it clearly if you manually change its limits:

library(ggplot2)
ggplot(data.frame(r = c(-100, 100) , theta = c(1, 1)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi')) +
  scale_x_continuous(limits = c(-200, NA))

I don't know exactly what you mean with "symmetric with respect to the origin" but something this would be ok?

library(ggplot2)
ggplot(data.frame(r = c(100, 100) , theta = c(1, 1 + pi)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi')) +
  scale_x_continuous(limits = c(0, NA))

Created on 2019-07-16 by the reprex package (v0.3.0)

Adapting Elio Campitelli's answer as a function, you could use something like:

plot_polar_signed <- function(r, theta) {
  data2 <- data.frame(r2 = abs(r),
             theta2 = theta + ifelse(r < 0, pi, 0))
  ggplot(data2, aes(x = r2, y = theta2)) +
    geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
    coord_polar(theta = 'y',
                direction = -1,
                start = -pi/2) +
    scale_y_continuous(limits = c(0, 2*pi),
                       breaks = c(0, pi/2, pi, 3*pi/2 ),
                       labels = c('0', 'pi/2', 'pi', '3/2pi'))

}

plot_polar_signed(r = c(-100, 100), theta = c(1, 1))

在此输入图像描述

Points with r < 0 are not defined in polar coordinates, since r is the distance from the center. Otherwise there would be 2 sets of coordinates for every point with r != 0 even when forcing theta to be in (0, 2pi) .

So you're really trying to plot in an extended polar coordinate system where negative r is allowed and (r, theta) and (-r, theta + pi) are the same points.

I suggest using a mapping from your system to the canonical polar coordinates.

canonical <- function(r, theta) {
  if (r >= 0) {
    c(r = r, theta = theta %% (2*pi))
  } else {
    c(r = -r, theta = (theta + pi) %% (2*pi))
  }
}

Or shorter and vectorised:

canonical <- function(r, theta) {
  list(r = abs(r), 
       theta = (theta + ifelse(r < 0, pi, 0)) %% (2 * pi))
}

This leaves valid polar coordinates untouched (except bringing theta in (0, 2pi) if it is not already) and converts points with r < 0 to valid polar coordinates.

canonical(1, 0)
# untouched 

canonical(-1, 0)
# becomes (1, pi)

The advantage is that you can use all the standard polar functions from ggplot after converting.

library(ggplot2)

df <- data.frame(r = c(-100, -50, 0, 50, 100) , theta = rep(1, 5))
df_polar <- as.data.frame(canonical(df$r, df$theta))

ggplot(df_polar,
       aes(x = r, y = theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y') +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi'))

极坐标的结果

Another option in the same vein is to convert from polar to cartesian coordinates to make it easy to draw straight lines. The mapping is x = r*cos(theta) and y=r*sin(theta) and, interestingly, is valid for negative r as well since cos(theta+pi) = -cos(theta) and same for sin .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM