From: Barak Itkin Date: Fri, 20 Apr 2012 20:22:06 +0000 (+0300) Subject: Add some basic geometric primitives X-Git-Tag: p2tc-0.1.0~106 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b6925533c0136e843f3d35b7dd327492a3b2162e;p=poly2tri-c Add some basic geometric primitives --- diff --git a/refine/bounded-line.c b/refine/bounded-line.c new file mode 100644 index 0000000..fdf96d5 --- /dev/null +++ b/refine/bounded-line.c @@ -0,0 +1,52 @@ +#include +#include "bounded-line.h" + +P2trBoundedLine* +p2tr_bounded_line_new (const P2trVector2 *start, + const P2trVector2 *end) +{ + P2trBoundedLine* line = g_slice_new (P2trBoundedLine); + p2tr_bounded_line_init (line, start, end); + return line; +} + +void +p2tr_bounded_line_init (P2trBoundedLine *line, + const P2trVector2 *start, + const P2trVector2 *end) +{ + /* Traditional line Equation: + * y - mx - n = 0 <==> y = mx + n + * Slope Equation: + * m = dy / dx + * Slope + Traditional: + * dx * y - dy * x - dx * n = 0 + * And the remaining part can be found as + * dx * y0 - dy * x0 = dx * n + * So the final equation is: + * dx * y - dy * x - (dx * y0 - dy * x0) = 0 + */ + gdouble dx = end->x - start->x; + gdouble dy = end->y - start->y; + + gdouble dxXn = start->y * dx - start->x * dy; + + p2tr_line_init(&line->infinite, -dy, dx, -dxXn); + + p2tr_vector2_copy(&line->start, start); + p2tr_vector2_copy(&line->end, end); +} + +gboolean +p2tr_bounded_line_intersect (const P2trBoundedLine *l1, + const P2trBoundedLine *l2) +{ + return p2tr_line_different_sides (&l1->infinite, &l2->start, &l2->end) + && p2tr_line_different_sides (&l2->infinite, &l1->start, &l1->end); +} + +void +p2tr_bounded_line_free (P2trBoundedLine *line) +{ + g_slice_free (P2trBoundedLine, line); +} diff --git a/refine/bounded-line.h b/refine/bounded-line.h new file mode 100644 index 0000000..5e33eaf --- /dev/null +++ b/refine/bounded-line.h @@ -0,0 +1,26 @@ +#ifndef __P2TC_REFINE_BOUNDED_LINE_H__ +#define __P2TC_REFINE_BOUNDED_LINE_H__ + +#include +#include "vector2.h" +#include "line.h" + +typedef struct +{ + P2trLine infinite; + P2trVector2 start, end; +} P2trBoundedLine; + +P2trBoundedLine* p2tr_bounded_line_new (const P2trVector2 *start, + const P2trVector2 *end); + +void p2tr_bounded_line_init (P2trBoundedLine *line, + const P2trVector2 *start, + const P2trVector2 *end); + +gboolean p2tr_bounded_line_intersect (const P2trBoundedLine *l1, + const P2trBoundedLine *l2); + +void p2tr_bounded_line_free (P2trBoundedLine *line); + +#endif \ No newline at end of file diff --git a/refine/circle.c b/refine/circle.c new file mode 100644 index 0000000..ad6e1ab --- /dev/null +++ b/refine/circle.c @@ -0,0 +1,15 @@ +#include +#include "circle.h" + +gboolean +p2tr_circle_test_point_outside (P2trCircle *circle, + P2trVector2 *pt) +{ + gdouble dx = circle->center.x - pt->x; + gdouble dy = circle->center.y - pt->y; + + gdouble d_squared = dx * dx + dy * dy; + gdouble radius_squared = circle->radius * circle->radius; + + return d_squared > radius_squared; +} \ No newline at end of file diff --git a/refine/circle.h b/refine/circle.h new file mode 100644 index 0000000..02b1cc3 --- /dev/null +++ b/refine/circle.h @@ -0,0 +1,14 @@ +#ifndef __P2TC_REFINE_CIRCLE_H__ +#define __P2TC_REFINE_CIRCLE_H__ + +#include +#include "vector2.h" + +typedef struct { + P2trVector2 center; + gdouble radius; +} P2trCircle; + +gboolean p2tr_circle_test_point_outside (P2trCircle *circle, P2trVector2 *pt); + +#endif \ No newline at end of file diff --git a/refine/line.c b/refine/line.c new file mode 100644 index 0000000..4b0457f --- /dev/null +++ b/refine/line.c @@ -0,0 +1,70 @@ +#include +#include "line.h" + +void +p2tr_line_init (P2trLine *line, + gdouble a, + gdouble b, + gdouble c) +{ + line->a = a; + line->b = b; + line->c = c; +} + +gboolean +p2tr_line_different_sides (const P2trLine *line, + const P2trVector2 *pt1, + const P2trVector2 *pt2) +{ + gdouble side1 = line->a * pt1->x + line->b * pt1->y + line->c; + gdouble side2 = line->a * pt2->x + line->b * pt2->y + line->c; + + /* Signs are different if the product is negative */ + return side1 * side2 < 0; +} + +P2trLineRelation +p2tr_line_intersection (const P2trLine *l1, + const P2trLine *l2, + P2trVector2 *out_intersection) +{ + /* In order to find the intersection, we intend to solve + * the following set of equations: + * + * ( A1 B1 ) ( x ) = ( -C1 ) + * ( A2 B2 ) ( y ) = ( -C2 ) + * + * We can simplify the solution using Cramers Rule which + * gives the following results: + * + * x = (-C1 * B2) - (-C2 * B1) / (A1 * B2 - A2 * B1) + * y = (A1 * -C2) - (A2 * -C1) / (A1 * B2 - A2 * B1) + */ + double d = l1->a * l2->b - l2->a * l1->b; + + /* If the denominator in the result of applying Cramers rule + * is zero, then the lines have exactly the same slope, meaning + * they are either exactly the same or they are parallel and + * never intersect */ + if (d == 0) + { + /* We want to check if the offsets of boths the lines are the + * same, i.e. whether: C1 / A1 = C2 / A2 + * This test can be done without zero division errors if we do + * it in like this: C1 * A2 = C2 * A1 + */ + if (l1->c * l2->a == l1->a * l2->c) + return P2TR_LINE_RELATION_SAME; + else + return P2TR_LINE_RELATION_PARALLEL; + } + + if (out_intersection != NULL) + { + out_intersection->x = (-l1->c * l2->b + l2->c * l1->b) / d; + out_intersection->y = (l1->a * -l2->c + l2->a * l1->c) / d; + } + + return P2TR_LINE_RELATION_INTERSECTING; +} \ No newline at end of file diff --git a/refine/line.h b/refine/line.h new file mode 100644 index 0000000..c68e05f --- /dev/null +++ b/refine/line.h @@ -0,0 +1,34 @@ +#ifndef __P2TC_REFINE_LINE_H__ +#define __P2TC_REFINE_LINE_H__ + +#include +#include "vector2.h" + +/* A line is the equation of the following form: + * a * X + b * Y + c = 0 + */ +typedef struct { + gdouble a, b, c; +} P2trLine; + +typedef enum +{ + P2TR_LINE_RELATION_INTERSECTING = 0, + P2TR_LINE_RELATION_PARALLEL = 1, + P2TR_LINE_RELATION_SAME = 2 +} P2trLineRelation; + +void p2tr_line_init (P2trLine *line, + gdouble a, + gdouble b, + gdouble c); + +gboolean p2tr_line_different_sides (const P2trLine *line, + const P2trVector2 *pt1, + const P2trVector2 *pt2); + +P2trLineRelation p2tr_line_intersection (const P2trLine *l1, + const P2trLine *l2, + P2trVector2 *out_intersection); + +#endif \ No newline at end of file diff --git a/refine/vector2.c b/refine/vector2.c new file mode 100644 index 0000000..8a19e8d --- /dev/null +++ b/refine/vector2.c @@ -0,0 +1,43 @@ +#include +#include +#include "basic-geometry.h" + +gdouble +p2tr_vector2_dot (P2trVector2 *a, + P2trVector2 *b) +{ + return a->x * b->x + a->y * b->y; +} + +gboolean +p2tr_vector2_is_same (P2trVector2 *a, + P2trVector2 *b) +{ + if (a == NULL || b == NULL) + return ! ((a == NULL) ^ (b == NULL)); + else + return a->x == b->x && a->y == b->y; +} + +void +p2tr_vector2_sub (P2trVector2 *a, + P2trVector2 *b, + P2trVector2 *dest) +{ + dest->x = a->x - b->x; + dest->y = a->y - b->y; +} + +gdouble +p2tr_vector2_norm (P2trVector2 *v) +{ + return sqrt (v->x * v->x + v->y * v->y); +} + +void +p2tr_vector2_copy (P2trVector2 *dest, + P2trVector2 *src) +{ + dest->x = src->x; + dest->y = src->y; +} diff --git a/refine/vector2.h b/refine/vector2.h new file mode 100644 index 0000000..9d6a58c --- /dev/null +++ b/refine/vector2.h @@ -0,0 +1,17 @@ +#ifndef __P2TR_REFINE_VECTOR2_H__ +#define __P2TR_REFINE_VECTOR2_H__ + +#include + +typedef struct { + gdouble x; + gdouble y; +} P2trVector2; + +gdouble p2tr_vector2_dot (P2trVector2 *a, P2trVector2 *b); +gboolean p2tr_vector2_is_same (P2trVector2 *a, P2trVector2 *b); +void p2tr_vector2_sub (P2trVector2 *a, P2trVector2 *b, P2trVector2 *dest); +gdouble p2tr_vector2_norm (P2trVector2 *v); +void p2tr_vector2_copy (P2trVector2 *dest, P2trVector2 *src); + +#endif \ No newline at end of file