Skip to content

Commit 74a4209

Browse files
committed
base
1 parent 5fbff8f commit 74a4209

File tree

5 files changed

+120
-0
lines changed

5 files changed

+120
-0
lines changed

geometry.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class Line(Sequence[float]):
109109
def collidecircle(self, circle: CircleValue) -> bool: ...
110110
@overload
111111
def collidecircle(self, x: float, y: float, r: float) -> bool: ...
112+
def collidepolygon(self, polygon: Polygon) -> bool: ...
112113
def as_rect(self) -> Rect: ...
113114
@overload
114115
def move(self, x: float, y: float) -> Line: ...
@@ -214,6 +215,7 @@ class Polygon:
214215
def collidepoint(self, x: float, y: float) -> bool: ...
215216
@overload
216217
def collidepoint(self, point: Coordinate) -> bool: ...
218+
def collideline(self, line: LineValue) -> bool: ...
217219
def get_bounding_box(self) -> Rect: ...
218220
def is_convex() -> bool: ...
219221
def insert_vertex(self, index: int, vertex: Coordinate) -> None: ...

src_c/collisions.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,70 @@ pgCollision_PolygonPoint(pgPolygonBase *poly, double x, double y)
319319
return collision;
320320
}
321321

322+
static inline int
323+
pgCollision_PolygonPoints(pgPolygonBase *poly, double x1, double y1, double x2,
324+
double y2)
325+
{
326+
int collision1 = 0, collision2 = 0;
327+
Py_ssize_t i, j;
328+
329+
double *vertices = poly->vertices;
330+
331+
for (i = 0, j = poly->verts_num - 1; i < poly->verts_num; j = i++) {
332+
double xi = vertices[i * 2];
333+
double yi = vertices[i * 2 + 1];
334+
double xj = vertices[j * 2];
335+
double yj = vertices[j * 2 + 1];
336+
337+
double xj_xi = xj - xi;
338+
double yj_yi = yj - yi;
339+
340+
if (((yi > y1) != (yj > y1)) &&
341+
(x1 < xj_xi * (y1 - yi) / yj_yi + xi)) {
342+
collision1 = !collision1;
343+
}
344+
345+
if (((yi > y2) != (yj > y2)) &&
346+
(x2 < xj_xi * (y2 - yi) / yj_yi + xi)) {
347+
collision2 = !collision2;
348+
}
349+
}
350+
351+
return collision1 || collision2;
352+
}
353+
354+
static inline int
355+
_pgCollision_line_edges(pgLineBase *line, pgPolygonBase *poly)
356+
{
357+
Py_ssize_t i, j;
358+
double *vertices = poly->vertices;
359+
360+
for (i = 0, j = poly->verts_num - 1; i < poly->verts_num; j = i++) {
361+
if (pgCollision_LineLine(line, &(pgLineBase){vertices[j * 2],
362+
vertices[j * 2 + 1],
363+
vertices[i * 2],
364+
vertices[i * 2 + 1]})) {
365+
return 1;
366+
}
367+
}
368+
369+
return 0;
370+
}
371+
372+
static inline int
373+
pgCollision_PolygonLine(pgPolygonBase *poly, pgLineBase *line, int only_edges)
374+
{
375+
int collision = 0;
376+
collision = _pgCollision_line_edges(line, poly);
377+
378+
if (collision || only_edges) {
379+
return collision;
380+
}
381+
382+
return pgCollision_PolygonPoints(poly, line->x1, line->y1, line->x2,
383+
line->y2);
384+
}
385+
322386
static int
323387
pgRaycast_LineLine(pgLineBase *A, pgLineBase *B, double max_t, double *T)
324388
{

src_c/include/collisions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@ pgRaycast_LineCircle(pgLineBase *, pgCircleBase *, double, double *);
4343
static int
4444
pgCollision_PolygonPoint(pgPolygonBase *, double, double);
4545

46+
static int
47+
pgCollision_PolygonLine(pgPolygonBase *, pgLineBase *, int);
48+
4649
#endif /* ~_PG_COLLISIONS_H */

src_c/line.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,33 @@ pg_line_flip_ip(pgLineObject *self, PyObject *_null)
490490
Py_RETURN_NONE;
491491
}
492492

493+
static PyObject *
494+
pg_line_collidepolygon(pgLineObject *self, PyObject *const *args,
495+
Py_ssize_t nargs)
496+
{
497+
pgPolygonBase poly;
498+
int was_sequence, result = 0, only_edges = 0;
499+
500+
if (PyBool_Check(args[nargs - 1])) {
501+
if (args[nargs - 1] == Py_True) {
502+
only_edges = 1;
503+
}
504+
nargs--;
505+
}
506+
507+
if (!pgPolygon_FromObjectFastcall(args, nargs, &poly, &was_sequence)) {
508+
return RAISE(
509+
PyExc_TypeError,
510+
"collidepolygon requires a Polygon or PolygonLike object");
511+
}
512+
513+
result = pgCollision_PolygonLine(&poly, &self->line, only_edges);
514+
515+
PG_FREEPOLY_COND(&poly, was_sequence);
516+
517+
return PyBool_FromLong(result);
518+
}
519+
493520
static struct PyMethodDef pg_line_methods[] = {
494521
{"__copy__", (PyCFunction)pg_line_copy, METH_NOARGS, NULL},
495522
{"copy", (PyCFunction)pg_line_copy, METH_NOARGS, NULL},
@@ -501,6 +528,7 @@ static struct PyMethodDef pg_line_methods[] = {
501528
{"collidecircle", (PyCFunction)pg_line_collidecircle, METH_FASTCALL, NULL},
502529
{"colliderect", (PyCFunction)pg_line_colliderect, METH_FASTCALL, NULL},
503530
{"collideswith", (PyCFunction)pg_line_collideswith, METH_O, NULL},
531+
{"collidepolygon", (PyCFunction)pg_line_collidepolygon, METH_FASTCALL, NULL},
504532
{"as_rect", (PyCFunction)pg_line_as_rect, METH_NOARGS, NULL},
505533
{"update", (PyCFunction)pg_line_update, METH_FASTCALL, NULL},
506534
{"move", (PyCFunction)pg_line_move, METH_FASTCALL, NULL},

src_c/polygon.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,13 +1134,36 @@ pg_polygon_is_convex(pgPolygonObject *self, PyObject *_null)
11341134
return PyBool_FromLong(_pg_polygon_is_convex_helper(&self->polygon));
11351135
}
11361136

1137+
static PyObject *
1138+
pg_polygon_collideline(pgPolygonObject *self, PyObject *const *args,
1139+
Py_ssize_t nargs)
1140+
{
1141+
pgLineBase line;
1142+
int only_edges = 0;
1143+
1144+
if (PyBool_Check(args[nargs - 1])) {
1145+
if (args[nargs - 1] == Py_True) {
1146+
only_edges = 1;
1147+
}
1148+
nargs--;
1149+
}
1150+
1151+
if (!pgLine_FromObjectFastcall(args, nargs, &line)) {
1152+
return RAISE(PyExc_TypeError, "Invalid line parameter");
1153+
}
1154+
1155+
return PyBool_FromLong(
1156+
pgCollision_PolygonLine(&self->polygon, &line, only_edges));
1157+
}
1158+
11371159
static struct PyMethodDef pg_polygon_methods[] = {
11381160
{"move", (PyCFunction)pg_polygon_move, METH_FASTCALL, NULL},
11391161
{"move_ip", (PyCFunction)pg_polygon_move_ip, METH_FASTCALL, NULL},
11401162
{"rotate", (PyCFunction)pg_polygon_rotate, METH_O, NULL},
11411163
{"rotate_ip", (PyCFunction)pg_polygon_rotate_ip, METH_O, NULL},
11421164
{"collidepoint", (PyCFunction)pg_polygon_collidepoint, METH_FASTCALL,
11431165
NULL},
1166+
{"collideline", (PyCFunction)pg_polygon_collideline, METH_FASTCALL, NULL},
11441167
{"get_bounding_box", (PyCFunction)pg_polygon_get_bounding_box, METH_NOARGS,
11451168
NULL},
11461169
{"is_convex", (PyCFunction)pg_polygon_is_convex, METH_NOARGS, NULL},

0 commit comments

Comments
 (0)