rgl 中的上标和下标

Superscript and subscript in rgl

我想在具有下标和上标的 rgl 绘图中使用 text3d 创建标签。

open3d(windowRect=c(500,500,1000,1000))
text3d(0, 0, 0, expression(CO[2]))

生成如下所示的图像:

并且,

open3d(windowRect=c(500,500,1000,1000)) 
text3d(0, 0, 0, bquote("CO"[2]))

产生

有什么方法可以在 rgl 中获取下标/上标?

不是真的。基础图形有一个完整的 "plotmath" 基础结构来解析这些表达式并将它们转换为绘图命令。 rgl 根本没有使用它。

我不认为 plotmath 代码在基础图形之外可用,所以唯一的可能性有点丑陋:

  • 在 3D 场景中将 2D 图形显示为位图(请参阅 ?show2d 或 ?sprites3d)。

  • 编写基本图形驱动程序(或搭载现有驱动程序)以获取 plotmath 的结果,并在 rgl 中重做。这对其他事情很有用,但很难。

编辑添加:

这是用 sprite 进行的第二次尝试。它仍然可以调整得更好:

  • 精灵在场景中调整大小,而文本通常不会。 (也许这是一个功能,而不是错误。)您可能需要使用 cex 设置来获得您想要的。

  • 不支持将文本放在边距中,就像您想要的标签一样。查看 mtext3d 函数来执行此操作。

  • 现在支持text中的多个元素。

  • 它现在有一个 adj 参数,其行为应该类似于 text3d

  • 它还没有经过太多测试。

无论如何,这是一个开始。如果您想到改进,请 post 他们。

plotmath3d <- function(x, y = NULL, z = NULL,
               text, 
               cex = par("cex"), adj = par("adj"),
               startsize = 480,
               ...) {
  xyz <- xyz.coords(x, y, z)
  n <- length(xyz$x)
  if (is.vector(text))
    text <- rep(text, length.out = n)
  cex <- rep(cex, length.out = n)
  adj <- c(adj, 0.5, 0.5)[1:2]
  save <- par3d(skipRedraw = TRUE)
  on.exit(par3d(save))
  for (i in seq_len(n)) {
    # The first device is to measure it.  
    f <- tempfile(fileext = ".png")
    png(f, bg = "transparent", width = startsize, height = startsize)
    par(mar = c(0, 0, 0, 0), xaxs = "i", xaxt = "n",  
        yaxs = "i", yaxt = "n",
        usr = c(0, 1, 0, 1))
    plot.new()
    if (is.vector(text))
      thistext <- text[i]
    else
      thistext <- text
    w <- strwidth(thistext, cex = 5, ...)*(2*abs(adj[1] - 0.5) + 1)
    h <- strheight(thistext, cex = 5, ...)*(2*abs(adj[2] - 0.5) + 1)
    dev.off()

    # Now make a smaller bitmap and draw it
    expand <- 1.5
    size <- round(expand*startsize*max(w, h))
    png(f, bg = "transparent", width = size, height = size)
    par(mar = c(0, 0, 0, 0), xaxs = "i", xaxt = "n", 
        yaxs = "i", yaxt = "n",
        usr = c(0, 1, 0, 1))
    plot.new()
    text(0.5, 0.5, thistext, adj = adj, cex = 5, ...)
    dev.off()

    with(xyz, sprites3d(x[i], y[i], z[i], texture = f, textype = "rgba", 
            col = "white", lit = FALSE, radius = cex[i]*size/100))
  }
}