From c15f2fb66c3cdf1652e80f98bb7b6dec3fb2bbf3 Mon Sep 17 00:00:00 2001 From: ganovelli Date: Thu, 15 Jul 2004 12:04:14 +0000 Subject: [PATCH] minor changes --- vcg/complex/local_optimization/base.h | 266 ++++++++++++++++++ .../local_optimization/tetra_edge_collapse.h | 261 +++++++++++++++++ .../local_optimization/tri_edge_collapse.h | 8 +- vcg/simplex/face/base.h | 5 +- vcg/simplex/face/pos.h | 14 +- vcg/simplex/face/topology.h | 4 +- 6 files changed, 548 insertions(+), 10 deletions(-) create mode 100644 vcg/complex/local_optimization/base.h create mode 100644 vcg/complex/local_optimization/tetra_edge_collapse.h diff --git a/vcg/complex/local_optimization/base.h b/vcg/complex/local_optimization/base.h new file mode 100644 index 00000000..c1238dbe --- /dev/null +++ b/vcg/complex/local_optimization/base.h @@ -0,0 +1,266 @@ +/**************************************************************************** +* 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. * +* * +****************************************************************************/ +/**************************************************************************** + $Log: not supported by cvs2svn $ + Revision 1.2 2004/07/09 10:22:56 ganovelli + working draft + + Revision 1.1 2004/07/08 08:25:15 ganovelli + first draft + +****************************************************************************/ + +#ifndef __VCGLIB_LOCALOPTIMIZATION +#define __VCGLIB_LOCALOPTIMIZATION +#include +#include +#include +#include + +namespace vcg{ +enum ModifierType{ TetraEdgeCollapseOp, TriEdgeSwapOp, TriVertexSplitOp, + TriEdgeCollapseOp,TetraEdgeSpliOpt,TetraEdgeSwapOp}; +/** \addtogroup tetramesh */ +/*@{*/ +/// This abstract class define which functions a local modification to be used in the LocalOptimization. +template +class LocalModification +{ + + public: + LocalModification(){}; + ~LocalModification(){}; + + /// 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; +}; //end class local modification + + +/// LocalOptimization: +/// This class implements the algorihms running on 0-1-2-3-simplicial complex that are based on local modification +/// THe local modification can be and edge_collpase, or an edge_swap, a vertex plit...as far as they implement +/// the interface defined in LocalModification. +/// Implementation note: i norder to keep the local modification itself indepented by its use in this class, they are not +/// really derived by LocalModification. INstead, a wrapper is done to this purpose (see vcg/complex/tetramesh/decimation/collapse.h) + +template +class LocalOptimization +{ +public: + LocalOptimization(){} + + struct HeapElem; + // scalar type + typedef typename MeshType::ScalarType ScalarType; + // type of the heap + typedef typename std::vector HeapType; + // modification type + typedef LocalModification LocModType; + // modification Pointer type + typedef LocalModification * LocModPtrType; + + + + /// termination conditions + enum { LOnSimplices = 0x00, // test number of simplicies + LOnVertices = 0x01, // test number of verticies + LOnOps = 0x02, // test number of operations + LOMetric = 0x04, // test Metric (error, quality...instance dependent) + LOTime = 0x08 // test how much time is passed since the start + } ; + + int tf; + int nPerfmormedOps, + nTargetOps, + nTargetSimplices, + nTargetVertices; + + float timeBudget, + start, + currMetric, + targetMetric; + + void SetTerminationFlag (int v){tf |= v;} + void ClearTerminationFlag (int v){tf &= ~v;} + bool IsTerminationFlag (int v){return (tf & v);} + + void SetTargetSimplices (int ts ){nTargetSimplices = ts; SetTerminationFlag(LOnSimplices); } + void SetTargetVertices (int tv ){nTargetSimplices = tv; SetTerminationFlag(LOnVertices); } + void SetTargetOperations(int to ){nTargetOps = to; SetTerminationFlag(LOnOps); } + + void SetTargetMetric (ScalarType tm ){targetMetric = tm; SetTerminationFlag(LOMetric); } + void SetTimeBudget (float tb ){timeBudget = tb; SetTerminationFlag(LOTime); } + + + /// the mesh to optimize + MeshType * m; + + + + ///the heap of operations + HeapType h; + + ///the element of the heap + struct HeapElem + { + HeapElem(){locModPtr = NULL;} + ~HeapElem(){} + + ///pointer to instance of local modifier + LocModPtrType locModPtr; + + + HeapElem( LocModPtrType _locModPtr) + { + locModPtr = _locModPtr; + }; + + const bool operator <(const HeapElem & h) const + { + return (locModPtr->Priority()Priority()); + } + + bool IsUpToDate() + { + return locModPtr->IsUpToDate(); + } + }; + + + + /// Default Constructor + LocalOptimization(MeshType *_m):m(_m){}; + /// Default distructor + ~LocalOptimization(){}; + + /// main cycle of optimization + bool DoOptimization() + { + nPerfmormedOps =0; + int i=0; + while( !GoalReached() && !h.empty()) + {int size = h.size(); + std::pop_heap(h.begin(),h.end()); + LocModPtrType locMod = h.back().locModPtr; + h.pop_back(); + + if( locMod->IsUpToDate() ) + { + locMod->ComputeError(); + // check if it is feasible + if (locMod->IsFeasible()) + { + nPerfmormedOps++; + int tmp = locMod->Execute(); + m->SimplexNumber()+= tmp; + locMod->UpdateHeap(h); + m->VertexNumber()--; + } + } + delete locMod; + } + return !(h.empty()); + } + + ///initialize for all vertex the temporary mark must call only at the start of decimation + ///by default it takes the first element in the heap and calls Init (static funcion) of that type + ///of local modification. + void Init() + { + m->InitVertexIMark(); + if(!h.empty()) + { + HeapElem el = h.back(); + h.clear(); + el.locModPtr->Init(*m,h); + } + std::make_heap(h.begin(),h.end()); + } + + + + + /// say if the process is to end or not: the process ends when any of the termination conditions is verified + /// override this function to implemetn other tests + bool GoalReached(){ + assert ( ( ( tf & LOnSimplices )==0) || ( nTargetSimplices!= -1)); + assert ( ( ( tf & LOnVertices )==0) || ( nTargetVertices != -1)); + assert ( ( ( tf & LOnOps )==0) || ( nTargetOps != -1)); + assert ( ( ( tf & LOMetric )==0) || ( targetMetric != -1)); + assert ( ( ( tf & LOTime )==0) || ( timeBudget != -1)); + + if ( ( tf & LOnSimplices) && ( m->SimplexNumber()< nTargetSimplices)) return true; + if ( ( tf & LOnVertices) && ( m->VertexNumber() < nTargetVertices)) return true; + if ( ( tf & LOnOps) && ( nPerfmormedOps == nTargetOps)) return true; + if ( ( tf & LOMetric) && ( currMetric > targetMetric)) return true; + if ( ( tf & LOTime) && ( (clock()-start)/(float)CLOCKS_PER_SEC > timeBudget)) return true; + return false; + } + + + +///erase from the heap the operations that are out of date + void ClearHeap() + { + typename HeapType::iterator hi; + for(hi=h.begin();hi!=h.end();++hi) + if(!(*hi).locModPtr->IsUpToDate()) + { + *hi=h.back(); + h.pop_back(); + if(hi==h.end()) break; + } + //printf("\nReduced heap from %i to %i",sz,h.size()); + make_heap(h.begin(),h.end()); + } + +};//end class decimation + +}//end namespace +#endif diff --git a/vcg/complex/local_optimization/tetra_edge_collapse.h b/vcg/complex/local_optimization/tetra_edge_collapse.h new file mode 100644 index 00000000..ee01fc20 --- /dev/null +++ b/vcg/complex/local_optimization/tetra_edge_collapse.h @@ -0,0 +1,261 @@ +/**************************************************************************** +* 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_COLLAPSE +#define __VCG_DECIMATION_COLLAPSE + +#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 tetra{ + +/** \addtogroup tetramesh */ +/*@{*/ +/// 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 TriEdgeCollapser: 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 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 +vcg::tetra::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 + TriEdgeCollapser() + {} + +///Constructor with postype + TriEdgeCollapser(PosType p,int mark) + { + _Imark() = mark; + pos=p; + _priority = _AspectRatioMedia(p); + } + + ~TriEdgeCollapser() + {} + +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(errorpos)); + } + + ScalarType ComputeError() + { + _EC.FindSets(pos); + return (_VolumePreservingError(pos,_NewPoint,5));// magic number....parametrize! + } + + int Execute() + { + _EC.FindSets(pos); + return -_EC.DoCollapse(pos,_NewPoint); + } + + + void UpdateHeap(LocalOptimization::HeapType & h_ret) + { + assert(!vrem->IsD()); + _Imark()++; + VTIterator VTi(vrem->VTb(),vrem->VTi()); + while (!VTi.End()) + { + VTi.Vt()->ComputeVolume(); + + for (int j=0;j<6;j++) + { + vcg::tri::Pos p=Pos(VTi.Vt(),Tetra::FofE(j,0),j,Tetra::VofE(j,0)); + h_ret.push_back(HeapElem(new TriEdgeCollapser(p,_Imark()))); + std::push_heap(h_ret.begin(),h_ret.end()); + // update the mark of the vertices + VTi.Vt()->V(Tetra::VofE(j,0))->IMark() = _Imark(); + } + VTi++; + } + } + + ModifierType IsOfType(){ return TriEdgeCollapser;} + + bool IsFeasible(){ + vcg::tri::EdgeCollapse::Reset(); + _EC.FindSets(pos); + return(_EC.CheckPreconditions(pos,_NewPoint)); + } + + bool IsUpToDate(){ + if (!pos.T()->IsD()) + { + VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0)); + VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1)); + + if(! (( (!v0->IsD()) && (!v1->IsD())) && + _Imark()>=v0->IMark() && + _Imark()>=v1->IMark())) + { + FAIL::OFD(); + return false; + } + else + return true; + } + else + return false; + } + + virtual ScalarType Priority(){ + return _priority; + } + + virtual void Init(TriMeshType&m,LocalOptimization::HeapType&h_ret){ + h_ret.clear(); + TriMeshType::TetraIterator ti; + int j; + for(ti = m.tetra.begin(); ti != m.tetra.end();++ti) + if(!(*ti).IsD()){ + (*ti).ComputeVolume(); + for (int j=0;j<6;j++) + { + PosType p=PosType(&*ti,Tetra::FofE(j,0),j,Tetra::VofE(j,0)); + h_ret.push_back(HeapElem(new TriEdgeCollapser(p,m.IMark))); + } + } + } + +}; +}//end namespace tetra +}//end namespace vcg +#endif \ No newline at end of file diff --git a/vcg/complex/local_optimization/tri_edge_collapse.h b/vcg/complex/local_optimization/tri_edge_collapse.h index 31e79260..fac86a56 100644 --- a/vcg/complex/local_optimization/tri_edge_collapse.h +++ b/vcg/complex/local_optimization/tri_edge_collapse.h @@ -189,7 +189,7 @@ public: } - void UpdateHeap(LocalOptimization::HeapType & h_ret) + void UpdateHeap(typename LocalOptimization::HeapType & h_ret) { _Imark()++; vcg::face::VFIterator VFi(pos.V(1)->VFp(),pos.V(1)->VFi()); @@ -198,14 +198,14 @@ public: for (int j=0;j<3;j++) { PosType p; - p.Set(VFi.f,VFi.z,VFi.f->V(VFi.z)); + p.Set(VFi.F(),VFi.I(),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++; + ++VFi; } } @@ -235,7 +235,7 @@ public: // return _priority; } - virtual void Init(TriMeshType&m,LocalOptimization::HeapType&h_ret){ + virtual void Init(TriMeshType&m,typename LocalOptimization::HeapType&h_ret){ h_ret.clear(); TriMeshType::FaceIterator fi; int j; diff --git a/vcg/simplex/face/base.h b/vcg/simplex/face/base.h index add6b9c7..c3fcd6b5 100644 --- a/vcg/simplex/face/base.h +++ b/vcg/simplex/face/base.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.16 2004/07/15 11:31:59 ganovelli +minor changes + Revision 1.15 2004/07/12 12:17:09 pietroni added function NormalizedNormal @@ -100,7 +103,7 @@ public: /// The base type of the face typedef FACE_TYPE BaseFaceType; /// The base type of the face itself - typedef FACE_TYPE FaceType; + typedef FFTYPE FaceType; /// The vertex type typedef FVTYPE VertexType; /// The type of the scalar field of the vertex coordinate diff --git a/vcg/simplex/face/pos.h b/vcg/simplex/face/pos.h index d3e8eaee..1d35180d 100644 --- a/vcg/simplex/face/pos.h +++ b/vcg/simplex/face/pos.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.7 2004/07/15 11:28:44 ganovelli +basefacetype to facetype + Revision 1.6 2004/07/06 06:25:44 cignoni changed the VFIterator ++ to return a facepointer instead of a bool @@ -325,24 +328,27 @@ public: /// The vertex type typedef typename FaceType::VertexType VertexType; /// The Base face type - typedef typename FaceType::FaceType FaceType; + typedef typename FaceType VFIFaceType; /// The vector type typedef typename VertexType::CoordType CoordType; /// The scalar type typedef typename VertexType::ScalarType ScalarType; /// Pointer to the face of the half-edge - typename FaceType::FaceType *f; + VFIFaceType *f; /// Index of the vertex int z; /// Default constructor VFIterator(){} /// Constructor which associates the half-edge elementet with a face and its vertex - VFIterator(FaceType * _f, const int & _z){f = _f; z = _z;} + VFIterator(FaceType const * _f, const int & _z){f = _f; z = _z;} + + const VFIFaceType * F() const { return f;} + const int I() const { return z;} bool End() const {return f==0;} - FaceType *operator++() { + VFIFaceType *operator++() { FaceType* t = f; f = t->VFp(z); z = t->VFi(z); diff --git a/vcg/simplex/face/topology.h b/vcg/simplex/face/topology.h index 6246eb03..71b44b19 100644 --- a/vcg/simplex/face/topology.h +++ b/vcg/simplex/face/topology.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.8 2004/07/15 11:26:48 ganovelli +VFDetach corrected + Revision 1.7 2004/05/12 12:23:23 cignoni Conformed C++ syntax to GCC requirements @@ -221,7 +224,6 @@ void Swap (SwapFaceType &f, const int z ) template void VFDetach(FaceType & f, int z) { - printf("detach %d \n",&f); if(f.V(z)->VFp()==&f ) //if it is the first face detach from the begin { int fz = f.V(z)->VFi();