source: 2014/24/EemeliK/Zombieland/Jypeli/AdvanceMath/Geometry2D/BoundingCircle.cs @ 5974

Revision 5974, 13.2 KB checked in by empaheik, 4 years ago (diff)
Line 
1#region MIT License
2/*
3 * Copyright (c) 2005-2008 Jonathan Mark Porter. http://physics2d.googlepages.com/
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#endregion
23
24
25
26
27#if UseDouble
28using Scalar = System.Double;
29#else
30using Scalar = System.Single;
31#endif
32using System;
33using System.Runtime.InteropServices;
34using AdvanceMath.Design;
35namespace AdvanceMath.Geometry2D
36{
37
38    [StructLayout(LayoutKind.Sequential, Size = BoundingCircle.Size)]
39    [AdvBrowsableOrder("Position,Radius")]
40#if !CompactFramework && !WindowsCE && !PocketPC && !XBOX360 && !SILVERLIGHT && !WINDOWS_PHONE
41    [Serializable]
42    [System.ComponentModel.TypeConverter(typeof(AdvTypeConverter<BoundingCircle>))]
43#endif
44    public struct BoundingCircle : IEquatable<BoundingCircle>
45    {
46        public const int Size = Vector2D.Size + sizeof(Scalar);
47
48        public static BoundingCircle FromRectangle(BoundingRectangle rect)
49        {
50            BoundingCircle result;
51            FromRectangle(ref rect, out result);
52            return result;
53        }
54        public static void FromRectangle(ref BoundingRectangle rect, out BoundingCircle result)
55        {
56            result.Position.X = (rect.Min.X + rect.Max.X) * .5f;
57            result.Position.Y = (rect.Min.Y + rect.Max.Y) * .5f;
58            Scalar xRadius = (rect.Max.X - rect.Min.X) * .5f;
59            Scalar yRadius = (rect.Max.Y - rect.Min.Y) * .5f;
60            result.Radius = MathHelper.Sqrt(xRadius * xRadius + yRadius * yRadius);
61        }
62        public static BoundingCircle FromVectors(Vector2D[] vertexes)
63        {
64            BoundingCircle result;
65            FromVectors(vertexes, out result);
66            return result;
67        }
68        public static void FromVectors(Vector2D[] vertexes, out BoundingCircle result)
69        {
70            BoundingPolygon.GetCentroid(vertexes, out result.Position);
71            result.Radius = -1;
72            for (int index = 0; index < vertexes.Length; ++index)
73            {
74                Scalar distSq;
75                Vector2D.DistanceSq(ref result.Position, ref vertexes[index], out distSq);
76                if (result.Radius == -1 || (distSq < result.Radius))
77                {
78                    result.Radius = distSq;
79                }
80            }
81            result.Radius = MathHelper.Sqrt(result.Radius);
82        }
83
84        [AdvBrowsable]
85        public Vector2D Position;
86        [AdvBrowsable]
87        public Scalar Radius;
88        [InstanceConstructor("Position,Radius")]
89        public BoundingCircle(Vector2D position, Scalar radius)
90        {
91            this.Position = position;
92            this.Radius = radius;
93        }
94        public BoundingCircle(Scalar x, Scalar y, Scalar radius)
95        {
96            this.Position.X = x;
97            this.Position.Y = y;
98            this.Radius = radius;
99        }
100
101        public Scalar Area
102        {
103            get
104            {
105                return MathHelper.Pi * Radius * Radius;
106            }
107        }
108        public Scalar Perimeter
109        {
110            get
111            {
112                return MathHelper.TwoPi * Radius;
113            }
114        }
115
116        public Scalar GetDistance(Vector2D point)
117        {
118            Scalar result;
119            GetDistance(ref point, out result);
120            return result;
121        }
122        public void GetDistance(ref Vector2D point, out Scalar result)
123        {
124            Vector2D diff;
125            Vector2D.Subtract(ref point, ref Position, out diff);
126            Vector2D.GetMagnitude(ref  diff, out result);
127            result -= Radius;
128        }
129
130        public ContainmentType Contains(Vector2D point)
131        {
132            Scalar distance;
133            GetDistance(ref point, out distance);
134            return ((distance <= 0) ? (ContainmentType.Contains) : (ContainmentType.Disjoint));
135        }
136        public void Contains(ref Vector2D point, out ContainmentType result)
137        {
138            Scalar distance;
139            GetDistance(ref point, out distance);
140            result = ((distance <= 0) ? (ContainmentType.Contains) : (ContainmentType.Disjoint));
141        }
142
143        public ContainmentType Contains(BoundingCircle circle)
144        {
145            Scalar distance;
146            GetDistance(ref circle.Position, out distance);
147            if (-distance >= circle.Radius)
148            {
149                return ContainmentType.Contains;
150            }
151            else if (distance > circle.Radius)
152            {
153                return ContainmentType.Disjoint;
154            }
155            else
156            {
157                return ContainmentType.Intersects;
158            }
159        }
160        public void Contains(ref BoundingCircle circle, out ContainmentType result)
161        {
162            Scalar distance;
163            GetDistance(ref circle.Position, out distance);
164            if (-distance >= circle.Radius)
165            {
166                result = ContainmentType.Contains;
167            }
168            else if (distance > circle.Radius)
169            {
170                result = ContainmentType.Disjoint;
171            }
172            else
173            {
174                result = ContainmentType.Intersects;
175            }
176        }
177
178        public ContainmentType Contains(BoundingRectangle rect)
179        {
180            ContainmentType result;
181            Contains(ref rect, out result);
182            return result;
183        }
184        public void Contains(ref BoundingRectangle rect, out ContainmentType result)
185        {
186            Scalar mag;
187            Vector2D maxDistance,minDistance;
188            MathHelper.Sort(rect.Max.X - Position.X, Position.X - rect.Min.X, out maxDistance.X,out minDistance.X);
189            MathHelper.Sort(rect.Max.Y - Position.Y, Position.Y - rect.Min.Y, out maxDistance.Y,out minDistance.Y);
190            Vector2D.GetMagnitude(ref maxDistance, out mag);
191            if (mag <= Radius)
192            {
193                result = ContainmentType.Contains;
194            }
195            else 
196            {
197                Vector2D.GetMagnitude(ref minDistance, out mag);
198                if (mag <= Radius)
199                {
200                    result = ContainmentType.Intersects;
201                }
202                else
203                {
204                    result = ContainmentType.Disjoint;
205                }
206            }
207        }
208
209        public ContainmentType Contains(BoundingPolygon polygon)
210        {
211            ContainmentType result;
212            Contains(ref polygon, out result);
213            return result;
214        }
215        public void Contains(ref BoundingPolygon polygon, out ContainmentType result)
216        {
217            if (polygon == null) { throw new ArgumentNullException("polygon"); }
218            Vector2D[] vertexes = polygon.Vertexes;
219            result = ContainmentType.Unknown;
220            for (int index = 0; index < vertexes.Length && result != ContainmentType.Intersects; ++index)
221            {
222                ContainmentType con;
223                Contains(ref vertexes[index], out con);
224                result |= con;
225            }
226            if (result == ContainmentType.Disjoint)
227            {
228                bool test;
229                polygon.Intersects(ref this, out test);
230                if (test)
231                {
232                    result = ContainmentType.Intersects;
233                }
234            }
235        }
236
237        public Scalar Intersects(Ray ray)
238        {
239            Scalar result;
240            Intersects(ref ray, true, out result);
241            return result;
242        }
243        public bool Intersects(BoundingRectangle rect)
244        {
245            bool result;
246            Intersects(ref rect, out result);
247            return result;
248        }
249        public bool Intersects(BoundingCircle circle)
250        {
251            bool result;
252            Intersects(ref circle, out result);
253            return result;
254        }
255        public bool Intersects(BoundingPolygon polygon)
256        {
257            bool result;
258            polygon.Intersects(ref this, out result);
259            return result;
260        }
261        public bool Intersects(LineSegment line)
262        {
263            bool result;
264            Intersects(ref line, out result);
265            return result;
266        }
267        public bool Intersects(Line line)
268        {
269            bool result;
270            Intersects(ref line, out result);
271            return result;
272        }
273
274        public void Intersects(ref Ray ray, out Scalar result)
275        {
276            Intersects(ref ray, true, out result);
277        }
278        public void Intersects(ref Ray ray, bool discardInside, out Scalar result)
279        {
280            Vector2D rayOriginRelativeToCircle2D;
281            Vector2D.Subtract(ref ray.Origin, ref Position, out rayOriginRelativeToCircle2D);
282            Scalar radiusSq = this.Radius * this.Radius;
283            Scalar MagSq = rayOriginRelativeToCircle2D.MagnitudeSq;
284
285            if ((MagSq <= radiusSq) && !discardInside)
286            {
287                result = 0;
288                return;
289            }
290            Scalar a = ray.Direction.MagnitudeSq;
291            Scalar b = 2 * rayOriginRelativeToCircle2D * ray.Direction;
292            Scalar c = MagSq - radiusSq;
293            Scalar minus;
294            Scalar plus;
295            if (MathHelper.TrySolveQuadratic(a, b, c, out plus, out minus))
296            {
297                if (minus < 0)
298                {
299                    if (plus > 0)
300                    {
301                        result = plus;
302                        return;
303                    }
304                }
305                else
306                {
307                    result = minus;
308                    return;
309                }
310            }
311            result = -1;
312        }
313        public void Intersects(ref LineSegment line, out bool result)
314        {
315            Scalar distance;
316            line.GetDistance(ref Position, out distance);
317            result = Math.Abs(distance) <= Radius;
318        }
319        public void Intersects(ref Line line, out bool result)
320        {
321            Scalar distance;
322            Vector2D.Dot(ref line.Normal, ref Position, out distance);
323            result = (distance + line.D) <= Radius;
324        }
325        public void Intersects(ref BoundingRectangle rect, out bool result)
326        {
327            Vector2D proj;
328            Vector2D.Clamp(ref Position,ref rect.Min,ref rect.Max, out proj);
329            Scalar distSq;
330            Vector2D.DistanceSq(ref Position, ref proj, out distSq);
331            result = distSq <= Radius * Radius;
332        }
333        public void Intersects(ref BoundingCircle circle, out bool result)
334        {
335            Scalar distSq;
336            Vector2D.DistanceSq(ref Position, ref circle.Position, out distSq);
337            result = distSq <= (Radius * Radius + circle.Radius * circle.Radius);
338        }
339        public void Intersects(ref BoundingPolygon polygon, out bool result)
340        {
341            polygon.Intersects(ref this, out result);
342        }
343
344
345
346        public override string ToString()
347        {
348            return string.Format("P: {0} R: {1}", Position, Radius);
349        }
350        public override int GetHashCode()
351        {
352            return Position.GetHashCode() ^ Radius.GetHashCode();
353        }
354        public override bool Equals(object obj)
355        {
356            return obj is BoundingCircle && Equals((BoundingCircle)obj);
357        }
358        public bool Equals(BoundingCircle other)
359        {
360            return Equals(ref this, ref other);
361        }
362        public static bool Equals(BoundingCircle circle1, BoundingCircle circle2)
363        {
364            return Equals(ref circle1, ref circle2);
365        }
366        [CLSCompliant(false)]
367        public static bool Equals(ref BoundingCircle circle1, ref BoundingCircle circle2)
368        {
369            return Vector2D.Equals(ref circle1.Position, ref circle2.Position) && circle1.Radius == circle2.Radius;
370        }
371        public static bool operator ==(BoundingCircle circle1, BoundingCircle circle2)
372        {
373            return Equals(ref circle1, ref circle2);
374        }
375        public static bool operator !=(BoundingCircle circle1, BoundingCircle circle2)
376        {
377            return !Equals(ref circle1, ref circle2);
378        }
379    }
380}
Note: See TracBrowser for help on using the repository browser.