绘制具有交集的球体强度着色

问题描述 投票:0回答:1

如何根据单个值、0-500 范围内的位置以及热图调色板(黄到红或绿-黄-红)为球体着色?

此外,如何根据每个球体值的总和为两个球体的交集着色?

enter image description here

library(plotly)

f <- function(x, y, z){
  x^2 + y^2 + z^2
}
R <- 2 # radius
x <- y <- z <- seq(-R, R, length.out = 100) 
g <- expand.grid(x = x, y = y, z = z)
voxel <- array(with(g, f(x, y, z)), dim = c(100, 100, 100))

library(misc3d)
cont <- computeContour3d(voxel, level = R^2, x = x, y = y, z = z)
idx <- matrix(0:(nrow(cont)-1), ncol=3, byrow=TRUE)

plot_ly() |> 
  add_trace(
    type = "mesh3d",
    x = cont[, 1], y = cont[, 2], z = cont[, 3],
    i = idx[, 1], j = idx[, 2], k = idx[, 3],
    opacity = 0.2,
    hoverinfo = "text",
    text = "150"
  ) |> 
  add_trace(
    type = "mesh3d",
    x = cont[, 1]+2, y = cont[, 2]+2, z = cont[, 3]+2,
    i = idx[, 1], j = idx[, 2], k = idx[, 3],
    opacity = 0.2,
    hoverinfo = "text",
    text = "43"
  ) 

r plotly
1个回答
0
投票

首先我会推荐 rmarchingcubes 包而不是 misc3d,因为它更高效。

library(plotly)
library(rmarchingcubes)

f <- function(x, y, z){
  x^2 + y^2 + z^2
}
R <- 2 # radius

n <- 100
x_ <- y_ <- z_ <- seq(-R, R, length.out = 100) 
Grid <- expand.grid(X = x_, Y = y_, Z = z_)
voxel <- with(Grid, array(f(X, Y, Z), dim = c(n, n, n)))
surf <- contour3d(voxel, level = R^2, x_, y_, z_)

vertices <- surf$vertices
indices  <- surf$triangles - 1

plot_ly(
  x = vertices[, 1], y = vertices[, 2], z = vertices[, 3],
  i = indices[, 1], j = indices[, 2], k = indices[, 3],
  type = "mesh3d"
) %>% layout(scene = list(aspectmode = "data"))

我不明白你所说的“0-500范围内的球体位置”是什么意思。

如果您想根据附加到球体点的某些值对球体进行着色,您首先需要定义将点映射到这些值的函数。例如,我将取方位角的正弦值,以获得周期性的东西。然后我首先计算这些值:

# azimuthal angles
phi <- atan2(vertices[, 2], vertices[, 1])
# we color a vertex according to sin(phi)
values <- sin(phi)

这些值的范围从

-1
1
colorRamp
函数非常适合将颜色与数字关联起来;它需要
0
1
之间的数字,因此我通过应用函数
v -> (v + 1)/2
:

将值线性映射到此范围
# we map sin(phi) to (0, 1) in order to use the colorRamp function
u <- (values + 1) / 2
#
fPalette <- colorRamp(c("yellow", "green", "blue"))
vertexColors <- fPalette(u)

在这一步,

vertexColors
是一个表示0到255之间RGB值的矩阵,必须将它们转换为十六进制编码的颜色:

vertexColors <- rgb(
  vertexColors[, 1], vertexColors[, 2], vertexColors[, 3], maxColorValue = 255
)

然后我们可以用这些颜色进行绘图:

plot_ly(
  x = vertices[, 1], y = vertices[, 2], z = vertices[, 3],
  i = indices[, 1], j = indices[, 2], k = indices[, 3],
  vertexcolor = toRGB(vertexColors),
  type = "mesh3d"
) %>% layout(scene = list(aspectmode = "data"))

enter image description here

关于交叉路口,这个我不是很清楚。通过取

g(x,y,z)=0
,可以得到两个等值面
f1(x,y,z)=0
f2(x,y,z)=0
相交的隐式方程
g(x,y,z) = max(f1(x,y,z), f2(x,y,z))

f1 <- function(x, y, z){
  x^2 + y^2 + z^2 - R^2
}
f2 <- function(x, y, z){
  (x-2)^2 + (y-2)^2 + (z-2)^2 - R^2
}
g <- function(x, y, z) {
  pmax(f1(x, y, z), f2(x, y, z))
}
voxel <- with(Grid, array(g(X, Y, Z), dim = c(n, n, n)))
surf <- contour3d(voxel, level = 0, x_, y_, z_)
vertices <- surf$vertices
indices  <- surf$triangles - 1
plot_ly(
  x = vertices[, 1], y = vertices[, 2], z = vertices[, 3],
  i = indices[, 1], j = indices[, 2], k = indices[, 3],
  type = "mesh3d"
) %>% layout(scene = list(aspectmode = "data"))

enter image description here

但是,如果您想根据该顶点的两个球体值对该交点的每个顶点进行着色,则需要一个与球体所包围的 volume 中的每个点关联的“球体值”。仅对表面上的点有一些值是不够的,因为这是体积的交集。

© www.soinside.com 2019 - 2024. All rights reserved.