public void CycleTest() { var dcel = new DCEL(); var v1 = dcel.AddVertex(new DCELVertex(0, 0)); var v2 = dcel.AddVertex(new DCELVertex(10, 10)); var v3 = dcel.AddVertex(new DCELVertex(20, 0)); var e1 = dcel.AddEdge(v1, v2); var e2 = dcel.AddEdge(v2, v3); var e3 = dcel.AddEdge(v3, v1); Assert.Contains(e1, DCEL.Cycle(e1)); Assert.Contains(e2, DCEL.Cycle(e1)); Assert.Contains(e3, DCEL.Cycle(e1)); Assert.Contains(e1, DCEL.Cycle(e2)); Assert.Contains(e2, DCEL.Cycle(e2)); Assert.Contains(e3, DCEL.Cycle(e2)); Assert.Contains(e1, DCEL.Cycle(e3)); Assert.Contains(e2, DCEL.Cycle(e3)); Assert.Contains(e3, DCEL.Cycle(e3)); }
/// <summary> /// Returns a halfedge of the leftmost middle face. /// </summary> /// <param name="m_dcel"></param> /// <param name="m_dualLines"></param> /// <returns></returns> private static HalfEdge LeftMostMiddleHalfEdge(DCEL m_dcel, IEnumerable <Line> m_dualLines) { var bbox = m_dcel.InitBoundingBox.Value; // get all intersections with left line of bounding box var leftLine = new Line(new Vector2(bbox.xMin, bbox.yMin), new Vector2(bbox.xMin, bbox.yMax)); var intersections = m_dualLines .Where(l => !l.IsVertical) .Select(l => leftLine.Intersect(l).Value) .ToList(); // sort on y value intersections.Sort((v1, v2) => v1.y.CompareTo(v2.y)); // find edge between middle intersections var middleIntersectBot = intersections[intersections.Count / 2 - 1]; var middleIntersectTop = intersections[intersections.Count / 2]; var edgeInterval = new FloatInterval(middleIntersectBot.y, middleIntersectTop.y); // get corresponding halfedge in dcel HalfEdge workingEdge; if (bbox.yMin < edgeInterval.Min && bbox.yMax > edgeInterval.Max) { // both intersections contained on left segment of bounding box workingEdge = DCEL.Cycle(m_dcel.OuterFace.InnerComponents[0]) .FirstOrDefault(e => e.From.Pos.x == bbox.xMin && edgeInterval.ContainsEpsilon(e.From.Pos.y) && edgeInterval.ContainsEpsilon(e.To.Pos.y)); } else if (bbox.yMin >= edgeInterval.Min) { // bottom intersection lies below left segment // find halfedge pointing to bottom left corner workingEdge = DCEL.Cycle(m_dcel.OuterFace.InnerComponents[0]) .FirstOrDefault(e => MathUtil.Equals(e.From.Pos, new Vector2(bbox.xMin, bbox.yMin))); // traverse outer cycle until we find line with the corresponding bottom intersection while (workingEdge.Twin.Prev.Segment.Line.IsVertical || !MathUtil.EqualsEps(workingEdge.Twin.Prev.Segment.Line.Intersect(leftLine).Value, middleIntersectBot)) { workingEdge = workingEdge.Next; } } else { // top intersection lies above left segment // find halfedge pointing away from top left corner workingEdge = DCEL.Cycle(m_dcel.OuterFace.InnerComponents[0]) .FirstOrDefault(e => MathUtil.Equals(e.To.Pos, new Vector2(bbox.xMin, bbox.yMax))); // traverse outer cycle until we find line with the corresponding top intersection while (workingEdge.Twin.Next.Segment.Line.IsVertical || !MathUtil.EqualsEps(workingEdge.Twin.Next.Segment.Line.Intersect(leftLine).Value, middleIntersectTop)) { workingEdge = workingEdge.Prev; } } // middle edge should always exist if (workingEdge == null) { throw new GeomException("working edge not found"); } // return twin (edge of middle face, not outer face) return(workingEdge.Twin); }