介绍

R 教程 逐步描述了如何使用 rgl包 构建 3D 图形。

RGL 是一个 3D 图形包,可生成实时交互式 3D 绘图。

它允许交互式旋转、缩放图形和选择区域。

rgl 包还包括一个名为 R3D 的通用 3D 接口。

R3D 是本文末尾描述的通用 3D 对象和函数的集合。

内容14913字 32图!

安装 RGL 包

1
install.packages("rgl")

在 Linux 操作系统上,可以按如下方式安装rgl包:

1
sudo apt-get install r-cran-rgl

加载 RGL 包

1
library("rgl")

准备数据

我们将在以下示例中使用iris数据集:

1
2
3
4
5
6
data(iris)
head(iris)

x <- sep.l <- iris$Sepal.Length
y <- pet.l <- iris$Petal.Length
z <- sep.w <- iris$Sepal.Width

启动和关闭 RGL device

要使用 RGL 制作 3D 绘图,应该首先在 R 中启动 RGL device

以下函数用于管理 RGL :

  • rgl.open():打开一个新设备
  • rgl.close():关闭当前设备
  • rgl.clear():清除当前设备
  • rgl.cur():返回活动设备 ID
  • rgl.quit():关闭 RGL

第一部分,为每个绘图打开一个新的 RGL 设备。

可以第一次使用函数 rgl.open() –> 然后制作第一个 3D 绘图 –> 然后使用 rgl.clear() 清除场景 –> 并再次制作新的绘图。

3D 散点图

基本图

函数rgl.points()用于绘制3D 散点图:

1
2
rgl.open() # 打开一个新的 RGL device
rgl.points(x, y, z, color ="lightgray") # 散点图

1

  • x, y, z:数值向量,指定要绘制的点的坐标。参数 y 和 z 在以下情况下是可选的:
  • x是包含至少 3 列的矩阵或数据框,将用作 x、y 和 z 坐标。例如:rgl.points(iris)
  • x是 zvar ~ xvar + yvar 形式的公式(参阅 ?xyz.coords )。例如:rgl.points(z ~ x + y)
  • …:材料特性。有关详细信息,请参阅 ?rgl.material

更改背景和点颜色

  • 函数rgl.bg(color)可用于设置场景的背景环境
  • 参数 color 在函数rgl.points()中用于更改点颜色

也可以使用参数 size 更改点的大小

1
2
3
rgl.open()# 打开一个新的 RGL device
rgl.bg(color = "white") # 设置背景颜色
rgl.points(x, y, z, color = "blue", size = 5) # 散点图

2

上述3d 界面的函数是:

  • open3d() : 打开一个新的 3D 设备
  • bg3d(color) : 设置场景的背景环境
  • points3d(x, y, z, ...) : 坐标 x, y, z 的绘图点

改变点的形状

可以使用函数rgl.spheres()spheres3d()绘制球体:

1
2
spheres3d(x, y = NULL, z = NULL, radius = 1, ...)
rgl.spheres(x, y = NULL, z = NULL, r, ...)

rgl.spheres()绘制具有中心 (x, y, z) 和半径 r 的球体。

  • x, y, z :指定每个球体中心坐标的数值向量。
    参数 y 和 z 在以下情况下是可选的:
  • x 是包含至少 3 列的矩阵或数据框,将用作 x、y 和 z 坐标。
    例如:rgl.spheres(iris, r = 0.2)
  • x 是 zvar ~ xvar + yvar 形式的公式(参见 ?xyz.coords)。
    例如:rgl.spheres(z ~ x + y, r = 0.2)
  • radius:表示球体半径的向量或单个值
  • …:材料属性。 有关详细信息,请参阅 ?rgl.material
1
2
3
rgl.open()# 打开一个新的 RGL device
rgl.bg(color = "white") # 设置背景颜色
rgl.spheres(x, y, z, r = 0.2, color = "grey")

3

