写在前面

本文为 R 语言 rgl 包的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。软件可能随时更新,建议配合官方文档一起阅读。


::: block-1

目录

  • 1 介绍
  • 2 关于本文档
  • 3 基础和高级函数
  • 4 添加图形元素
  • 5 控制场景的外观
  • 6 网格:构建形状
  • 7 多图布局
  • 8 带有 rgl 场景的文档
  • 9 实用功能
  • 10 警告:工作正在进行中!
    :::
官网教程:https://dmurdoch.github.io/rgl/articles/rgl.html

1 介绍

rgl包用于生成交互式 3-D 绘图。它包含按照经典 R 图形松散建模的高级图形命令,但在三维上工作。它还包含受grid包启发(但不兼容)的低级结构。

本文档提供了概述。有关详细信息,请参阅帮助页面。

有关安装说明,请参阅源 tarball rgl_1.3.12.tar.gz(或更高版本)顶级目录中的README文件。

2 关于本文档

本文档是用 R Markdown 编写的,使用knit包进行生产。它对应于rgl版本1.3.12。

大多数突出显示的函数名称都是 HTML 链接。内部链接应该在任何浏览器中都有效;如果您从 R 帮助系统中查看小插图,则帮助主题的链接应该有效。

该文档包含 WebGL 图形。要查看这些,您必须在浏览器中启用 Javascript 和 WebGL。一些较旧的浏览器可能不支持此功能 - 请参阅https://get.webgl.org以获取测试和讨论链接。

3 基础和高级函数

plot3d函数在 RGL 窗口内绘制点(points)。它类似于经典的plot函数,但适用于 3 维。

例如

with(iris, plot3d(Sepal.Length, Sepal.Width, Petal.Length, 
                  type="s", col=as.numeric(Species)))

 title=

可用于绘制三列iris数据。允许的绘图类型包括"p", "l", "h", "s",表示点(points)、线(lines)、从 z=0 开始的线段(segments)、球体(spheres)。指定坐标有很大的灵活性;grDevices 包中的 xyz.coords 函数用于此目的。

您可以使用鼠标来操纵绘图。默认情况下,如果单击并按住鼠标左键,则可以通过拖动来旋转绘图。鼠标右键用于调整其大小,中键用于更改视点的视角。

如果再次调用plot3d,它将覆盖当前绘图。要打开新的图形窗口,请使用open3d

另一个高级函数是persp3d,用于绘制曲面(surfaces)。它与经典的persp函数类似,但具有更大的灵活性。首先,xyz 中的任何一个都可以使用矩阵来指定,而不仅仅是 z。这允许绘制参数化曲面。甚至可以有更简单的规范:x可能是一个函数,在这种情况下persp3d将计算出网格本身。有关详细信息,请参阅?persp3d.function。例如,MASS包在?MASS::fitdistr示例中使用最大似然估计 Gamma 参数。这里我们展示了对数似然曲面。

# This example requires the MASS package
library(MASS)
# from the fitdistr example
set.seed(123)
x <- rgamma(100, shape = 5, rate = 0.1)
fit <- fitdistr(x, dgamma, list(shape = 1, rate = 0.1), lower = 0.001)
loglik <- function(shape, rate) sum(dgamma(x, shape=shape, rate=rate, 
                                           log=TRUE))
loglik <- Vectorize(loglik)
xlim <- fit$estimate[1]+4*fit$sd[1]*c(-1,1)
ylim <- fit$estimate[2]+4*fit$sd[2]*c(-1,1)

mfrow3d(1, 2, sharedMouse = TRUE)
persp3d(loglik, 
        xlim = xlim, ylim = ylim,
        n = 30)
zlim <- fit$loglik + c(-qchisq(0.99, 2)/2, 0)
next3d()
persp3d(loglik, 
        xlim = xlim, ylim = ylim, zlim = zlim,
        n = 30)

左边是整个表面的一系列参数;右侧仅显示对数似然值接近最大值的表面部分。

注意:此示例使用knit钩子函数(请参阅setupKnit)将场景插入到此小插图中;前面的示例使用了rglwidget函数。我们通常推荐较新的rglwidget方法。

请注意,plot3dpersp3d都是通用函数,定义了以下方法:

methods(plot3d)
##  [1] plot3d.ashape3d*      plot3d.default*       plot3d.deldir*       
##  [4] plot3d.formula*       plot3d.function*      plot3d.lm*           
##  [7] plot3d.mesh3d*        plot3d.rglbackground* plot3d.rglbboxdeco*  
## [10] plot3d.rglobject*     plot3d.rglscene*      plot3d.rglsubscene*  
## [13] plot3d.rglWebGL*      plot3d.tri*           plot3d.triSht*       
## see '?methods' for accessing help and source code
methods(persp3d)
## [1] persp3d.ashape3d* persp3d.default*  persp3d.deldir*   persp3d.formula* 
## [5] persp3d.function* persp3d.tri*      persp3d.triSht*  
## see '?methods' for accessing help and source code

4 添加图形元素

4.1 原始形状

正如经典图形中的pointslines一样,rgl中有许多低级函数可以将图形元素添加到当前活动的绘图中。"primitive" 形状是 OpenGL 原生的形状:

FunctionDescription
points3d添加点
lines3d添加线
segments3d添加线段
triangles3d添加三角形
quads3d添加四边形

上述每个函数都接受参数 xyz,为了灵活性再次使用 xyz.coords。他们根据需要对连续的条目进行分组。例如,triangles3d函数将每个连续的三重点作为三角形的顶点。

您可以使用这些函数来注释当前图形,或从头开始构建图形。

4.2 构造形状

rgl还有许多从原始形状构造的对象。

FunctionDescription
text3d, texts3d添加文本
abclines3d添加直线来绘图(如 abline)
arc3d添加球弧或螺旋线来绘图
planes3d添加平面到绘图中
clipplanes3d添加剪裁平面来绘图
sprites3d, particles3d添加精灵(固定形状或图像)来绘图
spheres3d添加球体
surface3d, terrain3d表面(如 persp3d 中使用的)
drape3d在表面或物体上覆盖线条
shadow3d将网格(mesh)投影到表面(surface)上
arrow3d向场景添加箭头
pch3d绘制基本样式的绘图符号
plotmath3d由 text3d 用于数学文本

4.3 轴和其它装饰

以下低级函数控制图形的外观:

FunctionDescription
axes3d, axis3d添加坐标轴到绘图
box3d, bbox3d在图周围添加框
title3d添加标题到绘图
mtext3d添加边际文本到绘图
decorate3d添加多个“装饰”(scales 等)到绘图
aspect3d设置绘图的纵横比
bg3d, bgplot3d设置场景的背景
show2d在 3D 场景中显示 2D 绘图或图像
legend3d为场景设定一个图例
grid3d向图表添加参考网格
thigmophobe3d选择标签位置以避免重叠
setAxisCallbacks设置用户定义的轴注释

例如,要绘制三个随机三角形,可以使用

triangles3d(cbind(x=rnorm(9), y=rnorm(9), z=rnorm(9)), col = "green")
decorate3d()
bg3d("lightgray")
aspect3d(1,1,1)

除了上面提到的 *3d 函数之外,还有已弃用的函数 rgl.abclinesrgl.bboxrgl.bgrgl.clipplanesrgl.linesrgl.linestripsrgl.planesrgl.pointsrgl.primitivergl.Qquadsrgl.setAxisCallbackrgl.spheresrgl.spritesrgl.surfacergl.textsrgl.triangles。您应该避免使用所有这些函数,它们不能与 *3d 函数一起正常工作,并且很快就会从 rgl 中删除。有关详细信息,请参阅 ?r3d 帮助主题。

函数 rgl.getAxisCallbacksetAxisCallbacks 提供低级支持。

5 控制场景的外观

5.1 拍摄角度

默认情况下,当您使用 open3d 打开新绘图时:

  • x 轴从左到右。
  • y 轴从靠近相机到远处。
  • z 轴从下到上。

您只需用鼠标拖动图片即可更改相机角度。

要以编程方式设置相机角度,请使用 view3d。这使用极坐标:

  • theta 设置绕垂直轴的旋转(以度为单位)。
  • phi 设置绕水平轴的“垂直”旋转,范围为 -90 到 90 度。

默认角度大致为 theta = 0,phi = -70。从这个位置开始:

  • 当您增加 theta 时,从您的角度来看,图表将逆时针旋转。
  • 当您将 phi 增加到 0 时,您开始从顶部向下看场景。如果将 phi 增加到 0 以上,您将继续并开始从“背面”(并且颠倒)查看图表。

您还可以使用 observer3d 使用 x、y、z 坐标更改相机位置。特别是,增加 z 坐标可以缩小,减少 z 坐标可以放大。

一种有用的方法是使用鼠标找到一个合适的视角。然后您可以使用 par3d("userMatrix") 保存它并稍后恢复相同的视图:

myview <- par3d("userMatrix")
# ... later ...
par3d(userMatrix = myview)

5.2 灯光

在大多数场景中,对象都是“被照亮”的,这意味着它们的外观取决于它们相对于场景中灯光的位置和方向。灯光本身通常不会出现,但它们对物体的影响却会出现。

