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

Trimesh中如何让倾斜圆柱与垂直圆柱正确融合而非错位?

问题:Trimesh中倾斜支撑圆柱与垂直圆柱错位,如何实现正确连接?

我编写了一段脚本,将垂直圆柱和倾斜支撑圆柱存入列表,导出时加载到Trimesh Scene中再导出。原本每个倾斜圆柱应该从垂直圆柱顶部延伸至相邻垂直圆柱的顶部,但导出后的场景中,倾斜圆柱却出现在垂直圆柱下方,完全错位。

以下是我的实现代码:

import trimesh
import numpy as np
import math  # 原代码未导入该模块,调用math.degrees会报错

def read_blue_points_file(filename):
    """Reads a text file of blue points and returns an array of points."""
    points = []
    with open(filename, "r") as f:
        for line in f:
            point = [float(x) for x in line.split(",")]
            points.append(point)
    return np.array(points)

def find_angle_between_points(point1, point2):
    # Calculate the angle between the two vectors
    angle = np.arccos(np.dot(point1, point2) / (np.linalg.norm(point1) * np.linalg.norm(point2)))
    return math.degrees(angle)

# input two XYZ points, return distance between points
def distance_between_points(point1, point2):
    # Convert the points to numpy arrays.
    point1 = np.array(point1)
    point2 = np.array(point2)
    # Calculate the difference between the two points.
    difference = np.subtract(point2, point1)
    # Calculate the norm of the difference vector.
    norm = np.linalg.norm(difference)
    # Return the distance.
    return norm

# 主逻辑
connection_points = read_blue_points_file("blue_points.txt")
cylinders = []
beams = []
scene = trimesh.Scene()

# Sort the array by the X coordinate
connection_points = connection_points[connection_points[:, 0].argsort()]
print(connection_points)

# Create Cylinders
for point in connection_points:
    height = point[2]
    cylinder = trimesh.primitives.Cylinder(radius=0.5, height=height, transform=None, sections=32, mutable=True)
    cylinder.apply_translation((point[0], point[1], 0))
    cylinder.collide = False
    cylinders.append(cylinder)

for index, point in enumerate(connection_points):
    if index < len(connection_points) - 1:
        current_cylinder = point
        next_cylinder = connection_points[index + 1]

        Angle = find_angle_between_points(current_cylinder, next_cylinder)
        Direction = current_cylinder - next_cylinder

        rotation_matrix = trimesh.transformations.rotation_matrix(angle=Angle, direction=Direction)
        distance = distance_between_points(current_cylinder, next_cylinder)
        beam = trimesh.primitives.Cylinder(radius=0.1, height=distance/2, transform=rotation_matrix, sections=32, mutable=True)
        beam.apply_translation(next_cylinder)
        beams.append(beam)

# 原代码缺失的场景导出逻辑
for cyl in cylinders:
    scene.add_geometry(cyl)
for beam in beams:
    scene.add_geometry(beam)
scene.export("result.glb")

错误分析与修正方案

1. 角度计算逻辑完全错误

原find_angle_between_points计算的是两点相对于原点的向量夹角,和倾斜圆柱需要的旋转角度无关。正确做法是直接让圆柱轴线对齐「当前圆柱顶部→下一个圆柱顶部」的向量,用trimesh.geometry.align_vectors生成旋转矩阵即可,无需手动计算角度。

2. 旋转矩阵角度单位不匹配

trimesh.transformations.rotation_matrix要求输入弧度,但原函数返回的是角度,直接使用会导致旋转量完全错误。

3. 倾斜圆柱长度设置错误

圆柱的height参数就是轴线的长度,原代码设为distance/2会让圆柱长度仅为两点间距的一半,直接导致错位。

4. 倾斜圆柱平移位置错误

原代码将圆柱平移到next_cylinder位置,但倾斜圆柱的中心应该在两个顶部点的中点,才能让两端刚好连接到圆柱顶部。

5. 旋转方向向量错误

原代码用current_cylinder - next_cylinder作为旋转方向,应该使用next_cylinder - current_cylinder作为目标方向,让圆柱从当前顶部指向下一个顶部。


修正后的完整代码

import trimesh
import numpy as np

def read_blue_points_file(filename):
    """读取蓝点文本文件,返回点数组"""
    points = []
    with open(filename, "r") as f:
        for line in f:
            point = [float(x) for x in line.split(",")]
            points.append(point)
    return np.array(points)

def distance_between_points(point1, point2):
    """计算两点间距离"""
    return np.linalg.norm(np.array(point2) - np.array(point1))

# 主逻辑
connection_points = read_blue_points_file("blue_points.txt")
cylinders = []
beams = []
scene = trimesh.Scene()

# 按X坐标排序点
connection_points = connection_points[connection_points[:, 0].argsort()]
print(connection_points)

# 创建垂直圆柱
for point in connection_points:
    x, y, z = point
    # 圆柱默认从(0,0,0)到(0,0,z),平移后底部在(x,y,0),顶部在(x,y,z)
    cylinder = trimesh.primitives.Cylinder(radius=0.5, height=z, sections=32, mutable=True)
    cylinder.apply_translation((x, y, 0))
    cylinder.collide = False
    cylinders.append(cylinder)

# 创建倾斜支撑圆柱
for index in range(len(connection_points) - 1):
    top_current = connection_points[index]
    top_next = connection_points[index + 1]
    
    # 两点间距离作为圆柱高度
    beam_length = distance_between_points(top_current, top_next)
    # 两点中点作为圆柱的中心位置
    mid_point = (top_current + top_next) / 2
    
    # 生成旋转矩阵:将圆柱默认Z轴(0,0,1)对齐到两点连线方向
    target_dir = top_next - top_current
    rotation_matrix = trimesh.geometry.align_vectors([0,0,1], target_dir)
    
    # 先旋转圆柱,再平移到中点
    beam = trimesh.primitives.Cylinder(radius=0.1, height=beam_length, sections=32, mutable=True)
    beam.apply_transform(rotation_matrix)
    beam.apply_translation(mid_point)
    beams.append(beam)

# 将所有几何体添加到场景并导出
scene.add_geometry(cylinders)
scene.add_geometry(beams)
scene.export("corrected_result.glb")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:12:06