可以通过按住鼠标或触摸板手动旋转rgl图。
也可以使用鼠标上的滚轮或使用 PC 上的触摸板
或 Mac 上的两个手指(向上或向下)按 ctrl + 进行缩放。

rgl_init():用于初始化 RGL 设备的自定义函数

如果请求或没有打开的设备,函数 rgl_init() 将创建一个新的 RGL 设备:

1
2
3
4
5
6
7
8
9
10
11
12
#' @param new.device 一个逻辑值。如果为 TRUE,则创建一个新设备
#' @param bg 设备的背景颜色
#' @param width 设备的宽度
rgl_init <- function(new.device = FALSE, bg = "white", width = 640) {
if( new.device | rgl.cur() == 0 ) {
rgl.open()
par3d(windowRect = 50 + c( 0, 0, width, width ) )
rgl.bg(color = bg )
}
rgl.clear(type = c("shapes", "bboxdeco"))
rgl.viewpoint(theta = 15, phi = 20, zoom = 0.7)
}

使用的 RGL 函数说明:

  • rgl.open(): 打开一个新设备
  • rgl.cur(): 返回活动设备 ID
  • par3d(windowRect): 设置窗口大小
  • rgl.viewpoint(theta, phi, fov, zoom): 设置视点。 参数 theta 和 phi 是极坐标。
  • thetaphi 是极坐标。 默认值分别为 0 和 15
  • fov 是以度为单位的视场角。 默认值为 60
  • zoom 是缩放系数。 默认值为 1
  • rgl.bg(color): 定义设备的背景颜色
  • rgl.clear(type):从指定堆栈中清除场景(“shapes”、“lights”、“bboxdeco”、“background”)

在上面的R 代码中,使用函数 rgl.viewpoint() 自动设置视点方向和缩放。RGL设备是交互式的,您可以使用鼠标调整视点和缩放绘图。

添加边界框装饰

使用函数rgl.bbox()

1
2
3
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow") # 散点图
rgl.bbox(color = "#333377") # 添加边界框装饰

4

函数rgl.bbox()的简化格式是:

1
rgl.bbox(xlen=5, ylen=5, zlen=5, marklen=15.9, ...)
  • xlen、ylen、zlen:分别指定 x、y 和 Z 轴上刻度线数量的值
  • marklen : 指定刻度线长度的值
  • …:其他 rgl 材料属性(参见?rgl.material)包括:
  • color : 颜色向量。第一种颜色用于边界框的背景颜色。第二种颜色用于刻度线标签。
  • emission, specular, shininess: 光照计算的属性
  • alpha : 指定颜色透明度的值。该值应介于 0.0(完全透明)和 1.0(不透明)之间
1
2
3
4
5
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow")
# Add bounding box decoration
rgl.bbox(color=c("#333377","black"), emission="#333377",
specular="#3333FF", shininess=5, alpha=0.8 )

5

添加轴线和标签

函数rgl.lines(x, y = NULL, z = NULL, ...)可用于添加轴线。
函数rgl.texts(x, y = NULL, z = NULL, text)用于添加轴标签

对于函数rgl.lines(),参数 x、y 和 z 是长度为 2 的数值向量(即: x = c(x1,x2), y = c(y1, y2), z = c(z1 , z2) )

  • 值 x1、y1 和 y3 是线起点的3D 坐标
  • x2、y2 和 y3 的值对应于线终点的3D 坐标

参数x可以是矩阵或数据框,其中至少包含 3 列分别对应于 x、y 和 z 坐标。在这种情况下,参数y和z可以省略

要绘制轴,应该将轴的范围(最小值和最大值)指定给函数rgl.lines()

1
2
3
4
5
6
7
# 制作散点图
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow")
# 添加 x、y 和 z 轴
rgl.lines(c(min(x), max(x)), c(0, 0), c(0, 0), color = "black")
rgl.lines(c(0, 0), c(min(y),max(y)), c(0, 0), color = "red")
rgl.lines(c(0, 0), c(0, 0), c(min(z),max(z)), color = "green")