使用 light3d 函数指定灯光的位置和特征。灯光可能无限远,也可能嵌入场景中。它们的特征包括 ambient, diffuse, specular 成分,全部默认为白色。ambient 成分从任何方向看都是一样的。diffuse 分量取决于表面和光线之间的角度,而 specular 分量还考虑了观看者的位置。

不应再使用已弃用的 rgl.light 函数;使用 light3d 代替。

5.3 材质

rgl 中使用的心理模型是场景中显示的对象是空间中的物理对象,其材质属性会影响光从它们反射(或由它们发出)的方式。这些主要由 material3d 函数或传递给它的其他函数的参数控制。

在调用 material3d 时识别的材料属性在 ?material3d 帮助页面中有详细描述,并在 rgl.material.names 变量中列出。除了 rgl.material.readonly 中的之外,所有这些都可以设置。这里我们给出一个概述。

PropertyDefaultMeaning
colorwhite应用于 diffuse 光的连续顶点的表面颜色向量
alpha1透明度:0 为不可见,1 为不透明
litTRUE是否应该进行光照计算
ambientblack环境光下的颜色
specularwhite镜面光下的颜色
emissionblack表面发出的颜色
shininess50控制镜面照明:高值看起来有光泽
smoothTRUE是否应在顶点之间插入阴影
textureNULL要显示在表面上的“纹理”位图的可选路径
front, backfill多边形应该被填充还是轮廓?
size3size of points in pixels
lwd1width of lines in pixels

其他属性包括 “texmipmap”、“texmagfilter”、“texminfilter”、“texenvmap”、“fog”、“point_antialias”、“line_antialias”、“depth_mask”、“depth_test”、“polygon_offset”、“margin”、“floating” 、“tag” 和 “blend”;有关详细信息,请参阅帮助页面。

还有一个已弃用的 rgl.material 函数,它在较低级别上工作;用户应该避免它。

5.4 纹理

如上一节所述,材质属性之一是 texture,即包含要在表面上显示的图像的位图文件(.png 格式)的名称。本节提供有关 textures 的更多详细信息。

OpenGL 中,多边形中的每个顶点都可以与位图中的特定位置相关联。多边形的内部在位图中进行插值。rgl 函数中有两种约定用于指定这些坐标。

指定基元(triangles3d 等)的函数接受可选的矩阵参数 texcoords,它给出位图中的 s(水平)和 t(垂直)位置,以列为单位,每个顶点一行。左下角坐标为 (0,0),右上角坐标为 (1,1)。如果给出的值超出此范围,则图像会重复,即 (1.1, 1.2) 将图像中的同一点指定为 (0.1, 0.2)

其他函数(例如为每个顶点坐标采用矩阵的 surface3d)也接受纹理坐标作为矩阵,在参数 texture_stexture_t 中。

例如,以下代码在四边形上显示 2D 图的四个副本,因为 st 中的纹理坐标都从 0 到 2:

filename <- tempfile(fileext = ".png")
png(filename = filename)
plot(rnorm(1000), rnorm(1000))
safe.dev.off()

open3d()

xyz <- cbind(c(0,1,1,0), 0, c(0,0,1,1))
quads3d(xyz, texture = filename, texcoords = xyz[,c(1, 3)]*2, 
        col = "white", specular = "black")

其他一些注意事项:

  • 上面的 quads3d() 中的颜色被指定为白色。默认情况下,位图中的颜色将修改表面的颜色。如果 col 是黑色(常见的默认值),您将看不到任何内容,因此可能会发出警告。
  • 您通常不希望出现镜面反射(表现为眩光)。将 specular 设置为黑色可以防止这些情况发生。
  • 材质属性 "texmode" 允许以不同方式使用纹理颜色。默认值为"modulate",其中纹理值与基础值乘法组合。
  • 位图处理方式的另一个方面是由材质属性"textype"控制的。默认值为"rgb",它从位图中获取红-绿-蓝颜色,并使用它们来修改多边形中相应的颜色。
  • Material3d 帮助页面中描述了"textype""texmode"的其他可能性。
  • 其他"tex*"材质属性控制图像内插值的完成方式。
  • 现代 OpenGL 支持 1 维和 3 维纹理;rgl 目前不支持这些。

5.5 字体

rgl 使用与绘制文本的基本图形相同的想法:有名为"sans""serif""mono"的字体系列用于绘制这些类型的文本。在 rgl 中,不支持"symbol"系列。

新的字体系列可以使用低级函数 rglFonts 定义,或者更简单地使用高级函数 rglExtrafonts 定义。后一个功能需要安装 extrafont 软件包。

5.6 par3d:其他图形参数

par3d 函数以经典图形 par 函数为模型,设置或读取 rgl.par3d.names 变量中列出的各种不同的 rgl 内部参数。除了 rgl.par3d.readonly 中的之外,所有这些都可以设置。有些参数是完全只读的;其他的在窗口打开时是固定的,其他的可能随时更改。

