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 
45 //=============================================================================
46 //
47 // CLASS RuleInterfaceT
48 //
49 //=============================================================================
50 
51 #ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH
52 #define OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH
53 
54 
55 //== INCLUDES =================================================================
56 
57 #include <string>
59 
60 //== NAMESPACE ================================================================
61 
62 namespace OpenMesh { // BEGIN_NS_OPENMESH
63 namespace Subdivider { // BEGIN_NS_SUBDIVIDER
64 namespace Adaptive { // BEGIN_NS_ADAPTIVE
65 
66 
67 //== FORWARDS =================================================================
68 
69 template <typename M> class CompositeT;
70 template <typename M> class RuleInterfaceT;
71 
72 //== CLASS DEFINITION =========================================================
73 
74 
75 // ----------------------------------------------------------------------------
76 
82 template < typename R >
83 struct RuleHandleT : public BaseHandle
84 {
85  explicit RuleHandleT(int _idx=-1) : BaseHandle(_idx) {}
86  typedef R Rule;
87 
88  operator bool() const { return is_valid(); }
89 
90 };
91 
95 #define COMPOSITE_RULE( classname, mesh_type ) \
96  protected:\
97  friend class CompositeT<mesh_type>; \
98  public: \
99  const char *type() const override { return #classname; } \
100  typedef classname<mesh_type> Self; \
101  typedef RuleHandleT< Self > Handle
102 
103 
104 // ----------------------------------------------------------------------------
108 template <typename M> class RuleInterfaceT
109 {
110 public:
111 
112  typedef M Mesh;
113  typedef RuleInterfaceT<M> Self;
114  typedef RuleHandleT< Self > Rule;
115 
116  typedef typename M::Scalar scalar_t;
117 
118 protected:
119 
121  RuleInterfaceT(Mesh& _mesh) : mesh_(_mesh),prev_rule_(nullptr),subdiv_rule_(nullptr),subdiv_type_(0),number_(0),n_rules_(0) {};
122 
123 public:
124 
126  virtual ~RuleInterfaceT() {};
127 
128 
131  virtual const char *type() const = 0;
132 
133 public:
134 
136 
137  virtual void raise(typename M::FaceHandle& _fh, state_t _target_state)
139  {
140  if (mesh_.data(_fh).state() < _target_state) {
141  update(_fh, _target_state);
142  mesh_.data(_fh).inc_state();
143  }
144  }
145 
146  virtual void raise(typename M::EdgeHandle& _eh, state_t _target_state)
147  {
148  if (mesh_.data(_eh).state() < _target_state) {
149  update(_eh, _target_state);
150  mesh_.data(_eh).inc_state();
151  }
152  }
153 
154  virtual void raise(typename M::VertexHandle& _vh, state_t _target_state)
155  {
156  if (mesh_.data(_vh).state() < _target_state) {
157  update(_vh, _target_state);
158  mesh_.data(_vh).inc_state();
159  }
160  }
162 
163  void update(typename M::FaceHandle& _fh, state_t _target_state)
164  {
165  typename M::FaceHandle opp_fh;
166 
167  while (mesh_.data(_fh).state() < _target_state - 1) {
168  prev_rule()->raise(_fh, _target_state - 1);
169  }
170 
171  // Don't use unflipped / unfinal faces!!!
172  if (subdiv_type() == 3) {
173 
174  if (mesh_.face_handle(mesh_.opposite_halfedge_handle(mesh_.halfedge_handle(_fh))).is_valid()) {
175 
176  while (!mesh_.data(_fh).final()) {
177 
178  opp_fh = mesh_.face_handle(mesh_.opposite_halfedge_handle(mesh_.halfedge_handle(_fh)));
179 
180  assert (mesh_.data(_fh).state() >=
181  mesh_.data(opp_fh).state());
182 
183  // different states: raise other face
184  if (mesh_.data(_fh).state() > mesh_.data(opp_fh).state()){
185 
186  // raise opposite face
187  prev_rule()->raise(opp_fh, _target_state - 1);
188  }
189 
190  else {
191 
192  // equal states
193 
194  // flip edge
195  // typename M::EdgeHandle eh(mesh_.edge_handle(mesh_.halfedge_handle(_fh)));
196 
197  // if (mesh_.is_flip_ok(eh)) {
198 
199  // std::cout << "Flipping Edge...\n";
200 
201  // mesh_.flip(eh);
202 
203  // mesh_.data(_fh).set_final();
204  // mesh_.data(opp_fh).set_final();
205  // }
206 
207  // else {
208 
209  // std::cout << "Flip not okay.\n";
210  // }
211  }
212  }
213  }
214 
215  else {
216 
217  // mesh_.data(_fh).set_final();
218  }
219 
220  // std::cout << "Raising Face to Level "
221  // << _target_state
222  // << " with "
223  // << type()
224  // << ".\n";
225 
226  }
227 
228  assert( subdiv_type() != 4 ||
229  mesh_.data(_fh).final() ||
230  _target_state%n_rules() == (subdiv_rule()->number() + 1)%n_rules() );
231 
232  typename M::FaceEdgeIter fe_it;
233  typename M::FaceVertexIter fv_it;
234  typename M::EdgeHandle eh;
235  typename M::VertexHandle vh;
236 
237  std::vector<typename M::FaceHandle> face_vector;
238  face_vector.clear();
239 
240  if (_target_state > 1) {
241 
242  for (fe_it = mesh_.fe_iter(_fh); fe_it.is_valid(); ++fe_it) {
243 
244  eh = *fe_it;
245  prev_rule()->raise(eh, _target_state - 1);
246  }
247 
248  for (fv_it = mesh_.fv_iter(_fh); fv_it.is_valid(); ++fv_it) {
249 
250  vh = *fv_it;
251  prev_rule()->raise(vh, _target_state - 1);
252  }
253  }
254  }
255 
256 
257  void update(typename M::EdgeHandle& _eh, state_t _target_state)
258  {
259  state_t state(mesh_.data(_eh).state());
260 
261  // raise edge to correct state
262  if (state + 1 < _target_state && _target_state > 0) {
263 
264  prev_rule()->raise(_eh, _target_state - 1);
265  }
266 
267  typename M::VertexHandle vh;
268  typename M::FaceHandle fh;
269 
270  if (_target_state > 1)
271  {
272  vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(_eh, 0));
273  prev_rule()->raise(vh, _target_state - 1);
274 
275  vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(_eh, 1));
276  prev_rule()->raise(vh, _target_state - 1);
277 
278  fh = mesh_.face_handle(mesh_.halfedge_handle(_eh, 0));
279  if (fh.is_valid())
280  prev_rule()->raise(fh, _target_state - 1);
281 
282  fh = mesh_.face_handle(mesh_.halfedge_handle(_eh, 1));
283  if (fh.is_valid())
284  prev_rule()->raise(fh, _target_state - 1);
285  }
286  }
287 
288 
289  void update(typename M::VertexHandle& _vh, state_t _target_state) {
290 
291  state_t state(mesh_.data(_vh).state());
292 
293  // raise vertex to correct state
294  if (state + 1 < _target_state)
295  {
296  prev_rule()->raise(_vh, _target_state - 1);
297  }
298 
299  std::vector<typename M::HalfedgeHandle> halfedge_vector;
300  halfedge_vector.clear();
301 
302  typename M::VertexOHalfedgeIter voh_it;
303  typename M::EdgeHandle eh;
304  typename M::FaceHandle fh;
305 
306  if (_target_state > 1)
307  {
308 
309  for (voh_it = mesh_.voh_iter(_vh); voh_it.is_valid(); ++voh_it) {
310  halfedge_vector.push_back(*voh_it);
311  }
312 
313  while ( !halfedge_vector.empty() ) {
314  eh = mesh_.edge_handle(halfedge_vector.back());
315  halfedge_vector.pop_back();
316 
317  prev_rule()->raise(eh, _target_state - 1);
318  }
319 
320  for (voh_it = mesh_.voh_iter(_vh); voh_it.is_valid(); ++voh_it) {
321  halfedge_vector.push_back(*voh_it);
322  }
323 
324  while ( !halfedge_vector.empty() ) {
325  fh = mesh_.face_handle(halfedge_vector.back());
326  halfedge_vector.pop_back();
327 
328  if (fh.is_valid())
329  prev_rule()->raise(fh, _target_state - 1);
330  }
331  }
332  }
333 
334 public:
335 
336 
338  int subdiv_type() const { return subdiv_type_; }
339 
340 
342  int number() const { return number_; }
343 
345 
346 
348  virtual void set_coeff( scalar_t _coeff ) { coeff_ = _coeff; }
349 
351  scalar_t coeff() const { return coeff_; }
352 
354 
355 protected:
356 
357  void set_prev_rule(Self*& _p) { prev_rule_ = _p; }
358  Self* prev_rule() { return prev_rule_; }
359 
360  void set_subdiv_rule(Self*& _n) { subdiv_rule_ = _n; }
361  Self* subdiv_rule() const { return subdiv_rule_; }
362 
363  void set_number(int _n) { number_ = _n; }
364 
365  void set_n_rules(int _n) { n_rules_ = _n; }
366  int n_rules() const { return n_rules_; }
367 
368  void set_subdiv_type(int _n)
369  { assert(_n == 3 || _n == 4); subdiv_type_ = _n; }
370 
371  friend class CompositeT<M>;
372 
373 protected:
374 
375  Mesh& mesh_;
376 
377 private:
378 
379  Self* prev_rule_;
380  Self* subdiv_rule_;
381 
382  int subdiv_type_;
383  int number_;
384  int n_rules_;
385 
386  scalar_t coeff_;
387 
388 private: // Noncopyable
389 
391  RuleInterfaceT& operator=(const RuleInterfaceT&);
392 
393 };
394 
395 //=============================================================================
396 } // END_NS_ADAPTIVE
397 } // END_NS_SUBDIVIDER
398 } // END_NS_OPENMESH
399 //=============================================================================
400 #endif // OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH defined
401 //=============================================================================
402 
scalar_t coeff() const
Get coefficient - ignored by non-parameterized rules.
virtual void set_coeff(scalar_t _coeff)
Set coefficient - ignored by non-parameterized rules.
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
int subdiv_type() const
Type of split operation, if it is a topological operator.
RuleInterfaceT(Mesh &_mesh)
Default constructor.
int number() const
Position in rule sequence.
CompositeTraits::state_t state_t