Plotly球体按悬停值及交集区域着色技术咨询
解决方案:Plotly中基于值为球体及交集区域着色
一、单个球体按悬停值(0-500范围)用热力图调色板着色
要实现单个球体根据其悬停值映射到热力图调色板,核心是利用Plotly mesh3d 的以下参数:
color:为每个三角面指定对应值(若整个球体为同一值,可将该值重复赋值给所有面)colorscale:选用热力图调色板(如'Viridis'、'RdYlBu')cmin/cmax:固定颜色映射范围为0-500,确保不同球体的颜色对比基准一致
二、交集区域基于两球体值之和着色
交集区域的实现需先计算两个球体的重叠部分并生成对应3D网格,再将该区域的颜色映射为两球体值的总和(范围设为0-1000,适配两值最大各500的情况),确保值越大颜色越深。
完整代码示例
library(plotly) library(misc3d) # 定义球体方程 sphere_eq <- function(x, y, z, cx, cy, cz, r) { (x - cx)^2 + (y - cy)^2 + (z - cz)^2 - r^2 } R <- 2 # 球体半径 # 生成覆盖两个球体的网格 x <- y <- z <- seq(-R, R + 2, length.out = 100) g <- expand.grid(x = x, y = y, z = z) # 两个球体的参数:中心坐标+悬停值 sphere1 <- list(cx=0, cy=0, cz=0, val=150) sphere2 <- list(cx=2, cy=2, cz=2, val=43) intersection_val <- sphere1$val + sphere2$val # 生成单个球体的轮廓 cont1 <- computeContour3d(with(g, sphere_eq(x, y, z, sphere1$cx, sphere1$cy, sphere1$cz, R)), level = 0, x = x, y = y, z = z) cont2 <- computeContour3d(with(g, sphere_eq(x, y, z, sphere2$cx, sphere2$cy, sphere2$cz, R)), level = 0, x = x, y = y, z = z) # 生成交集区域的轮廓:提取同时属于两个球体的点的表面 intersection_voxel <- array( with(g, ifelse(sphere_eq(x, y, z, sphere1$cx, sphere1$cy, sphere1$cz, R) <= 0 & sphere_eq(x, y, z, sphere2$cx, sphere2$cy, sphere2$cz, R) <= 0, 1, 0)), dim = c(100, 100, 100) ) cont_intersect <- computeContour3d(intersection_voxel, level = 0.5, x = x, y = y, z = z) # 生成三角面索引的工具函数 get_idx <- function(cont) { matrix(0:(nrow(cont)-1), ncol=3, byrow=TRUE) } idx1 <- get_idx(cont1) idx2 <- get_idx(cont2) idx_intersect <- get_idx(cont_intersect) # 绘制可视化图形 plot_ly() |> # 第一个球体 add_trace( type = "mesh3d", x = cont1[, 1], y = cont1[, 2], z = cont1[, 3], i = idx1[, 1], j = idx1[, 2], k = idx1[, 3], opacity = 0.3, hoverinfo = "text", text = sprintf("值: %d", sphere1$val), color = rep(sphere1$val, nrow(idx1)), colorscale = "Viridis", cmin = 0, cmax = 1000, # 兼容交集的和值范围 showscale = TRUE ) |> # 第二个球体 add_trace( type = "mesh3d", x = cont2[, 1], y = cont2[, 2], z = cont2[, 3], i = idx2[, 1], j = idx2[, 2], k = idx2[, 3], opacity = 0.3, hoverinfo = "text", text = sprintf("值: %d", sphere2$val), color = rep(sphere2$val, nrow(idx2)), colorscale = "Viridis", cmin = 0, cmax = 1000, showscale = FALSE # 仅保留一个颜色条 ) |> # 交集区域 add_trace( type = "mesh3d", x = cont_intersect[, 1], y = cont_intersect[, 2], z = cont_intersect[, 3], i = idx_intersect[, 1], j = idx_intersect[, 2], k = idx_intersect[, 3], opacity = 0.8, hoverinfo = "text", text = sprintf("交集值: %d", intersection_val), color = rep(intersection_val, nrow(idx_intersect)), colorscale = "Viridis", cmin = 0, cmax = 1000, showscale = FALSE ) |> layout(scene = list(aspectmode = "data"))
关键细节说明
- 颜色映射逻辑:将
cmax设为1000,同时兼容单个球体的0-500值和交集的0-1000值,确保值越大颜色越深的需求。 - 交集计算方式:通过判断网格点是否同时属于两个球体生成voxel数据,再提取表面轮廓,保证交集区域的准确性。
- 视觉层次优化:调整不同trace的
opacity参数,让交集区域更突出,同时保留两个球体的可见性。
内容的提问来源于stack exchange,提问作者its.me.adam
相关产品推荐
相关产品推荐