6

上图可以看到轴已绘制,但问题是它们不在点 c(0, 0, 0) 处相交

有两种解决方案来处理这种情况:

  • 扩展数据以使事情变得简单。变换 x、y 和 z 变量,使它们的 min = 0 和 max = 1
  • 使用 c(-max, +max) 作为轴的范围

缩放数据

1
2
3
x1 <- (x - min(x))/(max(x) - min(x))
y1 <- (y - min(y))/(max(y) - min(y))
z1 <- (z - min(z))/(max(z) - min(z))
1
2
3
4
5
6
7
# 制作散点图
rgl_init()
rgl.spheres(x1, y1, z1, r = 0.02, color = "yellow")
# 添加 x、y 和 z 轴
rgl.lines(c(0, 1), c(0, 0), c(0, 0), color = "black")
rgl.lines(c(0, 0), c(0,1), c(0, 0), color = "red")
rgl.lines(c(0, 0), c(0, 0), c(0,1), color = "green")

7

使用 c(-max, max)

让我们定义一个辅助函数来计算轴限制:

1
lim <- function(x){c(-max(abs(x)), max(abs(x))) * 1.1}
1
2
3
4
5
6
7
# 制作散点图
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow")
# 添加 x、y 和 z 轴
rgl.lines(lim(x), c(0, 0), c(0, 0), color = "black")
rgl.lines(c(0, 0), lim(y), c(0, 0), color = "red")
rgl.lines(c(0, 0), c(0, 0), lim(z), color = "green")

8

rgl_add_axes():添加 x、y 和 z 轴的自定义函数

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
# x, y, z : 对应点坐标的数值向量
#axis.col : 轴颜色
# xlab, ylab, zlab: 轴标签
# show.plane : 添加轴平面
# show.bbox : 添加边界框装饰
# bbox.col:边界框颜色。 第一种颜色是背景色; 第二种颜色是刻度线的颜色
rgl_add_axes <- function(x, y, z, axis.col = "grey",
xlab = "", ylab="", zlab="", show.plane = TRUE,
show.bbox = FALSE, bbox.col = c("#333377","black"))
{

lim <- function(x){c(-max(abs(x)), max(abs(x))) * 1.1}
# 添加轴
xlim <- lim(x); ylim <- lim(y); zlim <- lim(z)
rgl.lines(xlim, c(0, 0), c(0, 0), color = axis.col)
rgl.lines(c(0, 0), ylim, c(0, 0), color = axis.col)
rgl.lines(c(0, 0), c(0, 0), zlim, color = axis.col)

# 在每个轴的末端添加一个点以指定方向
axes <- rbind(c(xlim[2], 0, 0), c(0, ylim[2], 0),
c(0, 0, zlim[2]))
rgl.points(axes, color = axis.col, size = 3)

# 添加轴标签
rgl.texts(axes, text = c(xlab, ylab, zlab), color = axis.col,
adj = c(0.5, -0.8), size = 2)

# 添加平面
if(show.plane)
xlim <- xlim/1.1; zlim <- zlim /1.1
rgl.quads( x = rep(xlim, each = 2), y = c(0, 0, 0, 0),
z = c(zlim[1], zlim[2], zlim[2], zlim[1]))

# 添加边界框装饰
if(show.bbox){
rgl.bbox(color=c(bbox.col[1],bbox.col[2]), alpha = 0.5,
emission=bbox.col[1], specular=bbox.col[1], shininess=5,
xlen = 3, ylen = 3, zlen = 3)
}
}
  • 函数rgl.texts(x, y, z, text)用于向 RGL plot 添加文本。
  • rgl.quads(x, y, z)用于添加平面。x、y 和 z 是长度为 4 的数值向量,指定四边形的四个节点的坐标。
