在R语言中从3D点云生成可用于相交计算的3D polygon的实现方法问询
在R语言中从3D点云生成可用于相交计算的3D polygon的实现方法问询
嗨,我来帮你梳理下从3D点云生成可用的3D多边形的思路,结合你现有的算法来调整,同时满足后续相交计算的需求:
首先得明确一个关键前提:3D多边形如果要方便做相交计算,最好是平面多边形(所有顶点都在同一个平面上)——空间多边形(顶点不在同一平面)的相交逻辑会复杂很多,大部分R的几何计算库也更支持平面多边形的操作。下面分两种方案给你参考:
一、基于你现有极值点算法扩展到3D平面多边形
你现在的2D算法是通过提取XY平面的极值点来构建多边形,要扩展到3D,可以先把点云投影到一个拟合平面上,再复用你的逻辑生成2D多边形,最后映射回3D空间:
步骤拆解&代码实现
- 拟合点云的主平面:用PCA找到点云的最优拟合平面(保证后续生成的多边形是平面多边形)
- 将3D点投影到拟合平面:把所有点转换为平面内的2D坐标
- 复用你的极值点算法生成2D多边形顶点
- 把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
相关产品推荐
相关产品推荐

