rgl:绘制一个带有彩色面,顶点和线

时间:2016-09-27 17:28:17

标签: r linear-algebra rgl

为了演示3D中线性变换的效果x -> A x,我想绘制一个立方体并在A下显示其变换。为此,我需要分别为每个面着色,还要显示顶点和每个面的轮廓线。

我无法弄清楚如何为面部使用不同的颜色,以及如何使这更加通用,所以我不必重复转换结果的所有步骤。

我尝试了什么:

library(rgl)
c3d <- cube3d(color=rainbow(6), alpha=0.5)
open3d()
shade3d(c3d)
points3d(t(c3d$vb), size=5)
for (i in 1:6)
    lines3d(t(c3d$vb)[c3d$ib[,i],])

这给出了下图。但我不明白脸是如何着色的。而且,我似乎必须在points3d形状的组件上使用lines3dc3d,并且没有可以转换的单个对象。

enter image description here

下面的矩阵A给出了一个特殊的变换,这就是我如何将它添加到场景中,

A <- matrix(c( 1, 0, 1, 0, 2, 0,  1, 0, 2), 3, 3)
c3d_trans <- transform3d(c3d, A) 
shade3d( c3d_trans )
points3d(t(c3d_trans$vb), size=5)

这给出了:

enter image description here

有没有办法简化这个并使其更有用?

3 个答案:

答案 0 :(得分:6)

rgl中,绘制基本形状时,可以将颜色应用于顶点,而不是面。通过在顶点处插入颜色来对面进行着色。

但是,cube3d()不是原始形状,而是#34;网格&#34;。它被绘制为6个单独的四边形。每个顶点使用3次。

它没有真正记录,但使用颜色的顺序是前4个用于一个面,然后是下一个4用于下一个面,等等。如果你想要你的颜色是{{ 1}},你需要复制每种颜色4次:

rainbow(6)

Screenshot of rendered cube

我建议使用更高的library(rgl) c3d <- cube3d(color=rep(rainbow(6), each = 4), alpha = 0.5) open3d() shade3d(c3d) points3d(t(c3d$vb), size = 5) for (i in 1:6) lines3d(t(c3d$vb)[c3d$ib[,i],]) 值;我发现透明度在alpha处有点令人困惑。

顺便说一句,出于同样的目的,我通常使用看起来更加球形的形状作为基线;我认为它提供了更好的转型直觉。这是我用过的代码:

alpha = 0.5

这就形成了这个形状:

sphere

转换为:

sphere <- subdivision3d(cube3d(color=rep(rainbow(6),rep(4*4^4,6)), alpha=0.9),
    depth=4)
sphere$vb[4,] <- apply(sphere$vb[1:3,], 2, function(x) sqrt(sum(x^2)))
open3d()
shade3d(sphere)

transformed sphere

当然,如果你可以旋转它,一切看起来都会更好。

答案 1 :(得分:4)

(注意:我使用rgl version 0.96.0。如果我的记忆力正确,则wire3d()dot3d()规则已更改

在制作类mesh3d对象时提供彩色信息并不是一个好主意,因为shade3d()wire3d()dot3d()在不同的对象中使用它方法。最好在绘制对象时为plot-function提供颜色信息。

例如;
A <- matrix(c( 1, 0, 1, 0, 2, 0,  1, 0, 2), 3, 3)
c3d2 <- cube3d()
c3d_trans2 <- cube3d(A)
colv <- rep(2:7, each=4)

shade3d(c3d2, col = colv, alpha = 0.8)
wire3d(c3d2); dot3d(c3d2, size = 5)
shade3d(c3d_trans2, col = colv, alpha=0.5)
dot3d(c3d_trans2, size = 5)

enter image description here

<小时/> [与颜色和mesh3d.obj相关的详细信息]

最重要的规则是一个顶点消耗颜色无论何时使用(但它有点复杂,请参见下面的示例)。我在矩阵 ib mesh3d.obj$vb的列号索引下面调用。

cube3d()$ib
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    1    3    2    1    1    5
# [2,]    3    7    4    5    2    6
# [3,]    4    8    8    7    6    8
# [4,]    2    4    6    3    5    7
shade3d()规则(很容易)
plot3d(cube3d(scaleMatrix(1.2,1.2,1.2)), alpha=0)
text3d(t(cube3d()$vb[1:3,]*1.05), texts=1:8)  # indices
shade3d(cube3d(), col=c(rep(2,4), rep(3,4), rep(4,4), rep(5,4), rep(6,4), rep(7,4)), alpha=0.8)
                #  ib[1:4, 1]  [1:4, 2]  [1:4, 3]  [1:4, 4]  [1:4, 5]  [1:4, 6]
              # index 1,3,4,2  3,7,8,4   2,4,8,6, ...

enter image description here

wire3d规则(复杂而可怕......;已编辑)
text3d(t(cube3d()$vb[1:3,]*1.05), texts=1:8, font=2)  # indices
wire3d(cube3d(), col=c(rep(2,6), rep(3,6), rep(4,6), rep(5,6), rep(6,6), rep(7,6)))
# I gave each color 6 times.

index  1       3       4       2       1
ib$[1,1] - [2,1] - [3,1] - [4,1] - [1,1] - NA
 col   2       2       2       2       2    2  # Why NA uses a color!!??

index  3       7      8    4 (skipped) 3       # the line already has been drawn, skipped.
ib$[1,2] - [2,2] - [3,2] - [4,2] - [1,2] - NA; 
 col   3       3      3    3 (skipped) 3    3

index 2 (sk)   4 (sk)  8       6      2
ib$[1,3] - [2,3] - [3,3] - [4,3] - [1,3] - NA; 
 col 4  (sk)   4 (sk)  4       4       4    4,   and so on.

在一个ib的{​​{1}}中,一个顶点只有一种颜色(例如,在col,Index3的颜色信息用于1-3和3-4。线已经被绘制,它被跳过。太难了(有些模式是不可能的)ib[,1]绘制不同颜色的线条。如果你想这样做,那会更好使用wire3d()lines3d()

enter image description here

dot3d规则
segments3d()

如果您提供plot3d(cube3d(scaleMatrix(1.2,1.2,1.2)), alpha=0) text3d(t(cube3d()$vb[1:3,]*1.05), texts=1:8) # indices dot3d(cube3d(), col=1:8, size=8) unique(c(cube3d()$ib)) # [1] 1 3 4 2 7 8 6 5 ,则不是index2,而是index3变为col=1:8col = 2)。所以,red表示index1为col = c("col1", "col2", ..., "col8")[unique(c(object$ib))], index2是col1

enter image description here

答案 2 :(得分:2)

我的问题的第二部分 - 如何概括一下 - 没有答案。这是一个简单的函数,我现在用来使这些步骤可重用。

# draw a mesh3d object with vertex points and lines
draw3d <- function(object, ...) {
    shade3d(object, ...)
    vertices <- t(object$vb)
    indices <- object$ib
    points3d(vertices, size=5)
    for (i in 1:ncol(indices))
        lines3d(vertices[indices[,i],])
}