GemaMesh
The GeMA Mesh Plugin
uibhmTopology.h
Go to the documentation of this file.
1 /************************************************************************
2 **
3 ** Copyright (C) 2014 by Carlos Augusto Teixera Mendes
4 ** All rights reserved.
5 **
6 ** This file is part of the "GeMA" software. It's use should respect
7 ** the terms in the license agreement that can be found together
8 ** with this source code.
9 ** It is provided AS IS, with NO WARRANTY OF ANY KIND,
10 ** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
11 ** A PARTICULAR PURPOSE.
12 **
13 ************************************************************************/
14 
24 #ifndef _UIBHM_TOPOLOGY_H_
25 #define _UIBHM_TOPOLOGY_H_
26 
27 #include <vector>
28 #include <assert.h>
29 
30 #include "gmpGemaMeshConfig.h"
31 
32 #include <gmLog.h>
33 
34 class GmCellMesh;
35 template <class T> class UibhmQuery;
36 template <class T> class UibhmSurfaceQuery;
37 template <class T> class UibhmSolidQuery;
38 
40 #define GMP_UIBHM_SIDE_BITS 4
41 
43 #define GM_UIBHM_SIDE_MASK (~(~0u >> GMP_UIBHM_SIDE_BITS))
44 
46 #define GMP_UIBHM_MAX_SIDE_VALUE ((1 << GMP_UIBHM_SIDE_BITS) - 1)
47 
49 #define GMP_UIBHM_BORDER_SIDE GMP_UIBHM_MAX_SIDE_VALUE
50 
52 #define GMP_UIBHM_MID_SIDE (GMP_UIBHM_MAX_SIDE_VALUE - 1)
53 
55 #define GMP_UIBHM_MAX_NUM_SIDES GMP_UIBHM_MID_SIDE
56 
60 #define GMP_UIBHM_CELL_BITS (32 - GMP_UIBHM_SIDE_BITS)
61 
63 #define GM_UIBHM_CELL_MASK (~GM_UIBHM_SIDE_MASK)
64 
66 #define GMP_UIBHM_MAX_NUM_CELLS (1 << GMP_UIBHM_CELL_BITS)
67 
72 #define GMP_UIBHM_INVALID_VALUE (~0u)
73 
74 
75 // We don't want the topology structure to be able to store less cells than the mesh
76 // representation
77 static_assert(GMP_UIBHM_CELL_BITS >= GMP_GEMAMESH_CELL_ID_BITS, "Unexpected number of cell id bits");
78 
79 
83 class GMP_GEMAMESH_API_EXPORT UibhmTopologyBase
84 {
85 public:
87  virtual ~UibhmTopologyBase() {}
88 
89  virtual bool init(bool buildEdgeMap) = 0;
90  virtual bool addNewCells() = 0;
91  virtual bool cellIsIndexed(int cellId) = 0;
92 };
93 
94 
137 template <class Geometry>
138 class GMP_GEMAMESH_API_EXPORT UibhmTopology : public UibhmTopologyBase, public Geometry
139 {
140 public:
141 
143  using HalfSide = quint32;
144 
146  using HSVT = typename Geometry::template VectorType<HalfSide>;
147 
149  using IVT = typename Geometry::template VectorType<int>;
150 
155  : Geometry(mesh), _nhalf(0), _lastAddedCells(0), _hasOffset(false), _needsEH(false) {}
156 
157  virtual bool init(bool buildEdgeMap);
158  virtual bool addNewCells();
159 
161  virtual bool cellIsIndexed(int cellId) { return cellId < _lastAddedCells; }
162 
163  void printParameters(const GmLogCategory& logger, GmLogLevel level) const;
164  void print (const GmLogCategory& logger, GmLogLevel level) const;
165 
166  size_t printMemoryStatistics(const GmLogCategory& logger, GmLogLevel level) const;
167  size_t usedMemory() const;
168 
170  static HalfSide hsMake(int cellId, int side)
171  {
172  assert(cellId >= 0 && cellId < GMP_UIBHM_MAX_NUM_CELLS);
173  assert(side >= 0 && side < GMP_UIBHM_MAX_NUM_SIDES);
174  return (side << GMP_UIBHM_CELL_BITS) | cellId;
175  }
176 
178  static HalfSide hsMakeSpecial(int id, int side)
179  {
180  assert(id >= 0 && id < GMP_UIBHM_MAX_NUM_CELLS);
181  assert(side == GMP_UIBHM_BORDER_SIDE || side == GMP_UIBHM_MID_SIDE);
182  return (side << GMP_UIBHM_CELL_BITS) | id;
183  }
184 
186  static int hsCell(HalfSide hs) { return hs & GM_UIBHM_CELL_MASK; }
187 
189  static int hsSide(HalfSide hs) { return hs >> GMP_UIBHM_CELL_BITS; }
190 
192  void hsBreak(HalfSide hs, int* cellId, int* side) const
193  {
194  // TODO: Check if returning by a std:: pair is more efficient
195  *cellId = hsCell(hs);
196  *side = hsSide(hs);
197  assert(*cellId >= 0 && *cellId < this->numCells());
198  assert(*side >= 0 && *side < this->numSides(*cellId));
199  }
200 
204  static bool hsIsValid(HalfSide hs) { return hsSide(hs) < GMP_UIBHM_MAX_NUM_SIDES; }
205 
209  static bool hsIsMidElement(HalfSide hs) { return hsSide(hs) == GMP_UIBHM_MID_SIDE; }
210 
214  int linearHs(int cellId, int side) const
215  {
216  int lhs;
217  if constexpr(Geometry::IsHybrid)
218  lhs = (_hasOffset ? _Of[cellId] : this->co(cellId)) + side;
219  else
220  lhs = cellId * this->_typeTemplate->numSides() + side;
221  assert(lhs >= 0 && lhs < _nhalf);
222  return lhs;
223  }
224 
226  int linearHs(HalfSide hs) const
227  {
228  int cellId, side;
229  hsBreak(hs, &cellId, &side);
230  return linearHs(cellId, side);
231  }
232 
234  HalfSide oppositeHs(int cellId, int side) const { return _O[linearHs(cellId, side)]; }
235 
237  HalfSide oppositeHs(HalfSide hs) const { return _O[linearHs(hs)]; }
238 
240  bool isBorderHs(int cellId, int side) const { return hsSide(oppositeHs(cellId, side)) == GMP_UIBHM_BORDER_SIDE; }
241 
243  bool isBorderHs(HalfSide hs) const { assert(hsIsValid(hs)); return hsSide(oppositeHs(hs)) == GMP_UIBHM_BORDER_SIDE; }
244 
249  {
250  assert(hsIsValid(hs));
251  if(this->solid())
252  return isBorderHs(hs); // TODO: Change this?
253  else
254  {
255  HalfSide o = oppositeHs(hs);
256  return (hsSide(o) == GMP_UIBHM_BORDER_SIDE) && (o != GMP_UIBHM_INVALID_VALUE);
257  }
258  }
259 
265  {
266  assert(hsIsValid(hs) && !this->solid());
267  return oppositeHs(hs) == GMP_UIBHM_INVALID_VALUE;
268  }
269 
271  HalfSide firstHs(int cellId) const
272  {
273  assert(cellId >= 0 && cellId < this->numCells());
274  return hsMake(cellId, 0);
275  }
276 
279  {
280  int cellId, side;
281  hsBreak(hs, &cellId, &side);
282  return hsMake(cellId, (side + 1) % this->numSides(cellId));
283  }
284 
287  {
288  int cellId, side;
289  hsBreak(hs, &cellId, &side);
290  int ncs = this->numSides(cellId);
291  return hsMake(cellId, (side + ncs - 1) % ncs);
292  }
293 
298  HalfSide adjacentHf(HalfSide hf, int faceEdge) const
299  {
300  assert(this->solid());
301  int cellId, face;
302  hsBreak(hf, &cellId, &face);
303  assert(faceEdge >= 0 && faceEdge < this->tt(cellId)->numFaceVertices(face));
304  return hsMake(cellId, this->tt(cellId)->adjacentFaces(face)[faceEdge]);
305  }
306 
314  HalfSide radialHf(HalfSide hf, int faceEdge) const { return oppositeHs(adjacentHf(hf, faceEdge)); }
315 
316  protected:
317 
318  int buildOffsetTable();
319  int updateOffsetTable(int numAddedCells);
320 
321  bool buildOppositeTable();
322  bool updateOppositeTable(int numAddedCells);
323 
324  bool buildVertexHalfSideTable();
325  bool updateVertexHalfSideTable(int numAddedCells);
326 
327  bool buildEdgeHalfFaceMap();
328  bool updateEdgeHalfFaceMap(int numAddedCells);
329 
330  bool buildBordersTable();
331  bool updateBordersTable(int numAddedCells);
332 
333  template <class Key, class MakeKey> void oppositeTableTraverseCells(MakeKey makeKey, int first, int last, QMap <Key, HalfSide>& adjMap);
334 
335  void vertexHalfSideTableTraverseCells(int first, int last);
336  bool edgeHalfFaceMapTraverseCells(int first, int last);
337 
338  bool numNodesDifferentFromNumEdges() const;
339 
340  // The auxiliar map used to build the opposite table must be indexed by a key
341  // that uniquely identifies a side. Since we want to support large meshes we
342  // can NOT use a simple coding method like just doing v1*(nv^2) + v2*nv + v3
343  // for a face identified by v1, v2 & v3 (with a maximum of nv vertices), since
344  // that will result on an overflow, even if storing the result in a 64 bits
345  // integer, with around 2.6 million nodes.
346  // For surface meshes we encode the adge with a size_t as proposed by
347  // Geometry::encodeEdge, while for solid meshes we use a vector with 3 numbers
348  // filled with the smallest vertices from the face. Using only 3 vertices is possible
349  // since we do NOT support non-manifold meshes and so if two elements share a face,
350  // both faces should have the exact same vertices (although in different orders) and
351  // there can not be a "partial" intersection between faces (other than at an edge or
352  // a vertex).
353  struct V3
354  {
355  int v[3];
356  bool operator<(const struct V3& other) const
357  {
358  return (v[0] < other.v[0]) ||
359  (v[0] == other.v[0] && v[1] < other.v[1]) ||
360  (v[0] == other.v[0] && v[1] == other.v[1] && v[2] < other.v[2]);
361  }
362  bool operator==(const struct V3& other) const
363  {
364  return v[0] == other.v[0] && v[1] == other.v[1] && v[2] == other.v[2];
365  }
366  };
367 
369  static size_t makeSurfaceKey(QVarLengthArray<int, 10>& nodeList)
370  {
371  assert(nodeList.size() == 2);
372  return UibhmTopology<Geometry>::encodeEdge(nodeList[0], nodeList[1]);
373  };
374 
377  {
378  assert(nodeList.size() > 2);
379  qSort(nodeList);
380  return V3{ nodeList[0], nodeList[1], nodeList[2] };
381  };
382 
383  // Let the query classes access our internal structure
384  friend class UibhmQuery<Geometry>;
385  friend class UibhmSurfaceQuery<Geometry>;
386  friend class UibhmSolidQuery<Geometry>;
387 
388  int _nhalf;
389  bool _hasOffset;
390  bool _needsEH;
392 
403 
417 
431 
438 
446 };
447 
448 
449 #endif
HalfSide adjacentHf(HalfSide hf, int faceEdge) const
Given a half face (this method should NOT be used for surface meshes) and the local index of an edge ...
Definition: uibhmTopology.h:298
HSVT _O
The opposite table with _nhalf entries. For a half-side index 'hs', _O[linearHs(hs)] stores the half_...
Definition: uibhmTopology.h:402
static V3 makeSolidKey(QVarLengthArray< int, 10 > &nodeList)
Creates a map key from the 3 face vertices with smaller index.
Definition: uibhmTopology.h:376
HalfSide oppositeHs(HalfSide hs) const
Returns the opposite half-side to the given half-side.
Definition: uibhmTopology.h:237
#define GMP_UIBHM_CELL_BITS
The number of bits effectivelly used to encode the cell id inside a 32 bits half-side integer.
Definition: uibhmTopology.h:60
int _lastAddedCells
The number of mesh cells added to the topology when the structure was built / last updated.
Definition: uibhmTopology.h:391
int _nhalf
The number of half-sides in the mesh (either half-edges or half-faces)
Definition: uibhmTopology.h:388
IVT _Of
The side offset table. ONLY EXISTS for hybrid meshes and even though might be empty for surface meshe...
Definition: uibhmTopology.h:416
static HalfSide hsMakeSpecial(int id, int side)
Creates a half-side index to represent a border or a mid surface/volume node.
Definition: uibhmTopology.h:178
static int hsSide(HalfSide hs)
Extracts the side from the half-side index.
Definition: uibhmTopology.h:189
bool isBorderHs(HalfSide hs) const
Returns true if the given (valid) half-side is a border half-side.
Definition: uibhmTopology.h:243
static HalfSide hsMake(int cellId, int side)
Creates a half-side index from a cellId and side components.
Definition: uibhmTopology.h:170
HalfSide nextHs(HalfSide hs) const
Returns the index of the next half side in the cell associated with the given half side.
Definition: uibhmTopology.h:278
static int hsCell(HalfSide hs)
Extracts the cellId from the half-side index.
Definition: uibhmTopology.h:186
The basic class for topological queries using the UibhmTopology structure. Implements the GmCellMeshT...
Definition: uibhmQuery.h:36
virtual bool cellIsIndexed(int cellId)
Returns true if the cell already was indexed by the topological structure by the last call to init() ...
Definition: uibhmTopology.h:161
The UibhmQuery especialization for solid meshes.
Definition: uibhmQuery.h:106
virtual ~UibhmTopologyBase()
Virtual destructor.
Definition: uibhmTopology.h:87
static size_t makeSurfaceKey(QVarLengthArray< int, 10 > &nodeList)
Creates a map key from two vertices.
Definition: uibhmTopology.h:369
#define GMP_UIBHM_INVALID_VALUE
The value used to represent both the side and the cell for a border half-side when the border index i...
Definition: uibhmTopology.h:72
HalfSide firstHs(int cellId) const
Returns the index of the first half side for the given cell.
Definition: uibhmTopology.h:271
#define GMP_GEMAMESH_CELL_ID_BITS
The number of bits effectivelly used to encode the cell id inside a 32 bits integer,...
Definition: gmpGemaMeshConfig.h:46
bool isNonInterfaceBorderHs(HalfSide hs) const
Returns true if the given (valid) half-side is a border half-side that IS NOT an internal hole artifi...
Definition: uibhmTopology.h:248
#define GMP_UIBHM_MAX_NUM_SIDES
The maximum number of sides (keeping in mind the special values used for borders and mid nodes).
Definition: uibhmTopology.h:55
#define GMP_UIBHM_MAX_NUM_CELLS
The maximum number of allowed cells.
Definition: uibhmTopology.h:66
typename Geometry::template VectorType< HalfSide > HSVT
Let HSVT be the same vector type used by Geometry storing a half-side value.
Definition: uibhmTopology.h:146
quint32 HalfSide
The integer type used to represent a half-side index.
Definition: uibhmTopology.h:143
HalfSide radialHf(HalfSide hf, int faceEdge) const
Given a half face (this method should NOT be used for surface meshes) and the local index of an edge ...
Definition: uibhmTopology.h:314
#define GM_UIBHM_CELL_MASK
Mask with 1 on bits representing the cell id part (least significant bits up to the side mask).
Definition: uibhmTopology.h:63
bool isInterfaceBorderHs(HalfSide hs) const
Returns true if the given (valid) half-side is a border half-side that IS part of an internal hole ar...
Definition: uibhmTopology.h:264
#define GMP_UIBHM_MID_SIDE
The special side value used to specify that the half-side stores only a cell id (for mid nodes)
Definition: uibhmTopology.h:52
Interface for accessing the "exported" functions of a UibhmTopology class instance,...
Definition: uibhmTopology.h:83
void print(const GmMatrix &m, const GmLogCategory &logger, GmLogLevel level, int fieldWidth, char format, int precision)
static bool hsIsMidElement(HalfSide hs)
Returns true if the given half-side represents a special hs used to store the element for a quadratic...
Definition: uibhmTopology.h:209
HalfSide oppositeHs(int cellId, int side) const
Returns the opposite half-side to the given (cell, side) pair.
Definition: uibhmTopology.h:234
Definition: uibhmTopology.h:353
int linearHs(HalfSide hs) const
Returns the linear half-side index used to index the opposite table.
Definition: uibhmTopology.h:226
Declaration of usefull configuration definitions for the plugin library.
GmLogLevel
typename Geometry::template VectorType< int > IVT
Let IVT be the same vector type used by Geometry storing an integer.
Definition: uibhmTopology.h:149
HSVT _VH
The vertex half-side table with numNodes() entries. Each entry stores one half-side that contains tha...
Definition: uibhmTopology.h:430
int linearHs(int cellId, int side) const
Returns the linear half-side index used to index the opposite table for the given (cell,...
Definition: uibhmTopology.h:214
Definition: uibhmTopology.h:138
UibhmTopology(GmCellMesh *mesh)
Basic constructor. The internal structure is built by a required call to init() that returns true or ...
Definition: uibhmTopology.h:154
bool _needsEH
Did the user asked for the EH map? Needed for the special case when the mesh is initialized empty and...
Definition: uibhmTopology.h:390
bool isBorderHs(int cellId, int side) const
Returns true if the given (cell, side) pair corresponds to a border half-side.
Definition: uibhmTopology.h:240
QMap< size_t, HalfSide > _EH
The edge half-face map. Indexed by edge id, it stores one of its incident half-faces....
Definition: uibhmTopology.h:445
int size() const const
QVector< HalfSide > _B
The border table with one entry per border "curve". It stores one half-edge from this border....
Definition: uibhmTopology.h:437
bool _hasOffset
Do we have a built offset table? Equal to (!_Of.isEmpty()). Stored since linearHs() is called quite o...
Definition: uibhmTopology.h:389
void hsBreak(HalfSide hs, int *cellId, int *side) const
Breaks the half-side into its components. In debug mode, checks their validity as actual cells and si...
Definition: uibhmTopology.h:192
The UibhmQuery especialization for surface meshes.
Definition: uibhmQuery.h:74
HalfSide prevHs(HalfSide hs) const
Returns the index of the previous half side in the cell associated with the given half side.
Definition: uibhmTopology.h:286
#define GMP_UIBHM_BORDER_SIDE
The special side value used to specify that a half-side is at the border.
Definition: uibhmTopology.h:49
static bool hsIsValid(HalfSide hs)
Returns true for a standard half-side. Returns false for special half-sides used to represent borders...
Definition: uibhmTopology.h:204