Developer Documentation
RuleInterfaceT.hh
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Date$ *
46  * *
47 \*===========================================================================*/
48 
49 
50 //=============================================================================
51 //
52 // CLASS RuleInterfaceT
53 //
54 //=============================================================================
55 
56 #ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH
57 #define OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH
58 
59 
60 //== INCLUDES =================================================================
61 
62 #include <string>
64 
65 //== NAMESPACE ================================================================
66 
67 namespace OpenMesh { // BEGIN_NS_OPENMESH
68 namespace Subdivider { // BEGIN_NS_SUBDIVIDER
69 namespace Adaptive { // BEGIN_NS_ADAPTIVE
70 
71 
72 //== FORWARDS =================================================================
73 
74 template <typename M> class CompositeT;
75 template <typename M> class RuleInterfaceT;
76 
77 //== CLASS DEFINITION =========================================================
78 
79 
80 // ----------------------------------------------------------------------------
81 
87 template < typename R >
88 struct RuleHandleT : public BaseHandle
89 {
90  explicit RuleHandleT(int _idx=-1) : BaseHandle(_idx) {}
91  typedef R Rule;
92 
93  operator bool() const { return is_valid(); }
94 
95 };
96 
100 #define COMPOSITE_RULE( classname, mesh_type ) \
101  protected:\
102  friend class CompositeT<mesh_type>; \
103  public: \
104  const char *type() const { return #classname; } \
105  typedef classname<mesh_type> Self; \
106  typedef RuleHandleT< Self > Handle
107 
108 
109 // ----------------------------------------------------------------------------
113 template <typename M> class RuleInterfaceT
114 {
115 public:
116 
117  typedef M Mesh;
118  typedef RuleInterfaceT<M> Self;
119  typedef RuleHandleT< Self > Rule;
120 
121  typedef typename M::Scalar scalar_t;
122 
123 protected:
124 
126  RuleInterfaceT(Mesh& _mesh) : mesh_(_mesh) {};
127 
128 public:
129 
131  virtual ~RuleInterfaceT() {};
132 
133 
136  virtual const char *type() const = 0;
137 
138 public:
139 
141 
142  virtual void raise(typename M::FaceHandle& _fh, state_t _target_state)
144  {
145  if (mesh_.data(_fh).state() < _target_state) {
146  update(_fh, _target_state);
147  mesh_.data(_fh).inc_state();
148  }
149  }
150 
151  virtual void raise(typename M::EdgeHandle& _eh, state_t _target_state)
152  {
153  if (mesh_.data(_eh).state() < _target_state) {
154  update(_eh, _target_state);
155  mesh_.data(_eh).inc_state();
156  }
157  }
158 
159  virtual void raise(typename M::VertexHandle& _vh, state_t _target_state)
160  {
161  if (mesh_.data(_vh).state() < _target_state) {
162  update(_vh, _target_state);
163  mesh_.data(_vh).inc_state();
164  }
165  }
167 
168  void update(typename M::FaceHandle& _fh, state_t _target_state)
169  {
170  typename M::FaceHandle opp_fh;
171 
172  while (mesh_.data(_fh).state() < _target_state - 1) {
173  prev_rule()->raise(_fh, _target_state - 1);
174  }
175 
176  // Don't use unflipped / unfinal faces!!!
177  if (subdiv_type() == 3) {
178 
179  if (mesh_.face_handle(mesh_.opposite_halfedge_handle(mesh_.halfedge_handle(_fh))).is_valid()) {
180 
181  while (!mesh_.data(_fh).final()) {
182 
183  opp_fh = mesh_.face_handle(mesh_.opposite_halfedge_handle(mesh_.halfedge_handle(_fh)));
184 
185  assert (mesh_.data(_fh).state() >=
186  mesh_.data(opp_fh).state());
187 
188  // different states: raise other face
189  if (mesh_.data(_fh).state() > mesh_.data(opp_fh).state()){
190 
191  // raise opposite face
192  prev_rule()->raise(opp_fh, _target_state - 1);
193  }
194 
195  else {
196 
197  // equal states
198 
199  // flip edge
200  // typename M::EdgeHandle eh(mesh_.edge_handle(mesh_.halfedge_handle(_fh)));
201 
202  // if (mesh_.is_flip_ok(eh)) {
203 
204  // std::cout << "Flipping Edge...\n";
205 
206  // mesh_.flip(eh);
207 
208  // mesh_.data(_fh).set_final();
209  // mesh_.data(opp_fh).set_final();
210  // }
211 
212  // else {
213 
214  // std::cout << "Flip not okay.\n";
215  // }
216  }
217  }
218  }
219 
220  else {
221 
222  // mesh_.data(_fh).set_final();
223  }
224 
225  // std::cout << "Raising Face to Level "
226  // << _target_state
227  // << " with "
228  // << type()
229  // << ".\n";
230 
231  }
232 
233  assert( subdiv_type() != 4 ||
234  mesh_.data(_fh).final() ||
235  _target_state%n_rules() == (subdiv_rule()->number() + 1)%n_rules() );
236 
237  typename M::FaceEdgeIter fe_it;
238  typename M::FaceVertexIter fv_it;
239  typename M::EdgeHandle eh;
240  typename M::VertexHandle vh;
241 
242  std::vector<typename M::FaceHandle> face_vector;
243  face_vector.clear();
244 
245  if (_target_state > 1) {
246 
247  for (fe_it = mesh_.fe_iter(_fh); fe_it.is_valid(); ++fe_it) {
248 
249  eh = *fe_it;
250  prev_rule()->raise(eh, _target_state - 1);
251  }
252 
253  for (fv_it = mesh_.fv_iter(_fh); fv_it.is_valid(); ++fv_it) {
254 
255  vh = *fv_it;
256  prev_rule()->raise(vh, _target_state - 1);
257  }
258  }
259  }
260 
261 
262  void update(typename M::EdgeHandle& _eh, state_t _target_state)
263  {
264  state_t state(mesh_.data(_eh).state());
265 
266  // raise edge to correct state
267  if (state + 1 < _target_state && _target_state > 0) {
268 
269  prev_rule()->raise(_eh, _target_state - 1);
270  }
271 
272  typename M::VertexHandle vh;
273  typename M::FaceHandle fh;
274 
275  if (_target_state > 1)
276  {
277  vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(_eh, 0));
278  prev_rule()->raise(vh, _target_state - 1);
279 
280  vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(_eh, 1));
281  prev_rule()->raise(vh, _target_state - 1);
282 
283  fh = mesh_.face_handle(mesh_.halfedge_handle(_eh, 0));
284  if (fh.is_valid())
285  prev_rule()->raise(fh, _target_state - 1);
286 
287  fh = mesh_.face_handle(mesh_.halfedge_handle(_eh, 1));
288  if (fh.is_valid())
289  prev_rule()->raise(fh, _target_state - 1);
290  }
291  }
292 
293 
294  void update(typename M::VertexHandle& _vh, state_t _target_state) {
295 
296  state_t state(mesh_.data(_vh).state());
297 
298  // raise vertex to correct state
299  if (state + 1 < _target_state)
300  {
301  prev_rule()->raise(_vh, _target_state - 1);
302  }
303 
304  std::vector<typename M::HalfedgeHandle> halfedge_vector;
305  halfedge_vector.clear();
306 
307  typename M::VertexOHalfedgeIter voh_it;
308  typename M::EdgeHandle eh;
309  typename M::FaceHandle fh;
310 
311  if (_target_state > 1)
312  {
313 
314  for (voh_it = mesh_.voh_iter(_vh); voh_it.is_valid(); ++voh_it) {
315  halfedge_vector.push_back(*voh_it);
316  }
317 
318  while ( !halfedge_vector.empty() ) {
319  eh = mesh_.edge_handle(halfedge_vector.back());
320  halfedge_vector.pop_back();
321 
322  prev_rule()->raise(eh, _target_state - 1);
323  }
324 
325  for (voh_it = mesh_.voh_iter(_vh); voh_it.is_valid(); ++voh_it) {
326  halfedge_vector.push_back(*voh_it);
327  }
328 
329  while ( !halfedge_vector.empty() ) {
330  fh = mesh_.face_handle(halfedge_vector.back());
331  halfedge_vector.pop_back();
332 
333  if (fh.is_valid())
334  prev_rule()->raise(fh, _target_state - 1);
335  }
336  }
337  }
338 
339 public:
340 
341 
343  int subdiv_type() const { return subdiv_type_; }
344 
345 
347  int number() const { return number_; }
348 
350 
351 
353  virtual void set_coeff( scalar_t _coeff ) { coeff_ = _coeff; }
354 
356  scalar_t coeff() const { return coeff_; }
357 
359 
360 protected:
361 
362  void set_prev_rule(Self*& _p) { prev_rule_ = _p; }
363  Self* prev_rule() { return prev_rule_; }
364 
365  void set_subdiv_rule(Self*& _n) { subdiv_rule_ = _n; }
366  Self* subdiv_rule() { return subdiv_rule_; }
367 
368  void set_number(int _n) { number_ = _n; }
369 
370  void set_n_rules(int _n) { n_rules_ = _n; }
371  int n_rules() { return n_rules_; }
372 
373  void set_subdiv_type(int _n)
374  { assert(_n == 3 || _n == 4); subdiv_type_ = _n; }
375 
376  friend class CompositeT<M>;
377 
378 protected:
379 
380  Mesh& mesh_;
381 
382 private:
383 
384  Self* prev_rule_;
385  Self* subdiv_rule_;
386 
387  int subdiv_type_;
388  int number_;
389  int n_rules_;
390 
391  scalar_t coeff_;
392 
393 private: // Noncopyable
394 
396  RuleInterfaceT& operator=(const RuleInterfaceT&);
397 
398 };
399 
400 //=============================================================================
401 } // END_NS_ADAPTIVE
402 } // END_NS_SUBDIVIDER
403 } // END_NS_OPENMESH
404 //=============================================================================
405 #endif // OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH defined
406 //=============================================================================
407 
virtual void set_coeff(scalar_t _coeff)
Set coefficient - ignored by non-parameterized rules.
RuleInterfaceT(Mesh &_mesh)
Default constructor.
bool is_valid() const
The handle is valid iff the index is not equal to -1.
Definition: Handles.hh:77
int subdiv_type() const
Type of split operation, if it is a topological operator.
int number() const
Position in rule sequence.
CompositeTraits::state_t state_t
scalar_t coeff() const
Get coefficient - ignored by non-parameterized rules.