From 3cbbebedb7d5aff764ef15ca2179c8f6cc3e8f5d Mon Sep 17 00:00:00 2001 From: cignoni Date: Tue, 27 Jul 2004 09:46:15 +0000 Subject: [PATCH] First working version of the LocalOptimization/Simplification Framework --- vcg/complex/local_optimization.h | 145 ++++++---- vcg/complex/local_optimization/base.h | 266 ------------------ .../local_optimization/tri_edge_collapse.h | 216 +++++--------- vcg/complex/trimesh/edge_collapse.h | 147 +--------- 4 files changed, 157 insertions(+), 617 deletions(-) delete mode 100644 vcg/complex/local_optimization/base.h diff --git a/vcg/complex/local_optimization.h b/vcg/complex/local_optimization.h index dec133c9..6ce8d214 100644 --- a/vcg/complex/local_optimization.h +++ b/vcg/complex/local_optimization.h @@ -22,6 +22,12 @@ ****************************************************************************/ /**************************************************************************** $Log: not supported by cvs2svn $ + Revision 1.1 2004/07/15 12:04:14 ganovelli + minor changes + + Revision 1.2 2004/07/09 10:22:56 ganovelli + working draft + Revision 1.1 2004/07/08 08:25:15 ganovelli first draft @@ -35,14 +41,20 @@ #include namespace vcg{ -enum ModifierType{ TriEdgeCollapse, TriEdgeSwap, TriVertexSplit, - TetraEdgeCollapse,TetraEdgeSplit,TetraEdgeSwap}; +template +class LocalOptimization; + +enum ModifierType{ TetraEdgeCollapseOp, TriEdgeSwapOp, TriVertexSplitOp, + TriEdgeCollapseOp,TetraEdgeSpliOpt,TetraEdgeSwapOp}; +/** \addtogroup tetramesh */ /*@{*/ -/// This is an abstract class to define the interface of a local modification -template +/// This abstract class define which functions a local modification to be used in the LocalOptimization. +template class LocalModification { + typedef typename LocalOptimization::HeapType HeapType; + typedef typename MeshType::ScalarType ScalarType; public: LocalModification(){}; @@ -61,30 +73,32 @@ class LocalModification 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; - + virtual ScalarType Priority() const =0; /// Perform the operation and return the variation in the number of simplicies (>0 is refinement, <0 is simplification) - virtual int Execute()=0; + virtual void Execute(MeshType &m)=0; /// perform initialization - virtual void Init(MESH_TYPE&m,HeapType&)=0; - + static void Init(MeshType &m, HeapType&); + virtual const char *Info(MeshType &) {return 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(){} + LocalOptimization(MeshType &mm): m(mm){ ClearTermination();} struct HeapElem; // scalar type @@ -92,22 +106,24 @@ public: // type of the heap typedef typename std::vector HeapType; // modification type - typedef LocalModification LocModType; + typedef LocalModification LocModType; // modification Pointer type - typedef LocalModification * LocModPtrType; + typedef LocalModification * LocModPtrType; /// termination conditions - enum { LOnSimplices = 0x00, // test number of simplicies + enum LOTermination { + 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, + int tf; + + int nPerfmormedOps, nTargetOps, nTargetSimplices, nTargetVertices; @@ -122,14 +138,23 @@ public: bool IsTerminationFlag (int v){return (tf & v);} void SetTargetSimplices (int ts ){nTargetSimplices = ts; SetTerminationFlag(LOnSimplices); } - void SetTargetVertices (int tv ){nTargetSimplices = tv; SetTerminationFlag(LOnVertices); } + void SetTargetVertices (int tv ){nTargetVertices = 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); } - + void ClearTermination() + { + tf=0; + nTargetSimplices=0; + nTargetOps=0; + targetMetric=0; + timeBudget=0; + nTargetVertices=0; + } /// the mesh to optimize - MeshType * m; + MeshType & m; @@ -137,6 +162,10 @@ public: HeapType h; ///the element of the heap + // it is just a wrapper of the pointer to the localMod. + // std heap does not work for + // pointers and we want pointers to have heterogenous heaps. + struct HeapElem { HeapElem(){locModPtr = NULL;} @@ -151,10 +180,12 @@ public: locModPtr = _locModPtr; }; + /// STL heap has the largest element as the first one. + /// usually we mean priority as an error so we should invert the comparison const bool operator <(const HeapElem & h) const { - return (locModPtr->Priority()Priority()); - } + return (locModPtr->Priority() > h.locModPtr->Priority()); + } bool IsUpToDate() { @@ -170,47 +201,43 @@ public: ~LocalOptimization(){}; /// main cycle of optimization - void DoOptimization() + bool DoOptimization() { + start=clock(); nPerfmormedOps =0; - int i=0; - while( !GoalReached()) - {int size = h.size(); - LocModPtrType locMod = h.back().locModPtr; - if( ! h.back().IsUpToDate()) - { - h.pop_back(); // if it is out of date simply discard it - } - else - { - locMod->ComputeError(); - h.pop_back(); - // check if it is feasible - if (locMod->IsFeasible()) - { - nPerfmormedOps++; - int tmp = locMod->Execute(); - m->SimplexNumber()+= tmp; - locMod->UpdateHeap(h); - m->VertexNumber()--; + 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() ) + { + //printf("popped out: %s\n",locMod->Info(m)); + // check if it is feasible + if (locMod->IsFeasible()) + { + nPerfmormedOps++; + locMod->Execute(m); + locMod->UpdateHeap(h); + } } - + //else printf("popped out unfeasible\n"); + delete locMod; } - 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() + template void Init() { - m->InitIMark(); - if(!h.empty()) - { - (*h.begin()).locModPtr->Init(*m,h); - } + m.InitVertexIMark(); + LocalModificationType::Init(m,h); + std::make_heap(h.begin(),h.end()); } @@ -225,13 +252,11 @@ public: assert ( ( ( tf & LOMetric )==0) || ( targetMetric != -1)); assert ( ( ( tf & LOTime )==0) || ( timeBudget != -1)); - if(h.empty()) return true; - - 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; + if ( IsTerminationFlag(LOnSimplices) && ( m.SimplexNumber()< nTargetSimplices)) return true; + if ( IsTerminationFlag(LOnVertices) && ( m.VertexNumber() < nTargetVertices)) return true; + if ( IsTerminationFlag(LOnOps) && (nPerfmormedOps == nTargetOps)) return true; + if ( IsTerminationFlag(LOMetric) && ( currMetric > targetMetric)) return true; + if ( IsTerminationFlag(LOTime) && ( (clock()-start)/(float)CLOCKS_PER_SEC > timeBudget)) return true; return false; } diff --git a/vcg/complex/local_optimization/base.h b/vcg/complex/local_optimization/base.h deleted file mode 100644 index c1238dbe..00000000 --- a/vcg/complex/local_optimization/base.h +++ /dev/null @@ -1,266 +0,0 @@ -/**************************************************************************** -* 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/tri_edge_collapse.h b/vcg/complex/local_optimization/tri_edge_collapse.h index 2d219b0a..12452e2c 100644 --- a/vcg/complex/local_optimization/tri_edge_collapse.h +++ b/vcg/complex/local_optimization/tri_edge_collapse.h @@ -29,17 +29,8 @@ #include #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{ @@ -51,40 +42,42 @@ namespace tri{ /// 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 +template +class TriEdgeCollapse: public LocalOptimization::LocModType , public EdgeCollapse { - - /// 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: +public: + /// static data to gather statistical information about the reasons of collapse failures + struct FailStat { + static int &Volume() {static int vol=0; return vol;} + static int &LinkConditionFace(){static int lkf=0; return lkf;} + static int &LinkConditionEdge(){static int lke=0; return lke;} + static int &LinkConditionVert(){static int lkv=0; return lkv;} + static int &OutOfDate() {static int ofd=0; return ofd;} + static int &Border() {static int bor=0; return bor;} + static Init() + { + Volume() =0; + LinkConditionFace()=0; + LinkConditionEdge()=0; + LinkConditionVert()=0; + OutOfDate() =0; + Border() =0; + } +}; + + typedef typename TriMeshType::FaceType FaceType; + typedef typename FaceType::VertexType VertexType; + typedef typename FaceType::VertexType::CoordType CoordType; + typedef typename TriMeshType::VertexType::ScalarType ScalarType; + typedef vcg::face::Pos PosType; + 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; @@ -94,11 +87,11 @@ class TriEdgeCollapse: public LocalOptimization::LocModType {} ///Constructor with postype - TriEdgeCollapse(PosType p,int mark) + TriEdgeCollapse(PosType p, int mark) { _Imark() = mark; pos=p; - _priority = _AspectRatioMedia(p); + _priority = ComputePriority(); } ~TriEdgeCollapse() @@ -106,90 +99,32 @@ class TriEdgeCollapse: public LocalOptimization::LocModType 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(errorP(),pos.VFlip()->P()); + return _priority; } - ScalarType ComputeError() - { - return 0; + virtual const char *Info(TriMeshType &m) { + static char buf[60]; + sprintf(buf,"collapse %i -> %i %f\n", pos.V()-&m.vert[0], pos.VFlip()-&m.vert[0],_priority); + return buf; } - - int Execute() - { - _EC.FindSets(pos); - return -_EC.DoCollapse(pos,_NewPoint); - // _EC.FindSets(pos); - // return -_EC.DoCollapse(pos,_NewPoint); + + void Execute(TriMeshType &m) + { + CoordType MidPoint=(pos.V()->P()+pos.VFlip()->P())/2.0; + int FaceDel=DoCollapse(pos, MidPoint); + m.fn-=FaceDel; + --m.vn; } - void UpdateHeap(typename LocalOptimization::HeapType & h_ret) + void UpdateHeap(typename LocalOptimization::HeapType & h_ret) { _Imark()++; vcg::face::VFIterator VFi(pos.V(1)->VFp(),pos.V(1)->VFi()); @@ -212,40 +147,47 @@ public: ModifierType IsOfType(){ return TriEdgeCollapseOp;} bool IsFeasible(){ - return (!pos.V(0)->IsS() // bruttino qui...non toccare i vertici selezionati (pro-ponchio) - && _EC.LinkConditions(pos)); + return LinkConditions(pos); } bool IsUpToDate(){ - VertexType *v0=pos.V(0); - VertexType *v1=pos.V(1); + if(pos.f->IsD()) { + ++FailStat::OutOfDate(); + return false; + } + + if(pos.v->IsD()) { + ++FailStat::OutOfDate(); + return false; + } + + VertexType *v0=pos.V(); + VertexType *v1=pos.VFlip(); if(! (( (!v0->IsD()) && (!v1->IsD())) && _Imark()>=v0->IMark() && _Imark()>=v1->IMark())) { - FAIL::OFD(); + ++FailStat::OutOfDate(); return false; } - else return true; } - virtual ScalarType Priority(){ -// return _priority; -return 0; + virtual ScalarType Priority() const { + return _priority; } - virtual void Init(TriMeshType&m,typename LocalOptimization::HeapType&h_ret){ + static void Init(TriMeshType&m,typename 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()))); + //printf("Inserting in heap coll %3i ->%3i %f\n",p.V()-&m.vert[0],p.VFlip()-&m.vert[0],h_ret.back().locModPtr->Priority()); } } } @@ -253,33 +195,5 @@ return 0; }; }//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 diff --git a/vcg/complex/trimesh/edge_collapse.h b/vcg/complex/trimesh/edge_collapse.h index 50f92aea..0029ae64 100644 --- a/vcg/complex/trimesh/edge_collapse.h +++ b/vcg/complex/trimesh/edge_collapse.h @@ -102,140 +102,6 @@ class EdgeCollapse }; -std::map EdgeMark; - -void orMark(Edge E,char M) -{ - map::Iterator EI; - EdgeMark.find(E); - if (EI==EdgeMArk.end()) - EdgeMark.insert (Pair(E,M)); - else - (*EI).second()|=M; -} - -bool isMarked(Edge E,char M) -{ - map::Iterator EI; - EdgeMark.find(E); - if (EI==EdgeMArk.end()) - return false; - else return ((*EI).second()&M); -} - -///control link conditions for the collapse -//bool LinkCondition(vcg::face::Pos pos) -//{ -// const int LINK_V0 = VertexType::NewBitFlag(); -// const int LINK_V1 = VertexType::NewBitFlag(); -// const int LINK_EE = VertexType::NewBitFlag(); -// -// const int NOT_LINKED = ~(LINK_V0 | LINK_V1 | LINK_EE); -// -// VertexType *ve0=pos.f->V(pos.z); -// VertexType *ve1=pos.f->V((pos.z+1)%3); -// int edge =pos.z; -// -// VFIterator vf0(ve0->VFb(),ve0->VFi()); -// // Clear visited and adj flag for all vertices adj to v0; -// while (!vf0.End()) -// { -// vf0.f->V(0)->Flags() &= NOT_LINKED; -// vf0.f->V(1)->Flags() &= NOT_LINKED; -// vf0.f->V(2)->Flags() &= NOT_LINKED; -// vf0++; -// } -// -// VFIterator vf1(ve1->VFb(),ve1->VFi()); -// // Clear visited and adj flag for all vertices adj to v0; -// while (!vf1.End()) -// { -// vf1.f->V(0)->Flags() &= NOT_LINKED; -// vf1.f->V(1)->Flags() &= NOT_LINKED; -// vf1.f->V(2)->Flags() &= NOT_LINKED; -// vf1++; -// } -// -// vf0.f=ve0->VFb(); -// vf0.f=ve0->VFi(); -// // Mark vertices of v0 -// while (!vf0.End()) -// { -// vf0.f->V(0)->Flags() |= (LINK_V0); -// vf0.f->V(1)->Flags() |= (LINK_V0); -// vf0.f->V(2)->Flags() |= (LINK_V0); -// orMark(Edge(vf0.f->V(0),vf0.f->V(1)),LINK_V0); -// orMark(Edge(vf0.f->V(1),vf0.f->V(2)),LINK_V0); -// orMark(Edge(vf0.f->V(2),vf0.f->V(0)),LINK_V0); -// vf0++; -// } -// -// //mark the entities on the edge -// VertexType* vt0=pos.f->V(edge); -// VertexType* vt1=pos.f->V((edge+1)%3); -// VertexType* vt2=pos.f->V((edge+2)%3); -// -// vt0->Flags() |= (LINK_EE); -// vt1->Flags() |= (LINK_EE); -// vt2->Flags() |= (LINK_EE); -// -// -// FaceType *opp=pos.f()->FFp(edge); -// int eopp=pos.f()->FFi(edge); -// -// VertexType* vt3=opp.f->V((eopp+2)%3); -// vt3->Flags() |= LINK_EE; -// -// //mark the edges -// orMark(Edge(vt0,vt1),LINK_EE); -// orMark(Edge(vt0,vt2),LINK_EE); -// orMark(Edge(vt1,vt2),LINK_EE); -// orMark(Edge(vt0,vt3),LINK_EE); -// orMark(Edge(vt1,vt3),LINK_EE); -// -// //and at the end I verify if the intersection is equal to the star of the edge -// vf1.f=ve1->VFb(); -// vf1.f=ve1->VFi(); -// bool correct=true; -// while (!vf1.End()) -// { -// vt0=vf1.f->V(0); -// vt1=vf1.f->V(1); -// vt2=vf1.f->V(2); -// -// if ((vt0->Flags()& LINK_V0)&&(!(vt0->Flags()& LINK_EE))) -// correct=false; -// else -// if ((vt1->Flags()& LINK_V0)&&(!(vt1->Flags()& LINK_EE))) -// correct=false; -// else -// if ((vt2->Flags()& LINK_V0)&&(!(vt2->Flags()& LINK_EE))) -// correct=false; -// else -// if ((isMarked(Edge(v0,v1),LINK_V0))&&(!isMarked(Edge(v0,v1),LINK_EE))) -// correct=false; -// else -// if ((isMarked(Edge(v1,v2),LINK_V0))&&(!isMarked(Edge(v1,v2),LINK_EE))) -// correct=false; -// else -// if ((isMarked(Edge(v2,v0),LINK_V0))&&(!isMarked(Edge(v2,v0),LINK_EE))) -// correct=false; -// -// if (!correct) -// { -// VertexType::DeleteBitFlag(LINK_V0); -// VertexType::DeleteBitFlag(LINK_V1); -// VertexType::DeleteBitFlag(LINK_EE); -// return (false) -// } -// vf1++; -// } -// return true; -// VertexType::DeleteBitFlag(LINK_V0); -// VertexType::DeleteBitFlag(LINK_V1); -// VertexType::DeleteBitFlag(LINK_EE); -// } - static VFIVec & AV0(){static VFIVec av0; return av0;} static VFIVec & AV1(){static VFIVec av1; return av1;} static VFIVec & AV01(){static VFIVec av01; return av01;} @@ -252,7 +118,7 @@ bool isMarked(Edge E,char M) VFI x; - for( x.f = v0->VFp(), x.z = v0->VFi(); x.f!=0; x++) + for( x.f = v0->VFp(), x.z = v0->VFi(); x.f!=0; ++x) { int zv1 = -1; @@ -266,7 +132,7 @@ bool isMarked(Edge E,char M) else AV01().push_back( x ); } - for( x.f = v1->VFp(), x.z = v1->VFi(); x.f!=0; x++ ) + for( x.f = v1->VFp(), x.z = v1->VFi(); x.f!=0; ++x ) { int zv0 = -1; @@ -292,17 +158,17 @@ bool isMarked(Edge E,char M) //EdgePosB x; vcg::face::VFIterator x; // Clear visited and adj flag for all vertices adj to v0; - for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; x++ ) { + for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; ++x ) { x.f->V1(x.z)->Flags() &= NOTALLADJ; x.f->V2(x.z)->Flags() &= NOTALLADJ; } // Clear visited flag for all vertices adj to v1 and set them adj1 to v1; - for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; x++ ) { + for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; ++x ) { x.f->V1(x.z)->Flags() &= NOTALLADJ1; x.f->V2(x.z)->Flags() &= NOTALLADJ1; } // Mark vertices adj to v1 as ADJ_1 and adj1 to v1; - for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; x++ ) { + for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; ++x ) { if(x.f->V1(x.z)==pos.V(0)) x.f->V2(x.z)->Flags() |= ADJ_E | ADJ_1; else x.f->V2(x.z)->Flags() |= ADJ_1; if(x.f->V2(x.z)==pos.V(0)) x.f->V1(x.z)->Flags() |= ADJ_E | ADJ_1; @@ -312,7 +178,7 @@ bool isMarked(Edge E,char M) // compute the number of: int adj01=0; // vertices adjacents to both v0 and v1 int adje=0; // vertices adjacents to an egde (usually 2) - for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; x++ ) { + for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; ++x ) { if(!x.f->V1(x.z)->IsV()) { x.f->V1(x.z)->SetV(); if(x.f->V1(x.z)->Flags()&ADJ_1) ++adj01; @@ -337,6 +203,7 @@ bool isMarked(Edge E,char M) int DoCollapse(PosType & c, Point3 p) { + FindSets(c); VFIVec::iterator i; int n_face_del =0 ;