Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added geometry.Line base #3131

Merged
merged 12 commits into from
Oct 12, 2024
Merged
48 changes: 48 additions & 0 deletions buildconfig/stubs/pygame/geometry.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,27 @@ from .rect import Rect, FRect
from .math import Vector2

_CanBeCircle = Union[Circle, Tuple[Point, float], SequenceLike[float]]
_CanBeLine = Union[
damusss marked this conversation as resolved.
Show resolved Hide resolved
Line,
SequenceLike[float],
SequenceLike[Point],
]

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

_CircleValue = Union[_CanBeCircle, _HasCirclettribute]

class _HasLineAttribute(Protocol):
MyreMylar marked this conversation as resolved.
Show resolved Hide resolved
# An object that has a line attribute that is either a line, or a function
# that returns a line
line: Union[_CanBeLine, Callable[[], _CanBeLine]]


_LineValue = Union[_CanBeLine, _HasLineAttribute]

_CanBeCollided = Union[Circle, Rect, FRect, Point, Vector2]
_CanBeIntersected = Union[Circle]

Expand Down Expand Up @@ -134,3 +148,37 @@ class Circle:
def as_frect(self) -> FRect: ...
def copy(self) -> Circle: ...
def __copy__(self) -> Circle: ...

class Line:
@property
def ax(self) -> float: ...
@ax.setter
def ax(self, value: float) -> None: ...
@property
def ay(self) -> float: ...
@ay.setter
def ay(self, value: float) -> None: ...
@property
def bx(self) -> float: ...
@bx.setter
def bx(self, value: float) -> None: ...
@property
def by(self) -> float: ...
@by.setter
def by(self, value: float) -> None: ...
@property
def a(self) -> Tuple[float, float]: ...
@a.setter
def a(self, value: Point) -> None: ...
@property
def b(self) -> Tuple[float, float]: ...
@b.setter
def b(self, value: Point) -> None: ...
@overload
def __init__(self, ax: float, ay: float, bx: float, by: float) -> None: ...
@overload
def __init__(self, a: Point, b: Point) -> None: ...
@overload
def __init__(self, line: _LineValue) -> None: ...
def __copy__(self) -> Line: ...
def copy(self) -> Line: ...
124 changes: 124 additions & 0 deletions docs/reST/ref/geometry.rst
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,127 @@
.. ## Circle.copy ##

.. ## pygame.Circle ##


.. class:: Line

| :sl:`pygame object for representing a line`
| :sg:`Line((ax, ay), (bx, by)) -> Line`
| :sg:`Line(ax, ay, bx, by) -> Line`

.. versionadded:: 2.5.2

The `Line` class provides many useful methods for collision testing, transformation and intersection.
A `Line` can be created from a combination of two pairs of coordinates that represent the start and end points.
Lines can also be created from python objects that are already a `Line` (effectively copying the line) or have an attribute named "line".

Specifically, to construct a `Line` you can pass the ax, ay, bx, and by values as separate
arguments or inside a sequence(list or tuple).

As a special case you can also pass in `pygame.Rect` / `pygame.FRect`, in which case the
line will be created with (x, y, width, height) as the start and end points.

You can create lines with the same start and end points, but beware that some methods may
not work as expected or error out.

Functions that require a `Line` argument may also accept these values as Lines:

::

((ax, ay), (bx, by))
(ax, ay, bx, by)
(vector2, vector2)

The `Line` class only stores the ax, ay, bx, and by attributes, everything else is calculated
on the fly based on them.

**Line Attributes**

----

.. attribute:: ax

| :sl:`x coordinate of the start point of the line`
| :sg:`ax -> float`

The horizontal coordinate of the start point of the line. Reassigning it moves the line.

.. versionadded:: 2.5.2

.. ## Line.ax ##

.. attribute:: ay

| :sl:`y coordinate of the start point of the line`
| :sg:`ay -> float`

The vertical coordinate of the start point of the line. Reassigning it moves the line.

.. versionadded:: 2.5.2

.. ## Line.ay ##

.. attribute:: bx

| :sl:`x coordinate of the end point of the line`
| :sg:`bx -> float`

The horizontal coordinate of the end point of the line. Reassigning it moves the line.

.. versionadded:: 2.5.2

.. ## Line.bx ##

.. attribute:: by

| :sl:`y coordinate of the end point of the line`
| :sg:`by -> float`

The vertical coordinate of the end point of the line. Reassigning it moves the line.

.. versionadded:: 2.5.2

.. ## Line.by ##

.. attribute:: a

| :sl:`the first point of the line`
| :sg:`a -> (float, float)`

It's a tuple containing the `ax` and `ay` attributes representing the line's first point.
It can be reassigned to move the `Line`. If reassigned the `ax` and `ay` attributes
will be changed to produce a `Line` with matching first point position.
The `bx` and `by` attributes will not be affected.

.. versionadded:: 2.5.2

.. ## Line.a ##

.. attribute:: b

| :sl:`the second point of the line`
| :sg:`b -> (float, float)`

It's a tuple containing `bx` and `by` attributes representing the line's second point.
It can be reassigned to move the `Line`. If reassigned the `bx` and `by` attributes
will be changed to produce a `Line` with matching second point position.
The `ax` and `ay` attributes will not be affected.

.. versionadded:: 2.5.2

.. ## Line.b ##

**Line Methods**

----

.. method:: copy

| :sl:`copies the line`
| :sg:`copy() -> Line`

Returns a copy of this `Line`.

.. versionadded:: 2.5.2

.. ## Line.copy ##
2 changes: 1 addition & 1 deletion src_c/_pygame.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,6 @@ typedef enum {
#define PYGAMEAPI_BASE_NUMSLOTS 29
#define PYGAMEAPI_EVENT_NUMSLOTS 10
#define PYGAMEAPI_WINDOW_NUMSLOTS 1
#define PYGAMEAPI_GEOMETRY_NUMSLOTS 1
#define PYGAMEAPI_GEOMETRY_NUMSLOTS 2

#endif /* _PYGAME_INTERNAL_H */
8 changes: 8 additions & 0 deletions src_c/doc/geometry_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,11 @@
#define DOC_CIRCLE_ASRECT "as_rect() -> Rect\nreturns the smallest Rect containing the circle"
#define DOC_CIRCLE_ASFRECT "as_frect() -> FRect\nreturns the smallest FRect containing the circle"
#define DOC_CIRCLE_COPY "copy() -> Circle\ncopies the circle"
#define DOC_LINE "Line((ax, ay), (bx, by)) -> Line\nLine(ax, ay, bx, by) -> Line\npygame object for representing a line"
#define DOC_LINE_AX "ax -> float\nx coordinate of the start point of the line"
#define DOC_LINE_AY "ay -> float\ny coordinate of the start point of the line"
#define DOC_LINE_BX "bx -> float\nx coordinate of the end point of the line"
#define DOC_LINE_BY "by -> float\ny coordinate of the end point of the line"
#define DOC_LINE_A "a -> (float, float)\nthe first point of the line"
#define DOC_LINE_B "b -> (float, float)\nthe second point of the line"
#define DOC_LINE_COPY "copy() -> Line\ncopies the line"
13 changes: 13 additions & 0 deletions src_c/geometry.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "circle.c"
#include "line.c"
#include "geometry_common.c"

static PyMethodDef geometry_methods[] = {{NULL, NULL, 0, NULL}};
Expand Down Expand Up @@ -30,6 +31,10 @@ MODINIT_DEFINE(geometry)
return NULL;
}

if (PyType_Ready(&pgLine_Type) < 0) {
return NULL;
}

module = PyModule_Create(&_module);
if (!module) {
return NULL;
Expand All @@ -42,7 +47,15 @@ MODINIT_DEFINE(geometry)
return NULL;
}

Py_INCREF(&pgLine_Type);
if (PyModule_AddObject(module, "Line", (PyObject *)&pgLine_Type)) {
Py_DECREF(&pgLine_Type);
Py_DECREF(module);
return NULL;
}

c_api[0] = &pgCircle_Type;
c_api[1] = &pgLine_Type;
apiobj = encapsulate_api(c_api, "geometry");
if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) {
Py_XDECREF(apiobj);
Expand Down
19 changes: 16 additions & 3 deletions src_c/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,25 @@ typedef struct {

#define pgCircle_CAST(o) ((pgCircleObject *)(o))
#define pgCircle_AsCircle(o) (pgCircle_CAST(o)->circle)
#define pgCircle_GETX(self) (pgCircle_CAST(self)->circle.x)
#define pgCircle_GETY(self) (pgCircle_CAST(self)->circle.y)
#define pgCircle_GETR(self) (pgCircle_CAST(self)->circle.r)
itzpr3d4t0r marked this conversation as resolved.
Show resolved Hide resolved
#define pgCircle_Check(o) ((o)->ob_type == &pgCircle_Type)

typedef struct {
double ax, ay;
double bx, by;
} pgLineBase;

typedef struct {
PyObject_HEAD pgLineBase line;
PyObject *weakreflist;
} pgLineObject;

#define pgLine_CAST(o) ((pgLineObject *)(o))
#define pgLine_AsLine(o) (pgLine_CAST(o)->line)
#define pgLine_Check(o) ((o)->ob_type == &pgLine_Type)

static PyTypeObject pgCircle_Type;
static PyTypeObject pgLine_Type;

/* Constants */

/* PI */
Expand Down
Loading
Loading