Пример #1
0
        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);
        }
Пример #2
0
        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;
        }
Пример #3
0
        //
        // 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);
        }
Пример #4
0
        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;
        }
Пример #5
0
        //
        // 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);
        }