public List <Area_Based_Analyses.Atomizer.AtomicRegion> Atomize(List <Point> figurePoints) { // // Clear collinearities in preparation for determining intersection points. // List <Segment> extendedSegments = new List <Segment>(); foreach (Segment side in orderedSides) { side.ClearCollinear(); } // // Determine if any side intersects a non-adjacent side. // If so, track all the intersection points. // List <Point> imagPts = new List <Point>(); for (int s1 = 0; s1 < orderedSides.Count - 1; s1++) { // +2 excludes this side and the adjacent side for (int s2 = s1 + 2; s2 < orderedSides.Count; s2++) { // Avoid intersecting the first with the last. if (s1 != 0 || s2 != orderedSides.Count - 1) { Point intersection = orderedSides[s1].FindIntersection(orderedSides[s2]); intersection = Utilities.AcquirePoint(figurePoints, intersection); if (intersection != null) { // The point of interest must be on the perimeter of the polygon. if (this.PointLiesOn(intersection) || this.PointLiesInside(intersection)) { orderedSides[s1].AddCollinearPoint(intersection); orderedSides[s2].AddCollinearPoint(intersection); // The intersection point may be a vertex; avoid redundant additions. if (!Utilities.HasStructurally <Point>(imagPts, intersection)) { imagPts.Add(intersection); } } } } } } // // Add the imaginary points to the list of figure points; // this is needed for consistency among all regions / polygons. // Utilities.AddUniqueList <Point>(figurePoints, imagPts); // // Construct the Planar graph for atomic region identification. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(); // Add all imaginary points and intersection points foreach (Point pt in this.points) { graph.AddNode(pt); } foreach (Point pt in imagPts) { graph.AddNode(pt); } // // Cycle through collinearities adding to the graph. // Ensure that a connection is interior to this polygon. // foreach (Segment side in orderedSides) { for (int p = 0; p < side.collinear.Count - 1; p++) { // // Find the midpoint of this segment and determine if it is interior to the polygon. // If it is, then this is a legitimate connection. // Segment thisSegment = new Segment(side.collinear[p], side.collinear[p + 1]); Point midpoint = thisSegment.Midpoint(); if (this.PointLiesInOrOn(midpoint)) { graph.AddUndirectedEdge(side.collinear[p], side.collinear[p + 1], thisSegment.Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } } // // Convert the planar graph to atomic regions. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph); FacetCalculator atomFinder = new FacetCalculator(copy); List <Primitive> primitives = atomFinder.GetPrimitives(); List <AtomicRegion> atoms = PrimitiveToRegionConverter.Convert(graph, primitives, new List <Circle>()); // No circles here. // State ownership foreach (AtomicRegion atom in atoms) { atom.AddOwner(this); this.AddAtomicRegion(atom); } return(atoms); }
public List<Area_Based_Analyses.Atomizer.AtomicRegion> Atomize(List<Point> figurePoints) { List<Segment> constructedChords = new List<Segment>(); List<Segment> constructedRadii = new List<Segment>(); List<Point> imagPoints = new List<Point>(); List<Point> interPts = GetIntersectingPoints(); // // Construct the radii // switch (interPts.Count) { // If there are no points of interest, the circle is the atomic region. case 0: return Utilities.MakeList<AtomicRegion>(new ShapeAtomicRegion(this)); // If only 1 intersection point, create the diameter. case 1: Point opp = Utilities.AcquirePoint(figurePoints, this.OppositePoint(interPts[0])); constructedRadii.Add(new Segment(center, interPts[0])); constructedRadii.Add(new Segment(center, opp)); imagPoints.Add(opp); interPts.Add(opp); break; default: foreach (Point interPt in interPts) { constructedRadii.Add(new Segment(center, interPt)); } break; } // // Construct the chords // List<Segment> chords = new List<Segment>(); for (int p1 = 0; p1 < interPts.Count - 1; p1++) { for (int p2 = p1 + 1; p2 < interPts.Count; p2++) { Segment chord = new Segment(interPts[p1], interPts[p2]); if (!DefinesDiameter(chord)) constructedChords.Add(chord); } } // // Do any of the created segments result in imaginary intersection points. // foreach (Segment chord in constructedChords) { foreach (Segment radius in constructedRadii) { Point inter = Utilities.AcquireRestrictedPoint(figurePoints, chord.FindIntersection(radius), chord, radius); if (inter != null) { chord.AddCollinearPoint(inter); radius.AddCollinearPoint(inter); // if (!Utilities.HasStructurally<Point>(figurePoints, inter)) imagPoints.Add(inter); Utilities.AddUnique<Point>(imagPoints, inter); } } } for (int c1 = 0; c1 < constructedChords.Count - 1; c1++) { for (int c2 = c1 + 1; c2 < constructedChords.Count; c2++) { Point inter = constructedChords[c1].FindIntersection(constructedChords[c2]); inter = Utilities.AcquireRestrictedPoint(figurePoints, inter, constructedChords[c1], constructedChords[c2]); if (inter != null) { constructedChords[c1].AddCollinearPoint(inter); constructedChords[c2].AddCollinearPoint(inter); //if (!Utilities.HasStructurally<Point>(figurePoints, inter)) imagPoints.Add(inter); Utilities.AddUnique<Point>(imagPoints, inter); } } } // // Add all imaginary points to the list of figure points. // Utilities.AddUniqueList<Point>(figurePoints, imagPoints); // // Construct the Planar graph for atomic region identification. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(); // // Add all imaginary points, intersection points, and center. // foreach (Point pt in imagPoints) { graph.AddNode(pt); } foreach (Point pt in interPts) { graph.AddNode(pt); } graph.AddNode(this.center); // // Add all chords and radii as edges. // foreach (Segment chord in constructedChords) { for (int p = 0; p < chord.collinear.Count - 1; p++) { graph.AddUndirectedEdge(chord.collinear[p], chord.collinear[p + 1], new Segment(chord.collinear[p], chord.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } foreach (Segment radius in constructedRadii) { for (int p = 0; p < radius.collinear.Count - 1; p++) { graph.AddUndirectedEdge(radius.collinear[p], radius.collinear[p + 1], new Segment(radius.collinear[p], radius.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } // // Add all arcs // List<Point> arcPts = this.ConstructAllMidpoints(interPts); for (int p = 0; p < arcPts.Count; p++) { graph.AddNode(arcPts[p]); graph.AddNode(arcPts[(p + 1) % arcPts.Count]); graph.AddUndirectedEdge(arcPts[p], arcPts[(p + 1) % arcPts.Count], new Segment(arcPts[p], arcPts[(p + 1) % interPts.Count]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_ARC); } // // Convert the planar graph to atomic regions. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph); FacetCalculator atomFinder = new FacetCalculator(copy); List<Primitive> primitives = atomFinder.GetPrimitives(); List<AtomicRegion> atoms = PrimitiveToRegionConverter.Convert(graph, primitives, Utilities.MakeList<Circle>(this)); // // A filament may result in the creation of a major AND minor arc; both are not required. // Figure out which one to omit. // Multiple semi-circles may arise as well; omit if they can be broken into constituent elements. // List <AtomicRegion> trueAtoms = new List<AtomicRegion>(); for (int a1 = 0; a1 < atoms.Count; a1++) { bool trueAtom = true; for (int a2 = 0; a2 < atoms.Count; a2++) { if (a1 != a2) { if (atoms[a1].Contains(atoms[a2])) { trueAtom = false; break; } } } if (trueAtom) trueAtoms.Add(atoms[a1]); } atoms = trueAtoms; return trueAtoms; }
// // Compose this atomic region with a segment // This operation will return a list of atomic regions iff the segment passes through the atomic region; this // creates two new atomic regions since the segment divides the atom. // //public static List<AtomicRegion> Compose(AtomicRegion thisAtom, Segment that, Figure owner) //{ // List<AtomicRegion> newAtoms = new List<AtomicRegion>(); // List<AtomicRegion.IntersectionAgg> intersections = thisAtom.GetIntersections(that); // // If there is only 1 intersection then we may have a 'corner' inside of the atomic region. // if (intersections.Count == 1) return newAtoms; // if (intersections.Count > 2) throw new ArgumentException("More than 3 intersections due to a segment during atomic region composition"); // // If there are two intersection points, this atomic region is split into 2 regions. // if (intersections.Count != 2) // { // throw new ArgumentException("Expected 2 intersections due to a segment during atomic region composition; have " + intersections.Count); // } // // // // Split the region into 2 new atomic regions. // // // // (0) Order the connections of this atomic region. // // (1) Make a copy of the list of connections // // (2) Replace 2 intersected connections with (up to) 4 new connections. // // (3) Add this segment connection // // // thisAtom.OrderConnections(); // AtomicRegion newAtom1 = new AtomicRegion(); // AtomicRegion newAtom2 = new AtomicRegion(); // bool[] marked = new bool[intersections.Count]; // bool atom1 = true; // foreach (Connection conn in thisAtom.connections) // { // bool found = false; // for (int i = 0; i < intersections.Count; i++) // { // if (!marked[i]) // { // marked[i] = true; // if (conn.Equals(intersections[i].Key)) // { // found = true; // // // // How does this new segment intersect this connection? // // // // Endpoint // if (conn.HasPoint(intersections[i].Value)) // { // // No-op // } // // Split this connection in the middle // else // { // Connection newConn1 = new Connection(conn.endpoint1, intersections[i].Value, conn.type, conn.segmentOwner); // Connection newConn2 = new Connection(conn.endpoint2, intersections[i].Value, conn.type, conn.segmentOwner); // // // // Which atomic region owns which new connection. // // // if (newAtom1.HasPoint(conn.endpoint1)) // { // newAtom1.AddConnection(newConn1); // newAtom2.AddConnection(newConn2); // } // else if (newAtom2.HasPoint(conn.endpoint1)) // { // newAtom2.AddConnection(newConn1); // newAtom1.AddConnection(newConn2); // } // // Neither atomic region has the point (possibly the first connection encountered). // else // { // // Arbitrary assignment // newAtom1.AddConnection(newConn1); // newAtom2.AddConnection(newConn2); // } // } // // Shift to the second (new) atomic region. // atom1 = false; // } // } // } // // This is not a splittable connection so just add it to the list. // if (!found) // { // if (atom1) newAtom1.AddConnection(conn); // else newAtom2.AddConnection(conn); // } // } // // // // Add this new segment as a connection to both atomic regions. // // // newAtom1.AddConnection(intersections[0].Value, intersections[1].Value, ConnectionType.SEGMENT, owner); // newAtom2.AddConnection(intersections[0].Value, intersections[1].Value, ConnectionType.SEGMENT, owner); // // Order the connections in the new regions we created. // newAtom1.OrderConnections(); // newAtom2.OrderConnections(); // newAtoms.Add(newAtom1); // newAtoms.Add(newAtom2); // return newAtoms; //} public static void Overlap(List<Point> figurePoints, AtomicRegion thisAtom, AtomicRegion thatAtom, out List<AtomicRegion> toAdd, out List<AtomicRegion> toRemove) { // // Acquire all arcs and segments. // List<Arc> graphArcs = new List<Arc>(); List<Segment> graphSegments = new List<Segment>(); foreach (Connection thisConn in thisAtom.connections) { if (thisConn.type == ConnectionType.SEGMENT) graphSegments.Add(thisConn.segmentOrArc as Segment); else graphArcs.Add(thisConn.segmentOrArc as Arc); } foreach (Connection thatConn in thatAtom.connections) { if (thatConn.type == ConnectionType.SEGMENT) graphSegments.Add(thatConn.segmentOrArc as Segment); else graphArcs.Add(thatConn.segmentOrArc as Arc); } // // Clear collinearities of all segments / arcs. // List<Circle> circles = new List<Circle>(); // get the list of applicable circles to these atoms. foreach (Segment seg in graphSegments) seg.ClearCollinear(); foreach (Arc arc in graphArcs) { Utilities.AddStructurallyUnique<Circle>(circles, arc.theCircle); arc.ClearCollinear(); } // // All points of interest for these atoms. // List<Point> allPoints = new List<Point>(); allPoints.AddRange(thisAtom.GetVertices()); allPoints.AddRange(thatAtom.GetVertices()); // // Determine 'collinearities' for the intersections. // List<AtomicRegion.IntersectionAgg> intersections = thisAtom.GetIntersections(figurePoints, thatAtom); List<Point> intersectionPts = new List<Point>(); foreach (AtomicRegion.IntersectionAgg agg in intersections) { if (agg.intersection1 != null) { if (!Utilities.HasStructurally<Point>(allPoints, agg.intersection1)) intersectionPts.Add(agg.intersection1); agg.thisConn.segmentOrArc.AddCollinearPoint(agg.intersection1); agg.thatConn.segmentOrArc.AddCollinearPoint(agg.intersection1); } if (agg.intersection2 != null) { if (!Utilities.HasStructurally<Point>(allPoints, agg.intersection2)) intersectionPts.Add(agg.intersection2); intersectionPts.Add(agg.intersection2); agg.thisConn.segmentOrArc.AddCollinearPoint(agg.intersection2); agg.thatConn.segmentOrArc.AddCollinearPoint(agg.intersection2); } } // Add any unlabeled intersection points. allPoints.AddRange(intersectionPts); // // Construct the Planar graph for atomic region identification. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(); // Add the points as nodes in the graph. foreach (Point pt in allPoints) { graph.AddNode(pt); } // // Edges are based on all the collinear relationships. // foreach (Segment segment in graphSegments) { for (int p = 0; p < segment.collinear.Count - 1; p++) { graph.AddUndirectedEdge(segment.collinear[p], segment.collinear[p+1], new Segment(segment.collinear[p], segment.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } foreach (Arc arc in graphArcs) { for (int p = 0; p < arc.collinear.Count - 1; p++) { graph.AddUndirectedEdge(arc.collinear[p], arc.collinear[p + 1], new Segment(arc.collinear[p], arc.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_ARC); } } // // Convert the planar graph to atomic regions. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph); FacetCalculator atomFinder = new FacetCalculator(copy); List<Primitive> primitives = atomFinder.GetPrimitives(); List<AtomicRegion> atoms = PrimitiveToRegionConverter.Convert(graph, primitives, circles); // // Determine ownership of the atomic regions. // foreach (AtomicRegion atom in atoms) { if (thisAtom.Contains(atom)) { atom.AddOwners(thisAtom.owners); } if (thatAtom.Contains(atom)) { atom.AddOwners(thatAtom.owners); } } toAdd = atoms; toRemove = new List<AtomicRegion>(); toRemove.Add(thisAtom); toRemove.Add(thatAtom); }
public List<Area_Based_Analyses.Atomizer.AtomicRegion> Atomize(List<Point> figurePoints) { // // Clear collinearities in preparation for determining intersection points. // List<Segment> extendedSegments = new List<Segment>(); foreach (Segment side in orderedSides) { side.ClearCollinear(); } // // Determine if any side intersects a non-adjacent side. // If so, track all the intersection points. // List<Point> imagPts = new List<Point>(); for (int s1 = 0; s1 < orderedSides.Count - 1; s1++) { // +2 excludes this side and the adjacent side for (int s2 = s1 + 2; s2 < orderedSides.Count; s2++) { // Avoid intersecting the first with the last. if (s1 != 0 || s2 != orderedSides.Count - 1) { Point intersection = orderedSides[s1].FindIntersection(orderedSides[s2]); intersection = Utilities.AcquirePoint(figurePoints, intersection); if (intersection != null) { // The point of interest must be on the perimeter of the polygon. if (this.PointLiesOn(intersection) || this.PointLiesInside(intersection)) { orderedSides[s1].AddCollinearPoint(intersection); orderedSides[s2].AddCollinearPoint(intersection); // The intersection point may be a vertex; avoid redundant additions. if (!Utilities.HasStructurally<Point>(imagPts, intersection)) { imagPts.Add(intersection); } } } } } } // // Add the imaginary points to the list of figure points; // this is needed for consistency among all regions / polygons. // Utilities.AddUniqueList<Point>(figurePoints, imagPts); // // Construct the Planar graph for atomic region identification. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(); // Add all imaginary points and intersection points foreach (Point pt in this.points) { graph.AddNode(pt); } foreach (Point pt in imagPts) { graph.AddNode(pt); } // // Cycle through collinearities adding to the graph. // Ensure that a connection is interior to this polygon. // foreach (Segment side in orderedSides) { for (int p = 0; p < side.collinear.Count - 1; p++) { // // Find the midpoint of this segment and determine if it is interior to the polygon. // If it is, then this is a legitimate connection. // Segment thisSegment = new Segment(side.collinear[p], side.collinear[p + 1]); Point midpoint = thisSegment.Midpoint(); if (this.PointLiesInOrOn(midpoint)) { graph.AddUndirectedEdge(side.collinear[p], side.collinear[p + 1], thisSegment.Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } } // // Convert the planar graph to atomic regions. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph); FacetCalculator atomFinder = new FacetCalculator(copy); List<Primitive> primitives = atomFinder.GetPrimitives(); List<AtomicRegion> atoms = PrimitiveToRegionConverter.Convert(graph, primitives, new List<Circle>()); // No circles here. // State ownership foreach (AtomicRegion atom in atoms) { atom.AddOwner(this); this.AddAtomicRegion(atom); } return atoms; }
// // Compose this atomic region with a segment // This operation will return a list of atomic regions iff the segment passes through the atomic region; this // creates two new atomic regions since the segment divides the atom. // //public static List<AtomicRegion> Compose(AtomicRegion thisAtom, Segment that, Figure owner) //{ // List<AtomicRegion> newAtoms = new List<AtomicRegion>(); // List<AtomicRegion.IntersectionAgg> intersections = thisAtom.GetIntersections(that); // // If there is only 1 intersection then we may have a 'corner' inside of the atomic region. // if (intersections.Count == 1) return newAtoms; // if (intersections.Count > 2) throw new ArgumentException("More than 3 intersections due to a segment during atomic region composition"); // // If there are two intersection points, this atomic region is split into 2 regions. // if (intersections.Count != 2) // { // throw new ArgumentException("Expected 2 intersections due to a segment during atomic region composition; have " + intersections.Count); // } // // // // Split the region into 2 new atomic regions. // // // // (0) Order the connections of this atomic region. // // (1) Make a copy of the list of connections // // (2) Replace 2 intersected connections with (up to) 4 new connections. // // (3) Add this segment connection // // // thisAtom.OrderConnections(); // AtomicRegion newAtom1 = new AtomicRegion(); // AtomicRegion newAtom2 = new AtomicRegion(); // bool[] marked = new bool[intersections.Count]; // bool atom1 = true; // foreach (Connection conn in thisAtom.connections) // { // bool found = false; // for (int i = 0; i < intersections.Count; i++) // { // if (!marked[i]) // { // marked[i] = true; // if (conn.Equals(intersections[i].Key)) // { // found = true; // // // // How does this new segment intersect this connection? // // // // Endpoint // if (conn.HasPoint(intersections[i].Value)) // { // // No-op // } // // Split this connection in the middle // else // { // Connection newConn1 = new Connection(conn.endpoint1, intersections[i].Value, conn.type, conn.segmentOwner); // Connection newConn2 = new Connection(conn.endpoint2, intersections[i].Value, conn.type, conn.segmentOwner); // // // // Which atomic region owns which new connection. // // // if (newAtom1.HasPoint(conn.endpoint1)) // { // newAtom1.AddConnection(newConn1); // newAtom2.AddConnection(newConn2); // } // else if (newAtom2.HasPoint(conn.endpoint1)) // { // newAtom2.AddConnection(newConn1); // newAtom1.AddConnection(newConn2); // } // // Neither atomic region has the point (possibly the first connection encountered). // else // { // // Arbitrary assignment // newAtom1.AddConnection(newConn1); // newAtom2.AddConnection(newConn2); // } // } // // Shift to the second (new) atomic region. // atom1 = false; // } // } // } // // This is not a splittable connection so just add it to the list. // if (!found) // { // if (atom1) newAtom1.AddConnection(conn); // else newAtom2.AddConnection(conn); // } // } // // // // Add this new segment as a connection to both atomic regions. // // // newAtom1.AddConnection(intersections[0].Value, intersections[1].Value, ConnectionType.SEGMENT, owner); // newAtom2.AddConnection(intersections[0].Value, intersections[1].Value, ConnectionType.SEGMENT, owner); // // Order the connections in the new regions we created. // newAtom1.OrderConnections(); // newAtom2.OrderConnections(); // newAtoms.Add(newAtom1); // newAtoms.Add(newAtom2); // return newAtoms; //} public static void Overlap(List <Point> figurePoints, AtomicRegion thisAtom, AtomicRegion thatAtom, out List <AtomicRegion> toAdd, out List <AtomicRegion> toRemove) { // // Acquire all arcs and segments. // List <Arc> graphArcs = new List <Arc>(); List <Segment> graphSegments = new List <Segment>(); foreach (Connection thisConn in thisAtom.connections) { if (thisConn.type == ConnectionType.SEGMENT) { graphSegments.Add(thisConn.segmentOrArc as Segment); } else { graphArcs.Add(thisConn.segmentOrArc as Arc); } } foreach (Connection thatConn in thatAtom.connections) { if (thatConn.type == ConnectionType.SEGMENT) { graphSegments.Add(thatConn.segmentOrArc as Segment); } else { graphArcs.Add(thatConn.segmentOrArc as Arc); } } // // Clear collinearities of all segments / arcs. // List <Circle> circles = new List <Circle>(); // get the list of applicable circles to these atoms. foreach (Segment seg in graphSegments) { seg.ClearCollinear(); } foreach (Arc arc in graphArcs) { Utilities.AddStructurallyUnique <Circle>(circles, arc.theCircle); arc.ClearCollinear(); } // // All points of interest for these atoms. // List <Point> allPoints = new List <Point>(); allPoints.AddRange(thisAtom.GetVertices()); allPoints.AddRange(thatAtom.GetVertices()); // // Determine 'collinearities' for the intersections. // List <AtomicRegion.IntersectionAgg> intersections = thisAtom.GetIntersections(figurePoints, thatAtom); List <Point> intersectionPts = new List <Point>(); foreach (AtomicRegion.IntersectionAgg agg in intersections) { if (agg.intersection1 != null) { if (!Utilities.HasStructurally <Point>(allPoints, agg.intersection1)) { intersectionPts.Add(agg.intersection1); } agg.thisConn.segmentOrArc.AddCollinearPoint(agg.intersection1); agg.thatConn.segmentOrArc.AddCollinearPoint(agg.intersection1); } if (agg.intersection2 != null) { if (!Utilities.HasStructurally <Point>(allPoints, agg.intersection2)) { intersectionPts.Add(agg.intersection2); } intersectionPts.Add(agg.intersection2); agg.thisConn.segmentOrArc.AddCollinearPoint(agg.intersection2); agg.thatConn.segmentOrArc.AddCollinearPoint(agg.intersection2); } } // Add any unlabeled intersection points. allPoints.AddRange(intersectionPts); // // Construct the Planar graph for atomic region identification. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(); // Add the points as nodes in the graph. foreach (Point pt in allPoints) { graph.AddNode(pt); } // // Edges are based on all the collinear relationships. // foreach (Segment segment in graphSegments) { for (int p = 0; p < segment.collinear.Count - 1; p++) { graph.AddUndirectedEdge(segment.collinear[p], segment.collinear[p + 1], new Segment(segment.collinear[p], segment.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } foreach (Arc arc in graphArcs) { for (int p = 0; p < arc.collinear.Count - 1; p++) { graph.AddUndirectedEdge(arc.collinear[p], arc.collinear[p + 1], new Segment(arc.collinear[p], arc.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_ARC); } } // // Convert the planar graph to atomic regions. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph); FacetCalculator atomFinder = new FacetCalculator(copy); List <Primitive> primitives = atomFinder.GetPrimitives(); List <AtomicRegion> atoms = PrimitiveToRegionConverter.Convert(graph, primitives, circles); // // Determine ownership of the atomic regions. // foreach (AtomicRegion atom in atoms) { if (thisAtom.Contains(atom)) { atom.AddOwners(thisAtom.owners); } if (thatAtom.Contains(atom)) { atom.AddOwners(thatAtom.owners); } } toAdd = atoms; toRemove = new List <AtomicRegion>(); toRemove.Add(thisAtom); toRemove.Add(thatAtom); }