Developer Documentation
HexahedralMeshIterators.cc
1/*===========================================================================*\
2 * *
3 * OpenVolumeMesh *
4 * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
5 * www.openvolumemesh.org *
6 * *
7 *---------------------------------------------------------------------------*
8 * This file is part of OpenVolumeMesh. *
9 * *
10 * OpenVolumeMesh is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
18 * link it with other files to produce an executable, this file does *
19 * not by itself cause the resulting executable to be covered by the *
20 * GNU Lesser General Public License. This exception does not however *
21 * invalidate any other reasons why the executable file might be *
22 * covered by the GNU Lesser General Public License. *
23 * *
24 * OpenVolumeMesh is distributed in the hope that it will be useful, *
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27 * GNU Lesser General Public License for more details. *
28 * *
29 * You should have received a copy of the GNU LesserGeneral Public *
30 * License along with OpenVolumeMesh. If not, *
31 * see <http://www.gnu.org/licenses/>. *
32 * *
33\*===========================================================================*/
34
35
36#include <set>
37
38#include <OpenVolumeMesh/Mesh/HexahedralMeshIterators.hh>
39#include <OpenVolumeMesh/Mesh/HexahedralMeshTopologyKernel.hh>
40
41namespace OpenVolumeMesh {
42
43//================================================================================================
44// CellSheetCellIter
45//================================================================================================
46
47
48CellSheetCellIter::CellSheetCellIter(const CellHandle& _ref_h,
49 const unsigned char _orthDir, const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
50BaseIter(_mesh, _ref_h, _max_laps) {
51
52 if(!_mesh->has_face_bottom_up_incidences()) {
53#ifndef NDEBUG
54 std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
55#endif
56 BaseIter::valid(false);
57 return;
58 }
59
60 // First off, get all surrounding cells
61 std::vector<HalfFaceHandle> halffaces = _mesh->cell(_ref_h).halffaces();
62 for(std::vector<HalfFaceHandle>::const_iterator hf_it = halffaces.begin();
63 hf_it != halffaces.end(); ++hf_it) {
64 // Add those, that are perpendicular to the specified _orthDir
65 if(_mesh->orientation(*hf_it, _ref_h) != _orthDir &&
66 _mesh->orientation(*hf_it, _ref_h) != _mesh->opposite_orientation(_orthDir)) {
67 CellHandle ch = _mesh->incident_cell(_mesh->opposite_halfface_handle(*hf_it));
68 if(ch != TopologyKernel::InvalidCellHandle) {
69 neighb_sheet_cell_hs_.push_back(ch);
70 }
71 }
72 }
73
74 // Remove all duplicate entries
75 std::sort(neighb_sheet_cell_hs_.begin(), neighb_sheet_cell_hs_.end());
76 neighb_sheet_cell_hs_.resize(std::unique(neighb_sheet_cell_hs_.begin(), neighb_sheet_cell_hs_.end()) - neighb_sheet_cell_hs_.begin());
77
78 cur_index_ = 0;
79 BaseIter::valid(neighb_sheet_cell_hs_.size() > 0);
80 if(BaseIter::valid()) {
81 BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
82 }
83}
84
85
86CellSheetCellIter& CellSheetCellIter::operator--() {
87
88 if (cur_index_ == 0) {
89 cur_index_ = neighb_sheet_cell_hs_.size() - 1;
90 --lap_;
91 if (lap_ < 0)
92 BaseIter::valid(false);
93 } else {
94 --cur_index_;
95 }
96
97 BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
98
99 return *this;
100}
101
102
103CellSheetCellIter& CellSheetCellIter::operator++() {
104
105 ++cur_index_;
106 if(cur_index_ == neighb_sheet_cell_hs_.size()) {
107 cur_index_ = 0;
108 ++lap_;
109 if (lap_ >= max_laps_)
110 BaseIter::valid(false);
111 }
112
113 BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
114
115 return *this;
116}
117
118//================================================================================================
119// HalfFaceSheetHalfFaceIter
120//================================================================================================
121
122
123HalfFaceSheetHalfFaceIter::HalfFaceSheetHalfFaceIter(const HalfFaceHandle& _ref_h,
124 const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
125BaseIter(_mesh, _ref_h, _max_laps) {
126
127 if(!_mesh->has_face_bottom_up_incidences()) {
128#ifndef NDEBUG
129 std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
130#endif
131 BaseIter::valid(false);
132 return;
133 }
134
135 /*
136 * Each halfface uniquely belongs to either a cell
137 * or the boundary. If the halfface belongs
138 * to a cell, it suffices to determine the local axis
139 * the halfface represents w.r.t. the cell and to
140 * iterate over all neighboring cells orthogonal to
141 * this direction. We have to find those halffaces
142 * of the neighboring cells that contain exactly one
143 * of the initial halfface's opposite halfedges.
144 */
145
146 if(_mesh->is_boundary(_ref_h)) {
147#ifndef NDEBUG
148 std::cerr << "HalfFaceSheetHalfFaceIter: HalfFace is boundary!" << std::endl;
149#endif
150 BaseIter::valid(false);
151 return;
152 }
153
154 CellHandle ch = _mesh->incident_cell(_ref_h);
155 unsigned char orientation = _mesh->orientation(_ref_h, ch);
156 std::vector<HalfEdgeHandle> hes_v = _mesh->opposite_halfface(_mesh->halfface(_ref_h)).halfedges();
157 std::set<HalfEdgeHandle> hes;
158 hes.insert(hes_v.begin(), hes_v.end());
159
160 for(CellSheetCellIter csc_it = _mesh->csc_iter(ch, orientation);
161 csc_it.valid(); ++csc_it) {
162
163 std::vector<HalfFaceHandle> hfs = _mesh->cell(*csc_it).halffaces();
164 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin();
165 hf_it != hfs.end(); ++hf_it) {
166
167 std::vector<HalfEdgeHandle> hf_hes = _mesh->halfface(*hf_it).halfedges();
168 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hf_hes.begin();
169 he_it != hf_hes.end(); ++he_it) {
170
171 if(hes.count(*he_it) > 0) {
172 // Found halfface that lies on the same sheet
173 adjacent_halffaces_.push_back(*hf_it);
174 common_edges_.push_back(_mesh->edge_handle(*he_it));
175 break;
176 }
177 }
178 }
179 }
180
181 cur_index_ = 0;
182 BaseIter::valid(adjacent_halffaces_.size() > 0);
183 if(BaseIter::valid()) {
184 BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
185 }
186}
187
188
189HalfFaceSheetHalfFaceIter& HalfFaceSheetHalfFaceIter::operator--() {
190
191 if (cur_index_ == 0) {
192 cur_index_ = adjacent_halffaces_.size() - 1;
193 --lap_;
194 if (lap_ < 0)
195 BaseIter::valid(false);
196 } else {
197 --cur_index_;
198 }
199
200 BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
201
202 return *this;
203}
204
205
206HalfFaceSheetHalfFaceIter& HalfFaceSheetHalfFaceIter::operator++() {
207
208 ++cur_index_;
209 if(cur_index_ == adjacent_halffaces_.size()) {
210 cur_index_ = 0;
211 ++lap_;
212 if (lap_ >= max_laps_)
213 BaseIter::valid(false);
214 }
215
216 BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
217
218 return *this;
219}
220
221//================================================================================================
222// HexVertexIter
223//================================================================================================
224
225
226HexVertexIter::HexVertexIter(const CellHandle& _ref_h,
227 const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
228BaseIter(_mesh, _ref_h, _max_laps) {
229
230 assert(_ref_h.is_valid());
231
232 HexahedralMeshTopologyKernel::Cell cell = _mesh->cell(_ref_h);
233 assert(cell.halffaces().size() == 6);
234
235 // Get first half-face
236 HalfFaceHandle curHF = *cell.halffaces().begin();
237 assert(curHF.is_valid());
238
239 // Get first half-edge
240 assert(_mesh->halfface(curHF).halfedges().size() == 4);
241 HalfEdgeHandle curHE = *_mesh->halfface(curHF).halfedges().begin();
242 assert(curHE.is_valid());
243
244 vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
245
246 curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
247
248 vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
249
250 curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
251
252 vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
253
254 curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
255
256 vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
257
258 curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
259 curHF = _mesh->adjacent_halfface_in_cell(curHF, curHE);
260 curHE = _mesh->opposite_halfedge_handle(curHE);
261 curHE = _mesh->next_halfedge_in_halfface(curHE, curHF);
262 curHE = _mesh->next_halfedge_in_halfface(curHE, curHF);
263 curHF = _mesh->adjacent_halfface_in_cell(curHF, curHE);
264 curHE = _mesh->opposite_halfedge_handle(curHE);
265
266 vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
267
268 curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
269
270 vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
271
272 curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
273
274 vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
275
276 vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
277
278 cur_index_ = 0;
279 BaseIter::valid(vertices_.size() > 0);
280 if(BaseIter::valid()) {
281 BaseIter::cur_handle(vertices_[cur_index_]);
282 }
283}
284
285
286HexVertexIter& HexVertexIter::operator--() {
287
288 if (cur_index_ == 0) {
289 cur_index_ = vertices_.size() - 1;
290 --lap_;
291 if (lap_ < 0)
292 BaseIter::valid(false);
293 } else {
294 --cur_index_;
295 }
296
297 BaseIter::cur_handle(vertices_[cur_index_]);
298
299 return *this;
300}
301
302
303HexVertexIter& HexVertexIter::operator++() {
304
305 ++cur_index_;
306 if(cur_index_ == vertices_.size()) {
307 cur_index_ = 0;
308 ++lap_;
309 if (lap_ >= max_laps_)
310 BaseIter::valid(false);
311 }
312
313 BaseIter::cur_handle(vertices_[cur_index_]);
314
315 return *this;
316}
317
318} // Namespace OpenVolumeMesh
A data structure basing on PolyhedralMesh with specializations for hexahedra.
Face opposite_halfface(HalfFaceHandle _halfFaceHandle) const
Get opposite halfface that corresponds to halfface with handle _halfFaceHandle.
CellHandle incident_cell(HalfFaceHandle _halfFaceHandle) const
Get cell that is incident to the given halfface.
const Cell & cell(CellHandle _cellHandle) const
Get cell with handle _cellHandle.
HalfEdgeHandle prev_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get previous halfedge within a halfface.
HalfEdgeHandle next_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get next halfedge within a halfface.
static EdgeHandle edge_handle(HalfEdgeHandle _h)
Handle conversion.
Face halfface(HalfFaceHandle _halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
Edge halfedge(HalfEdgeHandle _halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
HalfFaceHandle adjacent_halfface_in_cell(HalfFaceHandle _halfFaceHandle, HalfEdgeHandle _halfEdgeHandle) const
Get halfface that is adjacent (w.r.t. a common halfedge) within the same cell. It correctly handles s...