Skip to content

Commit 43cb6b6

Browse files
authored
Merge pull request #1489 from compas-dev/copilot/fix-sphere-scaled-method
Fix broken behavior with Sphere.scaled(), Cylinder.scaled(), and Capsule.scaled() and add scale() for Cone and Torus
2 parents b8cef0d + 2fe0681 commit 43cb6b6

File tree

9 files changed

+247
-0
lines changed

9 files changed

+247
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515

1616
* Updated minimum library version to `2.14.1` in Rhino8 GH components.
1717
* Changed name of YAK package from `bluejay` to `compas`.
18+
* Fixed broken `scaled()` method in `Sphere`, `Cylinder`, and `Capsule` classes by overriding to accept uniform scaling factor.
1819

1920
### Removed
2021

src/compas/geometry/shapes/cone.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,22 @@ def to_brep(self):
300300
# Transformations
301301
# ==========================================================================
302302

303+
def scale(self, factor):
304+
"""Scale the cone by multiplying the radius and height by a factor.
305+
306+
Parameters
307+
----------
308+
factor : float
309+
The scaling factor.
310+
311+
Returns
312+
-------
313+
None
314+
315+
"""
316+
self.radius *= factor
317+
self.height *= factor
318+
303319
# ==========================================================================
304320
# Methods
305321
# ==========================================================================

src/compas/geometry/shapes/shape.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,13 +432,36 @@ def scale(self, scale):
432432
433433
See Also
434434
--------
435+
scaled
435436
translate
436437
rotate
437438
transform
438439
439440
"""
440441
raise NotImplementedError
441442

443+
def scaled(self, factor):
444+
"""Returns a scaled copy of the shape.
445+
446+
Parameters
447+
----------
448+
factor : float
449+
The scaling factor.
450+
451+
Returns
452+
-------
453+
:class:`compas.geometry.Shape`
454+
The scaled shape.
455+
456+
See Also
457+
--------
458+
scale
459+
460+
"""
461+
shape = self.copy()
462+
shape.scale(factor)
463+
return shape
464+
442465
# =============================================================================
443466
# Methods
444467
# =============================================================================

src/compas/geometry/shapes/torus.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,20 @@ def transform(self, transformation):
278278
279279
"""
280280
self.frame.transform(transformation)
281+
282+
def scale(self, factor):
283+
"""Scale the torus by multiplying the axis radius and pipe radius by a factor.
284+
285+
Parameters
286+
----------
287+
factor : float
288+
The scaling factor.
289+
290+
Returns
291+
-------
292+
None
293+
294+
"""
295+
self.radius_axis *= factor
296+
self.radius_pipe *= factor
297+

tests/compas/geometry/test_capsule.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,39 @@ def test_capsule_discretization(capsule):
1414
assert capsule.edges
1515
assert capsule.faces
1616
assert capsule.vertices
17+
18+
19+
def test_capsule_scaled():
20+
"""Test that Capsule.scaled() returns a scaled copy without modifying the original."""
21+
capsule = Capsule(radius=5.0, height=10.0)
22+
23+
# Test uniform scaling
24+
scaled_capsule = capsule.scaled(0.5)
25+
26+
# Original should be unchanged
27+
assert capsule.radius == 5.0
28+
assert capsule.height == 10.0
29+
30+
# Scaled copy should have scaled dimensions
31+
assert scaled_capsule.radius == 2.5
32+
assert scaled_capsule.height == 5.0
33+
34+
# Test scaling with factor > 1
35+
scaled_capsule_2 = capsule.scaled(2.0)
36+
assert scaled_capsule_2.radius == 10.0
37+
assert scaled_capsule_2.height == 20.0
38+
assert capsule.radius == 5.0 # Original still unchanged
39+
assert capsule.height == 10.0
40+
41+
42+
def test_capsule_scale():
43+
"""Test that Capsule.scale() modifies the capsule in place."""
44+
capsule = Capsule(radius=5.0, height=10.0)
45+
46+
# Test uniform scaling
47+
capsule.scale(0.5)
48+
49+
# Capsule should be modified
50+
assert capsule.radius == 2.5
51+
assert capsule.height == 5.0
52+

tests/compas/geometry/test_cone.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,39 @@ def test_cone_discretization(cone):
1414
assert cone.edges
1515
assert cone.faces
1616
assert cone.vertices
17+
18+
19+
def test_cone_scaled():
20+
"""Test that Cone.scaled() returns a scaled copy without modifying the original."""
21+
cone = Cone(radius=5.0, height=10.0)
22+
23+
# Test uniform scaling
24+
scaled_cone = cone.scaled(0.5)
25+
26+
# Original should be unchanged
27+
assert cone.radius == 5.0
28+
assert cone.height == 10.0
29+
30+
# Scaled copy should have scaled dimensions
31+
assert scaled_cone.radius == 2.5
32+
assert scaled_cone.height == 5.0
33+
34+
# Test scaling with factor > 1
35+
scaled_cone_2 = cone.scaled(2.0)
36+
assert scaled_cone_2.radius == 10.0
37+
assert scaled_cone_2.height == 20.0
38+
assert cone.radius == 5.0 # Original still unchanged
39+
assert cone.height == 10.0
40+
41+
42+
def test_cone_scale():
43+
"""Test that Cone.scale() modifies the cone in place."""
44+
cone = Cone(radius=5.0, height=10.0)
45+
46+
# Test uniform scaling
47+
cone.scale(0.5)
48+
49+
# Cone should be modified
50+
assert cone.radius == 2.5
51+
assert cone.height == 5.0
52+

