bool Triangulate::Snip( const Vector2fVector &contour, int u, int v, int w, int n, int *V) { int p; float Ax, Ay, Bx, By, Cx, Cy, Px, Py; Ax = contour[V[u]].x; Ay = contour[V[u]].y; Bx = contour[V[v]].x; By = contour[V[v]].y; Cx = contour[V[w]].x; Cy = contour[V[w]].y; if (EPSILON > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false; for (p = 0; p < n; p++) { if ((p == u) || (p == v) || (p == w)) continue; Px = contour[V[p]].x; Py = contour[V[p]].y; if (InsideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) return false; } return true; }
bool HSTriangular::Snip( const HSVector2dV &contour,int u,int v,int w,int Vsize,int *V ) { int p; float Ax, Ay, Bx, By, Cx, Cy, Px, Py; Ax = contour[V[u]].GetX(); Ay = contour[V[u]].GetY(); Bx = contour[V[v]].GetX(); By = contour[V[v]].GetY(); Cx = contour[V[w]].GetX(); Cy = contour[V[w]].GetY(); if ( HS_EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false; for (p=0;p<Vsize;p++) { if( (p == u) || (p == v) || (p == w) ) continue; Px = contour[V[p]].GetX(); Py = contour[V[p]].GetY(); if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false; } return true; }
bool IsEar(const Polygon& poly, int u, int v, int w, int n, int *verts) { int p; Point U, V, W, P; U = poly[verts[u]]; V = poly[verts[v]]; W = poly[verts[w]]; if ((V.x - U.x) * (W.y - U.y) - (V.y - U.y) * (W.x - U.x) < EPS) { return false; } for (p = 0; p < n; p++) { if (p == u || p == v || p == w) { continue; } P = poly[verts[p]]; if (InsideTriangle(U, V, W, P)) { return false; } } return true; }
static unsigned _PolygonToTriangles(const PT *points, unsigned num_points, GLushort *triangles, typename PT::scalar_type min_distance) { // no redundant start/end please if (num_points >= 1 && points[0] == points[num_points - 1]) num_points--; if (num_points < 3) return 0; assert(num_points < 65536); // next vertex pointer auto next = new GLushort[num_points]; // index of the first vertex GLushort start = 0; // initialize next pointer counterclockwise if (PolygonRotatesLeft(points, num_points)) { for (unsigned i = 0; i < num_points-1; i++) next[i] = i + 1; next[num_points - 1] = 0; } else { next[0] = num_points - 1; for (unsigned i = 1; i < num_points; i++) next[i] = i - 1; } // thinning if (min_distance > 0) { for (unsigned a = start, b = next[a], c = next[b], heat = 0; num_points > 3 && heat < num_points; a = b, b = c, c = next[c], heat++) { bool point_removeable = TriangleEmpty(points[a], points[b], points[c]); if (!point_removeable) { typename PT::scalar_type distance = ManhattanDistance(points[a], points[b]); if (distance < min_distance) { point_removeable = true; if (distance > 0) { for (unsigned p = next[c]; p != a; p = next[p]) { if (InsideTriangle(points[p], points[a], points[b], points[c])) { point_removeable = false; break; } } } } } if (point_removeable) { // remove node b from polygon if (b == start) // keep track of the smallest index start = std::min(a, c); next[a] = c; num_points--; // 'a' should stay the same in the next loop b = a; // reset heat heat = 0; } } //LogDebug(_T("polygon thinning (%u) removed %u of %u vertices"), // min_distance, orig_num_points-num_points, orig_num_points); } // triangulation auto t = triangles; for (unsigned a = start, b = next[a], c = next[b], heat = 0; num_points > 2; a = b, b = c, c = next[c]) { typename PT::product_type bendiness = LeftBend(points[a], points[b], points[c]); // left bend, spike or line with a redundant point in the middle bool ear_cuttable = (bendiness >= 0); if (bendiness > 0) { // left bend for (unsigned prev_p = c, p = next[c]; p != a; prev_p = p, p = next[p]) { typename PT::product_type ab = PointLeftOfLine(points[p], points[a], points[b]); typename PT::product_type bc = PointLeftOfLine(points[p], points[b], points[c]); typename PT::product_type ca = PointLeftOfLine(points[p], points[c], points[a]); if (ab > 0 && bc > 0 && ca > 0) { // p is inside a,b,c ear_cuttable = false; break; } else if (ab >= 0 && bc >= 0 && ca >= 0) { // p is on one or two edges of a,b,c bool outside_ab = (ab == 0) && PointLeftOfLine(points[prev_p], points[a], points[b]) <= 0; bool outside_bc = (bc == 0) && PointLeftOfLine(points[prev_p], points[b], points[c]) <= 0; bool outside_ca = (ca == 0) && PointLeftOfLine(points[prev_p], points[c], points[a]) <= 0; if (!(outside_ab || outside_bc || outside_ca)) { // line p,prev_p intersects with triangle a,b,c ear_cuttable = false; break; } outside_ab = (ab == 0) && PointLeftOfLine(points[next[p]], points[a], points[b]) <= 0; outside_bc = (bc == 0) && PointLeftOfLine(points[next[p]], points[b], points[c]) <= 0; outside_ca = (ca == 0) && PointLeftOfLine(points[next[p]], points[c], points[a]) <= 0; if (!(outside_ab || outside_bc || outside_ca)) { // line p,next[p] intersects with triangle a,b,c ear_cuttable = false; break; } } } if (ear_cuttable) { // save triangle indices *t++ = a; *t++ = b; *t++ = c; } } if (ear_cuttable) { // remove node b from polygon next[a] = c; num_points--; // 'a' should stay the same in the next loop b = a; // reset heat heat = 0; } if (heat++ > num_points) { // if polygon edges overlap we may loop endlessly //LogDebug(_T("polygon_to_triangle: bad polygon")); delete[] next; return 0; } } delete[] next; return t - triangles; }
static unsigned _PolygonToTriangles(const PT *points, unsigned num_points, GLushort *triangles, unsigned min_distance) #endif { // no redundant start/end please if (num_points >= 1 && points[0].x == points[num_points - 1].x && points[0].y == points[num_points - 1].y) num_points--; if (num_points < 3) return 0; assert(num_points < 65536); // next vertex pointer GLushort *next = new GLushort[num_points]; // index of the first vertex GLushort start = 0; // initialize next pointer counterclockwise if (PolygonRotatesLeft(points, num_points)) { for (unsigned i = 0; i < num_points-1; i++) next[i] = i + 1; next[num_points - 1] = 0; } else { next[0] = num_points - 1; for (unsigned i = 1; i < num_points; i++) next[i] = i - 1; } // thinning if (min_distance > 0) { for (unsigned a = start, b = next[a], c = next[b], heat = 0; num_points > 3 && heat < num_points; a = b, b = c, c = next[c], heat++) { bool point_removeable = TriangleEmpty(points[a], points[b], points[c]); if (!point_removeable) { unsigned distance = manhattan_distance(points[a], points[b]); if (distance < min_distance) { point_removeable = true; if (distance != 0) { for (unsigned p = next[c]; p != a; p = next[p]) { if (InsideTriangle(points[p], points[a], points[b], points[c])) { point_removeable = false; break; } } } } } if (point_removeable) { // remove node b from polygon if (b == start) // keep track of the smallest index start = std::min(a, c); next[a] = c; num_points--; // 'a' should stay the same in the next loop b = a; // reset heat heat = 0; } } //LogDebug(_T("polygon thinning (%u) removed %u of %u vertices"), // min_distance, orig_num_points-num_points, orig_num_points); } // triangulation GLushort *t = triangles; for (unsigned a = start, b = next[a], c = next[b], heat = 0; num_points > 2; a = b, b = c, c = next[c]) { if (LeftBend(points[a], points[b], points[c])) { bool ear_cuttable = true; for (unsigned p = next[c]; p != a; p = next[p]) { if (InsideTriangle(points[p], points[a], points[b], points[c])) { ear_cuttable = false; break; } } if (ear_cuttable) { // save triangle indices *t++ = a; *t++ = b; *t++ = c; // remove node b from polygon next[a] = c; num_points--; // 'a' should stay the same in the next loop b = a; // reset heat heat = 0; } } if (heat++ > num_points) { // if polygon edges overlap we may loop endlessly //LogDebug(_T("polygon_to_triangle: bad polygon")); delete[] next; return 0; } } delete[] next; return t - triangles; }