Developer Documentation

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