Skip to content

Commit

Permalink
Merge pull request #2161 from mikedh/feat/spell
Browse files Browse the repository at this point in the history
Release: Fix Typos
  • Loading branch information
mikedh authored Feb 23, 2024
2 parents 3d5af39 + 31f4446 commit 95c5431
Show file tree
Hide file tree
Showing 14 changed files with 193 additions and 91 deletions.
2 changes: 1 addition & 1 deletion docs/content/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Trimesh has a lot of soft-required upstream packages, and we try to make sure th
| `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` |
| `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` |
| `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` |
|`requests`| Do network queries in `trimesh.exchange.load_remote`, will *only* make network requests when asked | | `easy`|
|`httpx`| Do network queries in `trimesh.exchange.load_remote`, will *only* make network requests when asked | `requests`, `aiohttp` | `easy`|
|`sympy`| Evaluate symbolic algebra | | `recommend`|
|`xxhash`| Quickly hash arrays, used for our cache checking | | `easy`|
|`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`|
Expand Down
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ requires = ["setuptools >= 61.0", "wheel"]
[project]
name = "trimesh"
requires-python = ">=3.7"
version = "4.1.4"
version = "4.1.5"
authors = [{name = "Michael Dawson-Haggerty", email = "[email protected]"}]
license = {file = "LICENSE.md"}
description = "Import, export, process, analyze and view triangular meshes."
Expand Down Expand Up @@ -139,3 +139,7 @@ ignore = [
"B904", # raise ... from err
"B905", # zip() without an explicit strict= parameter
]

[tool.codespell]
skip = "*.js*,./docs/built/*,./docs/generate/*,./models*,*.toml"
ignore-words-list = "nd,coo,whats,bu,childs,mis,filetests"
2 changes: 1 addition & 1 deletion tests/test_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def test_triangulate(self):
# check triangulation of both meshpy and triangle engine
# including an example that has interiors
for engine in self.engines:
# make sure all our polygons triangulate resonably
# make sure all our polygons triangulate reasonably
for poly in bench:
v, f = g.trimesh.creation.triangulate_polygon(poly, engine=engine)
# run asserts
Expand Down
2 changes: 1 addition & 1 deletion tests/test_gltf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ def test_relative_paths(self):
g.os.chdir(cwd)

with g.TemporaryDirectory() as d:
# now try it without chaging to that directory
# now try it without changing to that directory
full = g.os.path.join(d, "hi", "there", "different", "levels")
path = g.os.path.join(full, "hey.gltf")
g.os.makedirs(full)
Expand Down
4 changes: 3 additions & 1 deletion tests/test_ply.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ def test_face_attributes(self):
m.face_attributes["test_1d_attribute"] = test_1d_attribute.astype(dt)
m.face_attributes["test_nd_attribute"] = test_nd_attribute.astype(dt)

export = m.export(file_type="ply", include_attributes=True, encoding=encoding)
export = m.export(
file_type="ply", include_attributes=True, encoding=encoding
)
reconstructed = g.roundtrip(export, file_type="ply", process=False)

face_attributes = reconstructed.metadata["_ply_raw"]["face"]["data"]
Expand Down
2 changes: 1 addition & 1 deletion tests/test_visual.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def test_face_subset_color_visuals(self):

def test_face_maintain_order(self):
# chose a mesh that has the same number of vs and vts
# to prevent confict without unmerging when maintain_order=True
# to prevent conflict without unmerging when maintain_order=True
mesh1 = g.get_mesh("capsule.obj", process=False, maintain_order=True)
mesh2 = g.get_mesh("capsule.obj", process=False, maintain_order=False)
colors1 = mesh1.visual.to_color()
Expand Down
119 changes: 82 additions & 37 deletions trimesh/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2878,65 +2878,110 @@ def convex_decomposition(self, **kwargs) -> List["Trimesh"]:
]

