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