private void FinishLine(JCVEdge e) { if (!clipper.ClipEdge(e)) { return; } // Make sure the graph edges are CCW int flip = TriIsCCW(e.Sites[0].center, e.Points[0], e.Points[1]) ? 0 : 1; for (int i = 0; i < 2; i++) { PointF[] tempPts = new PointF[2]; JCVSite home = e.Sites[i]; JCVSite neighbor = e.Sites[1 - i]; tempPts[flip] = e.Points[i]; tempPts[1 - flip] = e.Points[1 - i]; JCVGraphEdge ge = new JCVGraphEdge(e, home, neighbor, tempPts); home.edges.Add(ge); } // // check that we didn't accidentally add a duplicate (rare), then remove it // if(ge->next && ge->angle == ge->next->angle ) // { // if(jcv_point_eq( &ge->pos[0], &ge->next->pos[0] ) && jcv_point_eq( &ge->pos[1], &ge->next->pos[1] ) ) // { // ge->next = ge->next->next; // Throw it away, they're so few anyways // } // } // } }
// They're sorted CCW, so if the current->pos[1] != next->pos[0], then we have a gap public override bool FillGaps(JCVSite site, JCVDiagram diagram) { if (site.edges.Count == 0) //no edges, must be single cell graph { if (diagram.sites.Count != 0) { throw new Exception("Invalid graph: edgeless site in graph"); } PointF[] points = new PointF[2]; points[0] = new PointF(boundingBox.Left, boundingBox.Top); points[1] = new PointF(boundingBox.Right, boundingBox.Top); JCVEdge edge = new JCVEdge(site, points); diagram.edges.Add(edge); JCVGraphEdge gap = new JCVGraphEdge(edge, site, null, points); site.edges.Add(gap); } if (site.edges.Count == 1) // one edge, assume corner gap { JCVGraphEdge current = site.edges[0]; PointF[] points = new PointF[2]; points[0] = current.Points[1]; if (current.Points[1].X < boundingBox.Right && current.Points[1].Y == boundingBox.Top) { points[1] = new PointF(boundingBox.Right, boundingBox.Top); } else if (current.Points[1].X > boundingBox.Left && current.Points[1].Y == boundingBox.Bottom) { points[1] = new PointF(boundingBox.Left, boundingBox.Bottom); } else if (current.Points[1].Y > boundingBox.Top && current.Points[1].X == boundingBox.Left) { points[1] = new PointF(boundingBox.Left, boundingBox.Top); } else if (current.Points[1].Y < boundingBox.Bottom && current.Points[1].X == boundingBox.Right) { points[1] = new PointF(boundingBox.Right, boundingBox.Bottom); } JCVEdge edge = new JCVEdge(site, points); diagram.edges.Add(edge); JCVGraphEdge gap = new JCVGraphEdge(edge, site, null, points); site.edges.Add(gap); } int eIndex = 0; while (eIndex < site.edges.Count) { JCVGraphEdge current = site.edges[eIndex]; JCVGraphEdge next = site.edges[(eIndex + 1) % site.edges.Count]; if (PointIsOnEdge(current.Points[1]) && current.Points[1] != next.Points[0]) { //border gap if (current.Points[1].X == next.Points[0].X || current.Points[1].Y == next.Points[0].Y) { PointF[] points = { current.Points[1], next.Points[0] }; JCVEdge edge = new JCVEdge(site, points); diagram.edges.Add(edge); JCVGraphEdge gap = new JCVGraphEdge(edge, site, null, points); // note: performance of repeated insertions may justify switching to linked list or SortedSet structure // for processing phase; List currently used due to ease of use, and fact that it will be as fast or // faster than other structures when the diagram is later used (post generation) site.edges.Insert(eIndex + 1, gap); } else if (PointIsOnEdge(current.Points[1]) && PointIsOnEdge(next.Points[0])) { PointF[] points = new PointF[2]; points[0] = current.Points[1]; if (current.Points[1].X < boundingBox.Right && current.Points[1].Y == boundingBox.Top) { points[1] = new PointF(boundingBox.Right, boundingBox.Top); } else if (current.Points[1].X > boundingBox.Left && current.Points[1].Y == boundingBox.Bottom) { points[1] = new PointF(boundingBox.Left, boundingBox.Bottom); } else if (current.Points[1].Y > boundingBox.Top && current.Points[1].X == boundingBox.Left) { points[1] = new PointF(boundingBox.Left, boundingBox.Top); } else if (current.Points[1].Y < boundingBox.Bottom && current.Points[1].X == boundingBox.Right) { points[1] = new PointF(boundingBox.Right, boundingBox.Bottom); } JCVEdge edge = new JCVEdge(site, points); diagram.edges.Add(edge); JCVGraphEdge gap = new JCVGraphEdge(edge, site, null, points); site.edges.Insert(eIndex + 1, gap); } else { //something went wrong; abort instead of looping indefinitely throw new Exception("Invalid Gap state, site location " + site.center.ToString()); } } eIndex++; } // current = current->next; // if (current) // { // next = current->next; // if (!next) // next = site->edges; // } //} ////*********** moved down from top **************** //jcv_graphedge* current = site->edges; //if (!current) //{ // // No edges, then it should be a single cell // assert(allocator->numsites == 1); // jcv_graphedge* gap = jcv_alloc_graphedge(allocator); // gap->neighbor = 0; // gap->pos[0] = clipper->min; // gap->pos[1].x = clipper->max.x; // gap->pos[1].y = clipper->min.y; // gap->angle = jcv_calc_sort_metric(site, gap); // gap->next = 0; // gap->edge = jcv_create_gap_edge(allocator, site, gap); // current = gap; // site->edges = gap; //} //jcv_graphedge* next = current->next; //if (!next) //{ // // Only one edge, then we assume it's a corner gap // jcv_graphedge* gap = jcv_alloc_graphedge(allocator); // jcv_create_corner_edge(allocator, site, current, gap); // gap->edge = jcv_create_gap_edge(allocator, site, gap); // gap->next = current->next; // current->next = gap; // current = gap; // next = site->edges; //} return(false); }