Skip to content

Commit

Permalink
Added Line methods and length attribute (#3179)
Browse files Browse the repository at this point in the history
* Added Line methods and 'length: attribute

* fixed minor checks

* Update geometry.pyi

* commit geometry.Line changes

* changed geometry docs

* changed docs, if_else statements and decluttered

* Compacted geometry_common.c

* Update geometry_common.c

* Update line.c
---------


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: itzpr3d4t0r <[email protected]>
  • Loading branch information
7 people authored Dec 1, 2024
1 parent 746197d commit b77bf55
Show file tree
Hide file tree
Showing 7 changed files with 609 additions and 30 deletions.
26 changes: 26 additions & 0 deletions buildconfig/stubs/pygame/geometry.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ class Line:
def b(self) -> tuple[float, float]: ...
@b.setter
def b(self, value: Point) -> None: ...
@property
def length(self) -> float: ...
@overload
def __init__(self, ax: float, ay: float, bx: float, by: float) -> None: ...
@overload
Expand All @@ -171,3 +173,27 @@ class Line:
def __init__(self, line: _LineLike) -> None: ...
def __copy__(self) -> Line: ...
def copy(self) -> Line: ...
@overload
def update(self, ax: float, ay: float, bx: float, by: float, /) -> None: ...
@overload
def update(self, a: Point, b: Point, /) -> None: ...
@overload
def update(self, line: _LineLike, /) -> None: ...
@overload
def move(self, x: float, y: float, /) -> Line: ...
@overload
def move(self, move_by: Point, /) -> Line: ...
@overload
def move_ip(self, x: float, y: float, /) -> None: ...
@overload
def move_ip(self, move_by: Point, /) -> None: ...
@overload
def scale(self, factor: float, origin: float, /) -> Line: ...
@overload
def scale(self, factor_and_origin: Tuple[float, float], /) -> Line: ...
@overload
def scale_ip(self, factor: float, origin: float, /) -> None: ...
@overload
def scale_ip(self, factor_and_origin: Tuple[float, float], /) -> None: ...
def flip_ab(self) -> Line: ...
def flip_ab_ip(self) -> None: ...
143 changes: 136 additions & 7 deletions docs/reST/ref/geometry.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
| :sl:`x and y coordinates of the center of the circle`
| :sg:`center -> (float, float)`
It's a tuple containing the circle's `x` and `y` coordinates representing its center.
A tuple containing the circle's `x` and `y` coordinates representing its center.
Reassigning it moves the circle to the new position.

.. versionadded:: 2.4.0
Expand Down Expand Up @@ -147,7 +147,7 @@
| :sl:`top coordinate of the circle`
| :sg:`top -> (float, float)`
It's a tuple containing the `x` and `y` coordinates that represent the top
A tuple containing the `x` and `y` coordinates that represent the top
of the circle.
Reassigning it moves the circle to the new position. The radius will not be affected.

Expand All @@ -160,7 +160,7 @@
| :sl:`bottom coordinate of the circle`
| :sg:`bottom -> (float, float)`
It's a tuple containing the `x` and `y` coordinates that represent the bottom
A tuple containing the `x` and `y` coordinates that represent the bottom
of the circle.
Reassigning it moves the circle to the new position. The radius will not be affected.

Expand All @@ -173,7 +173,7 @@
| :sl:`left coordinate of the circle`
| :sg:`left -> (float, float)`
It's a tuple containing the `x` and `y` coordinates that represent the left
A tuple containing the `x` and `y` coordinates that represent the left
of the circle.
Reassigning it moves the circle to the new position. The radius will not be affected.

Expand All @@ -186,7 +186,7 @@
| :sl:`right coordinate of the circle`
| :sg:`right -> (float, float)`
It's a tuple containing the `x` and `y` coordinates that represent the right
A tuple containing the `x` and `y` coordinates that represent the right
of the circle.
Reassigning it moves the circle to the new position. The radius will not be affected.

Expand Down Expand Up @@ -574,7 +574,7 @@
| :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.
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.
Expand All @@ -588,7 +588,7 @@
| :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.
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.
Expand All @@ -597,6 +597,19 @@

.. ## Line.b ##
.. attribute:: length

| :sl:`the length of the line`
| :sg:`length -> float`
The length of the line. Calculated using the `sqrt((bx-ax)**2 + (by-ay)**2)` formula.
This attribute is read-only, it cannot be reassigned. To change the line's length
use the `scale` method or change its `a` or `b` attributes.

.. versionadded:: 2.5.3

.. ## Line.length ##
**Line Methods**

----
Expand All @@ -611,3 +624,119 @@
.. versionadded:: 2.5.2

.. ## Line.copy ##
.. method:: move

| :sl:`moves the line by a given amount`
| :sg:`move((x, y)) -> Line`
| :sg:`move(x, y) -> Line`
Returns a new `Line` that is moved by the given offset. The original `Line` is
not modified.

This method is equivalent to the following code:

.. code-block:: python
Line(line.ax + x, line.ay + y, line.bx + x, line.by + y)
.. versionadded:: 2.5.3

.. ## Line.move ##
.. method:: move_ip

| :sl:`moves the line by a given amount`
| :sg:`move_ip((x, y)) -> None`
| :sg:`move_ip(x, y) -> None`
Moves the `Line` by the given offset. The original `Line` is modified. Always returns
`None`.

This method is equivalent to the following code:

.. code-block:: python
line.ax += x
line.ay += y
line.bx += x
line.by += y
.. versionadded:: 2.5.3

.. ## Line.move_ip ##
.. method:: update

| :sl:`updates the line's attributes`
| :sg:`update((ax, ay), (bx, by)) -> None`
| :sg:`update(ax, ay, bx, by) -> None`
| :sg:`update(line) -> None`
Updates the `Line`'s attributes. The original `Line` is modified. Always returns `None`.

This method is equivalent to the following code:

.. code-block:: python
line.ax = ax
line.ay = ay
line.bx = bx
line.by = by
.. versionadded:: 2.5.3

.. ## Line.update ##
.. method:: scale

| :sl:`scales the line by the given factor from the given origin`
| :sg:`scale(factor, origin) -> Line`
| :sg:`scale(factor_and_origin) -> Line`
Returns a new `Line` which is scaled by the given factor from the specified origin with 0.0 being
the starting point, 0.5 being the center and 1.0 being the end point.
The original `Line` is not modified.

.. versionadded:: 2.5.3

.. ## Line.scale ##
.. method:: scale_ip

| :sl:`scales the line by the given factor from the given origin in place`
| :sg:`scale_ip(factor, origin) -> None`
| :sg:`scale_ip(factor_and_origin) -> None`
Scales the `Line` by the given factor from the specified origin with 0.0 being
the starting point, 0.5 being the center and 1.0 being the end point.
The original `Line` is modified.
Always returns `None`.

.. versionadded:: 2.5.3

.. ## Line.scale_ip ##
.. method:: flip_ab

| :sl:`flips the line a and b points`
| :sg:`flip_ab() -> Line`
Returns a new `Line` that has the `a` and `b` points flipped.
The original `Line` is not modified.

.. versionadded:: 2.5.3

.. ## Line.flip_ab ##
.. method:: flip_ab_ip

| :sl:`flips the line a and b points, in place`
| :sg:`flip_ab_ip() -> None`
Flips the `Line`'s `a` and `b` points. The original `Line` is modified.
Always returns `None`.

.. versionadded:: 2.5.3

.. ## Line.flip_ab_ip ##
8 changes: 8 additions & 0 deletions src_c/doc/geometry_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,12 @@
#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_LENGTH "length -> float\nthe length of the line"
#define DOC_LINE_COPY "copy() -> Line\ncopies the line"
#define DOC_LINE_MOVE "move((x, y)) -> Line\nmove(x, y) -> Line\nmoves the line by a given amount"
#define DOC_LINE_MOVEIP "move_ip((x, y)) -> None\nmove_ip(x, y) -> None\nmoves the line by a given amount"
#define DOC_LINE_UPDATE "update((ax, ay), (bx, by)) -> None\nupdate(ax, ay, bx, by) -> None\nupdate(line) -> None\nupdates the line's attributes"
#define DOC_LINE_SCALE "scale(factor, origin) -> Line\nscale(factor_and_origin) -> Line\nscales the line by the given factor from the given origin"
#define DOC_LINE_SCALEIP "scale_ip(factor, origin) -> None\nscale_ip(factor_and_origin) -> None\nscales the line by the given factor from the given origin in place"
#define DOC_LINE_FLIPAB "flip_ab() -> Line\nflips the line a and b points"
#define DOC_LINE_FLIPABIP "flip_ab_ip() -> None\nflips the line a and b points, in place"
58 changes: 36 additions & 22 deletions src_c/geometry_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,29 +162,23 @@ pgLine_FromObject(PyObject *obj, pgLineBase *out)
length = PySequence_Fast_GET_SIZE(obj);
PyObject **farray = PySequence_Fast_ITEMS(obj);

if (length == 4) {
if (!pg_DoubleFromObj(farray[0], &out->ax) ||
!pg_DoubleFromObj(farray[1], &out->ay) ||
!pg_DoubleFromObj(farray[2], &out->bx) ||
!pg_DoubleFromObj(farray[3], &out->by)) {
return 0;
}
return 1;
}
else if (length == 2) {
if (!pg_TwoDoublesFromObj(farray[0], &out->ax, &out->ay) ||
!pg_TwoDoublesFromObj(farray[1], &out->bx, &out->by)) {
PyErr_Clear();
switch (length) {
case 4:
return pg_DoubleFromObj(farray[0], &out->ax) &&
pg_DoubleFromObj(farray[1], &out->ay) &&
pg_DoubleFromObj(farray[2], &out->bx) &&
pg_DoubleFromObj(farray[3], &out->by);
case 2:
return pg_TwoDoublesFromObj(farray[0], &out->ax, &out->ay) &&
pg_TwoDoublesFromObj(farray[1], &out->bx, &out->by);
case 1: /*looks like an arg?*/
if (PyUnicode_Check(farray[0]) ||
!pgLine_FromObject(farray[0], out)) {
return 0;
}
return 1;
default:
return 0;
}
return 1;
}
else if (length == 1) /*looks like an arg?*/ {
if (PyUnicode_Check(farray[0]) ||
!pgLine_FromObject(farray[0], out)) {
return 0;
}
return 1;
}
}
else if (PySequence_Check(obj)) {
Expand Down Expand Up @@ -276,6 +270,26 @@ pgLine_FromObject(PyObject *obj, pgLineBase *out)
return 1;
}

int
pgLine_FromObjectFastcall(PyObject *const *args, Py_ssize_t nargs,
pgLineBase *out)
{
switch (nargs) {
case 1:
return pgLine_FromObject(args[0], out);
case 2:
return pg_TwoDoublesFromObj(args[0], &out->ax, &out->ay) &&
pg_TwoDoublesFromObj(args[1], &out->bx, &out->by);
case 4:
return pg_DoubleFromObj(args[0], &out->ax) &&
pg_DoubleFromObj(args[1], &out->ay) &&
pg_DoubleFromObj(args[2], &out->bx) &&
pg_DoubleFromObj(args[3], &out->by);
default:
return 0;
}
}

static inline int
double_compare(double a, double b)
{
Expand Down
4 changes: 4 additions & 0 deletions src_c/geometry_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pgCircle_FromObjectFastcall(PyObject *const *args, Py_ssize_t nargs,
int
pgLine_FromObject(PyObject *obj, pgLineBase *out);

int
pgLine_FromObjectFastcall(PyObject *const *args, Py_ssize_t nargs,
pgLineBase *out);

static inline int
double_compare(double a, double b);

Expand Down
Loading

0 comments on commit b77bf55

Please sign in to comment.