Heavily changed the whole hole filling class, now much shorter, more readable and hopefully more robust.
Still to better balance shape vs diedral angle quality measure.
This commit is contained in:
parent
0edde01197
commit
f3ef64cc0c
|
@ -19,120 +19,6 @@
|
|||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.34 2007/01/31 15:25:49 giec
|
||||
Remove some usless code in Minimum Weight Triangulation.
|
||||
|
||||
Revision 1.33 2007/01/31 11:46:12 giec
|
||||
Bug fix
|
||||
|
||||
Revision 1.32 2007/01/18 18:15:14 cignoni
|
||||
added missing typenames
|
||||
|
||||
Revision 1.31 2007/01/18 11:17:43 giec
|
||||
The minimum weight algorithm keep the topology consistent.
|
||||
|
||||
Revision 1.30 2007/01/10 12:07:54 giec
|
||||
Bugfixed ComputeDihedralAngle function
|
||||
|
||||
Revision 1.29 2006/12/27 15:09:52 giec
|
||||
Bug fix on ComputeDihedralAngle function
|
||||
|
||||
Revision 1.28 2006/12/12 11:14:51 cignoni
|
||||
Commented some variant of the quality measure of weighted ears
|
||||
|
||||
Revision 1.27 2006/12/07 00:40:18 cignoni
|
||||
Added many this-> for gcc compiling
|
||||
|
||||
Revision 1.26 2006/12/06 13:03:59 cignoni
|
||||
Corrected bugs on selfintersection
|
||||
|
||||
Revision 1.25 2006/12/06 00:12:53 cignoni
|
||||
Heavily restructured and corrected. Now a single Close ear function
|
||||
Corrected Hole search function, and management of double non manifold vertex in a hole
|
||||
Changed priority strategy in the heap, now a mix of quality and dihedral angle.
|
||||
Changed but still untested IntersectionEar
|
||||
|
||||
Revision 1.24 2006/12/01 21:24:16 cignoni
|
||||
Corrected bug in the search of holes. Removed output prints
|
||||
|
||||
Revision 1.23 2006/12/01 08:53:55 cignoni
|
||||
Corrected pop_heap vs pop_back issue in heap usage
|
||||
|
||||
Revision 1.22 2006/12/01 00:11:17 cignoni
|
||||
Added Callback, Corrected some spelling errors (adiacense -> adjacency).
|
||||
Added Validity Check function for hole loops
|
||||
|
||||
Revision 1.21 2006/11/30 11:49:20 cignoni
|
||||
small gcc compiling issues
|
||||
|
||||
Revision 1.20 2006/11/29 16:21:45 cignoni
|
||||
Made static exposed funtions of the class
|
||||
|
||||
Revision 1.19 2006/11/29 15:25:22 giec
|
||||
Removed limit.
|
||||
|
||||
Revision 1.18 2006/11/29 15:18:49 giec
|
||||
Code refactory and bugfix.
|
||||
|
||||
Revision 1.17 2006/11/24 10:42:39 mariolatronico
|
||||
Now compiles on gcc under linux.
|
||||
|
||||
Revision 1.16 2006/11/22 13:43:28 giec
|
||||
Code refactory and added minimum weight triangolation.
|
||||
|
||||
Revision 1.15 2006/11/13 10:11:38 giec
|
||||
Clear some useless code
|
||||
|
||||
Revision 1.14 2006/11/07 15:13:56 zifnab1974
|
||||
Necessary changes for compilation with gcc 3.4.6. Especially the hash function is a problem
|
||||
|
||||
Revision 1.13 2006/11/07 11:47:11 cignoni
|
||||
gcc compiling issues
|
||||
|
||||
Revision 1.12 2006/11/07 07:56:43 cignoni
|
||||
Added missing std::
|
||||
|
||||
Revision 1.11 2006/11/06 16:12:29 giec
|
||||
Leipa ear now compute max dihedral angle.
|
||||
|
||||
Revision 1.10 2006/10/31 11:30:41 ganovelli
|
||||
changed access throught iterator with static call to comply 2005 compiler
|
||||
|
||||
Revision 1.9 2006/10/20 07:44:45 cignoni
|
||||
Added missing std::
|
||||
|
||||
Revision 1.8 2006/10/18 15:06:47 giec
|
||||
New policy for compute quality in TrivialEar.
|
||||
Bugfixed LeipaEar.
|
||||
Added new algorithm "selfintersection" with test for self intersection.
|
||||
|
||||
Revision 1.7 2006/10/10 09:12:02 giec
|
||||
Bugfix and added a new type of ear (Liepa like)
|
||||
|
||||
Revision 1.6 2006/10/09 10:07:07 giec
|
||||
Optimized version of "EAR HOLE FILLING", the Ear is selected according to its dihedral angle.
|
||||
|
||||
Revision 1.5 2006/10/06 15:28:14 giec
|
||||
first working implementationof "EAR HOLE FILLING".
|
||||
|
||||
Revision 1.4 2006/10/02 12:06:40 giec
|
||||
BugFix
|
||||
|
||||
Revision 1.3 2006/09/27 15:33:32 giec
|
||||
It close one simple hole . . .
|
||||
|
||||
Revision 1.2 2006/09/27 09:29:53 giec
|
||||
Frist working release whit a few bugs.
|
||||
It almost fills the hole ...
|
||||
|
||||
Revision 1.1 2006/09/25 09:17:44 cignoni
|
||||
First Non working Version
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef __VCG_TRI_UPDATE_HOLE
|
||||
#define __VCG_TRI_UPDATE_HOLE
|
||||
|
@ -140,21 +26,29 @@ First Non working Version
|
|||
#include <wrap/callback.h>
|
||||
#include <vcg/math/base.h>
|
||||
#include <vcg/complex/algorithms/clean.h>
|
||||
#include <vcg/space/point3.h>
|
||||
#include <vector>
|
||||
#include <float.h>
|
||||
|
||||
// This file contains three Ear Classes
|
||||
// - TrivialEar
|
||||
// - MinimumWeightEar
|
||||
// - SelfIntersectionEar
|
||||
// and a static class Hole for filling holes that is templated on the ear class
|
||||
|
||||
|
||||
|
||||
namespace vcg {
|
||||
namespace tri {
|
||||
|
||||
/*
|
||||
Un ear e' identificato da due hedge pos.
|
||||
i vertici dell'ear sono
|
||||
An ear is identified by TWO pos.
|
||||
The Three vertexes of an Ear are:
|
||||
e0.VFlip().v
|
||||
e0.v
|
||||
e1.v
|
||||
Vale che e1== e0.NextB();
|
||||
e che e1.FlipV() == e0;
|
||||
Invariants:
|
||||
e1 == e0.NextB();
|
||||
e1.FlipV() == e0;
|
||||
|
||||
Situazioni ear non manifold, e degeneri (buco triangolare)
|
||||
|
||||
T XXXXXXXXXXXXX A /XXXXX B en/XXXXX
|
||||
|
@ -167,9 +61,9 @@ namespace vcg {
|
|||
XXX \|/XXXXXXXX XXX \|/XXXXXXXX XXX \|/XXXXXXXX
|
||||
XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||
*/
|
||||
template<class MESH> class TrivialEar
|
||||
{
|
||||
public:
|
||||
template<class MESH> class TrivialEar
|
||||
{
|
||||
public:
|
||||
typedef typename MESH::FaceType FaceType;
|
||||
typedef typename MESH::FacePointer FacePointer;
|
||||
typedef typename face::Pos<FaceType> PosType;
|
||||
|
@ -180,6 +74,8 @@ namespace vcg {
|
|||
PosType e1;
|
||||
CoordType n; // the normal of the face defined by the ear
|
||||
const char * Dump() {return 0;}
|
||||
// The following members are useful to consider the Ear as a generic <triangle>
|
||||
// with p0 the 'center' of the ear.
|
||||
const CoordType &cP(int i) const {return P(i);}
|
||||
const CoordType &P(int i) const {
|
||||
switch(i) {
|
||||
|
@ -192,8 +88,7 @@ namespace vcg {
|
|||
}
|
||||
|
||||
ScalarType quality;
|
||||
ScalarType angle;
|
||||
//std::vector<typename MESH::FaceType>* vf;
|
||||
ScalarType angleRad;
|
||||
TrivialEar(){}
|
||||
TrivialEar(const PosType & ep)
|
||||
{
|
||||
|
@ -211,17 +106,17 @@ namespace vcg {
|
|||
// the angle computation takes into account the case of reversed ears
|
||||
void ComputeAngle()
|
||||
{
|
||||
angle=Angle(cP(2)-cP(0), cP(1)-cP(0));
|
||||
angleRad=Angle(cP(2)-cP(0), cP(1)-cP(0));
|
||||
ScalarType flipAngle = n.dot(e0.v->N());
|
||||
if(flipAngle<0) angle = (2.0 *(float)M_PI) - angle;
|
||||
if(flipAngle<0) angleRad = (2.0 *(ScalarType)M_PI) - angleRad;
|
||||
}
|
||||
|
||||
virtual inline bool operator < ( const TrivialEar & c ) const { return quality < c.quality; }
|
||||
|
||||
bool IsNull(){return e0.IsNull() || e1.IsNull();}
|
||||
void SetNull(){e0.SetNull();e1.SetNull();}
|
||||
virtual void ComputeQuality() { quality = QualityFace(*this) ; };
|
||||
bool IsUpToDate() {return ( e0.IsBorder() && e1.IsBorder());};
|
||||
virtual void ComputeQuality() { quality = QualityFace(*this) ; }
|
||||
bool IsUpToDate() {return ( e0.IsBorder() && e1.IsBorder());}
|
||||
// An ear is degenerated if both of its two endpoints are non manifold.
|
||||
bool IsDegen(const int nonManifoldBit)
|
||||
{
|
||||
|
@ -229,7 +124,7 @@ namespace vcg {
|
|||
return true;
|
||||
else return false;
|
||||
}
|
||||
bool IsConcave() const {return(angle > (float)M_PI);}
|
||||
bool IsConcave() const {return(angleRad > (float)M_PI);}
|
||||
|
||||
virtual bool Close(PosType &np0, PosType &np1, FaceType * f)
|
||||
{
|
||||
|
@ -248,27 +143,15 @@ namespace vcg {
|
|||
(*f).V(2) = e1.v;
|
||||
ComputeNormal(*f);
|
||||
|
||||
(*f).FFp(0) = e0.f;
|
||||
(*f).FFi(0) = e0.z;
|
||||
(*f).FFp(1) = e1.f;
|
||||
(*f).FFi(1) = e1.z;
|
||||
(*f).FFp(2) = f;
|
||||
(*f).FFi(2) = 2;
|
||||
|
||||
e0.f->FFp(e0.z)=f;
|
||||
e0.f->FFi(e0.z)=0;
|
||||
|
||||
e1.f->FFp(e1.z)=f;
|
||||
e1.f->FFi(e1.z)=1;
|
||||
face::FFAttachManifold(f,0,e0.f,e0.z);
|
||||
face::FFAttachManifold(f,1,e1.f,e1.z);
|
||||
face::FFSetBorder(f,2);
|
||||
|
||||
// caso ear degenere per buco triangolare
|
||||
if(ep==en)
|
||||
{
|
||||
//printf("Closing the last triangle");
|
||||
f->FFp(2)=en.f;
|
||||
f->FFi(2)=en.z;
|
||||
en.f->FFp(en.z)=f;
|
||||
en.f->FFi(en.z)=2;
|
||||
face::FFAttachManifold(f,2,en.f,en.z);
|
||||
np0.SetNull();
|
||||
np1.SetNull();
|
||||
}
|
||||
|
@ -278,10 +161,7 @@ namespace vcg {
|
|||
//printf("Ear Non manif A\n");
|
||||
PosType enold=en;
|
||||
en.NextB();
|
||||
f->FFp(2)=enold.f;
|
||||
f->FFi(2)=enold.z;
|
||||
enold.f->FFp(enold.z)=f;
|
||||
enold.f->FFi(enold.z)=2;
|
||||
face::FFAttachManifold(f,2,enold.f,enold.z);
|
||||
np0=ep;
|
||||
np1=en;
|
||||
}
|
||||
|
@ -291,10 +171,7 @@ namespace vcg {
|
|||
//printf("Ear Non manif B\n");
|
||||
PosType epold=ep;
|
||||
ep.FlipV(); ep.NextB(); ep.FlipV();
|
||||
f->FFp(2)=epold.f;
|
||||
f->FFi(2)=epold.z;
|
||||
epold.f->FFp(epold.z)=f;
|
||||
epold.f->FFi(epold.z)=2;
|
||||
face::FFAttachManifold(f,2,epold.f,epold.z);
|
||||
np0=ep; // assign the two new
|
||||
np1=en; // pos that denote the ears
|
||||
}
|
||||
|
@ -306,13 +183,14 @@ namespace vcg {
|
|||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//Ear with FillHoleMinimumWeight's quality policy
|
||||
template<class MESH> class MinimumWeightEar : public TrivialEar<MESH>
|
||||
{
|
||||
public:
|
||||
static float &DiedralWeight() { static float _dw=1.0; return _dw;}
|
||||
}; // end TrivialEar Class
|
||||
|
||||
//Ear with FillHoleMinimumWeight's quality policy
|
||||
template<class MESH> class MinimumWeightEar : public TrivialEar<MESH>
|
||||
{
|
||||
public:
|
||||
static float &DiedralWeight() { static float _dw=0.1; return _dw;}
|
||||
typedef TrivialEar<MESH> TE;
|
||||
typename MESH::ScalarType dihedralRad;
|
||||
typename MESH::ScalarType aspectRatio;
|
||||
|
@ -324,7 +202,6 @@ namespace vcg {
|
|||
}
|
||||
|
||||
MinimumWeightEar(){}
|
||||
//MinimumWeightEar(const PosType & ep) : TrivialEar<MESH>(ep)
|
||||
MinimumWeightEar(const typename face::Pos<typename MESH::FaceType>& ep) : TrivialEar<MESH>(ep)
|
||||
{
|
||||
ComputeQuality();
|
||||
|
@ -338,13 +215,12 @@ namespace vcg {
|
|||
|
||||
virtual inline bool operator < ( const MinimumWeightEar & c ) const
|
||||
{
|
||||
if(TE::IsConcave() == c.IsConcave())
|
||||
{
|
||||
return (pow((float)dihedralRad,(float)DiedralWeight())/aspectRatio) > (pow((float)c.dihedralRad,(float)DiedralWeight())/c.aspectRatio);
|
||||
}
|
||||
if(TE::IsConcave()) return true;
|
||||
// assert(c.IsConcave());
|
||||
return false;
|
||||
if(TE::IsConcave() && ! c.IsConcave() ) return true;
|
||||
if(!TE::IsConcave() && c.IsConcave() ) return false;
|
||||
|
||||
return aspectRatio - (dihedralRad/M_PI)*DiedralWeight() < c.aspectRatio -(c.dihedralRad/M_PI)*DiedralWeight();
|
||||
|
||||
// return (pow((float)dihedralRad,(float)DiedralWeight())/aspectRatio) > (pow((float)c.dihedralRad,(float)DiedralWeight())/c.aspectRatio);
|
||||
}
|
||||
|
||||
// the real core of the whole hole filling strategy.
|
||||
|
@ -358,11 +234,13 @@ namespace vcg {
|
|||
aspectRatio = QualityFace(*this);
|
||||
}
|
||||
|
||||
};
|
||||
//Ear for selfintersection algorithm
|
||||
template<class MESH> class SelfIntersectionEar : public MinimumWeightEar<MESH>
|
||||
{
|
||||
public:
|
||||
}; // end class MinimumWeightEar
|
||||
|
||||
|
||||
//Ear for selfintersection algorithm
|
||||
template<class MESH> class SelfIntersectionEar : public MinimumWeightEar<MESH>
|
||||
{
|
||||
public:
|
||||
typedef typename MESH::FaceType FaceType;
|
||||
typedef typename MESH::FacePointer FacePointer;
|
||||
typedef typename face::Pos<FaceType> PosType;
|
||||
|
@ -382,59 +260,48 @@ namespace vcg {
|
|||
{
|
||||
PosType ep=this->e0; ep.FlipV(); ep.NextB(); ep.FlipV(); // he precedente a e0
|
||||
PosType en=this->e1; en.NextB(); // he successivo a e1
|
||||
// bool triangularHole = false;
|
||||
// if(en==ep || en-) triangularHole=true;
|
||||
|
||||
|
||||
//costruisco la faccia e poi testo, o copio o butto via.
|
||||
(*f).V(0) = this->e0.VFlip();
|
||||
(*f).V(1) = this->e0.v;
|
||||
(*f).V(2) = this->e1.v;
|
||||
face::FFSetBorder(f,0);
|
||||
face::FFSetBorder(f,1);
|
||||
face::FFSetBorder(f,2);
|
||||
|
||||
(*f).FFp(0) = this->e0.f;
|
||||
(*f).FFi(0) = this->e0.z;
|
||||
(*f).FFp(1) = this->e1.f;
|
||||
(*f).FFi(1) = this->e1.z;
|
||||
(*f).FFp(2) = f;
|
||||
(*f).FFi(2) = 2;
|
||||
|
||||
int a1, a2;
|
||||
a1= this->e0.z;
|
||||
a2= this->e1.z;
|
||||
|
||||
this->e0.f->FFp(this->e0.z)=f;
|
||||
this->e0.f->FFi(this->e0.z)=0;
|
||||
|
||||
this->e1.f->FFp(this->e1.z)=f;
|
||||
this->e1.f->FFi(this->e1.z)=1;
|
||||
typename std::vector< FacePointer >::iterator it;
|
||||
for(it = this->AdjacencyRing().begin();it!= this->AdjacencyRing().end();++it)
|
||||
{
|
||||
if(!(*it)->IsD())
|
||||
if( tri::Clean<MESH>::TestFaceFaceIntersection(&(*f),*it))
|
||||
{
|
||||
this->e0.f->FFp(this->e0.z)= this->e0.f;
|
||||
this->e0.f->FFi(this->e0.z)=a1;
|
||||
|
||||
this->e1.f->FFp(this->e1.z)= this->e1.f;
|
||||
this->e1.f->FFi(this->e1.z)=a2;
|
||||
if( tri::Clean<MESH>::TestFaceFaceIntersection(f,*it))
|
||||
return false;
|
||||
// We must also check that the newly created face does not have any edge in common with other existing surrounding faces
|
||||
// Only the two faces of the ear can share an edge with the new face
|
||||
if(face::CountSharedVertex(f,*it)==2)
|
||||
{
|
||||
int e0,e1;
|
||||
bool ret=face::FindSharedEdge(f,*it,e0,e1);
|
||||
assert(ret);
|
||||
if(!face::IsBorder(**it,e1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//return ((TrivialEar<MESH> *)this)->Close(np0,np1,f);
|
||||
this->e0.f->FFp(this->e0.z)= this->e0.f;
|
||||
this->e0.f->FFi(this->e0.z)=a1;
|
||||
|
||||
this->e1.f->FFp(this->e1.z)=this->e1.f;
|
||||
this->e1.f->FFi(this->e1.z)=a2;
|
||||
|
||||
}
|
||||
bool ret=TrivialEar<MESH>::Close(np0,np1,f);
|
||||
if(ret) AdjacencyRing().push_back(f);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
}; // end class SelfIntersectionEar
|
||||
|
||||
// Funzione principale per chiudier un buco in maniera topologicamente corretta.
|
||||
// Gestisce situazioni non manifold ragionevoli
|
||||
// (tutte eccetto quelle piu' di 2 facce per 1 edge).
|
||||
// Controlla che non si generino nuove situazioni non manifold chiudendo orecchie
|
||||
// che sottendono un edge che gia'esiste.
|
||||
// Funzione principale per chiudier un buco in maniera topologicamente corretta.
|
||||
// Gestisce situazioni non manifold ragionevoli
|
||||
// (tutte eccetto quelle piu' di 2 facce per 1 edge).
|
||||
// Controlla che non si generino nuove situazioni non manifold chiudendo orecchie
|
||||
// che sottendono un edge che gia'esiste.
|
||||
|
||||
template <class MESH>
|
||||
class Hole
|
||||
|
@ -500,16 +367,39 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class EdgeToBeAvoided
|
||||
{
|
||||
VertexPointer v0,v1;
|
||||
EdgeToBeAvoided(VertexPointer _v0, VertexPointer _v1):v0(_v0),v1(_v1)
|
||||
{
|
||||
if(v0>v1) swap(v0,v1);
|
||||
}
|
||||
bool operator < (const EdgeToBeAvoided &e)
|
||||
{
|
||||
if(this->v0!=e.v0) return this->v0<e.v0;
|
||||
return this->v1<e.v1;
|
||||
}
|
||||
};
|
||||
/// Main Single Hole Filling Function
|
||||
/// Given a specific hole (identified by the Info h) it fills it
|
||||
/// It also update a vector of face pointers
|
||||
/// It uses an heap to choose the best ear to be closed
|
||||
|
||||
template<class EAR>
|
||||
static void FillHoleEar(MESH &m, Info &h ,int UBIT, std::vector<FacePointer *> &app,std::vector<FaceType > *vf =0)
|
||||
static void FillHoleEar(MESH &m, // The mesh to be filled
|
||||
Info &h, // the particular hole to be filled
|
||||
std::vector<FacePointer *> &facePointersToBeUpdated)
|
||||
{
|
||||
//Aggiungo le facce e aggiorno il puntatore alla faccia!
|
||||
FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, app);
|
||||
FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, facePointersToBeUpdated);
|
||||
|
||||
assert(h.p.f >= &*m.face.begin());
|
||||
assert(h.p.f <= &m.face.back());
|
||||
assert(h.p.IsBorder());//test fondamentale altrimenti qualcosa s'e' rotto!
|
||||
std::vector< EAR > H;
|
||||
H.reserve(h.size);
|
||||
assert(h.p.IsBorder());
|
||||
|
||||
std::vector< EAR > EarHeap;
|
||||
EarHeap.reserve(h.size);
|
||||
int nmBit= VertexType::NewBitFlag(); // non manifoldness bit
|
||||
|
||||
//First loops around the hole to mark non manifold vertices.
|
||||
|
@ -530,8 +420,8 @@ template<class EAR>
|
|||
|
||||
PosType fp = h.p;
|
||||
do{
|
||||
EAR app = EAR(fp);
|
||||
H.push_back( app );
|
||||
EAR appEar = EAR(fp);
|
||||
EarHeap.push_back( appEar );
|
||||
//printf("Adding ear %s ",app.Dump());
|
||||
fp.NextB();
|
||||
assert(fp.IsBorder());
|
||||
|
@ -539,60 +429,56 @@ template<class EAR>
|
|||
|
||||
int cnt=h.size;
|
||||
|
||||
make_heap(H.begin(), H.end());
|
||||
make_heap(EarHeap.begin(), EarHeap.end());
|
||||
|
||||
//finche' il buco non e' chiuso o non ci sono piu' orecchie da analizzare.
|
||||
while( cnt > 2 && !H.empty() )
|
||||
while( cnt > 2 && !EarHeap.empty() )
|
||||
{
|
||||
//printf("Front of the heap is %s", H.front().Dump());
|
||||
pop_heap(H.begin(), H.end()); // retrieve the MAXIMUM value and put in the back;
|
||||
PosType ep0,ep1;
|
||||
EAR BestEar=H.back();
|
||||
H.pop_back();
|
||||
pop_heap(EarHeap.begin(), EarHeap.end()); // retrieve the MAXIMUM value and put in the back;
|
||||
EAR BestEar=EarHeap.back();
|
||||
EarHeap.pop_back();
|
||||
|
||||
if(BestEar.IsUpToDate() && !BestEar.IsDegen(nmBit))
|
||||
{
|
||||
if((*f).HasPolyInfo()) (*f).Alloc(3);
|
||||
PosType ep0,ep1;
|
||||
if(BestEar.Close(ep0,ep1,&*f))
|
||||
{
|
||||
if(!ep0.IsNull()){
|
||||
H.push_back(EAR(ep0));
|
||||
push_heap( H.begin(), H.end());
|
||||
EarHeap.push_back(EAR(ep0));
|
||||
push_heap( EarHeap.begin(), EarHeap.end());
|
||||
}
|
||||
if(!ep1.IsNull()){
|
||||
H.push_back(EAR(ep1));
|
||||
push_heap( H.begin(), H.end());
|
||||
EarHeap.push_back(EAR(ep1));
|
||||
push_heap( EarHeap.begin(), EarHeap.end());
|
||||
}
|
||||
--cnt;
|
||||
f->SetUserBit(UBIT);
|
||||
if(vf != 0) (*vf).push_back(*f);
|
||||
++f;
|
||||
}
|
||||
}//is update()
|
||||
}//fine del while principale.
|
||||
//tolgo le facce non utilizzate.
|
||||
while(f!=m.face.end())
|
||||
{
|
||||
(*f).SetD();
|
||||
++f;
|
||||
m.fn--;
|
||||
|
||||
while(f!=m.face.end()){
|
||||
tri::Allocator<MESH>::DeleteFace(m,*f);
|
||||
f++;
|
||||
}
|
||||
|
||||
VertexType::DeleteBitFlag(nmBit); // non manifoldness bit
|
||||
}
|
||||
|
||||
template<class EAR>
|
||||
static int EarCuttingFill(MESH &m, int sizeHole, const int UBIT, bool Selected = false, CallBackPos *cb=0)
|
||||
static int EarCuttingFill(MESH &m, int sizeHole, bool Selected = false, CallBackPos *cb=0)
|
||||
{
|
||||
std::vector< Info > vinfo;
|
||||
// int UBIT = GetInfo(m, Selected,vinfo);
|
||||
GetInfo(m, Selected,vinfo);
|
||||
|
||||
typename std::vector<Info >::iterator ith;
|
||||
//Info app;
|
||||
int indCb=0;
|
||||
int holeCnt=0;
|
||||
std::vector<FacePointer *> vfp;
|
||||
std::vector<FacePointer *> facePtrToBeUpdated;
|
||||
for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith)
|
||||
vfp.push_back( &(*ith).p.f );
|
||||
facePtrToBeUpdated.push_back( &(*ith).p.f );
|
||||
|
||||
for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith)
|
||||
{
|
||||
|
@ -600,30 +486,22 @@ template<class EAR>
|
|||
if(cb) (*cb)(indCb*10/vinfo.size(),"Closing Holes");
|
||||
if((*ith).size < sizeHole){
|
||||
holeCnt++;
|
||||
FillHoleEar< EAR >(m, *ith,UBIT,vfp);
|
||||
FillHoleEar< EAR >(m, *ith,facePtrToBeUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
FaceIterator fi;
|
||||
for(fi = m.face.begin(); fi!=m.face.end(); ++fi)
|
||||
{
|
||||
if(!(*fi).IsD())
|
||||
(*fi).ClearUserBit(UBIT);
|
||||
}
|
||||
return holeCnt;
|
||||
}
|
||||
|
||||
// it returns the number of created holes.
|
||||
/// Main Hole Filling function.
|
||||
/// Given a mesh search for all the holes smaller than a given size and fill them
|
||||
/// It returns the number of filled holes.
|
||||
|
||||
template<class EAR>
|
||||
static int EarCuttingIntersectionFill(MESH &m, int sizeHole, const int UBIT, CallBackPos *cb=0)
|
||||
static int EarCuttingIntersectionFill(MESH &m, const int maxSizeHole, bool Selected, CallBackPos *cb=0)
|
||||
{
|
||||
std::vector<Info > vinfo;
|
||||
// int UBIT = GetInfo(m, Selected,vinfo);
|
||||
std::vector<FaceType > vf;
|
||||
PosType sp;
|
||||
PosType ap;
|
||||
typename std::vector<Info >::iterator ith;
|
||||
GetInfo(m, Selected,vinfo);
|
||||
typename std::vector<Info>::iterator ith;
|
||||
|
||||
// collect the face pointer that has to be updated by the various addfaces
|
||||
std::vector<FacePointer *> vfpOrig;
|
||||
|
@ -636,12 +514,12 @@ template<class EAR>
|
|||
{
|
||||
indCb++;
|
||||
if(cb) (*cb)(indCb*10/vinfo.size(),"Closing Holes");
|
||||
if((*ith).size < sizeHole){
|
||||
std::vector<FacePointer *> vfp;
|
||||
if((*ith).size < maxSizeHole){
|
||||
std::vector<FacePointer *> facePtrToBeUpdated;
|
||||
holeCnt++;
|
||||
vfp=vfpOrig;
|
||||
facePtrToBeUpdated=vfpOrig;
|
||||
EAR::AdjacencyRing().clear();
|
||||
//Loops around the hole to collect the races .
|
||||
//Loops around the hole to collect the faces that have to be tested for intersection.
|
||||
PosType ip = (*ith).p;
|
||||
do
|
||||
{
|
||||
|
@ -657,25 +535,20 @@ template<class EAR>
|
|||
|
||||
typename std::vector<FacePointer>::iterator fpi;
|
||||
for(fpi=EAR::AdjacencyRing().begin();fpi!=EAR::AdjacencyRing().end();++fpi)
|
||||
vfp.push_back( &*fpi );
|
||||
facePtrToBeUpdated.push_back( &*fpi );
|
||||
|
||||
FillHoleEar<EAR >(m, *ith,UBIT,vfp,&vf);
|
||||
FillHoleEar<EAR >(m, *ith,facePtrToBeUpdated);
|
||||
EAR::AdjacencyRing().clear();
|
||||
}
|
||||
}
|
||||
FaceIterator fi;
|
||||
for(fi = m.face.begin(); fi!=m.face.end(); ++fi)
|
||||
{
|
||||
if(!(*fi).IsD())
|
||||
(*fi).ClearUserBit(UBIT);
|
||||
}
|
||||
return holeCnt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void GetInfo(MESH &m, const int UBIT, bool Selected ,std::vector<Info >& VHI)
|
||||
static void GetInfo(MESH &m, bool Selected ,std::vector<Info >& VHI)
|
||||
{
|
||||
tri::UpdateFlags<MESH>::FaceClearV(m);
|
||||
for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi)
|
||||
{
|
||||
if(!(*fi).IsD())
|
||||
|
@ -684,15 +557,15 @@ template<class EAR>
|
|||
{
|
||||
//se devo considerare solo i triangoli selezionati e
|
||||
//quello che sto considerando non lo e' lo marchio e vado avanti
|
||||
(*fi).SetUserBit(UBIT);
|
||||
(*fi).SetV();
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j =0; j<3 ; ++j)
|
||||
{
|
||||
if( face::IsBorder(*fi,j) && !(*fi).IsUserBit(UBIT) )
|
||||
if( face::IsBorder(*fi,j) && !(*fi).IsV() )
|
||||
{//Trovato una faccia di bordo non ancora visitata.
|
||||
(*fi).SetUserBit(UBIT);
|
||||
(*fi).SetV();
|
||||
PosType sp(&*fi, j, (*fi).V(j));
|
||||
PosType fp=sp;
|
||||
int holesize=0;
|
||||
|
@ -700,14 +573,14 @@ template<class EAR>
|
|||
Box3Type hbox;
|
||||
hbox.Add(sp.v->cP());
|
||||
//printf("Looping %i : (face %i edge %i) \n", VHI.size(),sp.f-&*m.face.begin(),sp.z);
|
||||
sp.f->SetUserBit(UBIT);
|
||||
sp.f->SetV();
|
||||
do
|
||||
{
|
||||
sp.f->SetUserBit(UBIT);
|
||||
sp.f->SetV();
|
||||
hbox.Add(sp.v->cP());
|
||||
++holesize;
|
||||
sp.NextB();
|
||||
sp.f->SetUserBit(UBIT);
|
||||
sp.f->SetV();
|
||||
assert(sp.IsBorder());
|
||||
}while(sp != fp);
|
||||
|
||||
|
@ -915,15 +788,14 @@ template<class EAR>
|
|||
triangulate(m,f,k,j,vi,vv);
|
||||
}
|
||||
|
||||
static void MinimumWeightFill(MESH &m, const int UBIT, int holeSize, bool Selected)
|
||||
static void MinimumWeightFill(MESH &m, int holeSize, bool Selected)
|
||||
{
|
||||
FaceIterator fi;
|
||||
std::vector<PosType > vvi;
|
||||
std::vector<FacePointer * > vfp;
|
||||
|
||||
std::vector<Info > vinfo;
|
||||
typename std::vector<Info >::iterator VIT;
|
||||
GetInfo(m, UBIT, Selected,vinfo);
|
||||
GetInfo(m, Selected,vinfo);
|
||||
|
||||
for(VIT = vinfo.begin(); VIT != vinfo.end();++VIT)
|
||||
{
|
||||
|
@ -983,6 +855,6 @@ template<class EAR>
|
|||
|
||||
};//close class Hole
|
||||
|
||||
} // end namespace
|
||||
}
|
||||
} // end namespace tri
|
||||
} // end namespace vcg
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue