private void Initialize() { sweepline = new OA_Sweepline(); eventQueue = new RBTreeSet <OA_EventPoint>(OA_EventPoint.Compare); outputSubdivision = new DCEL_Subdivision(); foreach (DCEL_Subdivision inputSubdivision in inputSubdivisions) { foreach (DCEL_HalfEdge inputHalfEdge in inputSubdivision.HalfEdges.Keys) { OA_EventPoint upper = new OA_EventPoint(inputHalfEdge.Origin.Position); OA_EventPoint lower = new OA_EventPoint(inputHalfEdge.Destination.Position); //We want to take only one of the twins from every pair of half edges. if (upper.CompareTo(lower) > 0) { continue; } RBTreeSetNode <OA_EventPoint> upper_node = new RBTreeSetNode <OA_EventPoint>(upper); RBTreeSetNode <OA_EventPoint> lower_node = new RBTreeSetNode <OA_EventPoint>(lower); //If we didn't add the newly created event point, it already existed. if (!eventQueue.Add(ref upper_node)) { upper = upper_node.Key; } if (!eventQueue.Add(ref lower_node)) { lower = lower_node.Key; } OA_Segment segment = new OA_Segment(sweepline); segment.Source.Add(new OA_Source <DCEL_HalfEdge>(inputSubdivision, inputHalfEdge)); segment.Upper = upper; segment.Lower = lower; //***May be adding a duplicate if segment is in both subdivisions! upper.UpperList.Add(segment); if (!upper.Source.Any(OA_Source <DCEL_Vertex> .IsFrom(inputSubdivision))) { upper.Source.Add(new OA_Source <DCEL_Vertex>(inputSubdivision, inputHalfEdge.Origin)); } if (!lower.Source.Any(OA_Source <DCEL_Vertex> .IsFrom(inputSubdivision))) { lower.Source.Add(new OA_Source <DCEL_Vertex>(inputSubdivision, inputHalfEdge.Destination)); } } } foreach (OA_EventPoint eventPoint in eventQueue.Keys) { //***Remove those duplicates here, joining their source lists. eventPoint.UpperList.RemoveDuplicates(OA_Segment.CompareEndpoints, OA_Segment.JoinSource); } }
/// <summary> /// Merge subdivisionA and subdivisionB into a single subdivision, destroying subdivisionA and subdivisionB in the process. /// </summary> public static DCEL_Subdivision Overlay(DCEL_Subdivision subdivisionA, DCEL_Subdivision subdivisionB) { OA_Algorithm algorithm = new OA_Algorithm(new[] { subdivisionA, subdivisionB }); subdivisionA.WriteToFile("subdivisionA_pre_splitting.xml"); subdivisionB.WriteToFile("subdivisionB_pre_splitting.xml"); subdivisionA.WriteToFile_Faces("subdivisionA_pre_splitting_faces.xml"); subdivisionB.WriteToFile_Faces("subdivisionB_pre_splitting_faces.xml"); algorithm.phase = Phase.SplittingPhase; algorithm.Initialize(); algorithm.Sweep(); subdivisionA.WriteToFile("subdivisionA_post_splitting.xml"); subdivisionB.WriteToFile("subdivisionB_post_splitting.xml"); subdivisionA.WriteToFile_Faces("subdivisionA_post_splitting_faces.xml"); subdivisionB.WriteToFile_Faces("subdivisionB_post_splitting_faces.xml"); algorithm.phase = Phase.MergingPhase; algorithm.Initialize(); algorithm.Sweep(); algorithm.outputSubdivision.WriteToFile("outputSubdivision_post_merging.xml"); algorithm.phase = Phase.FacingPhase; algorithm.CreateFaces(); algorithm.outputSubdivision.WriteToFile("outputSubdivision_final.xml"); algorithm.outputSubdivision.WriteToFile_Faces("outputSubdivision_final_faces.xml"); //The inputSubdivisions have been destroyed, so clear them. foreach (DCEL_Subdivision inputSubdivision in algorithm.inputSubdivisions) { inputSubdivision.Clear(); } return(algorithm.outputSubdivision); }
private void HandleIntersection_SplittingPhase(OA_EventPoint eventPoint, List <OA_Segment> upperList, List <OA_Segment> middleList, List <OA_Segment> lowerList) { //if (upperList.Count() + middleList.Count() + lowerList.Count() <= 1) if (middleList.Count == 0) { return; } //If there are any subdivisions which don't have a vertex at this location, //then we will create one momentarily. For the moment, set the //(key, value) = (subdivision, null). Dictionary <DCEL_Subdivision, DCEL_Vertex> vertexLookup = CreateSourceLookup(eventPoint); //Make all segments meet at a vertex here, within each subdivision. //HalfEdges associated with segments in the middleList will be transformed //into HalfEdges associated with segments in the upperList. (With the associated //segments transforming as well.) foreach (OA_Segment middle in middleList) { foreach (OA_Source <DCEL_HalfEdge> source in middle.Source) { DCEL_Subdivision subdivision = source.Subdivision; DCEL_HalfEdge halfEdge = source.Element; DCEL_Vertex vertex = vertexLookup[subdivision]; //Create the vertex on-demand if it doesn't exist if (vertex == null) { vertex = new DCEL_Vertex(eventPoint.Position); vertexLookup[subdivision] = vertex; subdivision.Vertices.Add(new RBTreeSetNode <DCEL_Vertex>(vertex)); } SplitEdge(subdivision, halfEdge, vertex); if (!eventPoint.Source.Any(OA_Source <DCEL_Vertex> .IsFrom(subdivision))) { eventPoint.Source.Add(new OA_Source <DCEL_Vertex>(subdivision, vertex)); } } } }
/// <summary> /// halfEdge should be Upper->Lower so that the persistent half edges become: /// o halfEdge (Upper->Lower) ==> (vertex->Lower) /// o halfEdge.Twin (Lower->Upper) ==> (Lower->vertex) /// And the two newly created half edges are (vertex->Upper) and (Upper->vertex). /// </summary> private static void SplitEdge(DCEL_Subdivision subdivision, DCEL_HalfEdge halfEdge, DCEL_Vertex vertex) { Debug.Assert(VecRat2.CompareReadingOrder(halfEdge.Origin.Position, halfEdge.Destination.Position) < 0); DCEL_HalfEdge e1 = halfEdge; DCEL_HalfEdge e2 = e1.Twin; DCEL_HalfEdge e1_prev = e1.Prev; DCEL_HalfEdge e2_next = e2.Next; DCEL_Vertex e1_origin = e1.Origin; DCEL_HalfEdge e1_top = new DCEL_HalfEdge(); DCEL_HalfEdge e2_top = new DCEL_HalfEdge(); DCEL_Helper.JoinTwin(e1_top, e2_top); e1_top.IncidentFace = e1.IncidentFace; e2_top.IncidentFace = e2.IncidentFace; DCEL_Helper.JoinIncidentEdge(vertex, e2_top); DCEL_Helper.JoinIncidentEdge(vertex, e1); DCEL_Helper.JoinIncidentEdge(e1_origin, e1_top); if (e2_next == e1) { DCEL_Helper.JoinNext(e2, e2_top); DCEL_Helper.JoinNext(e2_top, e1_top); DCEL_Helper.JoinNext(e1_top, e1); } else { DCEL_Helper.JoinPrevNext(e2, e2_top, e2_next); DCEL_Helper.JoinPrevNext(e1_prev, e1_top, e1); } if (subdivision != null) { subdivision.HalfEdges.Add(new RBTreeSetNode <DCEL_HalfEdge>(e1_top)); subdivision.HalfEdges.Add(new RBTreeSetNode <DCEL_HalfEdge>(e2_top)); } }
public static Func <OA_Source <DCEL_T>, bool> IsFrom(DCEL_Subdivision subdivision) { return(source => (source.Subdivision == subdivision)); }
public OA_Source(DCEL_Subdivision subdivision, DCEL_T element) { Subdivision = subdivision; Element = element; }