Skip to content

Commit 76b6dd1

Browse files
authored
Release: Unit Hints (#2468)
- Be more flexible in getting unit hints from file names since it was a little silly that `20mm-xyz-cube` did not resolve as `mm`. - Apply [actions guidance](actions/runner-images#13045) updating to use the `macos-15-intel` image. - test and fix `trimesh.scene.lighting.autolight` crashing on empty scenes by checking `scene.bounds is None` - release #2470 - add a note about whether or not we should apply the fix from #2457 to `PBRMaterial.to_simple` using the same conversion function for the linear `baseColorFactor` to RGB, but don't actually apply the change as it seems likely to be a source of user confusion. - add a `Path2D.convex_hull` to match every other geometry method. - update `test_scene.py` to pytest style - release #2472 - release #2473 - Add in another `Literal` type for `VoxelizationMethodsType` rather than a "loose string".
2 parents 9d04496 + 95f7d64 commit 76b6dd1

File tree

21 files changed

+944
-746
lines changed

21 files changed

+944
-746
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
strategy:
2929
matrix:
3030
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
31-
os: [ubuntu-latest, macos-latest, macos-13, windows-latest]
31+
os: [ubuntu-latest, macos-latest, macos-15-intel, windows-latest]
3232
exclude:
3333
# windows runners have gotten flaky
3434
- os: windows-latest

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
strategy:
2727
matrix:
2828
python-version: ["3.8", "3.13"]
29-
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
29+
os: [ubuntu-latest, windows-latest, macos-latest, macos-15-intel]
3030
steps:
3131
- uses: actions/checkout@v4
3232
- name: Set up Python ${{ matrix.python-version }}

models/pyramids.3mf

32.2 KB
Binary file not shown.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ requires = ["setuptools >= 61.0", "wheel"]
55
[project]
66
name = "trimesh"
77
requires-python = ">=3.8"
8-
version = "4.8.3"
8+
version = "4.9.0"
99
authors = [{name = "Michael Dawson-Haggerty", email = "[email protected]"}]
1010
license = {file = "LICENSE.md"}
1111
description = "Import, export, process, analyze and view triangular meshes."

tests/generic.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,8 @@ def check_path2D(path):
464464
assert isinstance(path.identifier_hash, str)
465465
assert len(path.identifier_hash) == 64, len(path.identifier_hash)
466466

467+
assert path.convex_hull is not None
468+
467469

468470
def scene_equal(a, b):
469471
"""

tests/test_3mf.py

Lines changed: 61 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,67 @@
44
import generic as g
55

66

7-
class MFTest(g.unittest.TestCase):
8-
def test_3MF(self):
9-
# an assembly with instancing
10-
s = g.get_mesh("counterXP.3MF")
11-
12-
# should be 2 unique meshes
13-
assert len(s.geometry) == 2
14-
# should be 6 instances around the scene
15-
assert len(s.graph.nodes_geometry) == 6
16-
assert all(m.is_volume for m in s.geometry.values())
17-
18-
# a single body 3MF assembly
19-
s = g.get_mesh("featuretype.3MF")
20-
# should be 2 unique meshes
21-
assert len(s.geometry) == 1
22-
# should be 6 instances around the scene
23-
assert len(s.graph.nodes_geometry) == 1
24-
25-
def test_units(self):
26-
# test our unit conversion function
27-
converter = g.trimesh.units.unit_conversion
28-
# these are the units listed in the 3MF spec as valid
29-
units = ["micron", "millimeter", "centimeter", "inch", "foot", "meter"]
30-
# check conversion factor for all valid 3MF units
31-
assert all(converter(u, "inches") > 1e-12 for u in units)
32-
33-
def test_more_units(self):
34-
# make sure that units survive down to the mesh
35-
s = g.trimesh.load_scene(g.os.path.join(g.dir_models, "featuretype.3MF"))
36-
m = next(iter(s.geometry.values()))
37-
assert m.units is not None, m.metadata
38-
39-
def test_kwargs(self):
40-
# check if kwargs are properly passed to geometries
41-
s = g.get_mesh("P_XPM_0331_01.3mf")
42-
assert all(len(v.vertices) == 4 for v in s.geometry.values())
43-
44-
s = g.get_mesh("P_XPM_0331_01.3mf", process=False)
45-
assert all(len(v.vertices) == 5 for v in s.geometry.values())
46-
47-
def test_names(self):
48-
# check if two different objects with the same name are correctly
49-
# processed
50-
s = g.get_mesh("cube_and_sphere_same_name.3mf")
51-
assert len(s.geometry) == 2
52-
53-
def test_roundtrip(self):
54-
if g.sys.version_info < (3, 6):
55-
g.log.warning("relies on > Python 3.5")
56-
return
57-
58-
# test a scene round-tripped through the
59-
# 3MF exporter and importer
60-
s = g.get_mesh("cycloidal.3DXML")
61-
assert len(s.geometry) == 13
7+
def test_3MF():
8+
# an assembly with instancing
9+
s = g.get_mesh("counterXP.3MF")
10+
11+
# should be 2 unique meshes
12+
assert len(s.geometry) == 2
13+
# should be 6 instances around the scene
14+
assert len(s.graph.nodes_geometry) == 6
15+
assert all(m.is_volume for m in s.geometry.values())
16+
17+
# a single body 3MF assembly
18+
s = g.get_mesh("featuretype.3MF")
19+
# should be 2 unique meshes
20+
assert len(s.geometry) == 1
21+
# should be 6 instances around the scene
22+
assert len(s.graph.nodes_geometry) == 1
23+
24+
25+
def test_units():
26+
# test our unit conversion function
27+
converter = g.trimesh.units.unit_conversion
28+
# these are the units listed in the 3MF spec as valid
29+
units = ["micron", "millimeter", "centimeter", "inch", "foot", "meter"]
30+
# check conversion factor for all valid 3MF units
31+
assert all(converter(u, "inches") > 1e-12 for u in units)
32+
33+
34+
def test_more_units():
35+
# make sure that units survive down to the mesh
36+
s = g.trimesh.load_scene(g.os.path.join(g.dir_models, "featuretype.3MF"))
37+
m = next(iter(s.geometry.values()))
38+
assert m.units is not None, m.metadata
39+
40+
41+
def test_kwargs():
42+
# check if kwargs are properly passed to geometries
43+
s = g.get_mesh("P_XPM_0331_01.3mf")
44+
assert all(len(v.vertices) == 4 for v in s.geometry.values())
45+
46+
s = g.get_mesh("P_XPM_0331_01.3mf", process=False)
47+
assert all(len(v.vertices) == 5 for v in s.geometry.values())
48+
49+
50+
def test_names():
51+
# check if two different objects with the same name are correctly
52+
# processed
53+
s = g.get_mesh("cube_and_sphere_same_name.3mf")
54+
assert len(s.geometry) == 2
55+
56+
57+
def test_roundtrip():
58+
if g.sys.version_info < (3, 6):
59+
g.log.warning("relies on > Python 3.5")
60+
return
61+
62+
# test a scene round-tripped through the
63+
# 3MF exporter and importer
64+
65+
for name, count in [("cycloidal.3DXML", 13), ("pyramids.3mf", 6)]:
66+
s = g.get_mesh(name)
67+
assert len(s.geometry) == count
6268

6369
# export and reload
6470
r = g.trimesh.load(

tests/test_boolean.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,5 +207,6 @@ def test_multiple_difference():
207207
# should have done the diff
208208
assert np.allclose(diff_base.extents, [1.5, 1.5, 2.0], atol=1e-8)
209209

210-
if __name__ == '__main__':
210+
211+
if __name__ == "__main__":
211212
test_boolean()

tests/test_gltf.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,18 @@ def test_no_indices(self):
11221122
mesh = g.get_mesh("Mesh_PrimitiveMode_04.gltf")
11231123
assert len(mesh.triangles) == 2
11241124

1125+
def test_simple_material_conversion(self):
1126+
# make sure the name is preserved for a material
1127+
mesh = next(iter(g.get_mesh("Duck.glb").geometry.values()))
1128+
1129+
mat = mesh.visual.material
1130+
assert isinstance(mat, g.trimesh.visual.material.PBRMaterial)
1131+
assert isinstance(mat.name, str)
1132+
assert len(mat.name) > 0
1133+
1134+
simple = mesh.visual.material.to_simple()
1135+
assert simple.name == mesh.visual.material.name
1136+
11251137

11261138
if __name__ == "__main__":
11271139
g.trimesh.util.attach_to_log()

tests/test_obj.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ def test_multi_nodupe():
342342
for L in mtl["material.mtl"].decode("utf-8").split("\n")
343343
if "newmtl" in L
344344
]
345+
345346
# there should be 5 unique material names
346347
assert len(set(mtl_names)) == 5
347348

@@ -563,4 +564,4 @@ def test_obj_quad_uv():
563564

564565
if __name__ == "__main__":
565566
# test_material_name()
566-
test_vertex_color()
567+
test_multi_nodupe()

0 commit comments

Comments
 (0)