24 #ifndef __VCGLIB_CLEAN
25 #define __VCGLIB_CLEAN
27 #include <unordered_set>
30 #include <vcg/complex/complex.h>
31 #include <vcg/complex/algorithms/closest.h>
32 #include <vcg/space/index/grid_static_ptr.h>
33 #include <vcg/space/index/spatial_hashing.h>
34 #include <vcg/complex/algorithms/update/normal.h>
35 #include <vcg/space/triangle3.h>
36 #include <vcg/complex/append.h>
41 template <
class ConnectedEdgeMeshType>
45 typedef ConnectedEdgeMeshType MeshType;
46 typedef typename MeshType::VertexType VertexType;
47 typedef typename MeshType::VertexPointer VertexPointer;
48 typedef typename MeshType::VertexIterator VertexIterator;
49 typedef typename MeshType::ScalarType ScalarType;
50 typedef typename MeshType::EdgeType EdgeType;
51 typedef typename MeshType::EdgePointer EdgePointer;
52 typedef typename MeshType::EdgeIterator EdgeIterator;
53 typedef typename MeshType::ConstEdgeIterator ConstEdgeIterator;
54 typedef typename MeshType::EdgeContainer EdgeContainer;
59 EdgePointer ep = se.top();
61 for(
int i = 0; i < 2; ++i)
63 edge::VEIterator<EdgeType> vei(ep->V(i));
66 if (!tri::IsMarked(*mp, vei.E()))
68 tri::Mark(*mp, vei.E());
76 void start(MeshType &m, EdgePointer e)
78 tri::RequirePerEdgeMark(m);
94 EdgePointer operator *()
99 std::stack<EdgePointer> se;
103 template <
class ConnectedMeshType>
107 typedef ConnectedMeshType MeshType;
108 typedef typename MeshType::VertexType VertexType;
109 typedef typename MeshType::VertexPointer VertexPointer;
110 typedef typename MeshType::VertexIterator VertexIterator;
111 typedef typename MeshType::ScalarType ScalarType;
112 typedef typename MeshType::FaceType FaceType;
113 typedef typename MeshType::FacePointer FacePointer;
114 typedef typename MeshType::FaceIterator FaceIterator;
115 typedef typename MeshType::ConstFaceIterator ConstFaceIterator;
116 typedef typename MeshType::FaceContainer FaceContainer;
121 FacePointer fpt=sf.top();
123 for(
int j=0; j<fpt->VN(); ++j)
126 FacePointer l=fpt->FFp(j);
127 if( !tri::IsMarked(*mp,l) )
135 void start(MeshType &m, FacePointer p)
137 tri::RequirePerFaceMark(m);
139 while(!sf.empty()) sf.pop();
149 FacePointer operator *()
154 std::stack<FacePointer> sf;
163 template <
class CleanMeshType>
168 typedef CleanMeshType MeshType;
169 typedef typename MeshType::VertexType VertexType;
170 typedef typename MeshType::VertexPointer VertexPointer;
171 typedef typename MeshType::ConstVertexPointer ConstVertexPointer;
172 typedef typename MeshType::VertexIterator VertexIterator;
173 typedef typename MeshType::ConstVertexIterator ConstVertexIterator;
174 typedef typename MeshType::EdgeIterator EdgeIterator;
175 typedef typename MeshType::EdgePointer EdgePointer;
176 typedef typename MeshType::CoordType CoordType;
177 typedef typename MeshType::ScalarType ScalarType;
178 typedef typename MeshType::FaceType FaceType;
179 typedef typename MeshType::FacePointer FacePointer;
180 typedef typename MeshType::FaceIterator FaceIterator;
181 typedef typename MeshType::ConstFaceIterator ConstFaceIterator;
182 typedef typename MeshType::FaceContainer FaceContainer;
183 typedef typename MeshType::TetraType TetraType;
184 typedef typename MeshType::TetraPointer TetraPointer;
185 typedef typename MeshType::TetraIterator TetraIterator;
186 typedef typename MeshType::ConstTetraIterator ConstTetraIterator;
190 typedef GridStaticPtr<FaceType, ScalarType > TriMeshGrid;
195 inline bool operator()(VertexPointer
const &a, VertexPointer
const &b)
197 return ((*a).cP() == (*b).cP()) ? (a<b): ((*a).cP() < (*b).cP());
208 if(m.vert.size()==0 || m.vn==0)
return 0;
210 std::map<VertexPointer, VertexPointer> mp;
215 size_t num_vert = m.vert.size();
216 std::vector<VertexPointer> perm(num_vert);
217 for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++k)
222 std::sort(perm.begin(),perm.end(),c_obj);
226 mp[perm[i]] = perm[j];
230 if( (! (*perm[i]).IsD()) &&
231 (! (*perm[j]).IsD()) &&
232 (*perm[i]).P() == (*perm[j]).cP() )
234 VertexPointer t = perm[i];
235 mp[perm[i]] = perm[j];
247 for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi)
249 for(k = 0; k < (*fi).VN(); ++k)
250 if( mp.find( (
typename MeshType::VertexPointer)(*fi).V(k) ) != mp.end() )
252 (*fi).V(k) = &*mp[ (*fi).V(k) ];
256 for(EdgeIterator ei = m.edge.begin(); ei!=m.edge.end(); ++ei)
258 for(k = 0; k < 2; ++k)
259 if( mp.find( (
typename MeshType::VertexPointer)(*ei).V(k) ) != mp.end() )
261 (*ei).V(k) = &*mp[ (*ei).V(k) ];
264 for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
266 for (k = 0; k < 4; ++k)
267 if (mp.find((
typename MeshType::VertexPointer)(*ti).V(k)) != mp.end())
268 (*ti).V(k) = &*mp[ (*ti).V(k) ];
271 if(RemoveDegenerateFlag && m.en>0) {
272 RemoveDegenerateEdge(m);
282 SortedPair(
unsigned int v0,
unsigned int v1, EdgePointer _fp)
286 if(v[0]>v[1]) std::swap(v[0],v[1]);
290 return (v[1]!=p.v[1])?(v[1]<p.v[1]):
295 if( (v[0]==s.v[0]) && (v[1]==s.v[1]) )
return true;
306 SortedTriple(
unsigned int v0,
unsigned int v1,
unsigned int v2,FacePointer _fp)
308 v[0]=v0;v[1]=v1;v[2]=v2;
314 return (v[2]!=p.v[2])?(v[2]<p.v[2]):
315 (v[1]!=p.v[1])?(v[1]<p.v[1]):
320 if( (v[0]==s.v[0]) && (v[1]==s.v[1]) && (v[2]==s.v[2]) )
return true;
336 std::vector<SortedTriple> fvec;
337 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
341 tri::Index(m,(*fi).V(1)),
342 tri::Index(m,(*fi).V(2)),
345 std::sort(fvec.begin(),fvec.end());
347 for(
int i=0;i<int(fvec.size())-1;++i)
349 if(fvec[i]==fvec[i+1])
365 if (m.en==0)
return 0;
366 std::vector<SortedPair> eVec;
367 for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
370 eVec.push_back(
SortedPair( tri::Index(m,(*ei).V(0)), tri::Index(m,(*ei).V(1)), &*ei));
372 std::sort(eVec.begin(),eVec.end());
374 for(
int i=0;i<int(eVec.size())-1;++i)
376 if(eVec[i]==eVec[i+1])
385 static int CountUnreferencedVertex( MeshType& m)
398 tri::RequirePerVertexFlags(m);
400 std::vector<bool> referredVec(m.vert.size(),
false);
403 for(
auto fi = m.face.begin(); fi != m.face.end(); ++fi)
405 for(
auto j=0; j < (*fi).VN(); ++j)
406 referredVec[tri::Index(m, (*fi).V(j))]=
true;
408 for(
auto ei=m.edge.begin();ei!=m.edge.end();++ei)
410 referredVec[tri::Index(m, (*ei).V(0))]=
true;
411 referredVec[tri::Index(m, (*ei).V(1))]=
true;
414 for(
auto ti=m.tetra.begin(); ti!=m.tetra.end();++ti)
416 referredVec[tri::Index(m, (*ti).V(0))]=
true;
417 referredVec[tri::Index(m, (*ti).V(1))]=
true;
418 referredVec[tri::Index(m, (*ti).V(2))]=
true;
419 referredVec[tri::Index(m, (*ti).V(3))]=
true;
423 if(!DeleteVertexFlag)
424 return std::count(referredVec.begin(),referredVec.end(),
false);
426 for(
auto vi=m.vert.begin();vi!=m.vert.end();++vi)
427 if( (!(*vi).IsD()) && (!referredVec[tri::Index(m,*vi)]) )
444 for(vi=m.vert.begin(); vi!=m.vert.end();++vi)
445 if(math::IsNAN( (*vi).P()[0]) ||
446 math::IsNAN( (*vi).P()[1]) ||
447 math::IsNAN( (*vi).P()[2]) )
456 for(fi=m.face.begin(); fi!=m.face.end();++fi)
458 if( (*fi).V(0)->IsD() ||
481 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
484 if((*fi).V(0) == (*fi).V(1) ||
485 (*fi).V(0) == (*fi).V(2) ||
486 (*fi).V(1) == (*fi).V(2) )
495 static int RemoveDegenerateEdge(MeshType& m)
499 for(EdgeIterator ei=m.edge.begin(); ei!=m.edge.end();++ei)
502 if((*ei).V(0) == (*ei).V(1) )
511 static int RemoveNonManifoldVertex(MeshType& m)
515 int count_removed = 0;
516 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
517 if(!(*fi).IsD() && (*fi).IsS())
519 for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end();++vi)
520 if(!(*vi).IsD() && (*vi).IsS()) {
524 return count_removed;
528 static int SplitSelectedVertexOnEdgeMesh(MeshType& m)
530 tri::RequireCompactness(m);
533 std::unordered_map<size_t,size_t> refCount;
534 size_t countSplit = 0;
535 for (
size_t i=0; i<m.edge.size(); ++i)
537 for (
int j=0; j<2; ++j)
539 const VertexPointer vp = m.edge[i].V(j);
542 const size_t refs = ++refCount[Index(m, m.edge[i].V(j))];
553 for (
size_t i=0; i<m.edge.size(); ++i)
555 for (
int j=0; j<2; ++j)
557 const VertexPointer vp = m.edge[i].V(j);
558 const size_t vIdx = Index(m, vp);
561 if (--refCount[vIdx] > 0)
563 newVertIt->ImportData(*vp);
564 m.edge[i].V(j) = &*(newVertIt++);
570 return int(countSplit);
574 static void SelectNonManifoldVertexOnEdgeMesh(MeshType &m)
576 tri::RequireCompactness(m);
578 std::vector<int> cnt(m.vn,0);
580 for(
size_t i=0;i<m.edge.size();++i)
582 cnt[tri::Index(m,m.edge[i].V(0))]++;
583 cnt[tri::Index(m,m.edge[i].V(1))]++;
585 for(
size_t i=0;i<m.vert.size();++i)
586 if(cnt[i]>2) m.vert[i].SetS();
589 static void SelectCreaseVertexOnEdgeMesh(MeshType &m, ScalarType AngleRadThr)
591 tri::RequireCompactness(m);
592 tri::RequireVEAdjacency(m);
593 tri::UpdateTopology<MeshType>::VertexEdge(m);
595 for(
size_t i=0;i<m.vert.size();++i)
597 std::vector<VertexPointer> VVStarVec;
598 edge::VVStarVE(&(m.vert[i]),VVStarVec);
599 if(VVStarVec.size()==2)
601 CoordType v0 = m.vert[i].P() - VVStarVec[0]->P();
602 CoordType v1 = m.vert[i].P() - VVStarVec[1]->P();
603 float angle = M_PI-vcg::Angle(v0,v1);
604 if(angle > AngleRadThr) m.vert[i].SetS();
619 RequireFFAdjacency(m);
620 typedef std::pair<FacePointer,int> FaceInt;
622 std::vector<std::pair<VertexPointer, std::vector<FaceInt> > >ToSplitVec;
628 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
630 for (
int i=0; i<fi->VN(); i++)
631 if ((*fi).V(i)->IsS() && !(*fi).V(i)->IsV())
634 face::Pos<FaceType> startPos(&*fi,i);
635 face::Pos<FaceType> curPos = startPos;
636 std::set<FaceInt> faceSet;
639 faceSet.insert(std::make_pair(curPos.F(),curPos.VInd()));
642 }
while (curPos != startPos);
644 ToSplitVec.push_back(make_pair((*fi).V(i),std::vector<FaceInt>()));
646 typename std::set<FaceInt>::const_iterator iii;
648 for(iii=faceSet.begin();iii!=faceSet.end();++iii)
649 ToSplitVec.back().second.push_back(*iii);
656 for(
size_t i =0;i<ToSplitVec.size();++i)
659 VertexPointer np=ToSplitVec[i].first;
661 firstVp->ImportData(*np);
663 CoordType delta(0,0,0);
664 for(
size_t j=0;j<ToSplitVec[i].second.size();++j)
666 FaceInt ff=ToSplitVec[i].second[j];
667 ff.first->V(ff.second)=&*firstVp;
668 delta+=Barycenter(*(ff.first))-np->cP();
670 delta /= ToSplitVec[i].second.size();
671 firstVp->P() = firstVp->P() + delta * moveThreshold;
675 return int(ToSplitVec.size());
681 typedef typename MeshType::FacePointer FacePointer;
682 typedef typename MeshType::FaceIterator FaceIterator;
684 RequireFFAdjacency(m);
690 tmpMesh.vert.EnableVFAdjacency();
691 tmpMesh.face.EnableVFAdjacency();
693 if (m.face.IsWedgeTexCoordEnabled())
694 tmpMesh.face.EnableWedgeTexCoord();
698 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
699 if( !(*fi).IsD() && !(*fi).IsV() && !(*fi).IsS())
703 std::deque<FacePointer> visitStack;
704 visitStack.push_back(&*fi);
709 while(!visitStack.empty())
711 FacePointer fp = visitStack.front();
712 visitStack.pop_front();
714 for(
int i=0;i<fp->VN();++i) {
715 FacePointer ff = fp->FFp(i);
721 visitStack.push_back(ff);
732 for (
size_t i = 0; i < size_t(tmpMesh.VN()); ++i)
734 VertexType & v = tmpMesh.vert[i];
738 std::vector<FacePointer> faceVec;
739 std::vector<int> idxVec;
743 CoordType delta(0, 0, 0);
744 for (
auto fp : faceVec)
746 delta += vcg::Barycenter(*fp) - v.cP();
748 delta /= faceVec.size();
750 v.P() += delta * moveThreshold;
762 bool operator ()(FacePointer
const& f1, FacePointer
const& f2)
const {
763 return DoubleArea(*f1) < DoubleArea(*f2);
772 std::vector<FacePointer> ToDelVec;
774 for(fi=m.face.begin(); fi!=m.face.end();++fi)
777 if ((!IsManifold(*fi,0))||
778 (!IsManifold(*fi,1))||
779 (!IsManifold(*fi,2)))
780 ToDelVec.push_back(&*fi);
785 for(
size_t i=0;i<ToDelVec.size();++i)
787 if(!ToDelVec[i]->IsD())
789 FaceType &ff= *ToDelVec[i];
790 if ((!IsManifold(ff,0))||
791 (!IsManifold(ff,1))||
795 if(!face::IsBorder<FaceType>(ff,j))
796 vcg::face::FFDetach<FaceType>(ff,j);
807 static int RemoveFaceOutOfRangeArea(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits<ScalarType>::max)(),
bool OnlyOnSelected=
false)
812 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi){
814 if(!OnlyOnSelected || (*fi).IsS())
816 const ScalarType doubleArea=DoubleArea<FaceType>(*fi);
817 if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) )
827 static int RemoveZeroAreaFace(MeshType& m) {
return RemoveFaceOutOfRangeArea(m,0);}
836 typedef typename MeshType::FaceType F;
837 tri::RequirePerFaceFlags(m);
838 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
839 unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2);
840 if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2)
return false;
846 static bool IsFaceFauxConsistent(MeshType &m)
848 RequirePerFaceFlags(m);
849 RequireFFAdjacency(m);
850 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
852 for(
int z=0;z<(*fi).VN();++z)
854 FacePointer fp = fi->FFp(z);
856 if(fi->IsF(z) != fp->IsF(zp))
return false;
867 tri::RequirePerFaceFlags(m);
868 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) {
869 if ( !fi->IsD() && fi->IsAnyF() )
return false;
874 static bool IsBitPolygonal(
const MeshType &m){
884 tri::RequirePerFaceFlags(m);
885 typedef typename MeshType::FaceType F;
886 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
887 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
888 if ( tmp!=F::FAUX0 && tmp!=F::FAUX1 && tmp!=F::FAUX2 && tmp!=0 )
return false;
899 tri::RequirePerFaceFlags(m);
900 typedef typename MeshType::FaceType F;
902 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
903 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
904 if ( tmp==F::FAUX0 || tmp==F::FAUX1 || tmp==F::FAUX2) count++;
914 tri::RequirePerFaceFlags(m);
916 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
917 if (!(fi->IsAnyF())) count++;
928 tri::RequirePerFaceFlags(m);
930 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
931 if (fi->IsF(0)) count++;
932 if (fi->IsF(1)) count++;
933 if (fi->IsF(2)) count++;
935 return m.fn - count/2;
955 std::unordered_map<ConstVertexPointer, bool> vertVisited;
956 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
957 if (!vi->IsD()) vertVisited[&(*vi)] =
true;
960 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
962 for(
int i=0;i<3;++i){
963 vertVisited[fi->V(i)] =
false;
970 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
978 vertVisited[fi->V0(i)] =
true;
979 vertVisited[fi->V1(i)] =
true;
986 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
987 if (!vi->IsD() && !(vertVisited[&(*vi)])) countV++;
989 return m.fn - countE/2 + countV ;
1002 RequireFFAdjacency(m);
1003 RequirePerFaceFlags(m);
1005 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1007 for (
int k=0; k<3; k++)
1008 if( ( fi->IsF(k) != fi->cFFp(k)->IsF(fi->cFFi(k)) ) ||
1022 MeshAssert<MeshType>::OnlyEdgeMesh(m);
1023 RequireEEAdjacency(m);
1028 int nonManifoldCnt=0;
1029 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1033 for (ei = m.edge.begin(); ei != m.edge.end(); ++ei)
if (!ei->IsD())
1041 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if (!vi->IsD())
1045 if(SelectFlag) (*vi).SetS();
1049 return nonManifoldCnt;
1060 RequireFFAdjacency(m);
1062 nmfBit[0]= FaceType::NewBitFlag();
1063 nmfBit[1]= FaceType::NewBitFlag();
1064 nmfBit[2]= FaceType::NewBitFlag();
1075 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1079 for(
int i=0;i<3;++i)
1080 if(!IsManifold(*fi,i))
1082 if(!(*fi).IsUserBit(nmfBit[i]))
1087 (*fi).V0(i)->SetS();
1088 (*fi).V1(i)->SetS();
1091 face::Pos<FaceType> nmf(&*fi,i);
1094 if(SelectFlag) nmf.F()->SetS();
1095 nmf.F()->SetUserBit(nmfBit[nmf.E()]);
1098 while(nmf.f != &*fi);
1112 RequireFFAdjacency(m);
1115 int nonManifoldCnt=0;
1116 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1120 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1122 for (
int k=0; k<fi->VN(); k++)
1131 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1133 for(
int i=0; i<fi->VN(); ++i)
1134 if (!IsManifold(*fi,i))
1136 (*fi).V0(i)->SetV();
1137 (*fi).V1(i)->SetV();
1142 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1144 for(
int i=0; i<fi->VN(); i++)
if (!(*fi).V(i)->IsV())
1147 face::Pos<FaceType> pos(&(*fi),i);
1149 int starSizeFF = pos.NumberOfIncidentFaces();
1151 if (starSizeFF != TD[(*fi).V(i)])
1159 return nonManifoldCnt;
1170 int edgeNum=0,edgeBorderNum=0,edgeNonManifNum=0;
1171 CountEdgeNum(m, edgeNum, edgeBorderNum,edgeNonManifNum);
1172 return (edgeBorderNum==0) && (edgeNonManifNum==0);
1175 static void CountEdgeNum( MeshType & m,
int &total_e,
int &boundary_e,
int &non_manif_e )
1177 std::vector< typename tri::UpdateTopology<MeshType>::PEdge > edgeVec;
1179 sort(edgeVec.begin(), edgeVec.end());
1184 size_t f_on_cur_edge =1;
1185 for(
size_t i=0;i<edgeVec.size();++i)
1187 if(( (i+1) == edgeVec.size()) || !(edgeVec[i] == edgeVec[i+1]))
1190 if(f_on_cur_edge==1)
1205 static int CountHoles( MeshType & m)
1207 UpdateFlags<MeshType>::FaceClearV(m);
1209 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
if(!fi->IsD())
1211 for(
int j=0;j<3;++j)
1215 face::Pos<FaceType> startPos(&*fi,j);
1216 face::Pos<FaceType> curPos=startPos;
1222 while(curPos!=startPos);
1234 static int CountConnectedComponents(MeshType &m)
1236 std::vector< std::pair<int,FacePointer> > CCV;
1237 return ConnectedComponents(m,CCV);
1240 static int ConnectedComponents(MeshType &m, std::vector< std::pair<int,FacePointer> > &CCV)
1242 tri::RequireFFAdjacency(m);
1244 tri::UpdateFlags<MeshType>::FaceClearV(m);
1245 std::stack<FacePointer> sf;
1246 FacePointer fpt=&*(m.face.begin());
1247 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1249 if(!((*fi).IsD()) && !(*fi).IsV())
1252 CCV.push_back(std::make_pair(0,&*fi));
1259 for(
int j=0; j<fpt->VN(); ++j)
1263 FacePointer l = fpt->FFp(j);
1274 return int(CCV.size());
1277 static int edgeMeshConnectedComponents(MeshType & poly, std::vector<std::pair<int, typename MeshType::EdgePointer> > &eCC)
1279 typedef typename MeshType::EdgePointer EdgePointer;
1280 tri::UpdateTopology<MeshType>::VertexEdge(poly);
1281 tri::UpdateFlags<MeshType>::EdgeClear(poly);
1283 std::stack<EdgePointer> stack;
1285 for (
auto ei = poly.edge.begin(); ei != poly.edge.end(); ++ei)
1286 if (!ei->IsD() && !ei->IsV())
1290 std::pair<int, EdgePointer> cc(1, &*ei);
1293 while (!stack.empty())
1295 EdgePointer ep = stack.top();
1298 for (
int i = 0; i < 2; ++i)
1300 edge::VEIterator<typename MeshType::EdgeType> vei(ep->V(i));
1303 if (!vei.E()->IsV())
1306 stack.push(vei.E());
1315 return int(eCC.size());
1318 static void ComputeValence( MeshType &m,
typename MeshType::PerVertexIntHandle &h)
1320 for(VertexIterator vi=m.vert.begin(); vi!= m.vert.end();++vi)
1323 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1326 for(
int j=0;j<fi->VN();j++)
1327 ++h[tri::Index(m,fi->V(j))];
1366 static int MeshGenus(
int nvert,
int nedges,
int nfaces,
int numholes,
int numcomponents)
1368 return -((nvert + nfaces - nedges + numholes - 2 * numcomponents) / 2);
1375 int boundary_e,total_e,nonmanif_e;
1376 CountEdgeNum(m,total_e,boundary_e,nonmanif_e);
1377 int numholes=CountHoles(m);
1378 int numcomponents=CountConnectedComponents(m);
1379 int G=
MeshGenus(nvert,total_e,nfaces,numholes,numcomponents);
1396 RequireVFAdjacency(m);
1402 for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1406 face::Pos<FaceType> he((*vi).VFp(), &*vi);
1407 face::Pos<FaceType> ht = he;
1423 if ((n != 6)&&(!border && n != 4))
1432 Semiregular =
false;
1436 Semiregular =
false;
1441 static bool IsCoherentlyOrientedMesh(MeshType &m)
1443 RequireFFAdjacency(m);
1444 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1445 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1447 for(
int i=0;i<3;++i)
1454 static void OrientCoherentlyMesh(MeshType &m,
bool &_IsOriented,
bool &_IsOrientable)
1456 RequireFFAdjacency(m);
1457 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1458 bool IsOrientable =
true;
1459 bool IsOriented =
true;
1461 UpdateFlags<MeshType>::FaceClearV(m);
1462 std::stack<FacePointer> faces;
1463 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1465 if (!fi->IsD() && !fi->IsV())
1470 while (!faces.empty())
1472 FacePointer fp = faces.top();
1476 for (
int j = 0; j < 3; j++)
1478 if (!
face::IsBorder(*fp,j) && face::IsManifold<FaceType>(*fp, j))
1480 FacePointer fpaux = fp->FFp(j);
1481 int iaux = fp->FFi(j);
1482 if (!CheckOrientation(*fpaux, iaux))
1487 face::SwapEdge<FaceType,true>(*fpaux, iaux);
1490 IsOrientable =
false;
1503 if (!IsOrientable)
break;
1505 _IsOriented = IsOriented;
1506 _IsOrientable = IsOrientable;
1513 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD())
1514 if(!selected || (*fi).IsS())
1516 face::SwapEdge<FaceType,false>((*fi), 0);
1517 if (HasPerWedgeTexCoord(m))
1518 std::swap((*fi).WT(0),(*fi).WT(1));
1528 if(m.vert.empty())
return false;
1533 std::vector< VertexPointer > minVertVec;
1534 std::vector< VertexPointer > maxVertVec;
1537 std::vector< CoordType > dirVec;
1538 dirVec.push_back(CoordType(1,0,0));
1539 dirVec.push_back(CoordType(0,1,0));
1540 dirVec.push_back(CoordType(0,0,1));
1541 dirVec.push_back(CoordType( 1, 1,1));
1542 dirVec.push_back(CoordType(-1, 1,1));
1543 dirVec.push_back(CoordType(-1,-1,1));
1544 dirVec.push_back(CoordType( 1,-1,1));
1545 for(
size_t i=0;i<dirVec.size();++i)
1547 Normalize(dirVec[i]);
1548 minVertVec.push_back(&*m.vert.begin());
1549 maxVertVec.push_back(&*m.vert.begin());
1551 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if(!(*vi).IsD())
1553 for(
size_t i=0;i<dirVec.size();++i)
1555 if( (*vi).cP().dot(dirVec[i]) < minVertVec[i]->P().dot(dirVec[i])) minVertVec[i] = &*vi;
1556 if( (*vi).cP().dot(dirVec[i]) > maxVertVec[i]->P().dot(dirVec[i])) maxVertVec[i] = &*vi;
1561 ScalarType angleThreshold = cos(math::ToRad(85.0));
1562 for(
size_t i=0;i<dirVec.size();++i)
1566 if(minVertVec[i]->N().dot(dirVec[i]) > angleThreshold ) voteCount++;
1567 if(maxVertVec[i]->N().dot(dirVec[i]) < -angleThreshold ) voteCount++;
1570 if(voteCount <
int(dirVec.size())/2)
return false;
1578 static int RemoveFaceFoldByFlip(MeshType &m,
float normalThresholdDeg=175,
bool repeat=
true)
1580 RequireFFAdjacency(m);
1581 RequirePerVertexMark(m);
1583 int count, total = 0;
1590 ScalarType NormalThrRad = math::ToRad(normalThresholdDeg);
1591 ScalarType eps = ScalarType(0.0001);
1593 for(FaceIterator fi=m.face.begin();fi!= m.face.end();++fi )
if(!(*fi).IsV())
1595 if( vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(0)).Normalize()) > NormalThrRad &&
1596 vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(1)).Normalize()) > NormalThrRad &&
1597 vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(2)).Normalize()) > NormalThrRad )
1602 for(
int i=0;i<3;i++)
1606 bool ret = vcg::InterpolationParameters((*(*fi).FFp(i)),TriangleNormal(*(*fi).FFp(i)),p,L);
1607 if(ret && L[0]>eps && L[1]>eps && L[2]>eps)
1609 (*fi).FFp(i)->SetS();
1610 (*fi).FFp(i)->SetV();
1612 if(face::CheckFlipEdge<FaceType>( *fi, i )) {
1613 face::FlipEdge<FaceType>( *fi, i );
1623 while( repeat && count );
1628 static int RemoveTVertexByFlip(MeshType &m,
float threshold=40,
bool repeat=
true)
1630 RequireFFAdjacency(m);
1631 RequirePerVertexMark(m);
1633 int count, total = 0;
1641 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1643 FacePointer f = &(m.face[index]);
float sides[3]; CoordType dummy;
1644 sides[0] = Distance(f->P(0), f->P(1));
1645 sides[1] = Distance(f->P(1), f->P(2));
1646 sides[2] = Distance(f->P(2), f->P(0));
1648 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1649 if( tri::IsMarked(m,f->V2(i) ))
continue;
1651 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1653 tri::Mark(m,f->V2(i));
1654 if(face::CheckFlipEdge<FaceType>( *f, i )) {
1656 FacePointer g = f->FFp(i);
int k = f->FFi(i);
1657 Triangle3<ScalarType> t1(f->P(i), f->P1(i), f->P2(i)), t2(g->P(k), g->P1(k), g->P2(k)),
1658 t3(f->P(i), g->P2(k), f->P2(i)), t4(g->P(k), f->P2(i), g->P2(k));
1660 if ( std::min( QualityFace(t1), QualityFace(t2) ) < std::min( QualityFace(t3), QualityFace(t4) ))
1662 face::FlipEdge<FaceType>( *f, i );
1672 while( repeat && count );
1676 static int RemoveTVertexByCollapse(MeshType &m,
float threshold=40,
bool repeat=
true)
1678 RequirePerVertexMark(m);
1680 int count, total = 0;
1687 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1689 FacePointer f = &(m.face[index]);
1693 sides[0] = Distance(f->P(0), f->P(1));
1694 sides[1] = Distance(f->P(1), f->P(2));
1695 sides[2] = Distance(f->P(2), f->P(0));
1696 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1697 if( tri::IsMarked(m,f->V2(i) ))
continue;
1699 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1701 tri::Mark(m,f->V2(i));
1703 int j = Distance(dummy,f->P(i))<Distance(dummy,f->P1(i))?i:(i+1)%3;
1704 f->P2(i) = f->P(j); tri::Mark(m,f->V(j));
1714 while( repeat && count );
1719 static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret)
1721 RequirePerFaceMark(m);
1723 int referredBit = FaceType::NewBitFlag();
1724 tri::UpdateFlags<MeshType>::FaceClear(m,referredBit);
1727 gM.Set(m.face.begin(),m.face.end());
1729 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
1731 (*fi).SetUserBit(referredBit);
1732 Box3< ScalarType> bbox;
1733 (*fi).GetBBox(bbox);
1734 std::vector<FaceType*> inBox;
1735 vcg::tri::GetInBoxFace(m, gM, bbox,inBox);
1736 bool Intersected=
false;
1737 typename std::vector<FaceType*>::iterator fib;
1738 for(fib=inBox.begin();fib!=inBox.end();++fib)
1740 if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) )
1742 ret.push_back(*fib);
1744 ret.push_back(&*fi);
1752 FaceType::DeleteBitFlag(referredBit);
1753 return (ret.size()>0);
1761 int DeletedVertNum=0;
1762 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1763 if((*vi).IsD()) DeletedVertNum++;
1765 int DeletedEdgeNum=0;
1766 for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
1767 if((*ei).IsD()) DeletedEdgeNum++;
1769 int DeletedFaceNum=0;
1770 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1771 if((*fi).IsD()) DeletedFaceNum++;
1773 if(
size_t(m.vn+DeletedVertNum) != m.vert.size())
return false;
1774 if(
size_t(m.en+DeletedEdgeNum) != m.edge.size())
return false;
1775 if(
size_t(m.fn+DeletedFaceNum) != m.face.size())
return false;
1786 RequireFFAdjacency(m);
1788 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1791 for(
int i=0;i<3;++i)
1792 if(!FFCorrectness(*fi, i))
return false;
1802 tri::RequirePerFaceWedgeTexCoord(m);
1804 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1806 { FaceType &f=(*fi);
1807 if( ! ( (f.WT(0).N() == f.WT(1).N()) && (f.WT(0).N() == (*fi).WT(2).N()) ) )
1810 if((*fi).WT(0).N() <0)
return false;
1820 tri::RequirePerFaceWedgeTexCoord(m);
1822 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1825 if( (*fi).WT(0).P() == (*fi).WT(1).P() && (*fi).WT(0).P() == (*fi).WT(2).P() )
return false;
1841 if(sv==3)
return true;
1842 if(sv==0)
return (vcg::IntersectionTriangleTriangle<FaceType>((*f0),(*f1)));
1848 int i0,i1; ScalarType a,b;
1850 CoordType shP = f0->V(i0)->P()*0.5;
1851 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) )
1854 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
1857 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) )
1860 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
1876 mergedCnt = ClusterVertex(m,radius);
1881 static int ClusterVertex(MeshType &m,
const ScalarType radius)
1883 if(m.vn==0)
return 0;
1886 typedef vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT;
1888 tri::EmptyTMark<MeshType> markerFunctor;
1889 std::vector<VertexType*> closests;
1891 sht.Set(m.vert.begin(), m.vert.end());
1893 for(VertexIterator viv = m.vert.begin(); viv!= m.vert.end(); ++viv)
1894 if(!(*viv).IsD() && !(*viv).IsV())
1899 GridGetInBox(sht, markerFunctor, bb, closests);
1901 for(
size_t i=0; i<closests.size(); ++i)
1903 ScalarType dist = Distance(p,closests[i]->cP());
1904 if(dist < radius && !closests[i]->IsV())
1908 closests[i]->SetV();
1917 static std::pair<int,int> RemoveSmallConnectedComponentsSize(MeshType &m,
int maxCCSize)
1919 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1920 int TotalCC=ConnectedComponents(m, CCV);
1923 ConnectedComponentIterator<MeshType> ci;
1924 for(
unsigned int i=0;i<CCV.size();++i)
1926 std::vector<typename MeshType::FacePointer> FPV;
1927 if(CCV[i].first<maxCCSize)
1930 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1933 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
1934 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
1938 return std::make_pair(TotalCC,DeletedCC);
1946 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1947 int TotalCC=ConnectedComponents(m, CCV);
1950 for(
unsigned int i=0;i<CCV.size();++i)
1953 std::vector<typename MeshType::FacePointer> FPV;
1954 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1957 bb.
Add((*ci)->P(0));
1958 bb.
Add((*ci)->P(1));
1959 bb.
Add((*ci)->P(2));
1961 if(bb.
Diag()<maxDiameter)
1964 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
1965 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
1969 return std::make_pair(TotalCC,DeletedCC);
1976 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1977 int TotalCC=ConnectedComponents(m, CCV);
1980 for(
unsigned int i=0;i<CCV.size();++i)
1983 std::vector<typename MeshType::FacePointer> FPV;
1984 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1987 bb.
Add((*ci)->P(0));
1988 bb.
Add((*ci)->P(1));
1989 bb.
Add((*ci)->P(2));
1991 if(bb.
Diag()>minDiameter)
1994 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
1995 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
1999 return std::make_pair(TotalCC,DeletedCC);
2012 typedef std::unordered_set<VertexPointer> VertexSet;
2013 tri::RequireVFAdjacency(m);
2014 tri::RequirePerFaceNormal(m);
2015 tri::RequirePerVertexNormal(m);
2020 if (cosThreshold > 0)
2023 #pragma omp parallel for schedule(dynamic, 10)
2024 for (
int i = 0; i < m.face.size(); i++)
2026 VertexSet nearVertex;
2027 std::vector<CoordType> pointVec;
2028 FacePointer f = &m.face[i];
2029 for (
int j = 0; j < 3; j++)
2031 std::vector<VertexPointer> temp;
2032 vcg::face::VVStarVF<FaceType>(f->V(j), temp);
2033 typename std::vector<VertexPointer>::iterator iter = temp.begin();
2034 for (; iter != temp.end(); iter++)
2036 if ((*iter) != f->V1(j) && (*iter) != f->V2(j))
2038 if (nearVertex.insert((*iter)).second)
2039 pointVec.push_back((*iter)->P());
2042 nearVertex.insert(f->V(j));
2043 pointVec.push_back(f->P(j));
2046 if (pointVec.size() > 3)
2048 vcg::Plane3<ScalarType> plane;
2049 vcg::FitPlaneToPointSet(pointVec, plane);
2051 for (
auto nvp : nearVertex)
2052 avgDot += plane.Direction().dot(nvp->N());
2053 avgDot /= nearVertex.size();
2054 typename MeshType::VertexType::NormalType normal;
2056 normal = -plane.Direction();
2058 normal = plane.Direction();
2059 if (normal.dot(f->N()) < cosThreshold)
2070 RequirePerFaceMark(m2);
2071 RequireCompactness(m1);
2072 RequireCompactness(m2);
2077 gM.Set(m2.face.begin(),m2.face.end());
2079 for(
auto fi=m1.face.begin();fi!=m1.face.end();++fi)
2082 (*fi).GetBBox(bbox);
2083 std::vector<FaceType*> inBox;
2084 vcg::tri::GetInBoxFace(m2, gM, bbox,inBox);
2085 for(
auto fib=inBox.begin(); fib!=inBox.end(); ++fib)
void Add(const Box3< BoxScalarType > &b)
Definition: box3.h:104
BoxScalarType Diag() const
Return the lenght of the diagonal of the box .
Definition: box3.h:240
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
static void CompactFaceVector(MeshType &m, PointerUpdater< FacePointer > &pu)
Compact face vector by removing deleted elements.
Definition: allocate.h:1231
static void DeleteFace(MeshType &m, FaceType &f)
Definition: allocate.h:923
static void CompactVertexVector(MeshType &m, PointerUpdater< VertexPointer > &pu)
Compact vector of vertices removing deleted elements. Deleted elements are put to the end of the vect...
Definition: allocate.h:1084
static void DeleteVertex(MeshType &m, VertexType &v)
Definition: allocate.h:935
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater< VertexPointer > &pu)
Add n vertices to the mesh. Function to add n vertices to the mesh. The elements are added always to ...
Definition: allocate.h:189
static void DeleteEdge(MeshType &m, EdgeType &e)
Definition: allocate.h:946
static void MeshCopy(MeshLeft &ml, ConstMeshRight &mr, bool selected=false, const bool adjFlag=false)
Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected ...
Definition: append.h:601
static void Mesh(MeshLeft &ml, ConstMeshRight &mr, const bool selected=false, const bool adjFlag=false)
Append the second mesh to the first one.
Definition: append.h:253
Class of static functions to clean//restore meshs.
Definition: clean.h:165
static int RemoveDegenerateFace(MeshType &m)
Definition: clean.h:477
static int RemoveDuplicateFace(MeshType &m)
Definition: clean.h:334
static void SelectFoldedFaceFromOneRingFaces(MeshType &m, ScalarType cosThreshold)
Definition: clean.h:2010
static bool FlipNormalOutside(MeshType &m)
Definition: clean.h:1526
static int RemoveDuplicateVertex(MeshType &m, bool RemoveDegenerateFlag=true)
Definition: clean.h:206
static bool IsSizeConsistent(MeshType &m)
Definition: clean.h:1759
static int SelectIntersectingFaces(MeshType &m1, MeshType &m2)
Definition: clean.h:2068
static bool IsBitTriQuadOnly(const MeshType &m)
Definition: clean.h:882
static bool IsBitTriOnly(const MeshType &m)
Definition: clean.h:865
static bool HasZeroTexCoordFace(MeshType &m)
Definition: clean.h:1818
static std::pair< int, int > RemoveSmallConnectedComponentsDiameter(MeshType &m, ScalarType maxDiameter)
Remove the connected components smaller than a given diameter.
Definition: clean.h:1944
static size_t SplitManifoldComponents(MeshType &m, const ScalarType moveThreshold=0)
This function expand current selection to cover the whole connected component.
Definition: clean.h:679
static bool IsBitQuadOnly(const MeshType &m)
Definition: clean.h:834
static int CountNonManifoldEdgeEE(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1020
static int RemoveUnreferencedVertex(MeshType &m, bool DeleteVertexFlag=true)
Definition: clean.h:396
static int SplitNonManifoldVertex(MeshType &m, ScalarType moveThreshold)
Removal of faces that were incident on a non manifold edge.
Definition: clean.h:617
static int MeshGenus(int nvert, int nedges, int nfaces, int numholes, int numcomponents)
Definition: clean.h:1366
static int CountBitLargePolygons(const MeshType &m)
Definition: clean.h:949
static bool HasConsistentPerFaceFauxFlag(const MeshType &m)
Definition: clean.h:1000
static bool HasConsistentPerWedgeTexCoord(MeshType &m)
Definition: clean.h:1800
static std::pair< int, int > RemoveHugeConnectedComponentsDiameter(MeshType &m, ScalarType minDiameter)
Remove the connected components greater than a given diameter.
Definition: clean.h:1974
static bool TestFaceFaceIntersection(FaceType *f0, FaceType *f1)
Definition: clean.h:1838
static void FlipMesh(MeshType &m, bool selected=false)
Flip the orientation of the whole mesh flipping all the faces (by swapping the first two vertices)
Definition: clean.h:1511
static int CountBitQuads(const MeshType &m)
Definition: clean.h:897
static int RemoveDegenerateVertex(MeshType &m)
Definition: clean.h:439
static int CountBitPolygons(const MeshType &m)
Definition: clean.h:926
static bool IsWaterTight(MeshType &m)
Definition: clean.h:1168
static int CountBitTris(const MeshType &m)
Definition: clean.h:912
static int RemoveDuplicateEdge(MeshType &m)
Definition: clean.h:363
static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular)
Definition: clean.h:1394
static int CountNonManifoldEdgeFF(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1058
static int RemoveNonManifoldFace(MeshType &m)
Removal of faces that were incident on a non manifold edge.
Definition: clean.h:768
static int MergeCloseVertex(MeshType &m, const ScalarType radius)
Definition: clean.h:1873
static int CountNonManifoldVertexFF(MeshType &m, bool selectVert=true, bool clearSelection=true)
Definition: clean.h:1110
static bool IsFFAdjacencyConsistent(MeshType &m)
Definition: clean.h:1784
A stack for saving and restoring selection.
Definition: selection.h:43
bool pop(bool orFlag=false, bool andFlag=false)
Definition: selection.h:99
Management, updating and computation of per-vertex and per-face flags (like border flags).
Definition: flag.h:44
static void NormalizePerVertex(ComputeMeshType &m)
Normalize the length of the vertex normals.
Definition: normal.h:239
static void PerVertexAngleWeighted(ComputeMeshType &m)
Calculates the vertex normal as an angle weighted average. It does not need or exploit current face n...
Definition: normal.h:124
static void PerFaceNormalized(ComputeMeshType &m)
Equivalent to PerFace() and NormalizePerFace()
Definition: normal.h:276
static void PerVertexNormalized(ComputeMeshType &m)
Equivalent to PerVertex() and NormalizePerVertex()
Definition: normal.h:269
static void Clear(MeshType &m)
This function clears the selection flag for all the elements of a mesh (vertices, edges,...
Definition: selection.h:271
static size_t VertexClear(MeshType &m)
This function clear the selection flag for all the vertices.
Definition: selection.h:237
static size_t FaceClear(MeshType &m)
This function clears the selection flag for all the faces.
Definition: selection.h:253
static size_t FaceFromVertexLoose(MeshType &m, bool preserveSelection=false)
Select all the faces with at least one selected vertex.
Definition: selection.h:456
Generation of per-vertex and per-face topological information.
Definition: topology.h:43
static void VertexFace(MeshType &m)
Update the Vertex-Face topological relation.
Definition: topology.h:467
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
bool IsManifold(FaceType const &f, const int j)
Definition: topology.h:41
int CountSharedVertex(FaceType *f0, FaceType *f1)
Definition: topology.h:1273
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55
bool CheckOrientation(FaceType &f, int z)
Definition: topology.h:380
bool FindSharedVertex(FaceType *f0, FaceType *f1, int &i, int &j)
Definition: topology.h:1291
void VFStarVF(typename FaceType::VertexType *vp, std::vector< FaceType * > &faceVec, std::vector< int > &indexes)
Compute the set of faces adjacent to a given vertex using VF adjacency.
Definition: topology.h:993
Definition: namespaces.dox:6
P3ScalarType PSDist(const Point3< P3ScalarType > &p, const Point3< P3ScalarType > &v1, const Point3< P3ScalarType > &v2, Point3< P3ScalarType > &q)
Point(p) Edge(v1-v2) dist, q is the point in v1-v2 with min dist.
Definition: point3.h:522