Developer Documentation
CompositeT.cc
Go to the documentation of this file.
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 
53 //=============================================================================
54 //
55 // CLASS CompositeT - IMPLEMENTATION
56 //
57 //=============================================================================
58 
59 #define OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITET_CC
60 
61 
62 //== INCLUDES =================================================================
63 
64 #include <OpenMesh/Core/System/config.hh>
66 #include <ostream>
68 #include <OpenMesh/Tools/Subdivider/Adaptive/Composite/RuleInterfaceT.hh>
69 
70 
71 //== NAMESPACE ================================================================
72 
73 namespace OpenMesh { // BEGIN_NS_OPENMESH
74 namespace Subdivider { // BEGIN_NS_DECIMATER
75 namespace Adaptive { // BEGIN_NS_ADAPTIVE
76 
77 
78 //== IMPLEMENTATION ==========================================================
79 
80 
81 template<class M>
82 bool
84 initialize( void )
85 {
86  typename Mesh::VertexIter v_it;
87  typename Mesh::FaceIter f_it;
88  typename Mesh::EdgeIter e_it;
89  const typename Mesh::Point zero_point(0.0, 0.0, 0.0);
90 
91  // ---------------------------------------- Init Vertices
92  for (v_it = mesh_.vertices_begin(); v_it != mesh_.vertices_end(); ++v_it)
93  {
94  mesh_.data(*v_it).set_state(0);
95  mesh_.data(*v_it).set_final();
96  mesh_.data(*v_it).set_position(0, mesh_.point(*v_it));
97  }
98 
99  // ---------------------------------------- Init Faces
100  for (f_it = mesh_.faces_begin(); f_it != mesh_.faces_end(); ++f_it)
101  {
102  mesh_.data(*f_it).set_state(0);
103  mesh_.data(*f_it).set_final();
104  mesh_.data(*f_it).set_position(0, zero_point);
105  }
106 
107  // ---------------------------------------- Init Edges
108  for (e_it = mesh_.edges_begin(); e_it != mesh_.edges_end(); ++e_it)
109  {
110  mesh_.data(*e_it).set_state(0);
111  mesh_.data(*e_it).set_final();
112  mesh_.data(*e_it).set_position(0, zero_point);
113  }
114 
115 
116  // ---------------------------------------- Init Rules
117 
118  int n_subdiv_rules_ = 0;
119 
120 
121  // look for subdivision rule(s)
122  for (size_t i=0; i < n_rules(); ++i) {
123 
124  if (rule_sequence_[i]->type()[0] == 'T' ||
125  rule_sequence_[i]->type()[0] == 't')
126  {
127  ++n_subdiv_rules_;
128  subdiv_rule_ = rule_sequence_[i];
129  subdiv_type_ = rule_sequence_[i]->subdiv_type();
130  }
131  }
132 
133 
134  // check for correct number of subdivision rules
135  assert(n_subdiv_rules_ == 1);
136 
137  if (n_subdiv_rules_ != 1)
138  {
139  ::omerr() << "Error! More than one subdivision rules not allowed!\n";
140  return false;
141  }
142 
143  // check for subdivision type
144  assert(subdiv_type_ == 3 || subdiv_type_ == 4);
145 
146  if (subdiv_type_ != 3 && subdiv_type_ != 4)
147  {
148  ::omerr() << "Error! Unknown subdivision type in sequence!" << std::endl;
149  return false;
150  }
151 
152  // set pointer to last rule
153 // first_rule_ = rule_sequence_.front();
154 // last_rule_ = rule_sequence_.back(); //[n_rules() - 1];
155 
156  // set numbers and previous rule
157  for (size_t i = 0; i < n_rules(); ++i)
158  {
159  rule_sequence_[i]->set_subdiv_type(subdiv_type_);
160  rule_sequence_[i]->set_n_rules(n_rules());
161  rule_sequence_[i]->set_number(i);
162  rule_sequence_[i]->set_prev_rule(rule_sequence_[(i+n_rules()-1)%n_rules()]);
163  rule_sequence_[i]->set_subdiv_rule(subdiv_rule_);
164  }
165 
166  return true;
167 }
168 
169 
170 // ----------------------------------------------------------------------------
171 #define MOBJ mesh_.deref
172 #define TVH to_vertex_handle
173 #define HEH halfedge_handle
174 #define NHEH next_halfedge_handle
175 #define PHEH prev_halfedge_handle
176 #define OHEH opposite_halfedge_handle
177 // ----------------------------------------------------------------------------
178 
179 
180 template<class M>
181 void CompositeT<M>::refine(typename M::FaceHandle& _fh)
182 {
183  std::vector<typename Mesh::HalfedgeHandle> hh_vector;
184 
185  // -------------------- calculate new level for faces and vertices
186  int new_face_level =
187  t_rule()->number() + 1 +
188  ((int)floor((float)(mesh_.data(_fh).state() - t_rule()->number() - 1)/n_rules()) + 1) * n_rules();
189 
190  int new_vertex_level =
191  new_face_level + l_rule()->number() - t_rule()->number();
192 
193  // -------------------- store old vertices
194  // !!! only triangle meshes supported!
195  typename Mesh::VertexHandle vh[3];
196 
197  vh[0] = mesh_.TVH(mesh_.HEH(_fh));
198  vh[1] = mesh_.TVH(mesh_.NHEH(mesh_.HEH(_fh)));
199  vh[2] = mesh_.TVH(mesh_.PHEH(mesh_.HEH(_fh)));
200 
201  // save handles to incoming halfedges for getting the new vertices
202  // after subdivision (1-4 split)
203  if (subdiv_type_ == 4)
204  {
205  hh_vector.clear();
206 
207  // green face
208  if (mesh_.data(_fh).final())
209  {
210  typename Mesh::FaceHalfedgeIter fh_it(mesh_.fh_iter(_fh));
211 
212  for (; fh_it.is_valid(); ++fh_it)
213  {
214  hh_vector.push_back(mesh_.PHEH(mesh_.OHEH(*fh_it)));
215  }
216  }
217 
218  // red face
219  else
220  {
221 
222  typename Mesh::HalfedgeHandle red_hh(mesh_.data(_fh).red_halfedge());
223 
224  hh_vector.push_back(mesh_.PHEH(mesh_.OHEH(mesh_.NHEH(red_hh))));
225  hh_vector.push_back(mesh_.PHEH(mesh_.OHEH(mesh_.PHEH(mesh_.OHEH(red_hh)))));
226  }
227  }
228 
229 
230  // -------------------- Average rule before topo rule?
231  if (t_rule()->number() > 0)
232  t_rule()->prev_rule()->raise(_fh, new_face_level-1);
233 
234  // -------------------- Apply topological operator first
235  t_rule()->raise(_fh, new_face_level);
236 
237 #if 0 // original code
238  assert(MOBJ(_fh).state() >=
239  subdiv_rule_->number()+1+(int) (MOBJ(_fh).state()/n_rules())*n_rules());
240 #else // improved code (use % operation and avoid floating point division)
241  assert( mesh_.data(_fh).state() >= ( t_rule()->number()+1+generation(_fh) ) );
242 #endif
243 
244  // raise new vertices to final levels
245  if (subdiv_type_ == 3)
246  {
247  typename Mesh::VertexHandle new_vh(mesh_.TVH(mesh_.NHEH(mesh_.HEH(_fh))));
248 
249  // raise new vertex to final level
250  l_rule()->raise(new_vh, new_vertex_level);
251  }
252 
253  if (subdiv_type_ == 4)
254  {
255  typename Mesh::HalfedgeHandle hh;
256  typename Mesh::VertexHandle new_vh;
257 
258  while (!hh_vector.empty()) {
259 
260  hh = hh_vector.back();
261  hh_vector.pop_back();
262 
263  // get new vertex
264  new_vh = mesh_.TVH(mesh_.NHEH(hh));
265 
266  // raise new vertex to final level
267  l_rule()->raise(new_vh, new_vertex_level);
268  }
269  }
270 
271  // raise old vertices to final position
272  l_rule()->raise(vh[0], new_vertex_level);
273  l_rule()->raise(vh[1], new_vertex_level);
274  l_rule()->raise(vh[2], new_vertex_level);
275 }
276 
277 
278 // ----------------------------------------------------------------------------
279 
280 
281 template<class M>
282 void CompositeT<M>::refine(typename M::VertexHandle& _vh)
283 {
284  // calculate next final level for vertex
285  int new_vertex_state = generation(_vh) + l_rule()->number() + 1;
286 
287  // raise vertex to final position
288  l_rule()->raise(_vh, new_vertex_state);
289 }
290 
291 
292 // ----------------------------------------------------------------------------
293 
294 
295 template <class M>
296 std::string CompositeT<M>::rules_as_string(const std::string& _sep) const
297 {
298  std::string seq;
299  typename RuleSequence::const_iterator it = rule_sequence_.begin();
300 
301  if ( it != rule_sequence_.end() )
302  {
303  seq = (*it)->type();
304  for (++it; it != rule_sequence_.end(); ++it )
305  {
306  seq += _sep;
307  seq += (*it)->type();
308  }
309  }
310  return seq;
311 }
312 
313 // ----------------------------------------------------------------------------
314 #undef MOBJ
315 #undef TVH
316 #undef HEH
317 #undef NHEH
318 #undef PHEH
319 #undef OHEH
320 //=============================================================================
321 } // END_NS_ADAPTIVE
322 } // END_NS_SUBDIVIDER
323 } // END_NS_OPENMESH
324 //=============================================================================
Kernel::FaceHalfedgeIter FaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:171
bool initialize(void)
Initialize faces, edges, vertices, and rules.
Definition: CompositeT.cc:84
std::string rules_as_string(const std::string &_sep=" * ") const
Return the sequence as string.
Definition: CompositeT.cc:296
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
void refine(typename M::FaceHandle &_fh)
Refine one face.
Definition: CompositeT.cc:181
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115