Updated to reflect the Normal() -> TriangleNormal() change

Updated to reflect the changes to the UpdateFlags (new function names ::VertexBorderFromFaceAdj ::VertexBorderFromFaceBorder)
This commit is contained in:
Paolo Cignoni 2014-11-12 00:14:23 +00:00
parent 4b0e72293f
commit 9d89004760
8 changed files with 224 additions and 222 deletions

View File

@ -255,10 +255,10 @@ class Clustering
else
Grid.siz = Point3i::Construct(Grid.dim / _cellsize);
// find voxel size
Grid.voxel[0] = Grid.dim[0]/Grid.siz[0];
Grid.voxel[1] = Grid.dim[1]/Grid.siz[1];
Grid.voxel[2] = Grid.dim[2]/Grid.siz[2];
// find voxel size
Grid.voxel[0] = Grid.dim[0]/Grid.siz[0];
Grid.voxel[1] = Grid.dim[1]/Grid.siz[1];
Grid.voxel[2] = Grid.dim[2]/Grid.siz[2];
}
BasicGrid<ScalarType> Grid;
@ -277,18 +277,18 @@ class Clustering
STDEXT::hash_map<HashedPoint3i,CellType> GridCell;
void AddPointSet(MeshType &m, bool UseOnlySelected=false)
{
VertexIterator vi;
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
if(!UseOnlySelected || (*vi).IsS())
{
HashedPoint3i pi;
Grid.PToIP((*vi).cP(), pi );
GridCell[pi].AddVertex(m,Grid,pi,*(vi));
}
}
void AddPointSet(MeshType &m, bool UseOnlySelected=false)
{
VertexIterator vi;
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
if(!UseOnlySelected || (*vi).IsS())
{
HashedPoint3i pi;
Grid.PToIP((*vi).cP(), pi );
GridCell[pi].AddVertex(m,Grid,pi,*(vi));
}
}
void AddMesh(MeshType &m)
{
@ -377,7 +377,7 @@ class Clustering
// the best orientation according to the averaged normal
if(!DuplicateFaceParam)
{
CoordType N=vcg::Normal(m.face[i]);
CoordType N=TriangleNormal(m.face[i]);
int badOrient=0;
if( N.dot((*ti).v[0]->N()) <0) ++badOrient;
if( N.dot((*ti).v[1]->N()) <0) ++badOrient;

View File

@ -66,7 +66,7 @@ template <class MESH> class AdvancingFront {
UpdateFlags<MESH>::FaceBorderFromNone(mesh);
UpdateFlags<MESH>::VertexBorderFromFace(mesh);
UpdateFlags<MESH>::VertexBorderFromFaceBorder(mesh);
nb.clear();
nb.resize(mesh.vert.size(), 0);
@ -343,7 +343,7 @@ public:
protected:
void AddFace(int v0, int v1, int v2) {
FaceIterator fi = vcg::tri::Allocator<MESH>::AddFace(mesh,v0,v1,v2);
ComputeNormalizedNormal(*fi);
fi->N() = TriangleNormal(*fi).Normalize();
if(tri::HasVFAdjacency(mesh))
{
for(int j=0;j<3;++j)

View File

@ -376,7 +376,7 @@ void SphericalCap(MeshType &in, float angleRad, const int subdiv = 3 )
tri::Refine(in, MidPoint<MeshType>(&in));
tri::UpdateFlags<MeshType>::FaceBorderFromFF(in);
tri::UpdateFlags<MeshType>::VertexBorderFromFace(in);
tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(in);
for(int i=0;i<in.vn;++i)
if(in.vert[i].IsB())
@ -1015,6 +1015,7 @@ void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float in
typedef typename MeshType::CoordType CoordType;
if(height==0) height = mIn.bbox.Diag()/100.0f;
if(inset==0) inset = mIn.bbox.Diag()/200.0f;
tri::UpdateTopology<MeshType>::FaceFace(mIn);
tri::UpdateFlags<MeshType>::FaceClearV(mIn);
for(size_t i=0;i<mIn.face.size();++i) if(!mIn.face[i].IsV())
{
@ -1065,6 +1066,7 @@ void BuildPrismFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float in
if(smoothFlag)
{
faceM.face.EnableFFAdjacency();
tri::UpdateTopology<MeshType>::FaceFace(faceM);
tri::UpdateFlags<MeshType>::FaceBorderFromFF(faceM);
tri::Refine(faceM, MidPoint<MeshType>(&faceM),0,true);

View File

@ -94,7 +94,7 @@ public:
assert(e0.IsBorder());
e1=e0;
e1.NextB();
n=vcg::Normal<TrivialEar>(*this);
n=TriangleNormal<TrivialEar>(*this);
ComputeQuality();
ComputeAngle();
}
@ -159,7 +159,7 @@ public:
(*f).V(0) = e0.VFlip();
(*f).V(1) = e0.v;
(*f).V(2) = e1.v;
face::ComputeNormalizedNormal(*f);
f->N() = TriangleNormal(*f).Normalize();
face::FFAttachManifold(f,0,e0.f,e0.z);
face::FFAttachManifold(f,1,e1.f,e1.z);
@ -644,8 +644,8 @@ template<class EAR>
static float ComputeDihedralAngle(CoordType p1,CoordType p2,CoordType p3,CoordType p4)
{
CoordType n1 = NormalizedNormal(p1,p3,p2);
CoordType n2 = NormalizedNormal(p1,p2,p4);
CoordType n1 = Normal(p1,p3,p2);
CoordType n2 = Normal(p1,p2,p4);
return math::ToDeg(AngleN(n1,n2));
}

View File

@ -92,37 +92,37 @@ namespace tri{
/**
This class describe Quadric based collapse operation.
Requirements:
Requirements:
Vertex
must have:
Vertex
must have:
incremental mark
VF topology
must have:
members
must have:
members
QuadricType Qd();
ScalarType W() const;
A per-vertex Weight that can be used in simplification
lower weight means that error is lowered,
standard: return W==1.0
ScalarType W() const;
A per-vertex Weight that can be used in simplification
lower weight means that error is lowered,
standard: return W==1.0
void Merge(MESH_TYPE::vertex_type const & v);
Merges the attributes of the current vertex with the ones of v
(e.g. its weight with the one of the given vertex, the color ect).
Standard: void function;
void Merge(MESH_TYPE::vertex_type const & v);
Merges the attributes of the current vertex with the ones of v
(e.g. its weight with the one of the given vertex, the color ect).
Standard: void function;
OtherWise the class should be templated with a static helper class that helps to retrieve these functions.
If the vertex class exposes these functions a default static helper class is provided.
*/
//**Helper CLASSES**//
template <class VERTEX_TYPE>
class QInfoStandard
{
public:
//**Helper CLASSES**//
template <class VERTEX_TYPE>
class QInfoStandard
{
public:
QInfoStandard(){}
static void Init(){}
static math::Quadric<double> &Qd(VERTEX_TYPE &v) {return v.Qd();}
@ -130,7 +130,7 @@ namespace tri{
static typename VERTEX_TYPE::ScalarType W(VERTEX_TYPE */*v*/) {return 1.0;}
static typename VERTEX_TYPE::ScalarType W(VERTEX_TYPE &/*v*/) {return 1.0;}
static void Merge(VERTEX_TYPE & /*v_dest*/, VERTEX_TYPE const & /*v_del*/){}
};
};
class TriEdgeCollapseQuadricParameter : public BaseParameterClass
@ -189,11 +189,11 @@ public:
// typedef typename TEC::EdgeType EdgeType;
typedef typename TriEdgeCollapse<TriMeshType, VertexPair, MYTYPE>::HeapType HeapType;
typedef typename TriEdgeCollapse<TriMeshType, VertexPair, MYTYPE>::HeapElem HeapElem;
typedef typename TriMeshType::CoordType CoordType;
typedef typename TriMeshType::ScalarType ScalarType;
typedef math::Quadric< double > QuadricType;
typedef typename TriMeshType::FaceType FaceType;
typedef typename TriMeshType::VertexType VertexType;
typedef typename TriMeshType::CoordType CoordType;
typedef typename TriMeshType::ScalarType ScalarType;
typedef math::Quadric< double > QuadricType;
typedef typename TriMeshType::FaceType FaceType;
typedef typename TriMeshType::VertexType VertexType;
typedef TriEdgeCollapseQuadricParameter QParameter;
typedef HelperType QH;
@ -203,19 +203,19 @@ public:
// }
// puntatori ai vertici che sono stati messi non-w per preservare il boundary
static std::vector<typename TriMeshType::VertexPointer> & WV(){
// puntatori ai vertici che sono stati messi non-w per preservare il boundary
static std::vector<typename TriMeshType::VertexPointer> & WV(){
static std::vector<typename TriMeshType::VertexPointer> _WV; return _WV;
};
inline TriEdgeCollapseQuadric(){}
inline TriEdgeCollapseQuadric(){}
inline TriEdgeCollapseQuadric(const VertexPair &p, int i, BaseParameterClass *pp)
{
this->localMark = i;
this->pos=p;
{
this->localMark = i;
this->pos=p;
this->_priority = ComputePriority(pp);
}
}
inline bool IsFeasible(BaseParameterClass *_pp){
@ -249,7 +249,7 @@ public:
if(pp->FastPreserveBoundary)
{
typename TriMeshType::VertexIterator vi;
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD()) (*vi).SetW();
}
if(pp->PreserveBoundary)
@ -324,25 +324,25 @@ public:
}
}
}
else
else
{ // if the collapse is A-symmetric (e.g. u->v != v->u)
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD() && (*vi).IsRW())
{
vcg::face::VFIterator<FaceType> x;
UnMarkAll(m);
for( x.F() = (*vi).VFp(), x.I() = (*vi).VFi(); x.F()!=0; ++ x)
{
assert(x.F()->V(x.I())==&(*vi));
if(x.V()->IsRW() && x.V1()->IsRW() && !IsMarked(m,x.F()->V1(x.I()))){
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD() && (*vi).IsRW())
{
vcg::face::VFIterator<FaceType> x;
UnMarkAll(m);
for( x.F() = (*vi).VFp(), x.I() = (*vi).VFi(); x.F()!=0; ++ x)
{
assert(x.F()->V(x.I())==&(*vi));
if(x.V()->IsRW() && x.V1()->IsRW() && !IsMarked(m,x.F()->V1(x.I()))){
h_ret.push_back( HeapElem( new MYTYPE( VertexPair (x.V(),x.V1()),TriEdgeCollapse< TriMeshType,VertexPair,MYTYPE>::GlobalMark(),_pp)));
}
if(x.V()->IsRW() && x.V2()->IsRW() && !IsMarked(m,x.F()->V2(x.I()))){
}
if(x.V()->IsRW() && x.V2()->IsRW() && !IsMarked(m,x.F()->V2(x.I()))){
h_ret.push_back( HeapElem( new MYTYPE( VertexPair (x.V(),x.V2()),TriEdgeCollapse< TriMeshType,VertexPair,MYTYPE>::GlobalMark(),_pp)));
}
}
}
}
}
}
}
}
}
static float HeapSimplexRatio(BaseParameterClass *_pp) {return IsSymmetric(_pp)?5.0f:9.0f;}
static bool IsSymmetric(BaseParameterClass *_pp) {return ((QParameter *)_pp)->OptimalPlacement;}
@ -358,78 +358,78 @@ public:
ScalarType ComputePriority(BaseParameterClass *_pp)
{
QParameter *pp=(QParameter *)_pp;
ScalarType error;
typename vcg::face::VFIterator<FaceType> x;
std::vector<CoordType> on; // original normals
typename TriMeshType::VertexType * v[2];
v[0] = this->pos.V(0);
v[1] = this->pos.V(1);
ScalarType error;
typename vcg::face::VFIterator<FaceType> x;
std::vector<CoordType> on; // original normals
typename TriMeshType::VertexType * v[2];
v[0] = this->pos.V(0);
v[1] = this->pos.V(1);
if(pp->NormalCheck){ // Compute maximal normal variation
// store the old normals for non-collapsed face in v0
for(x.F() = v[0]->VFp(), x.I() = v[0]->VFi(); x.F()!=0; ++x ) // for all faces in v0
if(x.F()->V(0)!=v[1] && x.F()->V(1)!=v[1] && x.F()->V(2)!=v[1] ) // skip faces with v1
on.push_back(NormalizedNormal(*x.F()));
// store the old normals for non-collapsed face in v1
for(x.F() = v[1]->VFp(), x.I() = v[1]->VFi(); x.F()!=0; ++x ) // for all faces in v1
if(x.F()->V(0)!=v[0] && x.F()->V(1)!=v[0] && x.F()->V(2)!=v[0] ) // skip faces with v0
on.push_back(NormalizedNormal(*x.F()));
}
// store the old normals for non-collapsed face in v0
for(x.F() = v[0]->VFp(), x.I() = v[0]->VFi(); x.F()!=0; ++x ) // for all faces in v0
if(x.F()->V(0)!=v[1] && x.F()->V(1)!=v[1] && x.F()->V(2)!=v[1] ) // skip faces with v1
on.push_back(TriangleNormal(*x.F()).Normalize());
// store the old normals for non-collapsed face in v1
for(x.F() = v[1]->VFp(), x.I() = v[1]->VFi(); x.F()!=0; ++x ) // for all faces in v1
if(x.F()->V(0)!=v[0] && x.F()->V(1)!=v[0] && x.F()->V(2)!=v[0] ) // skip faces with v0
on.push_back(TriangleNormal(*x.F()).Normalize());
}
//// Move the two vertexe into new position (storing the old ones)
CoordType OldPos0=v[0]->P();
CoordType OldPos1=v[1]->P();
//// Move the two vertexe into new position (storing the old ones)
CoordType OldPos0=v[0]->P();
CoordType OldPos1=v[1]->P();
if(pp->OptimalPlacement) { v[0]->P() = ComputeMinimal(); v[1]->P()=v[0]->P();}
else v[0]->P() = v[1]->P();
else v[0]->P() = v[1]->P();
//// Rescan faces and compute quality and difference between normals
int i;
double ndiff,MinCos = 1e100; // minimo coseno di variazione di una normale della faccia
// (e.g. max angle) Mincos varia da 1 (normali coincidenti) a
// -1 (normali opposte);
double qt, MinQual = 1e100;
CoordType nn;
for(x.F() = v[0]->VFp(), x.I() = v[0]->VFi(),i=0; x.F()!=0; ++x ) // for all faces in v0
if(x.F()->V(0)!=v[1] && x.F()->V(1)!=v[1] && x.F()->V(2)!=v[1] ) // skip faces with v1
{
//// Rescan faces and compute quality and difference between normals
int i;
double ndiff,MinCos = 1e100; // minimo coseno di variazione di una normale della faccia
// (e.g. max angle) Mincos varia da 1 (normali coincidenti) a
// -1 (normali opposte);
double qt, MinQual = 1e100;
CoordType nn;
for(x.F() = v[0]->VFp(), x.I() = v[0]->VFi(),i=0; x.F()!=0; ++x ) // for all faces in v0
if(x.F()->V(0)!=v[1] && x.F()->V(1)!=v[1] && x.F()->V(2)!=v[1] ) // skip faces with v1
{
if(pp->NormalCheck){
nn=NormalizedNormal(*x.F());
ndiff=nn.dot(on[i++]);
if(ndiff<MinCos) MinCos=ndiff;
}
nn=TriangleNormal(*x.F()).Normalize();
ndiff=nn.dot(on[i++]);
if(ndiff<MinCos) MinCos=ndiff;
}
if(pp->QualityCheck){
qt= QualityFace(*x.F());
if(qt<MinQual) MinQual=qt;
}
}
for(x.F() = v[1]->VFp(), x.I() = v[1]->VFi(),i=0; x.F()!=0; ++x ) // for all faces in v1
if(x.F()->V(0)!=v[0] && x.F()->V(1)!=v[0] && x.F()->V(2)!=v[0] ) // skip faces with v0
{
qt= QualityFace(*x.F());
if(qt<MinQual) MinQual=qt;
}
}
for(x.F() = v[1]->VFp(), x.I() = v[1]->VFi(),i=0; x.F()!=0; ++x ) // for all faces in v1
if(x.F()->V(0)!=v[0] && x.F()->V(1)!=v[0] && x.F()->V(2)!=v[0] ) // skip faces with v0
{
if(pp->NormalCheck){
nn=NormalizedNormal(*x.F());
ndiff=nn.dot(on[i++]);
if(ndiff<MinCos) MinCos=ndiff;
}
nn=TriangleNormal(*x.F()).Normalize();
ndiff=nn.dot(on[i++]);
if(ndiff<MinCos) MinCos=ndiff;
}
if(pp->QualityCheck){
qt= QualityFace(*x.F());
if(qt<MinQual) MinQual=qt;
}
}
qt= QualityFace(*x.F());
if(qt<MinQual) MinQual=qt;
}
}
QuadricType qq=QH::Qd(v[0]);
qq+=QH::Qd(v[1]);
Point3d tpd=Point3d::Construct(v[1]->P());
Point3d tpd=Point3d::Construct(v[1]->P());
double QuadErr = pp->ScaleFactor*qq.Apply(tpd);
// All collapses involving triangles with quality larger than <QualityThr> has no penalty;
// All collapses involving triangles with quality larger than <QualityThr> has no penalty;
if(MinQual>pp->QualityThr) MinQual=pp->QualityThr;
if(pp->NormalCheck){
// All collapses where the normal vary less than <NormalThr> (e.g. more than CosineThr)
// have no penalty
// All collapses where the normal vary less than <NormalThr> (e.g. more than CosineThr)
// have no penalty
if(MinCos>pp->CosineThr) MinCos=pp->CosineThr;
MinCos=(MinCos+1)/2.0; // Now it is in the range 0..1 with 0 very dangerous!
}
MinCos=(MinCos+1)/2.0; // Now it is in the range 0..1 with 0 very dangerous!
}
if(QuadErr<pp->QuadricEpsilon) QuadErr=pp->QuadricEpsilon;
@ -440,12 +440,12 @@ public:
if(!pp->QualityCheck && pp->NormalCheck) error = (ScalarType)(QuadErr / MinCos);
if( pp->QualityCheck && pp->NormalCheck) error = (ScalarType)(QuadErr / (MinQual*MinCos));
//Rrestore old position of v0 and v1
v[0]->P()=OldPos0;
v[1]->P()=OldPos1;
this->_priority = error;
return this->_priority;
}
//Rrestore old position of v0 and v1
v[0]->P()=OldPos0;
v[1]->P()=OldPos1;
this->_priority = error;
return this->_priority;
}
//
//static double MaxError() {return 1e100;}
@ -510,72 +510,72 @@ public:
static void InitQuadric(TriMeshType &m,BaseParameterClass *_pp)
{
QParameter *pp=(QParameter *)_pp;
typename TriMeshType::FaceIterator pf;
typename TriMeshType::VertexIterator pv;
int j;
typename TriMeshType::FaceIterator pf;
typename TriMeshType::VertexIterator pv;
int j;
QH::Init();
// m.ClearFlags();
for(pv=m.vert.begin();pv!=m.vert.end();++pv) // Azzero le quadriche
if( ! (*pv).IsD() && (*pv).IsW())
// m.ClearFlags();
for(pv=m.vert.begin();pv!=m.vert.end();++pv) // Azzero le quadriche
if( ! (*pv).IsD() && (*pv).IsW())
QH::Qd(*pv).SetZero();
for(pf=m.face.begin();pf!=m.face.end();++pf)
if( !(*pf).IsD() && (*pf).IsR() )
if((*pf).V(0)->IsR() &&(*pf).V(1)->IsR() &&(*pf).V(2)->IsR())
{
QuadricType q;
Plane3<ScalarType,false> p;
// Calcolo piano
p.SetDirection( ( (*pf).V(1)->cP() - (*pf).V(0)->cP() ) ^ ( (*pf).V(2)->cP() - (*pf).V(0)->cP() ));
// Se normalizzo non dipende dall'area
for(pf=m.face.begin();pf!=m.face.end();++pf)
if( !(*pf).IsD() && (*pf).IsR() )
if((*pf).V(0)->IsR() &&(*pf).V(1)->IsR() &&(*pf).V(2)->IsR())
{
QuadricType q;
Plane3<ScalarType,false> p;
// Calcolo piano
p.SetDirection( ( (*pf).V(1)->cP() - (*pf).V(0)->cP() ) ^ ( (*pf).V(2)->cP() - (*pf).V(0)->cP() ));
// Se normalizzo non dipende dall'area
if(!pp->UseArea)
p.Normalize();
p.Normalize();
p.SetOffset( p.Direction().dot((*pf).V(0)->cP()));
p.SetOffset( p.Direction().dot((*pf).V(0)->cP()));
// Calcolo quadrica delle facce
q.ByPlane(p);
// Calcolo quadrica delle facce
q.ByPlane(p);
for(j=0;j<3;++j)
for(j=0;j<3;++j)
if( (*pf).V(j)->IsW() )
{
{
if(pp->QualityWeight)
q*=(*pf).V(j)->Q();
QH::Qd((*pf).V(j)) += q; // Sommo la quadrica ai vertici
}
q*=(*pf).V(j)->Q();
QH::Qd((*pf).V(j)) += q; // Sommo la quadrica ai vertici
}
for(j=0;j<3;++j)
for(j=0;j<3;++j)
if( (*pf).IsB(j) || pp->QualityQuadric ) // Bordo!
{
Plane3<ScalarType,false> pb; // Piano di bordo
{
Plane3<ScalarType,false> pb; // Piano di bordo
// Calcolo la normale al piano di bordo e la sua distanza
// Nota che la lunghezza dell'edge DEVE essere Normalizzata
// poiche' la pesatura in funzione dell'area e'gia fatta in p.Direction()
// Senza la normalize il bordo e' pesato in funzione della grandezza della mesh (mesh grandi non decimano sul bordo)
pb.SetDirection(p.Direction() ^ ( (*pf).V1(j)->cP() - (*pf).V(j)->cP() ).normalized());
// Calcolo la normale al piano di bordo e la sua distanza
// Nota che la lunghezza dell'edge DEVE essere Normalizzata
// poiche' la pesatura in funzione dell'area e'gia fatta in p.Direction()
// Senza la normalize il bordo e' pesato in funzione della grandezza della mesh (mesh grandi non decimano sul bordo)
pb.SetDirection(p.Direction() ^ ( (*pf).V1(j)->cP() - (*pf).V(j)->cP() ).normalized());
if( (*pf).IsB(j) ) pb.SetDirection(pb.Direction()* (ScalarType)pp->BoundaryWeight); // amplify border planes
else pb.SetDirection(pb.Direction()* (ScalarType)(pp->BoundaryWeight/100.0)); // and consider much less quadric for quality
pb.SetOffset(pb.Direction().dot((*pf).V(j)->cP()));
q.ByPlane(pb);
pb.SetOffset(pb.Direction().dot((*pf).V(j)->cP()));
q.ByPlane(pb);
if( (*pf).V (j)->IsW() ) QH::Qd((*pf).V (j)) += q; // Sommo le quadriche
if( (*pf).V1(j)->IsW() ) QH::Qd((*pf).V1(j)) += q;
}
}
if( (*pf).V (j)->IsW() ) QH::Qd((*pf).V (j)) += q; // Sommo le quadriche
if( (*pf).V1(j)->IsW() ) QH::Qd((*pf).V1(j)) += q;
}
}
if(pp->ScaleIndependent)
{
vcg::tri::UpdateBounding<TriMeshType>::Box(m);
//Make all quadric independent from mesh size
{
vcg::tri::UpdateBounding<TriMeshType>::Box(m);
//Make all quadric independent from mesh size
pp->ScaleFactor = 1e8*pow(1.0/m.bbox.Diag(),6); // scaling factor
//pp->ScaleFactor *=pp->ScaleFactor ;
//pp->ScaleFactor *=pp->ScaleFactor ;
//printf("Scale factor =%f\n",pp->ScaleFactor );
//printf("bb (%5.2f %5.2f %5.2f)-(%5.2f %5.2f %5.2f) Diag %f\n",m.bbox.min[0],m.bbox.min[1],m.bbox.min[2],m.bbox.max[0],m.bbox.max[1],m.bbox.max[2],m.bbox.Diag());
}
//printf("bb (%5.2f %5.2f %5.2f)-(%5.2f %5.2f %5.2f) Diag %f\n",m.bbox.min[0],m.bbox.min[1],m.bbox.min[2],m.bbox.max[0],m.bbox.max[1],m.bbox.max[2],m.bbox.Diag());
}
}
@ -595,25 +595,25 @@ public:
//
CoordType ComputeMinimal()
{
typename TriMeshType::VertexType * v[2];
v[0] = this->pos.V(0);
v[1] = this->pos.V(1);
QuadricType q=QH::Qd(v[0]);
q+=QH::Qd(v[1]);
typename TriMeshType::VertexType * v[2];
v[0] = this->pos.V(0);
v[1] = this->pos.V(1);
QuadricType q=QH::Qd(v[0]);
q+=QH::Qd(v[1]);
Point3<QuadricType::ScalarType> x;
bool rt=q.Minimum(x);
if(!rt) { // if the computation of the minimum fails we choose between the two edge points and the middle one.
Point3<QuadricType::ScalarType> x0=Point3d::Construct(v[0]->P());
Point3<QuadricType::ScalarType> x1=Point3d::Construct(v[1]->P());
if(!rt) { // if the computation of the minimum fails we choose between the two edge points and the middle one.
Point3<QuadricType::ScalarType> x0=Point3d::Construct(v[0]->P());
Point3<QuadricType::ScalarType> x1=Point3d::Construct(v[1]->P());
x.Import((v[0]->P()+v[1]->P())/2);
double qvx=q.Apply(x);
double qv0=q.Apply(x0);
double qv1=q.Apply(x1);
double qvx=q.Apply(x);
double qv0=q.Apply(x0);
double qv1=q.Apply(x1);
if(qv0<qvx) x=x0;
if(qv1<qvx && qv1<qv0) x=x1;
}
if(qv1<qvx && qv1<qv0) x=x1;
}
return CoordType::Construct(x);
}
@ -621,6 +621,6 @@ public:
//
};
} // namespace tri
} // namespace vcg
} // namespace tri
} // namespace vcg
#endif

