You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R语言中从3D点云生成可用于相交计算的3D polygon的实现方法问询

在R语言中从3D点云生成可用于相交计算的3D polygon的实现方法问询

嗨,我来帮你梳理下从3D点云生成可用的3D多边形的思路,结合你现有的算法来调整,同时满足后续相交计算的需求:

首先得明确一个关键前提:3D多边形如果要方便做相交计算,最好是平面多边形(所有顶点都在同一个平面上)——空间多边形(顶点不在同一平面)的相交逻辑会复杂很多,大部分R的几何计算库也更支持平面多边形的操作。下面分两种方案给你参考:


一、基于你现有极值点算法扩展到3D平面多边形

你现在的2D算法是通过提取XY平面的极值点来构建多边形,要扩展到3D,可以先把点云投影到一个拟合平面上,再复用你的逻辑生成2D多边形,最后映射回3D空间:

步骤拆解&代码实现

  1. 拟合点云的主平面:用PCA找到点云的最优拟合平面(保证后续生成的多边形是平面多边形)
  2. 将3D点投影到拟合平面:把所有点转换为平面内的2D坐标
  3. 复用你的极值点算法生成2D多边形顶点
  4. 把2D顶点映射回3D空间
library(sp)
library(deldir)
library(stats)
library(rgl) # 用于3D可视化

# 生成你的3D点云(保留你的原数据逻辑)
set.seed(25)
cloudOfPointsX <- runif(25, min=0, max=100)
cloudOfPointsY <- runif(25, min=0, max=100)
cloudOfPointsZ <- runif(25, min=0, max=100)
listOfPoints <- data.frame(x = cloudOfPointsX, y = cloudOfPointsY, z = cloudOfPointsZ)

# 1. 用PCA拟合点云的主平面
pca <- prcomp(listOfPoints, center = TRUE, scale. = FALSE)
normal_vector <- pca$rotation[,3] # 平面法向量(方差最小的主成分)
plane_center <- pca$center # 平面中心点

# 2. 定义3D点到平面的投影函数
project_to_plane <- function(point, center, normal) {
  vec <- point - center
  proj_length <- sum(vec * normal) # 计算点积
  point - proj_length * normal
}
# 对所有点做投影,得到平面内的2D坐标
projected_points <- t(apply(listOfPoints, 1, function(p) project_to_plane(p, plane_center, normal_vector)))
projected_df <- data.frame(u = projected_points[,1], v = projected_points[,2])

# 3. 复用你的极值点算法生成2D多边形顶点(优化了删除点的逻辑,避免重复值问题)
temp_points <- projected_df
polygon_vertices_2d <- data.frame()
while(nrow(temp_points) > 2){
  # 用行索引删除点,避免match的重复值问题
  max_u_idx <- which.max(temp_points$u)
  pMaxX <- temp_points[max_u_idx,]
  temp_points <- temp_points[-max_u_idx,]
  
  max_v_idx <- which.max(temp_points$v)
  pMaxY <- temp_points[max_v_idx,]
  temp_points <- temp_points[-max_v_idx,]
  
  min_u_idx <- which.min(temp_points$u)
  pMinX <- temp_points[min_u_idx,]
  temp_points <- temp_points[-min_u_idx,]
  
  min_v_idx <- which.min(temp_points$v)
  pMinY <- temp_points[min_v_idx,]
  temp_points <- temp_points[-min_v_idx,]
  
  polygon_vertices_2d <- rbind(polygon_vertices_2d, pMaxX, pMaxY, pMinX, pMinY)
}
# 去重并闭合多边形
polygon_vertices_2d <- unique(polygon_vertices_2d)
polygon_vertices_2d <- rbind(polygon_vertices_2d, polygon_vertices_2d[1,])

# 4. 将2D顶点映射回3D空间
basis1 <- pca$rotation[,1] # 平面的第一个基向量
basis2 <- pca$rotation[,2] # 平面的第二个基向量
polygon_vertices_3d <- apply(polygon_vertices_2d, 1, function(p) {
  plane_center + p$u * basis1 + p$v * basis2
})
polygon_vertices_3d <- t(polygon_vertices_3d)
colnames(polygon_vertices_3d) <- c("x", "y", "z")

# 3D可视化查看结果
plot3d(listOfPoints$x, listOfPoints$y, listOfPoints$z, col = "blue", size = 5)
lines3d(polygon_vertices_3d$x, polygon_vertices_3d$y, polygon_vertices_3d$z, col = "magenta", lwd = 3)

二、更可靠的方案:用凸包生成3D多边形

你现有的极值点算法比较简单,可能会生成不规则的多边形。如果后续要做相交计算,凸多边形的逻辑会更稳定,推荐用3D凸包算法来生成:

代码示例(用alphashape3d包)

library(alphashape3d)
library(rgl)

# 生成3D凸包(alpha=Inf时生成最小凸包)
ashape <- ashape3d(listOfPoints, alpha = Inf)

# 提取凸包的一个面作为多边形(凸包由三角面组成,这里选第一个面)
face_idx <- ashape$triang$tr[1,]
face_vertices <- listOfPoints[face_idx,]
face_vertices <- rbind(face_vertices, face_vertices[1,]) # 闭合多边形

# 可视化
plot3d(listOfPoints$x, listOfPoints$y, listOfPoints$z, col = "blue", size = 5)
lines3d(face_vertices$x, face_vertices$y, face_vertices$z, col = "red", lwd = 3)

三、关于3D多边形的相交计算

要实现和轴、线、其他多边形的相交,推荐用sf包(支持3D简单特征):

library(sf)

# 将3D多边形转换为sf的POLYGON Z对象
polygon_sf <- st_sfc(st_polygon(list(polygon_vertices_3d)), crs = NA)
# 生成一条3D测试直线
line_sf <- st_sfc(st_linestring(rbind(c(0,0,0), c(100,100,100))), crs = NA)

# 计算多边形和直线的交点
intersection <- st_intersection(polygon_sf, line_sf)
print(intersection)

备注:内容来源于stack exchange,提问作者AntonioC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 09:44:41