Developer Documentation
Loading...
Searching...
No Matches
HexahedralMeshTopologyKernel.hh
1#pragma once
2/*===========================================================================*\
3 * *
4 * OpenVolumeMesh *
5 * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
6 * www.openvolumemesh.org *
7 * *
8 *---------------------------------------------------------------------------*
9 * This file is part of OpenVolumeMesh. *
10 * *
11 * OpenVolumeMesh is free software: you can redistribute it and/or modify *
12 * it under the terms of the GNU Lesser General Public License as *
13 * published by the Free Software Foundation, either version 3 of *
14 * the License, or (at your option) any later version with the *
15 * following exceptions: *
16 * *
17 * If other files instantiate templates or use macros *
18 * or inline functions from this file, or you compile this file and *
19 * link it with other files to produce an executable, this file does *
20 * not by itself cause the resulting executable to be covered by the *
21 * GNU Lesser General Public License. This exception does not however *
22 * invalidate any other reasons why the executable file might be *
23 * covered by the GNU Lesser General Public License. *
24 * *
25 * OpenVolumeMesh is distributed in the hope that it will be useful, *
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
28 * GNU Lesser General Public License for more details. *
29 * *
30 * You should have received a copy of the GNU LesserGeneral Public *
31 * License along with OpenVolumeMesh. If not, *
32 * see <http://www.gnu.org/licenses/>. *
33 * *
34\*===========================================================================*/
35
36#ifndef NDEBUG
37#include <iostream>
38#endif
39#include <set>
40
41#include <OpenVolumeMesh/Core/TopologyKernel.hh>
42#include <OpenVolumeMesh/Mesh/HexahedralMeshIterators.hh>
43#include <OpenVolumeMesh/Config/Export.hh>
44
45namespace OpenVolumeMesh {
46
78public:
79
80 // Orientation constants
81 static const unsigned char XF = 0;
82 static const unsigned char XB = 1;
83 static const unsigned char YF = 2;
84 static const unsigned char YB = 3;
85 static const unsigned char ZF = 4;
86 static const unsigned char ZB = 5;
87 static const unsigned char INVALID = 6;
88
89 static inline unsigned char opposite_orientation(const unsigned char _d) {
90 return static_cast<unsigned char>(_d % 2 == 0 ? _d + 1 : _d - 1);
91 }
92
93 // Constructor
95
96 // Destructor
97 ~HexahedralMeshTopologyKernel() override = default;
98
99 // Overridden function
100 FaceHandle add_face(std::vector<HalfEdgeHandle> _halfedges, bool _topologyCheck = false) override;
101
102 // Overridden function
103 FaceHandle add_face(const std::vector<VertexHandle>& _vertices) override;
104
106 CellHandle add_cell(std::vector<HalfFaceHandle> _halffaces, bool _topologyCheck = false) override;
107
108private:
109
110 bool check_halfface_ordering(const std::vector<HalfFaceHandle>& _hfs) const;
111
112public:
113
134 CellHandle add_cell(const std::vector<VertexHandle>& _vertices, bool _topologyCheck = false);
135
136 // ======================= Specialized Iterators =============================
137
138 friend class CellSheetCellIter;
139 friend class HalfFaceSheetHalfFaceIter;
140 friend class HexVertexIter;
141
142 typedef class CellSheetCellIter CellSheetCellIter;
143 typedef class HalfFaceSheetHalfFaceIter HalfFaceSheetHalfFaceIter;
144 typedef class HexVertexIter HexVertexIter;
145
146 using TopologyKernel::is_valid;
147
148 CellSheetCellIter csc_iter(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(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(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(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(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(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(HalfFaceHandle _hfh, CellHandle _ch) const {
181
182 assert(is_valid(_hfh));
183 assert(is_valid(_ch));
184
185 if(orientation(_hfh, _ch) == XF) return xback_halfface(_ch);
186 if(orientation(_hfh, _ch) == XB) return xfront_halfface(_ch);
187 if(orientation(_hfh, _ch) == YF) return yback_halfface(_ch);
188 if(orientation(_hfh, _ch) == YB) return yfront_halfface(_ch);
189 if(orientation(_hfh, _ch) == ZF) return zback_halfface(_ch);
190 if(orientation(_hfh, _ch) == ZB) return zfront_halfface(_ch);
191
192 return TopologyKernel::InvalidHalfFaceHandle;
193 }
194
195 inline HalfFaceHandle xfront_halfface(CellHandle _ch) const {
196 assert(is_valid(_ch));
197
198 return TopologyKernel::cell(_ch).halffaces()[XF];
199 }
200
201 inline HalfFaceHandle xback_halfface(CellHandle _ch) const {
202 assert(is_valid(_ch));
203
204 return TopologyKernel::cell(_ch).halffaces()[XB];
205 }
206
207 inline HalfFaceHandle yfront_halfface(CellHandle _ch) const {
208 assert(is_valid(_ch));
209
210 return TopologyKernel::cell(_ch).halffaces()[YF];
211 }
212
213 inline HalfFaceHandle yback_halfface(CellHandle _ch) const {
214 assert(is_valid(_ch));
215
216 return TopologyKernel::cell(_ch).halffaces()[YB];
217 }
218
219 inline HalfFaceHandle zfront_halfface(CellHandle _ch) const {
220 assert(is_valid(_ch));
221
222 return TopologyKernel::cell(_ch).halffaces()[ZF];
223 }
224
225 inline HalfFaceHandle zback_halfface(CellHandle _ch) const {
226 assert(is_valid(_ch));
227
228 return TopologyKernel::cell(_ch).halffaces()[ZB];
229 }
230
231 unsigned char orientation(HalfFaceHandle _hfh, CellHandle _ch) const {
232 assert(is_valid(_ch));
233
234 std::vector<HalfFaceHandle> halffaces = TopologyKernel::cell(_ch).halffaces();
235 for(unsigned int i = 0; i < halffaces.size(); ++i) {
236 if(halffaces[i] == _hfh) return (unsigned char)i;
237 }
238
239 return INVALID;
240 }
241
242 static inline unsigned char orthogonal_orientation(const unsigned char _o1, const unsigned char _o2) {
243
244 if(_o1 == XF && _o2 == YF) return ZF;
245 if(_o1 == XF && _o2 == YB) return ZB;
246 if(_o1 == XF && _o2 == ZF) return YB;
247 if(_o1 == XF && _o2 == ZB) return YF;
248 if(_o1 == XB && _o2 == YF) return ZB;
249 if(_o1 == XB && _o2 == YB) return ZF;
250 if(_o1 == XB && _o2 == ZF) return YF;
251 if(_o1 == XB && _o2 == ZB) return YB;
252
253 if(_o1 == YF && _o2 == XF) return ZB;
254 if(_o1 == YF && _o2 == XB) return ZF;
255 if(_o1 == YF && _o2 == ZF) return XF;
256 if(_o1 == YF && _o2 == ZB) return XB;
257 if(_o1 == YB && _o2 == XF) return ZF;
258 if(_o1 == YB && _o2 == XB) return ZB;
259 if(_o1 == YB && _o2 == ZF) return XB;
260 if(_o1 == YB && _o2 == ZB) return XF;
261
262 if(_o1 == ZF && _o2 == YF) return XB;
263 if(_o1 == ZF && _o2 == YB) return XF;
264 if(_o1 == ZF && _o2 == XF) return YF;
265 if(_o1 == ZF && _o2 == XB) return YB;
266 if(_o1 == ZB && _o2 == YF) return XF;
267 if(_o1 == ZB && _o2 == YB) return XB;
268 if(_o1 == ZB && _o2 == XF) return YB;
269 if(_o1 == ZB && _o2 == XB) return YF;
270
271 return INVALID;
272
273 }
274
275 inline HalfFaceHandle get_oriented_halfface(const unsigned char _o, CellHandle _ch) const {
276
277 if(_o == XF) return xfront_halfface(_ch);
278 if(_o == XB) return xback_halfface(_ch);
279 if(_o == YF) return yfront_halfface(_ch);
280 if(_o == YB) return yback_halfface(_ch);
281 if(_o == ZF) return zfront_halfface(_ch);
282 if(_o == ZB) return zback_halfface(_ch);
283 return TopologyKernel::InvalidHalfFaceHandle;
284 }
285
286 HalfFaceHandle adjacent_halfface_on_sheet(HalfFaceHandle _hfh, HalfEdgeHandle _heh) const {
287
288 if(!TopologyKernel::has_face_bottom_up_incidences()) {
289#ifndef NDEBUG
290 std::cerr << "No bottom-up incidences computed so far, could not get adjacent halfface on sheet!" << std::endl;
291#endif
292 return TopologyKernel::InvalidHalfFaceHandle;
293 }
294
295 HalfFaceHandle n_hf = _hfh;
296 HalfEdgeHandle n_he = _heh;
297
298 // Try the 1st way
299 while(true) {
300 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
301 if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
302 n_hf = TopologyKernel::opposite_halfface_handle(n_hf);
303 if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
304 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
305 if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
306 else return n_hf;
307 }
308
309 n_hf = TopologyKernel::opposite_halfface_handle(_hfh);
310 n_he = TopologyKernel::opposite_halfedge_handle(_heh);
311
312 // Try the 2nd way
313 while(true) {
314 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
315 if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
316 n_hf = TopologyKernel::opposite_halfface_handle(n_hf);
317 if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
318 n_hf = TopologyKernel::adjacent_halfface_in_cell(n_hf, n_he);
319 if(n_hf == TopologyKernel::InvalidHalfFaceHandle) break;
320 else return TopologyKernel::opposite_halfface_handle(n_hf);
321 }
322
323 return TopologyKernel::InvalidHalfFaceHandle;
324 }
325
326 HalfFaceHandle adjacent_halfface_on_surface(HalfFaceHandle _hfh, HalfEdgeHandle _heh) const {
327
328 for(OpenVolumeMesh::HalfEdgeHalfFaceIter hehf_it = TopologyKernel::hehf_iter(_heh);
329 hehf_it.valid(); ++hehf_it) {
330 if(*hehf_it == _hfh) continue;
331 if(TopologyKernel::is_boundary(*hehf_it)) {
332 return *hehf_it;
333 }
334 if(TopologyKernel::is_boundary(TopologyKernel::opposite_halfface_handle(*hehf_it))) {
335 return TopologyKernel::opposite_halfface_handle(*hehf_it);
336 }
337 }
338 return TopologyKernel::InvalidHalfFaceHandle;
339 }
340
341 HalfFaceHandle neighboring_outside_halfface(HalfFaceHandle _hfh, HalfEdgeHandle _heh) const {
342
343 if(!TopologyKernel::has_face_bottom_up_incidences()) {
344#ifndef NDEBUG
345 std::cerr << "No bottom-up incidences computed so far, could not get neighboring outside halfface!" << std::endl;
346#endif
347 return TopologyKernel::InvalidHalfFaceHandle;
348 }
349
350 for(OpenVolumeMesh::HalfEdgeHalfFaceIter hehf_it = TopologyKernel::hehf_iter(_heh);
351 hehf_it; ++hehf_it) {
352 if(*hehf_it == _hfh) continue;
353 if(TopologyKernel::is_boundary(*hehf_it)) return *hehf_it;
354 if(TopologyKernel::is_boundary(TopologyKernel::opposite_halfface_handle(*hehf_it)))
355 return TopologyKernel::opposite_halfface_handle(*hehf_it);
356 }
357
358 return TopologyKernel::InvalidHalfFaceHandle;
359 }
360
361private:
362
363 HalfFaceHandle get_adjacent_halfface(HalfFaceHandle _hfh, HalfEdgeHandle _heh,
364 const std::vector<HalfFaceHandle>& _halffaces) const;
365
366};
367
368} // Namespace OpenVolumeMesh
A data structure basing on PolyhedralMesh with specializations for hexahedra.