File: local_optimization.h

package info (click to toggle)
meshlab 2020.09%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 45,132 kB
  • sloc: cpp: 400,238; ansic: 31,952; javascript: 1,578; sh: 387; yacc: 238; lex: 139; python: 86; makefile: 30
file content (304 lines) | stat: -rw-r--r-- 11,034 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
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