Пример #1
0
        /**
         *  @brief Returns the first {@link TSCollider2D} within a rectangular area. Returns null if there is none.
         *
         *  @param pointA Top-left corner of the rectangle.
         *  @param radius Bottom-right corner of the rectangle.
         **/
        public static object _OverlapArea(TSVector2 pointA, TSVector2 pointB, Physics2D.BodySpecialSensor sensorType)
        {
            TSVector2 center;

            center.x = (pointA.x + pointB.x) * FP.Half;
            center.y = (pointA.y + pointB.y) * FP.Half;

            Physics2D.Vertices vertices = new Physics2D.Vertices(4);
            vertices.Add(new TSVector2(pointA.x, pointA.y) - center);
            vertices.Add(new TSVector2(pointB.x, pointA.y) - center);
            vertices.Add(new TSVector2(pointB.x, pointB.y) - center);
            vertices.Add(new TSVector2(pointA.x, pointB.y) - center);

            return(OverlapGeneric(new Physics2D.PolygonShape(vertices, 1), center, sensorType));
        }
        public static object _OverlapArea(TSVector2 i_PointA, TSVector2 i_PointB, Physics2D.BodySpecialSensor i_SensorType, int i_Mask)
        {
            TSVector2 center;

            center.x = (i_PointA.x + i_PointB.x) * FP.Half;
            center.y = (i_PointA.y + i_PointB.y) * FP.Half;

            Physics2D.Vertices vertices = new Physics2D.Vertices(4);
            vertices.Add(new TSVector2(i_PointA.x, i_PointA.y) - center);
            vertices.Add(new TSVector2(i_PointB.x, i_PointA.y) - center);
            vertices.Add(new TSVector2(i_PointB.x, i_PointB.y) - center);
            vertices.Add(new TSVector2(i_PointA.x, i_PointB.y) - center);

            return(OverlapGeneric(new Physics2D.PolygonShape(vertices, 1), center, i_SensorType, i_Mask));
        }
Пример #3
0
        /**
         *  @brief Returns the first {@link TSCollider2D} within a rectangular area. Returns null if there is none.
         *
         *  @param pointA Top-left corner of the rectangle.
         *  @param radius Bottom-right corner of the rectangle.
         *  @param layerMask Unity's layer mask to filter objects.
         **/
        public static object _OverlapArea(TSVector2 pointA, TSVector2 pointB, Physics2D.BodySpecialSensor sensorType, int layerMask = UnityEngine.Physics.DefaultRaycastLayers)
        {
            TSVector2 center;

            center.x = (pointA.x + pointB.x) * FP.Half;
            center.y = (pointA.y + pointB.y) * FP.Half;

            Physics2D.Vertices vertices = new Physics2D.Vertices(4);
            vertices.Add(new TSVector2(pointA.x, pointA.y) - center);
            vertices.Add(new TSVector2(pointB.x, pointA.y) - center);
            vertices.Add(new TSVector2(pointB.x, pointB.y) - center);
            vertices.Add(new TSVector2(pointA.x, pointB.y) - center);

            return(OverlapGeneric(new Physics2D.PolygonShape(vertices, 1), center, sensorType, layerMask));
        }
Пример #4
0
        /**
         *  @brief Create the internal shape used to represent a PolygonCollider.
         **/
        public override TrueSync.Physics2D.Shape[] CreateShapes()
        {
            if (_points == null || _points.Length == 0)
            {
                return(null);
            }


            TSVector2 lossy2D = new TSVector2(lossyScale.x, lossyScale.y);

            TrueSync.Physics2D.Vertices v = new Physics2D.Vertices();
            for (int index = 0, length = _points.Length; index < length; index++)
            {
                v.Add(TSVector2.Scale(_points[index], lossy2D));
            }

            List <TrueSync.Physics2D.Vertices> convexShapeVs = TrueSync.Physics2D.BayazitDecomposer.ConvexPartition(v);

            TrueSync.Physics2D.Shape[] result = new Physics2D.Shape[convexShapeVs.Count];
            for (int index = 0, length = result.Length; index < length; index++)
            {
                result[index] = new TrueSync.Physics2D.PolygonShape(convexShapeVs[index], 1);
            }

            return(result);
        }
Пример #5
0
        /**
         *  @brief Create the internal shape used to represent a TSBoxCollider.
         **/
        public override TrueSync.Physics2D.Shape CreateShape()
        {
            if (_points == null || _points.Length == 0)
            {
                return(null);
            }

            TSVector2 lossy2D = new TSVector2(lossyScale.x, lossyScale.y);

            TrueSync.Physics2D.Vertices v = new Physics2D.Vertices();
            for (int index = 0, length = _points.Length; index < length; index++)
            {
                v.Add(TSVector2.Scale(_points[index], lossy2D));
            }

            return(new TrueSync.Physics2D.PolygonShape(v, 1));
        }
        /**
         *  @brief Create the internal shape used to represent a TSBoxCollider.
         **/
        public override Physics2D.Shape[] CreateShapes()
        {
            if (m_Points == null || m_Points.Length == 0)
            {
                return(null);
            }

            Physics2D.Vertices v = new Physics2D.Vertices();
            for (int index = 0, length = m_Points.Length; index < length; index++)
            {
                v.Add(m_Points[index]);
            }

            List <Physics2D.Vertices> convexShapeVs = Physics2D.BayazitDecomposer.ConvexPartition(v);

            Physics2D.Shape[] result = new Physics2D.Shape[convexShapeVs.Count];
            for (int index = 0, length = result.Length; index < length; index++)
            {
                result[index] = new Physics2D.PolygonShape(convexShapeVs[index], 1);
            }

            return(result);
        }
Пример #7
0
        public Dictionary <Fixture, TSVector2> Activate(TSVector2 pos, FP radius, FP maxForce)
        {
            AABB aABB;

            aABB.LowerBound = pos + new TSVector2(-radius, -radius);
            aABB.UpperBound = pos + new TSVector2(radius, radius);
            Fixture[] shapes              = new Fixture[this.MaxShapes];
            Fixture[] containedShapes     = new Fixture[5];
            bool      exit                = false;
            int       shapeCount          = 0;
            int       containedShapeCount = 0;

            this.World.QueryAABB(delegate(Fixture fixture)
            {
                bool flag22 = fixture.TestPoint(ref pos);
                bool result2;
                if (flag22)
                {
                    bool ignoreWhenInsideShape = this.IgnoreWhenInsideShape;
                    if (ignoreWhenInsideShape)
                    {
                        exit    = true;
                        result2 = false;
                        return(result2);
                    }
                    Fixture[] arg_45_0  = containedShapes;
                    int num4            = containedShapeCount;
                    containedShapeCount = num4 + 1;
                    arg_45_0[num4]      = fixture;
                }
                else
                {
                    Fixture[] arg_62_0 = shapes;
                    int num4           = shapeCount;
                    shapeCount         = num4 + 1;
                    arg_62_0[num4]     = fixture;
                }
                result2 = true;
                return(result2);
            }, ref aABB);
            bool exit2 = exit;
            Dictionary <Fixture, TSVector2> result;

            if (exit2)
            {
                result = new Dictionary <Fixture, TSVector2>();
            }
            else
            {
                Dictionary <Fixture, TSVector2> dictionary = new Dictionary <Fixture, TSVector2>(shapeCount + containedShapeCount);
                FP[] array = new FP[shapeCount * 2];
                int  num   = 0;
                for (int i = 0; i < shapeCount; i++)
                {
                    CircleShape  circleShape = shapes[i].Shape as CircleShape;
                    bool         flag        = circleShape != null;
                    PolygonShape polygonShape;
                    if (flag)
                    {
                        Vertices  vertices = new Vertices();
                        TSVector2 item     = TSVector2.zero + new TSVector2(circleShape.Radius, 0);
                        vertices.Add(item);
                        item = TSVector2.zero + new TSVector2(0, circleShape.Radius);
                        vertices.Add(item);
                        item = TSVector2.zero + new TSVector2(-circleShape.Radius, circleShape.Radius);
                        vertices.Add(item);
                        item = TSVector2.zero + new TSVector2(0, -circleShape.Radius);
                        vertices.Add(item);
                        polygonShape = new PolygonShape(vertices, 0);
                    }
                    else
                    {
                        polygonShape = (shapes[i].Shape as PolygonShape);
                    }
                    bool flag2 = shapes[i].Body.BodyType == BodyType.Dynamic && polygonShape != null;
                    if (flag2)
                    {
                        TSVector2 tSVector = shapes[i].Body.GetWorldPoint(polygonShape.MassData.Centroid) - pos;
                        FP        y        = FP.Atan2(tSVector.y, tSVector.x);
                        FP        y2       = FP.MaxValue;
                        FP        y3       = FP.MinValue;
                        FP        fP       = 0f;
                        FP        fP2      = 0f;
                        for (int j = 0; j < polygonShape.Vertices.Count; j++)
                        {
                            TSVector2 tSVector2 = shapes[i].Body.GetWorldPoint(polygonShape.Vertices[j]) - pos;
                            FP        fP3       = FP.Atan2(tSVector2.y, tSVector2.x);
                            FP        fP4       = fP3 - y;
                            fP4 = (fP4 - MathHelper.Pi) % (2 * MathHelper.Pi);
                            bool flag3 = fP4 < 0f;
                            if (flag3)
                            {
                                fP4 += 2 * MathHelper.Pi;
                            }
                            fP4 -= MathHelper.Pi;
                            bool flag4 = FP.Abs(fP4) > MathHelper.Pi;
                            if (!flag4)
                            {
                                bool flag5 = fP4 > y3;
                                if (flag5)
                                {
                                    y3  = fP4;
                                    fP2 = fP3;
                                }
                                bool flag6 = fP4 < y2;
                                if (flag6)
                                {
                                    y2 = fP4;
                                    fP = fP3;
                                }
                            }
                        }
                        array[num] = fP;
                        num++;
                        array[num] = fP2;
                        num++;
                    }
                }
                Array.Sort <FP>(array, 0, num, this._rdc);
                this._data.Clear();
                bool flag7 = true;
                for (int k = 0; k < num; k++)
                {
                    Fixture fixture = null;
                    int     num2    = (k == num - 1) ? 0 : (k + 1);
                    bool    flag8   = array[k] == array[num2];
                    if (!flag8)
                    {
                        bool flag9 = k == num - 1;
                        FP   x;
                        if (flag9)
                        {
                            x = array[0] + MathHelper.Pi * 2 + array[k];
                        }
                        else
                        {
                            x = array[k + 1] + array[k];
                        }
                        x /= 2;
                        TSVector2 pos2       = pos;
                        TSVector2 point      = radius * new TSVector2(FP.Cos(x), FP.Sin(x)) + pos;
                        bool      hitClosest = false;
                        this.World.RayCast(delegate(Fixture f, TSVector2 p, TSVector2 n, FP fr)
                        {
                            Body body   = f.Body;
                            bool flag22 = !this.IsActiveOn(body);
                            FP result2;
                            if (flag22)
                            {
                                result2 = 0;
                            }
                            else
                            {
                                hitClosest = true;
                                fixture    = f;
                                result2    = fr;
                            }
                            return(result2);
                        }, pos2, point);
                        bool flag10 = hitClosest && fixture.Body.BodyType == BodyType.Dynamic;
                        if (flag10)
                        {
                            bool flag11 = this._data.Any <ShapeData>() && this._data.Last <ShapeData>().Body == fixture.Body && !flag7;
                            if (flag11)
                            {
                                int       index = this._data.Count - 1;
                                ShapeData value = this._data[index];
                                value.Max         = array[num2];
                                this._data[index] = value;
                            }
                            else
                            {
                                ShapeData item2;
                                item2.Body = fixture.Body;
                                item2.Min  = array[k];
                                item2.Max  = array[num2];
                                this._data.Add(item2);
                            }
                            bool flag12 = this._data.Count > 1 && k == num - 1 && this._data.Last <ShapeData>().Body == this._data.First <ShapeData>().Body&& this._data.Last <ShapeData>().Max == this._data.First <ShapeData>().Min;
                            if (flag12)
                            {
                                ShapeData value2 = this._data[0];
                                value2.Min = this._data.Last <ShapeData>().Min;
                                this._data.RemoveAt(this._data.Count - 1);
                                this._data[0] = value2;
                                while (this._data.First <ShapeData>().Min >= this._data.First <ShapeData>().Max)
                                {
                                    value2.Min   -= MathHelper.Pi * 2;
                                    this._data[0] = value2;
                                }
                            }
                            int       index2 = this._data.Count - 1;
                            ShapeData value3 = this._data[index2];
                            while (this._data.Count > 0 && this._data.Last <ShapeData>().Min >= this._data.Last <ShapeData>().Max)
                            {
                                value3.Min         = this._data.Last <ShapeData>().Min - 2 * MathHelper.Pi;
                                this._data[index2] = value3;
                            }
                            flag7 = false;
                        }
                        else
                        {
                            flag7 = true;
                        }
                    }
                }
                for (int l = 0; l < this._data.Count; l++)
                {
                    bool flag13 = !this.IsActiveOn(this._data[l].Body);
                    if (!flag13)
                    {
                        FP   fP5    = this._data[l].Max - this._data[l].Min;
                        FP   fP6    = MathHelper.Min(RealExplosion.MaxEdgeOffset, this.EdgeRatio * fP5);
                        int  num3   = FP.Ceiling((fP5 - 2f * fP6 - (this.MinRays - 1) * this.MaxAngle) / this.MaxAngle).AsInt();
                        bool flag14 = num3 < 0;
                        if (flag14)
                        {
                            num3 = 0;
                        }
                        FP y4  = (fP5 - fP6 * 2f) / (this.MinRays + num3 - 1);
                        FP fP7 = this._data[l].Min + fP6;
                        while (fP7 < this._data[l].Max || MathUtils.FPEquals(fP7, this._data[l].Max, 0.0001f))
                        {
                            TSVector2      pos3        = pos;
                            TSVector2      tSVector3   = pos + radius * new TSVector2(FP.Cos(fP7), FP.Sin(fP7));
                            TSVector2      tSVector4   = TSVector2.zero;
                            FP             fP8         = FP.MaxValue;
                            List <Fixture> fixtureList = this._data[l].Body.FixtureList;
                            for (int m = 0; m < fixtureList.Count; m++)
                            {
                                Fixture      fixture3 = fixtureList[m];
                                RayCastInput rayCastInput;
                                rayCastInput.Point1      = pos3;
                                rayCastInput.Point2      = tSVector3;
                                rayCastInput.MaxFraction = 50f;
                                RayCastOutput rayCastOutput;
                                bool          flag15 = fixture3.RayCast(out rayCastOutput, ref rayCastInput, 0);
                                if (flag15)
                                {
                                    bool flag16 = fP8 > rayCastOutput.Fraction;
                                    if (flag16)
                                    {
                                        fP8       = rayCastOutput.Fraction;
                                        tSVector4 = rayCastOutput.Fraction * tSVector3 + (1 - rayCastOutput.Fraction) * pos3;
                                    }
                                }
                                FP        scaleFactor = fP5 / (this.MinRays + num3) * maxForce * 180f / MathHelper.Pi * (1f - TSMath.Min(FP.One, fP8));
                                TSVector2 tSVector5   = TSVector2.Dot(scaleFactor * new TSVector2(FP.Cos(fP7), FP.Sin(fP7)), -rayCastOutput.Normal) * new TSVector2(FP.Cos(fP7), FP.Sin(fP7));
                                this._data[l].Body.ApplyLinearImpulse(ref tSVector5, ref tSVector4);
                                bool flag17 = dictionary.ContainsKey(fixture3);
                                if (flag17)
                                {
                                    Dictionary <Fixture, TSVector2> dictionary2 = dictionary;
                                    Fixture key = fixture3;
                                    dictionary2[key] += tSVector5;
                                }
                                else
                                {
                                    dictionary.Add(fixture3, tSVector5);
                                }
                                bool flag18 = fP8 > 1f;
                                if (flag18)
                                {
                                    tSVector4 = tSVector3;
                                }
                            }
                            fP7 += y4;
                        }
                    }
                }
                for (int n2 = 0; n2 < containedShapeCount; n2++)
                {
                    Fixture fixture2 = containedShapes[n2];
                    bool    flag19   = !this.IsActiveOn(fixture2.Body);
                    if (!flag19)
                    {
                        FP          scaleFactor2 = this.MinRays * maxForce * 180f / MathHelper.Pi;
                        CircleShape circleShape2 = fixture2.Shape as CircleShape;
                        bool        flag20       = circleShape2 != null;
                        TSVector2   worldPoint;
                        if (flag20)
                        {
                            worldPoint = fixture2.Body.GetWorldPoint(circleShape2.Position);
                        }
                        else
                        {
                            PolygonShape polygonShape2 = fixture2.Shape as PolygonShape;
                            worldPoint = fixture2.Body.GetWorldPoint(polygonShape2.MassData.Centroid);
                        }
                        TSVector2 value4 = scaleFactor2 * (worldPoint - pos);
                        fixture2.Body.ApplyLinearImpulse(ref value4, ref worldPoint);
                        bool flag21 = !dictionary.ContainsKey(fixture2);
                        if (flag21)
                        {
                            dictionary.Add(fixture2, value4);
                        }
                    }
                }
                result = dictionary;
            }
            return(result);
        }
