Search code examples
python3dtrimesh

Trimesh, Making two mesh objects merge with each other


I have a script that places two sets of meshes into a list. When I want to export the result, I load all the objects into a scene and then I export the scene. One being a set of slanted cylinders, and the other a set of vertical cylinders.

Each slanted cylinder is translated and transformed so that it is pointing towards the next (closest) vertical cylinder, but for some reason when the final scene is exported the slanted cylinders appear below the vertical cylinders.

the slanted beams/braces that are present are supposed to start at the top of each cylinder and move across to the next closest cylinder.

**How can I make it so the slanted cylinders are merged together instead of appearing below the vertical cylinders? **

Here is my implementation;

import trimesh
import numpy as np

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)
        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

Text File of List of points

Current Result


Solution

  • With the above mentioned tweaks, here's some output I used to check it- note I might have flipped it vertically- but should be enough for you to get yours working:

    enter image description here

    Updated code as follows:

    import trimesh
    import numpy as np
    
    #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
    
    def find_angle_between_points(point1, point2):
        # Calculate the angle between the two vectors
    
        print("P1 ", point1)
        print("P2 ", point2)
    
        angle = np.arccos(np.dot(point1, point2-point1) / (np.linalg.norm(point1) * np.linalg.norm(point2-point1)))
        print("NormP1 ", np.linalg.norm(point1))
        print("NormP2 ", np.linalg.norm(point2))
    
    
        return np.degrees(angle)
    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 main():
    
        print("IN MAIN")
        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],height/2))
            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
                print("direction", Direction)
                print("angle ", Angle)
    
                rotation_matrix = trimesh.geometry.align_vectors([0, 0, 1], Direction, return_angle=False)
    
                print("r matrix ", rotation_matrix)
                distance = distance_between_points(current_cylinder, next_cylinder)
                print(distance)
    
                beam = trimesh.primitives.Cylinder(radius = 0.1, height = distance, transform=rotation_matrix, sections=32, mutable=True)
    
                beam.apply_translation(current_cylinder - Direction*0.5)
                beams.append(beam)
    
        scene.add_geometry(cylinders)
        scene.add_geometry(beams)
        scene.export("op.stl")
    
    if __name__ == '__main__':
        main()