Пример #1
0
        /// <summary>
        /// Checks if the other group's outer perimeter is inside this group's perimeter.  Inclusive of the two groups
        /// sharing vertices.
        /// </summary>
        /// <param name="otherGroup"></param>
        /// <returns>True if the other group is inside this group, false otherwise.</returns>
        public bool IsOtherGroupInThisGroup(ConnectedNodeGroup otherGroup)
        {
            HashSet <Vector2> sharedVertices = this.GetSharedVertices(otherGroup);

            if (sharedVertices.Count == 0)
            {
                return(GeometryFuncs.IsPolyInPoly(otherGroup.outerPerimSimplified, this.outerPerimSimplified));
            }
            else
            {
                bool isInside = true;
                foreach (PolygonSplittingGraphNode node in otherGroup.nodes.Values)
                {
                    var nodeCoord = new Vector2(node.x, node.y);
                    if (sharedVertices.Contains(nodeCoord))
                    {
                        continue;
                    }
                    if (!GeometryFuncs.IsPointInPoly(nodeCoord, this.outerPerimSimplified))
                    {
                        isInside = false;
                        break;
                    }
                }
                return(isInside);
            }
        }
Пример #2
0
        /// <summary>
        /// Checks which potential holes could be contained within this polygon and adds them
        /// to holes if they pass the IsPolyInPoly check.
        /// </summary>
        /// <param name="potentialHoles"></param>
        /// <returns></returns>
        private List <Vector2>[] _GetContainedHoles(List <Vector2>[] potentialHoles)
        {
            var confirmedHoles = new List <List <Vector2> >();

            foreach (List <Vector2> hole in potentialHoles)
            {
                HashSet <Vector2> sharedVertices;
                if (GeometryFuncs.IsPolyInPoly(hole.ToArray(), this._outerPerim))
                {
                    confirmedHoles.Add(hole);
                }
                else if ((sharedVertices = this._GetHoleSharedVertices(hole)).Count > 0)
                {
                    int holeVerticesInPoly = 0; //guilty until proven innocent, to prevent snake poly from containing hole
                    foreach (Vector2 holeVertex in hole)
                    {
                        if (sharedVertices.Contains(holeVertex))
                        {
                            continue;
                        }
                        if (GeometryFuncs.IsPointInPoly(holeVertex, this._outerPerim) &&
                            !GeometryFuncs.IsPointOnPolyBoundary(holeVertex, this._outerPerim))
                        {
                            holeVerticesInPoly++;
                        }
                    }
                    if (holeVerticesInPoly > 0)
                    {
                        confirmedHoles.Add(hole);
                    }
                }
            }
            return(confirmedHoles.ToArray());
        }
        /// <summary>
        /// Checks if a segment between two vertexes is a valid chord, which relies on the following conditions:
        /// 0. The segment is not in the chords array already (with/without reversed points)
        /// 1. The vertices are different
        /// 2. The segment is vertical or horizontal
        /// 3. The segment does not CONTAIN a part of the polygon's outer perimeter OR hole perimeter(s).
        /// 4 WHICH I FORGOT. The segment does not intersect any part of the perimeter
        /// 5 WHICH I ALSO FORGOT. The segment is actually within the polygon.
        /// </summary>
        /// <param name="pointA"></param>
        /// <param name="pointB"></param>
        /// <param name="allIsoPerims"></param>
        /// <param name="chords"></param>
        /// <returns></returns>
        private static bool _IsChordValid(Vector2 pointA, Vector2 pointB, List <Vector2>[] allIsoPerims,
                                          IEnumerable <Chord> chords)
        {
            if (chords.Any(chord => (chord.a == pointA && chord.b == pointB) || (chord.a == pointB && chord.b == pointA)))
            { //if not already in chords array
                return(false);
            }

            if (pointA == pointB)
            {
                return(false);                  //if vertices are different
            }
            if (pointA.x != pointB.x && pointA.y != pointB.y)
            {
                return(false);                                              //if the segment is vertical or horizontal
            }
            Vector2 midpoint = (pointB - pointA) / 2 + pointA;

            for (int i = 0; i < allIsoPerims.Length; i++)
            {
                List <Vector2> perims = allIsoPerims[i];
                if (i == 0)
                { //midpoint not in poly
                    if (!GeometryFuncs.IsPointInPoly(midpoint, perims.ToArray()))
                    {
                        return(false);
                    }
                }
                else
                { //midpoint in hole
                    if (GeometryFuncs.IsPointInPoly(midpoint, perims.ToArray()))
                    {
                        return(false);
                    }
                }
                for (int j = 0; j < perims.Count - 1; j++) //i < perims.Count - 1 because perims[0] = perims[last]
                {                                          //if segment does not contain a part of the polygon's perimeter(s)
                    Vector2 perimVertexA = perims[j];
                    Vector2 perimVertexB = perims[j + 1];
                    if (GeometryFuncs.DoSegmentsOverlap(pointA, pointB, perimVertexA, perimVertexB))
                    { //segment confirmed to contain part of polygon's perimeter(s)
                        return(false);
                    }
                    if (perimVertexA != pointA && perimVertexA != pointB && perimVertexB != pointA && perimVertexB != pointB)
                    {
                        if (GeometryFuncs.DoSegmentsIntersect(pointA, pointB, perimVertexA, perimVertexB))
                        { //segment intersects part of perimeter
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }