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() ||
480 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
483 if((*fi).V(0) == (*fi).V(1) ||
484 (*fi).V(0) == (*fi).V(2) ||
485 (*fi).V(1) == (*fi).V(2) )
494 static int RemoveDegenerateEdge(MeshType& m)
498 for(EdgeIterator ei=m.edge.begin(); ei!=m.edge.end();++ei)
501 if((*ei).V(0) == (*ei).V(1) )
510 static int RemoveNonManifoldVertex(MeshType& m)
514 int count_removed = 0;
515 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
516 if(!(*fi).IsD() && (*fi).IsS())
518 for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end();++vi)
519 if(!(*vi).IsD() && (*vi).IsS()) {
523 return count_removed;
527 static int SplitSelectedVertexOnEdgeMesh(MeshType& m)
529 tri::RequireCompactness(m);
532 std::unordered_map<size_t,size_t> refCount;
533 size_t countSplit = 0;
534 for (
size_t i=0; i<m.edge.size(); ++i)
536 for (
int j=0; j<2; ++j)
538 const VertexPointer vp = m.edge[i].V(j);
541 const size_t refs = ++refCount[Index(m, m.edge[i].V(j))];
552 for (
size_t i=0; i<m.edge.size(); ++i)
554 for (
int j=0; j<2; ++j)
556 const VertexPointer vp = m.edge[i].V(j);
557 const size_t vIdx = Index(m, vp);
560 if (--refCount[vIdx] > 0)
562 newVertIt->ImportData(*vp);
563 m.edge[i].V(j) = &*(newVertIt++);
569 return int(countSplit);
573 static void SelectNonManifoldVertexOnEdgeMesh(MeshType &m)
575 tri::RequireCompactness(m);
577 std::vector<int> cnt(m.vn,0);
579 for(
size_t i=0;i<m.edge.size();++i)
581 cnt[tri::Index(m,m.edge[i].V(0))]++;
582 cnt[tri::Index(m,m.edge[i].V(1))]++;
584 for(
size_t i=0;i<m.vert.size();++i)
585 if(cnt[i]>2) m.vert[i].SetS();
588 static void SelectCreaseVertexOnEdgeMesh(MeshType &m, ScalarType AngleRadThr)
590 tri::RequireCompactness(m);
591 tri::RequireVEAdjacency(m);
592 tri::UpdateTopology<MeshType>::VertexEdge(m);
594 for(
size_t i=0;i<m.vert.size();++i)
596 std::vector<VertexPointer> VVStarVec;
597 edge::VVStarVE(&(m.vert[i]),VVStarVec);
598 if(VVStarVec.size()==2)
600 CoordType v0 = m.vert[i].P() - VVStarVec[0]->P();
601 CoordType v1 = m.vert[i].P() - VVStarVec[1]->P();
602 float angle = M_PI-vcg::Angle(v0,v1);
603 if(angle > AngleRadThr) m.vert[i].SetS();
618 RequireFFAdjacency(m);
619 typedef std::pair<FacePointer,int> FaceInt;
621 std::vector<std::pair<VertexPointer, std::vector<FaceInt> > >ToSplitVec;
627 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
629 for (
int i=0; i<fi->VN(); i++)
630 if ((*fi).V(i)->IsS() && !(*fi).V(i)->IsV())
633 face::Pos<FaceType> startPos(&*fi,i);
634 face::Pos<FaceType> curPos = startPos;
635 std::set<FaceInt> faceSet;
638 faceSet.insert(std::make_pair(curPos.F(),curPos.VInd()));
641 }
while (curPos != startPos);
643 ToSplitVec.push_back(make_pair((*fi).V(i),std::vector<FaceInt>()));
645 typename std::set<FaceInt>::const_iterator iii;
647 for(iii=faceSet.begin();iii!=faceSet.end();++iii)
648 ToSplitVec.back().second.push_back(*iii);
655 for(
size_t i =0;i<ToSplitVec.size();++i)
658 VertexPointer np=ToSplitVec[i].first;
660 firstVp->ImportData(*np);
662 CoordType delta(0,0,0);
663 for(
size_t j=0;j<ToSplitVec[i].second.size();++j)
665 FaceInt ff=ToSplitVec[i].second[j];
666 ff.first->V(ff.second)=&*firstVp;
667 delta+=Barycenter(*(ff.first))-np->cP();
669 delta /= ToSplitVec[i].second.size();
670 firstVp->P() = firstVp->P() + delta * moveThreshold;
674 return int(ToSplitVec.size());
680 typedef typename MeshType::FacePointer FacePointer;
681 typedef typename MeshType::FaceIterator FaceIterator;
683 RequireFFAdjacency(m);
689 tmpMesh.vert.EnableVFAdjacency();
690 tmpMesh.face.EnableVFAdjacency();
692 if (m.face.IsWedgeTexCoordEnabled())
693 tmpMesh.face.EnableWedgeTexCoord();
697 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
698 if( !(*fi).IsD() && !(*fi).IsV() && !(*fi).IsS())
702 std::deque<FacePointer> visitStack;
703 visitStack.push_back(&*fi);
708 while(!visitStack.empty())
710 FacePointer fp = visitStack.front();
711 visitStack.pop_front();
713 for(
int i=0;i<fp->VN();++i) {
714 FacePointer ff = fp->FFp(i);
720 visitStack.push_back(ff);
731 for (
size_t i = 0; i < size_t(tmpMesh.VN()); ++i)
733 VertexType & v = tmpMesh.vert[i];
737 std::vector<FacePointer> faceVec;
738 std::vector<int> idxVec;
742 CoordType delta(0, 0, 0);
743 for (
auto fp : faceVec)
745 delta += vcg::Barycenter(*fp) - v.cP();
747 delta /= faceVec.size();
749 v.P() += delta * moveThreshold;
761 bool operator ()(FacePointer
const& f1, FacePointer
const& f2)
const {
762 return DoubleArea(*f1) < DoubleArea(*f2);
771 std::vector<FacePointer> ToDelVec;
773 for(fi=m.face.begin(); fi!=m.face.end();++fi)
776 if ((!IsManifold(*fi,0))||
777 (!IsManifold(*fi,1))||
778 (!IsManifold(*fi,2)))
779 ToDelVec.push_back(&*fi);
784 for(
size_t i=0;i<ToDelVec.size();++i)
786 if(!ToDelVec[i]->IsD())
788 FaceType &ff= *ToDelVec[i];
789 if ((!IsManifold(ff,0))||
790 (!IsManifold(ff,1))||
794 if(!face::IsBorder<FaceType>(ff,j))
795 vcg::face::FFDetach<FaceType>(ff,j);
806 static int RemoveFaceOutOfRangeArea(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits<ScalarType>::max)(),
bool OnlyOnSelected=
false)
811 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi){
813 if(!OnlyOnSelected || (*fi).IsS())
815 const ScalarType doubleArea=DoubleArea<FaceType>(*fi);
816 if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) )
826 static int RemoveZeroAreaFace(MeshType& m) {
return RemoveFaceOutOfRangeArea(m,0);}
835 typedef typename MeshType::FaceType F;
836 tri::RequirePerFaceFlags(m);
837 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
838 unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2);
839 if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2)
return false;
845 static bool IsFaceFauxConsistent(MeshType &m)
847 RequirePerFaceFlags(m);
848 RequireFFAdjacency(m);
849 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
851 for(
int z=0;z<(*fi).VN();++z)
853 FacePointer fp = fi->FFp(z);
855 if(fi->IsF(z) != fp->IsF(zp))
return false;
866 tri::RequirePerFaceFlags(m);
867 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) {
868 if ( !fi->IsD() && fi->IsAnyF() )
return false;
873 static bool IsBitPolygonal(
const MeshType &m){
883 tri::RequirePerFaceFlags(m);
884 typedef typename MeshType::FaceType F;
885 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
886 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
887 if ( tmp!=F::FAUX0 && tmp!=F::FAUX1 && tmp!=F::FAUX2 && tmp!=0 )
return false;
898 tri::RequirePerFaceFlags(m);
899 typedef typename MeshType::FaceType F;
901 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
902 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
903 if ( tmp==F::FAUX0 || tmp==F::FAUX1 || tmp==F::FAUX2) count++;
913 tri::RequirePerFaceFlags(m);
915 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
916 if (!(fi->IsAnyF())) count++;
927 tri::RequirePerFaceFlags(m);
929 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
930 if (fi->IsF(0)) count++;
931 if (fi->IsF(1)) count++;
932 if (fi->IsF(2)) count++;
934 return m.fn - count/2;
954 std::unordered_map<ConstVertexPointer, bool> vertVisited;
955 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
956 if (!vi->IsD()) vertVisited[&(*vi)] =
true;
959 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
961 for(
int i=0;i<3;++i){
962 vertVisited[fi->V(i)] =
false;
969 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
977 vertVisited[fi->V0(i)] =
true;
978 vertVisited[fi->V1(i)] =
true;
985 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
986 if (!vi->IsD() && !(vertVisited[&(*vi)])) countV++;
988 return m.fn - countE/2 + countV ;
1001 RequireFFAdjacency(m);
1002 RequirePerFaceFlags(m);
1004 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1006 for (
int k=0; k<3; k++)
1007 if( ( fi->IsF(k) != fi->cFFp(k)->IsF(fi->cFFi(k)) ) ||
1021 MeshAssert<MeshType>::OnlyEdgeMesh(m);
1022 RequireEEAdjacency(m);
1027 int nonManifoldCnt=0;
1028 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1032 for (ei = m.edge.begin(); ei != m.edge.end(); ++ei)
if (!ei->IsD())
1040 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if (!vi->IsD())
1044 if(SelectFlag) (*vi).SetS();
1048 return nonManifoldCnt;
1059 RequireFFAdjacency(m);
1061 nmfBit[0]= FaceType::NewBitFlag();
1062 nmfBit[1]= FaceType::NewBitFlag();
1063 nmfBit[2]= FaceType::NewBitFlag();
1074 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1078 for(
int i=0;i<3;++i)
1079 if(!IsManifold(*fi,i))
1081 if(!(*fi).IsUserBit(nmfBit[i]))
1086 (*fi).V0(i)->SetS();
1087 (*fi).V1(i)->SetS();
1090 face::Pos<FaceType> nmf(&*fi,i);
1093 if(SelectFlag) nmf.F()->SetS();
1094 nmf.F()->SetUserBit(nmfBit[nmf.E()]);
1097 while(nmf.f != &*fi);
1111 RequireFFAdjacency(m);
1114 int nonManifoldCnt=0;
1115 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1119 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1121 for (
int k=0; k<fi->VN(); k++)
1130 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1132 for(
int i=0; i<fi->VN(); ++i)
1133 if (!IsManifold(*fi,i))
1135 (*fi).V0(i)->SetV();
1136 (*fi).V1(i)->SetV();
1141 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1143 for(
int i=0; i<fi->VN(); i++)
if (!(*fi).V(i)->IsV())
1146 face::Pos<FaceType> pos(&(*fi),i);
1148 int starSizeFF = pos.NumberOfIncidentFaces();
1150 if (starSizeFF != TD[(*fi).V(i)])
1158 return nonManifoldCnt;
1169 int edgeNum=0,edgeBorderNum=0,edgeNonManifNum=0;
1170 CountEdgeNum(m, edgeNum, edgeBorderNum,edgeNonManifNum);
1171 return (edgeBorderNum==0) && (edgeNonManifNum==0);
1174 static void CountEdgeNum( MeshType & m,
int &total_e,
int &boundary_e,
int &non_manif_e )
1176 std::vector< typename tri::UpdateTopology<MeshType>::PEdge > edgeVec;
1178 sort(edgeVec.begin(), edgeVec.end());
1183 size_t f_on_cur_edge =1;
1184 for(
size_t i=0;i<edgeVec.size();++i)
1186 if(( (i+1) == edgeVec.size()) || !(edgeVec[i] == edgeVec[i+1]))
1189 if(f_on_cur_edge==1)
1204 static int CountHoles( MeshType & m)
1206 UpdateFlags<MeshType>::FaceClearV(m);
1208 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
if(!fi->IsD())
1210 for(
int j=0;j<3;++j)
1214 face::Pos<FaceType> startPos(&*fi,j);
1215 face::Pos<FaceType> curPos=startPos;
1221 while(curPos!=startPos);
1233 static int CountConnectedComponents(MeshType &m)
1235 std::vector< std::pair<int,FacePointer> > CCV;
1236 return ConnectedComponents(m,CCV);
1239 static int ConnectedComponents(MeshType &m, std::vector< std::pair<int,FacePointer> > &CCV)
1241 tri::RequireFFAdjacency(m);
1243 tri::UpdateFlags<MeshType>::FaceClearV(m);
1244 std::stack<FacePointer> sf;
1245 FacePointer fpt=&*(m.face.begin());
1246 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1248 if(!((*fi).IsD()) && !(*fi).IsV())
1251 CCV.push_back(std::make_pair(0,&*fi));
1258 for(
int j=0; j<fpt->VN(); ++j)
1262 FacePointer l = fpt->FFp(j);
1273 return int(CCV.size());
1276 static int edgeMeshConnectedComponents(MeshType & poly, std::vector<std::pair<int, typename MeshType::EdgePointer> > &eCC)
1278 typedef typename MeshType::EdgePointer EdgePointer;
1279 tri::UpdateTopology<MeshType>::VertexEdge(poly);
1280 tri::UpdateFlags<MeshType>::EdgeClear(poly);
1282 std::stack<EdgePointer> stack;
1284 for (
auto ei = poly.edge.begin(); ei != poly.edge.end(); ++ei)
1285 if (!ei->IsD() && !ei->IsV())
1289 std::pair<int, EdgePointer> cc(1, &*ei);
1292 while (!stack.empty())
1294 EdgePointer ep = stack.top();
1297 for (
int i = 0; i < 2; ++i)
1299 edge::VEIterator<typename MeshType::EdgeType> vei(ep->V(i));
1302 if (!vei.E()->IsV())
1305 stack.push(vei.E());
1314 return int(eCC.size());
1317 static void ComputeValence( MeshType &m,
typename MeshType::PerVertexIntHandle &h)
1319 for(VertexIterator vi=m.vert.begin(); vi!= m.vert.end();++vi)
1322 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1325 for(
int j=0;j<fi->VN();j++)
1326 ++h[tri::Index(m,fi->V(j))];
1365 static int MeshGenus(
int nvert,
int nedges,
int nfaces,
int numholes,
int numcomponents)
1367 return -((nvert + nfaces - nedges + numholes - 2 * numcomponents) / 2);
1374 int boundary_e,total_e,nonmanif_e;
1375 CountEdgeNum(m,total_e,boundary_e,nonmanif_e);
1376 int numholes=CountHoles(m);
1377 int numcomponents=CountConnectedComponents(m);
1378 int G=
MeshGenus(nvert,total_e,nfaces,numholes,numcomponents);
1395 RequireVFAdjacency(m);
1401 for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1405 face::Pos<FaceType> he((*vi).VFp(), &*vi);
1406 face::Pos<FaceType> ht = he;
1422 if ((n != 6)&&(!border && n != 4))
1431 Semiregular =
false;
1435 Semiregular =
false;
1440 static bool IsCoherentlyOrientedMesh(MeshType &m)
1442 RequireFFAdjacency(m);
1443 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1444 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1446 for(
int i=0;i<3;++i)
1453 static void OrientCoherentlyMesh(MeshType &m,
bool &_IsOriented,
bool &_IsOrientable)
1455 RequireFFAdjacency(m);
1456 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1457 bool IsOrientable =
true;
1458 bool IsOriented =
true;
1460 UpdateFlags<MeshType>::FaceClearV(m);
1461 std::stack<FacePointer> faces;
1462 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1464 if (!fi->IsD() && !fi->IsV())
1469 while (!faces.empty())
1471 FacePointer fp = faces.top();
1475 for (
int j = 0; j < 3; j++)
1477 if (!
face::IsBorder(*fp,j) && face::IsManifold<FaceType>(*fp, j))
1479 FacePointer fpaux = fp->FFp(j);
1480 int iaux = fp->FFi(j);
1481 if (!CheckOrientation(*fpaux, iaux))
1486 face::SwapEdge<FaceType,true>(*fpaux, iaux);
1489 IsOrientable =
false;
1502 if (!IsOrientable)
break;
1504 _IsOriented = IsOriented;
1505 _IsOrientable = IsOrientable;
1512 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD())
1513 if(!selected || (*fi).IsS())
1515 face::SwapEdge<FaceType,false>((*fi), 0);
1516 if (HasPerWedgeTexCoord(m))
1517 std::swap((*fi).WT(0),(*fi).WT(1));
1527 if(m.vert.empty())
return false;
1532 std::vector< VertexPointer > minVertVec;
1533 std::vector< VertexPointer > maxVertVec;
1536 std::vector< CoordType > dirVec;
1537 dirVec.push_back(CoordType(1,0,0));
1538 dirVec.push_back(CoordType(0,1,0));
1539 dirVec.push_back(CoordType(0,0,1));
1540 dirVec.push_back(CoordType( 1, 1,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 for(
size_t i=0;i<dirVec.size();++i)
1546 Normalize(dirVec[i]);
1547 minVertVec.push_back(&*m.vert.begin());
1548 maxVertVec.push_back(&*m.vert.begin());
1550 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if(!(*vi).IsD())
1552 for(
size_t i=0;i<dirVec.size();++i)
1554 if( (*vi).cP().dot(dirVec[i]) < minVertVec[i]->P().dot(dirVec[i])) minVertVec[i] = &*vi;
1555 if( (*vi).cP().dot(dirVec[i]) > maxVertVec[i]->P().dot(dirVec[i])) maxVertVec[i] = &*vi;
1560 ScalarType angleThreshold = cos(math::ToRad(85.0));
1561 for(
size_t i=0;i<dirVec.size();++i)
1565 if(minVertVec[i]->N().dot(dirVec[i]) > angleThreshold ) voteCount++;
1566 if(maxVertVec[i]->N().dot(dirVec[i]) < -angleThreshold ) voteCount++;
1569 if(voteCount <
int(dirVec.size())/2)
return false;
1577 static int RemoveFaceFoldByFlip(MeshType &m,
float normalThresholdDeg=175,
bool repeat=
true)
1579 RequireFFAdjacency(m);
1580 RequirePerVertexMark(m);
1582 int count, total = 0;
1589 ScalarType NormalThrRad = math::ToRad(normalThresholdDeg);
1590 ScalarType eps = ScalarType(0.0001);
1592 for(FaceIterator fi=m.face.begin();fi!= m.face.end();++fi )
if(!(*fi).IsV())
1594 if( vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(0)).Normalize()) > NormalThrRad &&
1595 vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(1)).Normalize()) > NormalThrRad &&
1596 vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(2)).Normalize()) > NormalThrRad )
1601 for(
int i=0;i<3;i++)
1605 bool ret = vcg::InterpolationParameters((*(*fi).FFp(i)),TriangleNormal(*(*fi).FFp(i)),p,L);
1606 if(ret && L[0]>eps && L[1]>eps && L[2]>eps)
1608 (*fi).FFp(i)->SetS();
1609 (*fi).FFp(i)->SetV();
1611 if(face::CheckFlipEdge<FaceType>( *fi, i )) {
1612 face::FlipEdge<FaceType>( *fi, i );
1622 while( repeat && count );
1627 static int RemoveTVertexByFlip(MeshType &m,
float threshold=40,
bool repeat=
true)
1629 RequireFFAdjacency(m);
1630 RequirePerVertexMark(m);
1632 int count, total = 0;
1640 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1642 FacePointer f = &(m.face[index]);
float sides[3]; CoordType dummy;
1643 sides[0] = Distance(f->P(0), f->P(1));
1644 sides[1] = Distance(f->P(1), f->P(2));
1645 sides[2] = Distance(f->P(2), f->P(0));
1647 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1648 if( tri::IsMarked(m,f->V2(i) ))
continue;
1650 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1652 tri::Mark(m,f->V2(i));
1653 if(face::CheckFlipEdge<FaceType>( *f, i )) {
1655 FacePointer g = f->FFp(i);
int k = f->FFi(i);
1656 Triangle3<ScalarType> t1(f->P(i), f->P1(i), f->P2(i)), t2(g->P(k), g->P1(k), g->P2(k)),
1657 t3(f->P(i), g->P2(k), f->P2(i)), t4(g->P(k), f->P2(i), g->P2(k));
1659 if ( std::min( QualityFace(t1), QualityFace(t2) ) < std::min( QualityFace(t3), QualityFace(t4) ))
1661 face::FlipEdge<FaceType>( *f, i );
1671 while( repeat && count );
1675 static int RemoveTVertexByCollapse(MeshType &m,
float threshold=40,
bool repeat=
true)
1677 RequirePerVertexMark(m);
1679 int count, total = 0;
1686 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1688 FacePointer f = &(m.face[index]);
1692 sides[0] = Distance(f->P(0), f->P(1));
1693 sides[1] = Distance(f->P(1), f->P(2));
1694 sides[2] = Distance(f->P(2), f->P(0));
1695 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1696 if( tri::IsMarked(m,f->V2(i) ))
continue;
1698 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1700 tri::Mark(m,f->V2(i));
1702 int j = Distance(dummy,f->P(i))<Distance(dummy,f->P1(i))?i:(i+1)%3;
1703 f->P2(i) = f->P(j); tri::Mark(m,f->V(j));
1713 while( repeat && count );
1718 static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret)
1720 RequirePerFaceMark(m);
1722 int referredBit = FaceType::NewBitFlag();
1723 tri::UpdateFlags<MeshType>::FaceClear(m,referredBit);
1726 gM.Set(m.face.begin(),m.face.end());
1728 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
1730 (*fi).SetUserBit(referredBit);
1731 Box3< ScalarType> bbox;
1732 (*fi).GetBBox(bbox);
1733 std::vector<FaceType*> inBox;
1734 vcg::tri::GetInBoxFace(m, gM, bbox,inBox);
1735 bool Intersected=
false;
1736 typename std::vector<FaceType*>::iterator fib;
1737 for(fib=inBox.begin();fib!=inBox.end();++fib)
1739 if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) )
1741 ret.push_back(*fib);
1743 ret.push_back(&*fi);
1751 FaceType::DeleteBitFlag(referredBit);
1752 return (ret.size()>0);
1760 int DeletedVertNum=0;
1761 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1762 if((*vi).IsD()) DeletedVertNum++;
1764 int DeletedEdgeNum=0;
1765 for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
1766 if((*ei).IsD()) DeletedEdgeNum++;
1768 int DeletedFaceNum=0;
1769 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1770 if((*fi).IsD()) DeletedFaceNum++;
1772 if(
size_t(m.vn+DeletedVertNum) != m.vert.size())
return false;
1773 if(
size_t(m.en+DeletedEdgeNum) != m.edge.size())
return false;
1774 if(
size_t(m.fn+DeletedFaceNum) != m.face.size())
return false;
1785 RequireFFAdjacency(m);
1787 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1790 for(
int i=0;i<3;++i)
1791 if(!FFCorrectness(*fi, i))
return false;
1801 tri::RequirePerFaceWedgeTexCoord(m);
1803 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1805 { FaceType &f=(*fi);
1806 if( ! ( (f.WT(0).N() == f.WT(1).N()) && (f.WT(0).N() == (*fi).WT(2).N()) ) )
1809 if((*fi).WT(0).N() <0)
return false;
1819 tri::RequirePerFaceWedgeTexCoord(m);
1821 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1824 if( (*fi).WT(0).P() == (*fi).WT(1).P() && (*fi).WT(0).P() == (*fi).WT(2).P() )
return false;
1840 if(sv==3)
return true;
1841 if(sv==0)
return (vcg::IntersectionTriangleTriangle<FaceType>((*f0),(*f1)));
1847 int i0,i1; ScalarType a,b;
1849 CoordType shP = f0->V(i0)->P()*0.5;
1850 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) )
1853 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
1856 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) )
1859 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
1875 mergedCnt = ClusterVertex(m,radius);
1880 static int ClusterVertex(MeshType &m,
const ScalarType radius)
1882 if(m.vn==0)
return 0;
1885 typedef vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT;
1887 tri::EmptyTMark<MeshType> markerFunctor;
1888 std::vector<VertexType*> closests;
1890 sht.Set(m.vert.begin(), m.vert.end());
1892 for(VertexIterator viv = m.vert.begin(); viv!= m.vert.end(); ++viv)
1893 if(!(*viv).IsD() && !(*viv).IsV())
1898 GridGetInBox(sht, markerFunctor, bb, closests);
1900 for(
size_t i=0; i<closests.size(); ++i)
1902 ScalarType dist = Distance(p,closests[i]->cP());
1903 if(dist < radius && !closests[i]->IsV())
1907 closests[i]->SetV();
1916 static std::pair<int,int> RemoveSmallConnectedComponentsSize(MeshType &m,
int maxCCSize)
1918 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1919 int TotalCC=ConnectedComponents(m, CCV);
1922 ConnectedComponentIterator<MeshType> ci;
1923 for(
unsigned int i=0;i<CCV.size();++i)
1925 std::vector<typename MeshType::FacePointer> FPV;
1926 if(CCV[i].first<maxCCSize)
1929 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1932 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
1933 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
1937 return std::make_pair(TotalCC,DeletedCC);
1945 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1946 int TotalCC=ConnectedComponents(m, CCV);
1949 for(
unsigned int i=0;i<CCV.size();++i)
1952 std::vector<typename MeshType::FacePointer> FPV;
1953 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1956 bb.
Add((*ci)->P(0));
1957 bb.
Add((*ci)->P(1));
1958 bb.
Add((*ci)->P(2));
1960 if(bb.
Diag()<maxDiameter)
1963 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
1964 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
1968 return std::make_pair(TotalCC,DeletedCC);
1975 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1976 int TotalCC=ConnectedComponents(m, CCV);
1979 for(
unsigned int i=0;i<CCV.size();++i)
1982 std::vector<typename MeshType::FacePointer> FPV;
1983 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1986 bb.
Add((*ci)->P(0));
1987 bb.
Add((*ci)->P(1));
1988 bb.
Add((*ci)->P(2));
1990 if(bb.
Diag()>minDiameter)
1993 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
1994 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
1998 return std::make_pair(TotalCC,DeletedCC);
2011 typedef std::unordered_set<VertexPointer> VertexSet;
2012 tri::RequireVFAdjacency(m);
2013 tri::RequirePerFaceNormal(m);
2014 tri::RequirePerVertexNormal(m);
2019 if (cosThreshold > 0)
2022 #pragma omp parallel for schedule(dynamic, 10)
2023 for (
int i = 0; i < m.face.size(); i++)
2025 VertexSet nearVertex;
2026 std::vector<CoordType> pointVec;
2027 FacePointer f = &m.face[i];
2028 for (
int j = 0; j < 3; j++)
2030 std::vector<VertexPointer> temp;
2031 vcg::face::VVStarVF<FaceType>(f->V(j), temp);
2032 typename std::vector<VertexPointer>::iterator iter = temp.begin();
2033 for (; iter != temp.end(); iter++)
2035 if ((*iter) != f->V1(j) && (*iter) != f->V2(j))
2037 if (nearVertex.insert((*iter)).second)
2038 pointVec.push_back((*iter)->P());
2041 nearVertex.insert(f->V(j));
2042 pointVec.push_back(f->P(j));
2045 if (pointVec.size() > 3)
2047 vcg::Plane3<ScalarType> plane;
2048 vcg::FitPlaneToPointSet(pointVec, plane);
2050 for (
auto nvp : nearVertex)
2051 avgDot += plane.Direction().dot(nvp->N());
2052 avgDot /= nearVertex.size();
2053 typename MeshType::VertexType::NormalType normal;
2055 normal = -plane.Direction();
2057 normal = plane.Direction();
2058 if (normal.dot(f->N()) < cosThreshold)
2069 RequirePerFaceMark(m2);
2070 RequireCompactness(m1);
2071 RequireCompactness(m2);
2076 gM.Set(m2.face.begin(),m2.face.end());
2078 for(
auto fi=m1.face.begin();fi!=m1.face.end();++fi)
2081 (*fi).GetBBox(bbox);
2082 std::vector<FaceType*> inBox;
2083 vcg::tri::GetInBoxFace(m2, gM, bbox,inBox);
2084 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:476
static int RemoveDuplicateFace(MeshType &m)
Definition: clean.h:334
static void SelectFoldedFaceFromOneRingFaces(MeshType &m, ScalarType cosThreshold)
Definition: clean.h:2009
static bool FlipNormalOutside(MeshType &m)
Definition: clean.h:1525
static int RemoveDuplicateVertex(MeshType &m, bool RemoveDegenerateFlag=true)
Definition: clean.h:206
static bool IsSizeConsistent(MeshType &m)
Definition: clean.h:1758
static int SelectIntersectingFaces(MeshType &m1, MeshType &m2)
Definition: clean.h:2067
static bool IsBitTriQuadOnly(const MeshType &m)
Definition: clean.h:881
static bool IsBitTriOnly(const MeshType &m)
Definition: clean.h:864
static bool HasZeroTexCoordFace(MeshType &m)
Definition: clean.h:1817
static std::pair< int, int > RemoveSmallConnectedComponentsDiameter(MeshType &m, ScalarType maxDiameter)
Remove the connected components smaller than a given diameter.
Definition: clean.h:1943
static size_t SplitManifoldComponents(MeshType &m, const ScalarType moveThreshold=0)
This function expand current selection to cover the whole connected component.
Definition: clean.h:678
static bool IsBitQuadOnly(const MeshType &m)
Definition: clean.h:833
static int CountNonManifoldEdgeEE(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1019
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:616
static int MeshGenus(int nvert, int nedges, int nfaces, int numholes, int numcomponents)
Definition: clean.h:1365
static int CountBitLargePolygons(const MeshType &m)
Definition: clean.h:948
static bool HasConsistentPerFaceFauxFlag(const MeshType &m)
Definition: clean.h:999
static bool HasConsistentPerWedgeTexCoord(MeshType &m)
Definition: clean.h:1799
static std::pair< int, int > RemoveHugeConnectedComponentsDiameter(MeshType &m, ScalarType minDiameter)
Remove the connected components greater than a given diameter.
Definition: clean.h:1973
static bool TestFaceFaceIntersection(FaceType *f0, FaceType *f1)
Definition: clean.h:1837
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:1510
static int CountBitQuads(const MeshType &m)
Definition: clean.h:896
static int RemoveDegenerateVertex(MeshType &m)
Definition: clean.h:439
static int CountBitPolygons(const MeshType &m)
Definition: clean.h:925
static bool IsWaterTight(MeshType &m)
Definition: clean.h:1167
static int CountBitTris(const MeshType &m)
Definition: clean.h:911
static int RemoveDuplicateEdge(MeshType &m)
Definition: clean.h:363
static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular)
Definition: clean.h:1393
static int CountNonManifoldEdgeFF(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1057
static int RemoveNonManifoldFace(MeshType &m)
Removal of faces that were incident on a non manifold edge.
Definition: clean.h:767
static int MergeCloseVertex(MeshType &m, const ScalarType radius)
Definition: clean.h:1872
static int CountNonManifoldVertexFF(MeshType &m, bool selectVert=true, bool clearSelection=true)
Definition: clean.h:1109
static bool IsFFAdjacencyConsistent(MeshType &m)
Definition: clean.h:1783
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:469
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:397
bool IsManifold(FaceType const &f, const int j)
Definition: topology.h:41
int CountSharedVertex(FaceType *f0, FaceType *f1)
Definition: topology.h:1261
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55
bool CheckOrientation(FaceType &f, int z)
Definition: topology.h:383
bool FindSharedVertex(FaceType *f0, FaceType *f1, int &i, int &j)
Definition: topology.h:1279
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:981
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