NameChangeable?Description
antialiasfixed硬件抗锯齿量
cex 文本的默认大小
family 与设备无关的字体系列名称;参见 ?text3d
font 整数字体编号
useFreeType 如果有的话应该使用 FreeType 字体吗?
fontnameread-onlyrglFonts 设置的系统相关字体名称
FOV 视野,以度为单位。零表示等距透视
ignoreExtent rgl 在计算边界框时是否应该忽略新对象的大小?
skipRedraw rgl 应该抑制显示更新吗?
maxClipPlanesread-only可以定义多少个裁剪平面?
modelMatrixread-onlyOpenGL 模型视图矩阵;部分由 view3d 设置
projMatrixread-onlyOpenGL 投影矩阵
bboxread-only场景的当前边界框
viewport 窗口内场景的尺寸(以像素为单位)
windowRect 整个屏幕上窗口的尺寸(以像素为单位)
listeners 哪些子场景响应当前场景中的鼠标操作
mouseMode 鼠标按钮的作用。请参阅 "mouseMode"
observerread-only观察者的位置;由 observer3d 设置
scale 对每个坐标重新缩放;参见 aspect3d
zoom 场景放大

不应使用已弃用的 rgl.viewpoint 函数。

5.7 默认设置

r3dDefaults 列表和 getr3dDefaults 函数控制 open3d 打开的新窗口中的默认值。
该函数在用户的全局环境中查找该变量,如果没有找到,则在 rgl 命名空间中查找该变量。这允许用户覆盖新窗口的默认设置。

找到后,r3dDefaults 列表将提供 par3d 参数的初始值,以及组件 "material""bg" 中的 material3dbg3d 的默认值。

6 网格:构建形状

rgl 包含许多用于构造和显示各种实体形状的函数。它们生成"shape3d""mesh3d""shapelist3d"类的对象。类的详细信息如下所述。我们从生成它们的函数开始。

6.1 特定固体

这些函数生成特定的形状。可选参数允许指定颜色或变换等属性。

FunctionDescription
tetrahedron3d, cube3d, octahedron3d, dodecahedron3d, icosahedron3dPlatonic solids
cuboctahedron3d, oh3dother solids
cols <- rainbow(7)
layout3d(matrix(1:16, 4,4), heights=c(1,3,1,3))
text3d(0,0,0,"tetrahedron3d"); next3d()
shade3d(tetrahedron3d(col=cols[1])); next3d()
text3d(0,0,0,"cube3d"); next3d()
shade3d(cube3d(col=cols[2])); next3d()
text3d(0,0,0,"octahedron3d"); next3d()
shade3d(octahedron3d(col=cols[3])); next3d()
text3d(0,0,0,"dodecahedron3d"); next3d()
shade3d(dodecahedron3d(col=cols[4])); next3d()
text3d(0,0,0,"icosahedron3d"); next3d()
shade3d(icosahedron3d(col=cols[5])); next3d()
text3d(0,0,0,"cuboctahedron3d"); next3d()
shade3d(cuboctahedron3d(col=cols[6])); next3d()
text3d(0,0,0,"oh3d"); next3d()
shade3d(oh3d(col=cols[7]))

Rpolyhedra 包中包含非常多的多面体集合。

6.2 生成新形状

这些函数生成新的形状:

FunctionDescription
cylinder3d生成管子或圆柱体
polygon3d通过三角测量生成平面多边形
extrude3d生成多边形的“挤压”
turn3d生成旋转固体
ellipse3d以各种方式生成椭球体
mesh3d从索引顶点生成形状
shapelist3d通过组合其他形状生成一个形状
as.mesh3d通用函数;见下文

一个相关的函数是 triangulate,它采用二维多边形并使用“ear-clipping”算法将其分成三角形。

提供通用函数 as.mesh3d 来允许将其他代码生成的数据结构转换为网格结构。目前支持以下类:

ClassPackageDescription
deldirdeldir不规则点云的 Delaunay 三角剖分
triShtinterp也是 Delaunay 三角剖分
tritripack广义 Delaunay 三角剖分
ashape3dalphashape3dAlpha-shapes
rglIdrglrgl 对象标识符

checkDeldir 函数检查是否安装了 deldir 软件包的兼容版本。

默认的 as.mesh3d.default 方法是一种从顶点矩阵构造网格的简单方法;它可以使用 mergeVertices(也可以单独使用)来合并矩阵内的重复顶点,从而允许使用 addNormals 来提供平滑的外观。

as.tmesh3d 泛型是一种变体,可保证生成的对象不会有四边形条目。

函数 tmesh3dqmesh3d 现已过时;使用 mesh3d 代替。

6.3 形状的底层类结构

"shape3d" 是基本的抽象类型。此类的对象可以通过 shade3d(对面进行着色)、wire3d(绘制边)、或 dot3d(在每个顶点绘制点)来显示。

"mesh3d" 是后代类型。该类型的对象包含以下字段:

FieldMeaning
vb齐次坐标中的 4 x n 顶点矩阵。每列都是一个点
ip(可选)点的顶点索引向量
is(可选)顶点索引的 2 x s 矩阵。每列都是一条线段
it(可选)顶点索引的 3 x t 矩阵。每列都是一个三角形
ib(可选)顶点索引的 4 x q 矩阵。每列都是一个四边形
material(可选)材质属性列表
normals(可选)与 vb 形状相同的矩阵,包含每个顶点的法向量
texcoords(可选)与每个顶点对应的纹理坐标的 2 x n 矩阵
values(可选)长度为 n 的向量,在每个顶点保存值
meshColor(可选)一个文本值指示如何解释颜色和纹理坐标
tags(可选)由某些函数(例如 clipMesh3d)添加的向量,用于将输出部分与输入部分相关联

6.4 轮廓和剪裁形状

这些函数计算并绘制曲面上函数的轮廓,或沿函数的轮廓剪切对象。

FunctionDescription
contourLines3d在曲面上绘制轮廓线
filledContour3d填充曲面轮廓之间
clipMesh3d使用弯曲边界裁剪网格对象
clipObj3d使用弯曲边界裁剪一般对象

6.5 操纵形状

这些函数操作和修改网格对象:

FunctionDescription
addNormals添加法线向量以使形状看起来平滑
subdivision3d添加额外的顶点使其看起来更平滑
merge合并网格对象
facing3d面向“向上”的网格子集
getBoundary3d获取网格对象的边界

subdivision3d 中的各个步骤也可用:deform.mesh3ddivide.mesh3dnormalize.mesh3d。这些主要供内部使用。

7 多图布局

rgl 有几个函数支持在同一窗口中显示多个不同的“子场景”。高级功能是

FunctionDescription
mfrow3d多图(如 par("mfrow"))
layout3d多图(如 layout)
next3d移至下一个图(如 plot.new 或 frame)
subsceneList列出当前布局中的所有子场景
clearSubsceneList清除当前列表并恢复到上一个列表

还有一些较低级别的功能。

FunctionDescription
newSubscene3d创建一个新的子场景,对从父场景继承的内容进行精细控制
currentSubscene3d报告活动的子场景
subsceneInfo获取当前子场景的信息
useSubscene3d激活不同的子场景
addToSubscene3d, delFromSubscene3d将对象添加到子场景,或删除它们
gc3d进行“垃圾收集”:删除未在任何子场景中显示的对象

8 带有 rgl 场景的文档

rgl 包可以生成可嵌入其他文档中的输出。多年来,推荐的执行此操作的方法已多次更改。我们将从当前的建议开始,然后列出旧的方法。

8.1 推荐方法

目前,在文档中嵌入 rgl 场景的最佳方法是使用 R Markdown 生成 HTML 文档。在文档的前面,您应该在其中一个设置代码块中包含如下代码:

```{r echo=FALSE, include=FALSE}
library(rgl)
setupKnitr(autoprint = TRUE)
```

setupKnit() 的调用将在 knit 中安装许多钩子并设置选项,以便正确处理 rgl 代码。autoprint = TRUE 参数使 rgl 在文档中的行为几乎与在控制台中的行为相同,或者与 knit 处理基本图形的方式相同:如果打印高级 rgl 函数的值,则绘图将插入到输出,但可能只有在对其进行低级修改完成之后。例如,此代码块在最后的单个图中打印三角形和球体:

xyz <- matrix(rnorm(27), ncol = 3)
triangles3d(xyz, col = rainbow(9))
spheres3d(xyz, col = rainbow(9), radius = 0.1)

如果情况复杂,则存在一些差异:

  • 该机制取决于自动打印 rgl 函数调用的结果。如果调用位于循环或其他不会发生自动打印的代码块中,则您将需要一些技巧来打印内容。例如,这将打印三个图:
foreignHigh()   # Produces a high level plot, but doesn't return
                # an appropriate value
highlevel()
foreignLow()    # Modifies the previous plot
lowlevel()

当假设修改完成时,这应该在代码块的末尾显示输出。

8.2 生成 PDF 输出

虽然某些 PDF 预览器支持交互式 3D 图形,但大多数不支持。要在具有 PDF 输出的 R Markdown 文档中生成 rgl 场景的屏幕截图,只需按照上面给出的说明进行操作即可。自动打印将检测 PDF 输出并使用 snapshot3d 生成要插入的 PNG 文件。(如果您想插入不同格式的图形,请参见下文。)

