add vcglib
This commit is contained in:
1 parent
6f6c0c8eb7
commit
af8100f851
1537 files changed
+634197
No files matched your search
@@ -0,0 +1,304 @@
|
||||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004-2016 \/)\/ *
|
||||
* 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. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __VCGLIB_LOCALOPTIMIZATION
|
||||
#define __VCGLIB_LOCALOPTIMIZATION
|
||||
#include <vcg/complex/complex.h>
|
||||
#include <time.h>
|
||||
namespace vcg{
|
||||
// Base class for Parameters
|
||||
// all parameters must be derived from this.
|
||||
class BaseParameterClass { };
|
||||
|
||||
template<class MeshType>
|
||||
class LocalOptimization;
|
||||
|
||||
enum ModifierType{ TetraEdgeCollapseOp, TriEdgeSwapOp, TriVertexSplitOp,
|
||||
TriEdgeCollapseOp,TetraEdgeSpliOpt,TetraEdgeSwapOp, TriEdgeFlipOp,
|
||||
QuadDiagCollapseOp, QuadEdgeCollapseOp};
|
||||
/** \addtogroup tetramesh */
|
||||
/*@{*/
|
||||
/// This abstract class define which functions a local modification class must have to be used in the LocalOptimization framework.
|
||||
template <class MeshType>
|
||||
class LocalModification
|
||||
{
|
||||
public:
|
||||
typedef typename LocalOptimization<MeshType>::HeapType HeapType;
|
||||
typedef typename MeshType::ScalarType ScalarType;
|
||||
|
||||
inline LocalModification(){}
|
||||
virtual ~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() const = 0 ;
|
||||
|
||||
/// return true if no constraint disallow this operation to be performed (ex: change of topology in edge collapses)
|
||||
virtual bool IsFeasible(BaseParameterClass *pp) = 0;
|
||||
|
||||
/// Compute the priority to be used in the heap
|
||||
virtual ScalarType ComputePriority(BaseParameterClass *pp)=0;
|
||||
|
||||
/// Return the priority to be used in the heap (implement static priority)
|
||||
virtual ScalarType Priority() const =0;
|
||||
|
||||
/// Perform the operation
|
||||
virtual void Execute(MeshType &m, BaseParameterClass *pp)=0;
|
||||
|
||||
/// perform initialization
|
||||
static void Init(MeshType &m, HeapType&, BaseParameterClass *pp);
|
||||
|
||||
/// An approximation of the size of the heap with respect of the number of simplex
|
||||
/// of the mesh. When this number is exceeded a clear heap purging is performed.
|
||||
/// so it is should be reasonably larger than the minimum expected size to avoid too frequent clear heap
|
||||
/// For example for symmetric edge collapse a 5 is a good guess.
|
||||
/// while for non symmetric edge collapse a larger number like 9 is a better choice
|
||||
static float HeapSimplexRatio(BaseParameterClass *) {return 6.0f;}
|
||||
|
||||
virtual const char *Info(MeshType &) {return 0;}
|
||||
/// Update the heap as a consequence of this operation
|
||||
virtual void UpdateHeap(HeapType&, BaseParameterClass *pp)=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: in order 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 MeshType>
|
||||
class LocalOptimization
|
||||
{
|
||||
public:
|
||||
LocalOptimization(MeshType &mm, BaseParameterClass *_pp): m(mm){ ClearTermination();HeapSimplexRatio=5; pp=_pp;}
|
||||
|
||||
struct HeapElem;
|
||||
typedef typename MeshType::ScalarType ScalarType;
|
||||
typedef typename std::vector<HeapElem> HeapType;
|
||||
typedef LocalModification <MeshType> LocModType;
|
||||
|
||||
/// termination conditions
|
||||
enum LOTermination {
|
||||
LOnSimplices = 0x01, // test number of simplicies
|
||||
LOnVertices = 0x02, // test number of verticies
|
||||
LOnOps = 0x04, // test number of operations
|
||||
LOMetric = 0x08, // test Metric (error, quality...instance dependent)
|
||||
LOTime = 0x10 // test how much time is passed since the start
|
||||
} ;
|
||||
|
||||
int tf; // Termination Flag
|
||||
|
||||
int nPerformedOps,
|
||||
nTargetOps,
|
||||
nTargetSimplices,
|
||||
nTargetVertices;
|
||||
|
||||
float timeBudget;
|
||||
clock_t start;
|
||||
ScalarType currMetric;
|
||||
ScalarType targetMetric;
|
||||
BaseParameterClass *pp;
|
||||
|
||||
// The ratio between Heap size and the number of simplices in the current mesh
|
||||
// When this value is exceeded a ClearHeap Start;
|
||||
|
||||
float HeapSimplexRatio;
|
||||
|
||||
void SetTerminationFlag (int v){tf |= v;}
|
||||
void ClearTerminationFlag (int v){tf &= ~v;}
|
||||
bool IsTerminationFlag (int v){return ((tf & v)!=0);}
|
||||
|
||||
void SetTargetSimplices (int ts ){nTargetSimplices = ts; SetTerminationFlag(LOnSimplices); }
|
||||
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;
|
||||
|
||||
///the heap of operations
|
||||
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
|
||||
{
|
||||
inline HeapElem(){locModPtr = NULL;}
|
||||
~HeapElem(){}
|
||||
|
||||
///pointer to instance of local modifier
|
||||
LocModType *locModPtr;
|
||||
float pri;
|
||||
|
||||
inline HeapElem( LocModType *_locModPtr)
|
||||
{
|
||||
locModPtr = _locModPtr;
|
||||
pri=float(locModPtr->Priority());
|
||||
}
|
||||
|
||||
/// STL heap has the largest element as the first one.
|
||||
/// usually we mean priority as an error so we should invert the comparison
|
||||
inline bool operator <(const HeapElem & h) const
|
||||
{
|
||||
return (pri > h.pri);
|
||||
//return (locModPtr->Priority() < h.locModPtr->Priority());
|
||||
}
|
||||
|
||||
bool IsUpToDate() const
|
||||
{
|
||||
return locModPtr->IsUpToDate();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Default distructor
|
||||
~LocalOptimization(){
|
||||
typename HeapType::iterator i;
|
||||
for(i = h.begin(); i != h.end(); i++)
|
||||
delete (*i).locModPtr;
|
||||
}
|
||||
|
||||
/// main cycle of optimization
|
||||
bool DoOptimization()
|
||||
{
|
||||
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));
|
||||
|
||||
start=clock();
|
||||
nPerformedOps =0;
|
||||
while( !GoalReached() && !h.empty())
|
||||
{
|
||||
if(h.size()> m.SimplexNumber()*HeapSimplexRatio ) ClearHeap();
|
||||
std::pop_heap(h.begin(),h.end());
|
||||
LocModType *locMod = h.back().locModPtr;
|
||||
currMetric=h.back().pri;
|
||||
h.pop_back();
|
||||
|
||||
if( locMod->IsUpToDate() )
|
||||
{
|
||||
//printf("popped out: %s\n",locMod->Info(m));
|
||||
if (locMod->IsFeasible(this->pp))
|
||||
{
|
||||
nPerformedOps++;
|
||||
locMod->Execute(m,this->pp);
|
||||
locMod->UpdateHeap(h,this->pp);
|
||||
}
|
||||
}
|
||||
delete locMod;
|
||||
}
|
||||
return !(h.empty());
|
||||
}
|
||||
|
||||
// It removes from the heap all the operations that are no more 'uptodate'
|
||||
// (e.g. collapses that have some recently modified vertices)
|
||||
// This function is called from time to time by the doOptimization (e.g. when the heap is larger than fn*3)
|
||||
void ClearHeap()
|
||||
{
|
||||
// int sz=h.size(); int t0=clock();
|
||||
for(auto hi=h.begin();hi!=h.end();)
|
||||
{
|
||||
if(!(*hi).locModPtr->IsUpToDate())
|
||||
{
|
||||
delete (*hi).locModPtr;
|
||||
*hi=h.back();
|
||||
if(&*hi==&h.back())
|
||||
{
|
||||
hi=h.end();
|
||||
h.pop_back();
|
||||
break;
|
||||
}
|
||||
h.pop_back();
|
||||
continue;
|
||||
}
|
||||
++hi;
|
||||
}
|
||||
// printf("\nReduced heap from %7i to %7i (fn %7i) in %7.2f \n",sz,h.size(),m.fn,float(clock()-t0)/CLOCKS_PER_SEC);
|
||||
make_heap(h.begin(),h.end());
|
||||
}
|
||||
|
||||
///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.
|
||||
template <class LocalModificationType> void Init()
|
||||
{
|
||||
vcg::tri::InitVertexIMark(m);
|
||||
|
||||
// The expected size of heap depends on the type of the local modification we are using..
|
||||
HeapSimplexRatio = LocalModificationType::HeapSimplexRatio(pp);
|
||||
|
||||
LocalModificationType::Init(m,h,pp);
|
||||
std::make_heap(h.begin(),h.end());
|
||||
if(!h.empty()) currMetric=h.front().pri;
|
||||
}
|
||||
|
||||
|
||||
template <class LocalModificationType> void Finalize()
|
||||
{
|
||||
LocalModificationType::Finalize(m,h,pp);
|
||||
}
|
||||
|
||||
|
||||
/// 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(){
|
||||
if ( IsTerminationFlag(LOnSimplices) && ( m.SimplexNumber()<= nTargetSimplices)) return true;
|
||||
if ( IsTerminationFlag(LOnVertices) && ( m.VertexNumber() <= nTargetVertices)) return true;
|
||||
if ( IsTerminationFlag(LOnOps) && (nPerformedOps == nTargetOps)) return true;
|
||||
if ( IsTerminationFlag(LOMetric) && ( currMetric > targetMetric)) return true;
|
||||
if ( IsTerminationFlag(LOTime) )
|
||||
{
|
||||
clock_t cur = clock();
|
||||
if(cur<start) // overflow of tick counter;
|
||||
return true; // panic
|
||||
else
|
||||
if ( (cur - start)/(double)CLOCKS_PER_SEC > timeBudget) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};//end class decimation
|
||||
|
||||
}//end namespace
|
||||
#endif
|
||||
Reference in new issue
Block a user