1 /* Copyright Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file Circle.cpp
16         @author Jukka Jyl�nki
17         @brief Implementation for the Circle geometry object. */
18 #include "Circle.h"
19 #include "Plane.h"
20 #include "../Math/MathFunc.h"
21 #include "../Math/float2.h"
22 #include "../Math/float3x3.h"
23 #include "../Math/float3x4.h"
24 #include "../Math/float4x4.h"
25 #include "../Math/Quat.h"
26 #include "Ray.h"
27 #include "AABB.h"
28 #include "OBB.h"
29 #include "LineSegment.h"
30 #include "Line.h"
31
32 #ifdef MATH_ENABLE_STL_SUPPORT
33 #include <iostream>
34 #endif
35
36 MATH_BEGIN_NAMESPACE
37
38 Circle::Circle(const vec &center, const vec &n, float radius)
39 :pos(center),
40 normal(n),
41 r(radius)
42 {
43 }
44
45 vec Circle::BasisU() const
46 {
47         return normal.Perpendicular();
48 }
49
50 vec Circle::BasisV() const
51 {
52         return normal.AnotherPerpendicular();
53 }
54
55 vec Circle::GetPoint(float angleRadians) const
56 {
57         float sin, cos;
58         SinCos(angleRadians, sin, cos);
59         return pos + r * (sin * BasisU() + cos * BasisV());
60 }
61
62 vec Circle::GetPoint(float angleRadians, float d) const
63 {
64         float sin, cos;
65         SinCos(angleRadians, sin, cos);
66         return pos + r * d * (cos * BasisU() + sin * BasisV());
67 }
68
69 vec Circle::ExtremePoint(const vec &direction) const
70 {
71         vec d = direction - direction.ProjectToNorm(normal);
72         if (d.IsZero())
73                 return pos;
74         else
75                 return pos + d.ScaledToLength(r);
76 }
77
78 Plane Circle::ContainingPlane() const
79 {
80         return Plane(posnormal);
81 }
82
83 void Circle::Translate(const vec &offset)
84 {
85         pos += offset;
86 }
87
88 void Circle::Transform(const float3x3 &transform)
89 {
90         assume(transform.HasUniformScale());
91         assume(transform.IsColOrthogonal());
92         pos = transform.Mul(pos);
93         normal = transform.Mul(normal).Normalized();
94         r *= transform.Col(0).Length(); // Scale the radius of the circle.
95 }
96
97 void Circle::Transform(const float3x4 &transform)
98 {
99         assume(transform.HasUniformScale());
100         assume(transform.IsColOrthogonal());
101         pos = transform.MulPos(pos);
102         normal = transform.MulDir(normal).Normalized();
103         r *= transform.Col(0).Length(); // Scale the radius of the circle.
104 }
105
106 void Circle::Transform(const float4x4 &transform)
107 {
108         assume(transform.HasUniformScale());
109         assume(transform.IsColOrthogonal3());
110         pos = transform.MulPos(pos);
111         normal = transform.MulDir(normal).Normalized();
112         r *= transform.Col3(0).Length(); // Scale the radius of the circle.
113 }
114
115 void Circle::Transform(const Quat &transform)
116 {
117         pos = transform.Mul(pos);
118         normal = transform.Mul(normal);
119 }
120
121 bool Circle::EdgeContains(const vec &point, float maxDistance) const
122 {
123         return DistanceToEdge(point) <= maxDistance;
124 }
125 /*
126 bool Circle::DiscContains(const vec &point, float maxDistance) const
127 {
128         return DistanceToDisc(point) <= maxDistance;
129 }
130
131 */
132 float Circle::DistanceToEdge(const vec &point) const
133 {
134         return ClosestPointToEdge(point).Distance(point);
135 }
136 /*
137 float Circle::DistanceToEdge(const Ray &ray, float *d, vec *closestPoint) const
138 {
139         float t;
140         vec cp = ClosestPointToEdge(ray, &t);
141         if (closestPoint)
142                 *closestPoint = cp;
143         if (d)
144                 *d = t;
145         return cp.Distance(ray.GetPoint(t));
146 }
147
148 float Circle::DistanceToEdge(const LineSegment &lineSegment, float *d, vec *closestPoint) const
149 {
150         float t;
151         vec cp = ClosestPointToEdge(lineSegment, &t);
152         if (closestPoint)
153                 *closestPoint = cp;
154         if (d)
155                 *d = t;
156         return cp.Distance(lineSegment.GetPoint(t));
157 }
158
159 float Circle::DistanceToEdge(const Line &line, float *d, vec *closestPoint) const
160 {
161         float t;
162         vec cp = ClosestPointToEdge(line, &t);
163         if (closestPoint)
164                 *closestPoint = cp;
165         if (d)
166                 *d = t;
167         return cp.Distance(line.GetPoint(t));
168 }
169 */
170 float Circle::DistanceToDisc(const vec &point) const
171 {
172         return ClosestPointToDisc(point).Distance(point);
173 }
174
175 vec Circle::ClosestPointToEdge(const vec &point) const
176 {
177         vec pointOnPlane = ContainingPlane().Project(point);
178         vec diff = pointOnPlane - pos;
179         if (diff.IsZero())
180                 return GetPoint(0); // The point is in the center of the circle, all points are equally close.
181         return pos + diff.ScaledToLength(r);
182 }
183
184 vec Circle::ClosestPointToDisc(const vec &point) const
185 {
186         vec pointOnPlane = ContainingPlane().Project(point);
187         vec diff = pointOnPlane - pos;
188         float dist = diff.LengthSq();
189         if (dist > r*r)
190                 diff = diff * (r / Sqrt(dist));
191
192         return pos + diff;
193 }
194
195 int Circle::Intersects(const Plane &plane, vec *pt1, vec *pt2) const
196 {
197         return plane.Intersects(*this, pt1, pt2);
198 }
199
200 int Circle::Intersects(const Plane &plane) const
201 {
202         return plane.Intersects(*this);
203 }
204
205 bool Circle::IntersectsDisc(const Line &line) const
206 {
207         float d;
208         bool intersectsPlane = line.Intersects(ContainingPlane(), &d);
209         if (intersectsPlane)
210                 return false;
211         return line.GetPoint(d).DistanceSq(pos) <= r*r;
212 }
213
214 bool Circle::IntersectsDisc(const LineSegment &lineSegment) const
215 {
216         float d;
217         bool intersectsPlane = lineSegment.Intersects(ContainingPlane(), &d);
218         if (intersectsPlane)
219                 return false;
220         return lineSegment.GetPoint(d).DistanceSq(pos) <= r*r;
221 }
222
223 bool Circle::IntersectsDisc(const Ray &ray) const
224 {
225         float d;
226         bool intersectsPlane = ray.Intersects(ContainingPlane(), &d);
227         if (intersectsPlane)
228                 return false;
229         return ray.GetPoint(d).DistanceSq(pos) <= r*r;
230 }
231
232 #ifdef MATH_ENABLE_STL_SUPPORT
233 VecArray Circle::IntersectsFaces(const AABB &aabb) const
234 {
235     return IntersectsFaces(aabb.ToOBB());
236 }
237
238 VecArray Circle::IntersectsFaces(const OBB &obb) const
239 {
240         VecArray intersectionPoints;
241         for(int i = 0; i < 6; ++i)
242         {               
243                 Plane p = obb.FacePlane(i);
244                 vec pt1, pt2;
245                 int numIntersections = Intersects(p, &pt1, &pt2);
246                 if (numIntersections >= 1 && obb.Contains(pt1))
247                         intersectionPoints.push_back(pt1);
248                 if (numIntersections >= 2 && obb.Contains(pt2))
249                         intersectionPoints.push_back(pt2);
250         }
251         return intersectionPoints;
252 }
253
254 std::string Circle::ToString() const
255 {
256         char str[256];
257         sprintf(str, "Circle(pos:(%.2f, %.2f, %.2f) normal:(%.2f, %.2f, %.2f), r:%.2f)",
258                 pos.x, pos.y, pos.z, normal.xnormal.ynormal.zr);
259         return str;
260 }
261
262 std::ostream &operator <<(std::ostream &o, const Circle &circle)
263 {
264         o << circle.ToString();
265         return o;
266 }
267
268 #endif
269
270 Circle operator *(const float3x3 &transform, const Circle &circle)
271 {
272         Circle c(circle);
273         c.Transform(transform);
274         return c;
275 }
276
277 Circle operator *(const float3x4 &transform, const Circle &circle)
278 {
279         Circle c(circle);
280         c.Transform(transform);
281         return c;
282 }
283
284 Circle operator *(const float4x4 &transform, const Circle &circle)
285 {
286         Circle c(circle);
287         c.Transform(transform);
288         return c;
289 }
290
291 Circle operator *(const Quat &transform, const Circle &circle)
292 {
293         Circle c(circle);
294         c.Transform(transform);
295         return c;
296 }
297
298 MATH_END_NAMESPACE

Go back to previous page