From 27ad95379afb09b012997f92708f4d49b33889c0 Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Mon, 13 May 2024 16:34:10 +0200 Subject: [PATCH 01/15] Added trimesh to depencencies --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index e1d2b0d..a3fb6ad 100644 --- a/setup.cfg +++ b/setup.cfg @@ -61,6 +61,7 @@ install_requires = packaging resolve-robotics-uri-py scipy + trimesh xmltodict [options.extras_require] From 8acc9cdf37c2df9ba7114eac979c6c1e8b2b436d Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Mon, 13 May 2024 16:35:42 +0200 Subject: [PATCH 02/15] Implemented MeshBuilder class, plus its inertia and geometry overrides --- src/rod/builder/primitives.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/rod/builder/primitives.py b/src/rod/builder/primitives.py index 8d51b9c..28c30a2 100644 --- a/src/rod/builder/primitives.py +++ b/src/rod/builder/primitives.py @@ -1,4 +1,9 @@ import dataclasses +import pathlib +from typing import Union + +import trimesh +from numpy.typing import ArrayLike import rod from rod.builder.primitive_builder import PrimitiveBuilder @@ -54,3 +59,28 @@ def _geometry(self) -> rod.Geometry: return rod.Geometry( cylinder=rod.Cylinder(radius=self.radius, length=self.length) ) + + +@dataclasses.dataclass +class MeshBuilder(PrimitiveBuilder): + mesh_path: Union[str, pathlib.Path] + scale: ArrayLike + + def __post_init__(self) -> None: + self.mesh: trimesh.base.Trimesh = trimesh.load( + str(self.mesh_path), force="mesh" + ) + assert self.scale.shape == ( + 3, + ), f"Scale must be a 3D vector, got {self.scale.shape}" + + def _inertia(self) -> rod.Inertia: + inertia = self.mesh.moment_inertia + return rod.Inertia( + ixx=inertia[0, 0], + iyy=inertia[1, 1], + izz=inertia[2, 2], + ) + + def _geometry(self) -> rod.Geometry: + return rod.Geometry(mesh=rod.Mesh(uri=str(self.mesh_path), scale=self.scale)) From 16e652c14a9801000b20a03f28b451acc31a474a Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Mon, 13 May 2024 16:36:24 +0200 Subject: [PATCH 03/15] Implemented 2 tests on meshbuilder 1. Creation of a meshbuilder on a box 2. Creation of a meshbuilder on a custom mesh --- tests/test_meshbuilder.py | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/test_meshbuilder.py diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py new file mode 100644 index 0000000..ca1af5c --- /dev/null +++ b/tests/test_meshbuilder.py @@ -0,0 +1,50 @@ +from rod.builder.primitives import MeshBuilder +import trimesh +import os +import numpy as np +import pathlib + + +def test_builder_creation(): + mesh = trimesh.creation.box([1, 1, 1]) + # Temporary write to file because rod Mesh works with uri + filename = pathlib.Path(__file__).parent / "test_mesh.stl" + mesh.export(filename) + builder = MeshBuilder( + name="test_mesh", mesh_path=filename, mass=1.0, scale=np.array([1.0, 1.0, 1.0]) + ) + # Assert on meshes (builder mesh vs trimesh) + try: + assert builder.mesh.vertices.shape == mesh.vertices.shape + assert builder.mesh.faces.shape == mesh.faces.shape + assert builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() + assert builder.mesh.volume == mesh.volume + finally: + os.remove(filename) + + +def test_builder_creation_custom_mesh(): + # Create a custom mesh + vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]]) + faces = np.array([[0, 1, 2], [0, 2, 3]]) + custom_mesh = trimesh.Trimesh(vertices=vertices, faces=faces) + + # Temporary write to file because rod Mesh works with uri + filename = pathlib.Path(__file__).parent / "test_custom_mesh.stl" + custom_mesh.export(filename) + + builder = MeshBuilder( + name="test_custom_mesh", + mesh_path=filename, + mass=1.0, + scale=np.array([1.0, 1.0, 1.0]), + ) + + # Assert on meshes (builder mesh vs custom_mesh) + try: + assert builder.mesh.vertices.shape == custom_mesh.vertices.shape + assert builder.mesh.faces.shape == custom_mesh.faces.shape + assert builder.mesh.moment_inertia.all() == custom_mesh.moment_inertia.all() + assert builder.mesh.volume == custom_mesh.volume + finally: + os.remove(filename) From f10a04c4d693d85bbdcd9909430ce26e226b66c7 Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Mon, 13 May 2024 16:44:32 +0200 Subject: [PATCH 04/15] Run isort on meshbuilder tests --- tests/test_meshbuilder.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py index ca1af5c..04509ee 100644 --- a/tests/test_meshbuilder.py +++ b/tests/test_meshbuilder.py @@ -1,9 +1,11 @@ -from rod.builder.primitives import MeshBuilder -import trimesh import os -import numpy as np import pathlib +import numpy as np +import trimesh + +from rod.builder.primitives import MeshBuilder + def test_builder_creation(): mesh = trimesh.creation.box([1, 1, 1]) From 91f2332edefbb360cae9bd466848f7e392d5652c Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Mon, 13 May 2024 16:51:44 +0200 Subject: [PATCH 05/15] Updated conda dependencies on github actions with trimesh --- .github/workflows/ci_cd.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 42a628f..0b8ddaf 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -122,7 +122,8 @@ jobs: pptree \ idyntree \ pytest \ - robot_descriptions + robot_descriptions \ + trimesh # pytest-icdiff \ # creates problems on macOS mamba install -y gz-sim7 idyntree From 38a1a5c189647a21282fa230332ddd874a6a7bcb Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Tue, 14 May 2024 15:23:14 +0200 Subject: [PATCH 06/15] Updated scale type hinting to numpy NDArray --- src/rod/builder/primitives.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/rod/builder/primitives.py b/src/rod/builder/primitives.py index 28c30a2..7ac884d 100644 --- a/src/rod/builder/primitives.py +++ b/src/rod/builder/primitives.py @@ -3,7 +3,7 @@ from typing import Union import trimesh -from numpy.typing import ArrayLike +from numpy.typing import NDArray import rod from rod.builder.primitive_builder import PrimitiveBuilder @@ -64,7 +64,7 @@ def _geometry(self) -> rod.Geometry: @dataclasses.dataclass class MeshBuilder(PrimitiveBuilder): mesh_path: Union[str, pathlib.Path] - scale: ArrayLike + scale: NDArray def __post_init__(self) -> None: self.mesh: trimesh.base.Trimesh = trimesh.load( @@ -78,7 +78,10 @@ def _inertia(self) -> rod.Inertia: inertia = self.mesh.moment_inertia return rod.Inertia( ixx=inertia[0, 0], + ixy=inertia[0, 1], + ixz=inertia[0, 2], iyy=inertia[1, 1], + iyz=inertia[1, 2], izz=inertia[2, 2], ) From 7113789d5f42392314d7c7a9dbc94a4c4c8bd14c Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Tue, 14 May 2024 15:55:40 +0200 Subject: [PATCH 07/15] Updated test on meshbuilder to use tempfile rather than creating file manually --- tests/test_meshbuilder.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py index 04509ee..cef2ab8 100644 --- a/tests/test_meshbuilder.py +++ b/tests/test_meshbuilder.py @@ -1,5 +1,6 @@ import os import pathlib +import tempfile import numpy as np import trimesh @@ -9,21 +10,20 @@ def test_builder_creation(): mesh = trimesh.creation.box([1, 1, 1]) - # Temporary write to file because rod Mesh works with uri - filename = pathlib.Path(__file__).parent / "test_mesh.stl" - mesh.export(filename) - builder = MeshBuilder( - name="test_mesh", mesh_path=filename, mass=1.0, scale=np.array([1.0, 1.0, 1.0]) - ) - # Assert on meshes (builder mesh vs trimesh) - try: - assert builder.mesh.vertices.shape == mesh.vertices.shape - assert builder.mesh.faces.shape == mesh.faces.shape - assert builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() - assert builder.mesh.volume == mesh.volume - finally: - os.remove(filename) + print(mesh.vertices.shape) + # Temporary write to file because rod Mesh works with uri + with tempfile.NamedTemporaryFile() as fp: + #fp.write(trimesh.exchange.stl.export_stl(mesh)) + mesh.export(fp.name, file_type="stl") + + builder = MeshBuilder( + name="test_mesh", mesh_path=fp.name, mass=1.0, scale=np.array([1.0, 1.0, 1.0]) + ) + assert builder.mesh.vertices.shape == mesh.vertices.shape, f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}" + assert builder.mesh.faces.shape == mesh.faces.shape, f"{builder.mesh.faces.shape} != {mesh.faces.shape}" + assert builder.mesh.moment_inertia.all() == mesh.moment_inertia.all(), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" + assert builder.mesh.volume == mesh.volume, f"{builder.mesh.volume} != {mesh.volume}" def test_builder_creation_custom_mesh(): # Create a custom mesh From 22b981636d1642f04ee662da6e9ba5c22fbc4e7e Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Tue, 14 May 2024 15:56:32 +0200 Subject: [PATCH 08/15] Forced mesh type to be .stl on mesh load --- src/rod/builder/primitives.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/rod/builder/primitives.py b/src/rod/builder/primitives.py index 7ac884d..1c11531 100644 --- a/src/rod/builder/primitives.py +++ b/src/rod/builder/primitives.py @@ -67,12 +67,14 @@ class MeshBuilder(PrimitiveBuilder): scale: NDArray def __post_init__(self) -> None: - self.mesh: trimesh.base.Trimesh = trimesh.load( - str(self.mesh_path), force="mesh" - ) - assert self.scale.shape == ( - 3, - ), f"Scale must be a 3D vector, got {self.scale.shape}" + self.mesh: trimesh.base.Trimesh = trimesh.load( + str(self.mesh_path), + file_type="stl", + force="mesh", + ) + assert self.scale.shape == ( + 3, + ), f"Scale must be a 3D vector, got {self.scale.shape}" def _inertia(self) -> rod.Inertia: inertia = self.mesh.moment_inertia From 1fbf07f13f4cba553a555e1cecb5459381efc8cd Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Tue, 14 May 2024 15:59:03 +0200 Subject: [PATCH 09/15] Added docstring to meshbuilder and reformatted affected files --- src/rod/builder/primitives.py | 24 ++++++++++++++++-------- tests/test_meshbuilder.py | 24 ++++++++++++++++++------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/rod/builder/primitives.py b/src/rod/builder/primitives.py index 1c11531..008e281 100644 --- a/src/rod/builder/primitives.py +++ b/src/rod/builder/primitives.py @@ -67,14 +67,22 @@ class MeshBuilder(PrimitiveBuilder): scale: NDArray def __post_init__(self) -> None: - self.mesh: trimesh.base.Trimesh = trimesh.load( - str(self.mesh_path), - file_type="stl", - force="mesh", - ) - assert self.scale.shape == ( - 3, - ), f"Scale must be a 3D vector, got {self.scale.shape}" + """ + Post-initialization method for the class. + Loads the mesh from the specified file path and performs necessary checks. + + Raises: + AssertionError: If the scale is not a 3D vector. + """ + + self.mesh: trimesh.base.Trimesh = trimesh.load( + str(self.mesh_path), + file_type="stl", + force="mesh", + ) + assert self.scale.shape == ( + 3, + ), f"Scale must be a 3D vector, got {self.scale.shape}" def _inertia(self) -> rod.Inertia: inertia = self.mesh.moment_inertia diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py index cef2ab8..e560a52 100644 --- a/tests/test_meshbuilder.py +++ b/tests/test_meshbuilder.py @@ -14,16 +14,28 @@ def test_builder_creation(): # Temporary write to file because rod Mesh works with uri with tempfile.NamedTemporaryFile() as fp: - #fp.write(trimesh.exchange.stl.export_stl(mesh)) + # fp.write(trimesh.exchange.stl.export_stl(mesh)) mesh.export(fp.name, file_type="stl") builder = MeshBuilder( - name="test_mesh", mesh_path=fp.name, mass=1.0, scale=np.array([1.0, 1.0, 1.0]) + name="test_mesh", + mesh_path=fp.name, + mass=1.0, + scale=np.array([1.0, 1.0, 1.0]), ) - assert builder.mesh.vertices.shape == mesh.vertices.shape, f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}" - assert builder.mesh.faces.shape == mesh.faces.shape, f"{builder.mesh.faces.shape} != {mesh.faces.shape}" - assert builder.mesh.moment_inertia.all() == mesh.moment_inertia.all(), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" - assert builder.mesh.volume == mesh.volume, f"{builder.mesh.volume} != {mesh.volume}" + assert ( + builder.mesh.vertices.shape == mesh.vertices.shape + ), f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}" + assert ( + builder.mesh.faces.shape == mesh.faces.shape + ), f"{builder.mesh.faces.shape} != {mesh.faces.shape}" + assert ( + builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() + ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" + assert ( + builder.mesh.volume == mesh.volume + ), f"{builder.mesh.volume} != {mesh.volume}" + def test_builder_creation_custom_mesh(): # Create a custom mesh From d1d73f61e5303487706bd53798ce55c2db80d551 Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Tue, 14 May 2024 17:38:10 +0200 Subject: [PATCH 10/15] Added tempfile inside context for other meshbuilder test --- tests/test_meshbuilder.py | 65 ++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py index e560a52..2a6cf00 100644 --- a/tests/test_meshbuilder.py +++ b/tests/test_meshbuilder.py @@ -10,7 +10,6 @@ def test_builder_creation(): mesh = trimesh.creation.box([1, 1, 1]) - print(mesh.vertices.shape) # Temporary write to file because rod Mesh works with uri with tempfile.NamedTemporaryFile() as fp: @@ -23,42 +22,46 @@ def test_builder_creation(): mass=1.0, scale=np.array([1.0, 1.0, 1.0]), ) - assert ( - builder.mesh.vertices.shape == mesh.vertices.shape - ), f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}" - assert ( - builder.mesh.faces.shape == mesh.faces.shape - ), f"{builder.mesh.faces.shape} != {mesh.faces.shape}" - assert ( - builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() - ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" - assert ( - builder.mesh.volume == mesh.volume - ), f"{builder.mesh.volume} != {mesh.volume}" + assert ( + builder.mesh.vertices.shape == mesh.vertices.shape + ), f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}" + assert ( + builder.mesh.faces.shape == mesh.faces.shape + ), f"{builder.mesh.faces.shape} != {mesh.faces.shape}" + assert ( + builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() + ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" + assert ( + builder.mesh.volume == mesh.volume + ), f"{builder.mesh.volume} != {mesh.volume}" def test_builder_creation_custom_mesh(): # Create a custom mesh vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]]) faces = np.array([[0, 1, 2], [0, 2, 3]]) - custom_mesh = trimesh.Trimesh(vertices=vertices, faces=faces) + mesh = trimesh.Trimesh(vertices=vertices, faces=faces) # Temporary write to file because rod Mesh works with uri - filename = pathlib.Path(__file__).parent / "test_custom_mesh.stl" - custom_mesh.export(filename) - - builder = MeshBuilder( - name="test_custom_mesh", - mesh_path=filename, - mass=1.0, - scale=np.array([1.0, 1.0, 1.0]), - ) + with tempfile.NamedTemporaryFile() as fp: + # fp.write(trimesh.exchange.stl.export_stl(mesh)) + mesh.export(fp.name, file_type="stl") - # Assert on meshes (builder mesh vs custom_mesh) - try: - assert builder.mesh.vertices.shape == custom_mesh.vertices.shape - assert builder.mesh.faces.shape == custom_mesh.faces.shape - assert builder.mesh.moment_inertia.all() == custom_mesh.moment_inertia.all() - assert builder.mesh.volume == custom_mesh.volume - finally: - os.remove(filename) + builder = MeshBuilder( + name="test_mesh", + mesh_path=fp.name, + mass=1.0, + scale=np.array([1.0, 1.0, 1.0]), + ) + assert ( + builder.mesh.vertices.shape == mesh.vertices.shape + ), f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}" + assert ( + builder.mesh.faces.shape == mesh.faces.shape + ), f"{builder.mesh.faces.shape} != {mesh.faces.shape}" + assert ( + builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() + ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" + assert ( + builder.mesh.volume == mesh.volume + ), f"{builder.mesh.volume} != {mesh.volume}" \ No newline at end of file From 07789d3965ba1c8056effbb9feba2bca5fb79075 Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Tue, 14 May 2024 17:38:44 +0200 Subject: [PATCH 11/15] Added tempfile inside context for other meshbuilder test --- tests/test_meshbuilder.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py index 2a6cf00..5893ba2 100644 --- a/tests/test_meshbuilder.py +++ b/tests/test_meshbuilder.py @@ -31,9 +31,7 @@ def test_builder_creation(): assert ( builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" - assert ( - builder.mesh.volume == mesh.volume - ), f"{builder.mesh.volume} != {mesh.volume}" + assert builder.mesh.volume == mesh.volume, f"{builder.mesh.volume} != {mesh.volume}" def test_builder_creation_custom_mesh(): @@ -62,6 +60,4 @@ def test_builder_creation_custom_mesh(): assert ( builder.mesh.moment_inertia.all() == mesh.moment_inertia.all() ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}" - assert ( - builder.mesh.volume == mesh.volume - ), f"{builder.mesh.volume} != {mesh.volume}" \ No newline at end of file + assert builder.mesh.volume == mesh.volume, f"{builder.mesh.volume} != {mesh.volume}" From e00ee38d076d23b475780d8499bf92578280b778 Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Wed, 15 May 2024 09:47:18 +0200 Subject: [PATCH 12/15] Added extra type checks and extension parsig on mesh path --- src/rod/builder/primitives.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/rod/builder/primitives.py b/src/rod/builder/primitives.py index 008e281..dbf02d0 100644 --- a/src/rod/builder/primitives.py +++ b/src/rod/builder/primitives.py @@ -73,13 +73,26 @@ def __post_init__(self) -> None: Raises: AssertionError: If the scale is not a 3D vector. + TypeError: If the mesh_path is not a str or pathlib.Path. """ + if isinstance(self.mesh_path, str): + extension = pathlib.PurePath(self.mesh_path).suffix + elif isinstance(self.mesh_path, pathlib.Path): + extension = self.mesh_path.suffix + else: + raise TypeError( + f"Expected str or pathlib.Path for mesh_path, got {type(self.mesh_path)}" + ) + self.mesh: trimesh.base.Trimesh = trimesh.load( str(self.mesh_path), - file_type="stl", force="mesh", + file_type=extension.lstrip("."), ) + + if not isinstance(self.scale, NDArray): + raise TypeError(f"Expected numpy.ndarray for scale, got {type(self.scale)}") assert self.scale.shape == ( 3, ), f"Scale must be a 3D vector, got {self.scale.shape}" From f4bffdea7d74f70fb7d6b201877db1d106b38f73 Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Wed, 15 May 2024 09:47:47 +0200 Subject: [PATCH 13/15] Removed leftover comments --- tests/test_meshbuilder.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py index 5893ba2..665bfbe 100644 --- a/tests/test_meshbuilder.py +++ b/tests/test_meshbuilder.py @@ -13,7 +13,6 @@ def test_builder_creation(): # Temporary write to file because rod Mesh works with uri with tempfile.NamedTemporaryFile() as fp: - # fp.write(trimesh.exchange.stl.export_stl(mesh)) mesh.export(fp.name, file_type="stl") builder = MeshBuilder( @@ -42,7 +41,6 @@ def test_builder_creation_custom_mesh(): # Temporary write to file because rod Mesh works with uri with tempfile.NamedTemporaryFile() as fp: - # fp.write(trimesh.exchange.stl.export_stl(mesh)) mesh.export(fp.name, file_type="stl") builder = MeshBuilder( From fdc1fec0468fbc47f1b087e57d204ec86ee2985d Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Wed, 15 May 2024 14:04:48 +0200 Subject: [PATCH 14/15] Added type checks on mesh file type --- src/rod/builder/primitives.py | 8 +++----- tests/test_meshbuilder.py | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/rod/builder/primitives.py b/src/rod/builder/primitives.py index dbf02d0..aa196c1 100644 --- a/src/rod/builder/primitives.py +++ b/src/rod/builder/primitives.py @@ -77,9 +77,9 @@ def __post_init__(self) -> None: """ if isinstance(self.mesh_path, str): - extension = pathlib.PurePath(self.mesh_path).suffix + extension = self.mesh_path.split(".")[-1] elif isinstance(self.mesh_path, pathlib.Path): - extension = self.mesh_path.suffix + extension = str(self.mesh_path).split(".")[-1] else: raise TypeError( f"Expected str or pathlib.Path for mesh_path, got {type(self.mesh_path)}" @@ -88,11 +88,9 @@ def __post_init__(self) -> None: self.mesh: trimesh.base.Trimesh = trimesh.load( str(self.mesh_path), force="mesh", - file_type=extension.lstrip("."), + file_type=extension, ) - if not isinstance(self.scale, NDArray): - raise TypeError(f"Expected numpy.ndarray for scale, got {type(self.scale)}") assert self.scale.shape == ( 3, ), f"Scale must be a 3D vector, got {self.scale.shape}" diff --git a/tests/test_meshbuilder.py b/tests/test_meshbuilder.py index 665bfbe..18b91ee 100644 --- a/tests/test_meshbuilder.py +++ b/tests/test_meshbuilder.py @@ -12,7 +12,7 @@ def test_builder_creation(): mesh = trimesh.creation.box([1, 1, 1]) # Temporary write to file because rod Mesh works with uri - with tempfile.NamedTemporaryFile() as fp: + with tempfile.NamedTemporaryFile(suffix=".stl") as fp: mesh.export(fp.name, file_type="stl") builder = MeshBuilder( @@ -40,7 +40,7 @@ def test_builder_creation_custom_mesh(): mesh = trimesh.Trimesh(vertices=vertices, faces=faces) # Temporary write to file because rod Mesh works with uri - with tempfile.NamedTemporaryFile() as fp: + with tempfile.NamedTemporaryFile(suffix=".stl") as fp: mesh.export(fp.name, file_type="stl") builder = MeshBuilder( From 17d5028145958b5bf5e582643e8542cac4f381e6 Mon Sep 17 00:00:00 2001 From: Lorenzo Conti Date: Thu, 16 May 2024 14:49:48 +0200 Subject: [PATCH 15/15] Reverted extension extraction to usage of pathlib --- src/rod/builder/primitives.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rod/builder/primitives.py b/src/rod/builder/primitives.py index aa196c1..b6bb883 100644 --- a/src/rod/builder/primitives.py +++ b/src/rod/builder/primitives.py @@ -77,9 +77,9 @@ def __post_init__(self) -> None: """ if isinstance(self.mesh_path, str): - extension = self.mesh_path.split(".")[-1] + extension = pathlib.Path(self.mesh_path).suffix elif isinstance(self.mesh_path, pathlib.Path): - extension = str(self.mesh_path).split(".")[-1] + extension = self.mesh_path.suffix else: raise TypeError( f"Expected str or pathlib.Path for mesh_path, got {type(self.mesh_path)}"