tests/compas/geometry/test_cylinder.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,39 @@ def test_cylinder_discretization(cylinder):
1313
assert cylinder.edges
1414
assert cylinder.faces
1515
assert cylinder.vertices
16+
17+
18+
def test_cylinder_scaled():
19+
"""Test that Cylinder.scaled() returns a scaled copy without modifying the original."""
20+
cylinder = Cylinder(radius=5.0, height=10.0)
21+
22+
# Test uniform scaling
23+
scaled_cylinder = cylinder.scaled(0.5)
24+
25+
# Original should be unchanged
26+
assert cylinder.radius == 5.0
27+
assert cylinder.height == 10.0
28+
29+
# Scaled copy should have scaled dimensions
30+
assert scaled_cylinder.radius == 2.5
31+
assert scaled_cylinder.height == 5.0
32+
33+
# Test scaling with factor > 1
34+
scaled_cylinder_2 = cylinder.scaled(2.0)
35+
assert scaled_cylinder_2.radius == 10.0
36+
assert scaled_cylinder_2.height == 20.0
37+
assert cylinder.radius == 5.0 # Original still unchanged
38+
assert cylinder.height == 10.0
39+
40+
41+
def test_cylinder_scale():
42+
"""Test that Cylinder.scale() modifies the cylinder in place."""
43+
cylinder = Cylinder(radius=5.0, height=10.0)
44+
45+
# Test uniform scaling
46+
cylinder.scale(0.5)
47+
48+
# Cylinder should be modified
49+
assert cylinder.radius == 2.5
50+
assert cylinder.height == 5.0
51+

tests/compas/geometry/test_shpere.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,34 @@ def test_sphere_discretization(sphere):
1717
assert len(sphere.edges) == expected_edge_count
1818
assert len(sphere.faces) == expected_face_count
1919
assert len(sphere.vertices) == expected_vertex_count
20+
21+
22+
def test_sphere_scaled():
23+
"""Test that Sphere.scaled() returns a scaled copy without modifying the original."""
24+
sphere = Sphere(radius=10.0)
25+
26+
# Test uniform scaling
27+
scaled_sphere = sphere.scaled(0.5)
28+
29+
# Original should be unchanged
30+
assert sphere.radius == 10.0
31+
32+
# Scaled copy should have scaled radius
33+
assert scaled_sphere.radius == 5.0
34+
35+
# Test scaling with factor > 1
36+
scaled_sphere_2 = sphere.scaled(2.0)
37+
assert scaled_sphere_2.radius == 20.0
38+
assert sphere.radius == 10.0 # Original still unchanged
39+
40+
41+
def test_sphere_scale():
42+
"""Test that Sphere.scale() modifies the sphere in place."""
43+
sphere = Sphere(radius=10.0)
44+
45+
# Test uniform scaling
46+
sphere.scale(0.5)
47+
48+
# Sphere should be modified
49+
assert sphere.radius == 5.0
50+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import pytest
2+
3+
from compas.geometry import Torus
4+
5+
6+
@pytest.fixture
7+
def torus():
8+
return Torus(radius_axis=10.0, radius_pipe=2.0)
9+
10+
11+
def test_torus_discretization(torus):
12+
# just checking these don't break. Could not quickly find a formula that worked to test the actual values
13+
# as function of the resolution
14+
assert torus.edges
15+
assert torus.faces
16+
assert torus.vertices
17+
18+
19+
def test_torus_scaled():
20+
"""Test that Torus.scaled() returns a scaled copy without modifying the original."""
21+
torus = Torus(radius_axis=10.0, radius_pipe=2.0)
22+
23+
# Test uniform scaling
24+
scaled_torus = torus.scaled(0.5)
25+
26+
# Original should be unchanged
27+
assert torus.radius_axis == 10.0
28+
assert torus.radius_pipe == 2.0
29+
30+
# Scaled copy should have scaled dimensions
31+
assert scaled_torus.radius_axis == 5.0
32+
assert scaled_torus.radius_pipe == 1.0
33+
34+
# Test scaling with factor > 1
35+
scaled_torus_2 = torus.scaled(2.0)
36+
assert scaled_torus_2.radius_axis == 20.0
37+
assert scaled_torus_2.radius_pipe == 4.0
38+
assert torus.radius_axis == 10.0 # Original still unchanged
39+
assert torus.radius_pipe == 2.0
40+
41+
42+
def test_torus_scale():
43+
"""Test that Torus.scale() modifies the torus in place."""
44+
torus = Torus(radius_axis=10.0, radius_pipe=2.0)
45+
46+
# Test uniform scaling
47+
torus.scale(0.5)
48+
49+
# Torus should be modified
50+
assert torus.radius_axis == 5.0
51+
assert torus.radius_pipe == 1.0

0 commit comments

Comments
 (0)