Skip to content

Commit 95c5431

Browse files
authored
Merge pull request #2161 from mikedh/feat/spell
Release: Fix Typos
2 parents 3d5af39 + 31f4446 commit 95c5431

14 files changed

+193
-91
lines changed

docs/content/install.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Trimesh has a lot of soft-required upstream packages, and we try to make sure th
4848
| `networkx` | Pure Python graph library that's reasonably fast and has a nice API. `scipy.sparse.csgraph` is way faster in most cases but is hard to understand and doesn't implement as many algorithms. | `graph-tool`, `scipy.sparse.csgraph` | `easy` |
4949
| `shapely` | Bindings to `GEOS` for 2D spatial stuff: "set-theoretic analysis and manipulation of planar features" which lets you offset, union, and query polygons. | `clipper` | `easy` |
5050
| `rtree` | Query ND rectangles with a spatial tree for a "broad phase" intersection. Used in polygon generation ("given N closed curves which curve contains the other curve?") and as the broad-phase for the built-in-numpy slow ray query engine. | `fcl` maybe? | `easy` |
51-
|`requests`| Do network queries in `trimesh.exchange.load_remote`, will *only* make network requests when asked | | `easy`|
51+
|`httpx`| Do network queries in `trimesh.exchange.load_remote`, will *only* make network requests when asked | `requests`, `aiohttp` | `easy`|
5252
|`sympy`| Evaluate symbolic algebra | | `recommend`|
5353
|`xxhash`| Quickly hash arrays, used for our cache checking | | `easy`|
5454
|`chardet`| When we fail to decode text as UTF-8 we then check with chardet which guesses an encoding, letting us load files even with weird encodings. | | `easy`|

pyproject.toml

+5-1
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.7"
8-
version = "4.1.4"
8+
version = "4.1.5"
99
authors = [{name = "Michael Dawson-Haggerty", email = "[email protected]"}]
1010
license = {file = "LICENSE.md"}
1111
description = "Import, export, process, analyze and view triangular meshes."
@@ -139,3 +139,7 @@ ignore = [
139139
"B904", # raise ... from err
140140
"B905", # zip() without an explicit strict= parameter
141141
]
142+
143+
[tool.codespell]
144+
skip = "*.js*,./docs/built/*,./docs/generate/*,./models*,*.toml"
145+
ignore-words-list = "nd,coo,whats,bu,childs,mis,filetests"

tests/test_creation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ def test_triangulate(self):
241241
# check triangulation of both meshpy and triangle engine
242242
# including an example that has interiors
243243
for engine in self.engines:
244-
# make sure all our polygons triangulate resonably
244+
# make sure all our polygons triangulate reasonably
245245
for poly in bench:
246246
v, f = g.trimesh.creation.triangulate_polygon(poly, engine=engine)
247247
# run asserts

tests/test_gltf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,7 @@ def test_relative_paths(self):
10111011
g.os.chdir(cwd)
10121012

10131013
with g.TemporaryDirectory() as d:
1014-
# now try it without chaging to that directory
1014+
# now try it without changing to that directory
10151015
full = g.os.path.join(d, "hi", "there", "different", "levels")
10161016
path = g.os.path.join(full, "hey.gltf")
10171017
g.os.makedirs(full)

tests/test_ply.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ def test_face_attributes(self):
111111
m.face_attributes["test_1d_attribute"] = test_1d_attribute.astype(dt)
112112
m.face_attributes["test_nd_attribute"] = test_nd_attribute.astype(dt)
113113

114-
export = m.export(file_type="ply", include_attributes=True, encoding=encoding)
114+
export = m.export(
115+
file_type="ply", include_attributes=True, encoding=encoding
116+
)
115117
reconstructed = g.roundtrip(export, file_type="ply", process=False)
116118

117119
face_attributes = reconstructed.metadata["_ply_raw"]["face"]["data"]

tests/test_visual.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_face_subset_color_visuals(self):
5555

5656
def test_face_maintain_order(self):
5757
# chose a mesh that has the same number of vs and vts
58-
# to prevent confict without unmerging when maintain_order=True
58+
# to prevent conflict without unmerging when maintain_order=True
5959
mesh1 = g.get_mesh("capsule.obj", process=False, maintain_order=True)
6060
mesh2 = g.get_mesh("capsule.obj", process=False, maintain_order=False)
6161
colors1 = mesh1.visual.to_color()

trimesh/base.py

+82-37
Original file line numberDiff line numberDiff line change
@@ -2878,65 +2878,110 @@ def convex_decomposition(self, **kwargs) -> List["Trimesh"]:
28782878
]
28792879

28802880
def union(
2881-
self, other: "Trimesh", engine: Optional[str] = None, **kwargs
2881+
self,
2882+
other: "Trimesh",
2883+
engine: Optional[str] = None,
2884+
check_volume: bool = True,
2885+
**kwargs,
28822886
) -> "Trimesh":
28832887
"""
2884-
Boolean union between this mesh and n other meshes
2888+
Boolean union between this mesh and other meshes.
28852889
28862890
Parameters
28872891
------------
28882892
other : Trimesh or (n, ) Trimesh
28892893
Other meshes to union
2890-
engine : None or str
2891-
Which backend to use
2894+
engine
2895+
Which backend to use, the default
2896+
recommendation is: `pip install manifold3d`.
2897+
check_volume
2898+
Raise an error if not all meshes are watertight
2899+
positive volumes. Advanced users may want to ignore
2900+
this check as it is expensive.
2901+
kwargs
2902+
Passed through to the `engine`.
28922903
28932904
Returns
28942905
---------
28952906
union : trimesh.Trimesh
28962907
Union of self and other Trimesh objects
28972908
"""
2898-
result = boolean.union(meshes=np.append(self, other), engine=engine, **kwargs)
2899-
return result
2909+
2910+
return boolean.union(
2911+
meshes=np.append(self, other),
2912+
engine=engine,
2913+
check_volume=check_volume,
2914+
**kwargs,
2915+
)
29002916

29012917
def difference(
2902-
self, other: "Trimesh", engine: Optional[str] = None, **kwargs
2918+
self,
2919+
other: "Trimesh",
2920+
engine: Optional[str] = None,
2921+
check_volume: bool = True,
2922+
**kwargs,
29032923
) -> "Trimesh":
29042924
"""
2905-
Boolean difference between this mesh and n other meshes
2906-
2907-
Parameters
2908-
------------
2909-
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
2910-
Meshes to difference
2911-
2912-
Returns
2913-
---------
2914-
difference : trimesh.Trimesh
2915-
Difference between self and other Trimesh objects
2916-
"""
2917-
result = boolean.difference(meshes=[self, other], engine=engine, **kwargs)
2918-
return result
2925+
Boolean difference between this mesh and n other meshes
2926+
2927+
Parameters
2928+
------------
2929+
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
2930+
Meshes to difference
2931+
engine
2932+
Which backend to use, the default
2933+
recommendation is: `pip install manifold3d`.
2934+
check_volume
2935+
Raise an error if not all meshes are watertight
2936+
positive volumes. Advanced users may want to ignore
2937+
this check as it is expensive.
2938+
kwargs
2939+
Passed through to the `engine`.
2940+
2941+
Returns
2942+
---------
2943+
difference : trimesh.Trimesh
2944+
Difference between self and other Trimesh objects
2945+
"""
2946+
return boolean.difference(
2947+
meshes=[self, other], engine=engine, check_volume=check_volume, **kwargs
2948+
)
29192949

29202950
def intersection(
2921-
self, other: "Trimesh", engine: Optional[str] = None, **kwargs
2951+
self,
2952+
other: "Trimesh",
2953+
engine: Optional[str] = None,
2954+
check_volume: bool = True,
2955+
**kwargs,
29222956
) -> "Trimesh":
29232957
"""
2924-
Boolean intersection between this mesh and n other meshes
2925-
2926-
Parameters
2927-
------------
2928-
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
2929-
Meshes to calculate intersections with
2930-
2931-
Returns
2932-
---------
2933-
intersection : trimesh.Trimesh
2934-
Mesh of the volume contained by all passed meshes
2935-
"""
2936-
result = boolean.intersection(
2937-
meshes=np.append(self, other), engine=engine, **kwargs
2958+
Boolean intersection between this mesh and other meshes.
2959+
2960+
Parameters
2961+
------------
2962+
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
2963+
Meshes to calculate intersections with
2964+
engine
2965+
Which backend to use, the default
2966+
recommendation is: `pip install manifold3d`.
2967+
check_volume
2968+
Raise an error if not all meshes are watertight
2969+
positive volumes. Advanced users may want to ignore
2970+
this check as it is expensive.
2971+
kwargs
2972+
Passed through to the `engine`.
2973+
2974+
Returns
2975+
---------
2976+
intersection : trimesh.Trimesh
2977+
Mesh of the volume contained by all passed meshes
2978+
"""
2979+
return boolean.intersection(
2980+
meshes=np.append(self, other),
2981+
engine=engine,
2982+
check_volume=check_volume,
2983+
**kwargs,
29382984
)
2939-
return result
29402985

