diff --git a/vcg/complex/local_optimization/tri_edge_collapse.h b/vcg/complex/local_optimization/tri_edge_collapse.h new file mode 100644 index 00000000..31e79260 --- /dev/null +++ b/vcg/complex/local_optimization/tri_edge_collapse.h @@ -0,0 +1,284 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History +****************************************************************************/ + +#ifndef __VCG_DECIMATION_TRICOLLAPSE +#define __VCG_DECIMATION_CTRIOLLAPSE + +#include +#include +#include + +struct FAIL{ + static VOL(){static int vol=0; return vol++;} + static LKF(){static int lkf=0; return lkf++;} + static LKE(){static int lke=0; return lke++;} + static LKV(){static int lkv=0; return lkv++;} + static OFD(){static int ofd=0; return ofd++;} + static BOR(){static int bor=0; return bor++;} + +}; + +namespace vcg{ +namespace tri{ + +/** \addtogroup trimesh */ +/*@{*/ +/// This Class is specialization of LocalModification for the edge collapse +/// It wraps the atomic operation EdgeCollapse to be used in a optimizatin routine. +/// Note that it has knowledge of the heap of the class LocalOptimization because +/// it is responsible of updating it after a collapse has been performed + +template +class TriEdgeCollapse: public LocalOptimization::LocModType +{ + + /// The tetrahedral mesh type + typedef typename TRI_MESH_TYPE TriMeshType; + /// The tetrahedron type + typedef typename TriMeshType::FaceType FaceType; + /// The vertex type + typedef typename FaceType::VertexType VertexType; + /// The coordinate type + typedef typename FaceType::VertexType::CoordType CoordType; + /// The scalar type + typedef typename TriMeshType::VertexType::ScalarType ScalarType; + /////the base type class + //typedef typename vcg::tri::LocalModification LocalMod; + /// The HEdgePos type + typedef vcg::face::Pos PosType; + /// The HEdgePos Loop type +// typedef PosLoop PosLType; + /// definition of the heap element + typedef typename LocalOptimization::HeapElem HeapElem; + private: + + ///the new point that substitute the edge + Point3 _NewPoint; + ///the pointer to edge collapser method + EdgeCollapse _EC; + ///mark for up_dating + static int& _Imark(){ static int im=0; return im;} + ///the pos of collapse + PosType pos; + ///pointer to vertex that remain + VertexType *vrem; + /// priority in the heap + ScalarType _priority; + + public: + /// Default Constructor + TriEdgeCollapse() + {} + + ///Constructor with postype + TriEdgeCollapse(PosType p,int mark) + { + _Imark() = mark; + pos=p; + _priority = _AspectRatioMedia(p); + } + + ~TriEdgeCollapse() + {} + +private: + +///Return the aspect Ratio media of the tetrahedrons +///that share the adge to collapse +ScalarType _AspectRatioMedia(PosType p) +{ + /* PosLType posl=PosLType(p.T(),p.F(),p.E(),p.V()); + posl.Reset(); + int num=0; + ScalarType ratio_media=0.f; + while(!posl.LoopEnd()) + { + ratio_media+=posl.T()->AspectRatio(); + posl.NextT(); + num++; + } + ratio_media=ratio_media/num; + return (ratio_media);*/ +} + + +///Modify pos and alfa to obtain the collapse that minimize the error +ScalarType _VolumePreservingError(PosType &pos,CoordType &new_point,int nsteps) +{ + //VertexType *ve0=(pos.T()->V(Tetra::VofE(pos.E(),0))); + //VertexType *ve1=(pos.T()->V(Tetra::VofE(pos.E(),1))); + //vrem =ve0; + //bool ext_v0=ve0->IsB(); + //bool ext_v1=ve1->IsB(); + + //ScalarType best_error=0.f; + // if ((ext_v0)&&(!ext_v1)) + // new_point=ve0->P(); + // else + // if ((!ext_v0)&&(ext_v1)) + // new_point=ve1->P(); + // else + // if ((!ext_v0)&&(!ext_v1)) + // new_point=(ve0->P()+ve1->P())/2.f; + // else + // if ((ext_v0)&&(ext_v1))//both are external vertex + // { + // ScalarType step=1.f/(nsteps-1); + // ScalarType Vol_Original=_EC.VolumeOriginal(); + // for (int i=0;iP()*alfatemp) +(ve1->P()*(1.f-alfatemp)); + // //the error is the absolute value of difference of volumes + // ScalarType error=fabs(Vol_Original-_EC.VolumeSimulateCollapse(pos,newPTemp)); + // if(error::HeapType & h_ret) + { + _Imark()++; + vcg::face::VFIterator VFi(pos.V(1)->VFp(),pos.V(1)->VFi()); + while (!VFi.End()) + { + for (int j=0;j<3;j++) + { + PosType p; + p.Set(VFi.f,VFi.z,VFi.f->V(VFi.z)); + h_ret.push_back(HeapElem(new TriEdgeCollapse(p,_Imark()))); + std::push_heap(h_ret.begin(),h_ret.end()); + //// update the mark of the vertices + VFi.f->V(VFi.z)->IMark() = _Imark(); + VFi.f->V( (VFi.z+1) % 3 )->IMark() = _Imark(); + } + VFi++; + } + } + + ModifierType IsOfType(){ return TriEdgeCollapseOp;} + + bool IsFeasible(){ + return (!pos.V(0)->IsS() // bruttino qui...non toccare i vertici selezionati (pro-ponchio) + && _EC.LinkConditions(pos)); + } + + bool IsUpToDate(){ + VertexType *v0=pos.V(0); + VertexType *v1=pos.V(1); + + if(! (( (!v0->IsD()) && (!v1->IsD())) && + _Imark()>=v0->IMark() && + _Imark()>=v1->IMark())) + { + FAIL::OFD(); + return false; + } + else + return true; + } + + virtual ScalarType Priority(){ +// return _priority; + } + + virtual void Init(TriMeshType&m,LocalOptimization::HeapType&h_ret){ + h_ret.clear(); + TriMeshType::FaceIterator fi; + int j; + for(fi = m.face.begin(); fi != m.face.end();++fi) + if(!(*fi).IsD()){ + for (int j=0;j<3;j++) + { + PosType p=PosType(&*fi,j,(*fi).V(j)); + h_ret.push_back(HeapElem(new TriEdgeCollapse(p,m.IMark()))); + } + } + } + +}; +}//end namespace tri +}//end namespace vcg +/// return the type of operation + //virtual ModifierType IsOfType() = 0 ; + + ///// return true if the data have not changed since it was created + //virtual bool IsUpToDate() = 0 ; + + ///// return true if no constraint disallow this operation to be performed (ex: change of topology in edge collapses) + //virtual bool IsFeasible() = 0; + + ///// Compute the priority to be used in the heap + //virtual ScalarType ComputePriority()=0; + + ///// Return the priority to be used in the heap (implement static priority) + //virtual ScalarType Priority()=0; + + ///// Compute the error caused by this modification (can be the same as priority) + //virtual ScalarType ComputeError()=0; + + + ///// Perform the operation and return the variation in the number of simplicies (>0 is refinement, <0 is simplification) + //virtual int Execute()=0; + + ///// perform initialization + //virtual void Init(MESH_TYPE&m,HeapType&)=0; + + + ///// Update the heap as a consequence of this operation + //virtual void UpdateHeap(HeapType&)=0; + +#endif \ No newline at end of file