/// <summary> /// Creates a Voronoi DCEL from a triangulation. Triangulation should be Delaunay /// </summary> /// <param name="m_Delaunay"></param> /// <returns></returns> public static DCEL Create(Triangulation m_Delaunay) { if (!Delaunay.IsValid(m_Delaunay)) { throw new GeomException("Triangulation should be delaunay for the Voronoi diagram."); } var dcel = new DCEL(); // create vertices for each triangles circumcenter and store them in a dictionary Dictionary <Triangle, DCELVertex> vertexMap = new Dictionary <Triangle, DCELVertex>(); foreach (var triangle in m_Delaunay.Triangles) { // degenerate triangle, just ignore if (!triangle.Circumcenter.HasValue) { continue; } var vertex = new DCELVertex(triangle.Circumcenter.Value); dcel.AddVertex(vertex); vertexMap.Add(triangle, vertex); } // remember which edges where visited // since each edge has a twin var edgesVisited = new HashSet <TriangleEdge>(); foreach (var edge in m_Delaunay.Edges) { // either already visited twin edge or edge is outer triangle if (edgesVisited.Contains(edge) || edge.IsOuter) { continue; } // add edge between the two adjacent triangles vertices // vertices at circumcenter of triangle if (edge.T != null && edge.Twin.T != null) { var v1 = vertexMap[edge.T]; var v2 = vertexMap[edge.Twin.T]; HalfEdge e1 = dcel.AddEdge(v1, v2); e1.Twin.Face.owner = m_Delaunay.GetOwner(edge.Point1); e1.Face.owner = m_Delaunay.GetOwner(edge.Point2); edgesVisited.Add(edge); edgesVisited.Add(edge.Twin); } } return(dcel); }