vcglib/vcg/complex/local_optimization.h

259 lines
7.8 KiB
C
Raw Normal View History

2004-07-08 10:25:15 +02:00
/****************************************************************************
* 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 $
2004-07-09 12:22:56 +02:00
Revision 1.1 2004/07/08 08:25:15 ganovelli
first draft
2004-07-08 10:25:15 +02:00
****************************************************************************/
#ifndef __VCGLIB_LOCALOPTIMIZATION
#define __VCGLIB_LOCALOPTIMIZATION
#include<vector>
#include<algorithm>
#include<time.h>
#include<math.h>
namespace vcg{
enum ModifierType{ TriEdgeCollapse, TriEdgeSwap, TriVertexSplit,
TetraEdgeCollapse,TetraEdgeSplit,TetraEdgeSwap};
/*@{*/
/// This is an abstract class to define the interface of a local modification
2004-07-09 12:22:56 +02:00
template <class ScalarType, class HeapType,class MESH_TYPE>
2004-07-08 10:25:15 +02:00
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;
2004-07-09 12:22:56 +02:00
/// Return the priority to be used in the heap (implement static priority)
virtual ScalarType Priority()=0;
2004-07-08 10:25:15 +02:00
/// Compute the error caused by this modification (can be the same as priority)
virtual ScalarType ComputeError()=0;
2004-07-09 12:22:56 +02:00
/// 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;
2004-07-08 10:25:15 +02:00
/// Update the heap as a consequence of this operation
virtual void UpdateHeap(HeapType&)=0;
}; //end class local modification
template<class MeshType>
class LocalOptimization
{
public:
LocalOptimization(){}
struct HeapElem;
// scalar type
typedef typename MeshType::ScalarType ScalarType;
// type of the heap
typedef typename std::vector<HeapElem> HeapType;
// modification type
2004-07-09 12:22:56 +02:00
typedef LocalModification <ScalarType, HeapType,MeshType> LocModType;
2004-07-08 10:25:15 +02:00
// modification Pointer type
2004-07-09 12:22:56 +02:00
typedef LocalModification <ScalarType, HeapType,MeshType> * LocModPtrType;
2004-07-08 10:25:15 +02:00
/// termination conditions
2004-07-09 12:22:56 +02:00
enum { LOnSimplices = 0x00, // test number of simplicies
2004-07-08 10:25:15 +02:00
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
2004-07-09 12:22:56 +02:00
} ;
int tf;
2004-07-08 10:25:15 +02:00
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
{
2004-07-09 12:22:56 +02:00
HeapElem(){locModPtr = NULL;}
~HeapElem(){}
2004-07-08 10:25:15 +02:00
///pointer to instance of local modifier
LocModPtrType locModPtr;
2004-07-09 12:22:56 +02:00
HeapElem( LocModPtrType _locModPtr)
2004-07-08 10:25:15 +02:00
{
locModPtr = _locModPtr;
};
const bool operator <(const HeapElem & h) const
{
return (locModPtr->Priority()<h.locModPtr->Priority());
}
bool IsUpToDate()
{
2004-07-09 12:22:56 +02:00
return locModPtr->IsUpToDate();
}
2004-07-08 10:25:15 +02:00
};
/// Default Constructor
2004-07-09 12:22:56 +02:00
LocalOptimization(MeshType *_m):m(_m){};
2004-07-08 10:25:15 +02:00
/// Default distructor
~LocalOptimization(){};
/// main cycle of optimization
void DoOptimization()
{
2004-07-09 12:22:56 +02:00
nPerfmormedOps =0;
2004-07-08 10:25:15 +02:00
int i=0;
while( !GoalReached())
2004-07-09 12:22:56 +02:00
{int size = h.size();
LocModPtrType locMod = h.back().locModPtr;
2004-07-08 10:25:15 +02:00
if( ! h.back().IsUpToDate())
2004-07-09 12:22:56 +02:00
{
h.pop_back(); // if it is out of date simply discard it
}
2004-07-08 10:25:15 +02:00
else
{
2004-07-09 12:22:56 +02:00
locMod->ComputeError();
2004-07-08 10:25:15 +02:00
h.pop_back();
2004-07-09 12:22:56 +02:00
// check if it is feasible
if (locMod->IsFeasible())
{
nPerfmormedOps++;
int tmp = locMod->Execute();
m->SimplexNumber()+= tmp;
locMod->UpdateHeap(h);
m->VertexNumber()--;
}
}
delete locMod;
}
2004-07-08 10:25:15 +02:00
}
///initialize for all vertex the temporary mark must call only at the start of decimation
2004-07-09 12:22:56 +02:00
///by default it takes the first element in the heap and calls Init (static funcion) of that type
///of local modification.
2004-07-08 10:25:15 +02:00
void Init()
{
2004-07-09 12:22:56 +02:00
m->InitIMark();
if(!h.empty())
{
(*h.begin()).locModPtr->Init(*m,h);
}
2004-07-08 10:25:15 +02:00
}
/// 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(){
2004-07-09 12:22:56 +02:00
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(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;
return false;
2004-07-08 10:25:15 +02:00
}
///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)
2004-07-09 12:22:56 +02:00
if(!(*hi).locModPtr->IsUpToDate())
2004-07-08 10:25:15 +02:00
{
*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