如果您确实需要交互式输出,请参阅 writeASY 函数。

8.3 手动插入图

您可能不想使用上述 setupKnit(autoprint = TRUE) 方法。它非常新,可能仍然存在错误;您可能有一个较旧的文档,但不想对其进行编辑以使其正常工作。

在这种情况下,您可以手动插入绘图。使用设置代码

```{r echo=FALSE, include=FALSE}
library(rgl)
setupKnitr()
```

并在您想要插入绘图时在顶层调用 rglwidget()

如果您不使用 autoprint,默认行为还有一些其他差异:

  • 默认情况下,每个代码块都会延续前面代码块的 rgl 场景。您需要显式的 open3d 调用才能获得干净的窗口。
  • 同样默认情况下,rgl 窗口在代码块末尾不会关闭。这可能并不重要,但如果场景很大,您可能会发现内存不足。

8.4 较旧的方法

在文档中插入 rgl 场景的原始方法是使用已弃用的 writeWebGL 函数编写 HTML 代码以插入到文档中。后来又添加了 Sweaveknitr hooks。这些不再受支持,您应该更新旧文档以使用较新的方法。如果您正在阅读建议使用这些方法的文档,请让作者知道它们需要更新!

9 实用功能

9.1 用户交互

默认情况下,rgl 检测并处理场景中的鼠标单击,并使用这些来控制其外观。您可以使用以下代码找出当前的处理程序:

par3d("mouseMode")
##        none        left       right      middle       wheel 
##      "none" "trackball"      "zoom"       "fov"      "pull"

标签 c("left", "right", "middle") 指的是三键鼠标上的按钮,或其他鼠标上的模拟按钮。"wheel"是指鼠标滚轮,"none"是指在不按任何按钮的情况下移动鼠标时发生的操作。

按钮操作通常对应于单击和拖动操作。鼠标指针或滚轮的"mouseMode"的可能值如下:

ModeDescription
"none"No action
"trackball"鼠标充当虚拟轨迹球。单击并拖动可旋转场景
"xAxis", "yAxis", "zAxis"类似于 "trackball",但仅限于绕一个轴旋转
"polar"鼠标通过直接控制极坐标来影响旋转
"selecting"select3d 函数正在使用鼠标
"zoom"鼠标缩放显示
"fov"鼠标通过改变视野来影响视角
"pull"朝用户方向旋转鼠标滚轮“拉近场景”
"push"同样的旋转“把场景推开”
"user"通过 setUserCallbacks、rgl.setMouseCallbacks、rgl.setWheelCallback 设置的用户操作。使用 rgl.getMouseCallbacks 和 rgl.getWheelCallback 进行检索

以下功能使用鼠标在场景内进行选择。

FunctionDescription
identify3d像经典的图形识别功能
select3d返回一个测试坐标是否被选择的函数
selectpoints3d从特定对象中选择
hover3d显示有关点的“悬停”信息

SelectionFunction3d 根据有关投影和鼠标选择区域的信息生成选择函数;它在上述函数内部使用。

已弃用的 rgl.select3d 函数是 select3d 的过时版本,rgl.select 是低级支持函数。

9.2 动画

rgl 有几个可用于构造动画的函数。这些基于根据当前现实世界时间更新场景的函数,以及对这些函数的重复调用。其功能是:

FunctionDescription
play3d反复调用更新函数
spin3d通过以恒定速率旋转来更新显示
par3dinterp通过随时间的插值计算一些 par3d 参数的新值

有关将动画输出到磁盘上文件的方法,请参阅 movie3d 函数。

尽管 playwidget 函数提供了等效的功能,但 rglwidget 编写的 HTML 目前不支持动画。

9.3 与 TCL/TK 集成

rgl 中有三个函数支持使用 TCL/TK 框架控制 rgl 场景。

FunctionDescription
tkspin3d在窗口中设置按钮来控制场景
tkspinControl将控制按钮嵌入单独的 TCL/TK 框架中
tkpar3dsave创建一个对话框以交互方式保存鼠标操作

这些函数以前包含在 tkrgl 包中(其名称中没有 tk 前缀)。该软件包现已被弃用。

9.4 导出和导入场景

rgl 包含多个将场景写入磁盘以供其他软件使用或将其读入的函数。

按照从最高保真度到最低保真度的顺序,这些函数是:

FunctionDescription
scene3d将场景保存到 R 变量,可以保存和重新加载
rglwidget以 HTML 和 Javascript 形式打印以在 Web 浏览器中显示场景(另请参阅 WebGL 中的用户交互)
writeASY为 Asymptote 编写文件
writePLY写入 PLY 文件(常用于 3D 打印)
readOBJ, writeOBJ读取或写入 OBJ 文件(常用于 3D 图形)
readSTL, writeSTL读取或写入 STL 文件(在 3D 打印中也很常见)
as.rglscene通用函数,rgl 中没有方法

