Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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>
65 #include <OpenMesh/Core/System/omstream.hh>
66 #include <ostream>
67 #include <OpenMesh/Tools/Subdivider/Adaptive/Composite/CompositeT.hh>
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
83 CompositeT<M> ::
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 //=============================================================================
OpenMesh::Subdivider::Adaptive::CompositeT::initialize
bool initialize(void)
Initialize faces, edges, vertices, and rules.
Definition: CompositeT.cc:84
OpenMesh::Subdivider::Adaptive::CompositeT::rules_as_string
std::string rules_as_string(const std::string &_sep=" * ") const
Return the sequence as string.
Definition: CompositeT.cc:296
OpenMesh
Definition: MeshItems.hh:64
OpenMesh::Subdivider::Adaptive::CompositeT::refine
void refine(typename M::FaceHandle &_fh)
Refine one face.
Definition: CompositeT.cc:181
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
omstream.hh
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
OpenMesh::PolyMeshT::FaceHalfedgeIter
Kernel::FaceHalfedgeIter FaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:171
CompositeT.hh