/// <summary>
 /// Given a non-overlapping multi polygon, will create a contour polygon from it conforming to the requirements
 /// of the ContourPolygon.
 /// </summary>
 /// <param name="pol"></param>
 /// <returns></returns>
 public static ContourPolygon ToContourPolygon(this MultiPolygon2D pol)
 {
     return(new ContourPolygon(pol.Polygons.Select(v => v.ToContour())));
 }
Пример #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.Entry.Count == 0)
            {
                if (WA.Subject.Vertices.ToList().Exists(p => !(WA.Clip.ContainsInside(p) || WA.Clip.OnBoundary(p))))
                {
                    multiPoly.AddPolygon(new Polygon2D(WA.Subject.Vertices));
                }
            }

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

                // remove an entry intersection point
                var startPoint = WA.Entry.LastOrDefault();
                WA.Entry.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.Entry.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);
        }