如何检查/判定/分割点是否在3D圆锥内?以兔子点云数据为例
3D圆锥内点的判定方法
核心判定逻辑
对于给定的圆锥,先明确其关键参数:
- 顶点 ( P_0 )
- 底面中心 ( P_1 )
- 底面半径 ( r )
- 圆锥高度 ( h = ||P_1 - P_0|| )(轴线长度)
任意点 ( P ) 满足以下两个条件时,即处于圆锥内部:
- 轴向范围约束:点 ( P ) 在顶点 ( P_0 ) 和底面中心 ( P_1 ) 之间的轴向投影范围内——向量 ( \vec{P_0P} ) 在轴线向量 ( \vec{P_0P_1} ) 上的投影长度 ( t ) 满足 ( 0 \leq t \leq h )。
- 径向范围约束:点 ( P ) 到圆锥轴线的距离 ( d ),不超过对应高度 ( t ) 处的圆锥半径 ( r(t) = \frac{r}{h} \times t )。
数学计算细节
- 轴线向量 ( \vec{V} = P_1 - P_0 )
- 向量 ( \vec{W} = P - P_0 )
- 投影长度 ( t = \frac{\vec{W} \cdot \vec{V}}{h} )(因 ( h = ||\vec{V}|| ))
- 点到轴线的距离 ( d = ||\vec{W} - \frac{t}{h}\vec{V}|| )(向量 ( \vec{W} ) 减去轴向投影后的模长)
- 最终判定:( 0 \leq t \leq h ) 且 ( d \leq \frac{r}{h} \times t )
兔子点云的实战实现
基于你提供的R代码,添加点云筛选逻辑即可找出圆锥内的点:
library("onion") library("rgl") # 加载兔子点云数据 data(bunny) # 定义圆锥参数 P0 <- c(0, 0, 0) # 顶点 P1 <- c(0, 0.23, 0) # 底面中心 r <- 0.15 # 底面半径 h <- sqrt(sum((P1 - P0)^2)) # 圆锥高度 # 圆锥可视化 pts <- cbind(P0, P1) radii <- c(0.0, r) cone <- cylinder3d(pts, radii, sides = 20) # 判定函数:判断单个点是否在圆锥内 is_in_cone <- function(point) { W <- point - P0 V <- P1 - P0 # 计算投影到轴线的长度t t <- sum(W * V) / h # 轴向范围检查 if (t < 0 || t > h) { return(FALSE) } # 计算点到轴线的距离 proj_W_on_V <- (t / h) * V d <- sqrt(sum((W - proj_W_on_V)^2)) # 径向范围检查 max_radius_at_t <- (r / h) * t return(d <= max_radius_at_t) } # 筛选兔子点云中的内部点 bunny_in_cone <- bunny[apply(bunny, 1, is_in_cone), ] # 可视化结果:圆锥+全部点云+内部点(红色高亮) points3d(bunny, col="pink", alpha = 0.3) shade3d(cone, col = "lightblue", alpha = 0.9) points3d(bunny_in_cone, col="red", size=3)
代码说明
is_in_cone函数实现了上述判定逻辑,对单个点返回布尔值- 通过
apply遍历点云所有点,筛选出符合条件的点 - 可视化时用红色高亮圆锥内的点,便于对比观察
内容的提问来源于stack exchange,提问作者ninaPeng
相关产品推荐
相关产品推荐

