6363 * neighbouring edges at the top or bottom vertex. This is handled by merging the
6464 * edges (merge_collinear_edges()).
6565 * B) Intersections may cause an edge to violate the left-to-right ordering of the
66- * active edge list. This is handled during merging or splitting by rewind()ing the
67- * active edge list to the vertex before potential violations occur.
66+ * active edge list. This is handled by detecting potential violations and rewinding
67+ * the active edge list to the vertex before they occur (rewind() during merging,
68+ * rewind_if_necessary() during splitting).
6869 *
6970 * The tessellation steps (5) and (6) are based on "Triangulating Simple Polygons and
7071 * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Note that it
@@ -328,10 +329,11 @@ struct Line {
328329 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
329330 * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf().
330331 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (because floating
331- * point). For speed, that case is only tested by the callers that require it. Edges also handle
332- * checking for intersection with other edges. Currently, this converts the edges to the
333- * parametric form, in order to avoid doing a division until an intersection has been confirmed.
334- * This is slightly slower in the "found" case, but a lot faster in the "not found" case.
332+ * point). For speed, that case is only tested by the callers that require it (e.g.,
333+ * rewind_if_necessary()). Edges also handle checking for intersection with other edges.
334+ * Currently, this converts the edges to the parametric form, in order to avoid doing a division
335+ * until an intersection has been confirmed. This is slightly slower in the "found" case, but
336+ * a lot faster in the "not found" case.
335337 *
336338 * The coefficients of the line equation stored in double precision to avoid catastrphic
337339 * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures that the result is
@@ -1023,17 +1025,60 @@ void rewind(EdgeList* activeEdges, Vertex** current, Vertex* dst, Comparator& c)
10231025 for (Edge* e = v->fFirstEdgeAbove ; e; e = e->fNextEdgeAbove ) {
10241026 insert_edge (e, leftEdge, activeEdges);
10251027 leftEdge = e;
1028+ Vertex* top = e->fTop ;
1029+ if (c.sweep_lt (top->fPoint , dst->fPoint ) &&
1030+ ((top->fLeftEnclosingEdge && !top->fLeftEnclosingEdge ->isLeftOf (e->fTop )) ||
1031+ (top->fRightEnclosingEdge && !top->fRightEnclosingEdge ->isRightOf (e->fTop )))) {
1032+ dst = top;
1033+ }
10261034 }
10271035 }
10281036 *current = v;
10291037}
10301038
1039+ void rewind_if_necessary (Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
1040+ if (!activeEdges || !current) {
1041+ return ;
1042+ }
1043+ Vertex* top = edge->fTop ;
1044+ Vertex* bottom = edge->fBottom ;
1045+ if (edge->fLeft ) {
1046+ Vertex* leftTop = edge->fLeft ->fTop ;
1047+ Vertex* leftBottom = edge->fLeft ->fBottom ;
1048+ if (c.sweep_lt (leftTop->fPoint , top->fPoint ) && !edge->fLeft ->isLeftOf (top)) {
1049+ rewind (activeEdges, current, leftTop, c);
1050+ } else if (c.sweep_lt (top->fPoint , leftTop->fPoint ) && !edge->isRightOf (leftTop)) {
1051+ rewind (activeEdges, current, top, c);
1052+ } else if (c.sweep_lt (bottom->fPoint , leftBottom->fPoint ) &&
1053+ !edge->fLeft ->isLeftOf (bottom)) {
1054+ rewind (activeEdges, current, leftTop, c);
1055+ } else if (c.sweep_lt (leftBottom->fPoint , bottom->fPoint ) && !edge->isRightOf (leftBottom)) {
1056+ rewind (activeEdges, current, top, c);
1057+ }
1058+ }
1059+ if (edge->fRight ) {
1060+ Vertex* rightTop = edge->fRight ->fTop ;
1061+ Vertex* rightBottom = edge->fRight ->fBottom ;
1062+ if (c.sweep_lt (rightTop->fPoint , top->fPoint ) && !edge->fRight ->isRightOf (top)) {
1063+ rewind (activeEdges, current, rightTop, c);
1064+ } else if (c.sweep_lt (top->fPoint , rightTop->fPoint ) && !edge->isLeftOf (rightTop)) {
1065+ rewind (activeEdges, current, top, c);
1066+ } else if (c.sweep_lt (bottom->fPoint , rightBottom->fPoint ) &&
1067+ !edge->fRight ->isRightOf (bottom)) {
1068+ rewind (activeEdges, current, rightTop, c);
1069+ } else if (c.sweep_lt (rightBottom->fPoint , bottom->fPoint ) &&
1070+ !edge->isLeftOf (rightBottom)) {
1071+ rewind (activeEdges, current, top, c);
1072+ }
1073+ }
1074+ }
1075+
10311076void set_top (Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
10321077 remove_edge_below (edge);
10331078 edge->fTop = v;
10341079 edge->recompute ();
10351080 insert_edge_below (edge, v, c);
1036- rewind (activeEdges, current, edge-> fTop , c);
1081+ rewind_if_necessary (edge, activeEdges, current , c);
10371082 merge_collinear_edges (edge, activeEdges, current, c);
10381083}
10391084
@@ -1042,7 +1087,7 @@ void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
10421087 edge->fBottom = v;
10431088 edge->recompute ();
10441089 insert_edge_above (edge, v, c);
1045- rewind (activeEdges, current, edge-> fTop , c);
1090+ rewind_if_necessary (edge, activeEdges, current , c);
10461091 merge_collinear_edges (edge, activeEdges, current, c);
10471092}
10481093
0 commit comments