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
相关产品推荐
相关产品推荐

