Skip to content

Commit 717c861

Browse files
authored
Merge pull request #2913 from damusss/circle-zero-radius
Allow degenerate circles (radius = 0)
2 parents 126c261 + 8940665 commit 717c861

File tree

4 files changed

+28
-21
lines changed

4 files changed

+28
-21
lines changed

docs/reST/ref/geometry.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@
3939
((x, y), radius)
4040
(x, y, radius)
4141

42-
It is important to note that you cannot create degenerate circles, which are circles with
43-
a radius of 0 or less. If you try to create such a circle, the `Circle` object will not be
44-
created and an error will be raised. This is because a circle with a radius of 0 or
45-
less is not a valid geometric object.
46-
4742
The `Circle` class has both virtual and non-virtual attributes. Non-virtual attributes
4843
are attributes that are stored in the `Circle` object itself. Virtual attributes are the
4944
result of calculations that utilize the Circle's non-virtual attributes.
@@ -91,6 +86,9 @@
9186

9287
.. versionadded:: 2.4.0
9388

89+
.. versionchanged:: 2.5.1 It is allowed to create degenerate circles with radius
90+
equal to ``0``. This also applies to virtual attributes.
91+
9492
.. ## Circle.r ##
9593
9694
.. attribute:: r_sqr

src_c/circle.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ pg_circle_init(pgCircleObject *self, PyObject *args, PyObject *kwds)
4747
PyErr_SetString(
4848
PyExc_TypeError,
4949
"Arguments must be a Circle, a sequence of length 3 or 2, or an "
50-
"object with an attribute called 'circle'");
50+
"object with an attribute called 'circle', all with corresponding "
51+
"nonnegative radius argument");
5152
return -1;
5253
}
5354
return 0;
@@ -494,8 +495,8 @@ pg_circle_setr(pgCircleObject *self, PyObject *value, void *closure)
494495
return -1;
495496
}
496497

497-
if (radius <= 0) {
498-
PyErr_SetString(PyExc_ValueError, "Radius must be positive");
498+
if (radius < 0) {
499+
PyErr_SetString(PyExc_ValueError, "Radius must be nonnegative");
499500
return -1;
500501
}
501502

@@ -523,9 +524,9 @@ pg_circle_setr_sqr(pgCircleObject *self, PyObject *value, void *closure)
523524
return -1;
524525
}
525526

526-
if (radius_squared <= 0) {
527+
if (radius_squared < 0) {
527528
PyErr_SetString(PyExc_ValueError,
528-
"Invalid radius squared value, must be > 0");
529+
"Invalid radius squared value, must be nonnegative");
529530
return -1;
530531
}
531532

@@ -570,8 +571,9 @@ pg_circle_setarea(pgCircleObject *self, PyObject *value, void *closure)
570571
return -1;
571572
}
572573

573-
if (area <= 0) {
574-
PyErr_SetString(PyExc_ValueError, "Invalid area value, must be > 0");
574+
if (area < 0) {
575+
PyErr_SetString(PyExc_ValueError,
576+
"Invalid area value, must be nonnegative");
575577
return -1;
576578
}
577579

@@ -600,9 +602,9 @@ pg_circle_setcircumference(pgCircleObject *self, PyObject *value,
600602
return -1;
601603
}
602604

603-
if (circumference <= 0) {
605+
if (circumference < 0) {
604606
PyErr_SetString(PyExc_ValueError,
605-
"Invalid circumference value, must be > 0");
607+
"Invalid circumference value, must be nonnegative");
606608
return -1;
607609
}
608610

@@ -630,9 +632,9 @@ pg_circle_setdiameter(pgCircleObject *self, PyObject *value, void *closure)
630632
return -1;
631633
}
632634

633-
if (diameter <= 0) {
635+
if (diameter < 0) {
634636
PyErr_SetString(PyExc_ValueError,
635-
"Invalid diameter value, must be > 0");
637+
"Invalid diameter value, must be nonnegative");
636638
return -1;
637639
}
638640

src_c/geometry_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ int
44
_pg_circle_set_radius(PyObject *value, pgCircleBase *circle)
55
{
66
double radius = 0.0;
7-
if (!pg_DoubleFromObj(value, &radius) || radius <= 0.0) {
7+
if (!pg_DoubleFromObj(value, &radius) || radius < 0.0) {
88
return 0;
99
}
1010
circle->r = radius;

test/geometry_test.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ def testConstructionTUP_XYR_int(self):
9595
self.assertEqual(2.0, c.y)
9696
self.assertEqual(3.0, c.r)
9797

98+
def testConstruction_zero_radius(self):
99+
c = Circle(1, 2, 0)
100+
101+
self.assertEqual(1.0, c.x)
102+
self.assertEqual(2.0, c.y)
103+
self.assertEqual(0, c.r)
104+
98105
def test_x(self):
99106
"""Ensures changing the x attribute moves the circle and does not change
100107
the circle's radius.
@@ -183,7 +190,7 @@ def test_r__invalid_value(self):
183190
with self.assertRaises(TypeError):
184191
c.radius = value
185192

186-
for value in (-10.3234, -1, 0, 0.0):
193+
for value in (-10.3234, -1):
187194
with self.assertRaises(ValueError):
188195
c.r = value
189196
with self.assertRaises(ValueError):
@@ -317,7 +324,7 @@ def test_area_invalid_value(self):
317324
with self.assertRaises(TypeError):
318325
c.area = value
319326

320-
for value in (-10.3234, -1, 0, 0.0):
327+
for value in (-10.3234, -1):
321328
with self.assertRaises(ValueError):
322329
c.area = value
323330

@@ -352,7 +359,7 @@ def test_circumference_invalid_value(self):
352359
with self.assertRaises(TypeError):
353360
c.circumference = value
354361

355-
for value in (-10.3234, -1, 0, 0.0):
362+
for value in (-10.3234, -1):
356363
with self.assertRaises(ValueError):
357364
c.circumference = value
358365

@@ -390,7 +397,7 @@ def test_diameter_invalid_value(self):
390397
with self.assertRaises(TypeError):
391398
c.diameter = value
392399

393-
for value in (-10.3234, -1, 0, 0.0):
400+
for value in (-10.3234, -1):
394401
with self.assertRaises(ValueError):
395402
c.diameter = value
396403
with self.assertRaises(ValueError):

0 commit comments

Comments
 (0)