Skip to content

Instantly share code, notes, and snippets.

@magcius
Created November 27, 2012 21:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save magcius/4157011 to your computer and use it in GitHub Desktop.
Save magcius/4157011 to your computer and use it in GitHub Desktop.
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;
}
}
@Cat-Ion
Copy link

Cat-Ion commented Nov 27, 2012

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;

    /* 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;

}

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); } }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment