source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/AdvanceMath/Geometry2D/BoundingRectangle.cs @ 4507

Revision 4507, 24.3 KB checked in by anlakane, 6 years ago (diff)

Talletus.

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    [StructLayout(LayoutKind.Sequential, Size = BoundingRectangle.Size)]
38    [AdvBrowsableOrder("Min,Max")]
39#if !CompactFramework && !WindowsCE && !PocketPC && !XBOX360 && !SILVERLIGHT && !WINDOWS_PHONE
40    [Serializable]
41    [System.ComponentModel.TypeConverter(typeof(AdvTypeConverter<BoundingRectangle>))]
42#endif
43    public struct BoundingRectangle : IEquatable<BoundingRectangle>
44    {
45        public const int Size = Vector2D.Size * 2;
46
47        public static void Transform(ref Matrix2x3 matrix,ref BoundingRectangle rect, out BoundingRectangle result)
48        {
49            FromVectors(ref matrix, rect.Corners(), out result);
50        }
51
52        /// <summary>
53        /// Creates a new BoundingRectangle Instance from 2 Vector2Ds.
54        /// </summary>
55        /// <param name="first">the first Vector2D.</param>
56        /// <param name="second">the second Vector2D.</param>
57        /// <returns>a new BoundingRectangle</returns>
58        /// <remarks>The Max and Min values are automatically determined.</remarks>
59        public static BoundingRectangle FromVectors(Vector2D first, Vector2D second)
60        {
61            BoundingRectangle result;
62            if (first.X > second.X)
63            {
64                result.Max.X = first.X;
65                result.Min.X = second.X;
66            }
67            else
68            {
69                result.Max.X = second.X;
70                result.Min.X = first.X;
71            }
72            if (first.Y > second.Y)
73            {
74                result.Max.Y = first.Y;
75                result.Min.Y = second.Y;
76            }
77            else
78            {
79                result.Max.Y = second.Y;
80                result.Min.Y = first.Y;
81            }
82            return result;
83        }
84        public static void FromVectors(ref Vector2D first, ref  Vector2D second, out BoundingRectangle result)
85        {
86            if (first.X > second.X)
87            {
88                result.Max.X = first.X;
89                result.Min.X = second.X;
90            }
91            else
92            {
93                result.Max.X = second.X;
94                result.Min.X = first.X;
95            }
96            if (first.Y > second.Y)
97            {
98                result.Max.Y = first.Y;
99                result.Min.Y = second.Y;
100            }
101            else
102            {
103                result.Max.Y = second.Y;
104                result.Min.Y = first.Y;
105            }
106        }
107        /// <summary>
108        /// Creates a new BoundingRectangle Instance from multiple Vector2Ds.
109        /// </summary>
110        /// <param name="vectors">the list of vectors</param>
111        /// <returns>a new BoundingRectangle</returns>
112        /// <remarks>The Max and Min values are automatically determined.</remarks>
113        public static BoundingRectangle FromVectors(Vector2D[] vectors)
114        {
115            BoundingRectangle result;
116            FromVectors(vectors, out result);
117            return result;
118        }
119        public static void FromVectors(Vector2D[] vectors, out BoundingRectangle result)
120        {
121            if (vectors == null) { throw new ArgumentNullException("vectors"); }
122            if (vectors.Length == 0) { throw new ArgumentOutOfRangeException("vectors"); }
123            result.Max = vectors[0];
124            result.Min = vectors[0];
125            for (int index = 1; index < vectors.Length; ++index)
126            {
127                Vector2D current = vectors[index];
128                if (current.X > result.Max.X)
129                {
130                    result.Max.X = current.X;
131                }
132                else if (current.X < result.Min.X)
133                {
134                    result.Min.X = current.X;
135                }
136                if (current.Y > result.Max.Y)
137                {
138                    result.Max.Y = current.Y;
139                }
140                else if (current.Y < result.Min.Y)
141                {
142                    result.Min.Y = current.Y;
143                }
144            }
145        }
146        public static void FromVectors(ref Matrix3x3 matrix, Vector2D[] vectors, out BoundingRectangle result)
147        {
148            if (vectors == null) { throw new ArgumentNullException("vectors"); }
149            if (vectors.Length == 0) { throw new ArgumentOutOfRangeException("vectors"); }
150
151            Vector2D current;
152            Vector2D.Transform(ref matrix, ref vectors[0], out current);
153            result.Max = current;
154            result.Min = current;
155            for (int index = 1; index < vectors.Length; ++index)
156            {
157                Vector2D.Transform(ref matrix, ref vectors[index], out current);
158                if (current.X > result.Max.X)
159                {
160                    result.Max.X = current.X;
161                }
162                else if (current.X < result.Min.X)
163                {
164                    result.Min.X = current.X;
165                }
166                if (current.Y > result.Max.Y)
167                {
168                    result.Max.Y = current.Y;
169                }
170                else if (current.Y < result.Min.Y)
171                {
172                    result.Min.Y = current.Y;
173                }
174            }
175        }
176        public static void FromVectors(ref Matrix2x3 matrix, Vector2D[] vectors, out BoundingRectangle result)
177        {
178            if (vectors == null) { throw new ArgumentNullException("vectors"); }
179            if (vectors.Length == 0) { throw new ArgumentOutOfRangeException("vectors"); }
180
181            Vector2D current;
182            Vector2D.TransformNormal(ref matrix, ref vectors[0], out current);
183            result.Max = current;
184            result.Min = current;
185            for (int index = 1; index < vectors.Length; ++index)
186            {
187                Vector2D.TransformNormal(ref matrix, ref vectors[index], out current);
188                if (current.X > result.Max.X)
189                {
190                    result.Max.X = current.X;
191                }
192                else if (current.X < result.Min.X)
193                {
194                    result.Min.X = current.X;
195                }
196                if (current.Y > result.Max.Y)
197                {
198                    result.Max.Y = current.Y;
199                }
200                else if (current.Y < result.Min.Y)
201                {
202                    result.Min.Y = current.Y;
203                }
204            }
205            result.Max.X += matrix.m02;
206            result.Max.Y += matrix.m12;
207            result.Min.X += matrix.m02;
208            result.Min.Y += matrix.m12;
209        }
210        /// <summary>
211        /// Makes a BoundingRectangle that can contain the 2 BoundingRectangles passed.
212        /// </summary>
213        /// <param name="first">The First BoundingRectangle.</param>
214        /// <param name="second">The Second BoundingRectangle.</param>
215        /// <returns>The BoundingRectangle that can contain the 2 BoundingRectangles passed.</returns>
216        public static BoundingRectangle FromUnion(BoundingRectangle first, BoundingRectangle second)
217        {
218            BoundingRectangle result;
219            Vector2D.Max(ref first.Max, ref second.Max, out result.Max);
220            Vector2D.Min(ref first.Min, ref second.Min, out result.Min);
221            return result;
222        }
223        public static void FromUnion(ref BoundingRectangle first, ref BoundingRectangle second, out BoundingRectangle result)
224        {
225            Vector2D.Max(ref first.Max, ref second.Max, out result.Max);
226            Vector2D.Min(ref first.Min, ref second.Min, out result.Min);
227        }
228        /// <summary>
229        /// Makes a BoundingRectangle that contains the area where the BoundingRectangles Intersect.
230        /// </summary>
231        /// <param name="first">The First BoundingRectangle.</param>
232        /// <param name="second">The Second BoundingRectangle.</param>
233        /// <returns>The BoundingRectangle that can contain the 2 BoundingRectangles passed.</returns>
234        public static BoundingRectangle FromIntersection(BoundingRectangle first, BoundingRectangle second)
235        {
236            BoundingRectangle result;
237            Vector2D.Min(ref first.Max, ref second.Max, out result.Max);
238            Vector2D.Max(ref first.Min, ref second.Min, out result.Min);
239            return result;
240        }
241        public static void FromIntersection(ref BoundingRectangle first, ref BoundingRectangle second, out BoundingRectangle result)
242        {
243            Vector2D.Min(ref first.Max, ref second.Max, out result.Max);
244            Vector2D.Max(ref first.Min, ref second.Min, out result.Min);
245        }
246
247        public static BoundingRectangle FromCircle(BoundingCircle circle)
248        {
249            BoundingRectangle result;
250            FromCircle(ref circle, out result);
251            return result;
252        }
253        public static void FromCircle(ref BoundingCircle circle, out BoundingRectangle result)
254        {
255            result.Max.X = circle.Position.X + circle.Radius;
256            result.Max.Y = circle.Position.Y + circle.Radius;
257            result.Min.X = circle.Position.X - circle.Radius;
258            result.Min.Y = circle.Position.Y - circle.Radius;
259        }
260
261        public static BoundingRectangle FromCircle( Matrix2x3 matrix, Scalar radius)
262        {
263            BoundingRectangle result;
264            FromCircle(ref matrix, ref radius, out result);
265            return result;
266        }
267        public static void FromCircle(ref Matrix2x3 matrix, ref Scalar radius, out BoundingRectangle result)
268        {
269            Scalar xRadius = matrix.m01 * matrix.m01 + matrix.m00 * matrix.m00;
270            xRadius = ((xRadius == 1) ? (radius) : (radius * MathHelper.Sqrt(xRadius)));
271            Scalar yRadius = matrix.m10 * matrix.m10 + matrix.m11 * matrix.m11;
272            yRadius = ((yRadius == 1) ? (radius) : (radius * MathHelper.Sqrt(yRadius)));
273
274            result.Max.X = matrix.m02 + xRadius;
275            result.Min.X = matrix.m02 - xRadius;
276            result.Max.Y = matrix.m12 + yRadius;
277            result.Min.Y = matrix.m12 - yRadius;
278        }
279       
280       
281        [AdvBrowsable]
282        public Vector2D Max;
283        [AdvBrowsable]
284        public Vector2D Min;
285
286        /// <summary>
287        /// Creates a new BoundingRectangle Instance.
288        /// </summary>
289        /// <param name="minX">The Lower Bound on the XAxis.</param>
290        /// <param name="minY">The Lower Bound on the YAxis.</param>
291        /// <param name="maxX">The Upper Bound on the XAxis.</param>
292        /// <param name="maxY">The Upper Bound on the YAxis.</param>
293        public BoundingRectangle(Scalar minX, Scalar minY, Scalar maxX, Scalar maxY)
294        {
295            this.Max.X = maxX;
296            this.Max.Y = maxY;
297            this.Min.X = minX;
298            this.Min.Y = minY;
299        }
300        /// <summary>
301        /// Creates a new BoundingRectangle Instance from 2 Vector2Ds.
302        /// </summary>
303        /// <param name="min">The Lower Vector2D.</param>
304        /// <param name="max">The Upper Vector2D.</param>
305        [InstanceConstructor("Min,Max")]
306        public BoundingRectangle(Vector2D min, Vector2D max)
307        {
308            this.Max = max;
309            this.Min = min;
310        }
311
312        public Scalar Area
313        {
314            get
315            {
316                return (Max.X - Min.X) * (Max.Y - Min.Y);
317            }
318        }
319        public Scalar Perimeter
320        {
321            get
322            {
323                return ((Max.X - Min.X) + (Max.Y - Min.Y)) * 2;
324            }
325        }
326
327        public Vector2D[] Corners()
328        {
329            return new Vector2D[4]
330            {
331                Max,
332                new Vector2D(Min.X, Max.Y),
333                Min,
334                new Vector2D(Max.X, Min.Y),
335            };
336        }
337
338        public Scalar GetDistance(Vector2D point)
339        {
340            Scalar result;
341            GetDistance(ref point, out result);
342            return result;
343        }
344        public void GetDistance(ref Vector2D point, out Scalar result)
345        {
346            Scalar xDistance = Math.Abs(point.X - ((Max.X + Min.X) * .5f)) - (Max.X - Min.X) * .5f;
347            Scalar yDistance = Math.Abs(point.Y - ((Max.Y + Min.Y) * .5f)) - (Max.Y - Min.Y) * .5f;
348            if (xDistance > 0 && yDistance > 0)
349            {
350                result = MathHelper.Sqrt(xDistance * xDistance + yDistance * yDistance);
351            }
352            else
353            {
354                result = Math.Max(xDistance, yDistance);
355            }
356        }
357
358        public ContainmentType Contains(Vector2D point)
359        {
360            if (point.X <= Max.X &&
361                point.X >= Min.X &&
362                point.Y <= Max.Y &&
363                point.Y >= Min.Y)
364            {
365                return ContainmentType.Contains;
366            }
367            else
368            {
369                return ContainmentType.Disjoint;
370            }
371
372        }
373        public void Contains(ref Vector2D point, out ContainmentType result)
374        {
375            if (point.X <= Max.X &&
376                point.X >= Min.X &&
377                point.Y <= Max.Y &&
378                point.Y >= Min.Y)
379            {
380                result = ContainmentType.Contains;
381            }
382            else
383            {
384                result = ContainmentType.Disjoint;
385            }
386        }
387
388        public ContainmentType Contains(BoundingRectangle rect)
389        {
390            if (this.Min.X > rect.Max.X ||
391                this.Min.Y > rect.Max.Y ||
392                this.Max.X < rect.Min.X ||
393                this.Max.Y < rect.Min.Y)
394            {
395                return ContainmentType.Disjoint;
396            }
397            else if (
398                this.Min.X <= rect.Min.X &&
399                this.Min.Y <= rect.Min.Y &&
400                this.Max.X >= rect.Max.X &&
401                this.Max.Y >= rect.Max.Y)
402            {
403                return ContainmentType.Contains;
404            }
405            else
406            {
407                return ContainmentType.Intersects;
408            }
409        }
410        public void Contains(ref BoundingRectangle rect, out ContainmentType result)
411        {
412            if (this.Min.X > rect.Max.X ||
413                this.Min.Y > rect.Max.Y ||
414                this.Max.X < rect.Min.X ||
415                this.Max.Y < rect.Min.Y)
416            {
417                result = ContainmentType.Disjoint;
418            }
419            else if (
420                this.Min.X <= rect.Min.X &&
421                this.Min.Y <= rect.Min.Y &&
422                this.Max.X >= rect.Max.X &&
423                this.Max.Y >= rect.Max.Y)
424            {
425                result = ContainmentType.Contains;
426            }
427            else
428            {
429                result = ContainmentType.Intersects;
430            }
431        }
432
433        public ContainmentType Contains(BoundingCircle circle)
434        {
435             if ((circle.Position.X + circle.Radius) <= Max.X &&
436                 (circle.Position.X - circle.Radius) >= Min.X &&
437                 (circle.Position.Y + circle.Radius) <= Max.Y &&
438                 (circle.Position.Y - circle.Radius) >= Min.Y)
439            {
440                return ContainmentType.Contains;
441            }
442            else
443            {
444                bool intersects;
445                circle.Intersects(ref this, out intersects);
446                if (intersects)
447                {
448                    return ContainmentType.Intersects;
449                }
450                else
451                {
452                    return ContainmentType.Disjoint;
453                }
454            }
455        }
456        public void Contains(ref BoundingCircle circle, out ContainmentType result)
457        {
458            if ((circle.Position.X + circle.Radius) <= Max.X &&
459                (circle.Position.X - circle.Radius) >= Min.X &&
460                (circle.Position.Y + circle.Radius) <= Max.Y &&
461                (circle.Position.Y - circle.Radius) >= Min.Y)
462            {
463                result = ContainmentType.Contains;
464            }
465            else
466            {
467                bool intersects;
468                circle.Intersects(ref this, out intersects);
469                if (intersects)
470                {
471                    result = ContainmentType.Intersects;
472                }
473                else
474                {
475                    result = ContainmentType.Disjoint;
476                }
477            }
478        }
479
480        public ContainmentType Contains(BoundingPolygon polygon)
481        {
482            ContainmentType result;
483            Contains(ref polygon, out result);
484            return result;
485        }
486        public void Contains(ref BoundingPolygon polygon, out ContainmentType result)
487        {
488            if (polygon == null) { throw new ArgumentNullException("polygon"); }
489            Vector2D[] vertexes = polygon.Vertexes;
490            result = ContainmentType.Unknown;
491            for (int index = 0; index < vertexes.Length && result != ContainmentType.Intersects; ++index)
492            {
493                ContainmentType con;
494                Contains(ref vertexes[index], out con);
495                result |= con;
496            }
497            if (result == ContainmentType.Disjoint)
498            {
499                bool test;
500                polygon.Intersects(ref this, out test);
501                if (test)
502                {
503                    result = ContainmentType.Intersects;
504                }
505            }
506        }
507
508        public Scalar Intersects(Ray ray)
509        {
510            Scalar result;
511            Intersects(ref ray, out result);
512            return result;
513        }
514        public bool Intersects(BoundingRectangle rect)
515        {
516            return
517                this.Min.X < rect.Max.X &&
518                this.Max.X > rect.Min.X &&
519                this.Max.Y > rect.Min.Y &&
520                this.Min.Y < rect.Max.Y;
521        }
522        public bool Intersects(BoundingCircle circle)
523        {
524            bool result;
525            circle.Intersects(ref this, out result);
526            return result;
527        }
528        public bool Intersects(Line line)
529        {
530            bool result;
531            line.Intersects(ref this, out result);
532            return result;
533        }
534        public bool Intersects(BoundingPolygon polygon)
535        {
536            if (polygon == null) { throw new ArgumentNullException("polygon"); }
537            bool result;
538            polygon.Intersects(ref this, out result);
539            return result;
540        }
541
542        public void Intersects(ref Ray ray, out Scalar result)
543        {
544
545            if (Contains(ray.Origin)== ContainmentType.Contains)
546            {
547                result = 0;
548                return;
549            }
550            Scalar distance;
551            Scalar intersectValue;
552            result = -1;
553            if (ray.Origin.X < Min.X && ray.Direction.X > 0)
554            {
555                distance = (Min.X - ray.Origin.X) / ray.Direction.X;
556                if (distance > 0)
557                {
558                    intersectValue = ray.Origin.Y + ray.Direction.Y * distance;
559                    if (intersectValue >= Min.Y && intersectValue <= Max.Y &&
560                        (result == -1 || distance < result))
561                    {
562                        result = distance;
563                    }
564                }
565            }
566            if (ray.Origin.X > Max.X && ray.Direction.X < 0)
567            {
568                distance = (Max.X - ray.Origin.X) / ray.Direction.X;
569                if (distance > 0)
570                {
571                    intersectValue = ray.Origin.Y + ray.Direction.Y * distance;
572                    if (intersectValue >= Min.Y && intersectValue <= Max.Y &&
573                        (result == -1 || distance < result))
574                    {
575                        result = distance;
576                    }
577                }
578            }
579            if (ray.Origin.Y < Min.Y && ray.Direction.Y > 0)
580            {
581                distance = (Min.Y - ray.Origin.Y) / ray.Direction.Y;
582                if (distance > 0)
583                {
584                    intersectValue = ray.Origin.X + ray.Direction.X * distance;
585                    if (intersectValue >= Min.X && intersectValue <= Max.X &&
586                        (result == -1 || distance < result))
587                    {
588                        result = distance;
589                    }
590                }
591            }
592            if (ray.Origin.Y > Max.Y && ray.Direction.Y < 0)
593            {
594                distance = (Max.Y - ray.Origin.Y) / ray.Direction.Y;
595                if (distance > 0)
596                {
597                    intersectValue = ray.Origin.X + ray.Direction.X * distance;
598                    if (intersectValue >= Min.X && intersectValue <= Max.X &&
599                        (result == -1 || distance < result))
600                    {
601                        result = distance;
602                    }
603                }
604            }
605        }
606        public void Intersects(ref BoundingRectangle rect, out bool result)
607        {
608            result =
609                this.Min.X <= rect.Max.X &&
610                this.Max.X >= rect.Min.X &&
611                this.Max.Y >= rect.Min.Y &&
612                this.Min.Y <= rect.Max.Y;
613        }
614        public void Intersects(ref BoundingCircle circle, out bool result)
615        {
616            circle.Intersects(ref this, out result);
617        }
618        public void Intersects(ref BoundingPolygon polygon, out bool result)
619        {
620            if (polygon == null) { throw new ArgumentNullException("polygon"); }
621            polygon.Intersects(ref this, out result);
622        }
623        public void Intersects(ref Line line, out bool result)
624        {
625            line.Intersects(ref this, out result);
626        }
627
628        public override string ToString()
629        {
630            return string.Format("{0} < {1}", Min, Max);
631        }
632
633        public override bool Equals(object obj)
634        {
635            return obj is BoundingRectangle && Equals((BoundingRectangle)obj);
636        }
637        public bool Equals(BoundingRectangle other)
638        {
639            return Equals(ref this, ref other);
640        }
641        public static bool Equals(BoundingRectangle rect1, BoundingRectangle rect2)
642        {
643            return Equals(ref rect1, ref rect2);
644        }
645        [CLSCompliant(false)]
646        public static bool Equals(ref BoundingRectangle rect1, ref BoundingRectangle rect2)
647        {
648            return Vector2D.Equals(ref rect1.Min, ref rect2.Min) && Vector2D.Equals(ref rect1.Max, ref rect2.Max);
649        }
650        public override int GetHashCode()
651        {
652            return Min.GetHashCode() ^ Max.GetHashCode();
653        }
654        public static bool operator ==(BoundingRectangle rect1, BoundingRectangle rect2)
655        {
656            return Equals(ref rect1, ref rect2);
657        }
658        public static bool operator !=(BoundingRectangle rect1, BoundingRectangle rect2)
659        {
660            return !Equals(ref rect1, ref rect2);
661        }
662    }
663}
Note: See TracBrowser for help on using the repository browser.