]> granicus.if.org Git - poly2tri-c/commitdiff
Add some basic geometric primitives
authorBarak Itkin <lightningismyname@gmail.com>
Fri, 20 Apr 2012 20:22:06 +0000 (23:22 +0300)
committerBarak Itkin <lightningismyname@gmail.com>
Fri, 20 Apr 2012 20:22:06 +0000 (23:22 +0300)
refine/bounded-line.c [new file with mode: 0644]
refine/bounded-line.h [new file with mode: 0644]
refine/circle.c [new file with mode: 0644]
refine/circle.h [new file with mode: 0644]
refine/line.c [new file with mode: 0644]
refine/line.h [new file with mode: 0644]
refine/vector2.c [new file with mode: 0644]
refine/vector2.h [new file with mode: 0644]

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