Developer Documentation
HexahedralMeshTopologyKernel.hh
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 #ifndef HEXAHEDRALMESHTOPOLOGYKERNEL_HH
36 #define HEXAHEDRALMESHTOPOLOGYKERNEL_HH
37 
38 #ifndef NDEBUG
39 #include <iostream>
40 #endif
41 #include <set>
42 
43 #include "../Core/TopologyKernel.hh"
44 #include "HexahedralMeshIterators.hh"
45 
46 namespace OpenVolumeMesh {
47 
79 public:
80 
81  // Orientation constants
82  static const unsigned char XF = 0;
83  static const unsigned char XB = 1;
84  static const unsigned char YF = 2;
85  static const unsigned char YB = 3;
86  static const unsigned char ZF = 4;
87  static const unsigned char ZB = 5;
88  static const unsigned char INVALID = 6;
89 
90  static inline unsigned char opposite_orientation(const unsigned char _d) {
91  return static_cast<unsigned char>(_d % 2 == 0 ? _d + 1 : _d - 1);
92  }
93 
94  // Constructor
95  HexahedralMeshTopologyKernel() = default;
96 
97  // Destructor
98  ~HexahedralMeshTopologyKernel() override = default;
99 
100  // Overridden function
101  FaceHandle add_face(const std::vector<HalfEdgeHandle>& _halfedges, bool _topologyCheck = false) override;
102 
103  // Overridden function
104  FaceHandle add_face(const std::vector<VertexHandle>& _vertices) override;
105 
107  CellHandle add_cell(const std::vector<HalfFaceHandle>& _halffaces, bool _topologyCheck = false) override;
108 
109 private:
110 
111  bool check_halfface_ordering(const std::vector<HalfFaceHandle>& _hfs) const;
112 
113 public:
114 
135  CellHandle add_cell(const std::vector<VertexHandle>& _vertices, bool _topologyCheck = false);
136 
137  // ======================= Specialized Iterators =============================
138 
139  friend class CellSheetCellIter;
140  friend class HalfFaceSheetHalfFaceIter;
141  friend class HexVertexIter;
142 
143  typedef class CellSheetCellIter CellSheetCellIter;
144  typedef class HalfFaceSheetHalfFaceIter HalfFaceSheetHalfFaceIter;
145  typedef class HexVertexIter HexVertexIter;
146 
147  CellSheetCellIter csc_iter(const CellHandle& _ref_h, const unsigned char _orthDir, int _max_laps = 1) const {
148  return CellSheetCellIter(_ref_h, _orthDir, this, _max_laps);
149  }
150 
151  std::pair<CellSheetCellIter,CellSheetCellIter> cell_sheet_cells(const CellHandle& _ref_h, const unsigned char _orthDir, int _max_laps = 1) const {
152  CellSheetCellIter begin = csc_iter(_ref_h, _orthDir, _max_laps);
153  CellSheetCellIter end = make_end_circulator(begin);
154  return std::make_pair(begin, end);
155  }
156 
157  HalfFaceSheetHalfFaceIter hfshf_iter(const HalfFaceHandle& _ref_h, int _max_laps = 1) const {
158  return HalfFaceSheetHalfFaceIter(_ref_h, this, _max_laps);
159  }
160 
161  std::pair<HalfFaceSheetHalfFaceIter,HalfFaceSheetHalfFaceIter> halfface_sheet_halffaces(const HalfFaceHandle& _ref_h, int _max_laps = 1) const {
162  HalfFaceSheetHalfFaceIter begin = hfshf_iter(_ref_h, _max_laps);
163  HalfFaceSheetHalfFaceIter end = make_end_circulator(begin);
164  return std::make_pair(begin, end);
165  }
166 
167  HexVertexIter hv_iter(const CellHandle& _ref_h, int _max_laps = 1) const {
168  return HexVertexIter(_ref_h, this, _max_laps);
169  }
170 
171  std::pair<HexVertexIter,HexVertexIter> hex_vertices(const CellHandle& _ref_h, int _max_laps = 1) const {
172  HexVertexIter begin = hv_iter(_ref_h, _max_laps);
173  HexVertexIter end = make_end_circulator(begin);
174  return std::make_pair(begin, end);
175  }
176 
177  // ======================= Connectivity functions =============================
178 
179  inline HalfFaceHandle opposite_halfface_handle_in_cell(const HalfFaceHandle& _hfh, const CellHandle& _ch) const {
180 
181  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
182 
183  if(orientation(_hfh, _ch) == XF) return xback_halfface(_ch);
184  if(orientation(_hfh, _ch) == XB) return xfront_halfface(_ch);
185  if(orientation(_hfh, _ch) == YF) return yback_halfface(_ch);
186  if(orientation(_hfh, _ch) == YB) return yfront_halfface(_ch);
187  if(orientation(_hfh, _ch) == ZF) return zback_halfface(_ch);
188  if(orientation(_hfh, _ch) == ZB) return zfront_halfface(_ch);
189 
190  return TopologyKernel::InvalidHalfFaceHandle;
191  }
192 
193  inline HalfFaceHandle xfront_halfface(const CellHandle& _ch) const {
194 
195  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
196 
197  return TopologyKernel::cell(_ch).halffaces()[XF];
198  }
199 
200  inline HalfFaceHandle xback_halfface(const CellHandle& _ch) const {
201 
202  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
203 
204  return TopologyKernel::cell(_ch).halffaces()[XB];
205  }
206 
207  inline HalfFaceHandle yfront_halfface(const CellHandle& _ch) const {
208 
209  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
210 
211  return TopologyKernel::cell(_ch).halffaces()[YF];
212  }
213 
214  inline HalfFaceHandle yback_halfface(const CellHandle& _ch) const {
215 
216  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
217 
218  return TopologyKernel::cell(_ch).halffaces()[YB];
219  }
220 
221  inline HalfFaceHandle zfront_halfface(const CellHandle& _ch) const {
222 
223  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
224 
225  return TopologyKernel::cell(_ch).halffaces()[ZF];
226  }
227 
228  inline HalfFaceHandle zback_halfface(const CellHandle& _ch) const {
229 
230  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
231 
232  return TopologyKernel::cell(_ch).halffaces()[ZB];
233  }
234 
235  unsigned char orientation(const HalfFaceHandle& _hfh, const CellHandle& _ch) const {
236 
237  assert((unsigned int)_ch.idx() < TopologyKernel::cells_.size());
238 
239  std::vector<HalfFaceHandle> halffaces = TopologyKernel::cell(_ch).halffaces();
240  for(unsigned int i = 0; i < halffaces.size(); ++i) {
241  if(halffaces[i] == _hfh) return (unsigned char)i;
242  }
243 
244  return INVALID;
245  }
246 
247  static inline unsigned char orthogonal_orientation(const unsigned char _o1, const unsigned char _o2) {
248 
249  if(_o1 == XF && _o2 == YF) return ZF;
250  if(_o1 == XF && _o2 == YB) return ZB;
251  if(_o1 == XF && _o2 == ZF) return YB;
252  if(_o1 == XF && _o2 == ZB) return YF;
253  if(_o1 == XB && _o2 == YF) return ZB;
254  if(_o1 == XB && _o2 == YB) return ZF;
255  if(_o1 == XB && _o2 == ZF) return YF;
256  if(_o1 == XB && _o2 == ZB) return YB;
257 
258  if(_o1 == YF && _o2 == XF) return ZB;
259  if(_o1 == YF && _o2 == XB) return ZF;
260  if(_o1 == YF && _o2 == ZF) return XF;
261  if(_o1 == YF && _o2 == ZB) return XB;
262  if(_o1 == YB && _o2 == XF) return ZF;
263  if(_o1 == YB && _o2 == XB) return ZB;
264  if(_o1 == YB && _o2 == ZF) return XB;
265  if(_o1 == YB && _o2 == ZB) return XF;
266 
267  if(_o1 == ZF && _o2 == YF) return XB;
268  if(_o1 == ZF && _o2 == YB) return XF;
269  if(_o1 == ZF && _o2 == XF) return YF;
270  if(_o1 == ZF && _o2 == XB) return YB;
271  if(_o1 == ZB && _o2 == YF) return XF;
272  if(_o1 == ZB && _o2 == YB) return XB;
273  if(_o1 == ZB && _o2 == XF) return YB;
274  if(_o1 == ZB && _o2 == XB) return YF;
275 
276  return INVALID;
277 
278  }
279 
280  inline HalfFaceHandle get_oriented_halfface(const unsigned char _o, const CellHandle& _ch) const {
281 
282  if(_o == XF) return xfront_halfface(_ch);
283  if(_o == XB) return xback_halfface(_ch);
284  if(_o == YF) return yfront_halfface(_ch);
285  if(_o == YB) return yback_halfface(_ch);
286  if(_o == ZF) return zfront_halfface(_ch);
287  if(_o == ZB) return zback_halfface(_ch);
288  return TopologyKernel::InvalidHalfFaceHandle;
289  }
290 
291  HalfFaceHandle adjacent_halfface_on_sheet(const HalfFaceHandle& _hfh, const HalfEdgeHandle& _heh) const {
292 
293  if(!TopologyKernel::has_face_bottom_up_incidences()) {
294 #ifndef NDEBUG
295  std::cerr << "No bottom-up incidences computed so far, could not get adjacent halfface on sheet!" << std::endl;
296 #endif
297  return TopologyKernel::InvalidHalfFaceHandle;
298  }
299 
300  HalfFaceHandle n_hf = _hfh;
301  HalfEdgeHandle n_he = _heh;
302 
303  // Try the 1st way
304  while(true) {
306  if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
307  n_hf = TopologyKernel::opposite_halfface_handle(n_hf);
308  if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
309  HalfEdgeHandle o_he = TopologyKernel::opposite_halfedge_handle(n_he);
310  if(o_he == TopologyKernel::InvalidHalfEdgeHandle) break;
312  if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
313  else return n_hf;
314  }
315 
316  n_hf = TopologyKernel::opposite_halfface_handle(_hfh);
317  n_he = TopologyKernel::opposite_halfedge_handle(_heh);
318 
319  // Try the 2nd way
320  while(true) {
322  if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
323  n_hf = TopologyKernel::opposite_halfface_handle(n_hf);
324  if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
325  HalfEdgeHandle o_he = TopologyKernel::opposite_halfedge_handle(n_he);
326  if(o_he == TopologyKernel::InvalidHalfEdgeHandle) break;
328  if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
329  else return TopologyKernel::opposite_halfface_handle(n_hf);
330  }
331 
332  return TopologyKernel::InvalidHalfFaceHandle;
333  }
334 
335  HalfFaceHandle adjacent_halfface_on_surface(const HalfFaceHandle& _hfh, const HalfEdgeHandle& _heh) const {
336 
337  for(OpenVolumeMesh::HalfEdgeHalfFaceIter hehf_it = TopologyKernel::hehf_iter(_heh);
338  hehf_it.valid(); ++hehf_it) {
339  if(*hehf_it == _hfh) continue;
340  if(TopologyKernel::is_boundary(*hehf_it)) {
341  return *hehf_it;
342  }
343  if(TopologyKernel::is_boundary(TopologyKernel::opposite_halfface_handle(*hehf_it))) {
344  return TopologyKernel::opposite_halfface_handle(*hehf_it);
345  }
346  }
347  return TopologyKernel::InvalidHalfFaceHandle;
348  }
349 
350  HalfFaceHandle neighboring_outside_halfface(const HalfFaceHandle& _hfh, const HalfEdgeHandle& _heh) const {
351 
352  if(!TopologyKernel::has_face_bottom_up_incidences()) {
353 #ifndef NDEBUG
354  std::cerr << "No bottom-up incidences computed so far, could not get neighboring outside halfface!" << std::endl;
355 #endif
356  return TopologyKernel::InvalidHalfFaceHandle;
357  }
358 
359  for(OpenVolumeMesh::HalfEdgeHalfFaceIter hehf_it = TopologyKernel::hehf_iter(_heh);
360  hehf_it; ++hehf_it) {
361  if(*hehf_it == _hfh) continue;
362  if(TopologyKernel::is_boundary(*hehf_it)) return *hehf_it;
363  if(TopologyKernel::is_boundary(TopologyKernel::opposite_halfface_handle(*hehf_it)))
364  return TopologyKernel::opposite_halfface_handle(*hehf_it);
365  }
366 
367  return TopologyKernel::InvalidHalfFaceHandle;
368  }
369 
370 private:
371 
372  const HalfFaceHandle& get_adjacent_halfface(const HalfFaceHandle& _hfh, const HalfEdgeHandle& _heh,
373  const std::vector<HalfFaceHandle>& _halffaces) const;
374 
375 };
376 
377 } // Namespace OpenVolumeMesh
378 
379 #endif /* HEXAHEDRALMESHTOPOLOGYKERNEL_HH */
A data structure basing on PolyhedralMesh with specializations for hexahedra.
CellHandle add_cell(const std::vector< HalfFaceHandle > &_halffaces, bool _topologyCheck=false) override
Overridden function.
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.
FaceHandle add_face(const std::vector< HalfEdgeHandle > &_halfedges, bool _topologyCheck=false) override
Add face via incident edges.
const Cell & cell(const CellHandle &_cellHandle) const
Get cell with handle _cellHandle.