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