$darkmode
VCG Library
topology.h
1 /****************************************************************************
2 * VCGLib o o *
3 * Visual and Computer Graphics Library o o *
4 * _ O _ *
5 * Copyright(C) 2004-2016 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23 
24 #ifndef __VCG_TRI_UPDATE_TOPOLOGY
25 #define __VCG_TRI_UPDATE_TOPOLOGY
26 
27 #include <cassert>
28 
29 #include <vcg/complex/base.h>
30 #include <vcg/simplex/face/topology.h>
31 #include <vcg/simplex/edge/pos.h>
32 
33 namespace vcg {
34 namespace tri {
36 
38 
40 
41 template <class UpdateMeshType>
43 {
44 
45 public:
46 typedef UpdateMeshType MeshType;
47 typedef typename MeshType::ScalarType ScalarType;
48 typedef typename MeshType::VertexType VertexType;
49 typedef typename MeshType::VertexPointer VertexPointer;
50 typedef typename MeshType::VertexIterator VertexIterator;
51 typedef typename MeshType::EdgeType EdgeType;
52 typedef typename MeshType::EdgePointer EdgePointer;
53 typedef typename MeshType::EdgeIterator EdgeIterator;
54 typedef typename MeshType::FaceType FaceType;
55 typedef typename MeshType::FacePointer FacePointer;
56 typedef typename MeshType::FaceIterator FaceIterator;
57 typedef typename MeshType::TetraType TetraType;
58 typedef typename MeshType::TetraPointer TetraPointer;
59 typedef typename MeshType::TetraIterator TetraIterator;
60 
61 
63 
65 
69 class PFace
70 {
71 public:
72  VertexPointer v[3]; //three ordered vertex pointers, identify a face
73  TetraPointer t; //the pointer to the tetra where this face belongs
74  int z; //index in [0..3] of the face in the tetra
75  bool isBorder;
76 
77  PFace () {}
78  PFace (TetraPointer tp, const int nz) { this->Set(tp, nz); }
79 
80  void Set (TetraPointer tp /*the tetra pointer*/, const int nz /*the face index*/)
81  {
82  assert (tp != 0);
83  assert (nz >= 0 && nz < 4);
84 
85  v[0] = tp->V(Tetra::VofF(nz, 0));
86  v[1] = tp->V(Tetra::VofF(nz, 1));
87  v[2] = tp->V(Tetra::VofF(nz, 2));
88 
89  assert(v[0] != v[1] && v[1] != v[2]); //no degenerate faces
90 
91  if (v[0] > v[1])
92  std::swap(v[0], v[1]);
93  if (v[1] > v[2])
94  std::swap(v[1], v[2]);
95  if (v[0] > v[1])
96  std::swap(v[0], v[1]);
97 
98  t = tp;
99  z = nz;
100 
101 
102  }
103 
104  inline bool operator < (const PFace & pf) const
105  {
106  if (v[0] < pf.v[0])
107  return true;
108  else
109  {
110  if (v[0] > pf.v[0]) return false;
111 
112  if (v[1] < pf.v[1])
113  return true;
114  else
115  {
116  if (v[1] > pf.v[1]) return false;
117 
118  return (v[2] < pf.v[2]);
119  }
120  }
121  }
122 
123  inline bool operator == (const PFace & pf) const
124  {
125  return v[0] == pf.v[0] && v[1] == pf.v[1] && v[2] == pf.v[2];
126  }
127 };
128 
129 static void FillFaceVector (MeshType & m, std::vector<PFace> & fvec)
130 {
131  ForEachTetra(m, [&fvec] (TetraType & t) {
132  for (int i = 0; i < 4; ++i)
133  fvec.push_back(PFace(&t, i));
134  });
135 }
136 
137 static void FillUniqueFaceVector (MeshType & m, std::vector<PFace> & fvec)
138 {
139  FillFaceVector(m, fvec);
140  std::sort(fvec.begin(), fvec.end());
141  typename std::vector<PFace>::iterator newEnd = std::unique(fvec.begin(), fvec.end());
142 }
143 
145 
148 class PEdge
149 {
150 public:
151 
152  VertexPointer v[2]; // the two Vertex pointer are ordered!
153  FacePointer f; // the face where this edge belong
154  int z; // index in [0..2] of the edge of the face
155  bool isBorder;
156 
157  PEdge() {}
158  PEdge(FacePointer pf, const int nz) { this->Set(pf,nz); }
159  void Set( FacePointer pf, const int nz )
160  {
161  assert(pf!=0);
162  assert(nz>=0);
163  assert(nz<pf->VN());
164 
165  v[0] = pf->V(nz);
166  v[1] = pf->V(pf->Next(nz));
167  assert(v[0] != v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes)
168 
169  if( v[0] > v[1] ) std::swap(v[0],v[1]);
170  f = pf;
171  z = nz;
172  }
173 
174  inline bool operator < ( const PEdge & pe ) const
175  {
176  if( v[0]<pe.v[0] ) return true;
177  else if( v[0]>pe.v[0] ) return false;
178  else return v[1] < pe.v[1];
179  }
180 
181  inline bool operator == ( const PEdge & pe ) const
182  {
183  return v[0]==pe.v[0] && v[1]==pe.v[1];
184  }
188  {
189  Point3<ScalarType> interp(0,0,0);
190  interp[ this->z ] = u;
191  interp[(this->z+1)%3] = 1.0f-u;
192  return interp;
193  }
194 };
195 
199 
200 static void FillEdgeVector(MeshType &m, std::vector<PEdge> &edgeVec, bool includeFauxEdge=true)
201 {
202  edgeVec.reserve(m.fn*3);
203  for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
204  if( ! (*fi).IsD() )
205  for(int j=0;j<(*fi).VN();++j)
206  if(includeFauxEdge || !(*fi).IsF(j))
207  edgeVec.push_back(PEdge(&*fi,j));
208 }
209 
210 static void FillUniqueEdgeVector(MeshType &m, std::vector<PEdge> &edgeVec, bool includeFauxEdge=true, bool computeBorderFlag=false)
211 {
212  FillEdgeVector(m,edgeVec,includeFauxEdge);
213  sort(edgeVec.begin(), edgeVec.end()); // oredering by vertex
214 
215  if (computeBorderFlag) {
216  for (size_t i=0; i<edgeVec.size(); i++)
217  edgeVec[ i ].isBorder = true;
218  for (size_t i=1; i<edgeVec.size(); i++) {
219  if (edgeVec[i]==edgeVec[i-1])
220  edgeVec[i].isBorder = edgeVec[i-1].isBorder = false;
221  }
222  }
223 
224  typename std::vector< PEdge>::iterator newEnd = std::unique(edgeVec.begin(), edgeVec.end());
225 
226  edgeVec.resize(newEnd-edgeVec.begin()); // redundant! remove?
227 }
228 
229 static void FillSelectedFaceEdgeVector(MeshType &m, std::vector<PEdge> &edgeVec)
230 {
231  edgeVec.reserve(m.fn*3);
232  ForEachFace(m, [&](FaceType &f){
233  for(int j=0;j<f.VN();++j)
234  if(f.IsFaceEdgeS(j))
235  edgeVec.push_back(PEdge(&f,j));
236  });
237 
238  sort(edgeVec.begin(), edgeVec.end()); // oredering by vertex
239  edgeVec.erase(std::unique(edgeVec.begin(), edgeVec.end()),edgeVec.end());
240 }
241 
242 
243 
249 static void AllocateEdge(MeshType &m)
250 {
251  // Delete all the edges (if any)
252  for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
255 
256  // Compute and add edges
257  std::vector<PEdge> Edges;
258  FillUniqueEdgeVector(m,Edges,true,tri::HasPerEdgeFlags(m) );
259  assert(m.edge.empty());
260  tri::Allocator<MeshType>::AddEdges(m,Edges.size());
261  assert(m.edge.size()==Edges.size());
262 
263  // Setup adjacency relations
264  if(tri::HasEVAdjacency(m))
265  {
266  for(size_t i=0; i< Edges.size(); ++i)
267  {
268  m.edge[i].V(0) = Edges[i].v[0];
269  m.edge[i].V(1) = Edges[i].v[1];
270  }
271  }
272 
273  if (tri::HasPerEdgeFlags(m)){
274  for(size_t i=0; i< Edges.size(); ++i) {
275  if (Edges[i].isBorder) m.edge[i].SetB(); else m.edge[i].ClearB();
276  }
277  }
278 
279  if(tri::HasEFAdjacency(m)) // Note it is an unordered relation.
280  {
281  for(size_t i=0; i< Edges.size(); ++i)
282  {
283  std::vector<FacePointer> fpVec;
284  std::vector<int> eiVec;
285  face::EFStarFF(Edges[i].f,Edges[i].z,fpVec,eiVec);
286  m.edge[i].EFp() = Edges[i].f;
287  m.edge[i].EFi() = Edges[i].z;
288  }
289  }
290 
291  if(tri::HasFEAdjacency(m))
292  {
293  for(size_t i=0; i< Edges.size(); ++i)
294  {
295  std::vector<FacePointer> fpVec;
296  std::vector<int> eiVec;
297  face::EFStarFF(Edges[i].f,Edges[i].z,fpVec,eiVec);
298  for(size_t j=0;j<fpVec.size();++j)
299  fpVec[j]->FEp(eiVec[j])=&(m.edge[i]);
300 
301 // Edges[i].f->FE(Edges[i].z) = &(m.edge[i]);
302 // Connect in loop the non manifold
303 // FaceType* fpit=fp;
304 // int eit=ei;
305 
306 // do
307 // {
308 // faceVec.push_back(fpit);
309 // indVed.push_back(eit);
310 // FaceType *new_fpit = fpit->FFp(eit);
311 // int new_eit = fpit->FFi(eit);
312 // fpit=new_fpit;
313 // eit=new_eit;
314 // } while(fpit != fp);
315 
316 
317 // m.edge[i].EFp() = Edges[i].f;
318 // m.edge[i].EFi() = ;
319  }
320  }
321 
322 }
323 
326 static void ClearTetraTetra (MeshType & m)
327 {
328  RequireTTAdjacency(m);
329  ForEachTetra(m, [] (TetraType & t) {
330  for (int i = 0; i < 4; ++i)
331  {
332  t.TTp(i) = NULL;
333  t.TTi(i) = -1;
334  }
335  });
336 }
337 
339 static void TetraTetra (MeshType & m)
340 {
341  RequireTTAdjacency(m);
342  if (m.tn == 0) return;
343 
344  std::vector<PFace> fvec;
345  FillFaceVector(m, fvec);
346  std::sort(fvec.begin(), fvec.end());
347 
348  typename std::vector<PFace>::iterator pback, pfront;
349  pback = fvec.begin();
350  pfront = fvec.begin();
351 
352  do
353  {
354  if (pfront == fvec.end() || !(*pfront == *pback))
355  {
356  typename std::vector<PFace>::iterator q, q_next;
357  for (q = pback; q < pfront - 1; ++q)
358  {
359  assert((*q).z >= 0);
360  q_next = q;
361  ++q_next;
362  assert((*q_next).z >= 0 && (*q_next).z < 4);
363 
364  (*q).t->TTp(q->z) = (*q_next).t;
365  (*q).t->TTi(q->z) = (*q_next).z;
366  }
367 
368  (*q).t->TTp(q->z) = pback->t;
369  (*q).t->TTi(q->z) = pback->z;
370  pback = pfront;
371  }
372  if (pfront == fvec.end()) break;
373  ++pfront;
374  } while (true);
375 }
378 static void ClearFaceFace(MeshType &m)
379 {
380  RequireFFAdjacency(m);
381  for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
382  {
383  if( ! (*fi).IsD() )
384  {
385  for(int j=0;j<fi->VN();++j)
386  {
387  fi->FFp(j)=0;
388  fi->FFi(j)=-1;
389  }
390  }
391  }
392 }
393 
395 static void FaceFace(MeshType &m)
396 {
397  RequireFFAdjacency(m);
398  if( m.fn == 0 ) return;
399  // we use an auxiliary vector of pairs (face,edge index) to sort the edges
400  std::vector<PEdge> e;
401  FillEdgeVector(m,e);
402  sort(e.begin(), e.end());
403 
404  auto ps = e.begin();
405  auto pe = e.begin();
406  // scans the sorted vector of edges searching for edges with the same pair of vertices
407  // and connect the corresponding faces
408  do
409  {
410  if( pe==e.end() || !(*pe == *ps) )
411  {
412  typename std::vector<PEdge>::iterator q,q_next;
413  for (q=ps;q<pe-1;++q)
414  {
415  assert((*q).z>=0);
416  //assert((*q).z< 3);
417  q_next = q;
418  ++q_next;
419  assert((*q_next).z>=0);
420  assert((*q_next).z< (*q_next).f->VN());
421  (*q).f->FFp(q->z) = (*q_next).f;
422  (*q).f->FFi(q->z) = (*q_next).z;
423  }
424  assert((*q).z>=0);
425  assert((*q).z< (*q).f->VN());
426  (*q).f->FFp((*q).z) = ps->f;
427  (*q).f->FFi((*q).z) = ps->z;
428  ps = pe;
429  }
430  if(pe==e.end()) break;
431  ++pe;
432  } while(true);
433 }
434 
435 
437 static void VertexTetra(MeshType & m)
438 {
439  RequireVTAdjacency(m);
440 
441 
442  ForEachVertex(m, [] (VertexType & v) {
443  v.VTp() = NULL;
444  v.VTi() = 0;
445  });
446 
447  ForEachTetra(m, [] (TetraType & t) {
448  //this works like this: the first iteration defines the end of the chain
449  //then it backwards chains everything
450  for (int i = 0; i < 4; ++i)
451  {
452  t.VTp(i) = t.V(i)->VTp();
453  t.VTi(i) = t.V(i)->VTi();
454  t.V(i)->VTp() = &t;
455  t.V(i)->VTi() = i;
456  }
457  });
458 }
460 
467 static void VertexFace(MeshType &m)
468 {
469  RequireVFAdjacency(m);
470 
471  for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
472  {
473  (*vi).VFp() = 0;
474  (*vi).VFi() = 0; // note that (0,-1) means uninitiazlied while 0,0 is the valid initialized values for isolated vertices.
475  }
476 
477  for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
478  if( ! (*fi).IsD() )
479  {
480  for(int j=0;j<(*fi).VN();++j)
481  {
482  (*fi).VFp(j) = (*fi).V(j)->VFp();
483  (*fi).VFi(j) = (*fi).V(j)->VFi();
484  (*fi).V(j)->VFp() = &(*fi);
485  (*fi).V(j)->VFi() = j;
486  }
487  }
488 }
489 
490 
492 
494 
498 class PEdgeTex
499 {
500 public:
501 
502  typename FaceType::TexCoordType v[2]; // the two TexCoord are ordered!
503  FacePointer f; // the face where this edge belong
504  int z; // index in [0..2] of the edge of the face
505 
506  PEdgeTex() {}
507 
508  void Set( FacePointer pf, const int nz )
509  {
510  assert(pf!=0);
511  assert(nz>=0);
512  assert(nz<3);
513 
514  v[0] = pf->WT(nz);
515  v[1] = pf->WT(pf->Next(nz));
516  assert(v[0] != v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes)
517 
518  if( v[1] < v[0] ) std::swap(v[0],v[1]);
519  f = pf;
520  z = nz;
521  }
522 
523  inline bool operator < ( const PEdgeTex & pe ) const
524  {
525  if( v[0]<pe.v[0] ) return true;
526  else if( pe.v[0]<v[0] ) return false;
527  else return v[1] < pe.v[1];
528  }
529  inline bool operator == ( const PEdgeTex & pe ) const
530  {
531  return (v[0]==pe.v[0]) && (v[1]==pe.v[1]);
532  }
533  inline bool operator != ( const PEdgeTex & pe ) const
534  {
535  return (v[0]!=pe.v[0]) || (v[1]!=pe.v[1]);
536  }
537 
538 };
539 
540 
542 
548 static void FaceFaceFromTexCoord(MeshType &m)
549 {
550  RequireFFAdjacency(m);
551  RequirePerFaceWedgeTexCoord(m);
553  for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
554  {
555  if (!(*fi).IsD())
556  {
557  for (int i = 0; i < (*fi).VN(); i++)
558  {
559  if (!vcg::face::IsBorder((*fi), i))
560  {
561  typename MeshType::FacePointer nextFace = (*fi).FFp(i);
562  int nextEdgeIndex = (*fi).FFi(i);
563  bool border = false;
564  if ((*fi).cV(i) == nextFace->cV(nextEdgeIndex))
565  {
566  if ((*fi).WT(i) != nextFace->WT(nextEdgeIndex) || (*fi).WT((*fi).Next(i)) != nextFace->WT(nextFace->Next(nextEdgeIndex)))
567  border = true;
568  }
569  else
570  {
571  if ((*fi).WT(i) != nextFace->WT(nextFace->Next(nextEdgeIndex)) || (*fi).WT((*fi).Next(i)) != nextFace->WT(nextEdgeIndex))
572  border = true;
573  }
574  if (border)
575  vcg::face::FFDetach((*fi), i);
576 
577  }
578  }
579  }
580  }
581 }
582 
584 static void TestVertexEdge(MeshType &m)
585 {
586  std::vector<int> numVertex(m.vert.size(),0);
587 
588  tri::RequireVEAdjacency(m);
589 
590  for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
591  {
592  if (!(*ei).IsD())
593  {
594  assert(tri::IsValidPointer(m,ei->V(0)));
595  assert(tri::IsValidPointer(m,ei->V(1)));
596  if(ei->VEp(0)) assert(tri::IsValidPointer(m,ei->VEp(0)));
597  if(ei->VEp(1)) assert(tri::IsValidPointer(m,ei->VEp(1)));
598  numVertex[tri::Index(m,(*ei).V(0))]++;
599  numVertex[tri::Index(m,(*ei).V(1))]++;
600  }
601  }
602 
603  for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
604  {
605  if (!vi->IsD())
606  {
607  int cnt =0;
608  for(edge::VEIterator<EdgeType> vei(&*vi);!vei.End();++vei)
609  cnt++;
610  assert((numVertex[tri::Index(m,*vi)] == 0) == (vi->VEp()==0) );
611  assert(cnt==numVertex[tri::Index(m,*vi)]);
612  (void)cnt;
613  }
614  }
615 }
616 
617 
619 static void TestVertexFace(MeshType &m)
620 {
621  SimpleTempData<typename MeshType::VertContainer, int > numVertex(m.vert,0);
622 
623  assert(tri::HasPerVertexVFAdjacency(m));
624 
625  for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
626  {
627  if (!(*fi).IsD())
628  {
629  numVertex[(*fi).V0(0)]++;
630  numVertex[(*fi).V1(0)]++;
631  numVertex[(*fi).V2(0)]++;
632  }
633  }
634 
635  vcg::face::VFIterator<FaceType> VFi;
636 
637  for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
638  {
639  if (!vi->IsD())
640  if(vi->VFp()!=0) // unreferenced vertices MUST have VF == 0;
641  {
642  int num=0;
643  assert(tri::IsValidPointer(m, vi->VFp()));
644  VFi.f=vi->VFp();
645  VFi.z=vi->VFi();
646  while (!VFi.End())
647  {
648  num++;
649  assert(!VFi.F()->IsD());
650  assert((VFi.F()->V(VFi.I()))==&(*vi));
651  ++VFi;
652  }
653  assert(num==numVertex[&(*vi)]);
654  (void)num;
655  }
656  }
657 }
658 
660 static void TestFaceFace(MeshType &m)
661 {
662  assert(HasFFAdjacency(m));
663 
664  for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
665  {
666  if (!fi->IsD())
667  {
668  for (int i=0;i<(*fi).VN();i++)
669  {
670  FaceType *ffpi=fi->FFp(i);
671  int e=fi->FFi(i);
672  //invariant property of FF topology for two manifold meshes
673  assert(ffpi->FFp(e) == &(*fi));
674  assert(ffpi->FFi(e) == i);
675 
676  // Test that the two faces shares the same edge
677  // Vertices of the i-th edges of the first face
678  VertexPointer v0i= fi->V0(i);
679  VertexPointer v1i= fi->V1(i);
680  // Vertices of the corresponding edge on the other face
681  VertexPointer ffv0i= ffpi->V0(e);
682  VertexPointer ffv1i= ffpi->V1(e);
683 
684  assert( (ffv0i==v0i) || (ffv0i==v1i) );
685  assert( (ffv1i==v0i) || (ffv1i==v1i) );
686  }
687 
688  }
689  }
690 }
691 
695 {
696 public:
697 
698  VertexPointer v; // the two Vertex pointer are ordered!
699  EdgePointer e; // the edge where this vertex belong
700  int z; // index in [0..1] of the vertex of the edge
701 
702  PVertexEdge( ) {}
703  PVertexEdge( EdgePointer pe, const int nz )
704 {
705  assert(pe!=0);
706  assert(nz>=0);
707  assert(nz<2);
708 
709  v= pe->V(nz);
710  e = pe;
711  z = nz;
712 }
713 inline bool operator < ( const PVertexEdge & pe ) const { return ( v<pe.v ); }
714 inline bool operator == ( const PVertexEdge & pe ) const { return ( v==pe.v ); }
715 inline bool operator != ( const PVertexEdge & pe ) const { return ( v!=pe.v ); }
716 };
717 
718 
719 
720 static void EdgeEdge(MeshType &m)
721 {
722  RequireEEAdjacency(m);
723  std::vector<PVertexEdge> v;
724  if( m.en == 0 ) return;
725 
726  for(EdgeIterator pf=m.edge.begin(); pf!=m.edge.end(); ++pf)
727  if( ! (*pf).IsD() )
728  for(int j=0;j<2;++j)
729  {
730  v.push_back(PVertexEdge(&*pf,j));
731  }
732 
733  sort(v.begin(), v.end());
734 
735  auto ps = v.begin();
736  auto pe = v.begin();
737  do
738  {
739  if( pe==v.end() || !(*pe == *ps) ) // search for blocs of edges with the same vertex
740  {
741  typename std::vector<PVertexEdge>::iterator q,q_next;
742  for (q=ps;q<pe-1;++q)
743  {
744  assert((*q).z>=0);
745  assert((*q).z< 2);
746  q_next = q;
747  ++q_next;
748  assert((*q_next).z>=0);
749  assert((*q_next).z< 2);
750  (*q).e->EEp(q->z) = (*q_next).e;
751  (*q).e->EEi(q->z) = (*q_next).z;
752  }
753  assert((*q).z>=0);
754  assert((*q).z< 2);
755  (*q).e->EEp((*q).z) = ps->e;
756  (*q).e->EEi((*q).z) = ps->z;
757  ps = pe;
758  }
759  if(pe==v.end()) break;
760  ++pe;
761  } while(true);
762 }
763 
764 static void VertexEdge(MeshType &m)
765 {
766  RequireVEAdjacency(m);
767 
768  for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
769  {
770  (*vi).VEp() = 0;
771  (*vi).VEi() = 0;
772  }
773 
774  for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
775  if( ! (*ei).IsD() )
776  {
777  for(int j=0;j<2;++j)
778  { assert(tri::IsValidPointer(m,ei->V(j)));
779  (*ei).VEp(j) = (*ei).V(j)->VEp();
780  (*ei).VEi(j) = (*ei).V(j)->VEi();
781  (*ei).V(j)->VEp() = &(*ei);
782  (*ei).V(j)->VEi() = j;
783  }
784  }
785 }
786 
787 }; // end class
788 
789 } // End namespace
790 } // End namespace
791 
792 
793 #endif
Definition: point3.h:43
static EdgeIterator AddEdges(MeshType &m, size_t n, PointerUpdater< EdgePointer > &pu)
Add n edges to the mesh. Function to add n edges to the mesh. The elements are added always to the en...
Definition: allocate.h:333
static void CompactEdgeVector(MeshType &m, PointerUpdater< EdgePointer > &pu)
Compact vector of edges removing deleted elements.
Definition: allocate.h:1122
static void DeleteEdge(MeshType &m, EdgeType &e)
Definition: allocate.h:946
Auxiliairy data structure for computing face face adjacency information.
Definition: topology.h:499
Auxiliary data structure for computing face face adjacency information.
Definition: topology.h:149
Point3< ScalarType > EdgeBarycentricToFaceBarycentric(ScalarType u) const
Definition: topology.h:187
Auxiliary data structure for computing tetra tetra adjacency information.
Definition: topology.h:70
Definition: topology.h:695
Generation of per-vertex and per-face topological information.
Definition: topology.h:43
static void ClearFaceFace(MeshType &m)
Clear the Face-Face topological relation setting each involved pointer to null. useful when you passe...
Definition: topology.h:378
static void VertexFace(MeshType &m)
Update the Vertex-Face topological relation.
Definition: topology.h:467
static void FaceFaceFromTexCoord(MeshType &m)
Update the Face-Face topological relation so that it reflects the per-wedge texture connectivity.
Definition: topology.h:548
static void FillEdgeVector(MeshType &m, std::vector< PEdge > &edgeVec, bool includeFauxEdge=true)
Definition: topology.h:200
static void FaceFace(MeshType &m)
Update the Face-Face topological relation by allowing to retrieve for each face what other faces shar...
Definition: topology.h:395
static void TestVertexFace(MeshType &m)
Test correctness of VFtopology.
Definition: topology.h:619
static void TestFaceFace(MeshType &m)
Test correctness of FFtopology (only for 2Manifold Meshes!)
Definition: topology.h:660
static void AllocateEdge(MeshType &m)
Initialize the edge vector all the edges that can be inferred from current face vector,...
Definition: topology.h:249
static void VertexTetra(MeshType &m)
Update the vertex-tetra topological relation.
Definition: topology.h:437
static void TetraTetra(MeshType &m)
Updates the Tetra-Tetra topological relation by allowing to retrieve for each tetra what other tetras...
Definition: topology.h:339
static void TestVertexEdge(MeshType &m)
Test correctness of VEtopology.
Definition: topology.h:584
static void ClearTetraTetra(MeshType &m)
Clear the tetra-tetra topological relation, setting each involved pointer to null....
Definition: topology.h:326
void ForEachTetra(const MeshType &m, Callable action)
Definition: foreach.h:270
void ForEachFace(const MeshType &m, Callable action)
Definition: foreach.h:78
void ForEachVertex(const MeshType &m, Callable action)
Definition: foreach.h:126
void EFStarFF(FaceType *fp, int ei, std::vector< FaceType * > &faceVec, std::vector< int > &indVed)
Compute the set of faces incident onto a given edge using FF adjacency.
Definition: topology.h:1020
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55
void FFDetach(FaceType &f, const int e)
Definition: topology.h:250
Definition: namespaces.dox:6