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

如何在Python中沿3D路径扫掠矩形生成满足约束的3D网格?

自定义3D扫掠网格生成方案

核心思路

Trimesh的sweep_polygon无法满足矩形始终水平、路径垂直穿中心的约束,因此需要手动实现扫掠逻辑,分三步解决:

  • 为每段路径生成满足约束的局部坐标系,确保矩形上下边对齐世界水平方向,路径垂直穿过矩形中心
  • 逐段生成扫掠网格面
  • 用类似Matplotlib的连接样式(斜接、圆角等)处理路径转角,避免孔洞

依赖安装(Docker无头环境)

先在容器内安装所需依赖:

# 安装系统依赖(xvfb用于无头渲染)
apt-get update && apt-get install -y xvfb
# 安装Python库
pip install numpy shapely trimesh pyvista

代码实现

1. 生成约束局部坐标系

计算每段路径对应的局部坐标系,保证矩形水平且路径穿中心:

import numpy as np

def get_local_coords(path_direction):
    # 世界水平参考方向(Y轴向上)
    up_axis = np.array([0, 1, 0])
    # 处理路径与上轴平行的特殊情况,避免叉乘为零
    if np.allclose(path_direction, up_axis) or np.allclose(path_direction, -up_axis):
        up_axis = np.array([0, 0, 1])
    # 局部X轴:上轴叉乘路径方向
    local_x = np.cross(up_axis, path_direction)
    local_x /= np.linalg.norm(local_x)
    # 局部Y轴:路径方向叉乘X轴,保证与世界上轴对齐
    local_y = np.cross(path_direction, local_x)
    local_y /= np.linalg.norm(local_y)
    # 局部Z轴:路径方向
    local_z = path_direction / np.linalg.norm(path_direction)
    return np.array([local_x, local_y, local_z])

2. 单段路径扫掠生成网格

将Shapely矩形转换为当前路径段的3D网格:

import trimesh
from shapely.geometry import Polygon

def sweep_segment(start_point, end_point, rectangle):
    dir_vec = end_point - start_point
    local_coords = get_local_coords(dir_vec)
    
    # 平移矩形到中心在原点,方便后续坐标转换
    rect_center = np.array(rectangle.centroid.coords[0])
    rect_2d_points = np.array(rectangle.exterior.coords) - rect_center
    
    # 转换为路径起点和终点处的3D矩形顶点
    start_3d = start_point + rect_2d_points @ local_coords
    end_3d = end_point + rect_2d_points @ local_coords
    
    # 生成侧面四边形面
    faces = []
    n_vert = len(start_3d) - 1  # 去除重复的收尾点
    for i in range(n_vert):
        # 四边形顶点索引:起点i、起点i+1、终点i+1、终点i
        face = [i, i+1, i+1+n_vert, i+n_vert]
        faces.append(face)
    # 添加首尾的矩形端面
    faces.append(list(range(n_vert)))
    faces.append(list(range(n_vert, n_vert*2)))
    
    # 创建当前段网格
    vertices = np.vstack([start_3d[:-1], end_3d[:-1]])
    return trimesh.Trimesh(vertices=vertices, faces=faces)

3. 路径转角连接(斜接样式)

处理路径段间的尖锐转角,生成无孔洞的过渡面:

def join_segments(prev_mesh, curr_mesh, join_style="mitre"):
    # 提取前一段终点和当前段起点的顶点
    prev_end_verts = prev_mesh.vertices[len(prev_mesh.vertices)//2:]
    curr_start_verts = curr_mesh.vertices[:len(curr_mesh.vertices)//2]
    
    # 斜接样式:直接连接对应顶点生成四边形过渡面
    join_faces = []
    n_vert = len(prev_end_verts)
    for i in range(n_vert):
        next_i = (i+1) % n_vert
        face = [i, next_i, next_i+n_vert, i+n_vert]
        join_faces.append(face)
    
    # 创建过渡网格并合并
    join_verts = np.vstack([prev_end_verts, curr_start_verts])
    join_mesh = trimesh.Trimesh(vertices=join_verts, faces=join_faces)
    return trimesh.util.concatenate([prev_mesh, join_mesh, curr_mesh])

4. 主流程与格式导出

import pyvista as pv

def generate_swept_mesh(path_array, rectangle, output_prefix="swept_object"):
    # 无头环境初始化PyVista
    pv.start_xvfb()
    
    total_mesh = None
    # 遍历所有路径段
    for i in range(len(path_array)-1):
        start = path_array[i]
        end = path_array[i+1]
        segment = sweep_segment(start, end, rectangle)
        
        if total_mesh is None:
            total_mesh = segment
        else:
            total_mesh = join_segments(total_mesh, segment)
    
    # 导出为多种格式
    total_mesh.export(f"{output_prefix}.stl")
    total_mesh.export(f"{output_prefix}.ply")
    # GLB导出需借助PyVista
    pv_mesh = pv.wrap(total_mesh)
    pv_mesh.save(f"{output_prefix}.glb")

# 示例调用
if __name__ == "__main__":
    # 真3D路径示例(段间有夹角)
    sample_path = np.array([
        [0, 0, 0],
        [1, 0, 1],
        [2, 1, 0],
        [3, 2, 2]
    ])
    # Shapely矩形示例
    sample_rect = Polygon([(0,0), (1,0), (1,0.5), (0,0.5)])
    generate_swept_mesh(sample_path, sample_rect)

扩展说明

  • 圆角连接:若需要圆角过渡,可在转角处生成小段圆弧路径,用sweep_segment生成圆角网格后再合并到总网格中
  • 坐标异常处理:代码已处理路径与世界上轴平行的特殊情况,避免坐标系计算失败
  • 无头环境验证:Docker容器中需确保xvfb服务正常运行,PyVista依赖其完成GLB格式的导出

内容的提问来源于stack exchange,提问作者swiss_knight

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:17:16