// A parent is a shape which fully contains another shape
        public bool IsParentOf(CompositeShapeData otherShape)
        {
            if (otherShape.parents.Contains(this))
            {
                return(true);
            }
            if (parents.Contains(otherShape))
            {
                return(false);
            }

            // check if first point in otherShape is inside this shape. If not, parent test fails.
            // if yes, then continue to line seg intersection test between the two shapes

            // (this point test is important because without it, if all line seg intersection tests fail,
            // we wouldn't know if otherShape is entirely inside or entirely outside of this shape)
            bool pointInsideShape = false;

            for (int i = 0; i < triangles.Length; i += 3)
            {
                if (Maths2D.PointInTriangle(polygon.points[triangles[i]], polygon.points[triangles[i + 1]], polygon.points[triangles[i + 2]], otherShape.points[0]))
                {
                    pointInsideShape = true;
                    break;
                }
            }

            if (!pointInsideShape)
            {
                return(false);
            }

            // Check for intersections between line segs of this shape and otherShape (any intersections will fail the parent test)
            for (int i = 0; i < points.Length; i++)
            {
                LineSegment parentSeg = new LineSegment(points[i], points[(i + 1) % points.Length]);
                for (int j = 0; j < otherShape.points.Length; j++)
                {
                    LineSegment childSeg = new LineSegment(otherShape.points[j], otherShape.points[(j + 1) % otherShape.points.Length]);
                    if (Maths2D.LineSegmentsIntersect(parentSeg.a, parentSeg.b, childSeg.a, childSeg.b))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
 // Test if the shapes overlap partially (test will fail if one shape entirely contains other shape, i.e. one is parent of the other).
 public bool OverlapsPartially(CompositeShapeData otherShape)
 {
     // Check for intersections between line segs of this shape and otherShape (any intersection will validate the overlap test)
     for (int i = 0; i < points.Length; i++)
     {
         LineSegment segA = new LineSegment(points[i], points[(i + 1) % points.Length]);
         for (int j = 0; j < otherShape.points.Length; j++)
         {
             LineSegment segB = new LineSegment(otherShape.points[j], otherShape.points[(j + 1) % otherShape.points.Length]);
             if (Maths2D.LineSegmentsIntersect(segA.a, segA.b, segB.a, segB.b))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
 // Checks if any of the line segments making up this shape intersect
 public bool IntersectsWithSelf()
 {
     for (int i = 0; i < points.Length; i++)
     {
         LineSegment segA = new LineSegment(points[i], points[(i + 1) % points.Length]);
         for (int j = i + 2; j < points.Length; j++)
         {
             if ((j + 1) % points.Length == i)
             {
                 continue;
             }
             LineSegment segB = new LineSegment(points[j], points[(j + 1) % points.Length]);
             if (Maths2D.LineSegmentsIntersect(segA.a, segA.b, segB.a, segB.b))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
    void SetInnerRing(Vector3[] verts, List <Vector3> validQuads, List <Vector3> validTris)
    {
        bool isClosed = verts[0] == verts[verts.Length - 1];

        Vector2[] points = new List <Vector2>(verts.Select(v => new Vector2(v.x, v.z))).GetRange(0, verts.Count() - (isClosed ? 1 : 0)).ToArray();

        debugList = new List <Vector3>();
        List <Vector3> pathVerts = new List <Vector3>();

        if (points.Length >= 3)
        {
            Polygon polygon   = new Polygon(points);
            int[]   triangles = new Triangulator(polygon).Triangulate();

            Vector3 min = GetScaledMin();
            for (float i = min.x; i < bounds.max.x; i += gridScale)
            {
                for (float j = min.z; j < bounds.max.z; j += gridScale)
                {
                    bool intersects1  = false;
                    bool intersects2  = false;
                    bool intersects34 = false;
                    for (int k = 0; k < outerRing.Count - 1; k++)
                    {
                        if (Maths2D.LineSegmentsIntersect(new Vector2(i, j), new Vector2(i + gridScale, j), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z)))
                        {
                            intersects1 = true;
                            break;
                        }
                        if (Maths2D.LineSegmentsIntersect(new Vector2(i, j), new Vector2(i, j + gridScale), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z)))
                        {
                            intersects2 = true;
                            break;
                        }
                        if (Maths2D.LineSegmentsIntersect(new Vector2(i + gridScale, j), new Vector2(i + gridScale, j + gridScale), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z)) ||
                            Maths2D.LineSegmentsIntersect(new Vector2(i, j + gridScale), new Vector2(i + gridScale, j + gridScale), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z)))
                        {
                            intersects34 = true;
                        }
                    }
                    if (intersects1)
                    {
                        if (PointInTriangles(polygon.points, triangles, new Vector2(i, j)))
                        {
                            pathVerts.Add(new Vector3(i, pathHeight, j));
                        }
                        if (PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j)))
                        {
                            pathVerts.Add(new Vector3(i + gridScale, pathHeight, j));
                        }
                    }
                    else if (intersects2)
                    {
                        if (PointInTriangles(polygon.points, triangles, new Vector2(i, j)))
                        {
                            pathVerts.Add(new Vector3(i, pathHeight, j));
                        }
                        if (PointInTriangles(polygon.points, triangles, new Vector2(i, j + gridScale)))
                        {
                            pathVerts.Add(new Vector3(i, pathHeight, j + gridScale));
                        }
                    }
                    else if (!intersects34 && PointInTriangles(polygon.points, triangles, new Vector2(i, j)))
                    {
                        validQuads.Add(new Vector3(i, pathHeight, j));
                    }
                    if (intersects1 || intersects2 || intersects34)
                    {
                        List <Vector3> possibleTris = new List <Vector3>();

                        if (PointInTriangles(polygon.points, triangles, new Vector2(i, j)))
                        {
                            possibleTris.Add(new Vector3(i, pathHeight, j));
                        }
                        if (PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j)))
                        {
                            possibleTris.Add(new Vector3(i + gridScale, pathHeight, j));
                        }
                        if (PointInTriangles(polygon.points, triangles, new Vector2(i, j + gridScale)))
                        {
                            possibleTris.Add(new Vector3(i, pathHeight, j + gridScale));
                        }
                        if (PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j + gridScale)))
                        {
                            possibleTris.Add(new Vector3(i + gridScale, pathHeight, j + gridScale));
                        }

                        if (possibleTris.Count == 3)
                        {
                            validTris.AddRange(possibleTris);
                        }
                        if (possibleTris.Count == 2)
                        {
                            if (!possibleTris.Contains(new Vector3(i, pathHeight, j)) && !possibleTris.Contains(new Vector3(i + gridScale, pathHeight, j)) && PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale + gridScale, j)))
                            {
                                pathVerts.Add(possibleTris[1]);
                                //validTris.AddRange(new Vector3[] { possibleTris[0], possibleTris[1], new Vector3(i + gridScale + gridScale, 0, j) });
                            }

                            /*
                             * if (!possibleTris.Contains(new Vector3(i + gridScale, 0, j)) && !possibleTris.Contains(new Vector3(i + gridScale, 0, j + gridScale)) &&
                             *  PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j - gridScale)) && !PointInTriangles(polygon.points, triangles, new Vector2(i, j + gridScale + gridScale))) {
                             *  //validTris.AddRange(new Vector3[] { possibleTris[0], possibleTris[1], new Vector3(i + gridScale, 0, j - gridScale) });
                             * }*/
                        }
                    }
                }
            }

            pathVerts = Utility.TrimDuplicates(pathVerts);

            innerRing = new List <Vector3> {
                pathVerts[0]
            };

            Vector3 previous     = pathVerts[0];
            int     reverseCount = pathVerts.Count;
            //if (debug) debugList.Add(pathVerts[0]);
            pathVerts.RemoveAt(0);

            while (pathVerts.Count > 0 && reverseCount > 0)
            {
                Vector3 closest = previous;
                foreach (Vector3 vert in pathVerts)
                {
                    if (Vector3.Distance(previous, vert) < gridScale * 1.1f)
                    {
                        closest = vert;
                        break;
                    }
                }
                if (closest == previous)
                {
                    foreach (Vector3 vert in pathVerts)
                    {
                        if (Vector3.Distance(previous, vert) < gridScale * 1.5f)
                        {
                            closest = vert;
                            break;
                        }
                    }
                }
                if (closest != previous)
                {
                    innerRing.Add(closest);
                    pathVerts.Remove(closest);
                    if (debug)
                    {
                        debugList.Add(closest);
                    }
                    previous = closest;
                }
                else
                {
                    --reverseCount;
                    innerRing.Reverse();
                    previous = innerRing[innerRing.Count - 1];
                }
            }

            if (pathVerts.Count > 0)
            {
                for (int i = 0; i < pathVerts.Count; i++)
                {
                    debugSegList.Add(new LineSegment(pathVerts[i], pathVerts[i] + Vector3.up * 10));
                }
                innerRing.AddRange(pathVerts);
                print("Verts Left: " + pathVerts.Count);
            }
            if (Vector3.Distance(innerRing[0], Utility.NoY(outerRing[0])) > gridScale * 1.5f && !isClosed)
            {
                innerRing.Reverse();
            }
        }
    }