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
86 class HexahedralMeshTopologyKernel : public TopologyKernel {
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
103 HexahedralMeshTopologyKernel();
104
105 // Destructor
106 ~HexahedralMeshTopologyKernel();
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) {
313 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
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;
319 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, o_he);
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) {
329 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
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;
335 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, o_he);
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 */
OpenVolumeMesh::HexahedralMeshTopologyKernel::add_cell
virtual CellHandle add_cell(const std::vector< HalfFaceHandle > &_halffaces, bool _topologyCheck=false)
Overridden function.
Definition: HexahedralMeshTopologyKernel.cc:96
OpenVolumeMesh::TopologyKernel::cell
const Cell & cell(const CellHandle &_cellHandle) const
Get cell with handle _cellHandle.
Definition: TopologyKernel.cc:2009
OpenVolumeMesh::TopologyKernel
Definition: TopologyKernel.hh:57
OpenVolumeMesh::HalfEdgeHalfFaceIter
Definition: Iterators.hh:365
OpenVolumeMesh::HexahedralMeshTopologyKernel
A data structure basing on PolyhedralMesh with specializations for hexahedra.
Definition: HexahedralMeshTopologyKernel.hh:86
OpenVolumeMesh::HandleT
Definition: OpenVolumeMeshHandle.hh:93
OpenVolumeMesh::TopologyKernel::adjacent_halfface_in_cell
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.
Definition: TopologyKernel.cc:2267
OpenVolumeMesh
Definition: ColorAttrib.hh:53
OpenVolumeMesh::HexahedralMeshTopologyKernel::add_face
virtual FaceHandle add_face(const std::vector< HalfEdgeHandle > &_halfedges, bool _topologyCheck=false)
Add face via incident edges.
Definition: HexahedralMeshTopologyKernel.cc:62