63
63
* neighbouring edges at the top or bottom vertex. This is handled by merging the
64
64
* edges (merge_collinear_edges()).
65
65
* 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).
68
69
*
69
70
* The tessellation steps (5) and (6) are based on "Triangulating Simple Polygons and
70
71
* Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Note that it
@@ -328,10 +329,11 @@ struct Line {
328
329
* An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
329
330
* "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf().
330
331
* 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.
335
337
*
336
338
* The coefficients of the line equation stored in double precision to avoid catastrphic
337
339
* 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)
1023
1025
for (Edge* e = v->fFirstEdgeAbove ; e; e = e->fNextEdgeAbove ) {
1024
1026
insert_edge (e, leftEdge, activeEdges);
1025
1027
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
+ }
1026
1034
}
1027
1035
}
1028
1036
*current = v;
1029
1037
}
1030
1038
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
+
1031
1076
void set_top (Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
1032
1077
remove_edge_below (edge);
1033
1078
edge->fTop = v;
1034
1079
edge->recompute ();
1035
1080
insert_edge_below (edge, v, c);
1036
- rewind (activeEdges, current, edge-> fTop , c);
1081
+ rewind_if_necessary (edge, activeEdges, current , c);
1037
1082
merge_collinear_edges (edge, activeEdges, current, c);
1038
1083
}
1039
1084
@@ -1042,7 +1087,7 @@ void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
1042
1087
edge->fBottom = v;
1043
1088
edge->recompute ();
1044
1089
insert_edge_above (edge, v, c);
1045
- rewind (activeEdges, current, edge-> fTop , c);
1090
+ rewind_if_necessary (edge, activeEdges, current , c);
1046
1091
merge_collinear_edges (edge, activeEdges, current, c);
1047
1092
}
1048
1093
0 commit comments