libnxter  0.1
Circle.nxc
Go to the documentation of this file.
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  Circle.nxc
4  Copyright (C) 2008 Naba Kumar <naba@gnome.org>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 
25 #ifndef _CIRCLE_H_
26 #define _CIRCLE_H_
27 
28 #include "Debug.nxc"
29 #include "Vector.nxc"
30 
31 struct Circle
32 {
33  Vector center;
34  long radius;
35 };
36 
45 bool CircleIntersectCircle(Vector &circleACenter, long circleARadius,
46  Vector &circleBCenter, long circleBRadius,
47  Vector &retIntersect1, Vector &retIntersect2)
48 {
49  long d, a, h;
50  Vector M;
51 
52  /* Distance between the two centers */
53  d = VectorGetDistanceVec(circleACenter, circleBCenter);
54 
55  if ((circleARadius + circleBRadius) < d)
56  {
57  return false; /* No intersection possible */
58  }
59  if (d == 0)
60  {
61  return false; /* Circles overlap. No unique solutions */
62  }
63 
64  /* Distance between the center of first circle from the mid point of
65  * intersections.
66  */
67  a = (circleARadius * circleARadius - circleBRadius * circleBRadius + d * d)/(2 * d);
68 
69  /* Perpendicular height of intersection points from the line joining
70  * the two centers of the circles.
71  */
72  h = circleARadius * circleARadius - a * a;
73  h = Sqrt(h);
74 
75  /* Mid point of intersections: M = Ca + a(Cb - Ca)/d */
76  M = circleBCenter;
77  VectorSubtract(M, circleACenter);
78  VectorScale(M, a);
79  VectorReduce(M, d);
80  VectorAdd(M, circleACenter);
81 
82  retIntersect1.x = M.x + (h * (circleBCenter.y - circleACenter.y))/d;
83  retIntersect1.y = M.y - (h * (circleBCenter.x - circleACenter.x))/d;
84  retIntersect2.x = M.x - (h * (circleBCenter.y - circleACenter.y))/d;
85  retIntersect2.y = M.y + (h * (circleBCenter.x - circleACenter.x))/d;
86  return true;
87 }
88 
99 bool CircleIntersectLine(Vector &circle, long radius,
100  Vector &pointA, Vector &pointB,
101  Vector &retIntersect1, Vector &retIntersect2)
102 {
103  long a, b, c, u1, u2, t, distance;
104  Vector A, B, T;
105 
106  A = pointA;
107  B = pointB;
108 
109  /* A long line will overlow the maths below, so trim the line segment */
110  while (VectorGetDistanceVec(A, B) > 500)
111  {
112  VectorSubtract(B, A);
113  VectorReduce(B, 2);
114  VectorAdd(B, A);
115  }
116 
117  /* Eqt: a = (x2 - x1)^2 + (y2 - y1)^2 */
118  a = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
119  // NumOut(0, LCD_LINE1, a, true);
120 
121  /* Eqt: b = 2[(x2 - x1)(x1 - x3) + (y2 - y1)(y1 - y3)] */
122  b = 2 * ((B.x - A.x) * (A.x - circle.x) + (B.y - A.y) * (A.y - circle.y));
123  // NumOut(0, LCD_LINE2, b, false);
124 
125  /* Eqt: c = x3^2 + y3^2 + x1^2 + y1^2 - 2(x3 * x1 + y3 * y1) - r2 */
126  c = circle.x * circle.x + circle.y * circle.y + A.x * A.x + A.y * A.y -
127  2 * (circle.x * A.x + circle.y * A.y) - radius * radius;
128  // NumOut(0, LCD_LINE3, c, false);
129 
130  /* FIXME: t can easily overflow */
131  /* Eqt: u = (-b +/- sqrt(b^2 - 4 * a * c((2 * a) */
132  t = b * b - 4 * a * c;
133 
134  // NumOut(0, LCD_LINE4, t, false); Wait(2000);
135 
136  if (t < 0) /* Line does not intersect */
137  {
138  return false;
139  }
140  else if (t == 0) /* Only one intersection point */
141  {
142  u1 = -b * 1000 / (2 * a);
143  u2 = u1;
144  }
145  else /* Two intersection points. Solve u proper */
146  {
147  long s = Sqrt(t);
148  u1 = (-b + s) * 1000 / (2 * a);
149  u2 = (-b - s) * 1000 / (2 * a);
150  }
151 
152  retIntersect1.x = A.x + u1 * (B.x - A.x) / 1000;
153  retIntersect1.y = A.y + u1 * (B.y - A.y) / 1000;
154  retIntersect2.x = A.x + u2 * (B.x - A.x) / 1000;
155  retIntersect2.y = A.y + u2 * (B.y - A.y) / 1000;
156  return true;
157 }
158 
159 #ifdef ENABLE_TEST
160 void TestCircle()
161 {
162  Vector circle, p1, p2, intersect1, intersect2;
163  bool success;
164 
165  VectorInit(circle, -50, -50, 0);
166  VectorInit(p1, 0, 0, 0);
167  VectorInit(p2, -100, -100, 0);
168 
169  success = CircleIntersectLine(circle, 50, p1, p2, intersect1, intersect2);
170  TEST((success == true), "Intersection");
171 
172  //VectorPrint(intersect1, "Intersect1", 2000);
173  //VectorPrint(intersect2, "Intersect2", 2000);
174 
175  TEST((intersect1.x == -85), "intersect1.x");
176  TEST((intersect1.y == -85), "intersect1.y");
177  TEST((intersect2.x == -14), "intersect2.x");
178  TEST((intersect2.y == -14), "intersect2.y");
179 
180  VectorInit(circle, 0, 0, 0);
181  VectorInit(p1, 0, 0, 0);
182  VectorInit(p2, 1000, 0, 0);
183 
184  success = CircleIntersectLine(circle, 30, p1, p2, intersect1, intersect2);
185  TEST((success == true), "Intersection 2");
186 
187  //VectorPrint(intersect1, "Intersect1a", 2000);
188  //VectorPrint(intersect2, "Intersect2a", 2000);
189 
190  TEST((intersect1.x == 30), "intersect1.x");
191  TEST((intersect1.y == 0), "intersect1.y");
192  TEST((intersect2.x == -30), "intersect2.x");
193  TEST((intersect2.y == 0), "intersect2.y");
194 }
195 #endif /* ENABLE_TEST */
196 #endif /* __CIRCLE_H_ */
197 
bool CircleIntersectLine(Vector &circle, long radius, Vector &pointA, Vector &pointB, Vector &retIntersect1, Vector &retIntersect2)
Determins the 2 points of intersection of a circle and a line given by two vector points...
Definition: Circle.nxc:99
A vector that represents a 2D point by x-y coordinates and a direction angle.
Definition: Vector.nxc:43
long VectorGetDistanceVec(Vector &a, Vector &b)
Gets the distance between given two vectors.
Definition: Vector.nxc:100
void VectorReduce(Vector &a, long S)
Reduces x and y vector components by the given factor. i.e. a = a / S.
Definition: Vector.nxc:201
Debugging utility macros.
A simple 3-components vector implementation (2D point + direction)
void VectorSubtract(Vector &a, Vector &b)
Subtracts vector b from a. i.e. a -= b.
Definition: Vector.nxc:182
long y
Definition: Vector.nxc:46
long x
Definition: Vector.nxc:45
void VectorScale(Vector &a, long S)
Scales x and y vector components by the given factor. i.e. a = a * S.
Definition: Vector.nxc:192
bool CircleIntersectCircle(Vector &circleACenter, long circleARadius, Vector &circleBCenter, long circleBRadius, Vector &retIntersect1, Vector &retIntersect2)
Determins the 2 points of intersection of two overlapping circles.
Definition: Circle.nxc:45
void VectorAdd(Vector &a, Vector &b)
Adds vector b to a. i.e. a += b.
Definition: Vector.nxc:172
void VectorInit(Vector &a, long x, long y, long theta)
Initializes the vector with given x, y and theta components.
Definition: Vector.nxc:122