def union(
self, other: "Trimesh", engine: Optional[str] = None, **kwargs
self,
other: "Trimesh",
engine: Optional[str] = None,
check_volume: bool = True,
**kwargs,
) -> "Trimesh":
"""
Boolean union between this mesh and n other meshes
Boolean union between this mesh and other meshes.
Parameters
------------
other : Trimesh or (n, ) Trimesh
Other meshes to union
engine : None or str
Which backend to use
engine
Which backend to use, the default
recommendation is: `pip install manifold3d`.
check_volume
Raise an error if not all meshes are watertight
positive volumes. Advanced users may want to ignore
this check as it is expensive.
kwargs
Passed through to the `engine`.
Returns
---------
union : trimesh.Trimesh
Union of self and other Trimesh objects
"""
result = boolean.union(meshes=np.append(self, other), engine=engine, **kwargs)
return result

return boolean.union(
meshes=np.append(self, other),
engine=engine,
check_volume=check_volume,
**kwargs,
)

def difference(
self, other: "Trimesh", engine: Optional[str] = None, **kwargs
self,
other: "Trimesh",
engine: Optional[str] = None,
check_volume: bool = True,
**kwargs,
) -> "Trimesh":
"""
Boolean difference between this mesh and n other meshes
Parameters
------------
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
Meshes to difference
Returns
---------
difference : trimesh.Trimesh
Difference between self and other Trimesh objects
"""
result = boolean.difference(meshes=[self, other], engine=engine, **kwargs)
return result
Boolean difference between this mesh and n other meshes
Parameters
------------
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
Meshes to difference
engine
Which backend to use, the default
recommendation is: `pip install manifold3d`.
check_volume
Raise an error if not all meshes are watertight
positive volumes. Advanced users may want to ignore
this check as it is expensive.
kwargs
Passed through to the `engine`.
Returns
---------
difference : trimesh.Trimesh
Difference between self and other Trimesh objects
"""
return boolean.difference(
meshes=[self, other], engine=engine, check_volume=check_volume, **kwargs
)

def intersection(
self, other: "Trimesh", engine: Optional[str] = None, **kwargs
self,
other: "Trimesh",
engine: Optional[str] = None,
check_volume: bool = True,
**kwargs,
) -> "Trimesh":
"""
Boolean intersection between this mesh and n other meshes
Parameters
------------
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
Meshes to calculate intersections with
Returns
---------
intersection : trimesh.Trimesh
Mesh of the volume contained by all passed meshes
"""
result = boolean.intersection(
meshes=np.append(self, other), engine=engine, **kwargs
Boolean intersection between this mesh and other meshes.
Parameters
------------
other : trimesh.Trimesh, or list of trimesh.Trimesh objects
Meshes to calculate intersections with
engine
Which backend to use, the default
recommendation is: `pip install manifold3d`.
check_volume
Raise an error if not all meshes are watertight
positive volumes. Advanced users may want to ignore
this check as it is expensive.
kwargs
Passed through to the `engine`.
Returns
---------
intersection : trimesh.Trimesh
Mesh of the volume contained by all passed meshes
"""
return boolean.intersection(
meshes=np.append(self, other),
engine=engine,
check_volume=check_volume,
**kwargs,
)
return result

