/// <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)); } }
private void HandleIntersection_MergingPhase(OA_EventPoint eventPoint, List <OA_Segment> upperList, List <OA_Segment> middleList, List <OA_Segment> lowerList) { if (middleList.Count != 0) { throw new Exception("MergingPhase: Something went wrong in the SplittingPhase, because there is an intersection with nonempty middleList."); } //Dictionary<DCEL_Subdivision, DCEL_Vertex> vertexLookup = CreateSourceLookup(eventPoint); //DCEL_Vertex mergedVertex = vertexLookup.Values.First(); DCEL_Vertex mergedVertex = eventPoint.Source.First().Element; lowerList.Sort(AngleComparisonLowerList(mergedVertex.Position)); upperList.Sort(AngleComparisonUpperList(mergedVertex.Position)); //JoinNext all consecutive pairs around circle, and join origins to mergedVertex { //Outgoing half edges in CCW order List <DCEL_HalfEdge> bothList = new List <DCEL_HalfEdge>(); bothList.AddRange(lowerList.Select(segment => segment.Source.First().Element.Twin)); bothList.AddRange(upperList.Select(segment => segment.Source.First().Element)); if (bothList.Count > 1) { DCEL_HalfEdge e, e_next; for (int i = 1; i < bothList.Count; i++) { e = bothList[i].Twin; e_next = bothList[i - 1]; DCEL_Helper.JoinNext(e, e_next); } e = bothList.First().Twin; e_next = bothList.Last(); DCEL_Helper.JoinNext(e, e_next); } else { DCEL_HalfEdge e = bothList[0].Twin; DCEL_HalfEdge e_next = e.Twin; DCEL_Helper.JoinNext(e, e_next); } //Set the origins to the mergedVertex foreach (DCEL_HalfEdge e in bothList) { e.Origin = mergedVertex; } mergedVertex.IncidentEdge = bothList.First(); } outputSubdivision.Vertices.Add(new RBTreeSetNode <DCEL_Vertex>(mergedVertex)); foreach (OA_Segment upper in upperList) { DCEL_HalfEdge e = upper.Source.First().Element; outputSubdivision.HalfEdges.Add(new RBTreeSetNode <DCEL_HalfEdge>(e)); outputSubdivision.HalfEdges.Add(new RBTreeSetNode <DCEL_HalfEdge>(e.Twin)); //HACK?///////////////////////////////////////// e.IncidentFace = null; e.Twin.IncidentFace = null; //HACK?///////////////////////////////////////// } //Store the left pick for the mergedVertex if (eventPoint.LeftPick != null) { leftPicksMap.Add(new RBTreeMapNode <DCEL_Vertex, DCEL_HalfEdge>(mergedVertex, eventPoint.LeftPick.Source.First().Element)); } else { leftPicksMap.Add(new RBTreeMapNode <DCEL_Vertex, DCEL_HalfEdge>(mergedVertex, null)); } }