1
2
3
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "blue")
rgl_add_axes(x, y, z)

9

显示刻度:刻度线

函数axis3d()可以如下使用:

1
2
3
4
5
6
7
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow")
rgl_add_axes(x, y, z)
# 显示刻度线
axis3d('x', pos=c( NA, 0, 0 ), col = "darkgrey")
axis3d('y', pos=c( 0, NA, 0 ), col = "darkgrey")
axis3d('z', pos=c( 0, 0, NA ), col = "darkgrey")

10

添加边界框装饰更容易:

1
2
3
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow")
rgl_add_axes(x, y, z, show.bbox = TRUE)

11

设置 x、y 和 z 轴的纵横比

在上图中,边界框显示为矩形。所有坐标都以相同的比例显示(iso-metric)。

函数 aspect3d(x, y = NULL, z = NULL) 可用于设置当前绘图的 x、y 和 z 轴的表观比率。

x、y 和 z 分别是 x、y 和 z 轴的比率。x 可以是长度为 3 的向量,指定 3 个轴的比率。

如果比率为 (1, 1, 1),则边界框将显示为立方体。

1
2
3
4
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow")
rgl_add_axes(x, y, z, show.bbox = TRUE)
aspect3d(1,1,1)

12

比率的值可以设置为更大或更小以在给定轴上缩放:

1
2
3
4
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "yellow")
rgl_add_axes(x, y, z, show.bbox = TRUE)
aspect3d(2,1,1) # 在 x 轴上缩放

13

按组更改点的颜色

辅助函数可用于为每个组自动选择颜色:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 获取因子变量不同级别的颜色
# @param groups 包含观察组的因子变量
# @param colors 包含要使用的默认颜色名称的向量

get_colors <- function(groups, group.col = palette()){
groups <- as.factor(groups)
ngrps <- length(levels(groups))
if(ngrps > length(group.col))
group.col <- rep(group.col, ngrps)
color <- group.col[as.numeric(groups)]
names(color) <- as.vector(groups)
return(color)
}

按组更改颜色:

1
2
3
4
5
rgl_init()
rgl.spheres(x, y, z, r = 0.2,
color = get_colors(iris$Species))
rgl_add_axes(x, y, z, show.bbox = TRUE)
aspect3d(1,1,1)

14

使用自定义颜色:

1
2
3
4
5
cols <- get_colors(iris$Species, c("#999999", "#E69F00", "#56B4E9"))
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = cols)
rgl_add_axes(x, y, z, show.bbox = TRUE)
aspect3d(1,1,1)

15

也可以使用RColorBrewer包中的调色板:

1
2
3
4
5
6
library("RColorBrewer")
cols <- get_colors(iris$Species, brewer.pal(n=3, name="Dark2") )
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = cols)
rgl_add_axes(x, y, z, show.bbox = TRUE)
aspect3d(1,1,1)

16

改变点的形状

RGL 包中有 6 个网格对象,可用作点形状:

  • cube3d()
  • tetrahedron3d()
  • octahedron3d()
  • icosahedron3d()
  • dodecahedron3d()
  • cuboctahedron3d()

17

要使用上面的对象进行绘图,可以使用函数shapelist3d()如下:

