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;
214 std::vector<VertexPointer> mp(m.vert.size(),
nullptr);
219 size_t num_vert = m.vert.size();
220 std::vector<VertexPointer> perm(num_vert);
221 for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++k)
226 std::sort(perm.begin(),perm.end(),c_obj);
233 if( (! (*perm[i]).IsD()) &&
234 (! (*perm[j]).IsD()) &&
235 (*perm[i]).P() == (*perm[j]).cP() )
237 VertexPointer t = perm[i];
238 mp[tri::Index(m, t)] = perm[j];
250 for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi)
252 for(k = 0; k < (*fi).VN(); ++k)
253 if( VertexPointer to = mp[tri::Index(m, (*fi).V(k))] )
256 for(EdgeIterator ei = m.edge.begin(); ei!=m.edge.end(); ++ei)
258 for(k = 0; k < 2; ++k)
259 if( VertexPointer to = mp[tri::Index(m, (*ei).V(k))] )
262 for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti)
264 for (k = 0; k < 4; ++k)
265 if (VertexPointer to = mp[tri::Index(m, (*ti).V(k))])
269 if(RemoveDegenerateFlag && m.en>0) {
270 RemoveDegenerateEdge(m);
280 SortedPair(
unsigned int v0,
unsigned int v1, EdgePointer _fp)
284 if(v[0]>v[1]) std::swap(v[0],v[1]);
288 return (v[1]!=p.v[1])?(v[1]<p.v[1]):
293 if( (v[0]==s.v[0]) && (v[1]==s.v[1]) )
return true;
304 SortedTriple(
unsigned int v0,
unsigned int v1,
unsigned int v2,FacePointer _fp)
306 v[0]=v0;v[1]=v1;v[2]=v2;
312 return (v[2]!=p.v[2])?(v[2]<p.v[2]):
313 (v[1]!=p.v[1])?(v[1]<p.v[1]):
318 if( (v[0]==s.v[0]) && (v[1]==s.v[1]) && (v[2]==s.v[2]) )
return true;
334 std::vector<SortedTriple> fvec;
335 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
339 tri::Index(m,(*fi).V(1)),
340 tri::Index(m,(*fi).V(2)),
343 std::sort(fvec.begin(),fvec.end());
345 for(
int i=0;i<int(fvec.size())-1;++i)
347 if(fvec[i]==fvec[i+1])
363 if (m.en==0)
return 0;
364 std::vector<SortedPair> eVec;
365 for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei)
368 eVec.push_back(
SortedPair( tri::Index(m,(*ei).V(0)), tri::Index(m,(*ei).V(1)), &*ei));
370 std::sort(eVec.begin(),eVec.end());
372 for(
int i=0;i<int(eVec.size())-1;++i)
374 if(eVec[i]==eVec[i+1])
383 static int CountUnreferencedVertex( MeshType& m)
396 tri::RequirePerVertexFlags(m);
398 std::vector<bool> referredVec(m.vert.size(),
false);
401 for(
auto fi = m.face.begin(); fi != m.face.end(); ++fi)
403 for(
auto j=0; j < (*fi).VN(); ++j)
404 referredVec[tri::Index(m, (*fi).V(j))]=
true;
406 for(
auto ei=m.edge.begin();ei!=m.edge.end();++ei)
408 referredVec[tri::Index(m, (*ei).V(0))]=
true;
409 referredVec[tri::Index(m, (*ei).V(1))]=
true;
412 for(
auto ti=m.tetra.begin(); ti!=m.tetra.end();++ti)
414 referredVec[tri::Index(m, (*ti).V(0))]=
true;
415 referredVec[tri::Index(m, (*ti).V(1))]=
true;
416 referredVec[tri::Index(m, (*ti).V(2))]=
true;
417 referredVec[tri::Index(m, (*ti).V(3))]=
true;
421 if(!DeleteVertexFlag)
422 return std::count(referredVec.begin(),referredVec.end(),
false);
424 for(
auto vi=m.vert.begin();vi!=m.vert.end();++vi)
425 if( (!(*vi).IsD()) && (!referredVec[tri::Index(m,*vi)]) )
442 for(vi=m.vert.begin(); vi!=m.vert.end();++vi)
443 if(math::IsNAN( (*vi).P()[0]) ||
444 math::IsNAN( (*vi).P()[1]) ||
445 math::IsNAN( (*vi).P()[2]) )
448 if (DeleteVertexFlag)
455 for(fi=m.face.begin(); fi!=m.face.end();++fi)
457 if( (*fi).V(0)->IsD() ||
462 if (DeleteVertexFlag)
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) )
496 static int RemoveDegenerateEdge(MeshType& m,
bool DeleteEdgesFlag=
true)
500 for(EdgeIterator ei=m.edge.begin(); ei!=m.edge.end();++ei)
503 if((*ei).V(0) == (*ei).V(1) )
513 static int RemoveNonManifoldVertex(MeshType& m)
517 int count_removed = 0;
518 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
519 if(!(*fi).IsD() && (*fi).IsS())
521 for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end();++vi)
522 if(!(*vi).IsD() && (*vi).IsS()) {
526 return count_removed;
530 static int SplitSelectedVertexOnEdgeMesh(MeshType& m)
532 tri::RequireCompactness(m);
535 std::unordered_map<size_t,size_t> refCount;
536 size_t countSplit = 0;
537 for (
size_t i=0; i<m.edge.size(); ++i)
539 for (
int j=0; j<2; ++j)
541 const VertexPointer vp = m.edge[i].V(j);
544 const size_t refs = ++refCount[Index(m, m.edge[i].V(j))];
555 for (
size_t i=0; i<m.edge.size(); ++i)
557 for (
int j=0; j<2; ++j)
559 const VertexPointer vp = m.edge[i].V(j);
560 const size_t vIdx = Index(m, vp);
563 if (--refCount[vIdx] > 0)
565 newVertIt->ImportData(*vp);
566 m.edge[i].V(j) = &*(newVertIt++);
572 return int(countSplit);
576 static void SelectNonManifoldVertexOnEdgeMesh(MeshType &m)
578 tri::RequireCompactness(m);
580 std::vector<int> cnt(m.vn,0);
582 for(
size_t i=0;i<m.edge.size();++i)
584 cnt[tri::Index(m,m.edge[i].V(0))]++;
585 cnt[tri::Index(m,m.edge[i].V(1))]++;
587 for(
size_t i=0;i<m.vert.size();++i)
588 if(cnt[i]>2) m.vert[i].SetS();
595 tri::RequireCompactness(m);
596 tri::RequireEEAdjacency(m);
600 for(
size_t i=0;i<m.edge.size();++i)
604 if(! m.edge[i].V(j)->IsV())
606 const CoordType ¢erV = m.edge[i].V(j)->cP();
607 m.edge[i].V(j)->SetV();
608 std::vector<VertexPointer> VVStarVec;
609 edge::VVStarEE(&(m.edge[i]),j,VVStarVec);
610 if(VVStarVec.size()==2)
612 CoordType v0 = centerV - VVStarVec[0]->P();
613 CoordType v1 = VVStarVec[1]->P() - centerV;
614 if(vcg::Angle(v0,v1) > AngleRadThr)
615 m.edge[i].V(j)->SetS();
625 tri::RequireCompactness(m);
626 tri::RequireVEAdjacency(m);
629 for(
size_t i=0;i<m.vert.size();++i)
631 std::vector<VertexPointer> VVStarVec;
632 edge::VVStarVE(&(m.vert[i]),VVStarVec);
633 if(VVStarVec.size()==2)
635 CoordType v0 = m.vert[i].P() - VVStarVec[0]->P();
636 CoordType v1 = m.vert[i].P() - VVStarVec[1]->P();
637 float angle = M_PI-vcg::Angle(v0,v1);
638 if(angle > AngleRadThr) m.vert[i].SetS();
652 RequireFFAdjacency(m);
653 typedef std::pair<FacePointer,int> FaceInt;
655 std::vector<std::pair<VertexPointer, std::vector<FaceInt> > >ToSplitVec;
661 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
663 for (
int i=0; i<fi->VN(); i++)
664 if ((*fi).V(i)->IsS() && !(*fi).V(i)->IsV())
667 face::Pos<FaceType> startPos(&*fi,i);
668 face::Pos<FaceType> curPos = startPos;
669 std::set<FaceInt> faceSet;
672 faceSet.insert(std::make_pair(curPos.F(),curPos.VInd()));
675 }
while (curPos != startPos);
677 ToSplitVec.push_back(make_pair((*fi).V(i),std::vector<FaceInt>()));
679 typename std::set<FaceInt>::const_iterator iii;
681 for(iii=faceSet.begin();iii!=faceSet.end();++iii)
682 ToSplitVec.back().second.push_back(*iii);
689 for(
size_t i =0;i<ToSplitVec.size();++i)
692 VertexPointer np=ToSplitVec[i].first;
694 firstVp->ImportData(*np);
696 CoordType delta(0,0,0);
697 for(
size_t j=0;j<ToSplitVec[i].second.size();++j)
699 FaceInt ff=ToSplitVec[i].second[j];
700 ff.first->V(ff.second)=&*firstVp;
701 delta+=Barycenter(*(ff.first))-np->cP();
703 delta /= ToSplitVec[i].second.size();
704 firstVp->P() = firstVp->P() + delta * moveThreshold;
708 return int(ToSplitVec.size());
714 typedef typename MeshType::FacePointer FacePointer;
715 typedef typename MeshType::FaceIterator FaceIterator;
717 RequireFFAdjacency(m);
723 tmpMesh.vert.EnableVFAdjacency();
724 tmpMesh.face.EnableVFAdjacency();
726 if (m.face.IsWedgeTexCoordEnabled())
727 tmpMesh.face.EnableWedgeTexCoord();
731 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
732 if( !(*fi).IsD() && !(*fi).IsV() && !(*fi).IsS())
736 std::deque<FacePointer> visitStack;
737 visitStack.push_back(&*fi);
742 while(!visitStack.empty())
744 FacePointer fp = visitStack.front();
745 visitStack.pop_front();
747 for(
int i=0;i<fp->VN();++i) {
748 FacePointer ff = fp->FFp(i);
754 visitStack.push_back(ff);
765 for (
size_t i = 0; i < size_t(tmpMesh.VN()); ++i)
767 VertexType & v = tmpMesh.vert[i];
771 std::vector<FacePointer> faceVec;
772 std::vector<int> idxVec;
776 CoordType delta(0, 0, 0);
777 for (
auto fp : faceVec)
779 delta += vcg::Barycenter(*fp) - v.cP();
781 delta /= faceVec.size();
783 v.P() += delta * moveThreshold;
795 bool operator ()(FacePointer
const& f1, FacePointer
const& f2)
const {
796 return DoubleArea(*f1) < DoubleArea(*f2);
805 std::vector<FacePointer> ToDelVec;
807 for(fi=m.face.begin(); fi!=m.face.end();++fi)
810 if ((!IsManifold(*fi,0))||
811 (!IsManifold(*fi,1))||
812 (!IsManifold(*fi,2)))
813 ToDelVec.push_back(&*fi);
816 if (!DeleteFacesFlag)
817 return ToDelVec.size();
821 for(
size_t i=0;i<ToDelVec.size();++i)
823 if(!ToDelVec[i]->IsD())
825 FaceType &ff= *ToDelVec[i];
826 if ((!IsManifold(ff,0))||
827 (!IsManifold(ff,1))||
831 if(!face::IsBorder<FaceType>(ff,j))
832 vcg::face::FFDetach<FaceType>(ff,j);
843 static int RemoveFaceOutOfRangeArea(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits<ScalarType>::max)(),
bool OnlyOnSelected=
false,
bool DeleteFacesFlag=
true)
848 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi){
850 if(!OnlyOnSelected || (*fi).IsS())
852 const ScalarType doubleArea=DoubleArea<FaceType>(*fi);
853 if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) )
864 static int RemoveZeroAreaFace(MeshType& m,
bool DeleteFacesFlag=
true) {
return RemoveFaceOutOfRangeArea(m,0, (std::numeric_limits<ScalarType>::max)(),
false, DeleteFacesFlag); }
873 typedef typename MeshType::FaceType F;
874 tri::RequirePerFaceFlags(m);
875 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
876 unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2);
877 if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2)
return false;
883 static bool IsFaceFauxConsistent(MeshType &m)
885 RequirePerFaceFlags(m);
886 RequireFFAdjacency(m);
887 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
889 for(
int z=0;z<(*fi).VN();++z)
891 FacePointer fp = fi->FFp(z);
893 if(fi->IsF(z) != fp->IsF(zp))
return false;
904 tri::RequirePerFaceFlags(m);
905 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) {
906 if ( !fi->IsD() && fi->IsAnyF() )
return false;
911 static bool IsBitPolygonal(
const MeshType &m){
921 tri::RequirePerFaceFlags(m);
922 typedef typename MeshType::FaceType F;
923 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
924 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
925 if ( tmp!=F::FAUX0 && tmp!=F::FAUX1 && tmp!=F::FAUX2 && tmp!=0 )
return false;
936 tri::RequirePerFaceFlags(m);
937 typedef typename MeshType::FaceType F;
939 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
940 unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
941 if ( tmp==F::FAUX0 || tmp==F::FAUX1 || tmp==F::FAUX2) count++;
951 tri::RequirePerFaceFlags(m);
953 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
954 if (!(fi->IsAnyF())) count++;
965 tri::RequirePerFaceFlags(m);
967 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) {
968 if (fi->IsF(0)) count++;
969 if (fi->IsF(1)) count++;
970 if (fi->IsF(2)) count++;
972 return m.fn - count/2;
992 std::unordered_map<ConstVertexPointer, bool> vertVisited;
993 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
994 if (!vi->IsD()) vertVisited[&(*vi)] =
true;
997 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
999 for(
int i=0;i<3;++i){
1000 vertVisited[fi->V(i)] =
false;
1007 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1009 for(
int i=0;i<3;++i)
1015 vertVisited[fi->V0(i)] =
true;
1016 vertVisited[fi->V1(i)] =
true;
1023 for (ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1024 if (!vi->IsD() && !(vertVisited[&(*vi)])) countV++;
1026 return m.fn - countE/2 + countV ;
1039 RequireFFAdjacency(m);
1040 RequirePerFaceFlags(m);
1042 for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1044 for (
int k=0; k<3; k++)
1045 if( ( fi->IsF(k) != fi->cFFp(k)->IsF(fi->cFFi(k)) ) ||
1059 MeshAssert<MeshType>::OnlyEdgeMesh(m);
1060 RequireEEAdjacency(m);
1065 int nonManifoldCnt=0;
1066 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1070 for (ei = m.edge.begin(); ei != m.edge.end(); ++ei)
if (!ei->IsD())
1078 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if (!vi->IsD())
1082 if(SelectFlag) (*vi).SetS();
1086 return nonManifoldCnt;
1097 RequireFFAdjacency(m);
1099 nmfBit[0]= FaceType::NewBitFlag();
1100 nmfBit[1]= FaceType::NewBitFlag();
1101 nmfBit[2]= FaceType::NewBitFlag();
1112 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1116 for(
int i=0;i<3;++i)
1117 if(!IsManifold(*fi,i))
1119 if(!(*fi).IsUserBit(nmfBit[i]))
1124 (*fi).V0(i)->SetS();
1125 (*fi).V1(i)->SetS();
1128 face::Pos<FaceType> nmf(&*fi,i);
1131 if(SelectFlag) nmf.F()->SetS();
1132 nmf.F()->SetUserBit(nmfBit[nmf.E()]);
1135 while(nmf.f != &*fi);
1141 FaceType::DeleteBitFlag(nmfBit[2]);
1142 FaceType::DeleteBitFlag(nmfBit[1]);
1143 FaceType::DeleteBitFlag(nmfBit[0]);
1153 RequireFFAdjacency(m);
1156 int nonManifoldCnt=0;
1157 SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
1161 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1163 for (
int k=0; k<fi->VN(); k++)
1172 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1174 for(
int i=0; i<fi->VN(); ++i)
1175 if (!IsManifold(*fi,i))
1177 (*fi).V0(i)->SetV();
1178 (*fi).V1(i)->SetV();
1183 for (fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
1185 for(
int i=0; i<fi->VN(); i++)
if (!(*fi).V(i)->IsV())
1188 face::Pos<FaceType> pos(&(*fi),i);
1190 int starSizeFF = pos.NumberOfIncidentFaces();
1192 if (starSizeFF != TD[(*fi).V(i)])
1200 return nonManifoldCnt;
1211 int edgeNum=0,edgeBorderNum=0,edgeNonManifNum=0;
1212 CountEdgeNum(m, edgeNum, edgeBorderNum,edgeNonManifNum);
1213 return (edgeBorderNum==0) && (edgeNonManifNum==0);
1216 static void CountEdgeNum( MeshType & m,
int &total_e,
int &boundary_e,
int &non_manif_e )
1218 std::vector< typename tri::UpdateTopology<MeshType>::PEdge > edgeVec;
1220 sort(edgeVec.begin(), edgeVec.end());
1225 size_t f_on_cur_edge =1;
1226 for(
size_t i=0;i<edgeVec.size();++i)
1228 if(( (i+1) == edgeVec.size()) || !(edgeVec[i] == edgeVec[i+1]))
1231 if(f_on_cur_edge==1)
1253 RequireFFAdjacency(m);
1254 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1262 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
if(!fi->IsD())
1263 for(
int j=0;j<3;++j)
1269 bool wellDefined=
true;
1270 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
if(!fi->IsD())
1271 for(
int j=0;j<3;++j)
1272 if(
face::IsBorder(*fi,j) && (fi->V(j)->IsV() || fi->V1(j)->IsV()))
1279 for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
if(!fi->IsD())
1281 for(
int j=0;j<3;++j)
1285 face::Pos<FaceType> startPos(&*fi,j);
1286 face::Pos<FaceType> curPos=startPos;
1292 while(curPos!=startPos);
1304 static int CountConnectedComponents(MeshType &m)
1306 std::vector< std::pair<int,FacePointer> > CCV;
1307 return ConnectedComponents(m,CCV);
1310 static int ConnectedComponents(MeshType &m, std::vector< std::pair<int,FacePointer> > &CCV)
1312 tri::RequireFFAdjacency(m);
1315 std::stack<FacePointer> sf;
1316 FacePointer fpt=&*(m.face.begin());
1317 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1319 if(!((*fi).IsD()) && !(*fi).IsV())
1322 CCV.push_back(std::make_pair(0,&*fi));
1329 for(
int j=0; j<fpt->VN(); ++j)
1333 FacePointer l = fpt->FFp(j);
1344 return int(CCV.size());
1347 static int edgeMeshConnectedComponents(MeshType & poly, std::vector<std::pair<int, typename MeshType::EdgePointer> > &eCC)
1349 typedef typename MeshType::EdgePointer EdgePointer;
1350 tri::UpdateTopology<MeshType>::VertexEdge(poly);
1351 tri::UpdateFlags<MeshType>::EdgeClear(poly);
1353 std::stack<EdgePointer> stack;
1355 for (
auto ei = poly.edge.begin(); ei != poly.edge.end(); ++ei)
1356 if (!ei->IsD() && !ei->IsV())
1360 std::pair<int, EdgePointer> cc(1, &*ei);
1363 while (!stack.empty())
1365 EdgePointer ep = stack.top();
1368 for (
int i = 0; i < 2; ++i)
1370 edge::VEIterator<typename MeshType::EdgeType> vei(ep->V(i));
1373 if (!vei.E()->IsV())
1376 stack.push(vei.E());
1385 return int(eCC.size());
1388 static void ComputeValence( MeshType &m,
typename MeshType::PerVertexIntHandle &h)
1390 for(VertexIterator vi=m.vert.begin(); vi!= m.vert.end();++vi)
1393 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1396 for(
int j=0;j<fi->VN();j++)
1397 ++h[tri::Index(m,fi->V(j))];
1436 static int MeshGenus(
int nvert,
int nedges,
int nfaces,
int numholes,
int numcomponents)
1438 return -((nvert + nfaces - nedges + numholes - 2 * numcomponents) / 2);
1445 int boundary_e,total_e,nonmanif_e;
1446 CountEdgeNum(m,total_e,boundary_e,nonmanif_e);
1448 int numcomponents=CountConnectedComponents(m);
1449 int G=
MeshGenus(nvert,total_e,nfaces,numholes,numcomponents);
1466 RequireVFAdjacency(m);
1472 for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1476 face::Pos<FaceType> he((*vi).VFp(), &*vi);
1477 face::Pos<FaceType> ht = he;
1493 if ((n != 6)&&(!border && n != 4))
1502 Semiregular =
false;
1506 Semiregular =
false;
1511 static bool IsCoherentlyOrientedMesh(MeshType &m)
1513 RequireFFAdjacency(m);
1514 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1515 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1517 for(
int i=0;i<3;++i)
1524 static void OrientCoherentlyMesh(MeshType &m,
bool &_IsOriented,
bool &_IsOrientable)
1526 RequireFFAdjacency(m);
1527 MeshAssert<MeshType>::FFAdjacencyIsInitialized(m);
1528 bool IsOrientable =
true;
1529 bool IsOriented =
true;
1531 UpdateFlags<MeshType>::FaceClearV(m);
1532 std::stack<FacePointer> faces;
1533 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1535 if (!fi->IsD() && !fi->IsV())
1540 while (!faces.empty())
1542 FacePointer fp = faces.top();
1546 for (
int j = 0; j < 3; j++)
1548 if (!
face::IsBorder(*fp,j) && face::IsManifold<FaceType>(*fp, j))
1550 FacePointer fpaux = fp->FFp(j);
1551 int iaux = fp->FFi(j);
1552 if (!CheckOrientation(*fpaux, iaux))
1557 face::SwapEdge<FaceType,true>(*fpaux, iaux);
1560 IsOrientable =
false;
1573 if (!IsOrientable)
break;
1575 _IsOriented = IsOriented;
1576 _IsOrientable = IsOrientable;
1583 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD())
1584 if(!selected || (*fi).IsS())
1586 face::SwapEdge<FaceType,false>((*fi), 0);
1587 if (HasPerWedgeTexCoord(m))
1588 std::swap((*fi).WT(0),(*fi).WT(1));
1598 if(m.vert.empty())
return false;
1603 std::vector< VertexPointer > minVertVec;
1604 std::vector< VertexPointer > maxVertVec;
1607 std::vector< CoordType > dirVec;
1608 dirVec.push_back(CoordType(1,0,0));
1609 dirVec.push_back(CoordType(0,1,0));
1610 dirVec.push_back(CoordType(0,0,1));
1611 dirVec.push_back(CoordType( 1, 1,1));
1612 dirVec.push_back(CoordType(-1, 1,1));
1613 dirVec.push_back(CoordType(-1,-1,1));
1614 dirVec.push_back(CoordType( 1,-1,1));
1615 for(
size_t i=0;i<dirVec.size();++i)
1617 Normalize(dirVec[i]);
1618 minVertVec.push_back(&*m.vert.begin());
1619 maxVertVec.push_back(&*m.vert.begin());
1621 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if(!(*vi).IsD())
1623 for(
size_t i=0;i<dirVec.size();++i)
1625 if( (*vi).cP().dot(dirVec[i]) < minVertVec[i]->P().dot(dirVec[i])) minVertVec[i] = &*vi;
1626 if( (*vi).cP().dot(dirVec[i]) > maxVertVec[i]->P().dot(dirVec[i])) maxVertVec[i] = &*vi;
1631 ScalarType angleThreshold = cos(math::ToRad(85.0));
1632 for(
size_t i=0;i<dirVec.size();++i)
1636 if(minVertVec[i]->N().dot(dirVec[i]) > angleThreshold ) voteCount++;
1637 if(maxVertVec[i]->N().dot(dirVec[i]) < -angleThreshold ) voteCount++;
1640 if(voteCount <
int(dirVec.size())/2)
return false;
1666 float normalThresholdDeg=175,
1668 bool updateTopology=
true)
1670 RequireFFAdjacency(m);
1671 RequireCompactness(m);
1672 RequirePerFaceNormal(m);
1673 RequireTriangularMesh(m);
1674 if (m.fn == 0 || !
IsBitTriOnly(m) || m.face.front().IsWedgeTexCoordEnabled())
1682 const ScalarType thresholdCos = math::Cos(math::ToRad(math::Clamp(
1683 ScalarType(normalThresholdDeg), ScalarType(0), ScalarType(180))));
1684 const ScalarType barycentricEps = ScalarType(0.0001);
1686 auto isFold = [&](
const auto &a,
const auto &b) {
1687 return a * b < thresholdCos;
1689 auto isFoldedAcrossEdge = [&](FaceType &f,
int edge,
const CoordType &normal) {
1691 const auto &adjacentNormal = f.FFp(edge)->N();
1692 return adjacentNormal.SquaredNorm() == ScalarType(0)
1693 || isFold(normal, adjacentNormal);
1696 std::vector<size_t> queue(m.fn);
1697 std::vector<unsigned char> queued(m.fn, 1);
1698 for (
size_t i = 0; i < queue.size(); ++i) queue[i] = i;
1699 auto enqueue = [&](FacePointer fp) {
1700 const size_t index = tri::Index(m, fp);
1701 if (queued[index])
return;
1703 queue.push_back(index);
1707 while (!queue.empty()) {
1708 const size_t faceIndex = queue.back();
1710 queued[faceIndex] = 0;
1711 FaceType &f = m.face[faceIndex];
1713 const auto &fNormal = f.N();
1714 if (fNormal.SquaredNorm() == ScalarType(0))
1717 bool isolatedFold =
true;
1718 for (
int edge = 0; edge < 3; ++edge) {
1720 isolatedFold =
false;
1723 const auto &adjacentNormal = f.FFp(edge)->N();
1724 if (adjacentNormal.SquaredNorm() == ScalarType(0)
1725 || !isFold(fNormal, adjacentNormal)) {
1726 isolatedFold =
false;
1734 for (
int edge = 0; edge < 3; ++edge) {
1735 FacePointer g = f.FFp(edge);
1736 const int oppositeEdge = f.FFi(edge);
1737 if (!face::CheckFlipEdge<FaceType>(f, edge))
1740 CoordType barycentric;
1741 if (!vcg::InterpolationParameters(
1742 *g, TriangleNormal(*g), f.P2(edge), barycentric))
1744 if (barycentric[0] <= barycentricEps
1745 || barycentric[1] <= barycentricEps
1746 || barycentric[2] <= barycentricEps)
1749 const CoordType newFNormal =
1750 Normal(f.P0(edge), g->P2(oppositeEdge), f.P2(edge)).Normalize();
1751 const CoordType newGNormal =
1752 Normal(f.P1(edge), f.P2(edge), g->P2(oppositeEdge)).Normalize();
1755 if (newFNormal.SquaredNorm() == ScalarType(0)
1756 || newGNormal.SquaredNorm() == ScalarType(0)
1757 || isFold(newFNormal, newGNormal)
1758 || isFoldedAcrossEdge(f, f.Next(edge), newGNormal)
1759 || isFoldedAcrossEdge(f, f.Prev(edge), newFNormal)
1760 || isFoldedAcrossEdge(*g, g->Next(oppositeEdge), newFNormal)
1761 || isFoldedAcrossEdge(*g, g->Prev(oppositeEdge), newGNormal))
1771 FacePointer g = f.FFp(flipEdge);
1772 const int oppositeEdge = f.FFi(flipEdge);
1773 const bool fNextSelected = f.IsFaceEdgeS(f.Next(flipEdge));
1774 const bool gNextSelected = g->IsFaceEdgeS(g->Next(oppositeEdge));
1775 face::FlipEdge<FaceType>(f, flipEdge);
1776 f.N() = NormalizedTriangleNormal(f);
1777 g->N() = NormalizedTriangleNormal(*g);
1779 if (gNextSelected) f.SetFaceEdgeS(flipEdge);
else f.ClearFaceEdgeS(flipEdge);
1780 if (fNextSelected) g->SetFaceEdgeS(oppositeEdge);
else g->ClearFaceEdgeS(oppositeEdge);
1781 f.ClearFaceEdgeS(f.Next(flipEdge));
1782 g->ClearFaceEdgeS(g->Next(oppositeEdge));
1787 for (
int edge = 0; edge < 3; ++edge) {
1788 enqueue(f.FFp(edge));
1789 enqueue(g->FFp(edge));
1797 static int RemoveTVertexByFlip(MeshType &m,
float threshold=40,
bool repeat=
true)
1799 RequireFFAdjacency(m);
1800 RequirePerVertexMark(m);
1802 int count, total = 0;
1810 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1812 FacePointer f = &(m.face[index]);
float sides[3]; CoordType dummy;
1813 sides[0] = Distance(f->P(0), f->P(1));
1814 sides[1] = Distance(f->P(1), f->P(2));
1815 sides[2] = Distance(f->P(2), f->P(0));
1817 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1818 if( tri::IsMarked(m,f->V2(i) ))
continue;
1820 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1822 tri::Mark(m,f->V2(i));
1823 if(face::CheckFlipEdge<FaceType>( *f, i )) {
1825 FacePointer g = f->FFp(i);
int k = f->FFi(i);
1826 Triangle3<ScalarType> t1(f->P(i), f->P1(i), f->P2(i)), t2(g->P(k), g->P1(k), g->P2(k)),
1827 t3(f->P(i), g->P2(k), f->P2(i)), t4(g->P(k), f->P2(i), g->P2(k));
1829 if ( std::min( QualityFace(t1), QualityFace(t2) ) < std::min( QualityFace(t3), QualityFace(t4) ))
1831 face::FlipEdge<FaceType>( *f, i );
1841 while( repeat && count );
1845 static int RemoveTVertexByCollapse(MeshType &m,
float threshold=40,
bool repeat=
true)
1847 RequirePerVertexMark(m);
1849 int count, total = 0;
1856 for(
unsigned int index = 0 ; index < m.face.size(); ++index )
1858 FacePointer f = &(m.face[index]);
1862 sides[0] = Distance(f->P(0), f->P(1));
1863 sides[1] = Distance(f->P(1), f->P(2));
1864 sides[2] = Distance(f->P(2), f->P(0));
1865 int i = std::find(sides, sides+3, std::max( std::max(sides[0],sides[1]), sides[2])) - (sides);
1866 if( tri::IsMarked(m,f->V2(i) ))
continue;
1868 if(
PSDist(f->P2(i),f->P(i),f->P1(i),dummy)*threshold <= sides[i] )
1870 tri::Mark(m,f->V2(i));
1872 int j = Distance(dummy,f->P(i))<Distance(dummy,f->P1(i))?i:(i+1)%3;
1873 f->P2(i) = f->P(j); tri::Mark(m,f->V(j));
1883 while( repeat && count );
1888 static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret)
1890 RequirePerFaceMark(m);
1892 int referredBit = FaceType::NewBitFlag();
1893 tri::UpdateFlags<MeshType>::FaceClear(m,referredBit);
1896 gM.Set(m.face.begin(),m.face.end());
1898 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
1900 (*fi).SetUserBit(referredBit);
1901 Box3< ScalarType> bbox;
1902 (*fi).GetBBox(bbox);
1903 std::vector<FaceType*> inBox;
1904 vcg::tri::GetInBoxFace(m, gM, bbox,inBox);
1905 bool Intersected=
false;
1906 typename std::vector<FaceType*>::iterator fib;
1907 for(fib=inBox.begin();fib!=inBox.end();++fib)
1909 if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) )
1911 ret.push_back(*fib);
1913 ret.push_back(&*fi);
1921 FaceType::DeleteBitFlag(referredBit);
1922 return (ret.size()>0);
1930 int DeletedVertNum=0;
1931 for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
1932 if((*vi).IsD()) DeletedVertNum++;
1934 int DeletedEdgeNum=0;
1935 for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei)
1936 if((*ei).IsD()) DeletedEdgeNum++;
1938 int DeletedFaceNum=0;
1939 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1940 if((*fi).IsD()) DeletedFaceNum++;
1942 if(
size_t(m.vn+DeletedVertNum) != m.vert.size())
return false;
1943 if(
size_t(m.en+DeletedEdgeNum) != m.edge.size())
return false;
1944 if(
size_t(m.fn+DeletedFaceNum) != m.face.size())
return false;
1955 RequireFFAdjacency(m);
1957 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1960 for(
int i=0;i<3;++i)
1961 if(!FFCorrectness(*fi, i))
return false;
1971 tri::RequirePerFaceWedgeTexCoord(m);
1973 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1975 { FaceType &f=(*fi);
1976 if( ! ( (f.WT(0).N() == f.WT(1).N()) && (f.WT(0).N() == (*fi).WT(2).N()) ) )
1979 if((*fi).WT(0).N() <0)
return false;
1989 tri::RequirePerFaceWedgeTexCoord(m);
1991 for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
1994 if( (*fi).WT(0).P() == (*fi).WT(1).P() && (*fi).WT(0).P() == (*fi).WT(2).P() )
return false;
2010 if(sv==3)
return true;
2011 if(sv==0)
return (vcg::IntersectionTriangleTriangle<FaceType>((*f0),(*f1)));
2017 int i0,i1; ScalarType a,b;
2019 CoordType shP = f0->V(i0)->P()*0.5;
2020 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) )
2023 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
2026 if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) )
2029 if(a+b>=1 || a<=EPSIL || b<=EPSIL )
return false;
2045 mergedCnt = ClusterVertex(m,radius);
2050 static int ClusterVertex(MeshType &m,
const ScalarType radius)
2052 if(m.vn==0)
return 0;
2055 typedef vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT;
2057 tri::EmptyTMark<MeshType> markerFunctor;
2058 std::vector<VertexType*> closests;
2060 sht.Set(m.vert.begin(), m.vert.end());
2062 for(VertexIterator viv = m.vert.begin(); viv!= m.vert.end(); ++viv)
2063 if(!(*viv).IsD() && !(*viv).IsV())
2068 GridGetInBox(sht, markerFunctor, bb, closests);
2070 for(
size_t i=0; i<closests.size(); ++i)
2072 ScalarType dist = Distance(p,closests[i]->cP());
2073 if(dist < radius && !closests[i]->IsV())
2077 closests[i]->SetV();
2086 static std::pair<int,int> RemoveSmallConnectedComponentsSize(MeshType &m,
int maxCCSize)
2088 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
2089 int TotalCC=ConnectedComponents(m, CCV);
2092 ConnectedComponentIterator<MeshType> ci;
2093 for(
unsigned int i=0;i<CCV.size();++i)
2095 std::vector<typename MeshType::FacePointer> FPV;
2096 if(CCV[i].first<maxCCSize)
2099 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
2102 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
2103 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
2107 return std::make_pair(TotalCC,DeletedCC);
2115 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
2116 int TotalCC=ConnectedComponents(m, CCV);
2119 for(
unsigned int i=0;i<CCV.size();++i)
2122 std::vector<typename MeshType::FacePointer> FPV;
2123 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
2126 bb.
Add((*ci)->P(0));
2127 bb.
Add((*ci)->P(1));
2128 bb.
Add((*ci)->P(2));
2130 if(bb.
Diag()<maxDiameter)
2133 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
2134 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
2138 return std::make_pair(TotalCC,DeletedCC);
2145 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
2146 int TotalCC=ConnectedComponents(m, CCV);
2149 for(
unsigned int i=0;i<CCV.size();++i)
2152 std::vector<typename MeshType::FacePointer> FPV;
2153 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
2156 bb.
Add((*ci)->P(0));
2157 bb.
Add((*ci)->P(1));
2158 bb.
Add((*ci)->P(2));
2160 if(bb.
Diag()>minDiameter)
2163 typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
2164 for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
2168 return std::make_pair(TotalCC,DeletedCC);
2181 typedef std::unordered_set<VertexPointer> VertexSet;
2182 tri::RequireVFAdjacency(m);
2183 tri::RequirePerFaceNormal(m);
2184 tri::RequirePerVertexNormal(m);
2189 if (cosThreshold > 0)
2192#pragma omp parallel for schedule(dynamic, 10)
2193 for (
int i = 0; i < m.face.size(); i++)
2195 VertexSet nearVertex;
2196 std::vector<CoordType> pointVec;
2197 FacePointer f = &m.face[i];
2198 for (
int j = 0; j < 3; j++)
2200 std::vector<VertexPointer> temp;
2201 vcg::face::VVStarVF<FaceType>(f->V(j), temp);
2202 typename std::vector<VertexPointer>::iterator iter = temp.begin();
2203 for (; iter != temp.end(); iter++)
2205 if ((*iter) != f->V1(j) && (*iter) != f->V2(j))
2207 if (nearVertex.insert((*iter)).second)
2208 pointVec.push_back((*iter)->P());
2211 nearVertex.insert(f->V(j));
2212 pointVec.push_back(f->P(j));
2215 if (pointVec.size() > 3)
2217 vcg::Plane3<ScalarType> plane;
2218 vcg::FitPlaneToPointSet(pointVec, plane);
2220 for (
auto nvp : nearVertex)
2221 avgDot += plane.Direction().dot(nvp->N());
2222 avgDot /= nearVertex.size();
2223 typename MeshType::VertexType::NormalType normal;
2225 normal = -plane.Direction();
2227 normal = plane.Direction();
2228 if (normal.dot(f->N()) < cosThreshold)
2239 RequirePerFaceMark(m2);
2240 RequireCompactness(m1);
2241 RequireCompactness(m2);
2246 gM.Set(m2.face.begin(),m2.face.end());
2248 for(
auto fi=m1.face.begin();fi!=m1.face.end();++fi)
2251 (*fi).GetBBox(bbox);
2252 std::vector<FaceType*> inBox;
2253 vcg::tri::GetInBoxFace(m2, gM, bbox,inBox);
2254 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:1237
static void DeleteFace(MeshType &m, FaceType &f)
Definition: allocate.h:929
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:1090
static void DeleteVertex(MeshType &m, VertexType &v)
Definition: allocate.h:941
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:195
static void DeleteEdge(MeshType &m, EdgeType &e)
Definition: allocate.h:952
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:437
static int RemoveFaceFoldByFlip(MeshType &m, float normalThresholdDeg=175, bool repeat=true, bool updateTopology=true)
Definition: clean.h:1664
static int RemoveDuplicateFace(MeshType &m)
Definition: clean.h:332
static void SelectFoldedFaceFromOneRingFaces(MeshType &m, ScalarType cosThreshold)
Definition: clean.h:2179
static bool FlipNormalOutside(MeshType &m)
Definition: clean.h:1596
static int RemoveDuplicateVertex(MeshType &m, bool RemoveDegenerateFlag=true)
Definition: clean.h:206
static bool IsSizeConsistent(MeshType &m)
Definition: clean.h:1928
static int SelectIntersectingFaces(MeshType &m1, MeshType &m2)
Definition: clean.h:2237
static bool IsBitTriQuadOnly(const MeshType &m)
Definition: clean.h:919
static bool IsBitTriOnly(const MeshType &m)
Definition: clean.h:902
static bool HasZeroTexCoordFace(MeshType &m)
Definition: clean.h:1987
static std::pair< int, int > RemoveSmallConnectedComponentsDiameter(MeshType &m, ScalarType maxDiameter)
Remove the connected components smaller than a given diameter.
Definition: clean.h:2113
static size_t SplitManifoldComponents(MeshType &m, const ScalarType moveThreshold=0)
This function expand current selection to cover the whole connected component.
Definition: clean.h:712
static bool IsBitQuadOnly(const MeshType &m)
Definition: clean.h:871
static int CountNonManifoldEdgeEE(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1057
static int RemoveUnreferencedVertex(MeshType &m, bool DeleteVertexFlag=true)
Definition: clean.h:394
static int SplitNonManifoldVertex(MeshType &m, ScalarType moveThreshold)
Removal of faces that were incident on a non manifold edge.
Definition: clean.h:650
static int MeshGenus(int nvert, int nedges, int nfaces, int numholes, int numcomponents)
Definition: clean.h:1436
static std::pair< int, int > RemoveHugeConnectedComponentsDiameter(MeshType &m, ScalarType minDiameter)
Remove the connected components greater than a given diameter.
Definition: clean.h:2143
static int CountBitLargePolygons(const MeshType &m)
Definition: clean.h:986
static bool HasConsistentPerFaceFauxFlag(const MeshType &m)
Definition: clean.h:1037
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:623
static bool HasConsistentPerWedgeTexCoord(MeshType &m)
Definition: clean.h:1969
static int CountHoles(MeshType &m)
Counts the boundary loops of the mesh. Needs FF adjacency.
Definition: clean.h:1251
static bool TestFaceFaceIntersection(FaceType *f0, FaceType *f1)
Definition: clean.h:2007
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:1581
static int CountBitQuads(const MeshType &m)
Definition: clean.h:934
static int CountBitPolygons(const MeshType &m)
Definition: clean.h:963
static bool IsWaterTight(MeshType &m)
Definition: clean.h:1209
static int RemoveDegenerateFace(MeshType &m, bool DeleteFacesFlag=true)
Definition: clean.h:477
static int CountBitTris(const MeshType &m)
Definition: clean.h:949
static int RemoveDuplicateEdge(MeshType &m)
Definition: clean.h:361
static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular)
Definition: clean.h:1464
static int CountNonManifoldEdgeFF(MeshType &m, bool SelectFlag=false)
Definition: clean.h:1095
static int RemoveNonManifoldFace(MeshType &m, bool DeleteFacesFlag=true)
Removal of faces that were incident on a non manifold edge.
Definition: clean.h:801
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:593
static int MergeCloseVertex(MeshType &m, const ScalarType radius)
Definition: clean.h:2042
static int CountNonManifoldVertexFF(MeshType &m, bool selectVert=true, bool clearSelection=true)
Definition: clean.h:1151
static bool IsFFAdjacencyConsistent(MeshType &m)
Definition: clean.h:1953
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