Skip to content

Commit 7f18a37

Browse files
itzpr3d4t0rEmc2356andrewhong04ScriptLineStudiosavaxar
authored
Added geometry.Line base (#3131)
* Added a first implementation of the geometry.Line class. Co-authored-by: Emc2356 <[email protected]> Co-authored-by: NovialRiptide <[email protected]> Co-authored-by: ScriptLineStudios <[email protected]> Co-authored-by: Avaxar <[email protected]> Co-authored-by: maqa41 <[email protected]> * fixed geometry.pyi a bit, removed redundant tuple specification as covered by SequenceLike. * more fixes and added FRect to _CanBeLine. * last .pyi fixes. * removed some unused/duplicate defines. * Fix merge errors * Now accepting degenerate lines, added some more __init__ tests. * Move pgLine_FromObject to geometry_common to conform with circle. * Now using PySequence_ITEM in pgLine_FromObject. * remove doc about not accepting degenerate lines * Renamed (xa, ya, xb, yb) -> (ax, ay, bx, by). Removed Rect/Frect from canbeline stub. Added some more info about passing a Rect/Frect to construct a Line and about degenerate lines potentially making some methods not work. --------- Co-authored-by: Emc2356 <[email protected]> Co-authored-by: NovialRiptide <[email protected]> Co-authored-by: ScriptLineStudios <[email protected]> Co-authored-by: Avaxar <[email protected]> Co-authored-by: maqa41 <[email protected]> Co-authored-by: Dan Lawrence <[email protected]>
1 parent dd3df52 commit 7f18a37

File tree

10 files changed

+884
-5
lines changed

10 files changed

+884
-5
lines changed

buildconfig/stubs/pygame/geometry.pyi

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,27 @@ from pygame.typing import Point, RectLike, SequenceLike
1313
from .math import Vector2
1414

1515
_CanBeCircle = Union[Circle, Tuple[Point, float], SequenceLike[float]]
16+
_CanBeLine = Union[
17+
Line,
18+
SequenceLike[float],
19+
SequenceLike[Point],
20+
]
1621

1722
class _HasCirclettribute(Protocol):
1823
# An object that has a circle attribute that is either a circle, or a function
1924
# that returns a circle
2025
circle: Union[_CanBeCircle, Callable[[], _CanBeCircle]]
2126

2227
_CircleValue = Union[_CanBeCircle, _HasCirclettribute]
28+
29+
class _HasLineAttribute(Protocol):
30+
# An object that has a line attribute that is either a line, or a function
31+
# that returns a line
32+
line: Union[_CanBeLine, Callable[[], _CanBeLine]]
33+
34+
35+
_LineValue = Union[_CanBeLine, _HasLineAttribute]
36+
2337
_CanBeCollided = Union[Circle, Rect, FRect, Point, Vector2]
2438
_CanBeIntersected = Union[Circle]
2539

@@ -133,3 +147,37 @@ class Circle:
133147
def as_frect(self) -> FRect: ...
134148
def copy(self) -> Circle: ...
135149
def __copy__(self) -> Circle: ...
150+
151+
class Line:
152+
@property
153+
def ax(self) -> float: ...
154+
@ax.setter
155+
def ax(self, value: float) -> None: ...
156+
@property
157+
def ay(self) -> float: ...
158+
@ay.setter
159+
def ay(self, value: float) -> None: ...
160+
@property
161+
def bx(self) -> float: ...
162+
@bx.setter
163+
def bx(self, value: float) -> None: ...
164+
@property
165+
def by(self) -> float: ...
166+
@by.setter
167+
def by(self, value: float) -> None: ...
168+
@property
169+
def a(self) -> Tuple[float, float]: ...
170+
@a.setter
171+
def a(self, value: Point) -> None: ...
172+
@property
173+
def b(self) -> Tuple[float, float]: ...
174+
@b.setter
175+
def b(self, value: Point) -> None: ...
176+
@overload
177+
def __init__(self, ax: float, ay: float, bx: float, by: float) -> None: ...
178+
@overload
179+
def __init__(self, a: Point, b: Point) -> None: ...
180+
@overload
181+
def __init__(self, line: _LineValue) -> None: ...
182+
def __copy__(self) -> Line: ...
183+
def copy(self) -> Line: ...

docs/reST/ref/geometry.rst

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,3 +487,127 @@
487487
.. ## Circle.copy ##
488488
489489
.. ## pygame.Circle ##
490+
491+
492+
.. class:: Line
493+
494+
| :sl:`pygame object for representing a line`
495+
| :sg:`Line((ax, ay), (bx, by)) -> Line`
496+
| :sg:`Line(ax, ay, bx, by) -> Line`
497+
498+
.. versionadded:: 2.5.2
499+
500+
The `Line` class provides many useful methods for collision testing, transformation and intersection.
501+
A `Line` can be created from a combination of two pairs of coordinates that represent the start and end points.
502+
Lines can also be created from python objects that are already a `Line` (effectively copying the line) or have an attribute named "line".
503+
504+
Specifically, to construct a `Line` you can pass the ax, ay, bx, and by values as separate
505+
arguments or inside a sequence(list or tuple).
506+
507+
As a special case you can also pass in `pygame.Rect` / `pygame.FRect`, in which case the
508+
line will be created with (x, y, width, height) as the start and end points.
509+
510+
You can create lines with the same start and end points, but beware that some methods may
511+
not work as expected or error out.
512+
513+
Functions that require a `Line` argument may also accept these values as Lines:
514+
515+
::
516+
517+
((ax, ay), (bx, by))
518+
(ax, ay, bx, by)
519+
(vector2, vector2)
520+
521+
The `Line` class only stores the ax, ay, bx, and by attributes, everything else is calculated
522+
on the fly based on them.
523+
524+
**Line Attributes**
525+
526+
----
527+
528+
.. attribute:: ax
529+
530+
| :sl:`x coordinate of the start point of the line`
531+
| :sg:`ax -> float`
532+
533+
The horizontal coordinate of the start point of the line. Reassigning it moves the line.
534+
535+
.. versionadded:: 2.5.2
536+
537+
.. ## Line.ax ##
538+
539+
.. attribute:: ay
540+
541+
| :sl:`y coordinate of the start point of the line`
542+
| :sg:`ay -> float`
543+
544+
The vertical coordinate of the start point of the line. Reassigning it moves the line.
545+
546+
.. versionadded:: 2.5.2
547+
548+
.. ## Line.ay ##
549+
550+
.. attribute:: bx
551+
552+
| :sl:`x coordinate of the end point of the line`
553+
| :sg:`bx -> float`
554+
555+
The horizontal coordinate of the end point of the line. Reassigning it moves the line.
556+
557+
.. versionadded:: 2.5.2
558+
559+
.. ## Line.bx ##
560+
561+
.. attribute:: by
562+
563+
| :sl:`y coordinate of the end point of the line`
564+
| :sg:`by -> float`
565+
566+
The vertical coordinate of the end point of the line. Reassigning it moves the line.
567+
568+
.. versionadded:: 2.5.2
569+
570+
.. ## Line.by ##
571+
572+
.. attribute:: a
573+
574+
| :sl:`the first point of the line`
575+
| :sg:`a -> (float, float)`
576+
577+
It's a tuple containing the `ax` and `ay` attributes representing the line's first point.
578+
It can be reassigned to move the `Line`. If reassigned the `ax` and `ay` attributes
579+
will be changed to produce a `Line` with matching first point position.
580+
The `bx` and `by` attributes will not be affected.
581+
582+
.. versionadded:: 2.5.2
583+
584+
.. ## Line.a ##
585+
586+
.. attribute:: b
587+
588+
| :sl:`the second point of the line`
589+
| :sg:`b -> (float, float)`
590+
591+
It's a tuple containing `bx` and `by` attributes representing the line's second point.
592+
It can be reassigned to move the `Line`. If reassigned the `bx` and `by` attributes
593+
will be changed to produce a `Line` with matching second point position.
594+
The `ax` and `ay` attributes will not be affected.
595+
596+
.. versionadded:: 2.5.2
597+
598+
.. ## Line.b ##
599+
600+
**Line Methods**
601+
602+
----
603+
604+
.. method:: copy
605+
606+
| :sl:`copies the line`
607+
| :sg:`copy() -> Line`
608+
609+
Returns a copy of this `Line`.
610+
611+
.. versionadded:: 2.5.2
612+
613+
.. ## Line.copy ##

src_c/_pygame.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,6 @@ typedef enum {
540540
#define PYGAMEAPI_BASE_NUMSLOTS 29
541541
#define PYGAMEAPI_EVENT_NUMSLOTS 10
542542
#define PYGAMEAPI_WINDOW_NUMSLOTS 1
543-
#define PYGAMEAPI_GEOMETRY_NUMSLOTS 1
543+
#define PYGAMEAPI_GEOMETRY_NUMSLOTS 2
544544

545545
#endif /* _PYGAME_INTERNAL_H */

src_c/doc/geometry_doc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,11 @@
2929
#define DOC_CIRCLE_ASRECT "as_rect() -> Rect\nreturns the smallest Rect containing the circle"
3030
#define DOC_CIRCLE_ASFRECT "as_frect() -> FRect\nreturns the smallest FRect containing the circle"
3131
#define DOC_CIRCLE_COPY "copy() -> Circle\ncopies the circle"
32+
#define DOC_LINE "Line((ax, ay), (bx, by)) -> Line\nLine(ax, ay, bx, by) -> Line\npygame object for representing a line"
33+
#define DOC_LINE_AX "ax -> float\nx coordinate of the start point of the line"
34+
#define DOC_LINE_AY "ay -> float\ny coordinate of the start point of the line"
35+
#define DOC_LINE_BX "bx -> float\nx coordinate of the end point of the line"
36+
#define DOC_LINE_BY "by -> float\ny coordinate of the end point of the line"
37+
#define DOC_LINE_A "a -> (float, float)\nthe first point of the line"
38+
#define DOC_LINE_B "b -> (float, float)\nthe second point of the line"
39+
#define DOC_LINE_COPY "copy() -> Line\ncopies the line"

src_c/geometry.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "circle.c"
2+
#include "line.c"
23
#include "geometry_common.c"
34

45
static PyMethodDef geometry_methods[] = {{NULL, NULL, 0, NULL}};
@@ -30,6 +31,10 @@ MODINIT_DEFINE(geometry)
3031
return NULL;
3132
}
3233

34+
if (PyType_Ready(&pgLine_Type) < 0) {
35+
return NULL;
36+
}
37+
3338
module = PyModule_Create(&_module);
3439
if (!module) {
3540
return NULL;
@@ -42,7 +47,15 @@ MODINIT_DEFINE(geometry)
4247
return NULL;
4348
}
4449

50+
Py_INCREF(&pgLine_Type);
51+
if (PyModule_AddObject(module, "Line", (PyObject *)&pgLine_Type)) {
52+
Py_DECREF(&pgLine_Type);
53+
Py_DECREF(module);
54+
return NULL;
55+
}
56+
4557
c_api[0] = &pgCircle_Type;
58+
c_api[1] = &pgLine_Type;
4659
apiobj = encapsulate_api(c_api, "geometry");
4760
if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) {
4861
Py_XDECREF(apiobj);

src_c/geometry.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,25 @@ typedef struct {
1616

1717
#define pgCircle_CAST(o) ((pgCircleObject *)(o))
1818
#define pgCircle_AsCircle(o) (pgCircle_CAST(o)->circle)
19-
#define pgCircle_GETX(self) (pgCircle_CAST(self)->circle.x)
20-
#define pgCircle_GETY(self) (pgCircle_CAST(self)->circle.y)
21-
#define pgCircle_GETR(self) (pgCircle_CAST(self)->circle.r)
2219
#define pgCircle_Check(o) ((o)->ob_type == &pgCircle_Type)
2320

21+
typedef struct {
22+
double ax, ay;
23+
double bx, by;
24+
} pgLineBase;
25+
26+
typedef struct {
27+
PyObject_HEAD pgLineBase line;
28+
PyObject *weakreflist;
29+
} pgLineObject;
30+
31+
#define pgLine_CAST(o) ((pgLineObject *)(o))
32+
#define pgLine_AsLine(o) (pgLine_CAST(o)->line)
33+
#define pgLine_Check(o) ((o)->ob_type == &pgLine_Type)
34+
2435
static PyTypeObject pgCircle_Type;
36+
static PyTypeObject pgLine_Type;
37+
2538
/* Constants */
2639

2740
/* PI */

0 commit comments

Comments
 (0)