Пример #8
0
        /// <summary>
        /// Merges all parallel edges in the list of vertices
        /// </summary>
        /// <param name="vertices">The vertices.</param>
        /// <param name="tolerance">The tolerance.</param>
        public static Vertices MergeParallelEdges(Vertices vertices, FP tolerance)
        {
            //From Eric Jordan's convex decomposition library

            if (vertices.Count <= 3)
            {
                return(vertices); //Can't do anything useful here to a triangle
            }
            bool[] mergeMe      = new bool[vertices.Count];
            int    newNVertices = vertices.Count;

            //Gather points to process
            for (int i = 0; i < vertices.Count; ++i)
            {
                int lower  = (i == 0) ? (vertices.Count - 1) : (i - 1);
                int middle = i;
                int upper  = (i == vertices.Count - 1) ? (0) : (i + 1);

                FP dx0   = vertices[middle].x - vertices[lower].x;
                FP dy0   = vertices[middle].y - vertices[lower].y;
                FP dx1   = vertices[upper].y - vertices[middle].x;
                FP dy1   = vertices[upper].y - vertices[middle].y;
                FP norm0 = FP.Sqrt(dx0 * dx0 + dy0 * dy0);
                FP norm1 = FP.Sqrt(dx1 * dx1 + dy1 * dy1);

                if (!(norm0 > 0.0f && norm1 > 0.0f) && newNVertices > 3)
                {
                    //Merge identical points
                    mergeMe[i] = true;
                    --newNVertices;
                }

                dx0 /= norm0;
                dy0 /= norm0;
                dx1 /= norm1;
                dy1 /= norm1;
                FP cross = dx0 * dy1 - dx1 * dy0;
                FP dot   = dx0 * dx1 + dy0 * dy1;

                if (FP.Abs(cross) < tolerance && dot > 0 && newNVertices > 3)
                {
                    mergeMe[i] = true;
                    --newNVertices;
                }
                else
                {
                    mergeMe[i] = false;
                }
            }

            if (newNVertices == vertices.Count || newNVertices == 0)
            {
                return(vertices);
            }

            int currIndex = 0;

            //Copy the vertices to a new list and clear the old
            Vertices newVertices = new Vertices(newNVertices);

            for (int i = 0; i < vertices.Count; ++i)
            {
                if (mergeMe[i] || newNVertices == 0 || currIndex == newNVertices)
                {
                    continue;
                }

                Debug.Assert(currIndex < newNVertices);

                newVertices.Add(vertices[i]);
                ++currIndex;
            }

            return(newVertices);
        }
Пример #9
0
        //Rounded rectangle contributed by Jonathan Smars - [email protected]

        /// <summary>
        /// Creates a rounded rectangle with the specified width and height.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="xRadius">The rounding X radius.</param>
        /// <param name="yRadius">The rounding Y radius.</param>
        /// <param name="segments">The number of segments to subdivide the edges.</param>
        /// <returns></returns>
        public static Vertices CreateRoundedRectangle(FP width, FP height, FP xRadius, FP yRadius,
                                                      int segments)
        {
            if (yRadius > height / 2 || xRadius > width / 2)
            {
                throw new Exception("Rounding amount can't be more than half the height and width respectively.");
            }
            if (segments < 0)
            {
                throw new Exception("Segments must be zero or more.");
            }

            //We need at least 8 vertices to create a rounded rectangle
            Debug.Assert(Settings.MaxPolygonVertices >= 8);

            Vertices vertices = new Vertices();

            if (segments == 0)
            {
                vertices.Add(new TSVector2(width * .5f - xRadius, -height * .5f));
                vertices.Add(new TSVector2(width * .5f, -height * .5f + yRadius));

                vertices.Add(new TSVector2(width * .5f, height * .5f - yRadius));
                vertices.Add(new TSVector2(width * .5f - xRadius, height * .5f));

                vertices.Add(new TSVector2(-width * .5f + xRadius, height * .5f));
                vertices.Add(new TSVector2(-width * .5f, height * .5f - yRadius));

                vertices.Add(new TSVector2(-width * .5f, -height * .5f + yRadius));
                vertices.Add(new TSVector2(-width * .5f + xRadius, -height * .5f));
            }
            else
            {
                int numberOfEdges = (segments * 4 + 8);

                FP  stepSize = FP.PiTimes2 / (numberOfEdges - 4);
                int perPhase = numberOfEdges / 4;

                TSVector2 posOffset = new TSVector2(width / 2 - xRadius, height / 2 - yRadius);
                vertices.Add(posOffset + new TSVector2(xRadius, -yRadius + yRadius));
                short phase = 0;
                for (int i = 1; i < numberOfEdges; i++)
                {
                    if (i - perPhase == 0 || i - perPhase * 3 == 0)
                    {
                        posOffset.x *= -1;
                        phase--;
                    }
                    else if (i - perPhase * 2 == 0)
                    {
                        posOffset.y *= -1;
                        phase--;
                    }

                    vertices.Add(posOffset + new TSVector2(xRadius * FP.Cos(stepSize * -(i + phase)),
                                                           -yRadius * FP.Sin(stepSize * -(i + phase))));
                }
            }

            return(vertices);
        }
Пример #10
0
        /// <summary>
        /// Creates an capsule with the specified  height, radius and number of edges.
        /// A capsule has the same form as a pill capsule.
        /// </summary>
        /// <param name="height">Height (inner height + radii) of the capsule.</param>
        /// <param name="topRadius">Radius of the top.</param>
        /// <param name="topEdges">The number of edges of the top. The more edges, the more it resembles an capsule</param>
        /// <param name="bottomRadius">Radius of bottom.</param>
        /// <param name="bottomEdges">The number of edges of the bottom. The more edges, the more it resembles an capsule</param>
        /// <returns></returns>
        public static Vertices CreateCapsule(FP height, FP topRadius, int topEdges, FP bottomRadius,
                                             int bottomEdges)
        {
            if (height <= 0)
            {
                throw new ArgumentException("Height must be longer than 0", "height");
            }

            if (topRadius <= 0)
            {
                throw new ArgumentException("The top radius must be more than 0", "topRadius");
            }

            if (topEdges <= 0)
            {
                throw new ArgumentException("Top edges must be more than 0", "topEdges");
            }

            if (bottomRadius <= 0)
            {
                throw new ArgumentException("The bottom radius must be more than 0", "bottomRadius");
            }

            if (bottomEdges <= 0)
            {
                throw new ArgumentException("Bottom edges must be more than 0", "bottomEdges");
            }

            if (topRadius >= height / 2)
            {
                throw new ArgumentException(
                          "The top radius must be lower than height / 2. Higher values of top radius would create a circle, and not a half circle.",
                          "topRadius");
            }

            if (bottomRadius >= height / 2)
            {
                throw new ArgumentException(
                          "The bottom radius must be lower than height / 2. Higher values of bottom radius would create a circle, and not a half circle.",
                          "bottomRadius");
            }

            Vertices vertices = new Vertices();

            FP newHeight = (height - topRadius - bottomRadius) * 0.5f;

            // top
            vertices.Add(new TSVector2(topRadius, newHeight));

            FP stepSize = FP.Pi / topEdges;

            for (int i = 1; i < topEdges; i++)
            {
                vertices.Add(new TSVector2(topRadius * FP.Cos(stepSize * i),
                                           topRadius * FP.Sin(stepSize * i) + newHeight));
            }

            vertices.Add(new TSVector2(-topRadius, newHeight));

            // bottom
            vertices.Add(new TSVector2(-bottomRadius, -newHeight));

            stepSize = FP.Pi / bottomEdges;
            for (int i = 1; i < bottomEdges; i++)
            {
                vertices.Add(new TSVector2(-bottomRadius * FP.Cos(stepSize * i),
                                           -bottomRadius * FP.Sin(stepSize * i) - newHeight));
            }

            vertices.Add(new TSVector2(bottomRadius, -newHeight));

            return(vertices);
        }
Пример #11
0
        public static Vertices GetConvexHull(Vertices vertices)
        {
            bool     flag = vertices.Count <= 3;
            Vertices result;

            if (flag)
            {
                result = vertices;
            }
            else
            {
                int num = 0;
                FP  y   = vertices[0].x;
                for (int i = 1; i < vertices.Count; i++)
                {
                    FP   x     = vertices[i].x;
                    bool flag2 = x > y || (x == y && vertices[i].y < vertices[num].y);
                    if (flag2)
                    {
                        num = i;
                        y   = x;
                    }
                }
                int[] array = new int[vertices.Count];
                int   num2  = 0;
                int   num3  = num;
                bool  flag6;
                do
                {
                    array[num2] = num3;
                    int num4 = 0;
                    for (int j = 1; j < vertices.Count; j++)
                    {
                        bool flag3 = num4 == num3;
                        if (flag3)
                        {
                            num4 = j;
                        }
                        else
                        {
                            TSVector2 tSVector  = vertices[num4] - vertices[array[num2]];
                            TSVector2 tSVector2 = vertices[j] - vertices[array[num2]];
                            FP        x2        = MathUtils.Cross(ref tSVector, ref tSVector2);
                            bool      flag4     = x2 < 0f;
                            if (flag4)
                            {
                                num4 = j;
                            }
                            bool flag5 = x2 == 0f && tSVector2.LengthSquared() > tSVector.LengthSquared();
                            if (flag5)
                            {
                                num4 = j;
                            }
                        }
                    }
                    num2++;
                    num3  = num4;
                    flag6 = (num4 == num);
                }while (!flag6);
                Vertices vertices2 = new Vertices(num2);
                for (int k = 0; k < num2; k++)
                {
                    vertices2.Add(vertices[array[k]]);
                }
                result = vertices2;
            }
            return(result);
        }
Пример #12
0
        private static bool ResolvePinchPoint(Vertices pin, out Vertices poutA, out Vertices poutB, FP tolerance)
        {
            poutA = new Vertices();
            poutB = new Vertices();
            bool flag = pin.Count < 3;
            bool result;

            if (flag)
            {
                result = false;
            }
            else
            {
                bool flag2 = false;
                int  num   = -1;
                int  num2  = -1;
                for (int i = 0; i < pin.Count; i++)
                {
                    for (int j = i + 1; j < pin.Count; j++)
                    {
                        bool flag3 = FP.Abs(pin[i].x - pin[j].x) < tolerance && FP.Abs(pin[i].y - pin[j].y) < tolerance && j != i + 1;
                        if (flag3)
                        {
                            num   = i;
                            num2  = j;
                            flag2 = true;
                            break;
                        }
                    }
                    bool flag4 = flag2;
                    if (flag4)
                    {
                        break;
                    }
                }
                bool flag5 = flag2;
                if (flag5)
                {
                    int  num3  = num2 - num;
                    bool flag6 = num3 == pin.Count;
                    if (flag6)
                    {
                        result = false;
                        return(result);
                    }
                    for (int k = 0; k < num3; k++)
                    {
                        int index = EarclipDecomposer.Remainder(num + k, pin.Count);
                        poutA.Add(pin[index]);
                    }
                    int num4 = pin.Count - num3;
                    for (int l = 0; l < num4; l++)
                    {
                        int index2 = EarclipDecomposer.Remainder(num2 + l, pin.Count);
                        poutB.Add(pin[index2]);
                    }
                }
                result = flag2;
            }
            return(result);
        }
