Skip to content

Commit e1979b9

Browse files
authored
Merge pull request #2201 from mikedh/fix/prim
Fix: escape none in primitives to avoid warning
2 parents f00f271 + 58b259e commit e1979b9

5 files changed

Lines changed: 54 additions & 11 deletions

File tree

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.7"
8-
version = "4.2.3"
8+
version = "4.2.4"
99
authors = [{name = "Michael Dawson-Haggerty", email = "mikedh@kerfed.com"}]
1010
license = {file = "LICENSE.md"}
1111
description = "Import, export, process, analyze and view triangular meshes."

tests/test_primitives.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,29 @@ def test_copy(self):
330330
assert g.np.allclose(box.center_mass, box_copy.center_mass)
331331
assert box.metadata["foo"] == box_copy.metadata["foo"]
332332

333+
def test_sphere_subdivisions(self):
334+
# make sure we don't subdivide when asked not to
335+
a = g.trimesh.creation.icosphere(subdivisions=0)
336+
assert a.faces.shape == g.trimesh.creation.icosahedron().faces.shape
337+
338+
# now apply the subdivisions ourself
339+
a = a.subdivide().subdivide()
340+
341+
# should have the same subdivisions as manually doing this
342+
b = g.trimesh.primitives.Sphere(subdivisions=2)
343+
344+
assert a.faces.shape == b.faces.shape
345+
346+
def test_sphere_subdivisions_radius(self):
347+
tf = list(g.random_transforms(4))
348+
for r in [1e-4, 1.1, 3, 1213.22]:
349+
for subd in range(4):
350+
s = g.trimesh.primitives.Sphere(
351+
radius=r, transform=tf[subd], subdivisions=subd
352+
)
353+
rc = g.np.linalg.norm(s.vertices - s.center_mass, axis=1)
354+
assert g.np.isclose(rc.mean(), r)
355+
333356

334357
if __name__ == "__main__":
335358
g.trimesh.util.attach_to_log()

trimesh/base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,8 +1937,9 @@ def compute_stable_poses(
19371937

19381938
def subdivide(self, face_index: Optional[ArrayLike] = None) -> "Trimesh":
19391939
"""
1940-
Subdivide a mesh, with each subdivided face replaced
1941-
with four smaller faces.
1940+
Subdivide a mesh with each subdivided face replaced
1941+
with four smaller faces. Will return a copy of current
1942+
mesh with subdivided faces.
19421943
19431944
Parameters
19441945
------------

trimesh/creation.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,16 +855,26 @@ def icosphere(subdivisions: Integer = 3, radius: Number = 1.0, **kwargs):
855855
ico : trimesh.Trimesh
856856
Meshed sphere
857857
"""
858+
radius = float(radius)
859+
subdivisions = int(subdivisions)
858860

859861
ico = icosahedron()
860862
ico._validate = False
863+
861864
for _ in range(subdivisions):
862865
ico = ico.subdivide()
863866
vectors = ico.vertices
864867
scalar = np.sqrt(np.dot(vectors**2, [1, 1, 1]))
865868
unit = vectors / scalar.reshape((-1, 1))
866869
ico.vertices += unit * (radius - scalar).reshape((-1, 1))
867870

871+
# if we didn't subdivide we still need to refine the radius
872+
if subdivisions <= 0:
873+
vectors = ico.vertices
874+
scalar = np.sqrt(np.dot(vectors**2, [1, 1, 1]))
875+
unit = vectors / scalar.reshape((-1, 1))
876+
ico.vertices += unit * (radius - scalar).reshape((-1, 1))
877+
868878
if "color" in kwargs:
869879
warnings.warn(
870880
"`icosphere(color=...)` is deprecated and will "

trimesh/primitives.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from . import transformations as tf
1717
from .base import Trimesh
1818
from .constants import log, tol
19+
from .typed import ArrayLike, Integer, Number, Optional
1920

2021
# immutable identity matrix for checks
2122
_IDENTITY = np.eye(4)
@@ -57,7 +58,8 @@ def faces(self):
5758

5859
@faces.setter
5960
def faces(self, values):
60-
log.warning("primitive faces are immutable: not setting!")
61+
if values is not None:
62+
raise ValueError("primitive faces are immutable: not setting!")
6163

6264
@property
6365
def vertices(self):
@@ -71,7 +73,7 @@ def vertices(self):
7173
@vertices.setter
7274
def vertices(self, values):
7375
if values is not None:
74-
log.warning("primitive vertices are immutable: not setting!")
76+
raise ValueError("primitive vertices are immutable: not setting!")
7577

7678
@property
7779
def face_normals(self):
@@ -550,28 +552,32 @@ def _create_mesh(self):
550552

551553
class Sphere(Primitive):
552554
def __init__(
553-
self, radius=1.0, center=None, transform=None, subdivisions=3, mutable=True
555+
self,
556+
radius: Number = 1.0,
557+
center: Optional[ArrayLike] = None,
558+
transform: Optional[ArrayLike] = None,
559+
subdivisions: Integer = 3,
560+
mutable: bool = True,
554561
):
555562
"""
556563
Create a Sphere Primitive, a subclass of Trimesh.
557564
558565
Parameters
559566
----------
560-
radius : float
567+
radius
561568
Radius of sphere
562569
center : None or (3,) float
563570
Center of sphere.
564571
transform : None or (4, 4) float
565572
Full homogeneous transform. Pass `center` OR `transform.
566-
subdivisions : int
573+
subdivisions
567574
Number of subdivisions for icosphere.
568-
mutable : bool
575+
mutable
569576
Are extents and transform mutable after creation.
570577
"""
571578

572579
super().__init__()
573580

574-
defaults = {"radius": 1.0, "transform": np.eye(4), "subdivisions": 3}
575581
constructor = {"radius": float(radius), "subdivisions": int(subdivisions)}
576582
# center is a helper method for "transform"
577583
# since a sphere is rotationally symmetric
@@ -586,7 +592,10 @@ def __init__(
586592

587593
# create the attributes object
588594
self.primitive = PrimitiveAttributes(
589-
self, defaults=defaults, kwargs=constructor, mutable=mutable
595+
self,
596+
defaults={"radius": 1.0, "transform": np.eye(4), "subdivisions": 3},
597+
kwargs=constructor,
598+
mutable=mutable,
590599
)
591600

592601
@property

0 commit comments

Comments
 (0)