Skip to content

Instantly share code, notes, and snippets.

@jvranish
Created July 9, 2012 16:13
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 jvranish/3077386 to your computer and use it in GitHub Desktop.
Save jvranish/3077386 to your computer and use it in GitHub Desktop.
Example detector function
#include "DetectDanger.h"
bool Detect_Ship_In_Danger(bool * const in_danger,
Position2D const detector1_pos,
Direction2D const detector1_ship_direction_time1,
Direction2D const detector1_ship_direction_time2,
Position2D const detector2_pos,
Direction2D const detector2_ship_direction_time1,
Direction2D const detector2_ship_direction_time2,
Position2D const hazard_pos,
float const hazard_danger_radius)
{
Position2D ship_pos_at_time1;
Position2D ship_pos_at_time2;
/* I really want a maybe monad here :( */
if ( Vector2D_LineIntersection( &ship_pos_at_time1
, detector1_pos
, detector1_ship_direction_time1
, detector2_pos
, detector2_ship_direction_time1))
{
if (Vector2D_LineIntersection( &ship_pos_at_time2
, detector1_pos
, detector1_ship_direction_time2
, detector2_pos
, detector2_ship_direction_time2))
{
Direction2D const ship_direction = Vector2D_Direction( ship_pos_at_time1
, ship_pos_at_time2 );
Position2D const closest_point =
Vector2D_ClosestPointToLine( ship_pos_at_time2
, ship_direction
, hazard_pos);
*in_danger = Vector2D_Distance(closest_point, hazard_pos) <= hazard_danger_radius;
return true;
}
}
return false;
}
#include "Vector2D.h"
bool Detect_Ship_In_Danger(bool * const in_danger,
Position2D const detector1_pos,
Direction2D const detector1_ship_direction_time1,
Direction2D const detector1_ship_direction_time2,
Position2D const detector2_pos,
Direction2D const detector2_ship_direction_time1,
Direction2D const detector2_ship_direction_time2,
Position2D const hazard_pos,
float const hazard_danger_radius);
#include "Vector2D.h"
#include <math.h>
Vector2D Vector2D_Vector(float const x, float const y)
{
Vector2D r;
r.x = x;
r.y = y;
return r;
}
float Vector2D_Magnitude(Vector2D const v)
{
return sqrtf(Vector2D_Dot(v, v));
}
Vector2D Vector2D_Normalize(Vector2D const v)
{
float const mag = Vector2D_Magnitude(v);
float const scale = (mag != 0.0f) ? (1.0f / mag) : 0.0f;
return Vector2D_Scale(v, scale);
}
float Vector2D_Dot(Vector2D const a, Vector2D const b)
{
return a.x * b.x + a.y * b.y;
}
Vector2D Vector2D_Scale(Vector2D const v, float const scale_by)
{
return Vector2D_Vector(v.x * scale_by, v.y * scale_by);
}
Vector2D Vector2D_Add(Vector2D const a, Vector2D const b)
{
return Vector2D_Vector(a.x + b.x, a.y + b.y);
}
Vector2D Vector2D_Sub(Vector2D const a, Vector2D const b)
{
return Vector2D_Vector(a.x - b.x, a.y - b.y);
}
Vector2D Vector2D_Perpendicular(Vector2D const v)
{
return Vector2D_Vector(-v.y, v.x);
}
Position2D Vector2D_Position2D(Vector2D v)
{
Position2D p;
p.position = v;
return p;
}
Direction2D Vector2D_Direction2D(Vector2D v)
{
Direction2D d;
d.direction = v;
return d;
}
float Vector2D_Distance(Position2D const a, Position2D const b)
{
return Vector2D_Magnitude(Vector2D_Sub(b.position, a.position));
}
/* Compute the direction from to b from a */
Direction2D Vector2D_Direction(Position2D const a, Position2D const b)
{
Vector2D const delta = Vector2D_Sub(b.position, a.position);
float const distance = Vector2D_Magnitude(delta);
/* add a special case for 0.0 since we always want our directions to have
a length of 1, (and if the distance is zero, any direction will do) */
Vector2D const result = (distance == 0.0f) ? Vector2D_Vector(1.0f, 0.0f) : Vector2D_Scale(delta, 1.0f / distance);
return Vector2D_Direction2D(result);
}
/* Compute a position a given distance and direction from another position */
Position2D Vector2D_PositionFrom(Position2D const pos, Direction2D dir, float dist)
{
return Vector2D_Position2D(Vector2D_Add(pos.position, Vector2D_Scale(dir.direction, dist)));
}
/*
Algorithm was actually taken from here: http://www.actionscript.org/resources/articles/626/1/Vector-intersection-calculations/Page1.html
of all places.
A generalized form is here: http://en.wikipedia.org/wiki/Line-line_intersection
Returns false if there is no intersection and if we return true, intercept will have the intercept point.
The intercept point assumes v1 and delta share an origin.
*/
bool Vector2D_Intercept(Vector2D * const intercept, Vector2D const v1, Vector2D const v2, Vector2D const delta)
{
float const d1 = Vector2D_Dot(Vector2D_Perpendicular(delta), v2);
float const d2 = Vector2D_Dot(Vector2D_Perpendicular(v1) , v2);
bool const intercept_found = d2 != 0.0f;
if (intercept_found)
{
*intercept = Vector2D_Scale(v1, d1/d2);
}
return intercept_found;
}
/* This just provides a cleaner interfaces around Vector2D_Intercept */
bool Vector2D_LineIntersection( Position2D * const intercept
, Position2D const pos_a, Direction2D const dir_a
, Position2D const pos_b, Direction2D const dir_b )
{
bool const result = Vector2D_Intercept(&intercept->position, dir_a.direction, dir_b.direction, Vector2D_Sub(pos_b.position, pos_a.position));
intercept->position = Vector2D_Add(intercept->position, pos_a.position);
return result;
}
/*
Algorithm taken from here: http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
*/
Position2D Vector2D_ClosestPointToLine( Position2D const point_on_line
, Direction2D const dir_from_point
, Position2D const other_point )
{
Vector2D const delta = Vector2D_Sub(point_on_line.position, other_point.position);
Vector2D const projection = Vector2D_Scale( dir_from_point.direction
, Vector2D_Dot(delta, dir_from_point.direction) );
return Vector2D_Position2D(Vector2D_Sub(point_on_line.position, projection));
}
#include <stdbool.h>
typedef struct
{
float x;
float y;
} Vector2D;
typedef struct
{
Vector2D position;
} Position2D;
/*
Directions should _always_ have a length of 1.0
*/
typedef struct
{
Vector2D direction;
} Direction2D;
Vector2D Vector2D_Vector(float const x, float const y);
float Vector2D_Magnitude(Vector2D const v);
Vector2D Vector2D_Normalize(Vector2D const v);
float Vector2D_Dot(Vector2D const a, Vector2D const b);
Vector2D Vector2D_Scale(Vector2D const v, float const scale_by);
Vector2D Vector2D_Add(Vector2D const a, Vector2D const b);
Vector2D Vector2D_Sub(Vector2D const a, Vector2D const b);
Vector2D Vector2D_Perpendicular(Vector2D const v);
bool Vector2D_Intercept(Vector2D * const intercept, Vector2D const v1, Vector2D const v2, Vector2D const delta);
Position2D Vector2D_Position2D(Vector2D v);
Direction2D Vector2D_Direction2D(Vector2D v);
Direction2D Vector2D_Direction(Position2D const a, Position2D const b);
float Vector2D_Distance(Position2D const a, Position2D const b);
Position2D Vector2D_PositionFrom(Position2D const pos, Direction2D dir, float dist);
bool Vector2D_LineIntersection( Position2D * const intercept
, Position2D const pos_a, Direction2D const dir_a
, Position2D const pos_b, Direction2D const dir_b );
Position2D Vector2D_ClosestPointToLine( Position2D const point_on_line
, Direction2D const dir_from_point
, Position2D const other_point );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment