mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-01 22:21:05 +00:00
Change point-in-polygon algorithm
This commit is contained in:
parent
bc5a0098ea
commit
0211492d96
1 changed files with 19 additions and 56 deletions
75
src/r_main.c
75
src/r_main.c
|
@ -1020,76 +1020,39 @@ void R_Init(void)
|
|||
boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y)
|
||||
{
|
||||
size_t i;
|
||||
line_t *closest = NULL;
|
||||
fixed_t closestdist = INT32_MAX;
|
||||
size_t passes = 0;
|
||||
|
||||
for (i = 0; i < sector->linecount; i++)
|
||||
{
|
||||
vertex_t v, *v1, *v2;
|
||||
fixed_t dist;
|
||||
|
||||
// find the line closest to the point we're looking for.
|
||||
P_ClosestPointOnLine(x, y, sector->lines[i], &v);
|
||||
vertex_t *v1, *v2;
|
||||
|
||||
v1 = sector->lines[i]->v1;
|
||||
v2 = sector->lines[i]->v2;
|
||||
|
||||
// do some correction in order to prevent points outside the line from being measured.
|
||||
if (abs(v1->x - v2->x) > abs(v1->y - v2->y))
|
||||
// make sure v1 is below v2
|
||||
if (v1->y > v2->y)
|
||||
{
|
||||
if (v.x < v1->x && v.x < v2->x)
|
||||
v = v1->x < v2->x ? *v1 : *v2;
|
||||
else if (v.x > v1->x && v.x > v2->x)
|
||||
v = v1->x > v2->x ? *v1 : *v2;
|
||||
vertex_t *tmp = v1;
|
||||
v1 = v2;
|
||||
v2 = tmp;
|
||||
}
|
||||
else
|
||||
else if (v1->y == v2->y)
|
||||
// horizontal line, we can't match this
|
||||
continue;
|
||||
|
||||
if (v1->y <= y && y < v2->y)
|
||||
{
|
||||
if (v.y < v1->y && v.y < v2->y)
|
||||
v = v1->y < v2->y ? *v1 : *v2;
|
||||
else if (v.y > v1->y && v.y > v2->y)
|
||||
v = v1->y > v2->y ? *v1 : *v2;
|
||||
}
|
||||
// if the y axis in inside the line, find the point where we intersect on the x axis...
|
||||
fixed_t vx = v1->x + (INT64)(v2->x - v1->x) * (y - v1->y) / (v2->y - v1->y);
|
||||
|
||||
dist = R_PointToDist2(v.x, v.y, x, y);
|
||||
if (dist < closestdist)
|
||||
{
|
||||
closest = sector->lines[i];
|
||||
closestdist = dist;
|
||||
}
|
||||
else if (dist == closestdist)
|
||||
{
|
||||
// coordinates are the same; we're most likely matching against a corner here.
|
||||
// check closest angle instead.
|
||||
vertex_t *cv, *dv;
|
||||
angle_t angle = R_PointToAngle2(v.x, v.y, x, y);
|
||||
angle_t ca, da;
|
||||
if (closest->v1->x == v.x && closest->v1->y == v.y)
|
||||
cv = closest->v2;
|
||||
else
|
||||
cv = closest->v1;
|
||||
|
||||
if (v1->x == v.x && v1->y == v.y)
|
||||
dv = v2;
|
||||
else
|
||||
dv = v1;
|
||||
|
||||
ca = R_PointToAngle2(v.x, v.y, cv->x, cv->y) - angle;
|
||||
da = R_PointToAngle2(v.x, v.y, dv->x, dv->y) - angle;
|
||||
if (ca > ANGLE_180)
|
||||
ca = -ca;
|
||||
if (da > ANGLE_180)
|
||||
da = -da;
|
||||
|
||||
if (ca > da)
|
||||
{
|
||||
closest = sector->lines[i];
|
||||
closestdist = dist;
|
||||
}
|
||||
// ...and if that point is to the left of the point, count it as inside.
|
||||
if (vx < x)
|
||||
passes++;
|
||||
}
|
||||
}
|
||||
|
||||
// if the side of the closest line is in this sector, we're inside of it.
|
||||
return P_PointOnLineSide(x, y, closest) == 0 ? closest->frontsector == sector : closest->backsector == sector;
|
||||
// and odd number of passes means we're inside the polygon.
|
||||
return passes % 2;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue