Skip to content

Commit b64c90d

Browse files
itzpr3d4t0rEmc2356andrewhong04
authored
Added missing Circle attrs (#2519)
Co-authored-by: Emc2356 <[email protected]> Co-authored-by: NovialRiptide <[email protected]>
1 parent 484cb28 commit b64c90d

File tree

7 files changed

+512
-7
lines changed

7 files changed

+512
-7
lines changed

buildconfig/stubs/pygame/geometry.pyi

+40-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,53 @@
11
from typing import (
2-
Sequence,
32
overload,
3+
Tuple,
44
)
55

6-
from pygame._common import Coordinate
7-
6+
from ._common import Coordinate
87

98
class Circle:
10-
x: float
11-
y: float
12-
r: float
9+
@property
10+
def x(self) -> float: ...
11+
@x.setter
12+
def x(self, value: float) -> None: ...
13+
@property
14+
def y(self) -> float: ...
15+
@y.setter
16+
def y(self, value: float) -> None: ...
17+
@property
18+
def r(self) -> float: ...
19+
@r.setter
20+
def r(self, value: float) -> None: ...
21+
22+
radius = r
23+
24+
@property
25+
def r_sqr(self) -> float: ...
26+
@r_sqr.setter
27+
def r_sqr(self, value: float) -> None: ...
28+
@property
29+
def d(self) -> float: ...
30+
@d.setter
31+
def d(self, value: float) -> None: ...
32+
33+
diameter = d
1334

35+
@property
36+
def area(self) -> float: ...
37+
@area.setter
38+
def area(self, value: float) -> None: ...
39+
@property
40+
def circumference(self) -> float: ...
41+
@circumference.setter
42+
def circumference(self, value: float) -> None: ...
43+
@property
44+
def center(self) -> Tuple[float, float]: ...
45+
@center.setter
46+
def center(self, value: Coordinate) -> None: ...
1447
@overload
1548
def __init__(self, x: float, y: float, r: float) -> None: ...
1649
@overload
17-
def __init__(self, pos: Sequence[float], r: float) -> None: ...
50+
def __init__(self, pos: Coordinate, r: float) -> None: ...
1851
@overload
1952
def __init__(self, circle: Circle) -> None: ...
2053
@overload

docs/reST/ref/geometry.rst

+55
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,61 @@
8585

8686
.. ## Circle.r ##
8787
88+
.. attribute:: r_sqr
89+
90+
| :sl:`radius of the circle squared`
91+
| :sg:`r_sqr -> float`
92+
93+
It's equivalent to `r*r`. It can be reassigned. If reassigned, the radius
94+
of the circle will be changed to the square root of the new value.
95+
The circle will not be moved from its original position.
96+
97+
.. ## Circle.r_sqr ##
98+
99+
.. attribute:: center
100+
101+
| :sl:`x and y coordinates of the center of the circle`
102+
| :sg:`center -> (float, float)`
103+
104+
It's a tuple containing the `x` and `y` coordinates that represent the center
105+
of the circle. It can be reassigned. If reassigned, the circle will be moved
106+
to the new position. The radius will not be affected.
107+
108+
.. ## Circle.center ##
109+
110+
.. attribute:: diameter
111+
112+
| :sl:`diameter of the circle`
113+
| :sg:`diameter -> float`
114+
115+
It's calculated using the `d=2*r` formula. It can be reassigned. If reassigned
116+
the radius will be changed to half the diameter.
117+
The circle will not be moved from its original position.
118+
119+
.. ## Circle.diameter ##
120+
121+
.. attribute:: area
122+
123+
| :sl:`area of the circle`
124+
| :sg:`area -> float`
125+
126+
It's calculated using the `area=pi*r*r` formula. It can be reassigned.
127+
If reassigned the circle radius will be changed to produce a circle with matching
128+
area. The circle will not be moved from its original position.
129+
130+
.. ## Circle.area ##
131+
132+
.. attribute:: circumference
133+
134+
| :sl:`circumference of the circle`
135+
| :sg:`circumference -> float`
136+
137+
It's calculated using the `circumference=2*pi*r` formula. It can be reassigned.
138+
If reassigned the circle radius will be changed to produce a circle with matching
139+
circumference. The circle will not be moved from its original position.
140+
141+
.. ## Circle.circumference ##
142+
88143
**Circle Methods**
89144

90145
----

src_c/circle.c

+151
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,161 @@ pg_circle_setr(pgCircleObject *self, PyObject *value, void *closure)
311311
return 0;
312312
}
313313

314+
static PyObject *
315+
pg_circle_getr_sqr(pgCircleObject *self, void *closure)
316+
{
317+
return PyFloat_FromDouble(self->circle.r * self->circle.r);
318+
}
319+
320+
static int
321+
pg_circle_setr_sqr(pgCircleObject *self, PyObject *value, void *closure)
322+
{
323+
double radius_squared;
324+
325+
DEL_ATTR_NOT_SUPPORTED_CHECK_NO_NAME(value);
326+
327+
if (!pg_DoubleFromObj(value, &radius_squared)) {
328+
PyErr_SetString(PyExc_TypeError,
329+
"Invalid type for radius squared, must be numeric");
330+
return -1;
331+
}
332+
333+
if (radius_squared <= 0) {
334+
PyErr_SetString(PyExc_ValueError,
335+
"Invalid radius squared value, must be > 0");
336+
return -1;
337+
}
338+
339+
self->circle.r = sqrt(radius_squared);
340+
341+
return 0;
342+
}
343+
344+
static PyObject *
345+
pg_circle_getcenter(pgCircleObject *self, void *closure)
346+
{
347+
return pg_tuple_couple_from_values_double(self->circle.x, self->circle.y);
348+
}
349+
350+
static int
351+
pg_circle_setcenter(pgCircleObject *self, PyObject *value, void *closure)
352+
{
353+
DEL_ATTR_NOT_SUPPORTED_CHECK_NO_NAME(value);
354+
if (!pg_TwoDoublesFromObj(value, &self->circle.x, &self->circle.y)) {
355+
PyErr_SetString(PyExc_TypeError, "Expected a sequence of 2 numbers");
356+
return -1;
357+
}
358+
return 0;
359+
}
360+
361+
static PyObject *
362+
pg_circle_getarea(pgCircleObject *self, void *closure)
363+
{
364+
return PyFloat_FromDouble(M_PI * self->circle.r * self->circle.r);
365+
}
366+
367+
static int
368+
pg_circle_setarea(pgCircleObject *self, PyObject *value, void *closure)
369+
{
370+
double area;
371+
372+
DEL_ATTR_NOT_SUPPORTED_CHECK_NO_NAME(value);
373+
374+
if (!pg_DoubleFromObj(value, &area)) {
375+
PyErr_SetString(PyExc_TypeError,
376+
"Invalid type for area, must be numeric");
377+
return -1;
378+
}
379+
380+
if (area <= 0) {
381+
PyErr_SetString(PyExc_ValueError, "Invalid area value, must be > 0");
382+
return -1;
383+
}
384+
385+
self->circle.r = sqrt(area / M_PI);
386+
387+
return 0;
388+
}
389+
390+
static PyObject *
391+
pg_circle_getcircumference(pgCircleObject *self, void *closure)
392+
{
393+
return PyFloat_FromDouble(M_TWOPI * self->circle.r);
394+
}
395+
396+
static int
397+
pg_circle_setcircumference(pgCircleObject *self, PyObject *value,
398+
void *closure)
399+
{
400+
double circumference;
401+
402+
DEL_ATTR_NOT_SUPPORTED_CHECK_NO_NAME(value);
403+
404+
if (!pg_DoubleFromObj(value, &circumference)) {
405+
PyErr_SetString(PyExc_TypeError,
406+
"Invalid type for circumference, must be numeric");
407+
return -1;
408+
}
409+
410+
if (circumference <= 0) {
411+
PyErr_SetString(PyExc_ValueError,
412+
"Invalid circumference value, must be > 0");
413+
return -1;
414+
}
415+
416+
self->circle.r = circumference / M_TWOPI;
417+
418+
return 0;
419+
}
420+
421+
static PyObject *
422+
pg_circle_getdiameter(pgCircleObject *self, void *closure)
423+
{
424+
return PyFloat_FromDouble(2 * self->circle.r);
425+
}
426+
427+
static int
428+
pg_circle_setdiameter(pgCircleObject *self, PyObject *value, void *closure)
429+
{
430+
double diameter;
431+
432+
DEL_ATTR_NOT_SUPPORTED_CHECK_NO_NAME(value);
433+
434+
if (!pg_DoubleFromObj(value, &diameter)) {
435+
PyErr_SetString(PyExc_TypeError,
436+
"Invalid type for diameter, must be numeric");
437+
return -1;
438+
}
439+
440+
if (diameter <= 0) {
441+
PyErr_SetString(PyExc_ValueError,
442+
"Invalid diameter value, must be > 0");
443+
return -1;
444+
}
445+
446+
self->circle.r = diameter / 2;
447+
448+
return 0;
449+
}
450+
314451
static PyGetSetDef pg_circle_getsets[] = {
315452
{"x", (getter)pg_circle_getx, (setter)pg_circle_setx, DOC_CIRCLE_X, NULL},
316453
{"y", (getter)pg_circle_gety, (setter)pg_circle_sety, DOC_CIRCLE_Y, NULL},
317454
{"r", (getter)pg_circle_getr, (setter)pg_circle_setr, DOC_CIRCLE_R, NULL},
455+
{"radius", (getter)pg_circle_getr, (setter)pg_circle_setr, DOC_CIRCLE_R,
456+
NULL},
457+
{"r_sqr", (getter)pg_circle_getr_sqr, (setter)pg_circle_setr_sqr,
458+
DOC_CIRCLE_RSQR, NULL},
459+
{"d", (getter)pg_circle_getdiameter, (setter)pg_circle_setdiameter,
460+
DOC_CIRCLE_DIAMETER, NULL},
461+
{"diameter", (getter)pg_circle_getdiameter, (setter)pg_circle_setdiameter,
462+
DOC_CIRCLE_DIAMETER, NULL},
463+
{"center", (getter)pg_circle_getcenter, (setter)pg_circle_setcenter,
464+
DOC_CIRCLE_CENTER, NULL},
465+
{"area", (getter)pg_circle_getarea, (setter)pg_circle_setarea,
466+
DOC_CIRCLE_AREA, NULL},
467+
{"circumference", (getter)pg_circle_getcircumference,
468+
(setter)pg_circle_setcircumference, DOC_CIRCLE_CIRCUMFERENCE, NULL},
318469
{NULL, 0, NULL, NULL, NULL}};
319470

320471
static PyTypeObject pgCircle_Type = {

src_c/doc/geometry_doc.h

+5
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@
44
#define DOC_CIRCLE_X "x -> float\ncenter x coordinate of the circle"
55
#define DOC_CIRCLE_Y "y -> float\ncenter y coordinate of the circle"
66
#define DOC_CIRCLE_R "r -> float\nradius of the circle"
7+
#define DOC_CIRCLE_RSQR "r_sqr -> float\nradius of the circle squared"
8+
#define DOC_CIRCLE_CENTER "center -> (float, float)\nx and y coordinates of the center of the circle"
9+
#define DOC_CIRCLE_DIAMETER "diameter -> float\ndiameter of the circle"
10+
#define DOC_CIRCLE_AREA "area -> float\narea of the circle"
11+
#define DOC_CIRCLE_CIRCUMFERENCE "circumference -> float\ncircumference of the circle"
712
#define DOC_CIRCLE_COLLIDEPOINT "collidepoint((x, y)) -> bool\ncollidepoint(x, y) -> bool\ncollidepoint(Vector2) -> bool\ntest if a point is inside the circle"
813
#define DOC_CIRCLE_COPY "copy() -> Circle\nreturns a copy of the circle"

src_c/geometry.h

+12
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,16 @@ static PyTypeObject pgCircle_Type;
2525
static int
2626
pgCircle_FromObject(PyObject *obj, pgCircleBase *out);
2727

28+
/* Constants */
29+
30+
/* PI */
31+
#ifndef M_PI
32+
#define M_PI 3.14159265358979323846
33+
#endif
34+
35+
/* 2PI */
36+
#ifndef M_TWOPI
37+
#define M_TWOPI 6.28318530717958647692
38+
#endif
39+
2840
#endif // PYGAME_CE_GEOMETRY_H

src_c/include/_pygame.h

+28
Original file line numberDiff line numberDiff line change
@@ -617,3 +617,31 @@ pg_tuple_triple_from_values_int(int val1, int val2, int val3)
617617

618618
return tup;
619619
}
620+
621+
static PG_INLINE PyObject *
622+
pg_tuple_couple_from_values_double(double val1, double val2)
623+
{
624+
/* This function turns two input doubles into a python tuple object.
625+
* Currently, 5th November 2022, this is faster than using Py_BuildValue
626+
* to do the same thing.
627+
*/
628+
PyObject *tuple = PyTuple_New(2);
629+
if (!tuple)
630+
return NULL;
631+
632+
PyObject *tmp = PyFloat_FromDouble(val1);
633+
if (!tmp) {
634+
Py_DECREF(tuple);
635+
return NULL;
636+
}
637+
PyTuple_SET_ITEM(tuple, 0, tmp);
638+
639+
tmp = PyFloat_FromDouble(val2);
640+
if (!tmp) {
641+
Py_DECREF(tuple);
642+
return NULL;
643+
}
644+
PyTuple_SET_ITEM(tuple, 1, tmp);
645+
646+
return tuple;
647+
}

0 commit comments

Comments
 (0)