advancing_front.h
Go to the documentation of this file.
00001 #ifndef MLS_ADVANCE_H
00002 #define MLS_ADVANCE_H
00003 
00004 #include <iostream>
00005 #include <list>
00006 #include <vcg/complex/algorithms/update/topology.h>
00007 #include <vcg/complex/algorithms/update/flag.h>
00008 
00009 namespace vcg {
00010   namespace tri {
00011 
00012 /* An active edge on the advancing front.
00013  * belong to a triangle (v0,v1,v2)
00014  * v0, v1 the active edge
00015  * v2     internal vertex
00016 */
00017 class FrontEdge {
00018  public:
00019   int v0, v1, v2;   //v0, v1 represent the FrontEdge, v2 the other vertex
00020                     //in the face this FrontEdge belongs to
00021   bool active; //keep tracks of wether it is in front or in deads
00022 
00023   //the loops in the front are mantained as a double linked list
00024   std::list<FrontEdge>::iterator next;
00025   std::list<FrontEdge>::iterator previous;
00026 
00027   FrontEdge() {}
00028   FrontEdge(int _v0, int _v1, int _v2):
00029              v0(_v0), v1(_v1), v2(_v2), active(true) {
00030                assert(v0 != v1 && v1 != v2 && v0 != v2);
00031   }
00032 
00033     bool operator==(const FrontEdge& f) const
00034     {
00035         return ((v0 == f.v0) && (v1 == f.v1) && (v2 == f.v2) );
00036     }
00037 };
00038 
00039 template <class MESH> class AdvancingFront {
00040  public:
00041 
00042   typedef typename MESH::VertexType     VertexType;
00043   typedef typename MESH::FaceType       FaceType;
00044   typedef typename MESH::FaceIterator       FaceIterator;
00045   typedef typename MESH::ScalarType     ScalarType;
00046   typedef typename MESH::VertexType::CoordType   Point3x;
00047 
00048   //class FrontEdgeLists
00049   //{
00050 
00051   //};
00052 
00053 
00054 // protected:
00055   std::list<FrontEdge> front;
00056   std::list<FrontEdge> deads;
00057   std::vector<int> nb; //number of fronts a vertex is into,
00058                        //this is used for the Visited and Border flags
00059                        //but adding topology may not be needed anymore
00060 
00061  public:
00062 
00063   MESH &mesh;           //this structure will be filled by the algorithm
00064 
00065   AdvancingFront(MESH &_mesh): mesh(_mesh) {
00066 
00067 
00068     UpdateFlags<MESH>::FaceBorderFromNone(mesh);
00069     UpdateFlags<MESH>::VertexBorderFromFaceBorder(mesh);
00070 
00071     nb.clear();
00072     nb.resize(mesh.vert.size(), 0);
00073 
00074     CreateLoops();
00075   }
00076   virtual ~AdvancingFront() {}
00077 
00078   void BuildMesh(CallBackPos call = NULL, int interval = 512)
00079   {
00080     float finalfacesext = mesh.vert.size() * 2.0f;
00081     if(call) call(0, "Advancing front");
00082     while(1) {
00083 
00084       for(int i = 0; i < interval; i++) {
00085         if(!front.size() && !SeedFace()) return;
00086         AddFace();
00087         if(call)
00088         {
00089             float rap = float(mesh.face.size()) / finalfacesext;
00090             int perc = (int) (100.0f * rap);
00091             (*call)(perc,"Adding Faces");
00092         }
00093       }
00094     }
00095   }
00096 
00097 protected:
00098   //Implement these functions in your subclass
00099   enum ListID {FRONT,DEADS};
00100   typedef std::pair< ListID,std::list<FrontEdge>::iterator > ResultIterator;
00101   virtual bool Seed(int &v0, int &v1, int &v2) = 0;
00102   // This function must find a vertex to be added to edge 'e'.
00103   // return -1 in case of failure
00104   virtual int Place(FrontEdge &e, ResultIterator &touch) = 0;
00105 
00106   //create the FrontEdge loops from seed faces
00107   void CreateLoops()
00108   {
00109     for(size_t i = 0; i < mesh.face.size(); i++)
00110     {
00111       FaceType &f = mesh.face[i];
00112       if(f.IsD()) continue;
00113 
00114       for(int k = 0; k < 3; k++) {
00115         if(f.IsB(k)) {
00116           addNewEdge(FrontEdge(tri::Index(mesh,f.V0(k)),tri::Index(mesh,f.V1(k)),tri::Index(mesh,f.V2(k))) );
00117           nb[tri::Index(mesh,f.V0(k))]++;
00118         }
00119       }
00120     }
00121 
00122     for(std::list<FrontEdge>::iterator s = front.begin(); s != front.end(); s++) {
00123       (*s).previous = front.end();
00124       (*s).next = front.end();
00125     }
00126     //now create loops:
00127     for(std::list<FrontEdge>::iterator s = front.begin(); s != front.end(); s++) {
00128       for(std::list<FrontEdge>::iterator j = front.begin(); j != front.end(); j++) {
00129         if(s == j) continue;
00130         if((*s).v1 != (*j).v0) continue;
00131         if((*j).previous != front.end()) continue;
00132         (*s).next = j;
00133         (*j).previous = s;
00134         break;
00135       }
00136     }
00137     for(std::list<FrontEdge>::iterator s = front.begin(); s != front.end(); s++) {
00138       assert((*s).next != front.end());
00139       assert((*s).previous != front.end());
00140     }
00141   }
00142 
00143   bool SeedFace() {
00144     int v[3];
00145     bool success = Seed(v[0], v[1], v[2]);
00146     if(!success) return false;
00147 
00148     nb.resize(mesh.vert.size(), 0);
00149 
00150      //create the border of the first face
00151     std::list<FrontEdge>::iterator e = front.end();
00152     std::list<FrontEdge>::iterator last = e;
00153     std::list<FrontEdge>::iterator first;
00154 
00155     for(int i = 0; i < 3; i++) {
00156       int v0 = v[i];
00157       int v1 = v[((i+1)%3)];
00158       int v2 = v[((i+2)%3)];
00159 
00160       mesh.vert[v0].SetB();
00161       nb[v[i]]++;
00162 
00163       e = front.insert(front.begin(), FrontEdge(v0, v1, v2));
00164       if(i != 0) {
00165         (*last).next = e;
00166         (*e).previous = last;
00167       } else
00168         first = e;
00169 
00170       last = e;
00171     }
00172     //connect last and first
00173     (*last).next = first;
00174     (*first).previous = last;
00175 
00176     AddFace(v[0], v[1], v[2]);
00177     return true;
00178   }
00179 
00180 public:
00181   bool AddFace() {
00182     if(!front.size()) return false;
00183 
00184     std::list<FrontEdge>::iterator ei = front.begin();
00185     FrontEdge &current = *ei;
00186     FrontEdge &previous = *current.previous;
00187     FrontEdge &next = *current.next;
00188 
00189     int v0 = current.v0, v1 = current.v1;
00190     assert(nb[v0] < 10 && nb[v1] < 10);
00191 
00192     ResultIterator touch;
00193     touch.first = FRONT;
00194     touch.second = front.end();
00195     int v2 = Place(current, touch);
00196 
00197     if(v2 == -1) {
00198       KillEdge(ei);
00199       return false;
00200     }
00201 
00202     assert(v2 != v0 && v2 != v1);
00203 
00204     if ( ( (touch.first == FRONT) && (touch.second != front.end()) ) ||
00205          ( (touch.first == DEADS) && (touch.second != deads.end()) )    )
00206 
00207     {
00208       //check for orientation and manifoldness
00209 
00210       //touch == current.previous?
00211       if(v2 == previous.v0) {
00212         if(!CheckEdge(v2, v1)) {
00213           KillEdge(ei);
00214           return false;
00215         }
00216           /*touching previous FrontEdge  (we reuse previous)
00217                                     next
00218              ------->v2 -----> v1------>
00219                       \       /
00220                        \     /
00221                previous \   / current
00222                          \ /
00223                           v0           */
00224 
00225         Detach(v0);
00226 
00227         std::list<FrontEdge>::iterator up = addNewEdge(FrontEdge(v2, v1, v0));
00228         MoveFront(up);
00229         (*up).previous = previous.previous;
00230         (*up).next = current.next;
00231         (*previous.previous).next = up;
00232         next.previous = up;
00233         Erase(current.previous);
00234         Erase(ei);
00235         Glue(up);
00236 
00237       //touch == (*current.next).next
00238       } else if(v2 == next.v1) {
00239         if(!CheckEdge(v0, v2)) {
00240           KillEdge(ei);
00241           return false;
00242         }
00243         /*touching next FrontEdge  (we reuse next)
00244           previous
00245              ------->v0 -----> v2------>
00246                       \       /
00247                        \     /
00248                         \   / next
00249                          \ /
00250                           v1           */
00251 
00252         Detach(v1);
00253         std::list<FrontEdge>::iterator up = addNewEdge(FrontEdge(v0, v2, v1));
00254         MoveFront(up);
00255         (*up).previous = current.previous;
00256         (*up).next = (*current.next).next;
00257         previous.next = up;
00258         (*next.next).previous = up;
00259         Erase(current.next);
00260         Erase(ei);
00261         Glue(up);
00262       } else {
00263         if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) {
00264           KillEdge(ei);
00265           return false;
00266         }
00267       //touching some loop: split (or merge it is local does not matter.
00268       //like this
00269       /*
00270                   left        right
00271                 <--------v2-<------
00272                           /|\
00273                          /   \
00274                      up /     \ down
00275                        /       \
00276                       /         V
00277                  ----v0 - - - > v1---------
00278                         current                         */
00279         std::list<FrontEdge>::iterator left = touch.second;
00280         std::list<FrontEdge>::iterator right = (*touch.second).previous;
00281 
00282         //this would be a really bad join
00283         if(v1 == (*right).v0 || v0 == (*left).v1) {
00284           KillEdge(ei);
00285           return false;
00286         }
00287 
00288         nb[v2]++;
00289 
00290         std::list<FrontEdge>::iterator down = addNewEdge(FrontEdge(v2, v1, v0));
00291         std::list<FrontEdge>::iterator up = addNewEdge(FrontEdge(v0, v2, v1));
00292 
00293         (*right).next = down;
00294         (*down).previous = right;
00295 
00296         (*down).next = current.next;
00297         next.previous = down;
00298 
00299         (*left).previous = up;
00300         (*up).next = left;
00301 
00302         (*up).previous = current.previous;
00303         previous.next = up;
00304         Erase(ei);
00305       }
00306 
00307 
00308     }
00309     else if (((touch.first == FRONT) && (touch.second == front.end())) ||
00310              ((touch.first == DEADS) && (touch.second == deads.end()))    )
00311     {
00312 //        assert(CheckEdge(v0, v2));
00313 //        assert(CheckEdge(v2, v1));
00314         /*  adding a new vertex
00315 
00316                            v2
00317                           /|\
00318                          /   \
00319                      up /     \ down
00320                        /       \
00321                       /         V
00322                  ----v0 - - - > v1--------- */
00323         assert(!mesh.vert[v2].IsB()); //fatal error! a new point is already a border?
00324         nb[v2]++;
00325         mesh.vert[v2].SetB();
00326 
00327         std::list<FrontEdge>::iterator down = addNewEdge(FrontEdge(v2, v1, v0));
00328         std::list<FrontEdge>::iterator up = addNewEdge(FrontEdge(v0, v2, v1));
00329 
00330         (*down).previous = up;
00331         (*up).next = down;
00332         (*down).next = current.next;
00333         next.previous = down;
00334         (*up).previous = current.previous;
00335         previous.next = up;
00336         Erase(ei);
00337       }
00338 
00339       AddFace(v0, v2, v1);
00340       return false;
00341   }
00342 
00343 protected:
00344   void AddFace(int v0, int v1, int v2) {
00345     FaceIterator fi = vcg::tri::Allocator<MESH>::AddFace(mesh,v0,v1,v2);
00346     fi->N() = TriangleNormal(*fi).Normalize();
00347     if(tri::HasVFAdjacency(mesh))
00348     {
00349       for(int j=0;j<3;++j)
00350       {
00351         (*fi).VFp(j) = (*fi).V(j)->VFp();
00352         (*fi).VFi(j) = (*fi).V(j)->VFi();
00353         (*fi).V(j)->VFp() = &(*fi);
00354         (*fi).V(j)->VFi() = j;
00355       }
00356     }
00357   }
00358 
00359   void AddVertex(VertexType &vertex) {
00360     VertexType *oldstart = NULL;
00361     if(mesh.vert.size()) oldstart = &*mesh.vert.begin();
00362     mesh.vert.push_back(vertex);
00363     mesh.vn++;
00364     VertexType *newstart = &*mesh.vert.begin();
00365     if(oldstart && oldstart != newstart) {
00366       for(int i = 0; i < mesh.face.size(); i++) {
00367         FaceType &face = mesh.face[i];
00368         for(int k = 0; k < 3; k++)
00369           face.V(k) = newstart + (face.V(k) - oldstart);
00370       }
00371     }
00372     nb.push_back(0);
00373   }
00374 
00375   // Given a possible new edge v0-v1
00376   // it checks that:
00377   // 1) the orientation is consistent (all the faces with vertex v0 and v1 have the edge in the opposite way)
00378   // 2) the edge appears at least once
00379 
00380   bool CheckEdge(int v0, int v1) {
00381     int tot = 0;
00382     VertexType *vv0 = &(mesh.vert[v0]);
00383     VertexType *vv1 = &(mesh.vert[v1]);
00384     if(tri::HasVFAdjacency(mesh))
00385     {
00386       face::VFIterator<FaceType> vfi(vv0);
00387       for (;!vfi.End();++vfi)
00388       {
00389         FaceType *f = vfi.F();
00390         for(int k = 0; k < 3; k++) {
00391           if(vv0 == f->V0(k) && vv1 == f->V1(k))  //orientation non constistent
00392              return false;
00393           else if(vv1 == f->V0(k) && vv0 == f->V1(k)) ++tot;
00394         }
00395       }
00396       return true;
00397     }
00398     for(int i = 0; i < (int)mesh.face.size(); i++) {
00399       FaceType &f = mesh.face[i];
00400       for(int k = 0; k < 3; k++) {
00401         if(vv0 == f.V0(k) && vv1 == f.V1(k))  //orientation non constistent
00402            return false;
00403         else if(vv1 == f.V0(k) && vv0 == f.V1(k)) ++tot;
00404       }
00405       if(tot >= 2) { //non manifold
00406         return false;
00407       }
00408     }
00409     return true;
00410   }
00411   //front management:
00412 
00413   //Add a new FrontEdge to the back of the queue
00414   std::list<FrontEdge>::iterator addNewEdge(FrontEdge e) {
00415     return front.insert(front.end(), e);
00416   }
00417 
00418   //move an Edge among the dead ones
00419   void KillEdge(std::list<FrontEdge>::iterator e)
00420   {
00421     if (e->active)
00422     {
00423         (*e).active = false;
00424         //std::list<FrontEdge>::iterator res = std::find(front.begin(),front.end(),e);
00425         FrontEdge tmp = *e;
00426         deads.splice(deads.end(), front, e);
00427         std::list<FrontEdge>::iterator newe = std::find(deads.begin(),deads.end(),tmp);
00428         tmp.previous->next = newe;
00429         tmp.next->previous = newe;
00430     }
00431   }
00432 
00433   void Erase(std::list<FrontEdge>::iterator e) {
00434     if((*e).active) front.erase(e);
00435     else deads.erase(e);
00436   }
00437 
00438   //move an FrontEdge to the back of the queue
00439   void MoveBack(std::list<FrontEdge>::iterator e) {
00440     front.splice(front.end(), front, e);
00441   }
00442 
00443   void MoveFront(std::list<FrontEdge>::iterator e) {
00444     front.splice(front.begin(), front, e);
00445   }
00446 
00447   //check if e can be sewed with one of oits neighbours
00448   bool Glue(std::list<FrontEdge>::iterator e) {
00449     return Glue((*e).previous, e) || Glue(e, (*e).next);
00450   }
00451 
00452   //Glue toghether a and b (where a.next = b
00453   bool Glue(std::list<FrontEdge>::iterator a, std::list<FrontEdge>::iterator b) {
00454     if((*a).v0 != (*b).v1) return false;
00455 
00456     std::list<FrontEdge>::iterator previous = (*a).previous;
00457     std::list<FrontEdge>::iterator next = (*b).next;
00458     (*previous).next = next;
00459     (*next).previous = previous;
00460     Detach((*a).v1);
00461     Detach((*a).v0);
00462     Erase(a);
00463     Erase(b);
00464     return true;
00465   }
00466 
00467   void Detach(int v) {
00468     assert(nb[v] > 0);
00469     if(--nb[v] == 0) {
00470       mesh.vert[v].ClearB();
00471     }
00472   }
00473 };
00474 
00475 template <class MESH> class AdvancingTest: public AdvancingFront<MESH> {
00476  public:
00477   typedef typename MESH::VertexType     VertexType;
00478   typedef typename MESH::VertexIterator VertexIterator;
00479   typedef typename MESH::FaceType       FaceType;
00480   typedef typename MESH::FaceIterator   FaceIterator;
00481 
00482   typedef typename MESH::ScalarType     ScalarType;
00483   typedef typename MESH::VertexType::CoordType   Point3x;
00484 
00485   AdvancingTest(MESH &_mesh): AdvancingFront<MESH>(_mesh) {}
00486 
00487   bool Seed(int &v0, int &v1, int &v2) {
00488     VertexType v[3];
00489     v[0].P() = Point3x(0, 0, 0);
00490     v[1].P() = Point3x(1, 0, 0);
00491     v[2].P() = Point3x(0, 1, 0);
00492     v[0].ClearFlags();
00493     v[1].ClearFlags();
00494     v[2].ClearFlags();
00495 
00496     v0 = this->mesh.vert.size();
00497     AddVertex(v[0]);
00498     v1 = this->mesh.vert.size();
00499     AddVertex(v[1]);
00500     v2 = this->mesh.vert.size();
00501     AddVertex(v[2]);
00502     return true;
00503   }
00504 
00505   int Place(FrontEdge &e, typename AdvancingFront<MESH>::ResultIterator &touch)
00506   {
00507      Point3f p[3];
00508      p[0] = this->mesh.vert[e.v0].P();
00509      p[1] = this->mesh.vert[e.v1].P();
00510      p[2] = this->mesh.vert[e.v2].P();
00511      Point3f point = p[0] + p[1] - p[2];
00512 
00513      int vn = this->mesh.vert.size();
00514      for(int i = 0; i < this->mesh.vert.size(); i++)
00515      {
00516        if((this->mesh.vert[i].P() - point).Norm() < 0.1)
00517        {
00518          vn = i;
00519          //find the border
00520          assert(this->mesh.vert[i].IsB());
00521          for(std::list<FrontEdge>::iterator k = this->front.begin(); k != this->front.end(); k++)
00522            if((*k).v0 == i)
00523            {
00524              touch.first = AdvancingFront<MESH>::FRONT;
00525              touch.second = k;
00526            }
00527 
00528          for(std::list<FrontEdge>::iterator k = this->deads.begin(); k != this->deads.end(); k++)
00529            if((*k).v0 == i)
00530              if((*k).v0 == i)
00531              {
00532                touch.first = AdvancingFront<MESH>::FRONT;
00533                touch.second = k;
00534              }
00535          break;
00536        }
00537      }
00538      if(vn == this->mesh.vert.size()) {
00539        VertexType v;
00540        v.P() = point;
00541        v.ClearFlags();
00542        AddVertex(v);
00543      }
00544      return vn;
00545   }
00546 };
00547 
00548 }//namespace tri
00549 }//namespace vcg
00550 
00551 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:28:51