def contains(self, points: ArrayLike) -> NDArray[bool]:
"""
Expand Down
110 changes: 79 additions & 31 deletions trimesh/boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,49 @@

import numpy as np

from . import exceptions, interfaces
from .typed import Optional, Sequence

try:
from manifold3d import Manifold, Mesh
except BaseException as E:
from .exceptions import ExceptionWrapper

Mesh = ExceptionWrapper(E)
Manifold = ExceptionWrapper(E)

from . import interfaces
Mesh = exceptions.ExceptionWrapper(E)
Manifold = exceptions.ExceptionWrapper(E)


def difference(meshes, engine=None, **kwargs):
def difference(
meshes: Sequence, engine: Optional[str] = None, check_volume: bool = True, **kwargs
):
"""
Compute the boolean difference between a mesh an n other meshes.
Parameters
----------
meshes : list of trimesh.Trimesh
Meshes to be processed
engine : str
meshes : sequence of trimesh.Trimesh
Meshes to be processed.
engine
Which backend to use, i.e. 'blender' or 'manifold'
check_volume
Raise an error if not all meshes are watertight
positive volumes. Advanced users may want to ignore
this check as it is expensive.
kwargs
Passed through to the `engine`.
Returns
----------
difference : a - (other meshes), **kwargs for a Trimesh
difference
A `Trimesh` that contains `meshes[0] - meshes[1:]`
"""
result = _engines[engine](meshes, operation="difference", **kwargs)
return result
if check_volume and not all(m.is_volume for m in meshes):
raise ValueError("Not all meshes are volumes!")

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

def union(meshes, engine=None, **kwargs):

def union(
meshes: Sequence, engine: Optional[str] = None, check_volume: bool = True, **kwargs
):
"""
Compute the boolean union between a mesh an n other meshes.
Expand All @@ -48,50 +60,86 @@ def union(meshes, engine=None, **kwargs):
Meshes to be processed
engine : str
Which backend to use, i.e. 'blender' or 'manifold'
check_volume
Raise an error if not all meshes are watertight
positive volumes. Advanced users may want to ignore
this check as it is expensive.
kwargs
Passed through to the `engine`.
Returns
----------
union : a + (other meshes), **kwargs for a Trimesh
union
A `Trimesh` that contains the union of all passed meshes.
"""
if check_volume and not all(m.is_volume for m in meshes):
raise ValueError("Not all meshes are volumes!")

result = _engines[engine](meshes, operation="union", **kwargs)
return result


def intersection(meshes, engine=None, **kwargs):
def intersection(
meshes: Sequence, engine: Optional[str] = None, check_volume: bool = True, **kwargs
):
"""
Compute the boolean intersection between a mesh an n other meshes.
Compute the boolean intersection between a mesh and other meshes.
Parameters
----------
meshes : list of trimesh.Trimesh
Meshes to be processed
engine : str
Which backend to use, i.e. 'blender' or 'manifold'
solver_options: str
Fast has some limitations
Exact is slow but handles most of the cases
use_self: Bool
Self Intersection, Do self-union or self-intersection
check_volume
Raise an error if not all meshes are watertight
positive volumes. Advanced users may want to ignore
this check as it is expensive.
kwargs
Passed through to the `engine`.
Returns
----------
intersection : **kwargs for a Trimesh object of the
volume that is contained by all meshes
intersection
A `Trimesh` that contains the intersection geometry.
"""
result = _engines[engine](meshes, operation="intersection", **kwargs)
return result


def boolean_manifold(meshes, operation, debug=False, **kwargs):
if check_volume and not all(m.is_volume for m in meshes):
raise ValueError("Not all meshes are volumes!")
return _engines[engine](meshes, operation="intersection", **kwargs)


def boolean_manifold(
meshes: Sequence,
operation: str,
check_volume: bool = True,
debug: bool = False,
**kwargs,
):
"""
Run an operation on a set of meshes using the Manifold engine.
Parameters
----------
meshes : list of trimesh.Trimesh
Meshes to be processed
operation
Which boolean operation to do.
check_volume
Raise an error if not all meshes are watertight
positive volumes. Advanced users may want to ignore
this check as it is expensive.
debug
Enable potentially slow additional checks and debug info.
kwargs
Passed through to the `engine`.
"""
# Convert to manifold meshes
manifolds = [
Manifold(
mesh=Mesh(
vert_properties=np.asarray(mesh.vertices, dtype="float32"),
tri_verts=np.asarray(mesh.faces, dtype="int32"),
vert_properties=np.array(mesh.vertices, dtype=np.float32),
tri_verts=np.array(mesh.faces, dtype=np.uint32),
)
)
for mesh in meshes
Expand Down
Loading

0 comments on commit 95c5431

Please sign in to comment.