polypartition.cpp
Go to the documentation of this file.
00001 //Copyright (C) 2011 by Ivan Fratric
00002 //
00003 //Permission is hereby granted, free of charge, to any person obtaining a copy
00004 //of this software and associated documentation files (the "Software"), to deal
00005 //in the Software without restriction, including without limitation the rights
00006 //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00007 //copies of the Software, and to permit persons to whom the Software is
00008 //furnished to do so, subject to the following conditions:
00009 //
00010 //The above copyright notice and this permission notice shall be included in
00011 //all copies or substantial portions of the Software.
00012 //
00013 //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014 //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015 //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00016 //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017 //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018 //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00019 //THE SOFTWARE.
00020 
00021 
00022 #include <stdio.h>
00023 #include <string.h>
00024 #include <math.h>
00025 #include <list>
00026 #include <algorithm>
00027 #include <set>
00028 
00029 using namespace std;
00030 
00031 #include "srs_env_model_percp/but_plane_detector/polypartition.h"
00032 
00033 #define TPPL_VERTEXTYPE_REGULAR 0
00034 #define TPPL_VERTEXTYPE_START 1
00035 #define TPPL_VERTEXTYPE_END 2
00036 #define TPPL_VERTEXTYPE_SPLIT 3
00037 #define TPPL_VERTEXTYPE_MERGE 4
00038 
00039 TPPLPoly::TPPLPoly() {
00040         hole = false;
00041         numpoints = 0;
00042         points = NULL;
00043 }
00044 
00045 TPPLPoly::~TPPLPoly() {
00046         if(points) delete [] points;
00047 }
00048 
00049 void TPPLPoly::Clear() {
00050         if(points) delete [] points;
00051         hole = false;
00052         numpoints = 0;
00053         points = NULL;
00054 }
00055 
00056 void TPPLPoly::Init(long numpoints) {
00057         Clear();
00058         this->numpoints = numpoints;
00059         points = new TPPLPoint[numpoints];
00060 }
00061 
00062 void TPPLPoly::Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) {
00063         Init(3);
00064         points[0] = p1;
00065         points[1] = p2;
00066         points[2] = p3;
00067 }
00068 
00069 TPPLPoly::TPPLPoly(const TPPLPoly &src) {
00070         hole = src.hole;
00071         numpoints = src.numpoints;
00072         points = new TPPLPoint[numpoints];
00073         memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
00074 }
00075 
00076 TPPLPoly& TPPLPoly::operator=(const TPPLPoly &src) {
00077         Clear();
00078         hole = src.hole;
00079         numpoints = src.numpoints;
00080         points = new TPPLPoint[numpoints];
00081         memcpy(points, src.points, numpoints*sizeof(TPPLPoint));
00082         return *this;
00083 }
00084 
00085 int TPPLPoly::GetOrientation() {
00086         long i1,i2;
00087         tppl_float area = 0;
00088         for(i1=0; i1<numpoints; i1++) {
00089                 i2 = i1+1;
00090                 if(i2 == numpoints) i2 = 0;
00091                 area += points[i1].x * points[i2].y - points[i1].y * points[i2].x;
00092         }
00093         if(area>0) return TPPL_CCW;
00094         if(area<0) return TPPL_CW;
00095         return 0;
00096 }
00097 
00098 void TPPLPoly::SetOrientation(int orientation) {
00099         int polyorientation = GetOrientation();
00100         if(polyorientation&&(polyorientation!=orientation)) {
00101                 Invert();
00102         }
00103 }
00104 
00105 void TPPLPoly::Invert() {
00106         long i;
00107         TPPLPoint *invpoints;
00108 
00109         invpoints = new TPPLPoint[numpoints];
00110         for(i=0;i<numpoints;i++) {
00111                 invpoints[i] = points[numpoints-i-1];
00112         }
00113 
00114         delete [] points;
00115         points = invpoints;
00116 }
00117 
00118 TPPLPoint TPPLPartition::Normalize(const TPPLPoint &p) {
00119         TPPLPoint r;
00120         tppl_float n = sqrt(p.x*p.x + p.y*p.y);
00121         if(n!=0) {
00122                 r = p/n;
00123         } else {
00124                 r.x = 0;
00125                 r.y = 0;
00126         }
00127         return r;
00128 }
00129 
00130 tppl_float TPPLPartition::Distance(const TPPLPoint &p1, const TPPLPoint &p2) {
00131         tppl_float dx,dy;
00132         dx = p2.x - p1.x;
00133         dy = p2.y - p1.y;
00134         return(sqrt(dx*dx + dy*dy));
00135 }
00136 
00137 //checks if two lines intersect
00138 int TPPLPartition::Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22) {
00139         if((p11.x == p21.x)&&(p11.y == p21.y)) return 0;
00140         if((p11.x == p22.x)&&(p11.y == p22.y)) return 0;
00141         if((p12.x == p21.x)&&(p12.y == p21.y)) return 0;
00142         if((p12.x == p22.x)&&(p12.y == p22.y)) return 0;
00143 
00144         TPPLPoint v1ort,v2ort,v;
00145         tppl_float dot11,dot12,dot21,dot22;
00146 
00147         v1ort.x = p12.y-p11.y;
00148         v1ort.y = p11.x-p12.x;
00149 
00150         v2ort.x = p22.y-p21.y;
00151         v2ort.y = p21.x-p22.x;
00152 
00153         v = p21-p11;
00154         dot21 = v.x*v1ort.x + v.y*v1ort.y;
00155         v = p22-p11;
00156         dot22 = v.x*v1ort.x + v.y*v1ort.y;
00157 
00158         v = p11-p21;
00159         dot11 = v.x*v2ort.x + v.y*v2ort.y;
00160         v = p12-p21;
00161         dot12 = v.x*v2ort.x + v.y*v2ort.y;
00162 
00163         if(dot11*dot12>0) return 0;
00164         if(dot21*dot22>0) return 0;
00165 
00166         return 1;
00167 }
00168 
00169 //removes holes from inpolys by merging them with non-holes
00170 int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys) {
00171         list<TPPLPoly> polys;
00172         list<TPPLPoly>::iterator holeiter,polyiter,iter,iter2;
00173         long i,i2,holepointindex,polypointindex;
00174         TPPLPoint holepoint,polypoint,bestpolypoint;
00175         TPPLPoint linep1,linep2;
00176         TPPLPoint v1,v2;
00177         TPPLPoly newpoly;
00178         bool hasholes;
00179         bool pointvisible;
00180         bool pointfound;
00181 
00182         //check for trivial case (no holes)
00183         hasholes = false;
00184         for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
00185                 if(iter->IsHole()) {
00186                         hasholes = true;
00187                         break;
00188                 }
00189         }
00190         if(!hasholes) {
00191                 for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
00192                         outpolys->push_back(*iter);
00193                 }
00194                 return 1;
00195         }
00196 
00197         polys = *inpolys;
00198 
00199         while(1) {
00200                 //find the hole point with the largest x
00201                 hasholes = false;
00202                 for(iter = polys.begin(); iter!=polys.end(); iter++) {
00203                         if(!iter->IsHole()) continue;
00204 
00205                         if(!hasholes) {
00206                                 hasholes = true;
00207                                 holeiter = iter;
00208                                 holepointindex = 0;
00209                         }
00210 
00211                         for(i=0; i < iter->GetNumPoints(); i++) {
00212                                 if(iter->GetPoint(i).x > holeiter->GetPoint(holepointindex).x) {
00213                                         holeiter = iter;
00214                                         holepointindex = i;
00215                                 }
00216                         }
00217                 }
00218                 if(!hasholes) break;
00219                 holepoint = holeiter->GetPoint(holepointindex);
00220 
00221                 pointfound = false;
00222                 for(iter = polys.begin(); iter!=polys.end(); iter++) {
00223                         if(iter->IsHole()) continue;
00224                         for(i=0; i < iter->GetNumPoints(); i++) {
00225                                 if(iter->GetPoint(i).x <= holepoint.x) continue;
00226                                 if(!InCone(iter->GetPoint((i+iter->GetNumPoints()-1)%(iter->GetNumPoints())),
00227                                         iter->GetPoint(i),
00228                                         iter->GetPoint((i+1)%(iter->GetNumPoints())),
00229                                         holepoint))
00230                                         continue;
00231                                 polypoint = iter->GetPoint(i);
00232                                 if(pointfound) {
00233                                         v1 = Normalize(polypoint-holepoint);
00234                                         v2 = Normalize(bestpolypoint-holepoint);
00235                                         if(v2.x > v1.x) continue;
00236                                 }
00237                                 pointvisible = true;
00238                                 for(iter2 = polys.begin(); iter2!=polys.end(); iter2++) {
00239                                         if(iter2->IsHole()) continue;
00240                                         for(i2=0; i2 < iter2->GetNumPoints(); i2++) {
00241                                                 linep1 = iter2->GetPoint(i2);
00242                                                 linep2 = iter2->GetPoint((i2+1)%(iter2->GetNumPoints()));
00243                                                 if(Intersects(holepoint,polypoint,linep1,linep2)) {
00244                                                         pointvisible = false;
00245                                                         break;
00246                                                 }
00247                                         }
00248                                         if(!pointvisible) break;
00249                                 }
00250                                 if(pointvisible) {
00251                                         pointfound = true;
00252                                         bestpolypoint = polypoint;
00253                                         polyiter = iter;
00254                                         polypointindex = i;
00255                                 }
00256                         }
00257                 }
00258 
00259                 if(!pointfound) return 0;
00260 
00261                 newpoly.Init(holeiter->GetNumPoints() + polyiter->GetNumPoints() + 2);
00262                 i2 = 0;
00263                 for(i=0;i<=polypointindex;i++) {
00264                         newpoly[i2] = polyiter->GetPoint(i);
00265                         i2++;
00266                 }
00267                 for(i=0;i<=holeiter->GetNumPoints();i++) {
00268                         newpoly[i2] = holeiter->GetPoint((i+holepointindex)%holeiter->GetNumPoints());
00269                         i2++;
00270                 }
00271                 for(i=polypointindex;i<polyiter->GetNumPoints();i++) {
00272                         newpoly[i2] = polyiter->GetPoint(i);
00273                         i2++;
00274                 }
00275 
00276                 polys.erase(holeiter);
00277                 polys.erase(polyiter);
00278                 polys.push_back(newpoly);
00279         }
00280 
00281         for(iter = polys.begin(); iter!=polys.end(); iter++) {
00282                 outpolys->push_back(*iter);
00283         }
00284 
00285         return 1;
00286 }
00287 
00288 bool TPPLPartition::IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3) {
00289         tppl_float tmp;
00290         tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
00291         if(tmp>0) return 1;
00292         else return 0;
00293 }
00294 
00295 bool TPPLPartition::IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3) {
00296         tppl_float tmp;
00297         tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
00298         if(tmp<0) return 1;
00299         else return 0;
00300 }
00301 
00302 bool TPPLPartition::IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p) {
00303         if(IsConvex(p1,p,p2)) return false;
00304         if(IsConvex(p2,p,p3)) return false;
00305         if(IsConvex(p3,p,p1)) return false;
00306         return true;
00307 }
00308 
00309 bool TPPLPartition::InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p) {
00310         bool convex;
00311 
00312         convex = IsConvex(p1,p2,p3);
00313 
00314         if(convex) {
00315                 if(!IsConvex(p1,p2,p)) return false;
00316                 if(!IsConvex(p2,p3,p)) return false;
00317                 return true;
00318         } else {
00319                 if(IsConvex(p1,p2,p)) return true;
00320                 if(IsConvex(p2,p3,p)) return true;
00321                 return false;
00322         }
00323 }
00324 
00325 bool TPPLPartition::InCone(PartitionVertex *v, TPPLPoint &p) {
00326         TPPLPoint p1,p2,p3;
00327 
00328         p1 = v->previous->p;
00329         p2 = v->p;
00330         p3 = v->next->p;
00331 
00332         return InCone(p1,p2,p3,p);
00333 }
00334 
00335 void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) {
00336         PartitionVertex *v1,*v3;
00337         v1 = v->previous;
00338         v3 = v->next;
00339         v->isConvex = !IsReflex(v1->p,v->p,v3->p);
00340 }
00341 
00342 void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) {
00343         long i;
00344         PartitionVertex *v1,*v3;
00345         TPPLPoint vec1,vec3;
00346 
00347         v1 = v->previous;
00348         v3 = v->next;
00349 
00350         v->isConvex = IsConvex(v1->p,v->p,v3->p);
00351 
00352         vec1 = Normalize(v1->p - v->p);
00353         vec3 = Normalize(v3->p - v->p);
00354         v->angle = vec1.x*vec3.x + vec1.y*vec3.y;
00355 
00356         if(v->isConvex) {
00357                 v->isEar = true;
00358                 for(i=0;i<numvertices;i++) {
00359                         if((vertices[i].p.x==v->p.x)&&(vertices[i].p.y==v->p.y)) continue;
00360                         if((vertices[i].p.x==v1->p.x)&&(vertices[i].p.y==v1->p.y)) continue;
00361                         if((vertices[i].p.x==v3->p.x)&&(vertices[i].p.y==v3->p.y)) continue;
00362                         if(IsInside(v1->p,v->p,v3->p,vertices[i].p)) {
00363                                 v->isEar = false;
00364                                 break;
00365                         }
00366                 }
00367         } else {
00368                 v->isEar = false;
00369         }
00370 }
00371 
00372 //triangulation by ear removal
00373 int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) {
00374         long numvertices;
00375         PartitionVertex *vertices;
00376         PartitionVertex *ear;
00377         TPPLPoly triangle;
00378         long i,j;
00379         bool earfound;
00380 
00381         if(poly->GetNumPoints() < 3) return 0;
00382         if(poly->GetNumPoints() == 3) {
00383                 triangles->push_back(*poly);
00384                 return 1;
00385         }
00386 
00387         numvertices = poly->GetNumPoints();
00388 
00389         vertices = new PartitionVertex[numvertices];
00390         for(i=0;i<numvertices;i++) {
00391                 vertices[i].isActive = true;
00392                 vertices[i].p = poly->GetPoint(i);
00393                 if(i==(numvertices-1)) vertices[i].next=&(vertices[0]);
00394                 else vertices[i].next=&(vertices[i+1]);
00395                 if(i==0) vertices[i].previous = &(vertices[numvertices-1]);
00396                 else vertices[i].previous = &(vertices[i-1]);
00397         }
00398         for(i=0;i<numvertices;i++) {
00399                 UpdateVertex(&vertices[i],vertices,numvertices);
00400         }
00401 
00402         for(i=0;i<numvertices-3;i++) {
00403                 earfound = false;
00404                 //find the most extruded ear
00405                 for(j=0;j<numvertices;j++) {
00406                         if(!vertices[j].isActive) continue;
00407                         if(!vertices[j].isEar) continue;
00408                         if(!earfound) {
00409                                 earfound = true;
00410                                 ear = &(vertices[j]);
00411                         } else {
00412                                 if(vertices[j].angle > ear->angle) {
00413                                         ear = &(vertices[j]);
00414                                 }
00415                         }
00416                 }
00417                 if(!earfound) {
00418                         delete [] vertices;
00419                         return 0;
00420                 }
00421 
00422                 triangle.Triangle(ear->previous->p,ear->p,ear->next->p);
00423                 triangles->push_back(triangle);
00424 
00425                 ear->isActive = false;
00426                 ear->previous->next = ear->next;
00427                 ear->next->previous = ear->previous;
00428 
00429                 if(i==numvertices-4) break;
00430 
00431                 UpdateVertex(ear->previous,vertices,numvertices);
00432                 UpdateVertex(ear->next,vertices,numvertices);
00433         }
00434         for(i=0;i<numvertices;i++) {
00435                 if(vertices[i].isActive) {
00436                         triangle.Triangle(vertices[i].previous->p,vertices[i].p,vertices[i].next->p);
00437                         triangles->push_back(triangle);
00438                         break;
00439                 }
00440         }
00441 
00442         delete [] vertices;
00443 
00444         return 1;
00445 }
00446 
00447 int TPPLPartition::Triangulate_EC(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles) {
00448         list<TPPLPoly> outpolys;
00449         list<TPPLPoly>::iterator iter;
00450 
00451         if(!RemoveHoles(inpolys,&outpolys)) return 0;
00452         for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
00453                 if(!Triangulate_EC(&(*iter),triangles)) return 0;
00454         }
00455         return 1;
00456 }
00457 
00458 int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
00459         list<TPPLPoly> triangles;
00460         list<TPPLPoly>::iterator iter1,iter2;
00461         TPPLPoly *poly1,*poly2;
00462         TPPLPoly newpoly;
00463         TPPLPoint d1,d2,p1,p2,p3;
00464         long i11,i12,i21,i22,i13,i23,j,k;
00465         bool isdiagonal;
00466         long numreflex;
00467 
00468         //check if the poly is already convex
00469         numreflex = 0;
00470         for(i11=0;i11<poly->GetNumPoints();i11++) {
00471                 if(i11==0) i12 = poly->GetNumPoints()-1;
00472                 else i12=i11-1;
00473                 if(i11==(poly->GetNumPoints()-1)) i13=0;
00474                 else i13=i11+1;
00475                 if(IsReflex(poly->GetPoint(i12),poly->GetPoint(i11),poly->GetPoint(i13))) {
00476                         numreflex = 1;
00477                         break;
00478                 }
00479         }
00480         if(numreflex == 0) {
00481                 parts->push_back(*poly);
00482                 return 1;
00483         }
00484 
00485         if(!Triangulate_EC(poly,&triangles)) return 0;
00486 
00487         for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
00488                 poly1 = &(*iter1);
00489                 for(i11=0;i11<poly1->GetNumPoints();i11++) {
00490                         d1 = poly1->GetPoint(i11);
00491                         i12 = (i11+1)%(poly1->GetNumPoints());
00492                         d2 = poly1->GetPoint(i12);
00493 
00494                         isdiagonal = false;
00495                         for(iter2 = iter1; iter2 != triangles.end(); iter2++) {
00496                                 if(iter1 == iter2) continue;
00497                                 poly2 = &(*iter2);
00498 
00499                                 for(i21=0;i21<poly2->GetNumPoints();i21++) {
00500                                         if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue;
00501                                         i22 = (i21+1)%(poly2->GetNumPoints());
00502                                         if((d1.x != poly2->GetPoint(i22).x)||(d1.y != poly2->GetPoint(i22).y)) continue;
00503                                         isdiagonal = true;
00504                                         break;
00505                                 }
00506                                 if(isdiagonal) break;
00507                         }
00508 
00509                         if(!isdiagonal) continue;
00510 
00511                         p2 = poly1->GetPoint(i11);
00512                         if(i11 == 0) i13 = poly1->GetNumPoints()-1;
00513                         else i13 = i11-1;
00514                         p1 = poly1->GetPoint(i13);
00515                         if(i22 == (poly2->GetNumPoints()-1)) i23 = 0;
00516                         else i23 = i22+1;
00517                         p3 = poly2->GetPoint(i23);
00518 
00519                         if(!IsConvex(p1,p2,p3)) continue;
00520 
00521                         p2 = poly1->GetPoint(i12);
00522                         if(i12 == (poly1->GetNumPoints()-1)) i13 = 0;
00523                         else i13 = i12+1;
00524                         p3 = poly1->GetPoint(i13);
00525                         if(i21 == 0) i23 = poly2->GetNumPoints()-1;
00526                         else i23 = i21-1;
00527                         p1 = poly2->GetPoint(i23);
00528 
00529                         if(!IsConvex(p1,p2,p3)) continue;
00530 
00531                         newpoly.Init(poly1->GetNumPoints()+poly2->GetNumPoints()-2);
00532                         k = 0;
00533                         for(j=i12;j!=i11;j=(j+1)%(poly1->GetNumPoints())) {
00534                                 newpoly[k] = poly1->GetPoint(j);
00535                                 k++;
00536                         }
00537                         for(j=i22;j!=i21;j=(j+1)%(poly2->GetNumPoints())) {
00538                                 newpoly[k] = poly2->GetPoint(j);
00539                                 k++;
00540                         }
00541 
00542                         triangles.erase(iter2);
00543                         *iter1 = newpoly;
00544                         poly1 = &(*iter1);
00545                         i11 = -1;
00546 
00547                         continue;
00548                 }
00549         }
00550 
00551         for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
00552                 parts->push_back(*iter1);
00553         }
00554 
00555         return 1;
00556 }
00557 
00558 int TPPLPartition::ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *parts) {
00559         list<TPPLPoly> outpolys;
00560         list<TPPLPoly>::iterator iter;
00561 
00562         if(!RemoveHoles(inpolys,&outpolys)) return 0;
00563         for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
00564                 if(!ConvexPartition_HM(&(*iter),parts)) return 0;
00565         }
00566         return 1;
00567 }
00568 
00569 //minimum-weight polygon triangulation by dynamic programming
00570 //O(n^3) time complexity
00571 //O(n^2) space complexity
00572 int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) {
00573         long i,j,k,gap,n;
00574         DPState **dpstates;
00575         TPPLPoint p1,p2,p3,p4;
00576         long bestvertex;
00577         tppl_float weight,minweight,d1,d2;
00578         Diagonal diagonal,newdiagonal;
00579         list<Diagonal> diagonals;
00580         TPPLPoly triangle;
00581         int ret = 1;
00582 
00583         n = poly->GetNumPoints();
00584         dpstates = new DPState *[n];
00585         for(i=1;i<n;i++) {
00586                 dpstates[i] = new DPState[i];
00587         }
00588 
00589         //init states and visibility
00590         for(i=0;i<(n-1);i++) {
00591                 p1 = poly->GetPoint(i);
00592                 for(j=i+1;j<n;j++) {
00593                         dpstates[j][i].visible = true;
00594                         dpstates[j][i].weight = 0;
00595                         dpstates[j][i].bestvertex = -1;
00596                         if(j!=(i+1)) {
00597                                 p2 = poly->GetPoint(j);
00598 
00599                                 //visibility check
00600                                 if(i==0) p3 = poly->GetPoint(n-1);
00601                                 else p3 = poly->GetPoint(i-1);
00602                                 if(i==(n-1)) p4 = poly->GetPoint(0);
00603                                 else p4 = poly->GetPoint(i+1);
00604                                 if(!InCone(p3,p1,p4,p2)) {
00605                                         dpstates[j][i].visible = false;
00606                                         continue;
00607                                 }
00608 
00609                                 if(j==0) p3 = poly->GetPoint(n-1);
00610                                 else p3 = poly->GetPoint(j-1);
00611                                 if(j==(n-1)) p4 = poly->GetPoint(0);
00612                                 else p4 = poly->GetPoint(j+1);
00613                                 if(!InCone(p3,p2,p4,p1)) {
00614                                         dpstates[j][i].visible = false;
00615                                         continue;
00616                                 }
00617 
00618                                 for(k=0;k<n;k++) {
00619                                         p3 = poly->GetPoint(k);
00620                                         if(k==(n-1)) p4 = poly->GetPoint(0);
00621                                         else p4 = poly->GetPoint(k+1);
00622                                         if(Intersects(p1,p2,p3,p4)) {
00623                                                 dpstates[j][i].visible = false;
00624                                                 break;
00625                                         }
00626                                 }
00627                         }
00628                 }
00629         }
00630         dpstates[n-1][0].visible = true;
00631         dpstates[n-1][0].weight = 0;
00632         dpstates[n-1][0].bestvertex = -1;
00633 
00634         for(gap = 2; gap<n; gap++) {
00635                 for(i=0; i<(n-gap); i++) {
00636                         j = i+gap;
00637                         if(!dpstates[j][i].visible) continue;
00638                         bestvertex = -1;
00639                         for(k=(i+1);k<j;k++) {
00640                                 if(!dpstates[k][i].visible) continue;
00641                                 if(!dpstates[j][k].visible) continue;
00642 
00643                                 if(k<=(i+1)) d1=0;
00644                                 else d1 = Distance(poly->GetPoint(i),poly->GetPoint(k));
00645                                 if(j<=(k+1)) d2=0;
00646                                 else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j));
00647 
00648                                 weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2;
00649 
00650                                 if((bestvertex == -1)||(weight<minweight)) {
00651                                         bestvertex = k;
00652                                         minweight = weight;
00653                                 }
00654                         }
00655                         if(bestvertex == -1) {
00656                                 for(i=1;i<n;i++) {
00657                                         delete [] dpstates[i];
00658                                 }
00659                                 delete [] dpstates;
00660 
00661                                 return 0;
00662                         }
00663 
00664                         dpstates[j][i].bestvertex = bestvertex;
00665                         dpstates[j][i].weight = minweight;
00666                 }
00667         }
00668 
00669         newdiagonal.index1 = 0;
00670         newdiagonal.index2 = n-1;
00671         diagonals.push_back(newdiagonal);
00672         while(!diagonals.empty()) {
00673                 diagonal = *(diagonals.begin());
00674                 diagonals.pop_front();
00675                 bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
00676                 if(bestvertex == -1) {
00677                         ret = 0;
00678                         break;
00679                 }
00680                 triangle.Triangle(poly->GetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2));
00681                 triangles->push_back(triangle);
00682                 if(bestvertex > (diagonal.index1+1)) {
00683                         newdiagonal.index1 = diagonal.index1;
00684                         newdiagonal.index2 = bestvertex;
00685                         diagonals.push_back(newdiagonal);
00686                 }
00687                 if(diagonal.index2 > (bestvertex+1)) {
00688                         newdiagonal.index1 = bestvertex;
00689                         newdiagonal.index2 = diagonal.index2;
00690                         diagonals.push_back(newdiagonal);
00691                 }
00692         }
00693 
00694         for(i=1;i<n;i++) {
00695                 delete [] dpstates[i];
00696         }
00697         delete [] dpstates;
00698 
00699         return ret;
00700 }
00701 
00702 void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) {
00703         Diagonal newdiagonal;
00704         list<Diagonal> *pairs;
00705         long w2;
00706 
00707         w2 = dpstates[a][b].weight;
00708         if(w>w2) return;
00709 
00710         pairs = &(dpstates[a][b].pairs);
00711         newdiagonal.index1 = i;
00712         newdiagonal.index2 = j;
00713 
00714         if(w<w2) {
00715                 pairs->clear();
00716                 pairs->push_front(newdiagonal);
00717                 dpstates[a][b].weight = w;
00718         } else {
00719                 if((!pairs->empty())&&(i <= pairs->begin()->index1)) return;
00720                 while((!pairs->empty())&&(pairs->begin()->index2 >= j)) pairs->pop_front();
00721                 pairs->push_front(newdiagonal);
00722         }
00723 }
00724 
00725 void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
00726         list<Diagonal> *pairs;
00727         list<Diagonal>::iterator iter,lastiter;
00728         long top;
00729         long w;
00730 
00731         if(!dpstates[i][j].visible) return;
00732         top = j;
00733         w = dpstates[i][j].weight;
00734     if(k-j > 1) {
00735                 if (!dpstates[j][k].visible) return;
00736                 w += dpstates[j][k].weight + 1;
00737     }
00738         if(j-i > 1) {
00739                 pairs = &(dpstates[i][j].pairs);
00740                 iter = pairs->end();
00741                 lastiter = pairs->end();
00742                 while(iter!=pairs->begin()) {
00743                         iter--;
00744                         if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = iter;
00745                         else break;
00746                 }
00747                 if(lastiter == pairs->end()) w++;
00748                 else {
00749                         if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->index1].p)) w++;
00750                         else top = lastiter->index1;
00751                 }
00752         }
00753         UpdateState(i,k,w,top,j,dpstates);
00754 }
00755 
00756 void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
00757         list<Diagonal> *pairs;
00758         list<Diagonal>::iterator iter,lastiter;
00759         long top;
00760         long w;
00761 
00762         if(!dpstates[j][k].visible) return;
00763         top = j;
00764         w = dpstates[j][k].weight;
00765 
00766         if (j-i > 1) {
00767                 if (!dpstates[i][j].visible) return;
00768                 w += dpstates[i][j].weight + 1;
00769         }
00770         if (k-j > 1) {
00771                 pairs = &(dpstates[j][k].pairs);
00772 
00773                 iter = pairs->begin();
00774                 if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p))) {
00775                         lastiter = iter;
00776                         while(iter!=pairs->end()) {
00777                                 if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) {
00778                                         lastiter = iter;
00779                                         iter++;
00780                                 }
00781                                 else break;
00782                         }
00783                         if(IsReflex(vertices[lastiter->index2].p,vertices[k].p,vertices[i].p)) w++;
00784                         else top = lastiter->index2;
00785                 } else w++;
00786         }
00787         UpdateState(i,k,w,j,top,dpstates);
00788 }
00789 
00790 int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
00791         TPPLPoint p1,p2,p3,p4;
00792         PartitionVertex *vertices;
00793         DPState2 **dpstates;
00794         long i,j,k,n,gap;
00795         list<Diagonal> diagonals,diagonals2;
00796         Diagonal diagonal,newdiagonal;
00797         list<Diagonal> *pairs,*pairs2;
00798         list<Diagonal>::iterator iter,iter2;
00799         int ret;
00800         TPPLPoly newpoly;
00801         list<long> indices;
00802         list<long>::iterator iiter;
00803         bool ijreal,jkreal;
00804 
00805         n = poly->GetNumPoints();
00806         vertices = new PartitionVertex[n];
00807 
00808         dpstates = new DPState2 *[n];
00809         for(i=0;i<n;i++) {
00810                 dpstates[i] = new DPState2[n];
00811         }
00812 
00813         //init vertex information
00814         for(i=0;i<n;i++) {
00815                 vertices[i].p = poly->GetPoint(i);
00816                 vertices[i].isActive = true;
00817                 if(i==0) vertices[i].previous = &(vertices[n-1]);
00818                 else vertices[i].previous = &(vertices[i-1]);
00819                 if(i==(poly->GetNumPoints()-1)) vertices[i].next = &(vertices[0]);
00820                 else vertices[i].next = &(vertices[i+1]);
00821         }
00822         for(i=1;i<n;i++) {
00823                 UpdateVertexReflexity(&(vertices[i]));
00824         }
00825 
00826         //init states and visibility
00827         for(i=0;i<(n-1);i++) {
00828                 p1 = poly->GetPoint(i);
00829                 for(j=i+1;j<n;j++) {
00830                         dpstates[i][j].visible = true;
00831                         if(j==i+1) {
00832                                 dpstates[i][j].weight = 0;
00833                         } else {
00834                                 dpstates[i][j].weight = 2147483647;
00835                         }
00836                         if(j!=(i+1)) {
00837                                 p2 = poly->GetPoint(j);
00838 
00839                                 //visibility check
00840                                 if(!InCone(&vertices[i],p2)) {
00841                                         dpstates[i][j].visible = false;
00842                                         continue;
00843                                 }
00844                                 if(!InCone(&vertices[j],p1)) {
00845                                         dpstates[i][j].visible = false;
00846                                         continue;
00847                                 }
00848 
00849                                 for(k=0;k<n;k++) {
00850                                         p3 = poly->GetPoint(k);
00851                                         if(k==(n-1)) p4 = poly->GetPoint(0);
00852                                         else p4 = poly->GetPoint(k+1);
00853                                         if(Intersects(p1,p2,p3,p4)) {
00854                                                 dpstates[i][j].visible = false;
00855                                                 break;
00856                                         }
00857                                 }
00858                         }
00859                 }
00860         }
00861         for(i=0;i<(n-2);i++) {
00862                 j = i+2;
00863                 if(dpstates[i][j].visible) {
00864                         dpstates[i][j].weight = 0;
00865                         newdiagonal.index1 = i+1;
00866                         newdiagonal.index2 = i+1;
00867                         dpstates[i][j].pairs.push_back(newdiagonal);
00868                 }
00869         }
00870 
00871         dpstates[0][n-1].visible = true;
00872         vertices[0].isConvex = false; //by convention
00873 
00874         for(gap=3; gap<n; gap++) {
00875                 for(i=0;i<n-gap;i++) {
00876                         if(vertices[i].isConvex) continue;
00877                         k = i+gap;
00878                         if(dpstates[i][k].visible) {
00879                                 if(!vertices[k].isConvex) {
00880                                         for(j=i+1;j<k;j++) TypeA(i,j,k,vertices,dpstates);
00881                                 } else {
00882                                         for(j=i+1;j<(k-1);j++) {
00883                                                 if(vertices[j].isConvex) continue;
00884                                                 TypeA(i,j,k,vertices,dpstates);
00885                                         }
00886                                         TypeA(i,k-1,k,vertices,dpstates);
00887                                 }
00888                         }
00889                 }
00890                 for(k=gap;k<n;k++) {
00891                         if(vertices[k].isConvex) continue;
00892                         i = k-gap;
00893                         if((vertices[i].isConvex)&&(dpstates[i][k].visible)) {
00894                                 TypeB(i,i+1,k,vertices,dpstates);
00895                                 for(j=i+2;j<k;j++) {
00896                                         if(vertices[j].isConvex) continue;
00897                                         TypeB(i,j,k,vertices,dpstates);
00898                                 }
00899                         }
00900                 }
00901         }
00902 
00903 
00904         //recover solution
00905         ret = 1;
00906         newdiagonal.index1 = 0;
00907         newdiagonal.index2 = n-1;
00908         diagonals.push_front(newdiagonal);
00909         while(!diagonals.empty()) {
00910                 diagonal = *(diagonals.begin());
00911                 diagonals.pop_front();
00912                 if((diagonal.index2 - diagonal.index1) <=1) continue;
00913                 pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
00914                 if(pairs->empty()) {
00915                         ret = 0;
00916                         break;
00917                 }
00918                 if(!vertices[diagonal.index1].isConvex) {
00919                         iter = pairs->end();
00920                         iter--;
00921                         j = iter->index2;
00922                         newdiagonal.index1 = j;
00923                         newdiagonal.index2 = diagonal.index2;
00924                         diagonals.push_front(newdiagonal);
00925                         if((j - diagonal.index1)>1) {
00926                                 if(iter->index1 != iter->index2) {
00927                                         pairs2 = &(dpstates[diagonal.index1][j].pairs);
00928                                         while(1) {
00929                                                 if(pairs2->empty()) {
00930                                                         ret = 0;
00931                                                         break;
00932                                                 }
00933                                                 iter2 = pairs2->end();
00934                                                 iter2--;
00935                                                 if(iter->index1 != iter2->index1) pairs2->pop_back();
00936                                                 else break;
00937                                         }
00938                                         if(ret == 0) break;
00939                                 }
00940                                 newdiagonal.index1 = diagonal.index1;
00941                                 newdiagonal.index2 = j;
00942                                 diagonals.push_front(newdiagonal);
00943                         }
00944                 } else {
00945                         iter = pairs->begin();
00946                         j = iter->index1;
00947                         newdiagonal.index1 = diagonal.index1;
00948                         newdiagonal.index2 = j;
00949                         diagonals.push_front(newdiagonal);
00950                         if((diagonal.index2 - j) > 1) {
00951                                 if(iter->index1 != iter->index2) {
00952                                         pairs2 = &(dpstates[j][diagonal.index2].pairs);
00953                                         while(1) {
00954                                                 if(pairs2->empty()) {
00955                                                         ret = 0;
00956                                                         break;
00957                                                 }
00958                                                 iter2 = pairs2->begin();
00959                                                 if(iter->index2 != iter2->index2) pairs2->pop_front();
00960                                                 else break;
00961                                         }
00962                                         if(ret == 0) break;
00963                                 }
00964                                 newdiagonal.index1 = j;
00965                                 newdiagonal.index2 = diagonal.index2;
00966                                 diagonals.push_front(newdiagonal);
00967                         }
00968                 }
00969         }
00970 
00971         if(ret == 0) {
00972                 for(i=0;i<n;i++) {
00973                         delete [] dpstates[i];
00974                 }
00975                 delete [] dpstates;
00976                 delete [] vertices;
00977 
00978                 return ret;
00979         }
00980 
00981         newdiagonal.index1 = 0;
00982         newdiagonal.index2 = n-1;
00983         diagonals.push_front(newdiagonal);
00984         while(!diagonals.empty()) {
00985                 diagonal = *(diagonals.begin());
00986                 diagonals.pop_front();
00987                 if((diagonal.index2 - diagonal.index1) <= 1) continue;
00988 
00989                 indices.clear();
00990                 diagonals2.clear();
00991                 indices.push_back(diagonal.index1);
00992                 indices.push_back(diagonal.index2);
00993                 diagonals2.push_front(diagonal);
00994 
00995                 while(!diagonals2.empty()) {
00996                         diagonal = *(diagonals2.begin());
00997                         diagonals2.pop_front();
00998                         if((diagonal.index2 - diagonal.index1) <= 1) continue;
00999                         ijreal = true;
01000                         jkreal = true;
01001                         pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
01002                         if(!vertices[diagonal.index1].isConvex) {
01003                                 iter = pairs->end();
01004                                 iter--;
01005                                 j = iter->index2;
01006                                 if(iter->index1 != iter->index2) ijreal = false;
01007                         } else {
01008                                 iter = pairs->begin();
01009                                 j = iter->index1;
01010                                 if(iter->index1 != iter->index2) jkreal = false;
01011                         }
01012 
01013                         newdiagonal.index1 = diagonal.index1;
01014                         newdiagonal.index2 = j;
01015                         if(ijreal) {
01016                                 diagonals.push_back(newdiagonal);
01017                         } else {
01018                                 diagonals2.push_back(newdiagonal);
01019                         }
01020 
01021                         newdiagonal.index1 = j;
01022                         newdiagonal.index2 = diagonal.index2;
01023                         if(jkreal) {
01024                                 diagonals.push_back(newdiagonal);
01025                         } else {
01026                                 diagonals2.push_back(newdiagonal);
01027                         }
01028 
01029                         indices.push_back(j);
01030                 }
01031 
01032                 indices.sort();
01033                 newpoly.Init((long)indices.size());
01034                 k=0;
01035                 for(iiter = indices.begin();iiter!=indices.end();iiter++) {
01036                         newpoly[k] = vertices[*iiter].p;
01037                         k++;
01038                 }
01039                 parts->push_back(newpoly);
01040         }
01041 
01042         for(i=0;i<n;i++) {
01043                 delete [] dpstates[i];
01044         }
01045         delete [] dpstates;
01046         delete [] vertices;
01047 
01048         return ret;
01049 }
01050 
01051 //triangulates a set of polygons by first partitioning them into monotone polygons
01052 //O(n*log(n)) time complexity, O(n) space complexity
01053 //the algorithm used here is outlined in the book
01054 //"Computational Geometry: Algorithms and Applications"
01055 //by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
01056 int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys) {
01057         list<TPPLPoly>::iterator iter;
01058         MonotoneVertex *vertices;
01059         long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
01060         long polystartindex, polyendindex;
01061         TPPLPoly *poly;
01062         MonotoneVertex *v,*v2,*vprev,*vnext;
01063         ScanLineEdge newedge;
01064         bool error = false;
01065 
01066         numvertices = 0;
01067         for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
01068                 numvertices += iter->GetNumPoints();
01069         }
01070 
01071         maxnumvertices = numvertices*3;
01072         vertices = new MonotoneVertex[maxnumvertices];
01073         newnumvertices = numvertices;
01074 
01075         polystartindex = 0;
01076         for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
01077                 poly = &(*iter);
01078                 polyendindex = polystartindex + poly->GetNumPoints()-1;
01079                 for(i=0;i<poly->GetNumPoints();i++) {
01080                         vertices[i+polystartindex].p = poly->GetPoint(i);
01081                         if(i==0) vertices[i+polystartindex].previous = polyendindex;
01082                         else vertices[i+polystartindex].previous = i+polystartindex-1;
01083                         if(i==(poly->GetNumPoints()-1)) vertices[i+polystartindex].next = polystartindex;
01084                         else vertices[i+polystartindex].next = i+polystartindex+1;
01085                 }
01086                 polystartindex = polyendindex+1;
01087         }
01088 
01089         //construct the priority queue
01090         long *priority = new long [numvertices];
01091         for(i=0;i<numvertices;i++) priority[i] = i;
01092         std::sort(priority,&(priority[numvertices]),VertexSorter(vertices));
01093 
01094         //determine vertex types
01095         char *vertextypes = new char[maxnumvertices];
01096         for(i=0;i<numvertices;i++) {
01097                 v = &(vertices[i]);
01098                 vprev = &(vertices[v->previous]);
01099                 vnext = &(vertices[v->next]);
01100 
01101                 if(Below(vprev->p,v->p)&&Below(vnext->p,v->p)) {
01102                         if(IsConvex(vnext->p,vprev->p,v->p)) {
01103                                 vertextypes[i] = TPPL_VERTEXTYPE_START;
01104                         } else {
01105                                 vertextypes[i] = TPPL_VERTEXTYPE_SPLIT;
01106                         }
01107                 } else if(Below(v->p,vprev->p)&&Below(v->p,vnext->p)) {
01108                         if(IsConvex(vnext->p,vprev->p,v->p))
01109                         {
01110                                 vertextypes[i] = TPPL_VERTEXTYPE_END;
01111                         } else {
01112                                 vertextypes[i] = TPPL_VERTEXTYPE_MERGE;
01113                         }
01114                 } else {
01115                         vertextypes[i] = TPPL_VERTEXTYPE_REGULAR;
01116                 }
01117         }
01118 
01119         //helpers
01120         long *helpers = new long[maxnumvertices];
01121 
01122         //binary search tree that holds edges intersecting the scanline
01123         //note that while set doesn't actually have to be implemented as a tree
01124         //complexity requirements for operations are the same as for the balanced binary search tree
01125         set<ScanLineEdge> edgeTree;
01126         //store iterators to the edge tree elements
01127         //this makes deleting existing edges much faster
01128         set<ScanLineEdge>::iterator *edgeTreeIterators,edgeIter;
01129         edgeTreeIterators = new set<ScanLineEdge>::iterator[maxnumvertices];
01130         pair<set<ScanLineEdge>::iterator,bool> edgeTreeRet;
01131 
01132         //for each vertex
01133         for(i=0;i<numvertices;i++) {
01134                 vindex = priority[i];
01135                 v = &(vertices[vindex]);
01136                 vindex2 = vindex;
01137                 v2 = v;
01138 
01139                 //depending on the vertex type, do the appropriate action
01140                 //comments in the following sections are copied from "Computational Geometry: Algorithms and Applications"
01141                 switch(vertextypes[vindex]) {
01142                         case TPPL_VERTEXTYPE_START:
01143                                 //Insert ei in T and set helper(ei) to vi.
01144                                 newedge.p1 = v->p;
01145                                 newedge.p2 = vertices[v->next].p;
01146                                 newedge.index = vindex;
01147                                 edgeTreeRet = edgeTree.insert(newedge);
01148                                 edgeTreeIterators[vindex] = edgeTreeRet.first;
01149                                 helpers[vindex] = vindex;
01150                                 break;
01151 
01152                         case TPPL_VERTEXTYPE_END:
01153                                 //if helper(ei-1) is a merge vertex
01154                                 if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
01155                                         //Insert the diagonal connecting vi to helper(ei-1) in D.
01156                                         AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]);
01157                                         vertextypes[newnumvertices-2] = vertextypes[vindex];
01158                                         edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
01159                                         helpers[newnumvertices-2] = helpers[vindex];
01160                                         vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
01161                                         edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
01162                                         helpers[newnumvertices-1] = helpers[helpers[v->previous]];
01163                                 }
01164                                 //Delete ei-1 from T
01165                                 edgeTree.erase(edgeTreeIterators[v->previous]);
01166                                 break;
01167 
01168                         case TPPL_VERTEXTYPE_SPLIT:
01169                                 //Search in T to find the edge e j directly left of vi.
01170                                 newedge.p1 = v->p;
01171                                 newedge.p2 = v->p;
01172                                 edgeIter = edgeTree.lower_bound(newedge);
01173                                 if(edgeIter == edgeTree.begin()) {
01174                                         error = true;
01175                                         break;
01176                                 }
01177                                 edgeIter--;
01178                                 //Insert the diagonal connecting vi to helper(ej) in D.
01179                                 AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]);
01180                                 vertextypes[newnumvertices-2] = vertextypes[vindex];
01181                                 edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
01182                                 helpers[newnumvertices-2] = helpers[vindex];
01183                                 vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
01184                                 edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
01185                                 helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
01186                                 vindex2 = newnumvertices-2;
01187                                 v2 = &(vertices[vindex2]);
01188                                 //helper(e j)�vi
01189                                 helpers[edgeIter->index] = vindex;
01190                                 //Insert ei in T and set helper(ei) to vi.
01191                                 newedge.p1 = v2->p;
01192                                 newedge.p2 = vertices[v2->next].p;
01193                                 newedge.index = vindex2;
01194                                 edgeTreeRet = edgeTree.insert(newedge);
01195                                 edgeTreeIterators[vindex2] = edgeTreeRet.first;
01196                                 helpers[vindex2] = vindex2;
01197                                 break;
01198 
01199                         case TPPL_VERTEXTYPE_MERGE:
01200                                 //if helper(ei-1) is a merge vertex
01201                                 if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
01202                                         //Insert the diagonal connecting vi to helper(ei-1) in D.
01203                                         AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]);
01204                                         vertextypes[newnumvertices-2] = vertextypes[vindex];
01205                                         edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
01206                                         helpers[newnumvertices-2] = helpers[vindex];
01207                                         vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
01208                                         edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
01209                                         helpers[newnumvertices-1] = helpers[helpers[v->previous]];
01210                                         vindex2 = newnumvertices-2;
01211                                         v2 = &(vertices[vindex2]);
01212                                 }
01213                                 //Delete ei-1 from T.
01214                                 edgeTree.erase(edgeTreeIterators[v->previous]);
01215                                 //Search in T to find the edge e j directly left of vi.
01216                                 newedge.p1 = v->p;
01217                                 newedge.p2 = v->p;
01218                                 edgeIter = edgeTree.lower_bound(newedge);
01219                                 if(edgeIter == edgeTree.begin()) {
01220                                         error = true;
01221                                         break;
01222                                 }
01223                                 edgeIter--;
01224                                 //if helper(ej) is a merge vertex
01225                                 if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
01226                                         //Insert the diagonal connecting vi to helper(e j) in D.
01227                                         AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index]);
01228                                         vertextypes[newnumvertices-2] = vertextypes[vindex2];
01229                                         edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex2];
01230                                         helpers[newnumvertices-2] = helpers[vindex2];
01231                                         vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
01232                                         edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
01233                                         helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
01234                                 }
01235                                 //helper(e j)�vi
01236                                 helpers[edgeIter->index] = vindex2;
01237                                 break;
01238 
01239                         case TPPL_VERTEXTYPE_REGULAR:
01240                                 //if the interior of P lies to the right of vi
01241                                 if(Below(v->p,vertices[v->previous].p)) {
01242                                         //if helper(ei-1) is a merge vertex
01243                                         if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
01244                                                 //Insert the diagonal connecting vi to helper(ei-1) in D.
01245                                                 AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]);
01246                                                 vertextypes[newnumvertices-2] = vertextypes[vindex];
01247                                                 edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
01248                                                 helpers[newnumvertices-2] = helpers[vindex];
01249                                                 vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]];
01250                                                 edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]];
01251                                                 helpers[newnumvertices-1] = helpers[helpers[v->previous]];
01252                                                 vindex2 = newnumvertices-2;
01253                                                 v2 = &(vertices[vindex2]);
01254                                         }
01255                                         //Delete ei-1 from T.
01256                                         edgeTree.erase(edgeTreeIterators[v->previous]);
01257                                         //Insert ei in T and set helper(ei) to vi.
01258                                         newedge.p1 = v2->p;
01259                                         newedge.p2 = vertices[v2->next].p;
01260                                         newedge.index = vindex2;
01261                                         edgeTreeRet = edgeTree.insert(newedge);
01262                                         edgeTreeIterators[vindex2] = edgeTreeRet.first;
01263                                         helpers[vindex2] = vindex;
01264                                 } else {
01265                                         //Search in T to find the edge ej directly left of vi.
01266                                         newedge.p1 = v->p;
01267                                         newedge.p2 = v->p;
01268                                         edgeIter = edgeTree.lower_bound(newedge);
01269                                         if(edgeIter == edgeTree.begin()) {
01270                                                 error = true;
01271                                                 break;
01272                                         }
01273                                         edgeIter--;
01274                                         //if helper(ej) is a merge vertex
01275                                         if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
01276                                                 //Insert the diagonal connecting vi to helper(e j) in D.
01277                                                 AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]);
01278                                                 vertextypes[newnumvertices-2] = vertextypes[vindex];
01279                                                 edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex];
01280                                                 helpers[newnumvertices-2] = helpers[vindex];
01281                                                 vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]];
01282                                                 edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]];
01283                                                 helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]];
01284                                         }
01285                                         //helper(e j)�vi
01286                                         helpers[edgeIter->index] = vindex;
01287                                 }
01288                                 break;
01289                 }
01290 
01291                 if(error) break;
01292         }
01293 
01294         char *used = new char[newnumvertices];
01295         memset(used,0,newnumvertices*sizeof(char));
01296 
01297         if(!error) {
01298                 //return result
01299                 long size;
01300                 TPPLPoly mpoly;
01301                 for(i=0;i<newnumvertices;i++) {
01302                         if(used[i]) continue;
01303                         v = &(vertices[i]);
01304                         vnext = &(vertices[v->next]);
01305                         size = 1;
01306                         while(vnext!=v) {
01307                                 vnext = &(vertices[vnext->next]);
01308                                 size++;
01309                         }
01310 
01311                         v = &(vertices[i]);
01312                         mpoly[0] = v->p;
01313                         vnext = &(vertices[v->next]);
01314                         size = 1;
01315                         used[i] = 1;
01316                         used[v->next] = 1;
01317                         while(vnext!=v) {
01318                                 mpoly[size] = vnext->p;
01319                                 used[vnext->next] = 1;
01320                                 vnext = &(vertices[vnext->next]);
01321                                 size++;
01322                         }
01323                         monotonePolys->push_back(mpoly);
01324                 }
01325         }
01326 
01327         //cleanup
01328         delete [] vertices;
01329         delete [] priority;
01330         delete [] vertextypes;
01331         delete [] edgeTreeIterators;
01332         delete [] helpers;
01333         delete [] used;
01334 
01335         if(error) {
01336                 return 0;
01337         } else {
01338                 return 1;
01339         }
01340 }
01341 
01342 //adds a diagonal to the doubly-connected list of vertices
01343 void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2) {
01344         long newindex1,newindex2;
01345 
01346         newindex1 = *numvertices;
01347         (*numvertices)++;
01348         newindex2 = *numvertices;
01349         (*numvertices)++;
01350 
01351         vertices[newindex1].p = vertices[index1].p;
01352         vertices[newindex2].p = vertices[index2].p;
01353 
01354         vertices[newindex2].next = vertices[index2].next;
01355         vertices[newindex1].next = vertices[index1].next;
01356 
01357         vertices[vertices[index2].next].previous = newindex2;
01358         vertices[vertices[index1].next].previous = newindex1;
01359 
01360         vertices[index1].next = newindex2;
01361         vertices[newindex2].previous = index1;
01362 
01363         vertices[index2].next = newindex1;
01364         vertices[newindex1].previous = index2;
01365 }
01366 
01367 bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) {
01368         if(p1.y < p2.y) return true;
01369         else if(p1.y == p2.y) {
01370                 if(p1.x < p2.x) return true;
01371         }
01372         return false;
01373 }
01374 
01375 //sorts in the falling order of y values, if y is equal, x is used instead
01376 bool TPPLPartition::VertexSorter::operator() (long index1, long index2) {
01377         if(vertices[index1].p.y > vertices[index2].p.y) return true;
01378         else if(vertices[index1].p.y == vertices[index2].p.y) {
01379                 if(vertices[index1].p.x > vertices[index2].p.x) return true;
01380         }
01381         return false;
01382 }
01383 
01384 bool TPPLPartition::ScanLineEdge::IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const {
01385         tppl_float tmp;
01386         tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
01387         if(tmp>0) return 1;
01388         else return 0;
01389 }
01390 
01391 bool TPPLPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const {
01392         if(other.p1.y == other.p2.y) {
01393                 if(p1.y == p2.y) {
01394                         if(p1.y < other.p1.y) return true;
01395                         else return false;
01396                 }
01397                 if(IsConvex(p1,p2,other.p1)) return true;
01398                 else return false;
01399         } else if(p1.y == p2.y) {
01400                 if(IsConvex(other.p1,other.p2,p1)) return false;
01401                 else return true;
01402         } else if(p1.y < other.p1.y) {
01403                 if(IsConvex(other.p1,other.p2,p1)) return false;
01404                 else return true;
01405         } else {
01406                 if(IsConvex(p1,p2,other.p1)) return true;
01407                 else return false;
01408         }
01409 }
01410 
01411 //triangulates monotone polygon
01412 //O(n) time, O(n) space complexity
01413 int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles) {
01414         long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
01415         TPPLPoint *points;
01416         long numpoints;
01417         TPPLPoly triangle;
01418 
01419         numpoints = inPoly->GetNumPoints();
01420         points = inPoly->GetPoints();
01421 
01422         //trivial calses
01423         if(numpoints < 3) return 0;
01424         if(numpoints == 3) {
01425                 triangles->push_back(*inPoly);
01426         }
01427 
01428         topindex = 0; bottomindex=0;
01429         for(i=1;i<numpoints;i++) {
01430                 if(Below(points[i],points[bottomindex])) bottomindex = i;
01431                 if(Below(points[topindex],points[i])) topindex = i;
01432         }
01433 
01434         //check if the poly is really monotone
01435         i = topindex;
01436         while(i!=bottomindex) {
01437                 i2 = i+1; if(i2>=numpoints) i2 = 0;
01438                 if(!Below(points[i2],points[i])) return 0;
01439                 i = i2;
01440         }
01441         i = bottomindex;
01442         while(i!=topindex) {
01443                 i2 = i+1; if(i2>=numpoints) i2 = 0;
01444                 if(!Below(points[i],points[i2])) return 0;
01445                 i = i2;
01446         }
01447 
01448         char *vertextypes = new char[numpoints];
01449         long *priority = new long[numpoints];
01450 
01451         //merge left and right vertex chains
01452         priority[0] = topindex;
01453         vertextypes[topindex] = 0;
01454         leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0;
01455         rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1;
01456         for(i=1;i<(numpoints-1);i++) {
01457                 if(leftindex==bottomindex) {
01458                         priority[i] = rightindex;
01459                         rightindex--; if(rightindex<0) rightindex = numpoints-1;
01460                         vertextypes[priority[i]] = -1;
01461                 } else if(rightindex==bottomindex) {
01462                         priority[i] = leftindex;
01463                         leftindex++;  if(leftindex>=numpoints) leftindex = 0;
01464                         vertextypes[priority[i]] = 1;
01465                 } else {
01466                         if(Below(points[leftindex],points[rightindex])) {
01467                                 priority[i] = rightindex;
01468                                 rightindex--; if(rightindex<0) rightindex = numpoints-1;
01469                                 vertextypes[priority[i]] = -1;
01470                         } else {
01471                                 priority[i] = leftindex;
01472                                 leftindex++;  if(leftindex>=numpoints) leftindex = 0;
01473                                 vertextypes[priority[i]] = 1;
01474                         }
01475                 }
01476         }
01477         priority[i] = bottomindex;
01478         vertextypes[bottomindex] = 0;
01479 
01480         long *stack = new long[numpoints];
01481         long stackptr = 0;
01482 
01483         stack[0] = priority[0];
01484         stack[1] = priority[1];
01485         stackptr = 2;
01486 
01487         //for each vertex from top to bottom trim as many triangles as possible
01488         for(i=2;i<(numpoints-1);i++) {
01489                 vindex = priority[i];
01490                 if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) {
01491                         for(j=0;j<(stackptr-1);j++) {
01492                                 if(vertextypes[vindex]==1) {
01493                                         triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
01494                                 } else {
01495                                         triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
01496                                 }
01497                                 triangles->push_back(triangle);
01498                         }
01499                         stack[0] = priority[i-1];
01500                         stack[1] = priority[i];
01501                         stackptr = 2;
01502                 } else {
01503                         stackptr--;
01504                         while(stackptr>0) {
01505                                 if(vertextypes[vindex]==1) {
01506                                         if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) {
01507                                                 triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]);
01508                                                 triangles->push_back(triangle);
01509                                                 stackptr--;
01510                                         } else {
01511                                                 break;
01512                                         }
01513                                 } else {
01514                                         if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) {
01515                                                 triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]);
01516                                                 triangles->push_back(triangle);
01517                                                 stackptr--;
01518                                         } else {
01519                                                 break;
01520                                         }
01521                                 }
01522                         }
01523                         stackptr++;
01524                         stack[stackptr] = vindex;
01525                         stackptr++;
01526                 }
01527         }
01528         vindex = priority[i];
01529         for(j=0;j<(stackptr-1);j++) {
01530                 if(vertextypes[stack[j+1]]==1) {
01531                         triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
01532                 } else {
01533                         triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
01534                 }
01535                 triangles->push_back(triangle);
01536         }
01537 
01538         delete [] priority;
01539         delete [] vertextypes;
01540         delete [] stack;
01541 
01542         return 1;
01543 }
01544 
01545 int TPPLPartition::Triangulate_MONO(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles) {
01546         list<TPPLPoly> monotone;
01547         list<TPPLPoly>::iterator iter;
01548 
01549         if(!MonotonePartition(inpolys,&monotone)) return 0;
01550         for(iter = monotone.begin(); iter!=monotone.end();iter++) {
01551                 if(!TriangulateMonotone(&(*iter),triangles)) return 0;
01552         }
01553         return 1;
01554 }
01555 
01556 int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, list<TPPLPoly> *triangles) {
01557         list<TPPLPoly> polys;
01558         polys.push_back(*poly);
01559 
01560         return Triangulate_MONO(&polys, triangles);
01561 }


srs_env_model_percp
Author(s): Rostislav Hulik (ihulik@fit.vutbr.cz), Tomas Hodan, Michal Spanel (spanel@fit.vutbr.cz)
autogenerated on Sun Jan 5 2014 11:51:56