Skip to content

Commit

Permalink
Merge pull request #2300 from mikedh/followup/3mf
Browse files Browse the repository at this point in the history
Release Followup: Tuning 3MF loading
  • Loading branch information
mikedh authored Oct 22, 2024
2 parents 207ba23 + 657020e commit 6ed17ba
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 30 deletions.
2 changes: 1 addition & 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.8"
version = "4.5.0"
version = "4.5.1"
authors = [{name = "Michael Dawson-Haggerty", email = "[email protected]"}]
license = {file = "LICENSE.md"}
description = "Import, export, process, analyze and view triangular meshes."
Expand Down
25 changes: 16 additions & 9 deletions tests/test_boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,21 @@ def test_multiple_difference():
spheres = [g.trimesh.creation.icosphere()]
spheres.extend(g.trimesh.creation.icosphere().apply_translation(c) for c in center)

# compute using meshes method
diff_base = spheres[0].difference(spheres[1:])
# compute using function call (should be identical)
diff_meth = g.trimesh.boolean.difference(spheres)
for engine, exists in engines:
if not exists:
g.log.warning("skipping boolean engine %s", engine)
continue

g.log.info("Testing multiple difference with engine %s", engine)

# compute using meshes method
diff_base = spheres[0].difference(spheres[1:], engine=engine)
# compute using function call (should be identical)
diff_meth = g.trimesh.boolean.difference(spheres, engine=engine)

# both methods should produce the same result
assert np.isclose(diff_base.volume, diff_meth.volume)
assert diff_base.volume < spheres[0].volume
# both methods should produce the same result
assert np.isclose(diff_base.volume, diff_meth.volume)
assert diff_base.volume < spheres[0].volume

# should have done the diff
assert np.allclose(diff_base.extents, [1.5, 1.5, 2.0], atol=1e-8)
# should have done the diff
assert np.allclose(diff_base.extents, [1.5, 1.5, 2.0], atol=1e-8)
44 changes: 35 additions & 9 deletions trimesh/exchange/threemf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,49 @@


def _read_mesh(mesh):
"""
Read a `<mesh ` XML element into Numpy vertices and faces.
This is generally the most expensive operation in the load as it
has to operate in Python-space on every single vertex and face.
Parameters
----------
mesh : lxml.etree.Element
Input mesh element with `vertex` and `triangle` children.
Returns
----------
vertex_array : (n, 3) float64
Vertices
face_array : (n, 3) int64
Indexes of vertices forming triangles.
"""
# get the XML elements for vertices and faces
vertices = mesh.find("{*}vertices")
v_array = np.array(
faces = mesh.find("{*}triangles")

# get every value as a flat space-delimited string
# this is very sensitive as it is large, i.e. it is
# much faster with the full list comprehension before
# the `.join` as the giant string can be fully allocated
vs = " ".join(
[
[i.attrib["x"], i.attrib["y"], i.attrib["z"]]
f'{i.attrib["x"]} {i.attrib["y"]} {i.attrib["z"]}'
for i in vertices.iter("{*}vertex")
],
dtype=np.float64,
]
)
# convert every value to floating point in one-shot rather than in a loop
v_array = np.fromstring(vs, dtype=np.float64, sep=" ").reshape((-1, 3))

faces = mesh.find("{*}triangles")
f_array = np.array(
# do the same behavior for faces but as an integer
fs = " ".join(
[
[i.attrib["v1"], i.attrib["v2"], i.attrib["v3"]]
f'{i.attrib["v1"]} {i.attrib["v2"]} {i.attrib["v3"]}'
for i in faces.iter("{*}triangle")
],
dtype=np.int64,
]
)
f_array = np.fromstring(fs, dtype=np.int64, sep=" ").reshape((-1, 3))

return v_array, f_array

Expand Down
7 changes: 6 additions & 1 deletion trimesh/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def to_dict(self):
"""
raise NotImplementedError()

def copy(self, **kwargs):
def copy(self, include_visual=True, **kwargs):
"""
Return a copy of the Primitive object.
Expand All @@ -129,6 +129,11 @@ def copy(self, **kwargs):
kwargs.pop("kind")
# create a new object with kwargs
primitive_copy = type(self)(**kwargs)

if include_visual:
# copy visual information
primitive_copy.visual = self.visual.copy()

# copy metadata
primitive_copy.metadata = self.metadata.copy()

Expand Down
2 changes: 1 addition & 1 deletion trimesh/scene/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ def rezero(self) -> None:

def dump(self, concatenate: bool = False) -> List[Geometry]:
"""
Get a list of every geometry moved to it's instance position,
Get a list of every geometry moved to its instance position,
i.e. freezing or "baking" transforms.
Parameters
Expand Down
21 changes: 12 additions & 9 deletions trimesh/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2015,17 +2015,20 @@ def triangle_strips_to_faces(strips):
"""

# save the length of each list in the list of lists
lengths = np.array([len(i) for i in strips])
lengths = np.array([len(i) for i in strips], dtype=np.int64)
# looping through a list of lists is extremely slow
# combine all the sequences into a blob we can manipulate
blob = np.concatenate(strips)

# preallocate and slice the blob into rough triangles
tri = np.zeros((len(blob) - 2, 3), dtype=np.int64)
for i in range(3):
tri[: len(blob) - 3, i] = blob[i : -3 + i]
# the last triangle is left off from the slicing, add it back
tri[-1] = blob[-3:]
blob = np.concatenate(strips, dtype=np.int64)

# slice the blob into rough triangles
tri = np.array([blob[:-2], blob[1:-1], blob[2:]], dtype=np.int64).T

# if we only have one strip we can do a *lot* less work
# as we keep every triangle and flip every other one
if len(strips) == 1:
# flip in-place every other triangle
tri[1::2] = np.fliplr(tri[1::2])
return tri

# remove the triangles which were implicit but not actually there
# because we combined everything into one big array for speed
Expand Down

0 comments on commit 6ed17ba

Please sign in to comment.