rcsr: Compute the Details of a 3D Spline for a Hive Plot Edge

Description Usage Arguments Details Value Author(s) Examples

View source: R/rcsr.R

Description

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.

Usage

1
rcsr(p0, cp, p1)

Arguments

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).

Details

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.

Value

A 3 column matrix with the x, y and z coordinates to be plotted to create a hive plot edge.

Author(s)

Bryan A. Hanson, DePauw University. hanson@depauw.edu

Examples

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# 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)

HiveR documentation built on July 1, 2020, 7:04 p.m.