rcsr | R Documentation |
This is a wild bit of trigonometry! Three points in 3D space, two ends and
an control point, are rotated into 2D space. Then a spline curve is
computed. This is necessary because spline curves are only defined in
R
as 2D objects. The new collection of points, which is the complete
spline curve and when drawn will be the edge of a hive plot, is rotated back
into the original 3D space. rcsr
stands for rotate, compute spline,
rotate back.
rcsr(p0, cp, p1)
p0 |
A triple representing one end of the final curve (x, y, z). |
cp |
A triple representing the control point used to compute the final curve (x, y, z). |
p1 |
A triple representing the other end of the final curve (x, y, z). |
See the code for exactly how the function works. Based upon the process described at http://www.fundza.com/mel/axis_to_vector/index.html Timing tests show this function is fast and scales linearly (i.e. 10x more splines to draw takes 10x more time). Roughly 3 seconds were required to draw 1,000 spline curves in my testing.
A 3 column matrix with the x, y and z coordinates to be plotted to create a hive plot edge.
Bryan A. Hanson, DePauw University. hanson@depauw.edu
# This is a lengthy example to prove it works.
# Read it and then copy the whole thing to a blank script.
# Parts of it require rgl and are interactive.
# So none of the below is run during package build/check.
### First, a helper function
## Not run:
drawUnitCoord <- function() {
# Simple function to draw a unit 3D coordinate system
# Draw a Coordinate System
r <- c(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1) # in polar coordinates
theta <- c(0, 0, 0, 90, 0, 180, 0, 270, 0, 0, 0, 0) # start, end, start, end
phi <- c(0, 90, 0, 90, 0, 90, 0, 90, 0, 0, 0, 180)
cs <- data.frame(radius = r, theta, phi)
ax.coord <- sph2cart(cs)
segments3d(ax.coord, col = "gray", line_antialias = TRUE)
points3d(
x = 0, y = 0, z = 0, color = "black", size = 4,
point_antialias = TRUE
) # plot origin
# Label the axes
r <- c(1.1, 1.1, 1.1, 1.1, 1.1, 1.1) # in polar coordinates
theta <- c(0, 90, 180, 270, 0, 0)
phi <- c(90, 90, 90, 90, 0, 180)
l <- data.frame(radius = r, theta, phi)
lab.coord <- sph2cart(l)
text3d(lab.coord, texts = c("+x", "+y", "-x", "-y", "+z", "-z"))
}
### Now, draw a reference coordinate system and demo the function in it.
drawUnitCoord()
### Draw a bounding box
box <- data.frame(
x = c(1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1),
y = c(1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1),
z = c(1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1)
)
segments3d(box$x, box$y, box$z, line_antialias = TRUE, col = "red")
### Draw the midlines defining planes
mid <- data.frame(
x = c(0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1),
y = c(-1, -1, -1, 1, 1, 1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 1, 1, 1, 1, -1),
z = c(-1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0)
)
segments3d(mid$x, mid$y, mid$z, line_antialias = TRUE, col = "blue")
### Generate two random points
p <- runif(6, -1, 1)
# Special case where p1 is on z axis
# Uncomment line below to demo
# p[4:5] <- 0
p0 <- c(p[1], p[2], p[3])
p1 <- c(p[4], p[5], p[6])
### Draw the pts, label them, draw vectors to those pts from origin
segments3d(
x = c(0, p[1], 0, p[4]),
y = c(0, p[2], 0, p[5]),
z = c(0, p[3], 0, p[6]),
line_antialias = TRUE, col = "black", lwd = 3
)
points3d(
x = c(p[1], p[4]),
y = c(p[2], p[5]),
z = c(p[3], p[6]),
point_antialias = TRUE, col = "black", size = 8
)
text3d(
x = c(p[1], p[4]),
y = c(p[2], p[5]),
z = c(p[3], p[6]),
col = "black", texts = c("p0", "p1"), adj = c(1, 1)
)
### Locate control point
### Compute and draw net vector from origin thru cp
### Connect p0 and p1
s <- p0 + p1
segments3d(
x = c(0, s[1]), y = c(0, s[2]), z = c(0, s[3]),
line_antialias = TRUE, col = "grey", lwd = 3
)
segments3d(
x = c(p[1], p[4]), # connect p0 & p1
y = c(p[2], p[5]),
z = c(p[3], p[6]),
line_antialias = TRUE, col = "grey", lwd = 3
)
cp <- 0.6 * s # Now for the control point
points3d(
x = cp[1], # Plot the control point
y = cp[2],
z = cp[3],
point_antialias = TRUE, col = "black", size = 8
)
text3d(
x = cp[1], # Label the control point
y = cp[2],
z = cp[3],
texts = c("cp"), col = "black", adj = c(1, 1)
)
### Now ready to work on the spline curve
n2 <- rcsr(p0, cp, p1) # Compute the spline
lines3d(
x = n2[, 1], y = n2[, 2], z = n2[, 3],
line_antialias = TRUE, col = "blue", lwd = 3
)
### Ta-Da!!!!!
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.