Beispiel #1
0
        /// <summary>
        /// A implementation of the Weiler-Atherthon algorithm that cuts away the provided clippling area from the subject polygon.
        /// Assumes the cutting polygon is not entirely inside subject polygon!
        /// </summary>
        /// <param name="a_subject"></param>
        /// <param name="a_clip"></param>
        /// <returns></returns>
        public static MultiPolygon2D CutOut(Polygon2D a_subject, Polygon2D a_clip)
        {
            // copy and maybe reverse
            if (a_subject.IsClockwise())
            {
                a_subject = new Polygon2D(a_subject.Vertices);
            }
            else
            {
                a_subject = new Polygon2D(a_subject.Vertices.Reverse());
            }

            if (a_clip.IsClockwise())
            {
                a_clip = new Polygon2D(a_clip.Vertices);
            }
            else
            {
                a_clip = new Polygon2D(a_clip.Vertices.Reverse());
            }


            var WA = new WeilerAtherton(a_subject, a_clip);

            //return new MultiPolygon2D();
            return(WeilerAthertonCutOut(WA));
        }
Beispiel #2
0
        /// <summary>
        /// Creates a cutout given the relevant weiler atherton object containing subject and clipping lists
        /// Can result in multiple polygons.
        /// Assumes the cutting polygon is not entirely inside subject polygon!
        /// </summary>
        /// <param name="WA"></param>
        /// <returns></returns>
        private static MultiPolygon2D WeilerAthertonCutOut(WeilerAtherton WA)
        {
            var multiPoly = new MultiPolygon2D();

            // check if polygons have intersections
            if (WA.EntryIntersections.Count == 0)
            {
                if (!WA.Subject.Vertices.ToList().Exists(p => WA.Clip.ContainsInside(p)))
                {
                    multiPoly.AddPolygon(new Polygon2D(WA.Subject.Vertices));
                }
            }

            while (WA.EntryIntersections.Count > 0)
            {
                var vertices = new List <Vector2>();
                var visited  = new HashSet <LinkedListNode <WAPoint> >();

                // remove an entry intersection point
                var startPoint = WA.EntryIntersections.LastOrDefault();
                WA.EntryIntersections.Remove(startPoint);

                LinkedListNode <WAPoint> node;
                try
                {
                    node = WA.ClipNode[startPoint];
                }
                catch (KeyNotFoundException e)
                {
                    Debug.Log("entry point not found: " + e);
                    continue;
                }

                WAPoint last = null;

                while (!visited.Contains(node))
                {
                    // remove entry intersection from starting list
                    WA.EntryIntersections.Remove(node.Value);

                    // traverse clip polygon in counter-clockwise order until exit vertex found
                    while (node.Value.Type != WAList.Exit && !visited.Contains(node))
                    {
                        // check for duplicates
                        if (last == null || !MathUtil.EqualsEps(node.Value.Pos, last.Pos))
                        {
                            vertices.Add(node.Value.Pos);
                            visited.Add(node);
                        }
                        last = node.Value;
                        node = node.Previous ?? WA.ClipList.Last;
                    }

                    // might contains entry but no exit vertex
                    // should not occur, return no polygon
                    if (visited.Contains(node))
                    {
                        vertices.Clear(); break;
                    }

                    try
                    {
                        node = WA.SubjectNode[node.Value];
                    }
                    catch (KeyNotFoundException e)
                    {
                        Debug.Log("exit point not found: " + e.StackTrace);
                        break;
                    }

                    // traverse subject polygon in clockwise order until new entr vertex found
                    while (node.Value.Type != WAList.Entry && !visited.Contains(node))
                    {
                        if (last == null || !MathUtil.EqualsEps(node.Value.Pos, last.Pos))
                        {
                            vertices.Add(node.Value.Pos);
                            visited.Add(node);
                        }
                        last = node.Value;
                        node = node.Next ?? WA.SubjectList.First;
                    }

                    if (visited.Contains(node))
                    {
                        break;
                    }

                    try
                    {
                        node = WA.ClipNode[node.Value];
                    }
                    catch (KeyNotFoundException e)
                    {
                        Debug.Log("entry point not found: " + e);
                        break;
                    }
                }

                // add new polygon from the vertices
                if (vertices.Count > 2)
                {
                    multiPoly.AddPolygon(new Polygon2D(vertices));
                }
            }

            return(multiPoly);
        }