//triangulation by ear removal int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) { long numvertices; PartitionVertex *vertices; PartitionVertex *ear = 0; TPPLPoly triangle; long i,j; bool earfound; if(poly->GetNumPoints() < 3) return 0; if(poly->GetNumPoints() == 3) { triangles->push_back(*poly); return 1; } numvertices = poly->GetNumPoints(); vertices = new PartitionVertex[numvertices]; for(i=0;i<numvertices;i++) { vertices[i].isActive = true; vertices[i].p = poly->GetPoint(i); if(i==(numvertices-1)) vertices[i].next=&(vertices[0]); else vertices[i].next=&(vertices[i+1]); if(i==0) vertices[i].previous = &(vertices[numvertices-1]); else vertices[i].previous = &(vertices[i-1]); } for(i=0;i<numvertices;i++) { UpdateVertex(&vertices[i],vertices,numvertices); } for(i=0;i<numvertices-3;i++) { earfound = false; //find the most extruded ear for(j=0;j<numvertices;j++) { if(!vertices[j].isActive) continue; if(!vertices[j].isEar) continue; if(!earfound) { earfound = true; ear = &(vertices[j]); } else { if(vertices[j].angle > ear->angle) { ear = &(vertices[j]); } } } if(!earfound) { delete [] vertices; return 0; } triangle.Triangle(ear->previous->p,ear->p,ear->next->p); triangles->push_back(triangle); ear->isActive = false; ear->previous->next = ear->next; ear->next->previous = ear->previous; if(i==numvertices-4) break; UpdateVertex(ear->previous,vertices,numvertices); UpdateVertex(ear->next,vertices,numvertices); } for(i=0;i<numvertices;i++) { if(vertices[i].isActive) { triangle.Triangle(vertices[i].previous->p,vertices[i].p,vertices[i].next->p); triangles->push_back(triangle); break; } } delete [] vertices; return 1; }
//minimum-weight polygon triangulation by dynamic programming //O(n^3) time complexity //O(n^2) space complexity int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) { long i,j,k,gap,n; DPState **dpstates; TPPLPoint p1,p2,p3,p4; long bestvertex; tppl_float weight,minweight,d1,d2; Diagonal diagonal,newdiagonal; list<Diagonal> diagonals; TPPLPoly triangle; int ret = 1; n = poly->GetNumPoints(); dpstates = new DPState *[n]; for(i=1;i<n;i++) { dpstates[i] = new DPState[i]; } //init states and visibility for(i=0;i<(n-1);i++) { p1 = poly->GetPoint(i); for(j=i+1;j<n;j++) { dpstates[j][i].visible = true; dpstates[j][i].weight = 0; dpstates[j][i].bestvertex = -1; if(j!=(i+1)) { p2 = poly->GetPoint(j); //visibility check if(i==0) p3 = poly->GetPoint(n-1); else p3 = poly->GetPoint(i-1); if(i==(n-1)) p4 = poly->GetPoint(0); else p4 = poly->GetPoint(i+1); if(!InCone(p3,p1,p4,p2)) { dpstates[j][i].visible = false; continue; } if(j==0) p3 = poly->GetPoint(n-1); else p3 = poly->GetPoint(j-1); if(j==(n-1)) p4 = poly->GetPoint(0); else p4 = poly->GetPoint(j+1); if(!InCone(p3,p2,p4,p1)) { dpstates[j][i].visible = false; continue; } for(k=0;k<n;k++) { p3 = poly->GetPoint(k); if(k==(n-1)) p4 = poly->GetPoint(0); else p4 = poly->GetPoint(k+1); if(Intersects(p1,p2,p3,p4)) { dpstates[j][i].visible = false; break; } } } } } dpstates[n-1][0].visible = true; dpstates[n-1][0].weight = 0; dpstates[n-1][0].bestvertex = -1; for(gap = 2; gap<n; gap++) { for(i=0; i<(n-gap); i++) { j = i+gap; if(!dpstates[j][i].visible) continue; bestvertex = -1; for(k=(i+1);k<j;k++) { if(!dpstates[k][i].visible) continue; if(!dpstates[j][k].visible) continue; if(k<=(i+1)) d1=0; else d1 = Distance(poly->GetPoint(i),poly->GetPoint(k)); if(j<=(k+1)) d2=0; else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j)); weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2; if((bestvertex == -1)||(weight<minweight)) { bestvertex = k; minweight = weight; } } if(bestvertex == -1) { for(i=1;i<n;i++) { delete [] dpstates[i]; } delete [] dpstates; return 0; } dpstates[j][i].bestvertex = bestvertex; dpstates[j][i].weight = minweight; } } newdiagonal.index1 = 0; newdiagonal.index2 = n-1; diagonals.push_back(newdiagonal); while(!diagonals.empty()) { diagonal = *(diagonals.begin()); diagonals.pop_front(); bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex; if(bestvertex == -1) { ret = 0; break; } triangle.Triangle(poly->GetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2)); triangles->push_back(triangle); if(bestvertex > (diagonal.index1+1)) { newdiagonal.index1 = diagonal.index1; newdiagonal.index2 = bestvertex; diagonals.push_back(newdiagonal); } if(diagonal.index2 > (bestvertex+1)) { newdiagonal.index1 = bestvertex; newdiagonal.index2 = diagonal.index2; diagonals.push_back(newdiagonal); } } for(i=1;i<n;i++) { delete [] dpstates[i]; } delete [] dpstates; return ret; }
//triangulates monotone polygon //O(n) time, O(n) space complexity int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles) { long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex; TPPLPoint *points; long numpoints; TPPLPoly triangle; numpoints = inPoly->GetNumPoints(); points = inPoly->GetPoints(); //trivial calses if(numpoints < 3) return 0; if(numpoints == 3) { triangles->push_back(*inPoly); } topindex = 0; bottomindex=0; for(i=1;i<numpoints;i++) { if(Below(points[i],points[bottomindex])) bottomindex = i; if(Below(points[topindex],points[i])) topindex = i; } //check if the poly is really monotone i = topindex; while(i!=bottomindex) { i2 = i+1; if(i2>=numpoints) i2 = 0; if(!Below(points[i2],points[i])) return 0; i = i2; } i = bottomindex; while(i!=topindex) { i2 = i+1; if(i2>=numpoints) i2 = 0; if(!Below(points[i],points[i2])) return 0; i = i2; } char *vertextypes = new char[numpoints]; long *priority = new long[numpoints]; //merge left and right vertex chains priority[0] = topindex; vertextypes[topindex] = 0; leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0; rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1; for(i=1;i<(numpoints-1);i++) { if(leftindex==bottomindex) { priority[i] = rightindex; rightindex--; if(rightindex<0) rightindex = numpoints-1; vertextypes[priority[i]] = -1; } else if(rightindex==bottomindex) { priority[i] = leftindex; leftindex++; if(leftindex>=numpoints) leftindex = 0; vertextypes[priority[i]] = 1; } else { if(Below(points[leftindex],points[rightindex])) { priority[i] = rightindex; rightindex--; if(rightindex<0) rightindex = numpoints-1; vertextypes[priority[i]] = -1; } else { priority[i] = leftindex; leftindex++; if(leftindex>=numpoints) leftindex = 0; vertextypes[priority[i]] = 1; } } } priority[i] = bottomindex; vertextypes[bottomindex] = 0; long *stack = new long[numpoints]; long stackptr = 0; stack[0] = priority[0]; stack[1] = priority[1]; stackptr = 2; //for each vertex from top to bottom trim as many triangles as possible for(i=2;i<(numpoints-1);i++) { vindex = priority[i]; if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) { for(j=0;j<(stackptr-1);j++) { if(vertextypes[vindex]==1) { triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); } else { triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); } triangles->push_back(triangle); } stack[0] = priority[i-1]; stack[1] = priority[i]; stackptr = 2; } else { stackptr--; while(stackptr>0) { if(vertextypes[vindex]==1) { if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) { triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]); triangles->push_back(triangle); stackptr--; } else { break; } } else { if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) { triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]); triangles->push_back(triangle); stackptr--; } else { break; } } } stackptr++; stack[stackptr] = vindex; stackptr++; } } vindex = priority[i]; for(j=0;j<(stackptr-1);j++) { if(vertextypes[stack[j+1]]==1) { triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); } else { triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); } triangles->push_back(triangle); } delete [] priority; delete [] vertextypes; delete [] stack; return 1; }