Skip to content

Commit c291e9e

Browse files
authored
Merge pull request #2598 from oddbookworm/clamp_zero_vector
Allow for clamping the zero vector when possible
2 parents da52aab + 7d53060 commit c291e9e

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

docs/reST/ref/math.rst

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ Multiple coordinates can be set using slices or swizzling
471471
| :sg:`clamp_magnitude(min_length, max_length, /) -> Vector2`
472472
473473
**Experimental:** feature still in development available for testing and feedback. It may change.
474-
`Please leave clamp_magnitude feedback with authors <https://github.com/pygame/pygame/pull/2990>`_
474+
`Please leave clamp_magnitude feedback with authors <https://github.com/pygame-community/pygame-ce>`_
475475

476476
Returns a new copy of a vector with the magnitude clamped between
477477
``max_length`` and ``min_length``. If only one argument is passed, it is
@@ -482,6 +482,12 @@ Multiple coordinates can be set using slices or swizzling
482482

483483
.. versionadded:: 2.1.3
484484

485+
.. versionchanged:: 2.4.0 It is now possible to use ``clamp_magnitude`` on a zero-vector as long as ``min_length``
486+
is unspecified or 0.
487+
488+
.. note::
489+
Before pygame-ce 2.4.0, attempting to clamp a zero vector would always raise a ``ValueError``
490+
485491
.. ## Vector2.clamp_magnitude ##
486492
487493
@@ -499,6 +505,12 @@ Multiple coordinates can be set using slices or swizzling
499505

500506
.. versionadded:: 2.1.3
501507

508+
.. versionchanged:: 2.4.0 It is now possible to use ``clamp_magnitude`` on a zero-vector as long as ``min_length``
509+
is unspecified or 0.
510+
511+
.. note::
512+
Before pygame-ce 2.4.0, attempting to clamp a zero vector would always raise a ``ValueError``
513+
502514
.. ## Vector2.clamp_magnitude_ip ##
503515
504516
@@ -1118,6 +1130,12 @@ Multiple coordinates can be set using slices or swizzling
11181130

11191131
.. versionadded:: 2.1.3
11201132

1133+
.. versionchanged:: 2.4.0 It is now possible to use ``clamp_magnitude`` on a zero-vector as long as ``min_length``
1134+
is unspecified or 0.
1135+
1136+
.. note::
1137+
Before pygame-ce 2.4.0, attempting to clamp a zero vector would always raise a ``ValueError``
1138+
11211139
.. ## Vector3.clamp_magnitude ##
11221140
11231141
@@ -1135,6 +1153,12 @@ Multiple coordinates can be set using slices or swizzling
11351153

11361154
.. versionadded:: 2.1.3
11371155

1156+
.. versionchanged:: 2.4.0 It is now possible to use ``clamp_magnitude`` on a zero-vector as long as ``min_length``
1157+
is unspecified or 0.
1158+
1159+
.. note::
1160+
Before pygame-ce 2.4.0, attempting to clamp a zero vector would always raise a ``ValueError``
1161+
11381162
.. ## Vector3.clamp_magnitude_ip ##
11391163
11401164
.. method:: update

src_c/math.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,9 +928,10 @@ vector_clamp_magnitude_ip(pgVector *self, PyObject *const *args,
928928

929929
/* Get magnitude of Vector */
930930
old_length_sq = _scalar_product(self->coords, self->coords, self->dim);
931-
if (old_length_sq == 0) {
931+
if (old_length_sq == 0 && min_length > 0) {
932932
return RAISE(PyExc_ValueError,
933-
"Cannot clamp a vector with zero length");
933+
"Cannot clamp a vector with zero length with a "
934+
"min_length greater than 0");
934935
}
935936

936937
/* Notes for other contributors reading this code:

test/math_test.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,11 @@ def test_clamp_mag_v2_no_change(self):
11731173
self.assertEqual(v1, v2)
11741174
self.assertEqual(v1, Vector2(1, 2))
11751175

1176+
v2 = Vector2()
1177+
self.assertEqual(v2.clamp_magnitude(1), Vector2())
1178+
v2.clamp_magnitude_ip(2)
1179+
self.assertEqual(v2.magnitude(), 0)
1180+
11761181
def test_clamp_mag_v2_edge_cases(self):
11771182
v1 = Vector2(1, 2)
11781183
v2 = v1.clamp_magnitude(6, 6)
@@ -1206,10 +1211,10 @@ def test_clamp_mag_v2_errors(self):
12061211
self.assertRaises(ValueError, v1.clamp_magnitude, *invalid_args)
12071212
self.assertRaises(ValueError, v1.clamp_magnitude_ip, *invalid_args)
12081213

1209-
# 0 vector
1214+
# 0 vector with a min_length > 0
12101215
v2 = Vector2()
1211-
self.assertRaises(ValueError, v2.clamp_magnitude, 3)
1212-
self.assertRaises(ValueError, v2.clamp_magnitude_ip, 4)
1216+
self.assertRaises(ValueError, v2.clamp_magnitude, 1, 2)
1217+
self.assertRaises(ValueError, v2.clamp_magnitude_ip, 2, 3)
12131218

12141219
def test_subclassing_v2(self):
12151220
"""Check if Vector2 is subclassable"""
@@ -2828,6 +2833,11 @@ def test_clamp_mag_v3_no_change(self):
28282833
self.assertEqual(v1, v2)
28292834
self.assertEqual(v1, Vector3(1, 2, 3))
28302835

2836+
v2 = Vector3()
2837+
self.assertEqual(v2.clamp_magnitude(1), Vector3())
2838+
v2.clamp_magnitude_ip(2)
2839+
self.assertEqual(v2.magnitude(), 0)
2840+
28312841
def test_clamp_mag_v3_edge_cases(self):
28322842
v1 = Vector3(1, 2, 1)
28332843
v2 = v1.clamp_magnitude(6, 6)
@@ -2863,8 +2873,8 @@ def test_clamp_mag_v3_errors(self):
28632873

28642874
# 0 vector
28652875
v2 = Vector3()
2866-
self.assertRaises(ValueError, v2.clamp_magnitude, 3)
2867-
self.assertRaises(ValueError, v2.clamp_magnitude_ip, 4)
2876+
self.assertRaises(ValueError, v2.clamp_magnitude, 1, 2)
2877+
self.assertRaises(ValueError, v2.clamp_magnitude_ip, 2, 3)
28682878

28692879
def test_subclassing_v3(self):
28702880
"""Check if Vector3 is subclassable"""

0 commit comments

Comments
 (0)