//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Sort out zero length edge issues. </summary> /// <remarks> /// Zero length edges are a pain and have to be dealt with specially since they don't sort /// properly using normal geometrical position nor can "sidedness" be determined solely from /// their geometry (a zero length line has no "sides"). Instead, we have to look at the non-zero /// length edges around them and determine this information by extrapolating from those edges /// topological connection to this edge. /// </remarks> //////////////////////////////////////////////////////////////////////////////////////////////////// internal void HandleZeroLengthEdges() { // If no zero length edges if (!FZeroLengthEdge) { // We're outta here return; } // For every edge in the polygon for (var i = 0; i < VertexCount; i++) { // Retrieve the edge var edgeCheck = FortuneEdges[i]; // If it's zero length if (edgeCheck.FZeroLength()) { // Remove the edge from both this polygon and the polygon "across" the zero length edge DetachEdge(edgeCheck); FortuneEdges.Remove(edgeCheck); edgeCheck.OtherPoly(this).FortuneEdges.Remove(edgeCheck); // We have to back up one because we deleted edge i i--; } } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Sort the edges in Clockwise order. </summary> /// <remarks> /// We do this partially by knowing that all the polygons in a Voronoi diagram are convex. That /// means we can sort edges by measuring their angle around the generator for the polygon. We /// have to pick the point to measure this angle carefully which is what /// WEEdge.PolyOrderingTestPoint() does. We also have to make a special case for the rare doubly /// infinite lines (such as that created with only two generators). /// Darrellp, 2/18/2011. /// </remarks> //////////////////////////////////////////////////////////////////////////////////////////////////// internal void SortEdges() { // If there are only two edges if (FortuneEdges.Count == 2) { // If they are split if (FortuneEdges[0].FSplit) { // If they need reordering // // I don't think this is really necessary. It makes sense to order more than 2 // edges because they really have an "order" which will be maintained no matter which // polygon they're ordered by (though the starting edge may change). With two oppositely // directed rays as in this case, there is no such "order" independent of the polygon that // does the ordering. I'm leaving it in but I don't think it's necessary. // TODO: Check on this! if (ICcw( FortuneEdges[0].PolyOrderingTestPoint, FortuneEdges[1].PolyOrderingTestPoint, VoronoiPoint) < 0) { // Reorder them var edgeT = FortuneEdges[0]; FortuneEdges[0] = FortuneEdges[1]; FortuneEdges[1] = edgeT; } } else { // I think this represents an infinite polygon with only two edges. // If not ordered around the single base point properly if (ICcw(FortuneEdges[0].VtxStart.Pt, FortuneEdges[0].PolyOrderingTestPoint, FortuneEdges[1].PolyOrderingTestPoint) > 0) { // Swap the edges var edgeT = FortuneEdges[0]; FortuneEdges[0] = FortuneEdges[1]; FortuneEdges[1] = edgeT; } } } else if (FortuneEdges.Count == 4 && FortuneEdges[0].FSplit) { // I think the nontransitivity of the "order" here will cause the CLR Sort() // to screw up our ordering in this case so we handle it specially... if (ICcw(FortuneEdges[0].VtxStart.Pt, FortuneEdges[0].PolyOrderingTestPoint, FortuneEdges[1].PolyOrderingTestPoint) > 0) { var edgeT = FortuneEdges[0]; FortuneEdges[0] = FortuneEdges[1]; FortuneEdges[1] = edgeT; } if (ICcw(FortuneEdges[2].VtxStart.Pt, FortuneEdges[2].PolyOrderingTestPoint, FortuneEdges[3].PolyOrderingTestPoint) > 0) { var edgeT = FortuneEdges[2]; FortuneEdges[2] = FortuneEdges[3]; FortuneEdges[3] = edgeT; } } else { // More than 3 vertices just get a standard CLR sort // TODO: Is nontransitivity screwing up here too and we're just not noticing? FortuneEdges.Sort(); } }