29412986
def contains(self, points: ArrayLike) -> NDArray[bool]:
29422987
"""

trimesh/boolean.py

+79-31
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,49 @@
88

99
import numpy as np
1010

11+
from . import exceptions, interfaces
12+
from .typed import Optional, Sequence
13+
1114
try:
1215
from manifold3d import Manifold, Mesh
1316
except BaseException as E:
14-
from .exceptions import ExceptionWrapper
15-
16-
Mesh = ExceptionWrapper(E)
17-
Manifold = ExceptionWrapper(E)
18-
19-
from . import interfaces
17+
Mesh = exceptions.ExceptionWrapper(E)
18+
Manifold = exceptions.ExceptionWrapper(E)
2019

2120

22-
def difference(meshes, engine=None, **kwargs):
21+
def difference(
22+
meshes: Sequence, engine: Optional[str] = None, check_volume: bool = True, **kwargs
23+
):
2324
"""
2425
Compute the boolean difference between a mesh an n other meshes.
2526
2627
Parameters
2728
----------
28-
meshes : list of trimesh.Trimesh
29-
Meshes to be processed
30-
engine : str
29+
meshes : sequence of trimesh.Trimesh
30+
Meshes to be processed.
31+
engine
3132
Which backend to use, i.e. 'blender' or 'manifold'
33+
check_volume
34+
Raise an error if not all meshes are watertight
35+
positive volumes. Advanced users may want to ignore
36+
this check as it is expensive.
37+
kwargs
38+
Passed through to the `engine`.
3239
3340
Returns
3441
----------
35-
difference : a - (other meshes), **kwargs for a Trimesh
42+
difference
43+
A `Trimesh` that contains `meshes[0] - meshes[1:]`
3644
"""
37-
result = _engines[engine](meshes, operation="difference", **kwargs)
38-
return result
45+
if check_volume and not all(m.is_volume for m in meshes):
46+
raise ValueError("Not all meshes are volumes!")
3947

48+
return _engines[engine](meshes, operation="difference", **kwargs)
4049

41-
def union(meshes, engine=None, **kwargs):
50+
51+
def union(
52+
meshes: Sequence, engine: Optional[str] = None, check_volume: bool = True, **kwargs
53+
):
4254
"""
4355
Compute the boolean union between a mesh an n other meshes.
4456
@@ -48,50 +60,86 @@ def union(meshes, engine=None, **kwargs):
4860
Meshes to be processed
4961
engine : str
5062
Which backend to use, i.e. 'blender' or 'manifold'
63+
check_volume
64+
Raise an error if not all meshes are watertight
65+
positive volumes. Advanced users may want to ignore
66+
this check as it is expensive.
67+
kwargs
68+
Passed through to the `engine`.
5169
5270
Returns
5371
----------
54-
union : a + (other meshes), **kwargs for a Trimesh
72+
union
73+
A `Trimesh` that contains the union of all passed meshes.
5574
"""
75+
if check_volume and not all(m.is_volume for m in meshes):
76+
raise ValueError("Not all meshes are volumes!")
77+
5678
result = _engines[engine](meshes, operation="union", **kwargs)
5779
return result
5880

5981

60-
def intersection(meshes, engine=None, **kwargs):
82+
def intersection(
83+
meshes: Sequence, engine: Optional[str] = None, check_volume: bool = True, **kwargs
84+
):
6185
"""
62-
Compute the boolean intersection between a mesh an n other meshes.
86+
Compute the boolean intersection between a mesh and other meshes.
6387
6488
Parameters
6589
----------
6690
meshes : list of trimesh.Trimesh
6791
Meshes to be processed
6892
engine : str
6993
Which backend to use, i.e. 'blender' or 'manifold'
70-
solver_options: str
71-
Fast has some limitations
72-
Exact is slow but handles most of the cases
73-
use_self: Bool
74-
Self Intersection, Do self-union or self-intersection
94+
check_volume
95+
Raise an error if not all meshes are watertight
96+
positive volumes. Advanced users may want to ignore
97+
this check as it is expensive.
98+
kwargs
99+
Passed through to the `engine`.
75100
76101
Returns
77102
----------
78-
intersection : **kwargs for a Trimesh object of the
79-
volume that is contained by all meshes
103+
intersection
104+
A `Trimesh` that contains the intersection geometry.
80105
"""
81-
result = _engines[engine](meshes, operation="intersection", **kwargs)
82-
return result
83-
84-
85-
def boolean_manifold(meshes, operation, debug=False, **kwargs):
106+
if check_volume and not all(m.is_volume for m in meshes):
107+
raise ValueError("Not all meshes are volumes!")
108+
return _engines[engine](meshes, operation="intersection", **kwargs)
109+
110+
111+
def boolean_manifold(
112+
meshes: Sequence,
113+
operation: str,
114+
check_volume: bool = True,
115+
debug: bool = False,
116+
**kwargs,
117+
):
86118
"""
87119
Run an operation on a set of meshes using the Manifold engine.
120+
121+
Parameters
122+
----------
123+
meshes : list of trimesh.Trimesh
124+
Meshes to be processed
125+
operation
126+
Which boolean operation to do.
127+
check_volume
128+
Raise an error if not all meshes are watertight
129+
positive volumes. Advanced users may want to ignore
130+
this check as it is expensive.
131+
debug
132+
Enable potentially slow additional checks and debug info.
133+
kwargs
134+
Passed through to the `engine`.
135+
88136
"""
89137
# Convert to manifold meshes
90138
manifolds = [
91139
Manifold(
92140
mesh=Mesh(
93-
vert_properties=np.asarray(mesh.vertices, dtype="float32"),
94-
tri_verts=np.asarray(mesh.faces, dtype="int32"),
141+
vert_properties=np.array(mesh.vertices, dtype=np.float32),
142+
tri_verts=np.array(mesh.faces, dtype=np.uint32),
95143
)
96144
)
97145
for mesh in meshes

0 commit comments

Comments
 (0)