/// <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()))); }
/// <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); }