Пример #13
0
        private static Vertices AddTriangle(Vertices t, Vertices vertices)
        {
            int num  = -1;
            int num2 = -1;
            int num3 = -1;
            int num4 = -1;

            for (int i = 0; i < vertices.Count; i++)
            {
                bool flag = t[0].x == vertices[i].x && t[0].y == vertices[i].y;
                if (flag)
                {
                    bool flag2 = num == -1;
                    if (flag2)
                    {
                        num  = i;
                        num2 = 0;
                    }
                    else
                    {
                        num3 = i;
                        num4 = 0;
                    }
                }
                else
                {
                    bool flag3 = t[1].x == vertices[i].x && t[1].y == vertices[i].y;
                    if (flag3)
                    {
                        bool flag4 = num == -1;
                        if (flag4)
                        {
                            num  = i;
                            num2 = 1;
                        }
                        else
                        {
                            num3 = i;
                            num4 = 1;
                        }
                    }
                    else
                    {
                        bool flag5 = t[2].x == vertices[i].x && t[2].y == vertices[i].y;
                        if (flag5)
                        {
                            bool flag6 = num == -1;
                            if (flag6)
                            {
                                num  = i;
                                num2 = 2;
                            }
                            else
                            {
                                num3 = i;
                                num4 = 2;
                            }
                        }
                    }
                }
            }
            bool flag7 = num == 0 && num3 == vertices.Count - 1;

            if (flag7)
            {
                num  = vertices.Count - 1;
                num3 = 0;
            }
            bool     flag8 = num3 == -1;
            Vertices result;

            if (flag8)
            {
                result = null;
            }
            else
            {
                int  num5  = 0;
                bool flag9 = num5 == num2 || num5 == num4;
                if (flag9)
                {
                    num5 = 1;
                }
                bool flag10 = num5 == num2 || num5 == num4;
                if (flag10)
                {
                    num5 = 2;
                }
                Vertices vertices2 = new Vertices(vertices.Count + 1);
                for (int j = 0; j < vertices.Count; j++)
                {
                    vertices2.Add(vertices[j]);
                    bool flag11 = j == num;
                    if (flag11)
                    {
                        vertices2.Add(t[num5]);
                    }
                }
                result = vertices2;
            }
            return(result);
        }
        /// <summary>
        /// Decompose the polygon into triangles.
        ///
        /// Properties:
        /// - Only works on counter clockwise polygons
        ///
        /// </summary>
        /// <param name="vertices">The list of points describing the polygon</param>
        public static List <Vertices> ConvexPartition(Vertices vertices)
        {
            Debug.Assert(vertices.Count > 3);
            Debug.Assert(vertices.IsCounterClockWise());

            int[] polygon = new int[vertices.Count];

            for (int v = 0; v < vertices.Count; v++)
            {
                polygon[v] = v;
            }

            int nv = vertices.Count;

            // Remove nv-2 Vertices, creating 1 triangle every time
            int count = 2 * nv; /* error detection */

            List <Vertices> result = new List <Vertices>();

            for (int v = nv - 1; nv > 2;)
            {
                // If we loop, it is probably a non-simple polygon
                if (0 >= (count--))
                {
                    // Triangulate: ERROR - probable bad polygon!
                    return(new List <Vertices>());
                }

                // Three consecutive vertices in current polygon, <u,v,w>
                int u = v;
                if (nv <= u)
                {
                    u = 0; // Previous
                }
                v = u + 1;
                if (nv <= v)
                {
                    v = 0; // New v
                }
                int w = v + 1;
                if (nv <= w)
                {
                    w = 0; // Next
                }
                _tmpA = vertices[polygon[u]];
                _tmpB = vertices[polygon[v]];
                _tmpC = vertices[polygon[w]];

                if (Snip(vertices, u, v, w, nv, polygon))
                {
                    int s, t;

                    // Output Triangle
                    Vertices triangle = new Vertices(3);
                    triangle.Add(_tmpA);
                    triangle.Add(_tmpB);
                    triangle.Add(_tmpC);
                    result.Add(triangle);

                    // Remove v from remaining polygon
                    for (s = v, t = v + 1; t < nv; s++, t++)
                    {
                        polygon[s] = polygon[t];
                    }
                    nv--;

                    // Reset error detection counter
                    count = 2 * nv;
                }
            }

            return(result);
        }
Пример #15
0
        public static Vertices MergeParallelEdges(Vertices vertices, FP tolerance)
        {
            bool     flag = vertices.Count <= 3;
            Vertices result;

            if (flag)
            {
                result = vertices;
            }
            else
            {
                bool[] array = new bool[vertices.Count];
                int    num   = vertices.Count;
                for (int i = 0; i < vertices.Count; i++)
                {
                    int  index  = (i == 0) ? (vertices.Count - 1) : (i - 1);
                    int  index2 = i;
                    int  index3 = (i == vertices.Count - 1) ? 0 : (i + 1);
                    FP   fP     = vertices[index2].x - vertices[index].x;
                    FP   fP2    = vertices[index2].y - vertices[index].y;
                    FP   fP3    = vertices[index3].y - vertices[index2].x;
                    FP   fP4    = vertices[index3].y - vertices[index2].y;
                    FP   fP5    = FP.Sqrt(fP * fP + fP2 * fP2);
                    FP   fP6    = FP.Sqrt(fP3 * fP3 + fP4 * fP4);
                    bool flag2  = (!(fP5 > 0f) || !(fP6 > 0f)) && num > 3;
                    if (flag2)
                    {
                        array[i] = true;
                        num--;
                    }
                    fP  /= fP5;
                    fP2 /= fP5;
                    fP3 /= fP6;
                    fP4 /= fP6;
                    FP   value = fP * fP4 - fP3 * fP2;
                    FP   x     = fP * fP3 + fP2 * fP4;
                    bool flag3 = FP.Abs(value) < tolerance && x > 0 && num > 3;
                    if (flag3)
                    {
                        array[i] = true;
                        num--;
                    }
                    else
                    {
                        array[i] = false;
                    }
                }
                bool flag4 = num == vertices.Count || num == 0;
                if (flag4)
                {
                    result = vertices;
                }
                else
                {
                    int      num2      = 0;
                    Vertices vertices2 = new Vertices(num);
                    for (int j = 0; j < vertices.Count; j++)
                    {
                        bool flag5 = array[j] || num == 0 || num2 == num;
                        if (!flag5)
                        {
                            Debug.Assert(num2 < num);
                            vertices2.Add(vertices[j]);
                            num2++;
                        }
                    }
                    result = vertices2;
                }
            }
            return(result);
        }
Пример #16
0
        private static PolyClipError BuildPolygonsFromChain(List <YuPengClipper.Edge> simplicies, out List <Vertices> result)
        {
            result = new List <Vertices>();
            PolyClipError polyClipError = PolyClipError.None;
            PolyClipError result2;

            while (simplicies.Count > 0)
            {
                Vertices vertices = new Vertices();
                vertices.Add(simplicies[0].EdgeStart);
                vertices.Add(simplicies[0].EdgeEnd);
                simplicies.RemoveAt(0);
                bool flag  = false;
                int  num   = 0;
                int  count = simplicies.Count;
                while (!flag && simplicies.Count > 0)
                {
                    bool flag2 = YuPengClipper.VectorEqual(vertices[vertices.Count - 1], simplicies[num].EdgeStart);
                    if (flag2)
                    {
                        bool flag3 = YuPengClipper.VectorEqual(simplicies[num].EdgeEnd, vertices[0]);
                        if (flag3)
                        {
                            flag = true;
                        }
                        else
                        {
                            vertices.Add(simplicies[num].EdgeEnd);
                        }
                        simplicies.RemoveAt(num);
                        num--;
                    }
                    else
                    {
                        bool flag4 = YuPengClipper.VectorEqual(vertices[vertices.Count - 1], simplicies[num].EdgeEnd);
                        if (flag4)
                        {
                            bool flag5 = YuPengClipper.VectorEqual(simplicies[num].EdgeStart, vertices[0]);
                            if (flag5)
                            {
                                flag = true;
                            }
                            else
                            {
                                vertices.Add(simplicies[num].EdgeStart);
                            }
                            simplicies.RemoveAt(num);
                            num--;
                        }
                    }
                    bool flag6 = !flag;
                    if (flag6)
                    {
                        bool flag7 = ++num == simplicies.Count;
                        if (flag7)
                        {
                            bool flag8 = count == simplicies.Count;
                            if (flag8)
                            {
                                result = new List <Vertices>();
                                Debug.WriteLine("Undefined error while building result polygon(s).");
                                result2 = PolyClipError.BrokenResult;
                                return(result2);
                            }
                            num   = 0;
                            count = simplicies.Count;
                        }
                    }
                }
                bool flag9 = vertices.Count < 3;
                if (flag9)
                {
                    polyClipError = PolyClipError.DegeneratedOutput;
                    Debug.WriteLine("Degenerated output polygon produced (vertices < 3).");
                }
                result.Add(vertices);
            }
            result2 = polyClipError;
            return(result2);
        }
Пример #17
0
        /// <summary>
        /// Returns the convex hull from the given vertices..
        /// </summary>
        public static Vertices GetConvexHull(Vertices vertices)
        {
            if (vertices.Count <= 3)
            {
                return(vertices);
            }

            Vertices pointSet = new Vertices(vertices);

            //Sort by X-axis
            pointSet.Sort(_pointComparer);

            TSVector2[] h = new TSVector2[pointSet.Count];
            Vertices    res;

            int top = -1; // indices for bottom and top of the stack
            int i;        // array scan index

            // Get the indices of points with min x-coord and min|max y-coord
            const int minmin = 0;
            FP        xmin   = pointSet[0].x;

            for (i = 1; i < pointSet.Count; i++)
            {
                if (pointSet[i].x != xmin)
                {
                    break;
                }
            }

            // degenerate case: all x-coords == xmin
            int minmax = i - 1;

            if (minmax == pointSet.Count - 1)
            {
                h[++top] = pointSet[minmin];

                if (pointSet[minmax].y != pointSet[minmin].y) // a nontrivial segment
                {
                    h[++top] = pointSet[minmax];
                }

                h[++top] = pointSet[minmin]; // add polygon endpoint

                res = new Vertices(top + 1);
                for (int j = 0; j < top + 1; j++)
                {
                    res.Add(h[j]);
                }

                return(res);
            }

            top = -1;

            // Get the indices of points with max x-coord and min|max y-coord
            int maxmax = pointSet.Count - 1;
            FP  xmax   = pointSet[pointSet.Count - 1].x;

            for (i = pointSet.Count - 2; i >= 0; i--)
            {
                if (pointSet[i].x != xmax)
                {
                    break;
                }
            }
            int maxmin = i + 1;

            // Compute the lower hull on the stack H
            h[++top] = pointSet[minmin]; // push minmin point onto stack
            i        = minmax;
            while (++i <= maxmin)
            {
                // the lower line joins P[minmin] with P[maxmin]
                if (MathUtils.Area(pointSet[minmin], pointSet[maxmin], pointSet[i]) >= 0 && i < maxmin)
                {
                    continue;   // ignore P[i] above or on the lower line
                }
                while (top > 0) // there are at least 2 points on the stack
                {
                    // test if P[i] is left of the line at the stack top
                    if (MathUtils.Area(h[top - 1], h[top], pointSet[i]) > 0)
                    {
                        break;          // P[i] is a new hull vertex
                    }
                    top--;              // pop top point off stack
                }
                h[++top] = pointSet[i]; // push P[i] onto stack
            }

            // Next, compute the upper hull on the stack H above the bottom hull
            if (maxmax != maxmin)            // if distinct xmax points
            {
                h[++top] = pointSet[maxmax]; // push maxmax point onto stack
            }
            int bot = top;

            i = maxmin;
            while (--i >= minmax)
            {
                // the upper line joins P[maxmax] with P[minmax]
                if (MathUtils.Area(pointSet[maxmax], pointSet[minmax], pointSet[i]) >= 0 && i > minmax)
                {
                    continue;     // ignore P[i] below or on the upper line
                }
                while (top > bot) // at least 2 points on the upper stack
                {
                    // test if P[i] is left of the line at the stack top
                    if (MathUtils.Area(h[top - 1], h[top], pointSet[i]) > 0)
                    {
                        break; // P[i] is a new hull vertex
                    }
                    top--;     // pop top point off stack
                }

                h[++top] = pointSet[i]; // push P[i] onto stack
            }

            if (minmax != minmin)
            {
                h[++top] = pointSet[minmin]; // push joining endpoint onto stack
            }
            res = new Vertices(top + 1);

            for (int j = 0; j < top + 1; j++)
            {
                res.Add(h[j]);
            }

            return(res);
        }
Пример #18
0
        public static List <Vertices> PolygonizeTriangles(List <Vertices> triangles, int maxPolys = 2147483647, float tolerance = 0.001f)
        {
            bool            flag = triangles.Count <= 0;
            List <Vertices> result;

            if (flag)
            {
                result = triangles;
            }
            else
            {
                List <Vertices> list  = new List <Vertices>();
                bool[]          array = new bool[triangles.Count];
                for (int i = 0; i < triangles.Count; i++)
                {
                    array[i] = false;
                    Vertices  vertices  = triangles[i];
                    TSVector2 tSVector  = vertices[0];
                    TSVector2 tSVector2 = vertices[1];
                    TSVector2 tSVector3 = vertices[2];
                    bool      flag2     = (tSVector.x == tSVector2.x && tSVector.y == tSVector2.y) || (tSVector2.x == tSVector3.x && tSVector2.y == tSVector3.y) || (tSVector.x == tSVector3.x && tSVector.y == tSVector3.y);
                    if (flag2)
                    {
                        array[i] = true;
                    }
                }
                int  num   = 0;
                bool flag3 = true;
                while (flag3)
                {
                    int num2 = -1;
                    for (int j = 0; j < triangles.Count; j++)
                    {
                        bool flag4 = array[j];
                        if (!flag4)
                        {
                            num2 = j;
                            break;
                        }
                    }
                    bool flag5 = num2 == -1;
                    if (flag5)
                    {
                        flag3 = false;
                    }
                    else
                    {
                        Vertices vertices2 = new Vertices(3);
                        for (int k = 0; k < 3; k++)
                        {
                            vertices2.Add(triangles[num2][k]);
                        }
                        array[num2] = true;
                        int l = 0;
                        int m = 0;
                        while (m < 2 * triangles.Count)
                        {
                            while (l >= triangles.Count)
                            {
                                l -= triangles.Count;
                            }
                            bool flag6 = array[l];
                            if (!flag6)
                            {
                                Vertices vertices3 = SimpleCombiner.AddTriangle(triangles[l], vertices2);
                                bool     flag7     = vertices3 == null;
                                if (!flag7)
                                {
                                    bool flag8 = vertices3.Count > Settings.MaxPolygonVertices;
                                    if (!flag8)
                                    {
                                        bool flag9 = vertices3.IsConvex();
                                        if (flag9)
                                        {
                                            vertices2 = new Vertices(vertices3);
                                            array[l]  = true;
                                        }
                                    }
                                }
                            }
                            m++;
                            l++;
                        }
                        bool flag10 = num < maxPolys;
                        if (flag10)
                        {
                            SimplifyTools.MergeParallelEdges(vertices2, tolerance);
                            bool flag11 = vertices2.Count >= 3;
                            if (flag11)
                            {
                                list.Add(new Vertices(vertices2));
                            }
                            else
                            {
                                Debug.WriteLine("Skipping corrupt poly.");
                            }
                        }
                        bool flag12 = vertices2.Count >= 3;
                        if (flag12)
                        {
                            num++;
                        }
                    }
                }
                for (int n = list.Count - 1; n >= 0; n--)
                {
                    bool flag13 = list[n].Count == 0;
                    if (flag13)
                    {
                        list.RemoveAt(n);
                    }
                }
                result = list;
            }
            return(result);
        }
        /// <summary>
        /// Calculates the polygon(s) from the result simplical chain.
        /// </summary>
        /// <remarks>Used by method <c>Execute()</c>.</remarks>
        private static PolyClipError BuildPolygonsFromChain(List <Edge> simplicies, out List <Vertices> result)
        {
            result = new List <Vertices>();
            PolyClipError errVal = PolyClipError.None;

            while (simplicies.Count > 0)
            {
                Vertices output = new Vertices();
                output.Add(simplicies[0].EdgeStart);
                output.Add(simplicies[0].EdgeEnd);
                simplicies.RemoveAt(0);
                bool closed = false;
                int  index  = 0;
                int  count  = simplicies.Count; // Needed to catch infinite loops
                while (!closed && simplicies.Count > 0)
                {
                    if (VectorEqual(output[output.Count - 1], simplicies[index].EdgeStart))
                    {
                        if (VectorEqual(simplicies[index].EdgeEnd, output[0]))
                        {
                            closed = true;
                        }
                        else
                        {
                            output.Add(simplicies[index].EdgeEnd);
                        }
                        simplicies.RemoveAt(index);
                        --index;
                    }
                    else if (VectorEqual(output[output.Count - 1], simplicies[index].EdgeEnd))
                    {
                        if (VectorEqual(simplicies[index].EdgeStart, output[0]))
                        {
                            closed = true;
                        }
                        else
                        {
                            output.Add(simplicies[index].EdgeStart);
                        }
                        simplicies.RemoveAt(index);
                        --index;
                    }
                    if (!closed)
                    {
                        if (++index == simplicies.Count)
                        {
                            if (count == simplicies.Count)
                            {
                                result = new List <Vertices>();
                                Debug.WriteLine("Undefined error while building result polygon(s).");
                                return(PolyClipError.BrokenResult);
                            }
                            index = 0;
                            count = simplicies.Count;
                        }
                    }
                }
                if (output.Count < 3)
                {
                    errVal = PolyClipError.DegeneratedOutput;
                    Debug.WriteLine("Degenerated output polygon produced (vertices < 3).");
                }
                result.Add(output);
            }
            return(errVal);
        }