1
shapelist3d(shapes, x, y, z)
  • shapes:单个 shape3d(例如:shapes = cube3d()
    对象或它们的列表(例如:shapes = list(cube3d(), icosahedron3d())
  • x, y, z:要绘制的点的坐标
1
2
3
4
5
rgl_init()
shapelist3d(tetrahedron3d(), x, y, z, size = 0.15,
color = get_colors(iris$Species))
rgl_add_axes(x, y, z, show.bbox = TRUE)
aspect3d(1,1,1)

18

添加一个椭圆的浓度

函数ellipse3d()用于估计浓度椭圆。一个简化的格式是:

1
2
ellipse3d(x, scale = c(1,1,1), centre = c(0,0,0), 
level = 0.95, ...)
  • x : x、y 和 z 之间的相关或协方差矩阵
  • scale:如果 x 是相关矩阵,则可以在 scale 参数中给出每个参数的标准差。这默认为 c(1, 1, 1),因此不会进行重新缩放。
  • center:椭圆的中心将在这个位置。
  • level:置信区域的置信水平。这用于控制椭球的大小。

ellipse3d() 函数返回一个 mesh3d 类的对象,可以使用函数 shade3d() 和/或 Wired3d() 绘制

  1. 使用函数shade3d()绘制椭圆:
1
2
3
4
5
6
7
8
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = TRUE)
# 计算并绘制浓度椭圆
ellips <- ellipse3d(cov(cbind(x,y,z)),
centre=c(mean(x), mean(y), mean(z)), level = 0.95)
shade3d(ellips, col = "#D95F02", alpha = 0.1, lit = FALSE)
aspect3d(1,1,1)

19

  1. 使用函数wired3d()绘制椭圆:
1
2
3
4
5
6
7
8
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = TRUE)
# 计算并绘制浓度椭圆
ellips <- ellipse3d(cov(cbind(x,y,z)),
centre=c(mean(x), mean(y), mean(z)), level = 0.95)
wire3d(ellips, col = "#D95F02", lit = FALSE)
aspect3d(1,1,1)

20

  1. 结合shade3d()wired3d()
1
2
3
4
5
6
7
8
9
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = TRUE)
# 计算并绘制浓度椭圆
ellips <- ellipse3d(cov(cbind(x,y,z)),
centre=c(mean(x), mean(y), mean(z)), level = 0.95)
shade3d(ellips, col = "#D95F02", alpha = 0.1, lit = FALSE)
wire3d(ellips, col = "#D95F02", lit = FALSE)
aspect3d(1,1,1)

21

  1. 为每个组添加椭圆
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Groups
groups <- iris$Species
levs <- levels(groups)
group.col <- c("red", "green", "blue")
# 绘制观察结果
rgl_init()
rgl.spheres(x, y, z, r = 0.2,
color = group.col[as.numeric(groups)])
rgl_add_axes(x, y, z, show.bbox = FALSE)
# 计算每个组的椭圆
for (i in 1:length(levs)) {
group <- levs[i]
selected <- groups == group
xx <- x[selected]; yy <- y[selected]; zz <- z[selected]
ellips <- ellipse3d(cov(cbind(xx,yy,zz)),
centre=c(mean(xx), mean(yy), mean(zz)), level = 0.95)
shade3d(ellips, col = group.col[i], alpha = 0.1, lit = FALSE)
# 显示组标签
texts3d(mean(xx),mean(yy), mean(zz), text = group,
col= group.col[i], cex = 2)
}
aspect3d(1,1,1)

22

回归平面

函数planes3d()rgl.planes()可用于将回归平面添加到 3D rgl 图中:

1
2
rgl.planes(a, b = NULL, c = NULL, d = 0, ...)
planes3d(a, b = NULL, c = NULL, d = 0, ...)

planes3d()rgl.planes()使用参数ax + by + cz + d = 0绘制平面。

  • a, b, c : 平面法线的坐标
  • d : 偏移坐标

使用示例:

1
2
3
4
5
6
7
8
9
10
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = FALSE)
aspect3d(1,1,1)
# Linear model
fit <- lm(z ~ x + y)
coefs <- coef(fit)
a <- coefs["x"]; b <- coefs["y"]; c <- -1
d <- coefs["(Intercept)"]
rgl.planes(a, b, c, d, alpha=0.2, color = "#D95F02")

23

上面的回归平面非常难看。让我们尝试做一个自定义的。遵循以下步骤:

  1. 使用函数 lm() 计算线性回归模型:ax + by + cz + d = 0
  2. 使用参数rgl.surface()添加回归曲面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = FALSE)
aspect3d(1,1,1)
# 计算线性回归(y = ax + bz + d)
fit <- lm(y ~ x + z)
# 预测常规 xz 网格上的值
grid.lines = 26
x.pred <- seq(min(x), max(x), length.out = grid.lines)
z.pred <- seq(min(z), max(z), length.out = grid.lines)
xz <- expand.grid( x = x.pred, z = z.pred)
y.pred <- matrix(predict(fit, newdata = xz),
nrow = grid.lines, ncol = grid.lines)
# 添加回归曲面
rgl.surface(x.pred, z.pred, y.pred, color = "steelblue",
alpha = 0.5, lit = FALSE)
# 添加网格线
rgl.surface(x.pred, z.pred, y.pred, color = "black",
alpha = 0.5, lit = FALSE, front = "lines", back = "lines")

24

创建 RGL 场景的动图

函数movie3d()可以按如下方式使用:

1
movie3d(f, duration, dir = tempdir(), convert = TRUE)
  • f 使用 spin3d(axis) 创建的函数
  • axis:所需的旋转轴。默认值为 c(0, 0, 1)。
  • duration : 动画的持续时间
  • dir : 为电影的每一帧创建临时文件的目录
  • convert:如果为 TRUE,则尝试将帧转换为单个 GIF 电影。它使用ImageMagick进行图像转换。

安装 ImageMagick(http://www.imagemagick.org/) 以便能够从 png 文件列表中创建电影。

1
2
3
4
5
6
7
8
9
10
11
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = TRUE)
# 计算并绘制浓度椭圆
ellips <- ellipse3d(cov(cbind(x,y,z)),
centre=c(mean(x), mean(y), mean(z)), level = 0.95)
wire3d(ellips, col = "#D95F02", lit = FALSE)
aspect3d(1,1,1)
# Create a movie
movie3d(spin3d(axis = c(0, 0, 1)), duration = 3,
dir = getwd())

25

将图像导出为 png 或 pdf

绘图可以保存为 png 或 pdf。

  • 函数rgl.snapshot()用于将屏幕截图保存为 png 文件:
1
rgl.snapshot(filename = "plot.png")
  • 函数rgl.postscript()用于将屏幕截图保存为ps、eps、tex、pdf、svg 或 pgf格式的文件:
1
rgl.postscript("plot.pdf",fmt="pdf")

使用示例:

1
2
3
4
5
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = T)
aspect3d(1,1,1)
rg.snapshot("plot.png")

将绘图导出为交互式 HTML 文件

函数writeWebGL()用于将当前场景写入 HTML:

1
writeWebGL(dir = "webGL", filename = file.path(dir, "index.html"))
  • dir : 写入文件的位置
  • filename : 用于主文件的文件名

下面的 R 代码写入场景的副本,然后将其显示在浏览器中:

1
2
3
4
5
6
7
8
9
10
rgl_init()
rgl.spheres(x, y, z, r = 0.2,
color = get_colors(iris$Species))
rgl_add_axes(x, y, z, show.bbox = FALSE)

# 这会将副本写入临时目录'webGL',然后显示它
browseURL(
paste("file://", writeWebGL(dir=file.path(tempdir(), "webGL"),
width=500), sep="")
)

在 RGL 场景中选择一个矩形

函数rgl.select3d()select3d()可用于选择3 维区域。

它们返回一个函数 f(x, y, z),该函数测试每个点 (x, y, z) 是否在所选区域中。

下面的 R 代码允许用户选择一些点,然后用不同的颜色重新绘制它们:

1
2
3
4
5
6
7
8
9
10
11
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = F)
aspect3d(1,1,1)
# Select a point
f <- select3d()
sel <- f(x,y,z)
rgl.clear("shapes")
# Redraw the points
rgl.spheres(x[!sel],y[!sel], z[!sel], r = 0.2, color = "#D95F02")
rgl.spheres(x[sel],y[sel], z[sel], r = 0.2, color = "green")

