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
78 class HexahedralMeshTopologyKernel : public TopologyKernel {
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) {
305 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
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;
311 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, o_he);
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) {
321 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
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;
327 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, o_he);
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 */
OpenVolumeMesh
Definition: ColorAttrib.hh:53
OpenVolumeMesh::HexahedralMeshTopologyKernel
A data structure basing on PolyhedralMesh with specializations for hexahedra.
Definition: HexahedralMeshTopologyKernel.hh:78
OpenVolumeMesh::HandleT
Definition: OpenVolumeMeshHandle.hh:108
OpenVolumeMesh::HexahedralMeshTopologyKernel::add_cell
CellHandle add_cell(const std::vector< HalfFaceHandle > &_halffaces, bool _topologyCheck=false) override
Overridden function.
Definition: HexahedralMeshTopologyKernel.cc:82
OpenVolumeMesh::HalfEdgeHalfFaceIter
Definition: Iterators.hh:369
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:2281
OpenVolumeMesh::HexahedralMeshTopologyKernel::add_face
FaceHandle add_face(const std::vector< HalfEdgeHandle > &_halfedges, bool _topologyCheck=false) override
Add face via incident edges.
Definition: HexahedralMeshTopologyKernel.cc:48
OpenVolumeMesh::TopologyKernel::cell
const Cell & cell(const CellHandle &_cellHandle) const
Get cell with handle _cellHandle.
Definition: TopologyKernel.cc:2023
OpenVolumeMesh::TopologyKernel
Definition: TopologyKernel.hh:49