diff --git a/Mesh/meshGRegionDelaunayInsertion.cpp b/Mesh/meshGRegionDelaunayInsertion.cpp index 4fc91233b8811f7cb5b8088003230a5f44332fa4..9514185c997ff0f39830e59199e66ef1c7b43174 100644 --- a/Mesh/meshGRegionDelaunayInsertion.cpp +++ b/Mesh/meshGRegionDelaunayInsertion.cpp @@ -67,18 +67,27 @@ int MTet4::inCircumSphere(const double *p) const static int faces[4][3] = {{0,1,2}, {0,2,3}, {0,3,1}, {1,3,2}}; struct faceXtet{ - MVertex *v[3]; + MVertex *v[3],*unsorted[3]; MTet4 *t1; int i1; - faceXtet(MTet4 *_t, int iFac) : t1(_t), i1(iFac) + faceXtet(MTet4 *_t=0, int iFac=0) : t1(_t), i1(iFac) { - v[0] = t1->tet()->getVertex(faces[iFac][0]); - v[1] = t1->tet()->getVertex(faces[iFac][1]); - v[2] = t1->tet()->getVertex(faces[iFac][2]); - std::sort(v, v + 3); + MVertex *v0 = t1->tet()->getVertex(faces[iFac][0]); + MVertex *v1 = t1->tet()->getVertex(faces[iFac][1]); + MVertex *v2 = t1->tet()->getVertex(faces[iFac][2]); + + unsorted[0] = v0; + unsorted[1] = v1; + unsorted[2] = v2; + + v[0] = std::min(std::min(v0,v1),v2); + v[2] = std::max(std::max(v0,v1),v2); + v[1] = (v0 != v[0] && v0 != v[2]) ? v0 : (v1 != v[0] && v1 != v[2]) ? v1 : v2; + // + // std::sort(v, v + 3); } - inline MVertex * getVertex (int i) const { return t1->tet()->getVertex(faces[i1][i]);} + inline MVertex * getVertex (int i) const { return unsorted[i];} inline bool operator < (const faceXtet & other) const { @@ -108,6 +117,32 @@ struct faceXtet{ } }; +void connectTets_vector2(std::vector<MTet4*> &t, std::vector<faceXtet> &conn) +{ + conn.clear(); + unsigned int k = 0; + for (unsigned int i=0;i<t.size();i++){ + if (!t[i]->isDeleted()){ + for (int j = 0; j < 4; j++){ + conn.push_back(faceXtet(t[i], j)); + } + } + } + if (!conn.size())return; + std::sort(conn.begin(), conn.end()); + + for (unsigned int i=0;i<conn.size()-1;i++){ + faceXtet &f1 = conn[i]; + faceXtet &f2 = conn[i+1]; + if (f1 == f2 && f1.t1 != f2.t1){ + f1.t1->setNeigh(f1.i1, f2.t1); + f2.t1->setNeigh(f2.i1, f1.t1); + ++i; + } + } +} + + template <class ITER> void connectTets_vector(ITER beg, ITER end) { @@ -296,19 +331,31 @@ void recurFindCavity(std::list<faceXtet> & shell, MVertex *v , MTet4 *t) { - // Msg::Info("tet %d %d %d %d",t->tet()->getVertex(0)->getNum(), - // t->tet()->getVertex(1)->getNum(), - // t->tet()->getVertex(2)->getNum(), - // t->tet()->getVertex(3)->getNum()); - - // invariant : this one has to be inserted in the cavity - // consider this tet deleted - // remove its reference to its neighbors t->setDeleted(true); - // the cavity that has to be removed - // because it violates delaunay criterion cavity.push_back(t); + for (int i = 0; i < 4; i++){ + MTet4 *neigh = t->getNeigh(i) ; + faceXtet fxt (t, i); + if (!neigh) + shell.push_back(fxt); + else if (!neigh->isDeleted()){ + int circ = neigh->inCircumSphere(v); + if (circ && (neigh->onWhat() == t->onWhat())) + recurFindCavity(shell, cavity, v, neigh); + else{ + shell.push_back(fxt); + } + } + } +} +void recurFindCavity(std::vector<faceXtet> & shell, + std::vector<MTet4*> & cavity, + MVertex *v , + MTet4 *t) +{ + t->setDeleted(true); + cavity.push_back(t); for (int i = 0; i < 4; i++){ MTet4 *neigh = t->getNeigh(i) ; faceXtet fxt (t, i); @@ -323,9 +370,9 @@ void recurFindCavity(std::list<faceXtet> & shell, } } } - // printf("cavity size %d\n",cavity.size()); } + void nonrecurFindCavity(std::list<faceXtet> & shell, std::list<MTet4*> & cavity, MVertex *v , @@ -1659,7 +1706,7 @@ static MTet4* search4Tet (MTet4 *t, MVertex *v, int _size) { double Y[3] = {fxt.v[0]->y(),fxt.v[1]->y(),fxt.v[2]->y()}; double Z[3] = {fxt.v[0]->z(),fxt.v[1]->z(),fxt.v[2]->z()}; // printf("%d %d\n",i,intersect_line_triangle(X,Y,Z,p1,p2-p1)); - if (intersect_line_triangle(X,Y,Z,p1,p1-p2, 1.e-12) > 0) { + if (intersect_line_triangle(X,Y,Z,p1,p1-p2, -1.e-8) > 0) { found = i; break; } @@ -1682,9 +1729,14 @@ static MTet4* search4Tet (MTet4 *t, MVertex *v, int _size) { MTet4 * getTetToBreak (MVertex *v, std::vector<MTet4*> &t, int &NB_GLOBAL_SEARCH){ // last inserted is used as starting point // we know it is not deleted - MTet4 *start = t[t.size() - 1]; + unsigned int k = t.size() - 1; + while(t[k]->isDeleted()){ + k--; + } + MTet4 *start = t[k]; start = search4Tet (start,v,(int)t.size()); if (start)return start; + printf("Global Search has to be done\n"); NB_GLOBAL_SEARCH++; for (size_t i = 0;i<t.size();i++){ if (!t[i]->isDeleted() && t[i]->inCircumSphere(v))return t[i]; @@ -1702,55 +1754,90 @@ bool tetOnBox (MTetrahedron *t, MVertex *box[8]){ void delaunayMeshIn3D(std::vector<MVertex*> &v, std::vector<MTetrahedron*> &result) { std::vector<MTet4*> t; + t.reserve (v.size()*7); + std::vector<faceXtet> conn; + std::vector<faceXtet> shell; + std::vector<MTet4*> cavity; MVertex *box[8]; initialCube (v,box,t); int NB_GLOBAL_SEARCH = 0; SortHilbert(v); double t1 = Cpu(); - + for (size_t i=0;i<v.size();i++){ MVertex *pv = v[i]; + + // if (i%10000 == 0)printf("PT(%7d)\n",i); + MTet4 * found = getTetToBreak (pv,t,NB_GLOBAL_SEARCH); - if(!found) continue; - std::list<faceXtet> shell; - std::list<MTet4*> cavity; + if(!found) { + printf("argh\n"); + continue; + } + shell.clear(); + cavity.clear(); recurFindCavity(shell, cavity, pv, found); + std::vector<MTet4*> extended_cavity; - std::list<faceXtet>::iterator it = shell.begin(); - while (it != shell.end()){ - MTetrahedron *tr = new MTetrahedron(it->getVertex(0), - it->getVertex(1), - it->getVertex(2), pv); - MTet4 *t4 = new MTet4(tr, 0.0); - t.push_back(t4); + for (unsigned int count = 0; count < shell.size(); count++){ + const faceXtet &fxt = shell[count]; + MTetrahedron *tr; + MTet4 *t4; + MVertex *v0 = fxt.getVertex(0); + MVertex *v1 = fxt.getVertex(1); + MVertex *v2 = fxt.getVertex(2); + MTet4 *otherSide = fxt.t1->getNeigh(fxt.i1); + if (count < cavity.size()){ + t4 = cavity[count]; + tr = t4->tet() ; + tr->setVertex(0,v0); + tr->setVertex(1,v1); + tr->setVertex(2,v2); + tr->setVertex(3,pv); + } + else{ + tr = new MTetrahedron(v0,v1,v2,pv); + t4 = new MTet4(tr, 0.0); + t.push_back(t4); + } extended_cavity.push_back(t4); - MTet4 *otherSide = it->t1->getNeigh(it->i1); if (otherSide) extended_cavity.push_back(otherSide); - ++it; } + // reuse memory --> reinitialize MTet4s + for (unsigned int k=0;k<cavity.size();k++){ + cavity[k]->setDeleted(false); + for (unsigned int l=0;l<4;l++){ + cavity[k]->setNeigh(l,0); + } + } + // printf("connecting %i tets\n",extended_cavity.size()); - connectTets_vector(extended_cavity.begin(),extended_cavity.end()); + connectTets_vector2(extended_cavity,conn); + // printf("done\n"); + //connectTets_vector(extended_cavity.begin(),extended_cavity.end()); } double t2 = Cpu(); printf("%d global searches among %d CPU = %g\n",NB_GLOBAL_SEARCH,v.size(), t2-t1); + printf("%d tets allocated (to compare with 7 #V = %d)\n",t.size(),7*v.size()); - - // FILE *f = fopen ("tet.pos","w"); - // fprintf(f,"View \"\"{\n"); + + // FILE *f = fopen ("tet.pos","w"); + // fprintf(f,"View \"\"{\n"); for (size_t i = 0;i<t.size();i++){ - if (t[i]->isDeleted() || tetOnBox (t[i]->tet(),box)) delete t[i]->tet(); + if (t[i]->tet() && t[i]->isDeleted() || tetOnBox (t[i]->tet(),box)) delete t[i]->tet(); else { result.push_back(t[i]->tet()); - // t[i]->tet()->writePOS (f, false,false,true,false,false,false); + // t[i]->tet()->writePOS (f, false,false,true,false,false,false); } delete t[i]; } - // fprintf(f,"};\n"); - // fclose(f); + + for (int i=0;i<8;i++)delete box[i]; + + // fprintf(f,"};\n"); + // fclose(f); } - - diff --git a/Mesh/meshGRegionDelaunayInsertion.h b/Mesh/meshGRegionDelaunayInsertion.h index 9360b5143991faa182cb4d598792cdf6ef207b8e..df64be601adad2db8d4b629d1af01b403f7ee395 100644 --- a/Mesh/meshGRegionDelaunayInsertion.h +++ b/Mesh/meshGRegionDelaunayInsertion.h @@ -124,6 +124,7 @@ class MTet4 inline void setQuality(const double &q){ circum_radius = q; } inline MTetrahedron *tet() const { return base; } inline MTetrahedron *&tet() { return base; } + inline void setTet(MTetrahedron *t) { base=t; } inline void setNeigh(int iN, MTet4 *n) { neigh[iN] = n; } inline MTet4 *getNeigh(int iN) const { return neigh[iN]; } int inCircumSphere(const double *p) const;