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