识别图中的点

使用函数identify3d()

1
identify3d(x, y = NULL, z = NULL, labels, n)

函数 identify3d() 的工作方式与基本图形中的 identify 函数类似。

下面的 R 代码,允许用户识别 5 个点:

1
2
3
4
5
6
rgl_init()
rgl.spheres(x, y, z, r = 0.2, color = "#D95F02")
rgl_add_axes(x, y, z, show.bbox = F)
aspect3d(1,1,1)
rgl.material(color = "blue")
identify3d(x, y, z, labels = rownames(iris), n = 5)

使用右键选择,中键退出。

R3D 界面

rgl包还包括一个更高级别的接口,称为 r3d 。该界面的设计更像是经典的 2D R 图形。

下一节将介绍如何使用 R3D 界面制作 3D 图形。

3D 散点图

使用函数plot3d()

1
2
3
4
5
6
7
8
9
10
## Default method
plot3d(x, y, z, xlab, ylab, zlab, type = "p", col,
size, lwd, radius, add = FALSE, aspect = !add, ...)
## Method for class 'mesh3d'
plot3d(x, xlab = "x", ylab = "y", zlab = "z",
type = c("shade", "wire", "dots"), add = FALSE, ...)
decorate3d(xlim, ylim, zlim,
xlab = "x", ylab = "y", zlab = "z",
box = TRUE, axes = TRUE, main = NULL, sub = NULL,
top = TRUE, aspect = FALSE, expand = 1.03, ...)
  • x, y, z:要绘制的点的向量。任何定义坐标的合理方式都是可以接受的。有关详细信息,请参阅函数 xyz.coords
  • xlab, yab, zlab : x, y 和 z 轴标签
  • type:
  • 对于默认方法:允许的值是:“p”表示点,“s”表示球体,“l”表示线,“h”表示从 z = 0 开始的线段,“n”表示无。
  • 对于 mesh3d 方法,“shade”、“wire”或“dots”之一
  • col : 用于绘制项目的颜色
  • size : 点的大小
  • lwd : 绘制项的线宽
  • radius : 球体的半径
  • add:是否将点添加到现有绘图中
  • aspect : 要么是一个逻辑的指示是否调整纵横比,要么是一个新的比例
  • …:将传递给 par3d、material3d 或 decorate3d 的附加参数
  • box, axes : 是否绘制框和轴。
  • main, sub : 主标题和副标题
  • top : 完成后是否将窗口置顶

建议使用函数 open3d() 来初始化 *3d 接口。但是,在以下 R 代码块中,我将继续使用自定义函数rgl_init()

画点:

1
2
rgl_init()
plot3d(x, y, z, col="blue", type ="p")

26

移除盒子并绘制球体:

1
2
3
rgl_init()
plot3d(x, y, z, col="blue", box = FALSE,
type ="s", radius = 0.15)

27

要删除坐标区,请使用参数axes = FALSE

轴标签:

1
2
3
4
rgl_init()
plot3d(x, y, z, col="blue", box = FALSE,
type ="s", radius = 0.15, xlab ="Sepal.Length",
ylab = "Petal.Length", zlab = "Sepal.Width")

28

添加浓度椭圆:

1
2
3
4
5
6
rgl_init()
plot3d(x, y, z, col="blue", box = FALSE,
type ="s", radius = 0.15)
ellips <- ellipse3d(cov(cbind(x,y,z)),
centre=c(mean(x), mean(y), mean(z)), level = 0.95)
plot3d(ellips, col = "blue", alpha = 0.2, add = TRUE, box = FALSE)

29

更改椭圆类型:参数类型的可能值= c(“shade”, “wire”, “dots”)

