source: 2014/24/EemeliK/Zombieland/Jypeli/Physics2DDotNet/Shapes/PolygonShape.cs @ 5974

Revision 5974, 8.9 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.Collections.Generic;
34
35using AdvanceMath;
36using AdvanceMath.Geometry2D;
37
38
39namespace Physics2DDotNet.Shapes
40{
41    /// <summary>
42    /// Use this to Represent a Polygon in the engine
43    /// </summary>
44#if !(WINDOWS_PHONE || XBOX)
45    [Serializable]
46#endif
47    public sealed class PolygonShape : 
48        IShape, IRaySegmentsCollidable, ILineFluidAffectable , IExplosionAffectable
49    {
50        #region fields
51        private DistanceGrid grid;
52        private Vector2D[] vertexes;
53        private Vector2D[] vertexNormals;
54        private Vector2D centroid;
55        private Scalar area;
56        private Scalar inertia;
57        private object tag;
58        #endregion
59        #region constructors
60        /// <summary>
61        /// Creates a new Polygon Instance.
62        /// </summary>
63        /// <param name="vertexes">the vertexes that make up the shape of the Polygon</param>
64        /// <param name="gridSpacing">
65        /// How large a grid cell is. Usualy you will want at least 2 cells between major vertexes.
66        /// The smaller this is the better precision you get, but higher cost in memory.
67        /// The larger the less precision and if it's to high collision detection may fail completely.
68        public PolygonShape(Vector2D[] vertexes, Scalar gridSpacing)
69        {
70            if (vertexes == null) { throw new ArgumentNullException("vertexes"); }
71            if (vertexes.Length < 3) { throw new ArgumentException("too few", "vertexes"); }
72            if (gridSpacing <= 0) { throw new ArgumentOutOfRangeException("gridSpacing"); }
73            this.vertexes = vertexes;
74            this.grid = new DistanceGrid(this, gridSpacing);
75            this.vertexNormals = VertexHelper.GetVertexNormals(this.vertexes);
76            VertexInfo info = VertexHelper.GetVertexInfo(vertexes);
77            this.inertia = info.Inertia;
78            this.centroid = info.Centroid;
79            this.area = info.Area;
80        }
81        /// <summary>
82        /// Creates a new Polygon Instance.
83        /// </summary>
84        /// <param name="vertexes">the vertexes that make up the shape of the Polygon</param>
85        /// <param name="gridSpacing">
86        /// How large a grid cell is. Usualy you will want at least 2 cells between major vertexes.
87        /// The smaller this is the better precision you get, but higher cost in memory.
88        /// The larger the less precision and if it's to high collision detection may fail completely.
89        /// </param>
90        /// <param name="momentOfInertiaMultiplier">
91        /// How hard it is to turn the shape. Depending on the construtor in the
92        /// Body this will be multiplied with the mass to determine the moment of inertia.
93        /// </param>
94        public PolygonShape(Vector2D[] vertexes, Scalar gridSpacing, Scalar inertia):this(vertexes,gridSpacing)
95        {
96            this.inertia = inertia;
97        }
98        #endregion
99        #region properties
100        public object Tag
101        {
102            get { return tag; }
103            set { tag = value; }
104        }
105        public Vector2D[] Vertexes {    get { return vertexes; } }
106        public Vector2D[] VertexNormals   {   get { return vertexNormals; }  }
107        public Scalar Inertia
108        {
109            get { return inertia; }
110        }
111        public Vector2D Centroid
112        {
113            get { return centroid; }
114        }
115        public Scalar Area
116        {
117            get { return area; }
118        }
119        public  bool CanGetIntersection
120        {
121            get { return true; }
122        }
123        public  bool CanGetCustomIntersection
124        {
125            get { return false; }
126        }
127        #endregion
128        #region methods
129        public  void CalcBoundingRectangle(ref Matrix2x3 matrix, out BoundingRectangle rectangle)
130        {
131            BoundingRectangle.FromVectors(ref matrix, Vertexes, out rectangle);
132        }
133        public  void GetDistance(ref Vector2D point, out Scalar result)
134        {
135            BoundingPolygon.GetDistance(Vertexes, ref point, out result);
136        }
137        public  bool TryGetIntersection(Vector2D point, out IntersectionInfo info)
138        {
139            return grid.TryGetIntersection(point, out info);
140        }
141        public  bool TryGetCustomIntersection(Body self, Body other, out object customIntersectionInfo)
142        {
143            throw new NotSupportedException();
144        }
145        DragInfo IGlobalFluidAffectable.GetFluidInfo(Vector2D tangent)
146        {
147            Scalar min, max;
148            ShapeHelper.GetProjectedBounds(this.Vertexes, tangent, out min, out max);
149            Scalar avg = (max + min) / 2;
150            return new DragInfo(tangent * avg, max - min);
151        }
152        bool IRaySegmentsCollidable.TryGetRayCollision(Body thisBody, Body raysBody, RaySegmentsShape raySegments, out RaySegmentIntersectionInfo info)
153        {
154            bool intersects = false;
155            Scalar temp;
156            RaySegment[] segments = raySegments.Segments;
157            Scalar[] result = new Scalar[segments.Length];
158            Matrix2x3 matrix = raysBody.Matrices.ToBody * thisBody.Matrices.ToWorld;
159            Vector2D[] polygon = new Vector2D[Vertexes.Length];
160            for (int index = 0; index < polygon.Length; ++index)
161            {
162                Vector2D.Transform(ref matrix, ref Vertexes[index], out polygon[index]);
163            }
164            BoundingRectangle rect;
165            BoundingRectangle.FromVectors(polygon, out rect);
166            BoundingPolygon poly = new BoundingPolygon(polygon);
167
168            for (int index = 0; index < segments.Length; ++index)
169            {
170                RaySegment segment = segments[index];
171
172                rect.Intersects(ref segment.RayInstance, out temp);
173                if (temp >= 0 && temp <= segment.Length)
174                {
175                   
176                    poly.Intersects(ref segment.RayInstance, out temp);
177                    if (temp < 0 || temp > segment.Length)
178                    {
179                        result[index] = -1;
180                    }
181                    else
182                    {
183                        result[index] = temp;
184                        intersects = true;
185                    }
186                }
187                else
188                {
189                    result[index] = -1;
190                }
191            }
192            if (intersects)
193            {
194                info = new RaySegmentIntersectionInfo(result);
195            }
196            else
197            {
198                info = null;
199            }
200            return intersects;
201        }
202        FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line)
203        {
204            return ShapeHelper.GetFluidInfo(Vertexes, callback, line);
205        }
206        DragInfo IExplosionAffectable.GetExplosionInfo(Matrix2x3 matrix, Scalar radius, GetTangentCallback callback)
207        {
208            //TODO: do this right!
209            Vector2D[] vertexes2 = new Vector2D[Vertexes.Length];
210            for (int index = 0; index < vertexes2.Length; ++index)
211            {
212                vertexes2[index] = matrix * Vertexes[index];
213            }
214            Vector2D[] inter = VertexHelper.GetIntersection(vertexes2, radius);
215            if (inter.Length < 3) { return null; }
216            Vector2D centroid = VertexHelper.GetCentroid(inter);
217            Vector2D tangent = callback(centroid);
218            Scalar min,max;
219            ShapeHelper.GetProjectedBounds(inter, tangent, out min, out max);
220            Scalar avg = (max + min) / 2;
221            return new DragInfo(tangent * avg, max - min);
222        }
223        #endregion
224
225
226    }
227}
Note: See TracBrowser for help on using the repository browser.