View File

@ -340,7 +340,7 @@ class TriEdgeCollapseQuadricTex: public vcg::tri::TriEdgeCollapse< TriMeshType,
qt= QualityFace(*x.F());
if(qt<MinQual) MinQual=qt;
if(pp->NormalCheck){
CoordType nn=NormalizedNormal(*x.F());
CoordType nn=TriangleNormal(*x.F()).Normalize();
ndiff=nn.dot(x.F()->N()) / x.F()->N().Norm();
if(ndiff<MinCos) MinCos=ndiff;
assert(!math::IsNAN(ndiff));
@ -352,7 +352,7 @@ class TriEdgeCollapseQuadricTex: public vcg::tri::TriEdgeCollapse< TriMeshType,
qt= QualityFace(*x.F());
if(qt<MinQual) MinQual=qt;
if(pp->NormalCheck){
CoordType nn=NormalizedNormal(*x.F());
CoordType nn=TriangleNormal(*x.F()).Normalize();
ndiff=nn.dot(x.F()->N() / x.F()->N().Norm());
if(ndiff<MinCos) MinCos=ndiff;
assert(!math::IsNAN(ndiff));

View File

@ -247,7 +247,7 @@ So it just require that you have correctly computed the flags; one way could be
\code
vcg::tri::UpdateTopology<Mesh>::FaceFace(m.cm);
vcg::tri::UpdateFlags<Mesh>::FaceBorderFromFF(m.cm);
vcg::tri::UpdateFlags<Mesh>::VertexBorderFromFace (m.cm);
vcg::tri::UpdateFlags<Mesh>::VertexBorderFromFaceBorder (m.cm);
vcg::tri::UpdateColor<Mesh>::PerVertexBorderFlag(m.cm);
\endcode
*/

View File

@ -503,7 +503,7 @@ static void ConvertVoronoiDiagramToMesh(MeshType &m,
if(vpp.triangulateRegion)
{
tri::UpdateFlags<MeshType>::FaceBorderFromFF(outMesh);
tri::UpdateFlags<MeshType>::VertexBorderFromFace(outMesh);
tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(outMesh);
for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi) if(!fi->IsD())
{
for(int i=0;i<3;++i)
@ -734,7 +734,7 @@ static void ConvertVoronoiDiagramToMeshOld(MeshType &m,
tri::Allocator<MeshType>::CompactEveryVector(outMesh);
tri::UpdateTopology<MeshType>::FaceFace(outMesh);
tri::UpdateFlags<MeshType>::FaceBorderFromFF(outMesh);
tri::UpdateFlags<MeshType>::VertexBorderFromFace(outMesh);
tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(outMesh);
// 3) set up faux bits
for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi)
@ -1282,7 +1282,7 @@ static int VoronoiRelaxing(MeshType &m, std::vector<VertexType *> &seedVec,
}
tri::UpdateFlags<MeshType>::FaceBorderFromVF(m);
tri::UpdateFlags<MeshType>::VertexBorderFromFace(m);
tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(m);
PerVertexPointerHandle sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
PerVertexBoolHandle fixed = tri::Allocator<MeshType>:: template GetPerVertexAttribute<bool> (m,"fixed");
int iter;