使用R的extrude3d()函数将多边形按属性值拉伸为3D网格并导出OBJ
用R从Geopackage多边形生成矢量3D OBJ文件
核心方案
要生成无栅格化瑕疵的矢量3D网格,需基于多边形的矢量拓扑,结合高度属性逐个拉伸为棱柱,再合并导出为OBJ格式。以下是可落地的步骤:
步骤1:读取并预处理Geopackage数据
使用sf包读取数据,确保所有图形为单个多边形(拆分多多边形避免拉伸异常):
library(sf) library(rgl) # 读取Geopackage文件 gpkg_data <- st_read("你的文件路径.gpkg") # 将多多边形拆分为单个多边形 gpkg_data <- st_cast(gpkg_data, "POLYGON")
步骤2:单个多边形的3D拉伸逻辑
自定义函数处理单多边形的顶点提取、高度拉伸和面生成,确保保留矢量拓扑:
# 输入单个sf多边形与高度值,输出拉伸后的顶点和面索引 extrude_single_poly <- function(poly, height) { # 提取XY顶点(移除闭合重复的最后一个点) coords <- st_coordinates(poly)[-nrow(st_coordinates(poly)), 1:2] vert_count <- nrow(coords) # 生成底部(Z=0)和顶部(Z=height)的顶点矩阵 bottom_verts <- cbind(coords, 0) top_verts <- cbind(coords, height) # 生成OBJ格式的面索引(索引从1开始) # 底部面 bottom_face <- 1:vert_count # 顶部面(反转索引保证面法线方向正确) top_face <- rev((vert_count + 1):(2*vert_count)) # 侧面的四边形面 side_faces <- lapply(1:vert_count, function(i) { next_idx <- ifelse(i == vert_count, 1, i + 1) c(i, next_idx, next_idx + vert_count, i + vert_count) }) list(vertices = rbind(bottom_verts, top_verts), faces = list(bottom_face, top_face, unlist(side_faces))) } # 对所有多边形批量生成3D部件 all_3d_parts <- lapply(1:nrow(gpkg_data), function(i) { extrude_single_poly(gpkg_data$geometry[i], gpkg_data$POINT...50[i]) })
步骤3:合并部件并导出OBJ
将所有拉伸后的棱柱顶点与面合并,用rgl导出为标准OBJ文件:
# 合并所有顶点 combined_verts <- do.call(rbind, lapply(all_3d_parts, function(x) x$vertices)) # 累加面索引(处理不同部件的顶点偏移) face_offset <- 0 combined_faces <- list() for(part in all_3d_parts) { adjusted_faces <- lapply(part$faces, function(f) f + face_offset) combined_faces <- c(combined_faces, adjusted_faces) face_offset <- face_offset + nrow(part$vertices) } # 创建3D网格并导出 open3d() shade3d(tmesh3d(vertices = t(combined_verts), indices = combined_faces), color = "lightgray") writeOBJ("最终3D模型.obj")
关键问题说明
- 解决extrude3d失效问题:
rgl::extrude3d仅支持自身的2D图形对象,直接处理sf多边形会报错,上述方案通过直接操作坐标点,适配sf数据结构。 - 避免栅格化瑕疵:全程基于矢量顶点生成面,无栅格转矢量的过程,保证OBJ文件为纯矢量网格。
- 处理复杂多边形:提前拆分多多边形,确保每个拉伸单元为简单多边形,避免拓扑错误。
内容的提问来源于stack exchange,提问作者elwwan
相关产品推荐
相关产品推荐

