spline and edge commands

This commit is contained in:
John Alanbrook 2023-02-10 20:31:58 +00:00
parent 99e9807552
commit 1fcdae17ba
2 changed files with 41 additions and 8 deletions

View file

@ -302,9 +302,23 @@ void ints2duk(int *ints)
} }
} }
int vec_between(cpVect p, cpVect a, cpVect b)
{
cpVect n;
n.x = b.x - a.x;
n.y = b.y - a.y;
n = cpvnormalize(n);
return (cpvdot(n, cpvsub(p, a)) > 0 && cpvdot(cpvneg(n), cpvsub(p, b)) > 0);
}
/* Determines between which two points in 'segs' point 'p' falls.
0 indicates 'p' comes before the first point.
arrlen(segs) indicates it comes after the last point.
*/
int point2segindex(cpVect p, cpVect *segs, double slop) int point2segindex(cpVect p, cpVect *segs, double slop)
{ {
float shortest = slop; float shortest = slop < 0 ? INFINITY : slop;
int best = -1; int best = -1;
for (int i = 0; i < arrlen(segs)-1; i++) for (int i = 0; i < arrlen(segs)-1; i++)
@ -315,19 +329,34 @@ int point2segindex(cpVect p, cpVect *segs, double slop)
float dist = abs(a*p.x + b*p.y + c) / sqrt(pow(a,2) + 1); float dist = abs(a*p.x + b*p.y + c) / sqrt(pow(a,2) + 1);
if (dist < shortest) { if (dist > shortest) continue;
int between = vec_between(p, segs[i], segs[i+1]);
if (between) {
shortest = dist; shortest = dist;
best = i; best = i+1;
} else {
if (i == 0 && cpvdist(p, segs[0]) < slop) {
shortest = dist;
best = i;
} else if (i == arrlen(segs)-2 && cpvdist(p, arrlast(segs)) < slop) {
shortest = dist;
best = arrlen(segs);
}
} }
} }
if (best == 0) { if (best == 1) {
cpVect n; cpVect n;
n.x = segs[1].x-segs[0].x; n.x = segs[1].x-segs[0].x;
n.y = segs[1].y-segs[0].y; n.y = segs[1].y-segs[0].y;
n = cpvnormalize(n); n = cpvnormalize(n);
if (cpvdot(n, cpvsub(p, segs[0])) < 0 && cpvdist(p, segs[0]) >= slop) if (cpvdot(n, cpvsub(p, segs[0])) < 0)
best = -1; if (cpvdist(p, segs[0]) >= slop)
best = -1;
else
best = 0;
} }
if (best == arrlen(segs)-1) { if (best == arrlen(segs)-1) {
@ -336,8 +365,11 @@ int point2segindex(cpVect p, cpVect *segs, double slop)
n.y = segs[best-1].y-segs[best-1].y; n.y = segs[best-1].y-segs[best-1].y;
n = cpvnormalize(n); n = cpvnormalize(n);
if (cpvdot(n, cpvsub(p, segs[best])) < 0 && cpvdist(p, segs[best]) >= slop) if (cpvdot(n, cpvsub(p, segs[best])) < 0)
best = -1; if (cpvdist(p, segs[best]) >= slop)
best = -1;
else
best = arrlen(segs);
} }

View file

@ -53,6 +53,7 @@ int pos2gameobject(cpVect pos)
} }
for (int i = 0; i < arrlen(gameobjects); i++) { for (int i = 0; i < arrlen(gameobjects); i++) {
if (!gameobjects[i].body) continue;
cpVect gpos = cpBodyGetPosition(gameobjects[i].body); cpVect gpos = cpBodyGetPosition(gameobjects[i].body);
float dist = cpvlength(cpvsub(gpos, pos)); float dist = cpvlength(cpvsub(gpos, pos));