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>
41template <
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;
103template <
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;
163template <
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]) )
450 if (DeleteVertexFlag)
457 for(fi=m.face.begin(); fi!=m.face.end();++fi)
459 if( (*fi).V(0)->IsD() ||
464 if (DeleteVertexFlag)
483 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
486 if((*fi).V(0) == (*fi).V(1) ||
487 (*fi).V(0) == (*fi).V(2) ||
488 (*fi).V(1) == (*fi).V(2) )
498 static int RemoveDegenerateEdge(MeshType& m,
bool DeleteEdgesFlag=
true)
502 for(EdgeIterator ei=m.edge.begin(); ei!=m.edge.end();++ei)
505 if((*ei).V(0) == (*ei).V(1) )
515 static int RemoveNonManifoldVertex(MeshType& m)
519 int count_removed = 0;
520 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
521 if(!(*fi).IsD() && (*fi).IsS())
523 for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end();++vi)
524 if(!(*vi).IsD() && (*vi).IsS()) {
528 return count_removed;
532 static int SplitSelectedVertexOnEdgeMesh(MeshType& m)
534 tri::RequireCompactness(m);
537 std::unordered_map<size_t,size_t> refCount;
538 size_t countSplit = 0;
539 for (
size_t i=0; i<m.edge.size(); ++i)
541 for (
int j=0; j<2; ++j)
543 const VertexPointer vp = m.edge[i].V(j);
546 const size_t refs = ++refCount[Index(m, m.edge[i].V(j))];
557 for (
size_t i=0; i<m.edge.size(); ++i)
559 for (
int j=0; j<2; ++j)
561 const VertexPointer vp = m.edge[i].V(j);
562 const size_t vIdx = Index(m, vp);
565 if (--refCount[vIdx] > 0)
567 newVertIt->ImportData(*vp);
568 m.edge[i].V(j) = &*(newVertIt++);
574 return int(countSplit);
578 static void SelectNonManifoldVertexOnEdgeMesh(MeshType &m)
580 tri::RequireCompactness(m);
582 std::vector<int> cnt(m.vn,0);
584 for(
size_t i=0;i<m.edge.size();++i)
586 cnt[tri::Index(m,m.edge[i].V(0))]++;
587 cnt[tri::Index(m,m.edge[i].V(1))]++;
589 for(
size_t i=0;i<m.vert.size();++i)
590 if(cnt[i]>2) m.vert[i].SetS();
597 tri::RequireCompactness(m);
598 tri::RequireEEAdjacency(m);
602 for(
size_t i=0;i<m.edge.size();++i)
606 if(! m.edge[i].V(j)->IsV())
608 const CoordType ¢erV = m.edge[i].V(j)->cP();
609 m.edge[i].V(j)->SetV();
610 std::vector<VertexPointer> VVStarVec;
611 edge::VVStarEE(&(m.edge[i]),j,VVStarVec);
612 if(VVStarVec.size()==2)
614 CoordType v0 = centerV - VVStarVec[0]->P();
615 CoordType v1 = VVStarVec[1]->P() - centerV;
616 if(vcg::Angle(v0,v1) > AngleRadThr)
617 m.edge[i].V(j)->SetS();
627 tri::RequireCompactness(m);
628 tri::RequireVEAdjacency(m);
631 for(
size_t i=0;i<m.vert.size();++i)
633 std::vector<VertexPointer> VVStarVec;
634 edge::VVStarVE(&(m.vert[i]),VVStarVec);
635 if(VVStarVec.size()==2)
637 CoordType v0 = m.vert[i].P() - VVStarVec[0]->P();
638 CoordType v1 = m.vert[i].P() - VVStarVec[1]->P();
639 float angle = M_PI-vcg::Angle(v0,v1);
640 if(angle > AngleRadThr) m.vert[i].SetS();
654 RequireFFAdjacency(m);
655 typedef std::pair<FacePointer,int> FaceInt;
657 std::vector<std::pair<VertexPointer, std::vector<FaceInt> > >ToSplitVec;
663 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
665 for (
int i=0; i<fi->VN(); i++)
666 if ((*fi).V(i)->IsS() && !(*fi).V(i)->IsV())
669 face::Pos<FaceType> startPos(&*fi,i);
670 face::Pos<FaceType> curPos = startPos;
671 std::set<FaceInt> faceSet;
674 faceSet.insert(std::make_pair(curPos.F(),curPos.VInd()));
677 }
while (curPos != startPos);
679 ToSplitVec.push_back(make_pair((*fi).V(i),std::vector<FaceInt>()));
681 typename std::set<FaceInt>::const_iterator iii;
683 for(iii=faceSet.begin();iii!=faceSet.end();++iii)
684 ToSplitVec.back().second.push_back(*iii);
691 for(
size_t i =0;i<ToSplitVec.size();++i)
694 VertexPointer np=ToSplitVec[i].first;
696 firstVp->ImportData(*np);
698 CoordType delta(0,0,0);
699 for(
size_t j=0;j<ToSplitVec[i].second.size();++j)
701 FaceInt ff=ToSplitVec[i].second[j];
702 ff.first->V(ff.second)=&*firstVp;
703 delta+=Barycenter(*(ff.first))-np->cP();
705 delta /= ToSplitVec[i].second.size();
706 firstVp->P() = firstVp->P() + delta * moveThreshold;
710 return int(ToSplitVec.size());
716 typedef typename MeshType::FacePointer FacePointer;
717 typedef typename MeshType::FaceIterator FaceIterator;
719 RequireFFAdjacency(m);
725 tmpMesh.vert.EnableVFAdjacency();
726 tmpMesh.face.EnableVFAdjacency();
728 if (m.face.IsWedgeTexCoordEnabled())
729 tmpMesh.face.EnableWedgeTexCoord();
733 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
734 if( !(*fi).IsD() && !(*fi).IsV() && !(*fi).IsS())
738 std::deque<FacePointer> visitStack;
739 visitStack.push_back(&*fi);
744 while(!visitStack.empty())
746 FacePointer fp = visitStack.front();
747 visitStack.pop_front();
749 for(
int i=0;i<fp->VN();++i) {
750 FacePointer ff = fp->FFp(i);
756 visitStack.push_back(ff);
767 for (
size_t i = 0; i < size_t(tmpMesh.VN()); ++i)
769 VertexType & v = tmpMesh.vert[i];
773 std::vector<FacePointer> faceVec;
774 std::vector<int> idxVec;
778 CoordType delta(0, 0, 0);
779 for (
auto fp : faceVec)
781 delta += vcg::Barycenter(*fp) - v.cP();
783 delta /= faceVec.size();
785 v.P() += delta * moveThreshold;
797 bool operator ()(FacePointer
const& f1, FacePointer
const& f2)
const {
798 return DoubleArea(*f1) < DoubleArea(*f2);
807 std::vector<FacePointer> ToDelVec;
809 for(fi=m.face.begin(); fi!=m.face.end();++fi)
812 if ((!IsManifold(*fi,0))||
813 (!IsManifold(*fi,1))||
814 (!IsManifold(*fi,2)))
815 ToDelVec.push_back(&*fi);
818 if (!DeleteFacesFlag)
819 return ToDelVec.size();
823 for(
size_t i=0;i<ToDelVec.size();++i)
825 if(!ToDelVec[i]->IsD())
827 FaceType &ff= *ToDelVec[i];
828 if ((!IsManifold(ff,0))||
829 (!IsManifold(ff,1))||
833 if(!face::IsBorder<FaceType>(ff,j))
834 vcg::face::FFDetach<FaceType>(ff,j);
845 static int RemoveFaceOutOfRangeArea(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits<ScalarType>::max)(),
bool OnlyOnSelected=
false,
bool DeleteFacesFlag=
true)
850 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi){
852 if(!OnlyOnSelected || (*fi).IsS())
854 const ScalarType doubleArea=DoubleArea<FaceType>(*fi);
855 if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) )
866 static int RemoveZeroAreaFace(MeshType& m,
bool DeleteFacesFlag=
true) {
return RemoveFaceOutOfRangeArea(m,0, (std::numeric_limits<ScalarType>::max)(),
false, DeleteFacesFlag); }
875 typedef typename MeshType::FaceType F;
876 tri::RequirePerFaceFlags(m);
877 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
878 unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2);
879 if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2)
return false;
885 static bool IsFaceFauxConsistent(MeshType &m)
887 RequirePerFaceFlags(m);
888 RequireFFAdjacency(m);
889 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
891 for(
int z=0;z<(*fi).VN();++z)
893 FacePointer fp = fi->FFp(z);
895 if(fi->IsF(z) != fp->IsF(zp))
return false;
906 tri::RequirePerFaceFlags(m);
907 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) {
908 if ( !fi->IsD() && fi->IsAnyF() )
return false;
913 static bool IsBitPolygonal(
const MeshType &m){
923 tri::RequirePerFaceFlags(m);
924 typedef typename MeshType::FaceType F;
925 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
926 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
927 if ( tmp!=F::FAUX0 && tmp!=F::FAUX1 && tmp!=F::FAUX2 && tmp!=0 )
return false;
938 tri::RequirePerFaceFlags(m);
939 typedef typename MeshType::FaceType F;
941 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
942 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
943 if ( tmp==F::FAUX0 || tmp==F::FAUX1 || tmp==F::FAUX2) count++;
953 tri::RequirePerFaceFlags(m);
955 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
956 if (!(fi->IsAnyF())) count++;
967 tri::RequirePerFaceFlags(m);
969 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
970 if (fi->IsF(0)) count++;
971 if (fi->IsF(1)) count++;
972 if (fi->IsF(2)) count++;
974 return m.fn - count/2;
994 std::unordered_map<ConstVertexPointer, bool> vertVisited;
995 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
996 if (!vi->IsD()) vertVisited[&(*vi)] =
true;
999 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1001 for(
int i=0;i<3;++i){
1002 vertVisited[fi->V(i)] =
false;
1009 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1011 for(
int i=0;i<3;++i)
1017 vertVisited[fi->V0(i)] =
true;
1018 vertVisited[fi->V1(i)] =
true;
1025 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1026 if (!vi->IsD() && !(vertVisited[&(*vi)])) countV++;
1028 return m.fn - countE/2 + countV ;
1041 RequireFFAdjacency(m);
1042 RequirePerFaceFlags(m);
1044 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1046 for (
int k=0; k<3; k++)
1047 if( ( fi->IsF(k) != fi->cFFp(k)->IsF(fi->cFFi(k)) ) ||
1061 MeshAssert<MeshType>::OnlyEdgeMesh(m);
1062 RequireEEAdjacency(m);
1067 int nonManifoldCnt=0;
1068 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1072 for (ei = m.edge.begin(); ei != m.edge.end(); ++ei)
if (!ei->IsD())
1080 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if (!vi->IsD())
1084 if(SelectFlag) (*vi).SetS();
1088 return nonManifoldCnt;
1099 RequireFFAdjacency(m);
1101 nmfBit[0]= FaceType::NewBitFlag();
1102 nmfBit[1]= FaceType::NewBitFlag();
1103 nmfBit[2]= FaceType::NewBitFlag();
1114 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1118 for(
int i=0;i<3;++i)
1119 if(!IsManifold(*fi,i))
1121 if(!(*fi).IsUserBit(nmfBit[i]))
1126 (*fi).V0(i)->SetS();
1127 (*fi).V1(i)->SetS();
1130 face::Pos<FaceType> nmf(&*fi,i);
1133 if(SelectFlag) nmf.F()->SetS();
1134 nmf.F()->SetUserBit(nmfBit[nmf.E()]);
1137 while(nmf.f != &*fi);
1151 RequireFFAdjacency(m);
1154 int nonManifoldCnt=0;
1155 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1159 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1161 for (
int k=0; k<fi->VN(); k++)
1170 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1172 for(
int i=0; i<fi->VN(); ++i)
1173 if (!IsManifold(*fi,i))
1175 (*fi).V0(i)->SetV();
1176 (*fi).V1(i)->SetV();
1181 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1183 for(
int i=0; i<fi->VN(); i++)
if (!(*fi).V(i)->IsV())
1186 face::Pos<FaceType> pos(&(*fi),i);
1188 int starSizeFF = pos.NumberOfIncidentFaces();
1190 if (starSizeFF != TD[(*fi).V(i)])
1198 return nonManifoldCnt;
1209 int edgeNum=0,edgeBorderNum=0,edgeNonManifNum=0;
1210 CountEdgeNum(m, edgeNum, edgeBorderNum,edgeNonManifNum);
1211 return (edgeBorderNum==0) && (edgeNonManifNum==0);
1214 static void CountEdgeNum( MeshType & m,
int &total_e,
int &boundary_e,
int &non_manif_e )
1216 std::vector< typename tri::UpdateTopology<MeshType>::PEdge > edgeVec;
1218 sort(edgeVec.begin(), edgeVec.end());
1223 size_t f_on_cur_edge =1;
1224 for(
size_t i=0;i<edgeVec.size();++i)
1226 if(( (i+1) == edgeVec.size()) || !(edgeVec[i] == edgeVec[i+1]))
1229 if(f_on_cur_edge==1)
1244 static int CountHoles( MeshType & m)
1246 UpdateFlags<MeshType>::FaceClearV(m);
1248 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
if(!fi->IsD())
1250 for(
int j=0;j<3;++j)
1254 face::Pos<FaceType> startPos(&*fi,j);
1255 face::Pos<FaceType> curPos=startPos;
1261 while(curPos!=startPos);
1273 static int CountConnectedComponents(MeshType &m)
1275 std::vector< std::pair<int,FacePointer> > CCV;
1276 return ConnectedComponents(m,CCV);
1279 static int ConnectedComponents(MeshType &m, std::vector< std::pair<int,FacePointer> > &CCV)
1281 tri::RequireFFAdjacency(m);
1283 tri::UpdateFlags<MeshType>::FaceClearV(m);
1284 std::stack<FacePointer> sf;
1285 FacePointer fpt=&*(m.face.begin());
1286 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1288 if(!((*fi).IsD()) && !(*fi).IsV())
1291 CCV.push_back(std::make_pair(0,&*fi));
1298 for(
int j=0; j<fpt->VN(); ++j)
1302 FacePointer l = fpt->FFp(j);
1313 return int(CCV.size());
1316 static int edgeMeshConnectedComponents(MeshType & poly, std::vector<std::pair<int, typename MeshType::EdgePointer> > &eCC)
1318 typedef typename MeshType::EdgePointer EdgePointer;
1319 tri::UpdateTopology<MeshType>::VertexEdge(poly);
1320 tri::UpdateFlags<MeshType>::EdgeClear(poly);
1322 std::stack<EdgePointer> stack;
1324 for (
auto ei = poly.edge.begin(); ei != poly.edge.end(); ++ei)
1325 if (!ei->IsD() && !ei->IsV())
1329 std::pair<int, EdgePointer> cc(1, &*ei);
1332 while (!stack.empty())
1334 EdgePointer ep = stack.top();
1337 for (
int i = 0; i < 2; ++i)
1339 edge::VEIterator<typename MeshType::EdgeType> vei(ep->V(i));
1342 if (!vei.E()->IsV())
1345 stack.push(vei.E());
1354 return int(eCC.size());
1357 static void ComputeValence( MeshType &m,
typename MeshType::PerVertexIntHandle &h)
1359 for(VertexIterator vi=m.vert.begin(); vi!= m.vert.end();++vi)
1362 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1365 for(
int j=0;j<fi->VN();j++)
1366 ++h[tri::Index(m,fi->V(j))];
1405 static int MeshGenus(
int nvert,
int nedges,
int nfaces,
int numholes,
int numcomponents)
1407 return -((nvert + nfaces - nedges + numholes - 2 * numcomponents) / 2);
1414 int boundary_e,total_e,nonmanif_e;
1415 CountEdgeNum(m,total_e,boundary_e,nonmanif_e);
1416 int numholes=CountHoles(m);
1417 int numcomponents=CountConnectedComponents(m);
1418 int G=
MeshGenus(nvert,total_e,nfaces,numholes,numcomponents);
1435 RequireVFAdjacency(m);
1441 for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1445 face::Pos<FaceType> he((*vi).VFp(), &*vi);
1446 face::Pos<FaceType> ht = he;
1462 if ((n != 6)&&(!border && n != 4))
1471 Semiregular =
false;
1475 Semiregular =
false;
1480 static bool IsCoherentlyOrientedMesh(MeshType &m)
1482 RequireFFAdjacency(m);
1483 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1484 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1486 for(
int i=0;i<3;++i)
1493 static void OrientCoherentlyMesh(MeshType &m,
bool &_IsOriented,
bool &_IsOrientable)
1495 RequireFFAdjacency(m);
1496 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1497 bool IsOrientable =
true;
1498 bool IsOriented =
true;
1500 UpdateFlags<MeshType>::FaceClearV(m);
1501 std::stack<FacePointer> faces;
1502 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1504 if (!fi->IsD() && !fi->IsV())
1509 while (!faces.empty())
1511 FacePointer fp = faces.top();
1515 for (
int j = 0; j < 3; j++)
1517 if (!
face::IsBorder(*fp,j) && face::IsManifold<FaceType>(*fp, j))
1519 FacePointer fpaux = fp->FFp(j);
1520 int iaux = fp->FFi(j);
1521 if (!CheckOrientation(*fpaux, iaux))
1526 face::SwapEdge<FaceType,true>(*fpaux, iaux);
1529 IsOrientable =
false;
1542 if (!IsOrientable)
break;
1544 _IsOriented = IsOriented;
1545 _IsOrientable = IsOrientable;
1552 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD())
1553 if(!selected || (*fi).IsS())
1555 face::SwapEdge<FaceType,false>((*fi), 0);
1556 if (HasPerWedgeTexCoord(m))
1557 std::swap((*fi).WT(0),(*fi).WT(1));
1567 if(m.vert.empty())
return false;
1572 std::vector< VertexPointer > minVertVec;
1573 std::vector< VertexPointer > maxVertVec;
1576 std::vector< CoordType > dirVec;
1577 dirVec.push_back(CoordType(1,0,0));
1578 dirVec.push_back(CoordType(0,1,0));
1579 dirVec.push_back(CoordType(0,0,1));
1580 dirVec.push_back(CoordType( 1, 1,1));
1581 dirVec.push_back(CoordType(-1, 1,1));
1582 dirVec.push_back(CoordType(-1,-1,1));
1583 dirVec.push_back(CoordType( 1,-1,1));
1584 for(
size_t i=0;i<dirVec.size();++i)
1586 Normalize(dirVec[i]);
1587 minVertVec.push_back(&*m.vert.begin());
1588 maxVertVec.push_back(&*m.vert.begin());
1590 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if(!(*vi).IsD())
1592 for(
size_t i=0;i<dirVec.size();++i)
1594 if( (*vi).cP().dot(dirVec[i]) < minVertVec[i]->P().dot(dirVec[i])) minVertVec[i] = &*vi;
1595 if( (*vi).cP().dot(dirVec[i]) > maxVertVec[i]->P().dot(dirVec[i])) maxVertVec[i] = &*vi;
1600 ScalarType angleThreshold = cos(math::ToRad(85.0));
1601 for(
size_t i=0;i<dirVec.size();++i)
1605 if(minVertVec[i]->N().dot(dirVec[i]) > angleThreshold ) voteCount++;
1606 if(maxVertVec[i]->N().dot(dirVec[i]) < -angleThreshold ) voteCount++;
1609 if(voteCount <
int(dirVec.size())/2)
return false;
1617 static int RemoveFaceFoldByFlip(MeshType &m,
float normalThresholdDeg=175,
bool repeat=
true)
1619 RequireFFAdjacency(m);
1620 RequirePerVertexMark(m);
1622 int count, total = 0;
1629 ScalarType NormalThrRad = math::ToRad(normalThresholdDeg);
1630 ScalarType eps = ScalarType(0.0001);
1632 for(FaceIterator fi=m.face.begin();fi!= m.face.end();++fi )
if(!(*fi).IsV())
1634 if( vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(0)).Normalize()) > NormalThrRad &&
1635 vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(1)).Normalize()) > NormalThrRad &&
1636 vcg::AngleN(NN,TriangleNormal(*(*fi).FFp(2)).Normalize()) > NormalThrRad )
1641 for(
int i=0;i<3;i++)
1645 bool ret = vcg::InterpolationParameters((*(*fi).FFp(i)),TriangleNormal(*(*fi).FFp(i)),p,L);
1646 if(ret && L[0]>eps && L[1]>eps && L[2]>eps)
1648 (*fi).FFp(i)->SetS();
1649 (*fi).FFp(i)->SetV();
1651 if(face::CheckFlipEdge<FaceType>( *fi, i )) {
1652 face::FlipEdge<FaceType>( *fi, i );
1662 while( repeat && count );
1667 static int RemoveTVertexByFlip(MeshType &m,
float threshold=40,
bool repeat=
true)
1669 RequireFFAdjacency(m);
1670 RequirePerVertexMark(m);
1672 int count, total = 0;
1680 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1682 FacePointer f = &(m.face[index]);
float sides[3]; CoordType dummy;
1683 sides[0] = Distance(f->P(0), f->P(1));
1684 sides[1] = Distance(f->P(1), f->P(2));
1685 sides[2] = Distance(f->P(2), f->P(0));
1687 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1688 if( tri::IsMarked(m,f->V2(i) ))
continue;
1690 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1692 tri::Mark(m,f->V2(i));
1693 if(face::CheckFlipEdge<FaceType>( *f, i )) {
1695 FacePointer g = f->FFp(i);
int k = f->FFi(i);
1696 Triangle3<ScalarType> t1(f->P(i), f->P1(i), f->P2(i)), t2(g->P(k), g->P1(k), g->P2(k)),
1697 t3(f->P(i), g->P2(k), f->P2(i)), t4(g->P(k), f->P2(i), g->P2(k));
1699 if ( std::min( QualityFace(t1), QualityFace(t2) ) < std::min( QualityFace(t3), QualityFace(t4) ))
1701 face::FlipEdge<FaceType>( *f, i );
1711 while( repeat && count );
1715 static int RemoveTVertexByCollapse(MeshType &m,
float threshold=40,
bool repeat=
true)
1717 RequirePerVertexMark(m);
1719 int count, total = 0;
1726 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1728 FacePointer f = &(m.face[index]);
1732 sides[0] = Distance(f->P(0), f->P(1));
1733 sides[1] = Distance(f->P(1), f->P(2));
1734 sides[2] = Distance(f->P(2), f->P(0));
1735 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1736 if( tri::IsMarked(m,f->V2(i) ))
continue;
1738 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1740 tri::Mark(m,f->V2(i));
1742 int j = Distance(dummy,f->P(i))<Distance(dummy,f->P1(i))?i:(i+1)%3;
1743 f->P2(i) = f->P(j); tri::Mark(m,f->V(j));
1753 while( repeat && count );
1758 static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret)
1760 RequirePerFaceMark(m);
1762 int referredBit = FaceType::NewBitFlag();
1763 tri::UpdateFlags<MeshType>::FaceClear(m,referredBit);
1766 gM.Set(m.face.begin(),m.face.end());
1768 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
1770 (*fi).SetUserBit(referredBit);
1771 Box3< ScalarType> bbox;
1772 (*fi).GetBBox(bbox);
1773 std::vector<FaceType*> inBox;
1774 vcg::tri::GetInBoxFace(m, gM, bbox,inBox);
1775 bool Intersected=
false;
1776 typename std::vector<FaceType*>::iterator fib;
1777 for(fib=inBox.begin();fib!=inBox.end();++fib)
1779 if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) )
1781 ret.push_back(*fib);
1783 ret.push_back(&*fi);
1791 FaceType::DeleteBitFlag(referredBit);
1792 return (ret.size()>0);
1800 int DeletedVertNum=0;
1801 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1802 if((*vi).IsD()) DeletedVertNum++;
1804 int DeletedEdgeNum=0;
1805 for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
1806 if((*ei).IsD()) DeletedEdgeNum++;
1808 int DeletedFaceNum=0;
1809 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1810 if((*fi).IsD()) DeletedFaceNum++;
1812 if(
size_t(m.vn+DeletedVertNum) != m.vert.size())
return false;
1813 if(
size_t(m.en+DeletedEdgeNum) != m.edge.size())
return false;
1814 if(
size_t(m.fn+DeletedFaceNum) != m.face.size())
return false;
1825 RequireFFAdjacency(m);
1827 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1830 for(
int i=0;i<3;++i)
1831 if(!FFCorrectness(*fi, i))
return false;
1841 tri::RequirePerFaceWedgeTexCoord(m);
1843 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1845 { FaceType &f=(*fi);
1846 if( ! ( (f.WT(0).N() == f.WT(1).N()) && (f.WT(0).N() == (*fi).WT(2).N()) ) )
1849 if((*fi).WT(0).N() <0)
return false;
1859 tri::RequirePerFaceWedgeTexCoord(m);
1861 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1864 if( (*fi).WT(0).P() == (*fi).WT(1).P() && (*fi).WT(0).P() == (*fi).WT(2).P() )
return false;
1880 if(sv==3)
return true;
1881 if(sv==0)
return (vcg::IntersectionTriangleTriangle<FaceType>((*f0),(*f1)));
1887 int i0,i1; ScalarType a,b;
1889 CoordType shP = f0->V(i0)->P()*0.5;
1890 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) )
1893 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
1896 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) )
1899 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
1915 mergedCnt = ClusterVertex(m,radius);
1920 static int ClusterVertex(MeshType &m,
const ScalarType radius)
1922 if(m.vn==0)
return 0;
1925 typedef vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT;
1927 tri::EmptyTMark<MeshType> markerFunctor;
1928 std::vector<VertexType*> closests;
1930 sht.Set(m.vert.begin(), m.vert.end());
1932 for(VertexIterator viv = m.vert.begin(); viv!= m.vert.end(); ++viv)
1933 if(!(*viv).IsD() && !(*viv).IsV())
1938 GridGetInBox(sht, markerFunctor, bb, closests);
1940 for(
size_t i=0; i<closests.size(); ++i)
1942 ScalarType dist = Distance(p,closests[i]->cP());
1943 if(dist < radius && !closests[i]->IsV())
1947 closests[i]->SetV();
1956 static std::pair<int,int> RemoveSmallConnectedComponentsSize(MeshType &m,
int maxCCSize)
1958 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1959 int TotalCC=ConnectedComponents(m, CCV);
1962 ConnectedComponentIterator<MeshType> ci;
1963 for(
unsigned int i=0;i<CCV.size();++i)
1965 std::vector<typename MeshType::FacePointer> FPV;
1966 if(CCV[i].first<maxCCSize)
1969 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1972 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
1973 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
1977 return std::make_pair(TotalCC,DeletedCC);
1985 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
1986 int TotalCC=ConnectedComponents(m, CCV);
1989 for(
unsigned int i=0;i<CCV.size();++i)
1992 std::vector<typename MeshType::FacePointer> FPV;
1993 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
1996 bb.
Add((*ci)->P(0));
1997 bb.
Add((*ci)->P(1));
1998 bb.
Add((*ci)->P(2));
2000 if(bb.
Diag()<maxDiameter)
2003 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
2004 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
2008 return std::make_pair(TotalCC,DeletedCC);
2015 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
2016 int TotalCC=ConnectedComponents(m, CCV);
2019 for(
unsigned int i=0;i<CCV.size();++i)
2022 std::vector<typename MeshType::FacePointer> FPV;
2023 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
2026 bb.
Add((*ci)->P(0));
2027 bb.
Add((*ci)->P(1));
2028 bb.
Add((*ci)->P(2));
2030 if(bb.
Diag()>minDiameter)
2033 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
2034 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
2038 return std::make_pair(TotalCC,DeletedCC);
2051 typedef std::unordered_set<VertexPointer> VertexSet;
2052 tri::RequireVFAdjacency(m);
2053 tri::RequirePerFaceNormal(m);
2054 tri::RequirePerVertexNormal(m);
2059 if (cosThreshold > 0)
2062#pragma omp parallel for schedule(dynamic, 10)
2063 for (
int i = 0; i < m.face.size(); i++)
2065 VertexSet nearVertex;
2066 std::vector<CoordType> pointVec;
2067 FacePointer f = &m.face[i];
2068 for (
int j = 0; j < 3; j++)
2070 std::vector<VertexPointer> temp;
2071 vcg::face::VVStarVF<FaceType>(f->V(j), temp);
2072 typename std::vector<VertexPointer>::iterator iter = temp.begin();
2073 for (; iter != temp.end(); iter++)
2075 if ((*iter) != f->V1(j) && (*iter) != f->V2(j))
2077 if (nearVertex.insert((*iter)).second)
2078 pointVec.push_back((*iter)->P());
2081 nearVertex.insert(f->V(j));
2082 pointVec.push_back(f->P(j));
2085 if (pointVec.size() > 3)
2087 vcg::Plane3<ScalarType> plane;
2088 vcg::FitPlaneToPointSet(pointVec, plane);
2090 for (
auto nvp : nearVertex)
2091 avgDot += plane.Direction().dot(nvp->N());
2092 avgDot /= nearVertex.size();
2093 typename MeshType::VertexType::NormalType normal;
2095 normal = -plane.Direction();
2097 normal = plane.Direction();
2098 if (normal.dot(f->N()) < cosThreshold)
2109 RequirePerFaceMark(m2);
2110 RequireCompactness(m1);
2111 RequireCompactness(m2);
2116 gM.Set(m2.face.begin(),m2.face.end());
2118 for(
auto fi=m1.face.begin();fi!=m1.face.end();++fi)
2121 (*fi).GetBBox(bbox);
2122 std::vector<FaceType*> inBox;
2123 vcg::tri::GetInBoxFace(m2, gM, bbox,inBox);
2124 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 RemoveDegenerateVertex(MeshType &m, bool DeleteVertexFlag=true)
Definition: clean.h:439
static int RemoveDuplicateFace(MeshType &m)
Definition: clean.h:334
static void SelectFoldedFaceFromOneRingFaces(MeshType &m, ScalarType cosThreshold)
Definition: clean.h:2049
static bool FlipNormalOutside(MeshType &m)
Definition: clean.h:1565
static int RemoveDuplicateVertex(MeshType &m, bool RemoveDegenerateFlag=true)
Definition: clean.h:206
static bool IsSizeConsistent(MeshType &m)
Definition: clean.h:1798
static int SelectIntersectingFaces(MeshType &m1, MeshType &m2)
Definition: clean.h:2107
static bool IsBitTriQuadOnly(const MeshType &m)
Definition: clean.h:921
static bool IsBitTriOnly(const MeshType &m)
Definition: clean.h:904
static bool HasZeroTexCoordFace(MeshType &m)
Definition: clean.h:1857
static std::pair< int, int > RemoveSmallConnectedComponentsDiameter(MeshType &m, ScalarType maxDiameter)
Remove the connected components smaller than a given diameter.
Definition: clean.h:1983
static size_t SplitManifoldComponents(MeshType &m, const ScalarType moveThreshold=0)
This function expand current selection to cover the whole connected component.
Definition: clean.h:714
static bool IsBitQuadOnly(const MeshType &m)
Definition: clean.h:873
static int CountNonManifoldEdgeEE(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1059
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:652
static int MeshGenus(int nvert, int nedges, int nfaces, int numholes, int numcomponents)
Definition: clean.h:1405
static std::pair< int, int > RemoveHugeConnectedComponentsDiameter(MeshType &m, ScalarType minDiameter)
Remove the connected components greater than a given diameter.
Definition: clean.h:2013
static int CountBitLargePolygons(const MeshType &m)
Definition: clean.h:988
static bool HasConsistentPerFaceFauxFlag(const MeshType &m)
Definition: clean.h:1039
static void SelectCreaseVertexOnEdgeMeshVE(MeshType &m, ScalarType AngleRadThr)
Given an edge mesh it selects the vertexes where the edge make an angle greater than AngleRadThr....
Definition: clean.h:625
static bool HasConsistentPerWedgeTexCoord(MeshType &m)
Definition: clean.h:1839
static bool TestFaceFaceIntersection(FaceType *f0, FaceType *f1)
Definition: clean.h:1877
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:1550
static int CountBitQuads(const MeshType &m)
Definition: clean.h:936
static int CountBitPolygons(const MeshType &m)
Definition: clean.h:965
static bool IsWaterTight(MeshType &m)
Definition: clean.h:1207
static int RemoveDegenerateFace(MeshType &m, bool DeleteFacesFlag=true)
Definition: clean.h:479
static int CountBitTris(const MeshType &m)
Definition: clean.h:951
static int RemoveDuplicateEdge(MeshType &m)
Definition: clean.h:363
static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular)
Definition: clean.h:1433
static int CountNonManifoldEdgeFF(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1097
static int RemoveNonManifoldFace(MeshType &m, bool DeleteFacesFlag=true)
Removal of faces that were incident on a non manifold edge.
Definition: clean.h:803
static void SelectCreaseVertexOnEdgeMeshEE(MeshType &m, ScalarType AngleRadThr)
Given an edge mesh it selects the vertexes where the edge make an angle greater than AngleRadThr....
Definition: clean.h:595
static int MergeCloseVertex(MeshType &m, const ScalarType radius)
Definition: clean.h:1912
static int CountNonManifoldVertexFF(MeshType &m, bool selectVert=true, bool clearSelection=true)
Definition: clean.h:1149
static bool IsFFAdjacencyConsistent(MeshType &m)
Definition: clean.h:1823
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:471
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
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