Updated the polypartition library from https://github.com/ivanfratric/polypartition

This commit is contained in:
bubnikv 2019-01-24 15:18:16 +01:00
parent 772b22265c
commit 584e8a8490
2 changed files with 482 additions and 435 deletions

View File

@ -25,6 +25,8 @@
#include <list> #include <list>
#include <algorithm> #include <algorithm>
#include <set> #include <set>
#include <vector>
#include <stdexcept>
using namespace std; using namespace std;
@ -66,21 +68,26 @@ void TPPLPoly::Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) {
points[2] = p3; points[2] = p3;
} }
TPPLPoly::TPPLPoly(const TPPLPoly &src) { TPPLPoly::TPPLPoly(const TPPLPoly &src) : TPPLPoly() {
hole = src.hole; hole = src.hole;
numpoints = src.numpoints; numpoints = src.numpoints;
points = new TPPLPoint[numpoints];
memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
}
TPPLPoly& TPPLPoly::operator=(const TPPLPoly &src) { if(numpoints > 0) {
if(&src != this) {
Clear();
hole = src.hole;
numpoints = src.numpoints;
points = new TPPLPoint[numpoints]; points = new TPPLPoint[numpoints];
memcpy(points, src.points, numpoints*sizeof(TPPLPoint)); memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
} }
}
TPPLPoly& TPPLPoly::operator=(const TPPLPoly &src) {
Clear();
hole = src.hole;
numpoints = src.numpoints;
if(numpoints > 0) {
points = new TPPLPoint[numpoints];
memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
}
return *this; return *this;
} }
@ -105,16 +112,11 @@ void TPPLPoly::SetOrientation(int orientation) {
} }
void TPPLPoly::Invert() { void TPPLPoly::Invert() {
long i; std::reverse(points, points + numpoints);
TPPLPoint *invpoints; }
invpoints = new TPPLPoint[numpoints]; TPPLPartition::PartitionVertex::PartitionVertex() : previous(NULL), next(NULL) {
for(i=0;i<numpoints;i++) {
invpoints[i] = points[numpoints-i-1];
}
delete [] points;
points = invpoints;
} }
TPPLPoint TPPLPartition::Normalize(const TPPLPoint &p) { TPPLPoint TPPLPartition::Normalize(const TPPLPoint &p) {
@ -169,10 +171,10 @@ int TPPLPartition::Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TP
} }
//removes holes from inpolys by merging them with non-holes //removes holes from inpolys by merging them with non-holes
int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys) { int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) {
list<TPPLPoly> polys; TPPLPolyList polys;
list<TPPLPoly>::iterator holeiter,polyiter,iter,iter2; TPPLPolyList::iterator holeiter,polyiter,iter,iter2;
long i,i2,holepointindex,polypointindex = 0; long i,i2,holepointindex,polypointindex;
TPPLPoint holepoint,polypoint,bestpolypoint; TPPLPoint holepoint,polypoint,bestpolypoint;
TPPLPoint linep1,linep2; TPPLPoint linep1,linep2;
TPPLPoint v1,v2; TPPLPoint v1,v2;
@ -183,14 +185,14 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
//check for trivial case (no holes) //check for trivial case (no holes)
hasholes = false; hasholes = false;
for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) { for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
if(iter->IsHole()) { if(iter->IsHole()) {
hasholes = true; hasholes = true;
break; break;
} }
} }
if(!hasholes) { if(!hasholes) {
for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) { for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
outpolys->push_back(*iter); outpolys->push_back(*iter);
} }
return 1; return 1;
@ -201,7 +203,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
while(1) { while(1) {
//find the hole point with the largest x //find the hole point with the largest x
hasholes = false; hasholes = false;
for(iter = polys.begin(); iter!=polys.end(); ++iter) { for(iter = polys.begin(); iter!=polys.end(); iter++) {
if(!iter->IsHole()) continue; if(!iter->IsHole()) continue;
if(!hasholes) { if(!hasholes) {
@ -221,7 +223,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
holepoint = holeiter->GetPoint(holepointindex); holepoint = holeiter->GetPoint(holepointindex);
pointfound = false; pointfound = false;
for(iter = polys.begin(); iter!=polys.end(); ++iter) { for(iter = polys.begin(); iter!=polys.end(); iter++) {
if(iter->IsHole()) continue; if(iter->IsHole()) continue;
for(i=0; i < iter->GetNumPoints(); i++) { for(i=0; i < iter->GetNumPoints(); i++) {
if(iter->GetPoint(i).x <= holepoint.x) continue; if(iter->GetPoint(i).x <= holepoint.x) continue;
@ -237,7 +239,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
if(v2.x > v1.x) continue; if(v2.x > v1.x) continue;
} }
pointvisible = true; pointvisible = true;
for(iter2 = polys.begin(); iter2!=polys.end(); ++iter2) { for(iter2 = polys.begin(); iter2!=polys.end(); iter2++) {
if(iter2->IsHole()) continue; if(iter2->IsHole()) continue;
for(i2=0; i2 < iter2->GetNumPoints(); i2++) { for(i2=0; i2 < iter2->GetNumPoints(); i2++) {
linep1 = iter2->GetPoint(i2); linep1 = iter2->GetPoint(i2);
@ -280,7 +282,7 @@ int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys
polys.push_back(newpoly); polys.push_back(newpoly);
} }
for(iter = polys.begin(); iter!=polys.end(); ++iter) { for(iter = polys.begin(); iter!=polys.end(); iter++) {
outpolys->push_back(*iter); outpolys->push_back(*iter);
} }
@ -335,7 +337,7 @@ bool TPPLPartition::InCone(PartitionVertex *v, TPPLPoint &p) {
} }
void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) { void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) {
PartitionVertex *v1,*v3; PartitionVertex *v1 = NULL,*v3 = NULL;
v1 = v->previous; v1 = v->previous;
v3 = v->next; v3 = v->next;
v->isConvex = !IsReflex(v1->p,v->p,v3->p); v->isConvex = !IsReflex(v1->p,v->p,v3->p);
@ -343,7 +345,7 @@ void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) {
void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) { void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) {
long i; long i;
PartitionVertex *v1,*v3; PartitionVertex *v1 = NULL,*v3 = NULL;
TPPLPoint vec1,vec3; TPPLPoint vec1,vec3;
v1 = v->previous; v1 = v->previous;
@ -372,10 +374,12 @@ void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices,
} }
//triangulation by ear removal //triangulation by ear removal
int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) { int TPPLPartition::Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles) {
if(!poly->Valid()) return 0;
long numvertices; long numvertices;
PartitionVertex *vertices; PartitionVertex *vertices = NULL;
PartitionVertex *ear; PartitionVertex *ear = NULL;
TPPLPoly triangle; TPPLPoly triangle;
long i,j; long i,j;
bool earfound; bool earfound;
@ -446,21 +450,23 @@ int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) {
return 1; return 1;
} }
int TPPLPartition::Triangulate_EC(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles) { int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
list<TPPLPoly> outpolys; TPPLPolyList outpolys;
list<TPPLPoly>::iterator iter; TPPLPolyList::iterator iter;
if(!RemoveHoles(inpolys,&outpolys)) return 0; if(!RemoveHoles(inpolys,&outpolys)) return 0;
for(iter=outpolys.begin();iter!=outpolys.end();++iter) { for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
if(!Triangulate_EC(&(*iter),triangles)) return 0; if(!Triangulate_EC(&(*iter),triangles)) return 0;
} }
return 1; return 1;
} }
int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) { int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts) {
list<TPPLPoly> triangles; if(!poly->Valid()) return 0;
list<TPPLPoly>::iterator iter1,iter2;
TPPLPoly *poly1,*poly2; TPPLPolyList triangles;
TPPLPolyList::iterator iter1,iter2;
TPPLPoly *poly1 = NULL,*poly2 = NULL;
TPPLPoly newpoly; TPPLPoly newpoly;
TPPLPoint d1,d2,p1,p2,p3; TPPLPoint d1,d2,p1,p2,p3;
long i11,i12,i21,i22,i13,i23,j,k; long i11,i12,i21,i22,i13,i23,j,k;
@ -486,7 +492,7 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
if(!Triangulate_EC(poly,&triangles)) return 0; if(!Triangulate_EC(poly,&triangles)) return 0;
for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) { for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
poly1 = &(*iter1); poly1 = &(*iter1);
for(i11=0;i11<poly1->GetNumPoints();i11++) { for(i11=0;i11<poly1->GetNumPoints();i11++) {
d1 = poly1->GetPoint(i11); d1 = poly1->GetPoint(i11);
@ -494,7 +500,7 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
d2 = poly1->GetPoint(i12); d2 = poly1->GetPoint(i12);
isdiagonal = false; isdiagonal = false;
for(iter2 = iter1; iter2 != triangles.end(); ++iter2) { for(iter2 = iter1; iter2 != triangles.end(); iter2++) {
if(iter1 == iter2) continue; if(iter1 == iter2) continue;
poly2 = &(*iter2); poly2 = &(*iter2);
@ -550,19 +556,19 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
} }
} }
for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) { for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
parts->push_back(*iter1); parts->push_back(*iter1);
} }
return 1; return 1;
} }
int TPPLPartition::ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *parts) { int TPPLPartition::ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts) {
list<TPPLPoly> outpolys; TPPLPolyList outpolys;
list<TPPLPoly>::iterator iter; TPPLPolyList::iterator iter;
if(!RemoveHoles(inpolys,&outpolys)) return 0; if(!RemoveHoles(inpolys,&outpolys)) return 0;
for(iter=outpolys.begin();iter!=outpolys.end();++iter) { for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
if(!ConvexPartition_HM(&(*iter),parts)) return 0; if(!ConvexPartition_HM(&(*iter),parts)) return 0;
} }
return 1; return 1;
@ -571,14 +577,16 @@ int TPPLPartition::ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *p
//minimum-weight polygon triangulation by dynamic programming //minimum-weight polygon triangulation by dynamic programming
//O(n^3) time complexity //O(n^3) time complexity
//O(n^2) space complexity //O(n^2) space complexity
int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) { int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles) {
if(!poly->Valid()) return 0;
long i,j,k,gap,n; long i,j,k,gap,n;
DPState **dpstates; DPState **dpstates = NULL;
TPPLPoint p1,p2,p3,p4; TPPLPoint p1,p2,p3,p4;
long bestvertex; long bestvertex;
tppl_float weight,minweight,d1,d2; tppl_float weight,minweight,d1,d2;
Diagonal diagonal,newdiagonal; Diagonal diagonal,newdiagonal;
list<Diagonal> diagonals; DiagonalList diagonals;
TPPLPoly triangle; TPPLPoly triangle;
int ret = 1; int ret = 1;
@ -703,7 +711,7 @@ int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) {
void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) { void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) {
Diagonal newdiagonal; Diagonal newdiagonal;
list<Diagonal> *pairs; DiagonalList *pairs = NULL;
long w2; long w2;
w2 = dpstates[a][b].weight; w2 = dpstates[a][b].weight;
@ -725,8 +733,8 @@ void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2
} }
void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
list<Diagonal> *pairs; DiagonalList *pairs = NULL;
list<Diagonal>::iterator iter,lastiter; DiagonalList::iterator iter,lastiter;
long top; long top;
long w; long w;
@ -742,7 +750,7 @@ void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPS
iter = pairs->end(); iter = pairs->end();
lastiter = pairs->end(); lastiter = pairs->end();
while(iter!=pairs->begin()) { while(iter!=pairs->begin()) {
--iter; iter--;
if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = iter; if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = iter;
else break; else break;
} }
@ -756,8 +764,8 @@ void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPS
} }
void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
list<Diagonal> *pairs; DiagonalList *pairs = NULL;
list<Diagonal>::iterator iter,lastiter; DiagonalList::iterator iter,lastiter;
long top; long top;
long w; long w;
@ -778,7 +786,7 @@ void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPS
while(iter!=pairs->end()) { while(iter!=pairs->end()) {
if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) { if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) {
lastiter = iter; lastiter = iter;
++iter; iter++;
} }
else break; else break;
} }
@ -789,19 +797,21 @@ void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPS
UpdateState(i,k,w,j,top,dpstates); UpdateState(i,k,w,j,top,dpstates);
} }
int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) { int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) {
if(!poly->Valid()) return 0;
TPPLPoint p1,p2,p3,p4; TPPLPoint p1,p2,p3,p4;
PartitionVertex *vertices; PartitionVertex *vertices = NULL;
DPState2 **dpstates; DPState2 **dpstates = NULL;
long i,j,k,n,gap; long i,j,k,n,gap;
list<Diagonal> diagonals,diagonals2; DiagonalList diagonals,diagonals2;
Diagonal diagonal,newdiagonal; Diagonal diagonal,newdiagonal;
list<Diagonal> *pairs,*pairs2; DiagonalList *pairs = NULL,*pairs2 = NULL;
list<Diagonal>::iterator iter,iter2; DiagonalList::iterator iter,iter2;
int ret; int ret;
TPPLPoly newpoly; TPPLPoly newpoly;
list<long> indices; vector<long> indices;
list<long>::iterator iiter; vector<long>::iterator iiter;
bool ijreal,jkreal; bool ijreal,jkreal;
n = poly->GetNumPoints(); n = poly->GetNumPoints();
@ -919,7 +929,7 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
} }
if(!vertices[diagonal.index1].isConvex) { if(!vertices[diagonal.index1].isConvex) {
iter = pairs->end(); iter = pairs->end();
--iter; iter--;
j = iter->index2; j = iter->index2;
newdiagonal.index1 = j; newdiagonal.index1 = j;
newdiagonal.index2 = diagonal.index2; newdiagonal.index2 = diagonal.index2;
@ -933,7 +943,7 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
break; break;
} }
iter2 = pairs2->end(); iter2 = pairs2->end();
--iter2; iter2--;
if(iter->index1 != iter2->index1) pairs2->pop_back(); if(iter->index1 != iter2->index1) pairs2->pop_back();
else break; else break;
} }
@ -1003,7 +1013,7 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs); pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
if(!vertices[diagonal.index1].isConvex) { if(!vertices[diagonal.index1].isConvex) {
iter = pairs->end(); iter = pairs->end();
--iter; iter--;
j = iter->index2; j = iter->index2;
if(iter->index1 != iter->index2) ijreal = false; if(iter->index1 != iter->index2) ijreal = false;
} else { } else {
@ -1031,10 +1041,10 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
indices.push_back(j); indices.push_back(j);
} }
indices.sort(); std::sort(indices.begin(), indices.end());
newpoly.Init((long)indices.size()); newpoly.Init((long)indices.size());
k=0; k=0;
for(iiter = indices.begin();iiter!=indices.end(); ++iiter) { for(iiter = indices.begin();iiter!=indices.end();iiter++) {
newpoly[k] = vertices[*iiter].p; newpoly[k] = vertices[*iiter].p;
k++; k++;
} }
@ -1055,18 +1065,19 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
//the algorithm used here is outlined in the book //the algorithm used here is outlined in the book
//"Computational Geometry: Algorithms and Applications" //"Computational Geometry: Algorithms and Applications"
//by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars //by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys) { int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys) {
list<TPPLPoly>::iterator iter; TPPLPolyList::iterator iter;
MonotoneVertex *vertices; MonotoneVertex *vertices = NULL;
long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices; long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
long polystartindex, polyendindex; long polystartindex, polyendindex;
TPPLPoly *poly; TPPLPoly *poly = NULL;
MonotoneVertex *v,*v2,*vprev,*vnext; MonotoneVertex *v = NULL,*v2 = NULL,*vprev = NULL,*vnext = NULL;
ScanLineEdge newedge; ScanLineEdge newedge;
bool error = false; bool error = false;
numvertices = 0; numvertices = 0;
for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) { for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
if(!iter->Valid()) return 0;
numvertices += iter->GetNumPoints(); numvertices += iter->GetNumPoints();
} }
@ -1075,7 +1086,7 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
newnumvertices = numvertices; newnumvertices = numvertices;
polystartindex = 0; polystartindex = 0;
for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) { for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
poly = &(*iter); poly = &(*iter);
polyendindex = polystartindex + poly->GetNumPoints()-1; polyendindex = polystartindex + poly->GetNumPoints()-1;
for(i=0;i<poly->GetNumPoints();i++) { for(i=0;i<poly->GetNumPoints();i++) {
@ -1130,6 +1141,7 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
set<ScanLineEdge>::iterator *edgeTreeIterators,edgeIter; set<ScanLineEdge>::iterator *edgeTreeIterators,edgeIter;
edgeTreeIterators = new set<ScanLineEdge>::iterator[maxnumvertices]; edgeTreeIterators = new set<ScanLineEdge>::iterator[maxnumvertices];
pair<set<ScanLineEdge>::iterator,bool> edgeTreeRet; pair<set<ScanLineEdge>::iterator,bool> edgeTreeRet;
for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = edgeTree.end();
//for each vertex //for each vertex
for(i=0;i<numvertices;i++) { for(i=0;i<numvertices;i++) {
@ -1152,16 +1164,15 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
break; break;
case TPPL_VERTEXTYPE_END: case TPPL_VERTEXTYPE_END:
if (edgeTreeIterators[v->previous] == edgeTree.end()) {
error = true;
break;
}
//if helper(ei-1) is a merge vertex //if helper(ei-1) is a merge vertex
if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
//Insert the diagonal connecting vi to helper(ei-1) in D. //Insert the diagonal connecting vi to helper(ei-1) in D.
AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
vertextypes[newnumvertices-2] = vertextypes[vindex]; vertextypes, edgeTreeIterators, &edgeTree, helpers);
edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
helpers[newnumvertices-2] = helpers[vindex];
vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
helpers[newnumvertices-1] = helpers[helpers[v->previous]];
} }
//Delete ei-1 from T //Delete ei-1 from T
edgeTree.erase(edgeTreeIterators[v->previous]); edgeTree.erase(edgeTreeIterators[v->previous]);
@ -1176,15 +1187,10 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
error = true; error = true;
break; break;
} }
--edgeIter; edgeIter--;
//Insert the diagonal connecting vi to helper(ej) in D. //Insert the diagonal connecting vi to helper(ej) in D.
AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]); AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
vertextypes[newnumvertices-2] = vertextypes[vindex]; vertextypes, edgeTreeIterators, &edgeTree, helpers);
edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
helpers[newnumvertices-2] = helpers[vindex];
vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
vindex2 = newnumvertices-2; vindex2 = newnumvertices-2;
v2 = &(vertices[vindex2]); v2 = &(vertices[vindex2]);
//helper(e j)<29>vi //helper(e j)<29>vi
@ -1199,16 +1205,15 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
break; break;
case TPPL_VERTEXTYPE_MERGE: case TPPL_VERTEXTYPE_MERGE:
if (edgeTreeIterators[v->previous] == edgeTree.end()) {
error = true;
break;
}
//if helper(ei-1) is a merge vertex //if helper(ei-1) is a merge vertex
if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
//Insert the diagonal connecting vi to helper(ei-1) in D. //Insert the diagonal connecting vi to helper(ei-1) in D.
AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
vertextypes[newnumvertices-2] = vertextypes[vindex]; vertextypes, edgeTreeIterators, &edgeTree, helpers);
edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
helpers[newnumvertices-2] = helpers[vindex];
vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
helpers[newnumvertices-1] = helpers[helpers[v->previous]];
vindex2 = newnumvertices-2; vindex2 = newnumvertices-2;
v2 = &(vertices[vindex2]); v2 = &(vertices[vindex2]);
} }
@ -1222,17 +1227,12 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
error = true; error = true;
break; break;
} }
--edgeIter; edgeIter--;
//if helper(ej) is a merge vertex //if helper(ej) is a merge vertex
if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) { if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
//Insert the diagonal connecting vi to helper(e j) in D. //Insert the diagonal connecting vi to helper(e j) in D.
AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index]); AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index],
vertextypes[newnumvertices-2] = vertextypes[vindex2]; vertextypes, edgeTreeIterators, &edgeTree, helpers);
edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex2];
helpers[newnumvertices-2] = helpers[vindex2];
vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
} }
//helper(e j)<29>vi //helper(e j)<29>vi
helpers[edgeIter->index] = vindex2; helpers[edgeIter->index] = vindex2;
@ -1241,16 +1241,15 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
case TPPL_VERTEXTYPE_REGULAR: case TPPL_VERTEXTYPE_REGULAR:
//if the interior of P lies to the right of vi //if the interior of P lies to the right of vi
if(Below(v->p,vertices[v->previous].p)) { if(Below(v->p,vertices[v->previous].p)) {
if (edgeTreeIterators[v->previous] == edgeTree.end()) {
error = true;
break;
}
//if helper(ei-1) is a merge vertex //if helper(ei-1) is a merge vertex
if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
//Insert the diagonal connecting vi to helper(ei-1) in D. //Insert the diagonal connecting vi to helper(ei-1) in D.
AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
vertextypes[newnumvertices-2] = vertextypes[vindex]; vertextypes, edgeTreeIterators, &edgeTree, helpers);
edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
helpers[newnumvertices-2] = helpers[vindex];
vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
helpers[newnumvertices-1] = helpers[helpers[v->previous]];
vindex2 = newnumvertices-2; vindex2 = newnumvertices-2;
v2 = &(vertices[vindex2]); v2 = &(vertices[vindex2]);
} }
@ -1272,17 +1271,12 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
error = true; error = true;
break; break;
} }
--edgeIter; edgeIter--;
//if helper(ej) is a merge vertex //if helper(ej) is a merge vertex
if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) { if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
//Insert the diagonal connecting vi to helper(e j) in D. //Insert the diagonal connecting vi to helper(e j) in D.
AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]); AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
vertextypes[newnumvertices-2] = vertextypes[vindex]; vertextypes, edgeTreeIterators, &edgeTree, helpers);
edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
helpers[newnumvertices-2] = helpers[vindex];
vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
} }
//helper(e j)<29>vi //helper(e j)<29>vi
helpers[edgeIter->index] = vindex; helpers[edgeIter->index] = vindex;
@ -1342,7 +1336,10 @@ int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *mo
} }
//adds a diagonal to the doubly-connected list of vertices //adds a diagonal to the doubly-connected list of vertices
void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2) { void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
char *vertextypes, set<ScanLineEdge>::iterator *edgeTreeIterators,
set<ScanLineEdge> *edgeTree, long *helpers)
{
long newindex1,newindex2; long newindex1,newindex2;
newindex1 = *numvertices; newindex1 = *numvertices;
@ -1364,6 +1361,18 @@ void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, lon
vertices[index2].next = newindex1; vertices[index2].next = newindex1;
vertices[newindex1].previous = index2; vertices[newindex1].previous = index2;
//update all relevant structures
vertextypes[newindex1] = vertextypes[index1];
edgeTreeIterators[newindex1] = edgeTreeIterators[index1];
helpers[newindex1] = helpers[index1];
if(edgeTreeIterators[newindex1] != edgeTree->end())
edgeTreeIterators[newindex1]->index = newindex1;
vertextypes[newindex2] = vertextypes[index2];
edgeTreeIterators[newindex2] = edgeTreeIterators[index2];
helpers[newindex2] = helpers[index2];
if(edgeTreeIterators[newindex2] != edgeTree->end())
edgeTreeIterators[newindex2]->index = newindex2;
} }
bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) { bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) {
@ -1375,7 +1384,7 @@ bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) {
} }
//sorts in the falling order of y values, if y is equal, x is used instead //sorts in the falling order of y values, if y is equal, x is used instead
bool TPPLPartition::VertexSorter::operator() (long index1, long index2) const { bool TPPLPartition::VertexSorter::operator() (long index1, long index2) {
if(vertices[index1].p.y > vertices[index2].p.y) return true; if(vertices[index1].p.y > vertices[index2].p.y) return true;
else if(vertices[index1].p.y == vertices[index2].p.y) { else if(vertices[index1].p.y == vertices[index2].p.y) {
if(vertices[index1].p.x > vertices[index2].p.x) return true; if(vertices[index1].p.x > vertices[index2].p.x) return true;
@ -1412,19 +1421,21 @@ bool TPPLPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const
//triangulates monotone polygon //triangulates monotone polygon
//O(n) time, O(n) space complexity //O(n) time, O(n) space complexity
int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles) { int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles) {
if(!inPoly->Valid()) return 0;
long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex; long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
TPPLPoint *points; TPPLPoint *points = NULL;
long numpoints; long numpoints;
TPPLPoly triangle; TPPLPoly triangle;
numpoints = inPoly->GetNumPoints(); numpoints = inPoly->GetNumPoints();
points = inPoly->GetPoints(); points = inPoly->GetPoints();
//trivial calses //trivial case
if(numpoints < 3) return 0;
if(numpoints == 3) { if(numpoints == 3) {
triangles->push_back(*inPoly); triangles->push_back(*inPoly);
return 1;
} }
topindex = 0; bottomindex=0; topindex = 0; bottomindex=0;
@ -1544,19 +1555,19 @@ int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangl
return 1; return 1;
} }
int TPPLPartition::Triangulate_MONO(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles) { int TPPLPartition::Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
list<TPPLPoly> monotone; TPPLPolyList monotone;
list<TPPLPoly>::iterator iter; TPPLPolyList::iterator iter;
if(!MonotonePartition(inpolys,&monotone)) return 0; if(!MonotonePartition(inpolys,&monotone)) return 0;
for(iter = monotone.begin(); iter!=monotone.end(); ++iter) { for(iter = monotone.begin(); iter!=monotone.end();iter++) {
if(!TriangulateMonotone(&(*iter),triangles)) return 0; if(!TriangulateMonotone(&(*iter),triangles)) return 0;
} }
return 1; return 1;
} }
int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, list<TPPLPoly> *triangles) { int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles) {
list<TPPLPoly> polys; TPPLPolyList polys;
polys.push_back(*poly); polys.push_back(*poly);
return Triangulate_MONO(&polys, triangles); return Triangulate_MONO(&polys, triangles);

View File

@ -18,9 +18,11 @@
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE. //THE SOFTWARE.
#ifndef POLYPARTITION_H
#define POLYPARTITION_H
#include <list> #include <list>
using namespace std; #include <set>
typedef double tppl_float; typedef double tppl_float;
@ -29,315 +31,349 @@ typedef double tppl_float;
//2D point structure //2D point structure
struct TPPLPoint { struct TPPLPoint {
tppl_float x; tppl_float x;
tppl_float y; tppl_float y;
// User-specified vertex identifier. Note that this isn't used internally
// by the library, but will be faithfully copied around.
int id;
TPPLPoint operator + (const TPPLPoint& p) const { TPPLPoint operator + (const TPPLPoint& p) const {
TPPLPoint r; TPPLPoint r;
r.x = x + p.x; r.x = x + p.x;
r.y = y + p.y; r.y = y + p.y;
return r; return r;
} }
TPPLPoint operator - (const TPPLPoint& p) const { TPPLPoint operator - (const TPPLPoint& p) const {
TPPLPoint r; TPPLPoint r;
r.x = x - p.x; r.x = x - p.x;
r.y = y - p.y; r.y = y - p.y;
return r; return r;
} }
TPPLPoint operator * (const tppl_float f ) const { TPPLPoint operator * (const tppl_float f ) const {
TPPLPoint r; TPPLPoint r;
r.x = x*f; r.x = x*f;
r.y = y*f; r.y = y*f;
return r; return r;
} }
TPPLPoint operator / (const tppl_float f ) const { TPPLPoint operator / (const tppl_float f ) const {
TPPLPoint r; TPPLPoint r;
r.x = x/f; r.x = x/f;
r.y = y/f; r.y = y/f;
return r; return r;
} }
bool operator==(const TPPLPoint& p) const { bool operator==(const TPPLPoint& p) const {
if((x == p.x)&&(y==p.y)) return true; if((x == p.x)&&(y==p.y)) return true;
else return false; else return false;
} }
bool operator!=(const TPPLPoint& p) const { bool operator!=(const TPPLPoint& p) const {
if((x == p.x)&&(y==p.y)) return false; if((x == p.x)&&(y==p.y)) return false;
else return true; else return true;
} }
}; };
//Polygon implemented as an array of points with a 'hole' flag //Polygon implemented as an array of points with a 'hole' flag
class TPPLPoly { class TPPLPoly {
protected: protected:
TPPLPoint *points; TPPLPoint *points;
long numpoints; long numpoints;
bool hole; bool hole;
public: public:
//constructors/destructors //constructors/destructors
TPPLPoly(); TPPLPoly();
~TPPLPoly(); ~TPPLPoly();
TPPLPoly(const TPPLPoly &src); TPPLPoly(const TPPLPoly &src);
TPPLPoly& operator=(const TPPLPoly &src); TPPLPoly& operator=(const TPPLPoly &src);
//getters and setters //getters and setters
long GetNumPoints() const { long GetNumPoints() const {
return numpoints; return numpoints;
} }
bool IsHole() const { bool IsHole() const {
return hole; return hole;
} }
void SetHole(bool hole) { void SetHole(bool hole) {
this->hole = hole; this->hole = hole;
} }
TPPLPoint &GetPoint(long i) { TPPLPoint &GetPoint(long i) {
return points[i]; return points[i];
} }
TPPLPoint *GetPoints() { const TPPLPoint &GetPoint(long i) const {
return points; return points[i];
} }
TPPLPoint& operator[] (int i) { TPPLPoint *GetPoints() {
return points[i]; return points;
} }
//clears the polygon points TPPLPoint& operator[] (int i) {
void Clear(); return points[i];
}
//inits the polygon with numpoints vertices const TPPLPoint& operator[] (int i) const {
void Init(long numpoints); return points[i];
}
//creates a triangle with points p1,p2,p3 //clears the polygon points
void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3); void Clear();
//inverts the orfer of vertices //inits the polygon with numpoints vertices
void Invert(); void Init(long numpoints);
//returns the orientation of the polygon //creates a triangle with points p1,p2,p3
//possible values: void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
// TPPL_CCW : polygon vertices are in counter-clockwise order
// TPPL_CW : polygon vertices are in clockwise order
// 0 : the polygon has no (measurable) area
int GetOrientation() const;
//sets the polygon orientation //inverts the orfer of vertices
//orientation can be void Invert();
// TPPL_CCW : sets vertices in counter-clockwise order
// TPPL_CW : sets vertices in clockwise order //returns the orientation of the polygon
void SetOrientation(int orientation); //possible values:
// TPPL_CCW : polygon vertices are in counter-clockwise order
// TPPL_CW : polygon vertices are in clockwise order
// 0 : the polygon has no (measurable) area
int GetOrientation() const;
//sets the polygon orientation
//orientation can be
// TPPL_CCW : sets vertices in counter-clockwise order
// TPPL_CW : sets vertices in clockwise order
void SetOrientation(int orientation);
//checks whether a polygon is valid or not
inline bool Valid() const { return this->numpoints >= 3; }
}; };
#ifdef TPPL_ALLOCATOR
typedef std::list<TPPLPoly, TPPL_ALLOCATOR(TPPLPoly)> TPPLPolyList;
#else
typedef std::list<TPPLPoly> TPPLPolyList;
#endif
class TPPLPartition { class TPPLPartition {
protected: protected:
struct PartitionVertex { struct PartitionVertex {
bool isActive; bool isActive;
bool isConvex; bool isConvex;
bool isEar; bool isEar;
TPPLPoint p; TPPLPoint p;
tppl_float angle; tppl_float angle;
PartitionVertex *previous; PartitionVertex *previous;
PartitionVertex *next; PartitionVertex *next;
};
struct MonotoneVertex { PartitionVertex();
TPPLPoint p; };
long previous;
long next;
};
class VertexSorter{ struct MonotoneVertex {
MonotoneVertex *vertices; TPPLPoint p;
public: long previous;
VertexSorter(MonotoneVertex *v) : vertices(v) {} long next;
bool operator() (long index1, long index2) const; };
};
struct Diagonal { class VertexSorter{
long index1; MonotoneVertex *vertices;
long index2; public:
}; VertexSorter(MonotoneVertex *v) : vertices(v) {}
bool operator() (long index1, long index2);
};
//dynamic programming state for minimum-weight triangulation struct Diagonal {
struct DPState { long index1;
bool visible; long index2;
tppl_float weight; };
long bestvertex;
};
//dynamic programming state for convex partitioning #ifdef TPPL_ALLOCATOR
struct DPState2 { typedef std::list<Diagonal, TPPL_ALLOCATOR(Diagonal)> DiagonalList;
bool visible; #else
long weight; typedef std::list<Diagonal> DiagonalList;
list<Diagonal> pairs; #endif
};
//edge that intersects the scanline //dynamic programming state for minimum-weight triangulation
struct ScanLineEdge { struct DPState {
long index; bool visible;
TPPLPoint p1; tppl_float weight;
TPPLPoint p2; long bestvertex;
};
//determines if the edge is to the left of another edge //dynamic programming state for convex partitioning
bool operator< (const ScanLineEdge & other) const; struct DPState2 {
bool visible;
long weight;
DiagonalList pairs;
};
bool IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const; //edge that intersects the scanline
}; struct ScanLineEdge {
mutable long index;
TPPLPoint p1;
TPPLPoint p2;
//standard helper functions //determines if the edge is to the left of another edge
bool IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3); bool operator< (const ScanLineEdge & other) const;
bool IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
bool IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p);
bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p); bool IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const;
bool InCone(PartitionVertex *v, TPPLPoint &p); };
int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22); //standard helper functions
bool IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
bool IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
bool IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p);
TPPLPoint Normalize(const TPPLPoint &p); bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2); bool InCone(PartitionVertex *v, TPPLPoint &p);
//helper functions for Triangulate_EC int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22);
void UpdateVertexReflexity(PartitionVertex *v);
void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices);
//helper functions for ConvexPartition_OPT TPPLPoint Normalize(const TPPLPoint &p);
void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates); tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2);
void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
//helper functions for MonotonePartition //helper functions for Triangulate_EC
bool Below(TPPLPoint &p1, TPPLPoint &p2); void UpdateVertexReflexity(PartitionVertex *v);
void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2); void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices);
//triangulates a monotone polygon, used in Triangulate_MONO //helper functions for ConvexPartition_OPT
int TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles); void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
public: //helper functions for MonotonePartition
bool Below(TPPLPoint &p1, TPPLPoint &p2);
void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
char *vertextypes, std::set<ScanLineEdge>::iterator *edgeTreeIterators,
std::set<ScanLineEdge> *edgeTree, long *helpers);
//simple heuristic procedure for removing holes from a list of polygons //triangulates a monotone polygon, used in Triangulate_MONO
//works by creating a diagonal from the rightmost hole vertex to some visible vertex int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles);
//time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
//space complexity: O(n)
//params:
// inpolys : a list of polygons that can contain holes
// vertices of all non-hole polys have to be in counter-clockwise order
// vertices of all hole polys have to be in clockwise order
// outpolys : a list of polygons without holes
//returns 1 on success, 0 on failure
int RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys);
//triangulates a polygon by ear clipping public:
//time complexity O(n^2), n is the number of vertices
//space complexity: O(n)
//params:
// poly : an input polygon to be triangulated
// vertices have to be in counter-clockwise order
// triangles : a list of triangles (result)
//returns 1 on success, 0 on failure
int Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles);
//triangulates a list of polygons that may contain holes by ear clipping algorithm //simple heuristic procedure for removing holes from a list of polygons
//first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon //works by creating a diagonal from the rightmost hole vertex to some visible vertex
//time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
//space complexity: O(n) //space complexity: O(n)
//params: //params:
// inpolys : a list of polygons to be triangulated (can contain holes) // inpolys : a list of polygons that can contain holes
// vertices of all non-hole polys have to be in counter-clockwise order // vertices of all non-hole polys have to be in counter-clockwise order
// vertices of all hole polys have to be in clockwise order // vertices of all hole polys have to be in clockwise order
// triangles : a list of triangles (result) // outpolys : a list of polygons without holes
//returns 1 on success, 0 on failure //returns 1 on success, 0 on failure
int Triangulate_EC(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles); int RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys);
//creates an optimal polygon triangulation in terms of minimal edge length //triangulates a polygon by ear clipping
//time complexity: O(n^3), n is the number of vertices //time complexity O(n^2), n is the number of vertices
//space complexity: O(n^2) //space complexity: O(n)
//params: //params:
// poly : an input polygon to be triangulated // poly : an input polygon to be triangulated
// vertices have to be in counter-clockwise order // vertices have to be in counter-clockwise order
// triangles : a list of triangles (result) // triangles : a list of triangles (result)
//returns 1 on success, 0 on failure //returns 1 on success, 0 on failure
int Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles); int Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles);
//triangulates a polygons by firstly partitioning it into monotone polygons //triangulates a list of polygons that may contain holes by ear clipping algorithm
//time complexity: O(n*log(n)), n is the number of vertices //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
//space complexity: O(n) //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
//params: //space complexity: O(n)
// poly : an input polygon to be triangulated //params:
// vertices have to be in counter-clockwise order // inpolys : a list of polygons to be triangulated (can contain holes)
// triangles : a list of triangles (result) // vertices of all non-hole polys have to be in counter-clockwise order
//returns 1 on success, 0 on failure // vertices of all hole polys have to be in clockwise order
int Triangulate_MONO(TPPLPoly *poly, list<TPPLPoly> *triangles); // triangles : a list of triangles (result)
//returns 1 on success, 0 on failure
int Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles);
//triangulates a list of polygons by firstly partitioning them into monotone polygons //creates an optimal polygon triangulation in terms of minimal edge length
//time complexity: O(n*log(n)), n is the number of vertices //time complexity: O(n^3), n is the number of vertices
//space complexity: O(n) //space complexity: O(n^2)
//params: //params:
// inpolys : a list of polygons to be triangulated (can contain holes) // poly : an input polygon to be triangulated
// vertices of all non-hole polys have to be in counter-clockwise order // vertices have to be in counter-clockwise order
// vertices of all hole polys have to be in clockwise order // triangles : a list of triangles (result)
// triangles : a list of triangles (result) //returns 1 on success, 0 on failure
//returns 1 on success, 0 on failure int Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles);
int Triangulate_MONO(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles);
//creates a monotone partition of a list of polygons that can contain holes //triangulates a polygons by firstly partitioning it into monotone polygons
//time complexity: O(n*log(n)), n is the number of vertices //time complexity: O(n*log(n)), n is the number of vertices
//space complexity: O(n) //space complexity: O(n)
//params: //params:
// inpolys : a list of polygons to be triangulated (can contain holes) // poly : an input polygon to be triangulated
// vertices of all non-hole polys have to be in counter-clockwise order // vertices have to be in counter-clockwise order
// vertices of all hole polys have to be in clockwise order // triangles : a list of triangles (result)
// monotonePolys : a list of monotone polygons (result) //returns 1 on success, 0 on failure
//returns 1 on success, 0 on failure int Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles);
int MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys);
//partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm //triangulates a list of polygons by firstly partitioning them into monotone polygons
//the algorithm gives at most four times the number of parts as the optimal algorithm //time complexity: O(n*log(n)), n is the number of vertices
//however, in practice it works much better than that and often gives optimal partition //space complexity: O(n)
//uses triangulation obtained by ear clipping as intermediate result //params:
//time complexity O(n^2), n is the number of vertices // inpolys : a list of polygons to be triangulated (can contain holes)
//space complexity: O(n) // vertices of all non-hole polys have to be in counter-clockwise order
//params: // vertices of all hole polys have to be in clockwise order
// poly : an input polygon to be partitioned // triangles : a list of triangles (result)
// vertices have to be in counter-clockwise order //returns 1 on success, 0 on failure
// parts : resulting list of convex polygons int Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles);
//returns 1 on success, 0 on failure
int ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts);
//partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm //creates a monotone partition of a list of polygons that can contain holes
//the algorithm gives at most four times the number of parts as the optimal algorithm //time complexity: O(n*log(n)), n is the number of vertices
//however, in practice it works much better than that and often gives optimal partition //space complexity: O(n)
//uses triangulation obtained by ear clipping as intermediate result //params:
//time complexity O(n^2), n is the number of vertices // inpolys : a list of polygons to be triangulated (can contain holes)
//space complexity: O(n) // vertices of all non-hole polys have to be in counter-clockwise order
//params: // vertices of all hole polys have to be in clockwise order
// inpolys : an input list of polygons to be partitioned // monotonePolys : a list of monotone polygons (result)
// vertices of all non-hole polys have to be in counter-clockwise order //returns 1 on success, 0 on failure
// vertices of all hole polys have to be in clockwise order int MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys);
// parts : resulting list of convex polygons
//returns 1 on success, 0 on failure
int ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *parts);
//optimal convex partitioning (in terms of number of resulting convex polygons) //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm
//using the Keil-Snoeyink algorithm //the algorithm gives at most four times the number of parts as the optimal algorithm
//M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998 //however, in practice it works much better than that and often gives optimal partition
//time complexity O(n^3), n is the number of vertices //uses triangulation obtained by ear clipping as intermediate result
//space complexity: O(n^3) //time complexity O(n^2), n is the number of vertices
// poly : an input polygon to be partitioned //space complexity: O(n)
// vertices have to be in counter-clockwise order //params:
// parts : resulting list of convex polygons // poly : an input polygon to be partitioned
//returns 1 on success, 0 on failure // vertices have to be in counter-clockwise order
int ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts); // parts : resulting list of convex polygons
//returns 1 on success, 0 on failure
int ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts);
//partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm
//the algorithm gives at most four times the number of parts as the optimal algorithm
//however, in practice it works much better than that and often gives optimal partition
//uses triangulation obtained by ear clipping as intermediate result
//time complexity O(n^2), n is the number of vertices
//space complexity: O(n)
//params:
// inpolys : an input list of polygons to be partitioned
// vertices of all non-hole polys have to be in counter-clockwise order
// vertices of all hole polys have to be in clockwise order
// parts : resulting list of convex polygons
//returns 1 on success, 0 on failure
int ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts);
//optimal convex partitioning (in terms of number of resulting convex polygons)
//using the Keil-Snoeyink algorithm
//M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998
//time complexity O(n^3), n is the number of vertices
//space complexity: O(n^3)
// poly : an input polygon to be partitioned
// vertices have to be in counter-clockwise order
// parts : resulting list of convex polygons
//returns 1 on success, 0 on failure
int ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts);
}; };
#endif