better collision detection
[engrid-github.git] / src / libengrid / meshpartition.h
blob45c8ef309af821eb1f3d9c85ec0df9d8e45f68dc
1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 // + +
3 // + This file is part of enGrid. +
4 // + +
5 // + Copyright 2008-2014 enGits GmbH +
6 // + +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
11 // + +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
16 // + +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
19 // + +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 #ifndef MESHPARTITION_H
23 #define MESHPARTITION_H
25 class MeshPartition;
27 #include "egvtkobject.h"
29 class MeshPartition : public EgVtkObject
32 private: // attributes
35 vtkUnstructuredGrid* m_Grid; ///< the grid underlying this mesh partition
36 QVector<vtkIdType> m_Cells; ///< all cells of the mesh partition
37 QVector<int> m_LCells; ///< inverse indexing for the cells
38 QVector<vtkIdType> m_Nodes; ///< all nodes of the mesh partition
39 QVector<int> m_LNodes; ///< inverse indexing for the nodes
40 QVector<QVector<int> > m_N2C; ///< node to cell information
41 QVector<QVector<int> > m_N2BC; ///< node to boundary code information
42 QVector<QVector<int> > m_N2N; ///< node to node information
43 QVector<QVector<int> > m_C2C; ///< cell to cell information
45 int m_CellsStamp; ///< "time"-stamp
46 int m_LCellsStamp; ///< "time"-stamp
47 int m_NodesStamp; ///< "time"-stamp
48 int m_LNodesStamp; ///< "time"-stamp
49 int m_N2NStamp; ///< "time"-stamp
50 int m_N2CStamp; ///< "time"-stamp
51 int m_N2BCStamp; ///< "time"-stamp
52 int m_C2CStamp; ///< "time"-stamp
54 bool m_TrackGrid; ///< flag to determine if grid should be tracked (make sure that all cells are always included)
55 unsigned long int m_GridMTime; ///< VTK's modification time of the underlying grid
57 private: // methods
59 void createNodeToBC();
61 void resetTimeStamps();
62 void checkCells();
63 void checkNodes();
64 void checkLCells();
65 void checkLNodes();
66 void checkN2N();
67 void checkN2C();
68 void checkN2BC();
69 void checkC2C();
71 public: // methods
73 /// Create an empty (undefined) mesh partition
74 MeshPartition();
76 /**
77 * Create a mesh partition with the grid set. Optionally all cells can be selected.
78 * @param grid the grid to use
79 * @param use_all_cells if set to true all cells will be selected;
81 MeshPartition(vtkUnstructuredGrid *grid, bool use_all_cells = false);
83 /**
84 * Create a mesh partition from a global volume definition
85 * @param volume_name the name of the volume
87 MeshPartition(QString volume_name);
89 /**
90 * Set the grid.
91 * @param a pointer to the grid
92 * @param use_all_cells if set to true all cells will be selected;
94 void setGrid(vtkUnstructuredGrid *grid, bool use_all_cells = false);
96 /**
97 * Set the grid and make sure all cells are always included (automatic tracking).
98 * @param a pointer to the grid
100 void trackGrid(vtkUnstructuredGrid *grid);
103 * Access to the grid.
104 * @return a pointer to the grid
106 vtkUnstructuredGrid* getGrid() const { return m_Grid; }
109 * Define the mesh partition by defining its cells.
110 * @param cls the cells of the subset
112 template <class C>
113 void setCells(const C& cls);
116 * Define the mesh partition by defining its nodes.
117 * @param nds the nodes of the subset
119 template <class C>
120 void setNodes(const C& nds);
123 * Define the mesh partition by defining boundary codes.
124 * @param bcs the boundary codes of the subset
126 template <class C>
127 void setBCs(const C& bcs);
130 * Define the mesh partition by defining all its cells.
132 void setAllCells();
135 * Define the mesh partition by giving a symbolic volume name.
136 * The grid will be changed to the default (main) grid that is currently loaded into ENGRID.
137 * @param volume_name the symbolic volume name
139 void setVolume(QString volume_name);
142 * Define the mesh partition as the remainder of an existing partition.
143 * @param part the existing partition
145 void setRemainder(const MeshPartition& part);
147 const QVector<vtkIdType>& getCells() const; ///< Access to the cell indices
148 const QVector<int>& getLocalCells(); ///< Access to the local cell indices
149 const QVector<vtkIdType>& getNodes(); ///< Access to the node indices
150 const QVector<int>& getLocalNodes(); ///< Access to the local node indices
151 const QVector<QVector<int> >& getN2N(); ///< Access to the local node to node structure
152 const QVector<QVector<int> >& getN2C(); ///< Access to the local node to cell structure
153 const QVector<QVector<int> >& getC2C(); ///< Access to the local cell to cell structure
155 void setVolumeOrientation(); ///< change the face orientation to match the volume definition
156 void setOriginalOrientation(); ///< change the orientation to match the original orientation
159 * Copy the partition to a VTK grid.
160 * @param new_grid the grid to copy the partition to (will be resized accordingly).
162 void extractToVtkGrid(vtkUnstructuredGrid *new_grid);
165 * Add another partition to this one.
166 * At the moment overlapping partitions on two different grids will not be handled well.
167 * If both partitions do not have the same underlying grid the grid will be extended in order
168 * to add the other partition.
169 * @param part the partition to add
170 * @param tol the tolerance to identify duplicate nodes
171 * (negative values denote a relative tolerance -- relative to the smallest edge length)
173 void addPartition(const MeshPartition& part, double tol = -1e-3);
176 * compute the smallest edge length of the partition
177 * @return the smallest edge length
179 double getSmallestEdgeLength() const;
182 * Get the number of nodes in the partition.
183 * @return the number of nodes
185 int getNumberOfNodes();
188 * Get the number of cells in the partition.
189 * @return the number of cells
191 int getNumberOfCells();
194 * Get the average length of all surface edges connected to this node.
195 * @param id_node the node ID of the node in question
196 * @return the average length of all connected surface edges
198 double getAverageSurfaceEdgeLength(vtkIdType id_node);
201 * @brief compute the minimal and maximal edge length of a surface stencil
202 * A surface stencil consists of all surface elements which have a single node in common.
203 * @param id_node the node in common
204 * @param l_min on return this will hold the minimal edge length
205 * @param l_max on return this will hold the maximal edge length
207 void computeMinAndMaxSurfaceStencilEdgeLengths(vtkIdType id_node, double &l_min, double &l_max);
210 * @brief get the minimal edge length of a surface stencil
211 * A surface stencil consists of all surface elements which have a single node in common.
212 * @param id_node the node in common
213 * @return the minimal edge length
215 double getMinSurfaceStencilEdgeLength(vtkIdType id_node);
218 * @brief get the maximal edge length of a surface stencil
219 * A surface stencil consists of all surface elements which have a single node in common.
220 * @param id_node the node in common
221 * @return the maximal edge length
223 double getMaxSurfaceStencilEdgeLength(vtkIdType id_node);
225 vtkIdType getVolumeCell(vtkIdType id_face);
227 int localNode(vtkIdType id_node);
228 vtkIdType globalNode(int i);
229 int localCell(vtkIdType id_cell);
230 vtkIdType globalCell(int i);
233 int n2nLSize(int i_nodes);
234 int n2nLL(int i_nodes, int j);
235 vtkIdType n2nLG(int i_nodes, int j);
236 int n2nGSize(vtkIdType id_node);
237 int n2nGL(vtkIdType id_node, int j);
238 vtkIdType n2nGG(vtkIdType id_node, int j);
239 int n2cLSize(int i_nodes);
240 int n2cLL(int i_nodes, int j);
241 vtkIdType n2cLG(int i_nodes, int j);
242 int n2cGSize(vtkIdType id_node);
243 int n2cGL(vtkIdType id_node, int j);
244 vtkIdType n2cGG(vtkIdType id_node, int j);
245 int c2cLSize(int i_cells);
246 int c2cLL(int i_cells, int j);
247 vtkIdType c2cLG(int i_cells, int j);
248 int c2cGSize(vtkIdType id_cell);
249 int c2cGL(vtkIdType id_cell, int j);
250 vtkIdType c2cGG(vtkIdType id_cell, int j);
251 int n2bcLSize(int i_nodes);
252 int n2bcL(int i_nodes, int j);
253 int n2bcGSize(vtkIdType id_node);
254 int n2bcG(vtkIdType id_node, int j);
256 bool hasNeighNode(vtkIdType id_node, vtkIdType id_neigh);
257 bool hasBC(vtkIdType id_node, int bc);
260 * Compute the normal vector of a node.
261 * @param id_node the global ID of the node
262 * @return the normalised normal vector
264 vec3_t globalNormal(vtkIdType id_node);
266 template <typename C>
267 void getGlobalN2N(vtkIdType id_node, C& cont);
269 int getNumberOfFeatureNeighbours(vtkIdType id_node);
271 template <typename C>
272 void getEdgeFaces(vtkIdType id_node1, vtkIdType id_node2, C &edge_faces);
274 int getEdgeType(vtkIdType id_node1, vtkIdType id_node2);
277 * @brief compute topological distance between two nodes
278 * @param id_node1 index of the first node
279 * @param id_node2 index of the second node
280 * @param max_dist maximal search distance
281 * @param restriction_type (0: no restriction, 1: only surface nodes, 2: only edge nodes)
282 * @return the number of edges for the shortest connection between the two nodes
284 int computeTopoDistance(vtkIdType id_node1, vtkIdType id_node2, int max_dist, int restriction_type);
287 * @brief get common nodes of two cells
288 * @param id_cell1 id of the first cell
289 * @param id_cell2 id of the second cell
290 * @param common_nodes holds the common node ids on return
292 void getCommonNodes(vtkIdType id_cell1, vtkIdType id_cell2, QVector<vtkIdType> &common_nodes);
295 * @brief get common boundary codes of a set of nodes
296 * @param nodes Qt container holding the nodes to investigate
297 * @param common_bcs holds the common boundary codes on return
299 template <typename C>
300 void getCommonBcs(const C &common_nodes, QVector<int> &common_bcs);
303 * @brief check if an edge is a feature edge
304 * The check is done by trying to snap to the edge geometry of the CAD interface.
305 * Depending on the distance of the snapped locations this will a feature edge or not.
306 * @param id_node1 first node of the edge
307 * @param id_node2 second node of the edge
308 * @param feature_angle the feature angle threshold
309 * @return true if id_node1 -> id_node2 is a feature edge
311 bool isFeatureEdge(vtkIdType id_node1, vtkIdType id_node2, double feature_angle);
316 template <class C>
317 inline void MeshPartition::setCells(const C& cls)
319 m_Cells.resize(cls.size());
320 qCopy(cls.begin(), cls.end(), m_Cells.begin());
321 ++m_CellsStamp;
324 template <class C>
325 inline void MeshPartition::setNodes(const C& nds)
327 QList<vtkIdType> cls;
328 QVector<bool> node_inside(m_Grid->GetNumberOfPoints(), false);
329 foreach (vtkIdType id_node, nds) {
330 node_inside[id_node] = true;
332 for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
333 vtkIdType N_pts, *pts;
334 m_Grid->GetCellPoints(id_cell, N_pts, pts);
335 bool append_cell = true;
336 for (int i = 0; i < N_pts; ++i) {
337 if (!node_inside[pts[i]]) {
338 append_cell = false;
339 break;
342 if (append_cell) {
343 cls.append(id_cell);
346 setCells(cls);
349 template <class C>
350 inline void MeshPartition::setBCs(const C& bcs)
352 QList<vtkIdType> cls;
353 EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
354 for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
355 foreach (int bc, bcs) {
356 if (cell_code->GetValue(id_cell) == bc) {
357 cls.append(id_cell);
358 break;
362 setCells(cls);
365 inline void MeshPartition::setAllCells()
367 QVector <vtkIdType> all_cells;
368 getAllCells(all_cells, m_Grid);
369 this->setCells(all_cells);
372 inline void MeshPartition::checkCells()
374 if (m_Grid->GetMTime() > m_GridMTime) {
375 setAllCells();
376 m_GridMTime = m_Grid->GetMTime();
380 inline void MeshPartition::checkNodes()
382 if (m_TrackGrid) {
383 checkCells();
385 if (m_CellsStamp > m_NodesStamp) {
386 getNodesFromCells(m_Cells, m_Nodes, m_Grid);
387 m_NodesStamp = m_CellsStamp;
391 inline void MeshPartition::checkLCells()
393 if (m_TrackGrid) {
394 checkCells();
396 if (m_CellsStamp > m_LCellsStamp) {
397 createCellMapping(m_Cells, m_LCells, m_Grid);
398 m_LCellsStamp = m_CellsStamp;
402 inline void MeshPartition::checkLNodes()
404 checkNodes();
405 if (m_NodesStamp > m_LNodesStamp) {
406 createNodeMapping(m_Nodes, m_LNodes, m_Grid);
407 m_LNodesStamp = m_NodesStamp;
411 inline void MeshPartition::checkN2N()
413 checkLNodes();
414 if (m_LNodesStamp > m_N2NStamp) {
415 createNodeToNode(m_Cells, m_Nodes, m_LNodes, m_N2N, m_Grid);
416 m_N2NStamp = m_LNodesStamp;
420 inline void MeshPartition::checkN2C()
422 checkLNodes();
423 if (m_LNodesStamp > m_N2CStamp) {
424 createNodeToCell(m_Cells, m_Nodes, m_LNodes, m_N2C, m_Grid);
425 m_N2CStamp = m_LNodesStamp;
429 inline void MeshPartition::checkN2BC()
431 checkN2C();
432 if (m_N2CStamp > m_N2BCStamp) {
433 createNodeToBC();
434 m_N2BCStamp = m_N2CStamp;
438 inline void MeshPartition::checkC2C()
440 checkLCells();
441 if (m_CellsStamp > m_C2CStamp) {
442 createCellToCell(m_Cells, m_C2C, m_Grid);
443 m_C2CStamp = m_CellsStamp;
447 inline const QVector<vtkIdType>& MeshPartition::getCells() const
449 return m_Cells;
452 inline const QVector<int>& MeshPartition::getLocalCells()
454 checkLCells();
455 return m_LCells;
458 inline const QVector<vtkIdType>& MeshPartition::getNodes()
460 checkNodes();
461 return m_Nodes;
464 inline const QVector<int>& MeshPartition::getLocalNodes()
466 checkLNodes();
467 return m_LNodes;
470 inline const QVector<QVector<int> >& MeshPartition::getN2N()
472 checkN2N();
473 return m_N2N;
476 inline const QVector<QVector<int> >& MeshPartition::getN2C()
478 checkN2C();
479 return m_N2C;
482 inline const QVector<QVector<int> >& MeshPartition::getC2C()
484 checkC2C();
485 return m_C2C;
488 inline int MeshPartition::n2nLSize(int i_nodes)
490 checkN2N();
491 return m_N2N[i_nodes].size();
494 inline int MeshPartition::n2nLL(int i_nodes, int j)
496 checkN2N();
497 return m_N2N[i_nodes][j];
500 inline vtkIdType MeshPartition::n2nLG(int i_nodes, int j)
502 checkN2N();
503 return m_Nodes[m_N2N[i_nodes][j]];
506 inline int MeshPartition::n2nGSize(vtkIdType id_node)
508 checkN2N();
509 return m_N2N[m_LNodes[id_node]].size();
512 inline int MeshPartition::n2nGL(vtkIdType id_node, int j)
514 checkN2N();
515 return m_N2N[m_LNodes[id_node]][j];
518 inline vtkIdType MeshPartition::n2nGG(vtkIdType id_node, int j)
520 checkN2N();
521 return m_Nodes[m_N2N[m_LNodes[id_node]][j]];
524 inline int MeshPartition::n2cLSize(int i_nodes)
526 checkN2C();
527 return m_N2C[i_nodes].size();
530 inline int MeshPartition::n2cLL(int i_nodes, int j)
532 checkN2C();
533 return m_N2C[i_nodes][j];
536 inline vtkIdType MeshPartition::n2cLG(int i_nodes, int j)
538 checkN2C();
539 int i_cell = m_N2C[i_nodes][j];
540 if(i_cell<0) return(-1);
541 else return m_Cells[i_cell];
544 inline int MeshPartition::n2cGSize(vtkIdType id_node)
546 checkN2C();
547 return m_N2C[m_LNodes[id_node]].size();
550 inline int MeshPartition::n2cGL(vtkIdType id_node, int j)
552 checkN2C();
553 return m_N2C[m_LNodes[id_node]][j];
556 inline vtkIdType MeshPartition::n2cGG(vtkIdType id_node, int j)
558 checkN2C();
559 int i_cell = m_N2C[m_LNodes[id_node]][j];
560 if(i_cell<0) return(-1);
561 else return m_Cells[i_cell];
564 inline int MeshPartition::c2cLSize(int i_cells)
566 checkC2C();
567 return m_C2C[i_cells].size();
570 inline int MeshPartition::c2cLL(int i_cells, int j)
572 checkC2C();
573 return m_C2C[i_cells][j];
576 inline vtkIdType MeshPartition::c2cLG(int i_cells, int j)
578 checkC2C();
579 int i_cell = m_C2C[i_cells][j];
580 if(i_cell<0) return(-1);
581 else return m_Cells[i_cell];
584 inline int MeshPartition::c2cGSize(vtkIdType id_cell)
586 checkC2C();
587 checkLCells();
588 return m_C2C[m_LCells[id_cell]].size();
591 inline int MeshPartition::c2cGL(vtkIdType id_cell, int j)
593 checkC2C();
594 checkLCells();
595 return m_C2C[m_LCells[id_cell]][j];
598 inline vtkIdType MeshPartition::c2cGG(vtkIdType id_cell, int j)
600 checkC2C();
601 checkLCells();
602 int i_cell = m_C2C[m_LCells[id_cell]][j];
603 if(i_cell<0) return(-1);
604 else return m_Cells[i_cell];
607 inline int MeshPartition::getNumberOfCells()
609 return m_Cells.size();
612 inline int MeshPartition::getNumberOfNodes()
614 checkNodes();
615 return m_Nodes.size();
618 inline int MeshPartition::localNode(vtkIdType id_node)
620 checkLNodes();
621 return m_LNodes[id_node];
624 inline vtkIdType MeshPartition::globalNode(int i)
626 checkNodes();
627 return m_Nodes[i];
630 inline int MeshPartition::localCell(vtkIdType id_cell)
632 checkLCells();
633 return m_LCells[id_cell];
636 inline vtkIdType MeshPartition::globalCell(int i)
638 if(i<0) return(-1);
639 else return m_Cells[i];
642 inline int MeshPartition::n2bcLSize(int i_nodes)
644 checkN2BC();
645 return m_N2BC[i_nodes].size();
648 inline int MeshPartition::n2bcL(int i_nodes, int j)
650 checkN2BC();
651 return m_N2BC[i_nodes][j];
654 inline int MeshPartition::n2bcGSize(vtkIdType id_node)
656 checkN2BC();
657 return m_N2BC[m_LNodes[id_node]].size();
660 inline int MeshPartition::n2bcG(vtkIdType id_node, int j)
662 checkN2BC();
663 return m_N2BC[m_LNodes[id_node]][j];
666 template <typename C>
667 void MeshPartition::getGlobalN2N(vtkIdType id_node, C& cont)
669 cont.clear();
670 for (int i = 0; i < n2nGSize(id_node); ++i) {
671 cont << n2nGG(id_node, i);
675 template <typename C>
676 void MeshPartition::getEdgeFaces(vtkIdType id_node1, vtkIdType id_node2, C &edge_faces)
678 edge_faces.clear();
679 for (int i = 0; i < n2cGSize(id_node1); ++i) {
680 vtkIdType id_cell = n2cGG(id_node1, i);
681 if (isSurface(id_cell, m_Grid)) {
682 vtkIdType num_pts, *pts;
683 m_Grid->GetCellPoints(id_cell, num_pts, pts);
684 for (int j = 0; j < num_pts; ++j) {
685 if (pts[j] == id_node2) {
686 edge_faces << id_cell;
687 break;
694 template <typename C>
695 void MeshPartition::getCommonBcs(const C &nodes, QVector<int> &common_bcs)
697 QSet<int> bcs;
698 bool first = true;
699 foreach (vtkIdType id_node, nodes) {
700 QSet<int> node_bcs;
701 for (int i = 0; i < n2bcGSize(id_node); ++i) {
702 node_bcs.insert(n2bcG(id_node, i));
704 if (first) {
705 first = false;
706 bcs = node_bcs;
707 } else {
708 bcs.intersect(node_bcs);
711 common_bcs.resize(bcs.size());
712 qCopy(bcs.begin(), bcs.end(), common_bcs.begin());
715 #endif // MESHPARTITION_H