R rgl text3d()工件块对象并更改绘图范围

R rgl text3d() artifacts block objects and change plot extent

当我用 quads3d() 绘制一个形状然后添加一个 text3d() 对象时,我发现了 3 个问题(我认为它们是相关的,因此这里只有一个 post):

  1. text3d() 对象产生干扰 画画;它们看起来像是与文本相交的文本后面的表面 以奇怪的方式绘制对象。
  2. 绘图缩小(并且 extent/bbox 更改)- 我可以使用 ignoreExtent=T 使其不缩放,但如果我这样做 axes3d(),则可以看到 bbox 更大比没有文字的那个。这似乎表明插入了一个相对非常大的几何体。几个字符的文字尺寸这么大怎么办?
  3. 文字看起来很蹩脚;像素化,数学符号弱等

我尝试了不同的字体系列(包括基本的四种)、颜色和其他文本参数。我使用 extrafont 包并使用 font_import() 加载了我的 Windows 字体。是不是新鲜的Rsession/environment也没关系。它发生在 plotMath=T 或 F.

我正在使用的几何图形很小,大致适合一个单位立方体,这会有什么不同吗?

我怎样才能去除伪影并获得 decent-looking 不改变绘图尺寸的文本?谢谢。

示例代码如下:

# Draw a 3D Shape and Label it

library(rgl)
library(extrafont)

# Open a new device in which to display the diagram
open3d(windowRect=c(900,200,1700,800))

# Define vertices of the faces

A0 <- c(0, 0.1, -0.02)
B0 <- c(0, -0.1, -0.02)
C0 <- c(0, -0.1, 0.02)
D0 <- c(0, 0.1, 0.02)

Al <- c(1, 0.02, -0.1)
Bl <- c(1, -0.02, -0.1)
Cl <- c(1, -0.02, 0.1)
Dl <- c(1, 0.02, 0.1)

# Define the quadrangles to be visualized

Face0 <- c(A0, B0, C0, D0)
Facel <- c(Bl, Al, Dl, Cl)

Side1 <- c(A0, Al, Bl, B0)
Side2 <- c(B0, Bl, Cl, C0)
Side3 <- c(C0, Cl, Dl, D0)
Side4 <- c(D0, Dl, Al, A0)

# Draw faces and sides
TColor <- "steelblue"
TAlpha <- .25
F0 <- quads3d(matrix((Face0), nrow=4, byrow=T), col=TColor, alpha=TAlpha)
Fl <- quads3d(matrix((Facel), nrow=4, byrow=T), col=TColor, alpha=TAlpha)
S1 <- quads3d(matrix((Side1), nrow=4, byrow=T), col=TColor, alpha=TAlpha)
S2 <- quads3d(matrix((Side2), nrow=4, byrow=T), col=TColor, alpha=TAlpha)
S3 <- quads3d(matrix((Side3), nrow=4, byrow=T), col=TColor, alpha=TAlpha)
S4 <- quads3d(matrix((Side4), nrow=4, byrow=T), col=TColor, alpha=TAlpha)

运行 生成了一个漂亮的 3d 形状图像:

如果我运行下面的代码添加一个文本标签,

# Label a point

Cx <- c(.6,-0.052,0.068)

Xcolor <- "#000000"

points3d(Cx[1], Cx[2], Cx[3], col=Xcolor, size=5)
points3d(matrix(Cx, nrow=1), col=Xcolor, size=5)

XVertexColor <- "darkseagreen4"
par3d(ignoreExtent=F)

labelCx <- text3d(x=Cx[1], y=Cx[2], z=Cx[3], adj=c(0,0), family="Calibri", cex=1, font=2, text=expression(bold(sqrt(1/C[3](x)))), usePlotmath=T, col=XVertexColor)

...它看起来像这样(ignoreExtent=F): The same rgl device, the only change has been the point and the text3d() 缩放和旋转图像会显示干扰几何视图的文本伪影:

请注意,平方根符号几乎看不见;无论是什么字体系列,无论是否应用 bold(),都是如此。

rgl 绘制透明(即 alpha < 1)对象的方式的一个已知限制是它们并不总是能很好地交互。问题是透明物体需要在当前视图中按照从远到近的顺序绘制,但是如果你有两个相交的透明多边形,有些部分需要一个顺序绘制,有些部分需要依次绘制相反的顺序。由于rgl没有将它们拆分成单独的部分,因此部分部分会绘制错误。

这会影响文本,因为文本被绘制为四边形,背景使用 alpha = 0 绘制,文本使用 alpha = 1 绘制。如果放置文本的四边形与透明多边形相交,其中一个的某些部分将被绘制得很差。

您可以通过增加 initCex 参数来减少文本的像素化;请参阅 ?plotmath3d 进行讨论。不幸的是,这使得平方根符号看起来更糟:我认为无论大小如何,它都是以恒定宽度绘制的(通过基本图形函数,而不是 rgl)。您可以使用

在基础图形中看到这一点
plot(1,1, type="n")
text(1,1,expression(bold(sqrt(1/C[3](x)))), cex = 5)

使用较小的 initCex 会得到更好比例的平方根,但它会变得模糊或像素化(取决于大小)。 (注意:请参阅下面的补充。)

编辑添加:

关于边界框的变化:这看起来确实像是一个错误,但它又一次似乎是设计的局限性。如前所述,文本绘制在透明四边形上。这个四边形是由 sprites3d 绘制的,这意味着它不随场景旋转,它始终面向观察者。如果你有 ignoreExtent = FALSE,那么 rgl 会尝试确保四边形适合场景而不考虑方向,即它占据与四边形周围的球体相同的 space。

X 方向的场景比 Y 或 Z 方向的场景大得多,因此球体确实会扭曲东西。

此处的解决方案是使用 ignoreExtent = TRUE 以便边界框忽略该球体。记得事后恢复。

另一个改进是可能的。由于您不想要可调整大小的文本,您可以通过将 cexinitCex 设置为相同的值,但使用不同的 material 属性来改进它的绘制方式。前 添加文本,将 texminfiltertexmagfilter 都设置为 "nearest",事情看起来会有点像素化,但比您看到的要好。

将两个更改放在一起:

也就是说,将最后两行代码更改为:

saveIgnore <- par3d(ignoreExtent = TRUE)
saveFilter <- material3d(texminfilter = "nearest", texmagfilter = "nearest")
labelCx <- text3d(x=Cx[1], y=Cx[2], z=Cx[3], adj=c(0,0),
                  family="Calibri", cex = 1, initCex = 1, font=2,
                  text=expression(bold(sqrt(1/C[3](x)))), 
                  usePlotmath=TRUE, col=XVertexColor)
material3d(saveFilter)
par3d(saveIgnore)

第二次编辑:

您的第一个问题有一些解决方法。最简单的方法是将文本从任何透明的地方移开,或者使透明的东西不透明。但是如果你真的想让文本靠近透明对象,设置 material 属性 depth_mask = FALSE 将意味着文本的四边形永远不会遮挡它后面的任何东西。这可能是一个很好的默认值。设置 depth_test = "always" 意味着没有任何东西可以遮盖文本。这可能会导致显示效果相当怪异,因此我一般不会推荐它,但对于您的 alpha = 0.25 表面,它看起来并不太糟糕。