/**
         *  @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));
        }
        /**
         *  @brief Create the internal shape used to represent a PolygonCollider.
         **/
        public override SyncFrame.Physics2D.Shape[] CreateShapes()
        {
            if (_points == null || _points.Length == 0)
            {
                return(null);
            }


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

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

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

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

            return(result);
        }
Beispiel #3
0
        /// <summary>
        /// Combine a list of triangles into a list of convex polygons.
        ///
        /// Note: This only works on triangles.
        /// </summary>
        ///<param name="triangles">The triangles.</param>
        ///<param name="maxPolys">The maximun number of polygons to return.</param>
        ///<param name="tolerance">The tolerance</param>
        public static List <Vertices> PolygonizeTriangles(List <Vertices> triangles, int maxPolys = int.MaxValue, float tolerance = 0.001f)
        {
            if (triangles.Count <= 0)
            {
                return(triangles);
            }

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

            bool[] covered = new bool[triangles.Count];
            for (int i = 0; i < triangles.Count; ++i)
            {
                covered[i] = false;

                //Check here for degenerate triangles
                Vertices  triangle = triangles[i];
                TSVector2 a        = triangle[0];
                TSVector2 b        = triangle[1];
                TSVector2 c        = triangle[2];

                if ((a.x == b.x && a.y == b.y) || (b.x == c.x && b.y == c.y) || (a.x == c.x && a.y == c.y))
                {
                    covered[i] = true;
                }
            }

            int polyIndex = 0;

            bool notDone = true;

            while (notDone)
            {
                int currTri = -1;
                for (int i = 0; i < triangles.Count; ++i)
                {
                    if (covered[i])
                    {
                        continue;
                    }

                    currTri = i;
                    break;
                }

                if (currTri == -1)
                {
                    notDone = false;
                }
                else
                {
                    Vertices poly = new Vertices(3);

                    for (int i = 0; i < 3; i++)
                    {
                        poly.Add(triangles[currTri][i]);
                    }

                    covered[currTri] = true;
                    int index = 0;
                    for (int i = 0; i < 2 * triangles.Count; ++i, ++index)
                    {
                        while (index >= triangles.Count)
                        {
                            index -= triangles.Count;
                        }
                        if (covered[index])
                        {
                            continue;
                        }
                        Vertices newP = AddTriangle(triangles[index], poly);
                        if (newP == null)
                        {
                            continue; // is this right
                        }
                        if (newP.Count > Settings.MaxPolygonVertices)
                        {
                            continue;
                        }

                        if (newP.IsConvex())
                        {
                            //Or should it be IsUsable?  Maybe re-write IsConvex to apply the angle threshold from Box2d
                            poly           = new Vertices(newP);
                            covered[index] = true;
                        }
                    }

                    //We have a maximum of polygons that we need to keep under.
                    if (polyIndex < maxPolys)
                    {
                        SimplifyTools.MergeParallelEdges(poly, tolerance);

                        //If identical points are present, a triangle gets
                        //borked by the MergeParallelEdges function, hence
                        //the vertex number check
                        if (poly.Count >= 3)
                        {
                            polys.Add(new Vertices(poly));
                        }
                        else
                        {
                            Debug.WriteLine("Skipping corrupt poly.");
                        }
                    }

                    if (poly.Count >= 3)
                    {
                        polyIndex++; //Must be outside (polyIndex < polysLength) test
                    }
                }
            }

            //TODO: Add sanity check
            //Remove empty vertice collections
            for (int i = polys.Count - 1; i >= 0; i--)
            {
                if (polys[i].Count == 0)
                {
                    polys.RemoveAt(i);
                }
            }

            return(polys);
        }
Beispiel #4
0
        private static Vertices AddTriangle(Vertices t, Vertices vertices)
        {
            // First, find vertices that connect
            int firstP  = -1;
            int firstT  = -1;
            int secondP = -1;
            int secondT = -1;

            for (int i = 0; i < vertices.Count; i++)
            {
                if (t[0].x == vertices[i].x && t[0].y == vertices[i].y)
                {
                    if (firstP == -1)
                    {
                        firstP = i;
                        firstT = 0;
                    }
                    else
                    {
                        secondP = i;
                        secondT = 0;
                    }
                }
                else if (t[1].x == vertices[i].x && t[1].y == vertices[i].y)
                {
                    if (firstP == -1)
                    {
                        firstP = i;
                        firstT = 1;
                    }
                    else
                    {
                        secondP = i;
                        secondT = 1;
                    }
                }
                else if (t[2].x == vertices[i].x && t[2].y == vertices[i].y)
                {
                    if (firstP == -1)
                    {
                        firstP = i;
                        firstT = 2;
                    }
                    else
                    {
                        secondP = i;
                        secondT = 2;
                    }
                }
            }
            // Fix ordering if first should be last vertex of poly
            if (firstP == 0 && secondP == vertices.Count - 1)
            {
                firstP  = vertices.Count - 1;
                secondP = 0;
            }

            // Didn't find it
            if (secondP == -1)
            {
                return(null);
            }

            // Find tip index on triangle
            int tipT = 0;

            if (tipT == firstT || tipT == secondT)
            {
                tipT = 1;
            }
            if (tipT == firstT || tipT == secondT)
            {
                tipT = 2;
            }

            Vertices result = new Vertices(vertices.Count + 1);

            for (int i = 0; i < vertices.Count; i++)
            {
                result.Add(vertices[i]);

                if (i == firstP)
                {
                    result.Add(t[tipT]);
                }
            }

            return(result);
        }
Beispiel #5
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);
        }