Created
November 27, 2012 21:05
-
-
Save magcius/4157011 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static BOOL | |
inside_segment(int v, int v1, int v2) | |
{ | |
if (v1 < 0 && v2 < 0) /* line */ | |
return TRUE; | |
else if (v1 < 0) /* ray */ | |
return v <= v2; | |
else if (v2 < 0) /* ray */ | |
return v >= v1; | |
else /* line segment */ | |
return v >= v1 && v <= v2; | |
} | |
#define T(v, a, b) (((float)v) - (a)) / ((b) - (a)) | |
#define F(t, a, b) ((t) * ((a) - (b)) + (a)) | |
/** | |
* Test if the movement vector x1/y1 → x2/y2 is intersecting with the | |
* barrier. A movement vector with the startpoint or endpoint adjacent to | |
* the barrier itself counts as intersecting. | |
* | |
* @param x1 X start coordinate of movement vector | |
* @param y1 Y start coordinate of movement vector | |
* @param x2 X end coordinate of movement vector | |
* @param y2 Y end coordinate of movement vector | |
* @param[out] distance The distance between the start point and the | |
* intersection with the barrier (if applicable). | |
* @return TRUE if the barrier intersects with the given vector | |
*/ | |
BOOL | |
barrier_is_blocking(const struct PointerBarrier * barrier, | |
int x1, int y1, int x2, int y2, double *distance) | |
{ | |
if (barrier_is_vertical(barrier)) { | |
float t, y; | |
t = T(barrier->x1, x1, x2); | |
if (t < 0 || t > 1) | |
return FALSE; | |
/* Edge case: moving away from barrier. */ | |
if (x2 > x1 && t == 0) | |
return FALSE; | |
y = F(t, y1, y2); | |
if (!inside_segment(y, barrier->y1, barrier->y2)) | |
return FALSE; | |
*distance = sqrt((pow(y - y1, 2) + pow(barrier->x1 - x1, 2))); | |
return TRUE; | |
} | |
else { | |
float t, x; | |
t = T(barrier->y1, y1, y2); | |
if (t < 0 || t > 1) | |
return FALSE; | |
/* Edge case: moving away from barrier. */ | |
if (y2 > y1 && t == 0) | |
return FALSE; | |
x = F(t, x1, x2); | |
if (!inside_segment(x, barrier->x1, barrier->x2)) | |
return FALSE; | |
*distance = sqrt((pow(x - x1, 2) + pow(barrier->y1 - y1, 2))); | |
return TRUE; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
BOOL barrier_helper(int x1, int x2, int y1, int y2, int barrierx, int barriery1, int barriery2) {
float t, y;
t = T(barrier->x1, x1, x2);
if (t < 0 || t > 1)
return FALSE;
}
BOOL barrier_is_blocking(...) { if(barrier_is_vertical(barrier)) { barrier_helper(x1, x2, y1, y2, barrier->x1, barrier->y1, barrier->y2); } else { /* Switch x/y coordinates and calculate for a vertical barrier */ barrier_helper(y1, y2, x1, x2, barrier->y1, barrier->x1, barrier->x2); } }