mirror of
https://github.com/gumyr/build123d.git
synced 2026-01-30 12:20:41 -08:00
Adding unittests for Mesher class
This commit is contained in:
parent
582a07c104
commit
bc6189f448
2 changed files with 199 additions and 22 deletions
|
|
@ -217,38 +217,42 @@ class Mesher:
|
|||
must_preserve=False,
|
||||
)
|
||||
|
||||
def get_meta_data(self) -> list[str]:
|
||||
def get_meta_data(self) -> list[dict]:
|
||||
"""Retrieve all of the metadata"""
|
||||
meta_data_group = self.model.GetMetaDataGroup()
|
||||
meta_data_contents = []
|
||||
for i in range(meta_data_group.GetMetaDataCount()):
|
||||
meta_data = meta_data_group.GetMetaData(i)
|
||||
meta_data_contents.append(f"Name Space: {meta_data.GetNameSpace()}")
|
||||
meta_data_contents.append(f"Name: {meta_data.GetName()}")
|
||||
meta_data_contents.append(f"Type: {meta_data.GetType()}")
|
||||
meta_data_contents.append(f"Value: {meta_data.GetValue()}")
|
||||
meta_data_dict = {}
|
||||
meta_data_dict["name_space"] = meta_data.GetNameSpace()
|
||||
meta_data_dict["name"] = meta_data.GetName()
|
||||
meta_data_dict["type"] = meta_data.GetType()
|
||||
meta_data_dict["value"] = meta_data.GetValue()
|
||||
meta_data_contents.append(meta_data_dict)
|
||||
return meta_data_contents
|
||||
|
||||
def get_meta_data_by_key(self, name_space: str, name: str) -> list[str]:
|
||||
def get_meta_data_by_key(self, name_space: str, name: str) -> dict:
|
||||
"""Retrive the metadata value and type for the provided name space and name"""
|
||||
meta_data_group = self.model.GetMetaDataGroup()
|
||||
meta_data_contents = []
|
||||
meta_data_contents = {}
|
||||
meta_data = meta_data_group.GetMetaDataByKey(name_space, name)
|
||||
meta_data_contents.append(f"Type: {meta_data.GetType()}")
|
||||
meta_data_contents.append(f"Value: {meta_data.GetValue()}")
|
||||
meta_data_contents["type"] = meta_data.GetType()
|
||||
meta_data_contents["value"] = meta_data.GetValue()
|
||||
return meta_data_contents
|
||||
|
||||
def get_mesh_properties(self) -> list[str]:
|
||||
def get_mesh_properties(self) -> list[dict]:
|
||||
"""Retrieve the properties from all the meshes"""
|
||||
properties = []
|
||||
for mesh in self.meshes:
|
||||
properties += f"Name: {mesh.GetName()}"
|
||||
properties += f"Part Number: {mesh.GetPartNumber()}"
|
||||
property_dict = {}
|
||||
property_dict["name"] = mesh.GetName()
|
||||
property_dict["part_number"] = mesh.GetPartNumber()
|
||||
type_3mf = Lib3MF.ObjectType(mesh.GetType())
|
||||
properties += f"Type: {Mesher._map_3mf_to_b3d_mesh_type[type_3mf].name}"
|
||||
uuid_valid, uuid_value = mesh.GetUUID()
|
||||
if uuid_valid:
|
||||
properties += f"UUID: {uuid_value}"
|
||||
property_dict["type"] = Mesher._map_3mf_to_b3d_mesh_type[type_3mf].name
|
||||
_uuid_valid, uuid_value = mesh.GetUUID()
|
||||
property_dict["uuid"] = uuid_value # are bad values possible?
|
||||
properties.append(property_dict)
|
||||
return properties
|
||||
|
||||
@staticmethod
|
||||
def _is_facet_forward(
|
||||
|
|
@ -424,7 +428,10 @@ class Mesher:
|
|||
ocp_mesh_vertices, triangles, b3d_shape.center()
|
||||
)
|
||||
|
||||
# Add the meta data
|
||||
# Build the mesh
|
||||
mesh_3mf.SetGeometry(vertices_3mf, triangles_3mf)
|
||||
|
||||
# Add the mesh properties
|
||||
mesh_3mf.SetType(Mesher._map_b3d_mesh_type_3mf[mesh_type])
|
||||
if b3d_shape.label:
|
||||
mesh_3mf.SetName(b3d_shape.label)
|
||||
|
|
@ -435,9 +442,6 @@ class Mesher:
|
|||
# mesh_3mf.SetAttachmentAsThumbnail
|
||||
# mesh_3mf.SetPackagePart
|
||||
|
||||
# Create the mesh
|
||||
mesh_3mf.SetGeometry(vertices_3mf, triangles_3mf)
|
||||
|
||||
# Add color
|
||||
self._add_color(b3d_shape, mesh_3mf)
|
||||
|
||||
|
|
@ -514,6 +518,7 @@ class Mesher:
|
|||
for mesh in self.meshes:
|
||||
shape = self._get_shape(mesh)
|
||||
shape.label = mesh.GetName()
|
||||
# Extract color
|
||||
color_indices = []
|
||||
for triangle_property in mesh.GetAllTriangleProperties():
|
||||
color_indices.extend(
|
||||
|
|
@ -523,9 +528,13 @@ class Mesher:
|
|||
]
|
||||
)
|
||||
unique_color_indices = list(set(color_indices))
|
||||
try:
|
||||
color_group = self.model.GetColorGroupByID(unique_color_indices[0][0])
|
||||
except:
|
||||
shapes.append(shape) # There are no colors
|
||||
continue
|
||||
if len(unique_color_indices) > 1:
|
||||
warnings.warn("Warning multiple colors found on mesh - one used")
|
||||
color_group = self.model.GetColorGroupByID(unique_color_indices[0][0])
|
||||
warnings.warn("Warning multiple colors found on mesh - only one used")
|
||||
color_3mf = color_group.GetColor(unique_color_indices[0][1])
|
||||
color = (color_3mf.Red, color_3mf.Green, color_3mf.Blue, color_3mf.Alpha)
|
||||
color = (c / 255.0 for c in color)
|
||||
|
|
|
|||
168
tests/test_mesher.py
Normal file
168
tests/test_mesher.py
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
import os, unittest, uuid
|
||||
from build123d.build_enums import MeshType, Unit
|
||||
from build123d.topology import Compound, Solid
|
||||
from build123d.geometry import Color, Vector, VectorLike, Location
|
||||
from build123d.mesher import Mesher
|
||||
|
||||
|
||||
class DirectApiTestCase(unittest.TestCase):
|
||||
def assertTupleAlmostEquals(
|
||||
self,
|
||||
first: tuple[float, ...],
|
||||
second: tuple[float, ...],
|
||||
places: int,
|
||||
msg: str = None,
|
||||
):
|
||||
"""Check Tuples"""
|
||||
self.assertEqual(len(second), len(first))
|
||||
for i, j in zip(second, first):
|
||||
self.assertAlmostEqual(i, j, places, msg=msg)
|
||||
|
||||
def assertVectorAlmostEquals(
|
||||
self, first: Vector, second: VectorLike, places: int, msg: str = None
|
||||
):
|
||||
second_vector = Vector(second)
|
||||
self.assertAlmostEqual(first.X, second_vector.X, places, msg=msg)
|
||||
self.assertAlmostEqual(first.Y, second_vector.Y, places, msg=msg)
|
||||
self.assertAlmostEqual(first.Z, second_vector.Z, places, msg=msg)
|
||||
|
||||
|
||||
class TestProperties(unittest.TestCase):
|
||||
def test_version(self):
|
||||
exporter = Mesher()
|
||||
self.assertEqual(exporter.library_version, "2.2.0")
|
||||
|
||||
def test_units(self):
|
||||
for unit in Unit:
|
||||
exporter = Mesher(unit=unit)
|
||||
exporter.add_shape(Solid.make_box(1, 1, 1))
|
||||
exporter.write("test.3mf")
|
||||
importer = Mesher()
|
||||
_shape = importer.read("test.3mf")
|
||||
self.assertEqual(unit, importer.model_unit)
|
||||
|
||||
def test_vertex_and_triangle_counts(self):
|
||||
exporter = Mesher()
|
||||
exporter.add_shape(Solid.make_box(1, 1, 1))
|
||||
self.assertEqual(exporter.vertex_counts[0], 8)
|
||||
self.assertEqual(exporter.triangle_counts[0], 12)
|
||||
|
||||
def test_mesh_counts(self):
|
||||
exporter = Mesher()
|
||||
exporter.add_shape(Solid.make_box(1, 1, 1))
|
||||
exporter.add_shape(Solid.make_cone(1, 0, 2))
|
||||
self.assertEqual(exporter.mesh_count, 2)
|
||||
|
||||
|
||||
class TestMetaData(unittest.TestCase):
|
||||
def test_add_meta_data(self):
|
||||
exporter = Mesher()
|
||||
exporter.add_shape(Solid.make_box(1, 1, 1))
|
||||
exporter.add_meta_data("test_space", "test0", "some data", "str", True)
|
||||
exporter.add_meta_data("test_space", "test1", "more data", "str", True)
|
||||
exporter.write("test.3mf")
|
||||
importer = Mesher()
|
||||
_shape = importer.read("test.3mf")
|
||||
imported_meta_data: list[dict] = importer.get_meta_data()
|
||||
self.assertEqual(imported_meta_data[0]["name_space"], "test_space")
|
||||
self.assertEqual(imported_meta_data[0]["name"], "test0")
|
||||
self.assertEqual(imported_meta_data[0]["value"], "some data")
|
||||
self.assertEqual(imported_meta_data[0]["type"], "str")
|
||||
self.assertEqual(imported_meta_data[1]["name_space"], "test_space")
|
||||
self.assertEqual(imported_meta_data[1]["name"], "test1")
|
||||
self.assertEqual(imported_meta_data[1]["value"], "more data")
|
||||
self.assertEqual(imported_meta_data[1]["type"], "str")
|
||||
|
||||
def test_add_code(self):
|
||||
exporter = Mesher()
|
||||
exporter.add_shape(Solid.make_box(1, 1, 1))
|
||||
exporter.add_code_to_metadata()
|
||||
exporter.write("test.3mf")
|
||||
importer = Mesher()
|
||||
_shape = importer.read("test.3mf")
|
||||
source_code = importer.get_meta_data_by_key("build123d", "test_mesher.py")
|
||||
self.assertEqual(len(source_code), 2)
|
||||
self.assertEqual(source_code["type"], "python")
|
||||
self.assertGreater(len(source_code["value"]), 10)
|
||||
|
||||
|
||||
class TestMeshProperties(unittest.TestCase):
|
||||
def test_properties(self):
|
||||
# Note: MeshType.OTHER can't be used with a Solid shape
|
||||
for mesh_type in [MeshType.MODEL, MeshType.SUPPORT, MeshType.SOLIDSUPPORT]:
|
||||
with self.subTest("MeshTYpe", mesh_type=mesh_type):
|
||||
exporter = Mesher()
|
||||
if mesh_type != MeshType.SUPPORT:
|
||||
test_uuid = uuid.uuid1()
|
||||
else:
|
||||
test_uuid = None
|
||||
name = "test" + mesh_type.name
|
||||
shape = Solid.make_box(1, 1, 1)
|
||||
shape.label = name
|
||||
exporter.add_shape(
|
||||
shape,
|
||||
mesh_type=mesh_type,
|
||||
part_number=str(mesh_type.value),
|
||||
uuid_value=test_uuid,
|
||||
)
|
||||
exporter.write("test.3mf")
|
||||
importer = Mesher()
|
||||
shape = importer.read("test.3mf")
|
||||
self.assertEqual(shape[0].label, name)
|
||||
self.assertEqual(importer.mesh_count, 1)
|
||||
properties = importer.get_mesh_properties()
|
||||
self.assertEqual(properties[0]["name"], name)
|
||||
self.assertEqual(properties[0]["part_number"], str(mesh_type.value))
|
||||
self.assertEqual(properties[0]["type"], mesh_type.name)
|
||||
if mesh_type != MeshType.SUPPORT:
|
||||
self.assertEqual(properties[0]["uuid"], str(test_uuid))
|
||||
|
||||
|
||||
class TestAddShape(DirectApiTestCase):
|
||||
def test_add_shape(self):
|
||||
exporter = Mesher()
|
||||
blue_shape = Solid.make_box(1, 1, 1)
|
||||
blue_shape.color = Color("blue")
|
||||
blue_shape.label = "blue"
|
||||
red_shape = Solid.make_cone(1, 0, 2).locate(Location((0, -1, 0)))
|
||||
red_shape.color = Color("red")
|
||||
red_shape.label = "red"
|
||||
exporter.add_shape([blue_shape, red_shape])
|
||||
exporter.write("test.3mf")
|
||||
importer = Mesher()
|
||||
box, cone = importer.read("test.3mf")
|
||||
self.assertVectorAlmostEquals(box.bounding_box().size, (1, 1, 1), 2)
|
||||
self.assertVectorAlmostEquals(box.bounding_box().size, (1, 1, 1), 2)
|
||||
self.assertEqual(len(box.clean().faces()), 6)
|
||||
self.assertEqual(box.label, "blue")
|
||||
self.assertEqual(cone.label, "red")
|
||||
self.assertTupleAlmostEquals(box.color.to_tuple(), (0, 0, 1, 1), 5)
|
||||
self.assertTupleAlmostEquals(cone.color.to_tuple(), (1, 0, 0, 1), 5)
|
||||
|
||||
def test_add_compound(self):
|
||||
exporter = Mesher()
|
||||
box = Solid.make_box(1, 1, 1)
|
||||
cone = Solid.make_cone(1, 0, 2).locate(Location((0, -1, 0)))
|
||||
shape_assembly = Compound.make_compound([box, cone])
|
||||
exporter.add_shape(shape_assembly)
|
||||
exporter.write("test.3mf")
|
||||
importer = Mesher()
|
||||
shapes = importer.read("test.3mf")
|
||||
self.assertEqual(importer.mesh_count, 2)
|
||||
|
||||
|
||||
class TestErrorChecking(unittest.TestCase):
|
||||
def test_read_invalid_file(self):
|
||||
with self.assertRaises(ValueError):
|
||||
importer = Mesher()
|
||||
importer.read("unknown_file.type")
|
||||
|
||||
def test_write_invalid_file(self):
|
||||
exporter = Mesher()
|
||||
exporter.add_shape(Solid.make_box(1, 1, 1))
|
||||
with self.assertRaises(ValueError):
|
||||
exporter.write("unknown_file.type")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue