22import pyvista as pv
33import trimesh
44from pydantic import BaseModel , Field
5- from tesseract_core .runtime import Array , Differentiable , Float32
5+ from tesseract_core .runtime import Array , Float32
66
77#
88# Schemata
1212class InputSchema (BaseModel ):
1313 """Input schema for bar geometry design and SDF generation."""
1414
15- differentiable_parameters : Differentiable [
15+ differentiable_parameters : list [
1616 Array [
1717 (None ,),
1818 Float32 ,
@@ -26,12 +26,14 @@ class InputSchema(BaseModel):
2626 )
2727 )
2828
29- non_differentiable_parameters : Array [
30- (None ,),
31- Float32 ,
29+ non_differentiable_parameters : list [
30+ Array [
31+ (None ,),
32+ Float32 ,
33+ ]
3234 ] = Field (description = "Flattened array of non-differentiable geometry parameters." )
3335
34- static_parameters : list [int ] = Field (
36+ static_parameters : list [list [ int ] ] = Field (
3537 description = (
3638 "List of integers used to construct the geometry."
3739 " The first integer is the number of bars, and the second integer is the number of vertices per bar."
@@ -53,60 +55,63 @@ class TriangularMesh(BaseModel):
5355
5456
5557class OutputSchema (BaseModel ):
56- """Output schema for generated geometry and SDF field ."""
58+ """Output schema for generated geometry."""
5759
58- mesh : TriangularMesh = Field (
59- description = "Triangular mesh representation of the geometry "
60+ meshes : list [ TriangularMesh ] = Field (
61+ description = "Triangular meshes representing the geometries "
6062 )
6163
6264
63- #
64- # Helper functions
65- #
65+ def pyvista_to_trimesh (mesh : pv .PolyData ) -> trimesh .Trimesh :
66+ """Convert a pyvista mesh to a trimesh style polygon mesh."""
67+ points = mesh .points
68+ points_per_face = mesh .faces [0 ]
69+ n_faces = mesh .faces .shape [0 ] // (points_per_face + 1 )
70+
71+ faces = mesh .faces .reshape (n_faces , (points_per_face + 1 ))[:, 1 :]
72+
73+ return trimesh .Trimesh (vertices = points , faces = faces )
6674
6775
68- def build_geometry (
69- differentiable_parameters : np .ndarray ,
70- non_differentiable_parameters : np .ndarray ,
71- static_parameters : list [int ],
76+ def build_geometries (
77+ differentiable_parameters : list [np .ndarray ],
78+ non_differentiable_parameters : list [np .ndarray ],
79+ static_parameters : list [list [int ]],
80+ string_parameters : list [str ],
7281) -> list [trimesh .Trimesh ]:
7382 """Build a pyvista geometry from the parameters.
7483
7584 The parameters are expected to be of shape (n_chains, n_edges_per_chain + 1, 3),
7685 """
77- n_chains = static_parameters [0 ]
78- n_vertices_per_chain = static_parameters [1 ]
79- geometry = []
80-
81- params = differentiable_parameters .reshape ((n_chains , n_vertices_per_chain , 3 ))
82- radius = non_differentiable_parameters [0 ]
83-
84- for chain in range (n_chains ):
85- tube = pv .Spline (points = params [chain ]).tube (
86- radius = radius , capping = True , n_sides = 30
86+ n_geometrics = len (differentiable_parameters )
87+ geometries = []
88+ for i in range (n_geometrics ):
89+ n_chains = static_parameters [i ][0 ]
90+ n_vertices_per_chain = static_parameters [i ][1 ]
91+ geometry = []
92+
93+ params = differentiable_parameters [i ].reshape (
94+ (n_chains , n_vertices_per_chain , 3 )
8795 )
88- tube = tube .triangulate ()
89- tube = pyvista_to_trimesh (tube )
90- geometry .append (tube )
96+ radius = non_differentiable_parameters [i ][0 ]
9197
92- # convert each geometry in a trimesh style mesh and combine them
93- mesh = geometry [0 ]
98+ for chain in range (n_chains ):
99+ tube = pv .Spline (points = params [chain ]).tube (
100+ radius = radius , capping = True , n_sides = 30
101+ )
102+ tube = tube .triangulate ()
103+ tube = pyvista_to_trimesh (tube )
104+ geometry .append (tube )
94105
95- for geom in geometry [ 1 :]:
96- mesh = mesh . union ( geom )
106+ # convert each geometry in a trimesh style mesh and combine them
107+ mesh = geometry [ 0 ]
97108
98- return mesh
109+ for geom in geometry [1 :]:
110+ mesh = mesh .union (geom )
99111
112+ geometries .append (mesh )
100113
101- def pyvista_to_trimesh (mesh : pv .PolyData ) -> trimesh .Trimesh :
102- """Convert a pyvista mesh to a trimesh style polygon mesh."""
103- points = mesh .points
104- points_per_face = mesh .faces [0 ]
105- n_faces = mesh .faces .shape [0 ] // (points_per_face + 1 )
106-
107- faces = mesh .faces .reshape (n_faces , (points_per_face + 1 ))[:, 1 :]
108-
109- return trimesh .Trimesh (vertices = points , faces = faces )
114+ return geometries
110115
111116
112117#
@@ -123,15 +128,19 @@ def apply(inputs: InputSchema) -> OutputSchema:
123128 Returns:
124129 Output schema with generated mesh and SDF field.
125130 """
126- mesh = build_geometry (
131+ meshes = build_geometries (
127132 differentiable_parameters = inputs .differentiable_parameters ,
128133 non_differentiable_parameters = inputs .non_differentiable_parameters ,
129134 static_parameters = inputs .static_parameters ,
135+ string_parameters = inputs .string_parameters ,
130136 )
131137
132138 return OutputSchema (
133- mesh = TriangularMesh (
134- points = mesh .vertices .astype (np .float32 ),
135- faces = mesh .faces .astype (np .int32 ),
136- ),
139+ meshes = [
140+ TriangularMesh (
141+ points = mesh .vertices .astype (np .float32 ),
142+ faces = mesh .faces .astype (np .int32 ),
143+ )
144+ for mesh in meshes
145+ ],
137146 )
0 commit comments