1
2
3
4
5
6
rgl_init()
plot3d(x, y, z, col="blue", box = FALSE,
type ="s", radius = 0.15)
ellips <- ellipse3d(cov(cbind(x,y,z)),
centre = c(mean(x), mean(y), mean(z)), level = 0.95)
plot3d(ellips, col = "blue", alpha = 0.5, add = TRUE, type = "wire")

30

bbox3d():添加边界框装饰

1
2
3
4
5
6
7
8
rgl_init()
plot3d(x, y, z, col="blue", box = FALSE,
type ="s", radius = 0.15)
# 添加边界框装饰
rgl.bbox(color=c("#333377","black"), emission="#333377",
specular="#3333FF", shininess=5, alpha=0.8, nticks = 3 )
# 更改轴纵横比
aspect3d(1,1,1)

31

一些重要的功能

  • open3d() : 打开一个新设备
  • 向当前场景添加一个形状:
  • points3d(x, y, z, …)
  • lines3d(x, y, z, …)
  • segments3d(x, y, z, …)
  • quads3d(x, y, z, …)
  • texts3d(x, y, z, text) : 添加文本
  • 绘制框、轴和其他文本:
  • axes3d() : 添加标准轴
  • title3d(main, sub, xlab, ylab, zlab) : 添加标题
  • box3d():在绘图周围绘制一个框
  • mtext3d() : 在绘图边距中放置文本

RGL 函数

下面列出了管理 RGL device 的一些重要功能:

设备管理

功能 描述
rgl.open() 打开一个新设备
rgl.close() 关闭当前设备
rgl.cur() 返回活动设备的 ID
rgl.dev.list() 返回所有设备 ID
rgl.set(which) 将设备设置为活动
rgl.quit() 关闭 RGL 设备系统

形状函数

将形状节点添加到当前场景。

功能 描述
rgl.points(x, y, z, …) 在 x、y 和 z 处绘制一个点
rgl.lines(x, y, z, …) 根据顶点对绘制线段 (x = c(x1,x2), y = c(y1,y2), z = c(z1, z2))
rgl.triangles(x, y, z, …) 用节点 (xi, yi, zi) 绘制三角形,i = 1, 2, 3
rgl.quads(x, y, z) 用节点 (xi, yi, zi) 绘制四边形,i = 1, 2, 3, 4
rgl.spheres(x, y, z, r, …) 绘制具有中心 (x, y, z) 和半径 r 的球体
rgl.texts(x, y, z, text, …) 向场景中添加文本
rgl.surface(x, y, z, …) 将表面添加到当前场景。x 和 y 是定义网格的两个向量。z 是定义每个网格点高度的矩阵

场景管理

功能 描述
rgl.clear(类型=“形状”) 从指定堆栈中清除场景(“shapes”、“lights”、“bboxdeco”、“background”)
rgl.pop(类型=“形状”) 从堆栈中删除最后添加的节点

设置环境

功能 描述
rgl.viewpoint(theta, phi, fov, zoom, …) 设置视点方向。theta和phi是极坐标。fov是以度为单位的视场角。缩放:缩放系数。
rgl.light(theta, phi, …) 向场景添加光源
rgl.bg(…) 设置场景的背景环境
rgl.bbox(…) 设置边界框装饰

外观设置

功能 描述
rgl.material(…) 设置几何外观的材料属性
方面3d(x,y,z) 设置 x、y 和 z 轴的纵横比

导出截图

功能 描述
rgl.snapshot(“plot.png”) 将屏幕截图保存为 png 文件
rgl.postscript(“plot.pdf”,fmt=“pdf”) 将屏幕截图保存为ps、eps、tex、pdf、svg 或 pgf格式的文件。

将焦点分配给 RGL 窗口

Rgl.bringtotop() : ‘rgl.bringtotop’ 将当前 RGL 窗口带到窗口堆栈的前面(并赋予它焦点)。

参考

Daniel Alder et al., RGL: A R-library for 3D visualization with OpenGL, http://rgl.neoscientists.org/arc/doc/RGL_INTERFACE03.pdf