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

Revision 5974, 8.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
32
33using System;
34
35using AdvanceMath;
36using AdvanceMath.Geometry2D;
37
38
39namespace Physics2DDotNet.Shapes
40{
41    /// <summary>
42    /// A Circle
43    /// </summary>
44#if !(WINDOWS_PHONE || XBOX)
45    [Serializable]
46#endif
47    public sealed class CircleShape : IShape, IRaySegmentsCollidable, ILineFluidAffectable, IExplosionAffectable
48    {
49        #region fields
50        private Scalar radius;
51        private object tag;
52        private Scalar inertia;
53        private Vector2D[] vertexNormals;
54        private Vector2D[] vertexes;
55        #endregion
56        #region constructors
57
58        /// <summary>
59        /// Creates a new Circle Instance.
60        /// </summary>
61        /// <param name="radius">how large the circle is.</param>
62        /// <param name="vertexCount">
63        /// The number or vertex that will be generated along the perimeter of the circle.
64        /// This is for collision detection.
65        /// </param>
66        public CircleShape(Scalar radius, int vertexCount)
67            : this(radius, vertexCount, MassInfo.InertiaOfSolidCylinder(radius))
68        { }
69        /// <summary>
70        /// Creates a new Circle Instance.
71        /// </summary>
72        /// <param name="radius">how large the circle is.</param>
73        /// <param name="vertexCount">
74        /// The number or vertex that will be generated along the perimeter of the circle.
75        /// This is for collision detection.
76        /// </param>
77        /// <param name="inertia">
78        /// How hard it is to turn the shape. Depending on the construtor in the
79        /// Body this will be multiplied with the mass to determine the moment of inertia.
80        /// </param>
81        public CircleShape(Scalar radius, int vertexCount, Scalar inertia)
82        {
83            if (radius <= 0) { throw new ArgumentOutOfRangeException("radius", "must be larger then zero"); }
84            if (vertexCount < 3) { throw new ArgumentOutOfRangeException("vertexCount", "Must be equal or greater then 3"); }
85            this.vertexes = VertexHelper.CreateCircle(radius, vertexCount);
86            this.vertexNormals = VertexHelper.CreateCircle(1, vertexCount);
87            this.inertia = inertia;
88            this.radius = radius;
89        }
90        #endregion
91        #region properties
92        public object Tag
93        {
94            get { return tag; }
95            set { tag = value; }
96        }
97        public Vector2D[] Vertexes { get { return vertexes; } }
98        public Vector2D[] VertexNormals { get { return vertexNormals; } }
99        public Scalar Inertia
100        {
101            get { return inertia; }
102        }
103        public Vector2D Centroid
104        {
105            get { return Vector2D.Zero; }
106        }
107        public Scalar Area
108        {
109            get { return radius * radius * MathHelper.Pi; }
110        }
111        /// <summary>
112        /// the distance from the position where the circle ends.
113        /// </summary>
114        public Scalar Radius
115        {
116            get { return radius; }
117        }
118        public bool CanGetIntersection
119        {
120            get { return true; }
121        }
122        public bool CanGetCustomIntersection
123        {
124            get { return false; }
125        }
126        #endregion
127        #region methods
128        public void CalcBoundingRectangle(ref Matrix2x3 matrix, out BoundingRectangle rectangle)
129        {
130            BoundingRectangle.FromCircle(ref matrix, ref radius, out rectangle);
131        }
132        public void GetDistance(ref Vector2D point, out Scalar result)
133        {
134            Vector2D.GetMagnitude(ref point, out result);
135            result -= radius;
136        }
137        public bool TryGetIntersection(Vector2D point, out IntersectionInfo info)
138        {
139            info.Position = point;
140            Vector2D normal;
141            Vector2D.Normalize(ref point, out info.Distance, out normal);
142            info.rawNormal = normal;
143            info.normalized = true;
144            info.Distance -= radius;
145            return info.Distance <= 0;
146        }
147        public bool TryGetCustomIntersection(Body self, Body other, out object customIntersectionInfo)
148        {
149            throw new NotSupportedException();
150        }
151        bool IRaySegmentsCollidable.TryGetRayCollision(Body thisBody, Body raysBody, RaySegmentsShape raySegments, out RaySegmentIntersectionInfo info)
152        {
153            bool intersects = false;
154            RaySegment[] segments = raySegments.Segments;
155            Scalar[] result = new Scalar[segments.Length];
156            BoundingCircle bounding = new BoundingCircle(Vector2D.Zero, this.radius);
157            Matrix2x3 vertexM = thisBody.Matrices.ToBody * raysBody.Matrices.ToWorld;
158
159            for (int index = 0; index < segments.Length; ++index)
160            {
161                RaySegment segment = segments[index];
162                Ray ray2;
163
164                Vector2D.Transform(ref vertexM, ref segment.RayInstance.Origin, out ray2.Origin);
165                Vector2D.TransformNormal(ref vertexM, ref segment.RayInstance.Direction, out ray2.Direction);
166
167                Scalar temp;
168                bounding.Intersects(ref ray2, out temp);
169                if (temp >= 0 && temp <= segment.Length)
170                {
171                    intersects = true;
172                    result[index] = temp;
173                    continue;
174                }
175                else
176                {
177                    result[index] = -1;
178                }
179            }
180            if (intersects)
181            {
182                info = new RaySegmentIntersectionInfo(result);
183            }
184            else
185            {
186                info = null;
187            }
188            return intersects;
189        }
190        DragInfo IGlobalFluidAffectable.GetFluidInfo(Vector2D tangent)
191        {
192            return new DragInfo(Vector2D.Zero, radius * 2);
193        }
194        FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line)
195        {
196            return ShapeHelper.GetFluidInfo(Vertexes, callback, line);
197        }
198        DragInfo IExplosionAffectable.GetExplosionInfo(Matrix2x3 matrix, Scalar radius, GetTangentCallback callback)
199        {
200            //TODO: do this right!
201            Vector2D[] vertexes2 = new Vector2D[Vertexes.Length];
202            for (int index = 0; index < vertexes2.Length; ++index)
203            {
204                vertexes2[index] = matrix * Vertexes[index];
205            }
206            Vector2D[] inter = VertexHelper.GetIntersection(vertexes2, radius);
207            if (inter.Length < 3) { return null; }
208            Vector2D centroid = VertexHelper.GetCentroid(inter);
209            Vector2D tangent = callback(centroid);
210            Scalar min, max;
211            ShapeHelper.GetProjectedBounds(inter, tangent, out min, out max);
212            Scalar avg = (max + min) / 2;
213            return new DragInfo(tangent * avg, max - min);
214        }
215        #endregion
216    }
217}
Note: See TracBrowser for help on using the repository browser.