Пример #20
0
        public static Vertices CreateCapsule(FP height, FP topRadius, int topEdges, FP bottomRadius, int bottomEdges)
        {
            bool flag = height <= 0;

            if (flag)
            {
                throw new ArgumentException("Height must be longer than 0", "height");
            }
            bool flag2 = topRadius <= 0;

            if (flag2)
            {
                throw new ArgumentException("The top radius must be more than 0", "topRadius");
            }
            bool flag3 = topEdges <= 0;

            if (flag3)
            {
                throw new ArgumentException("Top edges must be more than 0", "topEdges");
            }
            bool flag4 = bottomRadius <= 0;

            if (flag4)
            {
                throw new ArgumentException("The bottom radius must be more than 0", "bottomRadius");
            }
            bool flag5 = bottomEdges <= 0;

            if (flag5)
            {
                throw new ArgumentException("Bottom edges must be more than 0", "bottomEdges");
            }
            bool flag6 = topRadius >= height / 2;

            if (flag6)
            {
                throw new ArgumentException("The top radius must be lower than height / 2. Higher values of top radius would create a circle, and not a half circle.", "topRadius");
            }
            bool flag7 = bottomRadius >= height / 2;

            if (flag7)
            {
                throw new ArgumentException("The bottom radius must be lower than height / 2. Higher values of bottom radius would create a circle, and not a half circle.", "bottomRadius");
            }
            Vertices vertices = new Vertices();
            FP       fP       = (height - topRadius - bottomRadius) * 0.5f;

            vertices.Add(new TSVector2(topRadius, fP));
            FP x = MathHelper.Pi / topEdges;

            for (int i = 1; i < topEdges; i++)
            {
                vertices.Add(new TSVector2(topRadius * FP.Cos(x * i), topRadius * FP.Sin(x * i) + fP));
            }
            vertices.Add(new TSVector2(-topRadius, fP));
            vertices.Add(new TSVector2(-bottomRadius, -fP));
            x = MathHelper.Pi / bottomEdges;
            for (int j = 1; j < bottomEdges; j++)
            {
                vertices.Add(new TSVector2(-bottomRadius * FP.Cos(x * j), -bottomRadius * FP.Sin(x * j) - fP));
            }
            vertices.Add(new TSVector2(bottomRadius, -fP));
            return(vertices);
        }
Пример #21
0
        /// <summary>
        /// Activate the explosion at the specified position.
        /// </summary>
        /// <param name="pos">The position where the explosion happens </param>
        /// <param name="radius">The explosion radius </param>
        /// <param name="maxForce">The explosion force at the explosion point (then is inversely proportional to the square of the distance)</param>
        /// <returns>A list of bodies and the amount of force that was applied to them.</returns>
        public Dictionary <Fixture, TSVector2> Activate(TSVector2 pos, FP radius, FP maxForce)
        {
            AABB aabb;

            aabb.LowerBound = pos + new TSVector2(-radius, -radius);
            aabb.UpperBound = pos + new TSVector2(radius, radius);
            Fixture[] shapes = new Fixture[MaxShapes];

            // More than 5 shapes in an explosion could be possible, but still strange.
            Fixture[] containedShapes = new Fixture[5];
            bool      exit            = false;

            int shapeCount          = 0;
            int containedShapeCount = 0;

            // Query the world for overlapping shapes.
            World.QueryAABB(
                fixture =>
            {
                if (fixture.TestPoint(ref pos))
                {
                    if (IgnoreWhenInsideShape)
                    {
                        exit = true;
                        return(false);
                    }

                    containedShapes[containedShapeCount++] = fixture;
                }
                else
                {
                    shapes[shapeCount++] = fixture;
                }

                // Continue the query.
                return(true);
            }, ref aabb);

            if (exit)
            {
                return(new Dictionary <Fixture, TSVector2>());
            }

            Dictionary <Fixture, TSVector2> exploded = new Dictionary <Fixture, TSVector2>(shapeCount + containedShapeCount);

            // Per shape max/min angles for now.
            FP[] vals     = new FP[shapeCount * 2];
            int  valIndex = 0;

            for (int i = 0; i < shapeCount; ++i)
            {
                PolygonShape ps;
                CircleShape  cs = shapes[i].Shape as CircleShape;
                if (cs != null)
                {
                    // We create a "diamond" approximation of the circle
                    Vertices  v   = new Vertices();
                    TSVector2 vec = TSVector2.zero + new TSVector2(cs.Radius, 0);
                    v.Add(vec);
                    vec = TSVector2.zero + new TSVector2(0, cs.Radius);
                    v.Add(vec);
                    vec = TSVector2.zero + new TSVector2(-cs.Radius, cs.Radius);
                    v.Add(vec);
                    vec = TSVector2.zero + new TSVector2(0, -cs.Radius);
                    v.Add(vec);
                    ps = new PolygonShape(v, 0);
                }
                else
                {
                    ps = shapes[i].Shape as PolygonShape;
                }

                if ((shapes[i].Body.BodyType == BodyType.Dynamic) && ps != null)
                {
                    TSVector2 toCentroid      = shapes[i].Body.GetWorldPoint(ps.MassData.Centroid) - pos;
                    FP        angleToCentroid = FP.Atan2(toCentroid.y, toCentroid.x);
                    FP        min             = FP.MaxValue;
                    FP        max             = FP.MinValue;
                    FP        minAbsolute     = 0.0f;
                    FP        maxAbsolute     = 0.0f;

                    for (int j = 0; j < ps.Vertices.Count; ++j)
                    {
                        TSVector2 toVertex = (shapes[i].Body.GetWorldPoint(ps.Vertices[j]) - pos);
                        FP        newAngle = FP.Atan2(toVertex.y, toVertex.x);
                        FP        diff     = (newAngle - angleToCentroid);

                        diff = (diff - FP.Pi) % (2 * FP.Pi);
                        // the minus pi is important. It means cutoff for going other direction is at 180 deg where it needs to be

                        if (diff < 0.0f)
                        {
                            diff += 2 * FP.Pi; // correction for not handling negs
                        }
                        diff -= FP.Pi;

                        if (FP.Abs(diff) > FP.Pi)
                        {
                            continue; // Something's wrong, point not in shape but exists angle diff > 180
                        }
                        if (diff > max)
                        {
                            max         = diff;
                            maxAbsolute = newAngle;
                        }
                        if (diff < min)
                        {
                            min         = diff;
                            minAbsolute = newAngle;
                        }
                    }

                    vals[valIndex] = minAbsolute;
                    ++valIndex;
                    vals[valIndex] = maxAbsolute;
                    ++valIndex;
                }
            }

            Array.Sort(vals, 0, valIndex, _rdc);
            _data.Clear();
            bool rayMissed = true;

            for (int i = 0; i < valIndex; ++i)
            {
                Fixture fixture = null;
                FP      midpt;

                int iplus = (i == valIndex - 1 ? 0 : i + 1);
                if (vals[i] == vals[iplus])
                {
                    continue;
                }

                if (i == valIndex - 1)
                {
                    // the single edgecase
                    midpt = (vals[0] + FP.PiTimes2 + vals[i]);
                }
                else
                {
                    midpt = (vals[i + 1] + vals[i]);
                }

                midpt = midpt / 2;

                TSVector2 p1 = pos;
                TSVector2 p2 = radius * new TSVector2(FP.Cos(midpt), FP.Sin(midpt)) + pos;

                // RaycastOne
                bool hitClosest = false;
                World.RayCast((f, p, n, fr) =>
                {
                    Body body = f.Body;

                    if (!IsActiveOn(body))
                    {
                        return(0);
                    }

                    hitClosest = true;
                    fixture    = f;
                    return(fr);
                }, p1, p2);

                //draws radius points
                if ((hitClosest) && (fixture.Body.BodyType == BodyType.Dynamic))
                {
                    if ((_data.Any()) && (_data.Last().Body == fixture.Body) && (!rayMissed))
                    {
                        int       laPos = _data.Count - 1;
                        ShapeData la    = _data[laPos];
                        la.Max       = vals[iplus];
                        _data[laPos] = la;
                    }
                    else
                    {
                        // make new
                        ShapeData d;
                        d.Body = fixture.Body;
                        d.Min  = vals[i];
                        d.Max  = vals[iplus];
                        _data.Add(d);
                    }

                    if ((_data.Count > 1) &&
                        (i == valIndex - 1) &&
                        (_data.Last().Body == _data.First().Body) &&
                        (_data.Last().Max == _data.First().Min))
                    {
                        ShapeData fi = _data[0];
                        fi.Min = _data.Last().Min;
                        _data.RemoveAt(_data.Count - 1);
                        _data[0] = fi;
                        while (_data.First().Min >= _data.First().Max)
                        {
                            fi.Min  -= FP.PiTimes2;
                            _data[0] = fi;
                        }
                    }

                    int       lastPos = _data.Count - 1;
                    ShapeData last    = _data[lastPos];
                    while ((_data.Count > 0) &&
                           (_data.Last().Min >= _data.Last().Max))    // just making sure min<max
                    {
                        last.Min       = _data.Last().Min - FP.PiTimes2;
                        _data[lastPos] = last;
                    }
                    rayMissed = false;
                }
                else
                {
                    rayMissed = true; // raycast did not find a shape
                }
            }

            for (int i = 0; i < _data.Count; ++i)
            {
                if (!IsActiveOn(_data[i].Body))
                {
                    continue;
                }

                FP arclen = _data[i].Max - _data[i].Min;

                FP  first        = TSMath.Min(MaxEdgeOffset, EdgeRatio * arclen);
                int insertedRays = FP.Ceiling((((arclen - 2.0f * first) - (MinRays - 1) * MaxAngle) / MaxAngle)).AsInt();

                if (insertedRays < 0)
                {
                    insertedRays = 0;
                }

                FP offset = (arclen - first * 2.0f) / ((FP)MinRays + insertedRays - 1);

                //Note: This loop can go into infinite as it operates on FPs.
                //Added FPEquals with a large epsilon.
                for (FP j = _data[i].Min + first;
                     j < _data[i].Max || MathUtils.FPEquals(j, _data[i].Max, 0.0001f);
                     j += offset)
                {
                    TSVector2 p1        = pos;
                    TSVector2 p2        = pos + radius * new TSVector2(FP.Cos(j), FP.Sin(j));
                    TSVector2 hitpoint  = TSVector2.zero;
                    FP        minlambda = FP.MaxValue;

                    List <Fixture> fl = _data[i].Body.FixtureList;
                    for (int x = 0; x < fl.Count; x++)
                    {
                        Fixture      f = fl[x];
                        RayCastInput ri;
                        ri.Point1      = p1;
                        ri.Point2      = p2;
                        ri.MaxFraction = 50f;

                        RayCastOutput ro;
                        if (f.RayCast(out ro, ref ri, 0))
                        {
                            if (minlambda > ro.Fraction)
                            {
                                minlambda = ro.Fraction;
                                hitpoint  = ro.Fraction * p2 + (1 - ro.Fraction) * p1;
                            }
                        }

                        // the force that is to be applied for this particular ray.
                        // offset is angular coverage. lambda*length of segment is distance.
                        FP impulse = (arclen / (MinRays + insertedRays)) * maxForce * 180.0f / FP.Pi * (1.0f - TrueSync.TSMath.Min(FP.One, minlambda));

                        // We Apply the impulse!!!
                        TSVector2 vectImp = TSVector2.Dot(impulse * new TSVector2(FP.Cos(j), FP.Sin(j)), -ro.Normal) * new TSVector2(FP.Cos(j), FP.Sin(j));
                        _data[i].Body.ApplyLinearImpulse(ref vectImp, ref hitpoint);

                        // We gather the fixtures for returning them
                        if (exploded.ContainsKey(f))
                        {
                            exploded[f] += vectImp;
                        }
                        else
                        {
                            exploded.Add(f, vectImp);
                        }

                        if (minlambda > 1.0f)
                        {
                            hitpoint = p2;
                        }
                    }
                }
            }

            // We check contained shapes
            for (int i = 0; i < containedShapeCount; ++i)
            {
                Fixture fix = containedShapes[i];

                if (!IsActiveOn(fix.Body))
                {
                    continue;
                }

                FP        impulse = MinRays * maxForce * 180.0f / FP.Pi;
                TSVector2 hitPoint;

                CircleShape circShape = fix.Shape as CircleShape;
                if (circShape != null)
                {
                    hitPoint = fix.Body.GetWorldPoint(circShape.Position);
                }
                else
                {
                    PolygonShape shape = fix.Shape as PolygonShape;
                    hitPoint = fix.Body.GetWorldPoint(shape.MassData.Centroid);
                }

                TSVector2 vectImp = impulse * (hitPoint - pos);

                fix.Body.ApplyLinearImpulse(ref vectImp, ref hitPoint);

                if (!exploded.ContainsKey(fix))
                {
                    exploded.Add(fix, vectImp);
                }
            }

            return(exploded);
        }