// // Do all the endpoints in that region lie within this region? // And, are all intersection points, if any, on this perimeter? // public virtual bool Contains(AtomicRegion that) { // // Do all vertices of that lie on the interior of this atomic region? // List <Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesOnOrInside(vertex)) { return(false); } } // // Check all midpoints of conenctions are on the interior. // foreach (Connection thatConn in that.connections) { if (!this.PointLiesOnOrInside(thatConn.Midpoint())) { return(false); } } // // For any intersections between the atomic regions, the resultant points of intersection must be on the perimeter. // List <IntersectionAgg> intersections = this.GetIntersections(that); foreach (IntersectionAgg agg in intersections) { if (agg.overlap) { // No-Op } else { if (!this.PointLiesOn(agg.intersection1)) { return(false); } if (agg.intersection2 != null) { if (!this.PointLiesOn(agg.intersection2)) { return(false); } } } } return(true); }
// // All vertices of that region on the perimeter of this. // Number of intersections must equate to the number of vertices. // public bool Inscribed(AtomicRegion that) { List <Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesOn(vertex)) { return(false); } } return(this.GetIntersections(that).Count == thatVertices.Count); }
// // A region (that) lies inside this with one intersection. // public bool ContainsWithGreaterOneInscription(AtomicRegion that) { // // Do all vertices of that lie on the interior of this atomic region? // List <Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesOnOrInside(vertex)) { return(false); } } // There should be only ONE intersection return(this.GetIntersections(that).Count > 1); }
// // Do all the endpoints in that region lie within this region? // There should be no intersection points. // public bool StrictlyContains(AtomicRegion that) { // // Do all vertices of that lie on the interior of this atomic region? // List <Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesInside(vertex)) { return(false); } } // There should be no intersections return(!this.GetIntersections(that).Any()); }
// // If there is no interaction between these atomic regions OR just touching // public bool InteriorOfWithTouching(AtomicRegion that) { List <IntersectionAgg> intersections = this.GetIntersections(that); // All vertices cannot be interior to the region. List <Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (this.PointLiesOnOrInside(vertex)) { return(false); } } // All intersections must overlap; only point-based intersections which are on the perimeter. foreach (IntersectionAgg agg in intersections) { if (agg.overlap) { // No-Op } else { if (PointLiesExterior(agg.intersection1)) { return(false); } if (agg.intersection2 != null) { if (PointLiesExterior(agg.intersection2)) { return(false); } } } } return(true); }
public virtual bool Contains(List<Point> figurePoints, AtomicRegion atom) { // A figure contains itself. ShapeAtomicRegion shapeAtom = atom as ShapeAtomicRegion; if (shapeAtom != null) { if (this.StructurallyEquals(shapeAtom.shape)) return true; } // // Do all vertices of that lie on the interior of this figure // List<Point> thatVertices = atom.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesInOrOn(vertex)) return false; } // // Check all midpoints of conenctions are on the interior. // foreach (Connection thatConn in atom.connections) { if (!this.PointLiesInOrOn(thatConn.Midpoint())) return false; } // // For any intersections between the atomic regions, the resultant points of intersection must be on the perimeter. // AtomicRegion thisFigureRegion = this.GetFigureAsAtomicRegion(); List<AtomicRegion.IntersectionAgg> intersections = thisFigureRegion.GetIntersections(figurePoints, atom); foreach (AtomicRegion.IntersectionAgg agg in intersections) { if (agg.overlap) { // No-Op } else { // An approximation may result in an intersection inside the figure (although we would expect on) if (!this.PointLiesInOrOn(agg.intersection1)) return false; if (agg.intersection2 != null) { if (!this.PointLiesInOrOn(agg.intersection2)) return false; } } } return true; }
// // Do all the endpoints in that region lie within this region? // There should be no intersection points. // public bool StrictlyContains(AtomicRegion that) { // // Do all vertices of that lie on the interior of this atomic region? // List<Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesInside(vertex)) return false; } // There should be no intersections return !this.GetIntersections(that).Any(); }
// // All vertices of that region on the perimeter of this. // Number of intersections must equate to the number of vertices. // public bool Inscribed(AtomicRegion that) { List<Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesOn(vertex)) return false; } return this.GetIntersections(that).Count == thatVertices.Count; }
// // If there is no interaction between these atomic regions OR just touching // public bool OnExteriorOf(AtomicRegion that) { List<IntersectionAgg> intersections = this.GetIntersections(that); // All vertices cannot be interior to the region. List<Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (this.PointLiesInside(vertex)) return false; } // All intersections must be overlap; only point-based intersections which are on the perimeter. foreach (IntersectionAgg agg in intersections) { if (!agg.overlap) { if (agg.intersection2 != null) return false; if (!this.PointLiesOn(agg.intersection1)) return false; } else // agg.overlap { // No-Op } } return true; }
// // A region (that) lies inside this with one intersection. // public bool ContainsWithOneInscription(AtomicRegion that) { // // Do all vertices of that lie on the interior of this atomic region? // List<Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesOnOrInside(vertex)) return false; } // There should be only ONE intersection return this.GetIntersections(that).Count == 1; }
// // Do all the endpoints in that region lie within this region? // And, are all intersection points, if any, on this perimeter? // public virtual bool Contains(AtomicRegion that) { // // Do all vertices of that lie on the interior of this atomic region? // List<Point> thatVertices = that.GetVertices(); foreach (Point vertex in thatVertices) { if (!this.PointLiesOnOrInside(vertex)) return false; } // // Check all midpoints of conenctions are on the interior. // foreach (Connection thatConn in that.connections) { if (!this.PointLiesOnOrInside(thatConn.Midpoint())) return false; } // // For any intersections between the atomic regions, the resultant points of intersection must be on the perimeter. // List<IntersectionAgg> intersections = this.GetIntersections(that); foreach (IntersectionAgg agg in intersections) { if (agg.overlap) { // No-Op } else { if (!this.PointLiesOn(agg.intersection1)) return false; if (agg.intersection2 != null) { if (!this.PointLiesOn(agg.intersection2)) return false; } } } return true; }
// // Using a single atomic region as a set of bounds: // (1) Find all interesting regions (contained and intersecting) // (2) Recursively compose all contained regions. // (3) Combine all into the original boundary region. // private static List<AtomicRegion> ComposeSingleRegion(List<Point> figurePoints, AtomicRegion outerBounds, List<AtomicRegion> allRegions, List<AtomicRegion> knownAtomicRegions, List<AtomicRegion> knownNonAtomicRegions, List<List<AtomicRegion>> setsForNonAtomicRegions, Dictionary<Circle, int> circGranularity) { // // Base cases: we have already processed this atom as a sub-atom in a previous iteration. // if (knownAtomicRegions.Contains(outerBounds)) return Utilities.MakeList<AtomicRegion>(outerBounds); // We've processed this atom already. int index = knownNonAtomicRegions.IndexOf(outerBounds); if (index != -1) return setsForNonAtomicRegions[index]; // // Acquire the current set of regions under consideration. // List<AtomicRegion> currentAtoms = new List<AtomicRegion>(allRegions); AddRange(currentAtoms, knownAtomicRegions); // // Collect all interesting regions for this region: those that intersect with it and those that are contained inside. // List<AtomicRegion> intersectingSet = null; List<AtomicRegion> containedSet = null; GetInterestingRegions(currentAtoms, outerBounds, out intersectingSet, out containedSet); // If we have have no interactions, this is a truly atomic region. if (!intersectingSet.Any() && !containedSet.Any()) return Utilities.MakeList<AtomicRegion>(outerBounds); // // Recur on all containing regions. // List<AtomicRegion> newContainedAtoms = new List<AtomicRegion>(); foreach (AtomicRegion containedAtom in containedSet) { if (knownAtomicRegions.Contains(containedAtom)) AddAtom(newContainedAtoms, containedAtom); else if (knownNonAtomicRegions.Contains(containedAtom)) { AddRange(newContainedAtoms, setsForNonAtomicRegions[knownNonAtomicRegions.IndexOf(containedAtom)]); } else { // Get all regions using containedAtom as the boundary region. List<AtomicRegion> newContainedBoundedAtoms = ComposeSingleRegion(figurePoints, containedAtom, currentAtoms, knownAtomicRegions, knownNonAtomicRegions, setsForNonAtomicRegions, circGranularity); AddRange(newContainedAtoms, newContainedBoundedAtoms); // // This is a true atomic region that cannot be split. // if (newContainedBoundedAtoms.Count == 1) AddAtom(knownAtomicRegions, containedAtom); // // The boundary atom is replaced by all of the newAtoms else { // Save all of the contained atomic regions for this atom. if (AddAtom(knownNonAtomicRegions, containedAtom)) { setsForNonAtomicRegions.Add(newContainedBoundedAtoms); } // Indicate all found regions are truly atomic AddRange(knownAtomicRegions, newContainedBoundedAtoms); } } } // // Now that all contained regions are atomized, combine ALL intersections and atomic regions. // // Collect all segments and arcs (with explicit endpoints). // Extend only if they do not touch the sides of the boundaries. // // inside of the boundaries; determine all intersection points. // // (1) All intersecting regions. // (a) For all vertices inside the boundaries, extend to the closest atom. // (b) For all sides that pass through determine any intersections. // (2) All contained atoms // (a) For each side of a region, extend to the closest region. // (b) If a single circle or concentric circles, extend a diameter from the closest point inside the region, through the center. // (c) If several non-intersecting circles, extend diameters through the centers of each pair. // List<Point> points = new List<Point>(); List<Segment> segments = new List<Segment>(); List<Arc> arcs = new List<Arc>(); // // Add the outer boundaries. // points.AddRange(outerBounds.GetVertices()); foreach (Connection boundaryConn in outerBounds.connections) { if (boundaryConn.type == ConnectionType.ARC) { arcs.Add(boundaryConn.segmentOrArc as Arc); } if (boundaryConn.type == ConnectionType.SEGMENT) { segments.Add(boundaryConn.segmentOrArc as Segment); } } // // Regions that intersect the boundaries; selectively take connections. // foreach (AtomicRegion intersecting in intersectingSet) { List<AtomicRegion.IntersectionAgg> intersections = outerBounds.GetIntersections(figurePoints, intersecting); // Determine which intersections are interior to the boundaries. foreach (AtomicRegion.IntersectionAgg agg in intersections) { if (agg.overlap) { /* No-op */ } else { if (agg.intersection1 != null) { if (outerBounds.PointLiesOnOrInside(agg.intersection1)) { if (!outerBounds.NotInteriorTo(agg.thatConn)) { if (agg.thatConn.type == ConnectionType.ARC) GeometryTutorLib.Utilities.AddUnique<Arc>(arcs, agg.thatConn.segmentOrArc as Arc); if (agg.thatConn.type == ConnectionType.SEGMENT) GeometryTutorLib.Utilities.AddUnique<Segment>(segments, agg.thatConn.segmentOrArc as Segment); } GeometryTutorLib.Utilities.AddUnique<Point>(points, agg.intersection1); } } if (agg.intersection2 != null) { if (outerBounds.PointLiesOnOrInside(agg.intersection2)) { GeometryTutorLib.Utilities.AddUnique<Point>(points, agg.intersection2); } } } } } // // Deal with contained regions. // // TO BE COMPLETED: Deal with isolated circles. foreach (AtomicRegion contained in newContainedAtoms) { List<Point> verts = contained.GetVertices(); GeometryTutorLib.Utilities.AddUniqueList<Point>(points, verts); foreach (Connection conn in contained.connections) { if (conn.type == ConnectionType.ARC) Utilities.AddUnique<Arc>(arcs, conn.segmentOrArc as Arc); if (conn.type == ConnectionType.SEGMENT) { Utilities.AddUnique<Segment>(segments, conn.segmentOrArc as Segment); } } } // // Find all intersections...among segments and arcs. // foreach (Segment segment in segments) { segment.ClearCollinear(); } foreach (Arc arc in arcs) { arc.ClearCollinear(); } HandleSegmentSegmentIntersections(figurePoints, points, segments, outerBounds); HandleSegmentArcIntersections(figurePoints, points, segments, arcs, outerBounds); HandleArcArcIntersections(figurePoints, points, arcs, outerBounds); // Returns the list of maximal segments. segments = HandleCollinearSubSegments(segments); // HandleCollinearSubArcs(arcs); // // Construct the Planar graph for atomic region identification. // GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(); // Add the points as nodes in the graph. foreach (Point pt in points) { graph.AddNode(pt); } // // Edges are based on all the collinear relationships. // To ensure we are taking ONLY the closest extended intersections, choose ONLY the 1 point around the actual endpoints of the arc or segment. // foreach (Segment segment in segments) { for (int p = 0; p < segment.collinear.Count - 1; p++) { if (outerBounds.PointLiesInOrOn(segment.collinear[p]) && outerBounds.PointLiesInOrOn(segment.collinear[p + 1])) { graph.AddUndirectedEdge(segment.collinear[p], segment.collinear[p + 1], new Segment(segment.collinear[p], segment.collinear[p + 1]).Length, GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } } foreach (Arc arc in arcs) { List<Point> applicWithMidpoints = GetArcPoints(arc, circGranularity); // Add the points to the graph; preprocess to see if all points are inside the region. bool[] inOrOn = new bool[applicWithMidpoints.Count]; for (int p = 0; p < applicWithMidpoints.Count; p++) { if (outerBounds.PointLiesInOrOn(applicWithMidpoints[p])) { graph.AddNode(applicWithMidpoints[p]); inOrOn[p] = true; } } for (int p = 0; p < applicWithMidpoints.Count - 1; p++) { if (inOrOn[p] && inOrOn[p + 1]) { graph.AddUndirectedEdge(applicWithMidpoints[p], applicWithMidpoints[p + 1], new Segment(applicWithMidpoints[p], applicWithMidpoints[p + 1]).Length, GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_ARC); } } } // // Collect the circles from the arcs. // List<Circle> circles = new List<Circle>(); foreach (Arc arc in arcs) { GeometryTutorLib.Utilities.AddStructurallyUnique<Circle>(circles, arc.theCircle); } // // Convert the planar graph to atomic regions. // GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph); FacetCalculator atomFinder = new FacetCalculator(copy); List<Primitive> primitives = atomFinder.GetPrimitives(); List<AtomicRegion> boundedAtoms = PrimitiveToRegionConverter.Convert(graph, primitives, circles); //// //// Realign this set of atoms with the current set of working atoms; this guarantees we are looking at the same atom objects. //// //List<AtomicRegion> finalBoundedAtoms = new List<AtomicRegion>(); //foreach (AtomicRegion boundedAtom in boundedAtoms) //{ // int tempIndex = currentAtoms.IndexOf(boundedAtom); // if (tempIndex == -1) finalBoundedAtoms.Add(boundedAtom); // else finalBoundedAtoms.Add(currentAtoms[tempIndex]); //} // // Determine ownership of the atomic regions. // foreach (AtomicRegion boundedAtom in boundedAtoms) { boundedAtom.AddOwners(outerBounds.owners); // Indicate that the given boundary shape owns all of the new regions within. ShapeAtomicRegion shapeAtom = outerBounds as ShapeAtomicRegion; if (shapeAtom != null) { shapeAtom.shape.AddAtomicRegion(boundedAtom); } } return boundedAtoms; }
// // 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); }
// // 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); }