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  * *
37  * $Revision$ *
38  * $Date$ *
39  * $LastChangedBy$ *
40  * *
41 \*===========================================================================*/
42 
43 #include <set>
44 
45 #include "HexahedralMeshIterators.hh"
46 #include "HexahedralMeshTopologyKernel.hh"
47 
48 namespace OpenVolumeMesh {
49 
50 //================================================================================================
51 // CellSheetCellIter
52 //================================================================================================
53 
54 
55 CellSheetCellIter::CellSheetCellIter(const CellHandle& _ref_h,
56  const unsigned char _orthDir, const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
57 BaseIter(_mesh, _ref_h, _max_laps) {
58 
59  if(!_mesh->has_face_bottom_up_incidences()) {
60 #ifndef NDEBUG
61  std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
62 #endif
63  BaseIter::valid(false);
64  return;
65  }
66 
67  // First off, get all surrounding cells
68  std::vector<HalfFaceHandle> halffaces = _mesh->cell(_ref_h).halffaces();
69  for(std::vector<HalfFaceHandle>::const_iterator hf_it = halffaces.begin();
70  hf_it != halffaces.end(); ++hf_it) {
71  // Add those, that are perpendicular to the specified _orthDir
72  if(_mesh->orientation(*hf_it, _ref_h) != _orthDir &&
73  _mesh->orientation(*hf_it, _ref_h) != _mesh->opposite_orientation(_orthDir)) {
74  CellHandle ch = _mesh->incident_cell(_mesh->opposite_halfface_handle(*hf_it));
75  if(ch != TopologyKernel::InvalidCellHandle) {
76  neighb_sheet_cell_hs_.push_back(ch);
77  }
78  }
79  }
80 
81  // Remove all duplicate entries
82  std::sort(neighb_sheet_cell_hs_.begin(), neighb_sheet_cell_hs_.end());
83  neighb_sheet_cell_hs_.resize(std::unique(neighb_sheet_cell_hs_.begin(), neighb_sheet_cell_hs_.end()) - neighb_sheet_cell_hs_.begin());
84 
85  cur_index_ = 0;
86  BaseIter::valid(neighb_sheet_cell_hs_.size() > 0);
87  if(BaseIter::valid()) {
88  BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
89  }
90 }
91 
92 
93 CellSheetCellIter& CellSheetCellIter::operator--() {
94 
95  if (cur_index_ == 0) {
96  cur_index_ = neighb_sheet_cell_hs_.size() - 1;
97  --lap_;
98  if (lap_ < 0)
99  BaseIter::valid(false);
100  } else {
101  --cur_index_;
102  }
103 
104  BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
105 
106  return *this;
107 }
108 
109 
110 CellSheetCellIter& CellSheetCellIter::operator++() {
111 
112  ++cur_index_;
113  if(cur_index_ == neighb_sheet_cell_hs_.size()) {
114  cur_index_ = 0;
115  ++lap_;
116  if (lap_ >= max_laps_)
117  BaseIter::valid(false);
118  }
119 
120  BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
121 
122  return *this;
123 }
124 
125 //================================================================================================
126 // HalfFaceSheetHalfFaceIter
127 //================================================================================================
128 
129 
130 HalfFaceSheetHalfFaceIter::HalfFaceSheetHalfFaceIter(const HalfFaceHandle& _ref_h,
131  const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
132 BaseIter(_mesh, _ref_h, _max_laps) {
133 
134  if(!_mesh->has_face_bottom_up_incidences()) {
135 #ifndef NDEBUG
136  std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
137 #endif
138  BaseIter::valid(false);
139  return;
140  }
141 
142  /*
143  * Each halfface uniquely belongs to either a cell
144  * or the boundary. If the halfface belongs
145  * to a cell, it suffices to determine the local axis
146  * the halfface represents w.r.t. the cell and to
147  * iterate over all neighboring cells orthogonal to
148  * this direction. We have to find those halffaces
149  * of the neighboring cells that contain exactly one
150  * of the initial halfface's opposite halfedges.
151  */
152 
153  if(_mesh->is_boundary(_ref_h)) {
154 #ifndef NDEBUG
155  std::cerr << "HalfFaceSheetHalfFaceIter: HalfFace is boundary!" << std::endl;
156 #endif
157  BaseIter::valid(false);
158  return;
159  }
160 
161  CellHandle ch = _mesh->incident_cell(_ref_h);
162  unsigned char orientation = _mesh->orientation(_ref_h, ch);
163  std::vector<HalfEdgeHandle> hes_v = _mesh->opposite_halfface(_mesh->halfface(_ref_h)).halfedges();
164  std::set<HalfEdgeHandle> hes;
165  hes.insert(hes_v.begin(), hes_v.end());
166 
167  for(CellSheetCellIter csc_it = _mesh->csc_iter(ch, orientation);
168  csc_it.valid(); ++csc_it) {
169 
170  std::vector<HalfFaceHandle> hfs = _mesh->cell(*csc_it).halffaces();
171  for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin();
172  hf_it != hfs.end(); ++hf_it) {
173 
174  std::vector<HalfEdgeHandle> hf_hes = _mesh->halfface(*hf_it).halfedges();
175  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hf_hes.begin();
176  he_it != hf_hes.end(); ++he_it) {
177 
178  if(hes.count(*he_it) > 0) {
179  // Found halfface that lies on the same sheet
180  adjacent_halffaces_.push_back(*hf_it);
181  common_edges_.push_back(_mesh->edge_handle(*he_it));
182  break;
183  }
184  }
185  }
186  }
187 
188  cur_index_ = 0;
189  BaseIter::valid(adjacent_halffaces_.size() > 0);
190  if(BaseIter::valid()) {
191  BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
192  }
193 }
194 
195 
196 HalfFaceSheetHalfFaceIter& HalfFaceSheetHalfFaceIter::operator--() {
197 
198  if (cur_index_ == 0) {
199  cur_index_ = adjacent_halffaces_.size() - 1;
200  --lap_;
201  if (lap_ < 0)
202  BaseIter::valid(false);
203  } else {
204  --cur_index_;
205  }
206 
207  BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
208 
209  return *this;
210 }
211 
212 
213 HalfFaceSheetHalfFaceIter& HalfFaceSheetHalfFaceIter::operator++() {
214 
215  ++cur_index_;
216  if(cur_index_ == adjacent_halffaces_.size()) {
217  cur_index_ = 0;
218  ++lap_;
219  if (lap_ >= max_laps_)
220  BaseIter::valid(false);
221  }
222 
223  BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
224 
225  return *this;
226 }
227 
228 //================================================================================================
229 // HexVertexIter
230 //================================================================================================
231 
232 
233 HexVertexIter::HexVertexIter(const CellHandle& _ref_h,
234  const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
235 BaseIter(_mesh, _ref_h, _max_laps) {
236 
237  assert(_ref_h.is_valid());
238  assert(_mesh->cell(_ref_h).halffaces().size() == 6);
239 
240  // Get first half-face
241  HalfFaceHandle curHF = *_mesh->cell(_ref_h).halffaces().begin();
242  assert(curHF.is_valid());
243 
244  // Get first half-edge
245  assert(_mesh->halfface(curHF).halfedges().size() == 4);
246  HalfEdgeHandle curHE = *_mesh->halfface(curHF).halfedges().begin();
247  assert(curHE.is_valid());
248 
249  vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
250 
251  curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
252 
253  vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
254 
255  curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
256 
257  vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
258 
259  curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
260 
261  vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
262 
263  curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
264  curHF = _mesh->adjacent_halfface_in_cell(curHF, curHE);
265  curHE = _mesh->opposite_halfedge_handle(curHE);
266  curHE = _mesh->next_halfedge_in_halfface(curHE, curHF);
267  curHE = _mesh->next_halfedge_in_halfface(curHE, curHF);
268  curHF = _mesh->adjacent_halfface_in_cell(curHF, curHE);
269  curHE = _mesh->opposite_halfedge_handle(curHE);
270 
271  vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
272 
273  curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
274 
275  vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
276 
277  curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
278 
279  vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
280 
281  vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
282 
283  cur_index_ = 0;
284  BaseIter::valid(vertices_.size() > 0);
285  if(BaseIter::valid()) {
286  BaseIter::cur_handle(vertices_[cur_index_]);
287  }
288 }
289 
290 
291 HexVertexIter& HexVertexIter::operator--() {
292 
293  if (cur_index_ == 0) {
294  cur_index_ = vertices_.size() - 1;
295  --lap_;
296  if (lap_ < 0)
297  BaseIter::valid(false);
298  } else {
299  --cur_index_;
300  }
301 
302  BaseIter::cur_handle(vertices_[cur_index_]);
303 
304  return *this;
305 }
306 
307 
308 HexVertexIter& HexVertexIter::operator++() {
309 
310  ++cur_index_;
311  if(cur_index_ == vertices_.size()) {
312  cur_index_ = 0;
313  ++lap_;
314  if (lap_ >= max_laps_)
315  BaseIter::valid(false);
316  }
317 
318  BaseIter::cur_handle(vertices_[cur_index_]);
319 
320  return *this;
321 }
322 
323 } // Namespace OpenVolumeMesh
Edge halfedge(const HalfEdgeHandle &_halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
HalfEdgeHandle prev_halfedge_in_halfface(const HalfEdgeHandle &_heh, const HalfFaceHandle &_hfh) const
Get previous halfedge within a halfface.
const Cell & cell(const CellHandle &_cellHandle) const
Get cell with handle _cellHandle.
CellHandle incident_cell(const HalfFaceHandle &_halfFaceHandle) const
Get cell that is incident to the given halfface.
static EdgeHandle edge_handle(const HalfEdgeHandle &_h)
Handle conversion.
Face halfface(const HalfFaceHandle &_halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
HalfFaceHandle adjacent_halfface_in_cell(const HalfFaceHandle &_halfFaceHandle, const HalfEdgeHandle &_halfEdgeHandle) const
Get halfface that is adjacent (w.r.t. a common halfedge) within the same cell.
A data structure basing on PolyhedralMesh with specializations for hexahedra.
Face opposite_halfface(const HalfFaceHandle &_halfFaceHandle) const
Get opposite halfface that corresponds to halfface with handle _halfFaceHandle.
HalfEdgeHandle next_halfedge_in_halfface(const HalfEdgeHandle &_heh, const HalfFaceHandle &_hfh) const
Get next halfedge within a halfface.