rgl2gltf 包可以读取或写入 GLTF 和 GLB 文件。它包括一个 as.rglscene 方法,用于将 GLTF 对象转换为 rgl 场景。rglBuffer R6 类中的代码基于 GLTF 格式。rglwidget 使用它来使输出网页比以前小一些。

还有一些功能可以保存场景的快照或其他记录,而不保存任何 3D 信息:

FunctionDescription
snapshot3d保存场景的 PNG 文件位图
rgl.postscript保存场景的 Postscript、LaTeX、PDF、SVG 或 PGF 矢量渲染
movie3d保存一系列位图以组合成电影
rgl.pixels在 R 变量中获取有关场景的像素级信息
rgl.Sweave用于将快照插入 Sweave 文档的驱动程序功能
hook_rgl, hook_webglknitr 钩子函数用于将图像插入到文档中
setupKnitr设置 knitr 钩子的功能

rgl.snapshot 函数是 snapshot3d() 的低级版本;它要求 rgl 显示在屏幕上并从那里进行复制。snapshot3d() 尝试使用 webshot2 包,因此即使没有显示它也能工作。函数 rgl.Sweave.offSweave.snapshot 涉及 Sweave 处理,通常不被用户调用。

9.5 默认显示

在 R 中,通常有两种方式显示 rgl 场景。较旧的方式是在专用窗口中显示。在类似 Unix 的系统中,这是一个 X11 窗口;在 Microsoft Windows 中,这是一个本机窗口。在 macOS 上,需要安装 XQuartz 系统(请参阅 https://www.xquartz.org)才能支持此功能。

要禁止显示此内容,请在打开新的 rgl 窗口之前设置 options(rgl.useNULL = TRUE)。请参阅 rgl.useNULL 函数的帮助页面,了解如何在启动 R 之前设置此选项。

显示场景的较新方式是在浏览器窗口或 RStudio 中的查看器窗格中使用 WebGL。要选择此选项,请设置 options(rgl.printRglwidget = TRUE)。每个会更改场景的操作都会返回一个值,该值在打印时会触发新的 WebGL 显示。

9.6 使用 WebGL 场景

您应该使用以下方案将场景导出到网页。还有一个旧方案,不再受支持。

推荐的方法适用于 htmlwidgets 框架(请参阅 http://www.htmlwidgets.org/)。在 knit 中的 R Markdown 文档中,使用 rglwidget 函数。(您还可以使用块选项 webgl=TRUE;我们建议显式使用 rglwidget。)此方法还允许在 RStudio 中显示 rgl 场景。除了 rgl 场景之外,还可以显示它们的各种控件,并且有一些有用的实用函数:

FunctionDescription
propertyControlset individual properties
clipplaneControlcontrol a clipping plane
subsetControlcontrol which objects are displayed
ageControl“age” vertices of an object
vertexControlcontrol properties of vertices
par3dinterpControlWebGL control like par3dinterp
playwidgetdisplay and automate controls
toggleWidgetdisplay a button to toggle some items
%>%magrittr pipe
figHeight, figWidthDimensions of figures in R Markdown document
rglSharedshare data using crosstalk package
rglMousechange mouse mode in RGL scene
asRowarrange multiple objects in an HTML display
getWidgetIdget the elementId from a widget

这些函数与 Shiny 应用程序中的上述方案配合使用:

FunctionDescription
sceneChangeused in Shiny for large scene changes
shinyGetPar3d, shinySetPar3dget or set par3d values from Shiny
shinyResetBrushreset the mouse brush in Shiny

使用 Shiny 时,selectionFunction3d 函数也可能涉及鼠标交互。

一些函数主要供内部使用:elementId2PrefixplaywidgetOutputrenderPlaywidgetrglwidgetOutputrenderRglwidgetregisterSceneChange。更多详细信息请参阅 WebGL 中的用户交互。函数 lowlevelhighlevelrglId 也供内部使用,标记函数结果以便自动打印。最后,函数 setUserShaders 允许您在 WebGL 中使用手写着色器,而 getShaders 允许您查看将使用哪个着色器。

9.7 使用场景

rgl 维护它显示的所有场景的内部结构。以下功能允许用户查找有关它们的信息并对其进行操作。如果同时存在 *3drgl.* 版本的函数,大多数用户应使用 *3d 版本:rgl.* 函数更原始,主要供内部使用。

FunctionDescription
open3dopen a new window
close3dclose the current window
cur3did of the active device
set3dset a particular device to be active
pop3ddelete objects from the scene
clear3ddelete all objects of certain classes
ids3dids, types and tags of current objects
tagged3dfind tags or objects with tags

为了向后兼容,其中一些函数具有备用名称:

rgl.currgl.idsrgl.pop。任一名称都可以,但建议新代码使用 *3d 版本。有些版本已弃用:rgl.clearrgl.set。那些不应该被调用。

这些函数主要用于编程,没有相应的 *3d 对应函数:

FunctionDescription
rgl.bringtotopbring the current window to the top
rgl.dev.listids of all active devices
rgl.attrib, rgl.attrib.info, rgl.attrib.countattributes of objects in the scene
rgl.projectionreturn information about the current projection
rgl.user2window, rgl.window2userconvert between coordinates in the current projection

as.triangles3d 通用函数旨在以适合传递给 triangles3d 的形式提取坐标。目前为 rglId 对象提供了一种方法。

除此之外,还有一些不建议调用的函数:rgl.initrgl.openrgl.closergl.quit

9.8 使用 3-D 矢量

大多数 rgl 函数在内部使用“齐次”坐标工作。在该系统中,3D 点用 4 个坐标表示,通常称为 (x, y, z, w)。如果 w 非零,则对应的欧几里德点为 (x/w, y/w, z/w);w 的零值对应于“无穷远点”。该系统的优点是仿射变换(包括平移和透视移位)通过乘以 4 x 4 矩阵而变成线性变换。

rgl 具有以下用于处理齐次坐标的函数:

FunctionDescription
asEuclidean, asHomogeneousconvert between homogeneous and Euclidean coordinates when x, y and z are columns
asEuclidean2, asHomogeneous2convert when x, y and z are rows
rotate3d, scale3d, translate3dapply a transformation
transform3dapply a general transformation
rotationMatrix, scaleMatrix, translationMatrixcompute the transformation matrix
identityMatrixreturn a 4 x 4 identity matrix
projectDowna 3D to 2D projection down a vector

还有一个函数 GramSchmidt,主要供内部使用:它对 3x3 矩阵进行 Gram-Schmidt 正交化,并对其在 cylinder3d 中使用进行了一些专门化。

9.9 与其他包一起使用

有时,以交互方式将场景旋转到特定视图,然后以 lattice 或基础图形显示它可能会很方便。rglToLatticerglToBase 函数支持这一点。

例如,我们首先在 rgl 中显示 volcano 数据:

persp3d(volcano, col = "green")

该显示是交互式的,但我们可以使用 lattice wireframe 或基本图形 persp 函数重现初始视图:

# Only evaluated if the lattice & orientlib packages are installed
lattice::wireframe(volcano, col = "green", screen = rglToLattice())

angles <- rglToBase()
persp(volcano, col = "green", shade = TRUE,
      theta = angles$theta, phi = angles$phi)

请注意,orientlib 包必须可用才能使这些功能正常工作。

9.10 创建 pkgdown 网站

“Using RGL in pkgdown web sites” 小节描述了如何在 pkgdown 网站中使用 rgl。实用程序函数 in_pkgdown_example 可用于检测 pkgdown 是否正在使用。

9.11 使用 testthat

testthat 包广泛用于包中的单元测试。这样的测试很难用 rgl 编写,因为输出是可视化和交互式的,而不是简单的值。expect_known_scenecompare_proxy.mesh3dall.equal.mesh3d 函数通过删除 rgl 输出的系统相关功能来帮助解决此问题。

9.12 使用 JavaScript

使用 rglwidget 创建的 WebGL 显示依赖于该包中包含的大量 Javascript 代码。为了帮助开发此代码,编写了 makeDependency 函数。它可能在其他包含 Javascript 的包中有用。

9.13 其他函数和对象

本节适用于不属于本文档中任何其他类别的杂项函数和对象。

setGraphicsDelay 函数旨在解决 macOS 上的一个错误:如果在 rgl 窗口之后打开标准绘图窗口太快,R 可能会崩溃。此功能会在需要时插入一秒的延迟。

gltfTypes 向量包含 OpenGL 和 glTF 中使用的常量。

10 警告:工作正在进行中!

这个页面始终是一项正在进行的工作。rgl 包的某些方面没有描述,或者没有示例。如果以下列表不为空,甚至可能会完全错过某些功能:

## [1] "rgl.incrementID" "safe.dev.off"    "textureSource"


<center>--------------- 结束 ---------------</center>


<p style="color: gray; font-size: 10px;">注:本文为个人学习笔记,仅供大家参考学习,不得用于任何商业目的。如有侵权,请联系作者删除。</p>

本文由mdnice多平台发布


TigerZ知识宝库
4 声望8 粉丝