Salome HOME
561b10b202e264d542b5cfd2f31fd99b5b260ec1
[modules/smesh.git] / src / SMDS / SMDS_Downward.cxx
1 /*
2  * SMDS_Downward.cxx
3  *
4  *  Created on: Jun 3, 2010
5  *      Author: prascle
6  */
7
8 #include "SMDS_Downward.hxx"
9 #include "SMDS_Mesh.hxx"
10 #include "utilities.h"
11
12 #include <vtkCellType.h>
13 #include <vtkCellLinks.h>
14
15 #include <map>
16
17 using namespace std;
18
19 // ---------------------------------------------------------------------------
20
21 vector<int> SMDS_Downward::_cellDimension;
22
23 /*! get the dimension of a cell (1,2,3 for 1D, 2D 3D) given the vtk cell type
24  *
25  * @param cellType vtk cell type @see vtkCellType.h
26  * @return 1,2 or 3
27  */
28 int SMDS_Downward::getCellDimension(unsigned char cellType)
29 {
30   return _cellDimension[cellType];
31 }
32
33 // ---------------------------------------------------------------------------
34
35 /*! Generic constructor for all the downward connectivity structures (one per vtk cell type).
36  *  The static structure for cell dimension is set only once.
37  * @param grid unstructured grid associated to the mesh.
38  * @param nbDownCells number of downward entities associated to this vtk type of cell.
39  * @return
40  */
41 SMDS_Downward::SMDS_Downward(SMDS_UnstructuredGrid *grid, int nbDownCells) :
42   _grid(grid), _nbDownCells(nbDownCells)
43 {
44   this->_maxId = 0;
45   this->_cellIds.clear();
46   this->_cellTypes.clear();
47   if (_cellDimension.empty())
48     {
49       _cellDimension.resize(VTK_QUADRATIC_PYRAMID + 1, 0);
50       _cellDimension[VTK_LINE] = 1;
51       _cellDimension[VTK_QUADRATIC_EDGE] = 1;
52       _cellDimension[VTK_TRIANGLE] = 2;
53       _cellDimension[VTK_QUADRATIC_TRIANGLE] = 2;
54       _cellDimension[VTK_QUAD] = 2;
55       _cellDimension[VTK_QUADRATIC_QUAD] = 2;
56       _cellDimension[VTK_TETRA] = 3;
57       _cellDimension[VTK_QUADRATIC_TETRA] = 3;
58       _cellDimension[VTK_HEXAHEDRON] = 3;
59       _cellDimension[VTK_QUADRATIC_HEXAHEDRON] = 3;
60       _cellDimension[VTK_WEDGE] = 3;
61       _cellDimension[VTK_QUADRATIC_WEDGE] = 3;
62       _cellDimension[VTK_PYRAMID] = 3;
63       _cellDimension[VTK_QUADRATIC_PYRAMID] = 3;
64     }
65 }
66
67 SMDS_Downward::~SMDS_Downward()
68 {
69 }
70
71 /*! Give or create an entry for downward connectivity structure relative to a cell.
72  * If the entry already exists, just return its id, otherwise, create it.
73  * The internal storage memory is allocated if needed.
74  * The SMDS_UnstructuredGrid::_cellIdToDownId vector is completed for vtkUnstructuredGrid cells.
75  * @param vtkId for a vtkUnstructuredGrid cell  or -1 (default) for a created downward cell.
76  * @return the rank in downward[vtkType] structure.
77  */
78 int SMDS_Downward::addCell(int vtkId)
79 {
80   int localId = -1;
81   if (vtkId >= 0)
82     localId = _grid->CellIdToDownId(vtkId);
83   if (localId >= 0)
84     return localId;
85
86   localId = this->_maxId;
87   this->_maxId++;
88   this->allocate(_maxId);
89   if (vtkId >= 0)
90     {
91       this->_vtkCellIds[localId] = vtkId;
92       _grid->setCellIdToDownId(vtkId, localId);
93     }
94   this->initCell(localId);
95   return localId;
96 }
97
98 /*! generic method do nothing. see derived methods
99  *
100  * @param cellId
101  */
102 void SMDS_Downward::initCell(int cellId)
103 {
104 }
105
106 /*! Get the number of downward entities associated to a cell (always the same for a given vtk type of cell)
107  *
108  * @param cellId not used here.
109  * @return
110  */
111 int SMDS_Downward::getNumberOfDownCells(int cellId)
112 {
113   return _nbDownCells;
114 }
115
116 /*! get a pointer on the downward entities id's associated to a cell.
117  * @see SMDS_Downward::getNumberOfDownCells for the number of downward entities.
118  * @see SMDS_Downward::getDownTypes for the vtk cell types associated to the downward entities.
119  * @param cellId index of the cell in the downward structure relative to a given vtk cell type.
120  * @return table of downward entities id's.
121  */
122 const int* SMDS_Downward::getDownCells(int cellId)
123 {
124   //ASSERT((cellId >=0) && (cellId < _maxId));
125   return &_cellIds[_nbDownCells * cellId];
126 }
127
128 /*! get a list of vtk cell types associated to downward entities of a given cell, in the same order
129  * than the downward entities id's list (@see SMDS_Downward::getDownCells).
130  *
131  * @param cellId index of the cell in the downward structure relative to a vtk cell type.
132  * @return table of downward entities types.
133  */
134 const unsigned char* SMDS_Downward::getDownTypes(int cellId)
135 {
136   return &_cellTypes[0];
137 }
138
139 /*! add a downward entity of dimension n-1 (cell or node) to a given cell.
140  * Actual implementation is done in derived methods.
141  * @param cellId index of the parent cell (dimension n) in the downward structure relative to a vtk cell type.
142  * @param lowCellId index of the children cell to add (dimension n-1)
143  * @param aType vtk cell type of the cell to add (needed to find the SMDS_Downward structure containing the cell to add).
144  */
145 void SMDS_Downward::addDownCell(int cellId, int lowCellId, unsigned char aType)
146 {
147   ASSERT(0); // must be re-implemented in derived class
148 }
149
150 /*! add a downward entity of dimension n+1 to a given cell.
151  * Actual implementation is done in derived methods.
152  * @param cellId index of the children cell (dimension n) in the downward structure relative to a vtk cell type.
153  * @param upCellId index of the parent cell to add (dimension n+1)
154  * @param aType vtk cell type of the cell to add (needed to find the SMDS_Downward structure containing the cell to add).
155  */
156 void SMDS_Downward::addUpCell(int cellId, int upCellId, unsigned char aType)
157 {
158   ASSERT(0); // must be re-implemented in derived class
159 }
160
161 int SMDS_Downward::getNodeSet(int cellId, int* nodeSet)
162 {
163   return 0;
164 }
165
166 // ---------------------------------------------------------------------------
167
168 SMDS_Down1D::SMDS_Down1D(SMDS_UnstructuredGrid *grid, int nbDownCells) :
169   SMDS_Downward(grid, nbDownCells)
170 {
171   _upCellIdsVector.clear();
172   _upCellTypesVector.clear();
173   _upCellIds.clear();
174   _upCellTypes.clear();
175   _upCellIndex.clear();
176 }
177
178 SMDS_Down1D::~SMDS_Down1D()
179 {
180 }
181
182 /*! clear vectors used to reference 2D cells containing the edge
183  *
184  * @param cellId
185  */
186 void SMDS_Down1D::initCell(int cellId)
187 {
188   _upCellIdsVector[cellId].clear();
189   _upCellTypesVector[cellId].clear();
190 }
191
192 /*! Resize the downward connectivity storage vector if needed.
193  *
194  * @param nbElems total number of elements of the same type required
195  */
196 void SMDS_Down1D::allocate(int nbElems)
197 {
198   if (nbElems >= _vtkCellIds.size())
199     {
200       _vtkCellIds.resize(nbElems + SMDS_Mesh::chunkSize, -1);
201       _cellIds.resize(_nbDownCells * (nbElems + SMDS_Mesh::chunkSize), -1);
202       _upCellIdsVector.resize(nbElems + SMDS_Mesh::chunkSize);
203       _upCellTypesVector.resize(nbElems + SMDS_Mesh::chunkSize);
204     }
205 }
206
207 void SMDS_Down1D::compactStorage()
208 {
209   _cellIds.resize(_nbDownCells * _maxId);
210   _vtkCellIds.resize(_maxId);
211
212   int sizeUpCells = 0;
213   for (int i = 0; i < _maxId; i++)
214     sizeUpCells += _upCellIdsVector[i].size();
215   _upCellIds.resize(sizeUpCells, -1);
216   _upCellTypes.resize(sizeUpCells);
217   _upCellIndex.resize(_maxId + 1, -1); // id and types of rank i correspond to [ _upCellIndex[i], _upCellIndex[i+1] [
218   int current = 0;
219   for (int i = 0; i < _maxId; i++)
220     {
221       _upCellIndex[i] = current;
222       for (int j = 0; j < _upCellIdsVector[i].size(); j++)
223         {
224           _upCellIds[current] = _upCellIdsVector[i][j];
225           _upCellTypes[current] = _upCellTypesVector[i][j];
226           current++;
227         }
228     }
229   _upCellIndex[_maxId] = current;
230
231   _upCellIdsVector.clear();
232   _upCellTypesVector.clear();
233 }
234
235 void SMDS_Down1D::addUpCell(int cellId, int upCellId, unsigned char aType)
236 {
237   //ASSERT((cellId >=0) && (cellId < _maxId));
238   int nbFaces = _upCellIdsVector[cellId].size();
239   for (int i = 0; i < nbFaces; i++)
240     {
241       if ((_upCellIdsVector[cellId][i] == upCellId) && (_upCellTypesVector[cellId][i] == aType))
242         {
243           return; // already done
244         }
245     }
246   _upCellIdsVector[cellId].push_back(upCellId);
247   _upCellTypesVector[cellId].push_back(aType);
248 }
249
250 int SMDS_Down1D::getNumberOfUpCells(int cellId)
251 {
252   //ASSERT((cellId >=0) && (cellId < _maxId));
253   return _upCellIndex[cellId + 1] - _upCellIndex[cellId];
254 }
255
256 const int* SMDS_Down1D::getUpCells(int cellId)
257 {
258   //ASSERT((cellId >=0) && (cellId < _maxId));
259   return &_upCellIds[_upCellIndex[cellId]];
260 }
261
262 const unsigned char* SMDS_Down1D::getUpTypes(int cellId)
263 {
264   //ASSERT((cellId >=0) && (cellId < _maxId));
265   return &_upCellTypes[_upCellIndex[cellId]];
266 }
267
268 int SMDS_Down1D::getNodeSet(int cellId, int* nodeSet)
269 {
270   for (int i = 0; i < _nbDownCells; i++)
271     nodeSet[i] = _cellIds[_nbDownCells * cellId + i];
272   return _nbDownCells;
273 }
274
275 void SMDS_Down1D::setNodes(int cellId, int vtkId)
276 {
277   vtkIdType npts = 0;
278   vtkIdType *pts; // will refer to the point id's of the face
279   _grid->GetCellPoints(vtkId, npts, pts);
280   // MESSAGE(vtkId << " " << npts << "  " << _nbDownCells);
281   //ASSERT(npts == _nbDownCells);
282   for (int i = 0; i < npts; i++)
283     {
284       _cellIds[_nbDownCells * cellId + i] = pts[i];
285     }
286 }
287
288 void SMDS_Down1D::setNodes(int cellId, const int* nodeIds)
289 {
290   //ASSERT(nodeIds.size() == _nbDownCells);
291   for (int i = 0; i < _nbDownCells; i++)
292     {
293       _cellIds[_nbDownCells * cellId + i] = nodeIds[i];
294     }
295 }
296
297 /*! Build the list of vtkUnstructuredGrid cells containing the edge.
298  * We keep in the list the cells that contains all the nodes, we keep only volumes and faces.
299  * @param cellId id of the edge in the downward structure
300  * @param vtkIds vector of vtk id's
301  * @return number of vtk cells (size of vector)
302  */
303 int SMDS_Down1D::computeVtkCells(int cellId, std::vector<int>& vtkIds)
304 {
305   vtkIds.clear();
306
307   // --- find all the cells the points belong to, and how many of the points belong to a given cell
308
309   int *pts = &_cellIds[_nbDownCells * cellId];
310   int ncells = this->computeVtkCells(pts, vtkIds);
311   return ncells;
312 }
313
314 /*! Build the list of vtkUnstructuredGrid cells containing the edge.
315  *
316  * @param pts list of points id's defining an edge
317  * @param vtkIds vector of vtk id's
318  * @return number of vtk cells (size of vector)
319  */
320 int SMDS_Down1D::computeVtkCells(int *pts, std::vector<int>& vtkIds)
321 {
322
323   // --- find all the cells the points belong to, and how many of the points belong to a given cell
324
325   int cellIds[100];
326   int cellCnt[100];
327   int cnt = 0;
328   for (int i = 0; i < _nbDownCells; i++)
329     {
330       vtkIdType point = pts[i];
331       int numCells = _grid->GetLinks()->GetNcells(point);
332       vtkIdType *cells = _grid->GetLinks()->GetCells(point);
333       for (int j = 0; j < numCells; j++)
334         {
335           int vtkCellId = cells[j];
336           bool found = false;
337           for (int k = 0; k < cnt; k++)
338             {
339               if (cellIds[k] == vtkCellId)
340                 {
341                   cellCnt[k] += 1;
342                   found = true;
343                   break;
344                 }
345             }
346           if (!found)
347             {
348               cellIds[cnt] = vtkCellId;
349               cellCnt[cnt] = 1;
350               // TODO ASSERT(cnt<100);
351               cnt++;
352             }
353         }
354     }
355
356   // --- find the face and volume cells: they contains all the points and are of type volume or face
357
358   int ncells = 0;
359   for (int i = 0; i < cnt; i++)
360     {
361       if (cellCnt[i] == _nbDownCells)
362         {
363           int vtkElemId = cellIds[i];
364           int vtkType = _grid->GetCellType(vtkElemId);
365           if (SMDS_Downward::getCellDimension(vtkType) > 1)
366             {
367               vtkIds.push_back(vtkElemId);
368               ncells++;
369             }
370         }
371     }
372
373   return ncells;
374 }
375
376 /*! Build the list of downward faces from a list of vtk cells.
377  *
378  * @param cellId id of the edge in the downward structure
379  * @param vtkIds vector of vtk id's
380  * @param downFaces vector of face id's in downward structures
381  * @param downTypes vector of face types
382  * @return number of downward faces
383  */
384 int SMDS_Down1D::computeFaces(int cellId, int* vtkIds, int nbcells, int* downFaces, unsigned char* downTypes)
385 {
386   int *pts = &_cellIds[_nbDownCells * cellId];
387   int nbFaces = this->computeFaces(pts, vtkIds, nbcells, downFaces, downTypes);
388   return nbFaces;
389 }
390
391 /*! Build the list of downward faces from a list of vtk cells.
392  *
393  * @param pts list of points id's defining an edge
394  * @param vtkIds vector of vtk id's
395  * @param downFaces vector of face id's in downward structures
396  * @param downTypes vector of face types
397  * @return number of downward faces
398  */
399 int SMDS_Down1D::computeFaces(int* pts, int* vtkIds, int nbcells, int* downFaces, unsigned char* downTypes)
400 {
401   int cnt = 0;
402   for (int i = 0; i < nbcells; i++)
403     {
404       int vtkId = vtkIds[i];
405       int vtkType = _grid->GetCellType(vtkId);
406       if (SMDS_Downward::getCellDimension(vtkType) == 2)
407         {
408           int faceId = _grid->CellIdToDownId(vtkId);
409           downFaces[cnt] = faceId;
410           downTypes[cnt] = vtkType;
411           cnt++;
412         }
413       else
414         {
415           int volId = _grid->CellIdToDownId(vtkId);
416           SMDS_Downward * downvol = _grid->getDownArray(vtkType);
417           const int *downIds = downvol->getDownCells(volId);
418           const unsigned char* downTypesVol = downvol->getDownTypes(volId);
419           int nbFaces = downvol->getNumberOfDownCells(volId);
420           const int* faceIds = downvol->getDownCells(volId);
421           for (int n = 0; n < nbFaces; n++)
422             {
423               SMDS_Down2D *downFace = static_cast<SMDS_Down2D*> (_grid->getDownArray(downTypesVol[n]));
424               bool isInFace = downFace->isInFace(faceIds[n], pts, _nbDownCells);
425               if (isInFace)
426                 {
427                   bool alreadySet = false;
428                   for (int k = 0; k < cnt; k++)
429                     if (faceIds[n] == downFaces[k])
430                       {
431                         alreadySet = true;
432                         break;
433                       }
434                   if (!alreadySet)
435                     {
436                       downFaces[cnt] = faceIds[n];
437                       downTypes[cnt] = downTypesVol[n];
438                       cnt++;
439                     }
440                 }
441             }
442         }
443     }
444   return cnt;
445 }
446
447 // ---------------------------------------------------------------------------
448
449 SMDS_Down2D::SMDS_Down2D(SMDS_UnstructuredGrid *grid, int nbDownCells) :
450   SMDS_Downward(grid, nbDownCells)
451 {
452   _upCellIds.clear();
453   _upCellTypes.clear();
454   _tempNodes.clear();
455   _nbNodes = 0;
456 }
457
458 SMDS_Down2D::~SMDS_Down2D()
459 {
460 }
461
462 int SMDS_Down2D::getNumberOfUpCells(int cellId)
463 {
464   int nbup = 0;
465   if (_upCellIds[2 * cellId] >= 0)
466     nbup++;
467   if (_upCellIds[2 * cellId + 1] >= 0)
468     nbup++;
469   return nbup;
470 }
471
472 const int* SMDS_Down2D::getUpCells(int cellId)
473 {
474   //ASSERT((cellId >=0) && (cellId < _maxId));
475   return &_upCellIds[2 * cellId];
476 }
477
478 const unsigned char* SMDS_Down2D::getUpTypes(int cellId)
479 {
480   //ASSERT((cellId >=0) && (cellId < _maxId));
481   return &_upCellTypes[2 * cellId];
482 }
483
484 /*! Find in vtkUnstructuredGrid the volumes containing a face already stored in vtkUnstructuredGrid.
485  * Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
486  * with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
487  * A face belongs to 0, 1 or 2 volumes, identified by their id in vtkUnstructuredGrid.
488  * @param cellId the face cell id in vkUnstructuredGrid
489  * @param ids a couple of vtkId, initialized at -1 (no parent volume)
490  * @return number of volumes (0, 1 or 2)
491  */
492 int SMDS_Down2D::computeVolumeIds(int cellId, int* ids)
493 {
494   // --- find point id's of the face
495
496   vtkIdType npts = 0;
497   vtkIdType *pts; // will refer to the point id's of the face
498   _grid->GetCellPoints(cellId, npts, pts);
499   vector<int> nodes;
500   for (int i = 0; i < npts; i++)
501     nodes.push_back(pts[i]);
502   int nvol = this->computeVolumeIdsFromNodesFace(&nodes[0], npts, ids);
503   return nvol;
504 }
505
506 /*! Find in vtkUnstructuredGrid the volumes containing a face described by it's nodes
507  * Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
508  * with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
509  * A face belongs to 0, 1 or 2 volumes, identified by their id in vtkUnstructuredGrid.
510  * @param faceByNodes
511  * @param ids a couple of vtkId, initialized at -1 (no parent volume)
512  * @return number of volumes (0, 1 or 2)
513  */
514 int SMDS_Down2D::computeVolumeIds(ElemByNodesType& faceByNodes, int* ids)
515 {
516   int nvol = this->computeVolumeIdsFromNodesFace(&faceByNodes.nodeIds[0], faceByNodes.nbNodes, ids);
517   return nvol;
518 }
519
520 /*! Find in vtkUnstructuredGrid the volumes containing a face described by it's nodes
521  * Search the volumes containing a face, to store the info in SMDS_Down2D for later uses
522  * with SMDS_Down2D::getUpCells and SMDS_Down2D::getUpTypes.
523  * A face belongs to 0, 1 or 2 volumes, identified by their id in vtkUnstructuredGrid.
524  * @param pts array of vtk node id's
525  * @param npts number of nodes
526  * @param ids
527  * @return number of volumes (0, 1 or 2)
528  */
529 int SMDS_Down2D::computeVolumeIdsFromNodesFace(int* pts, int npts, int* ids)
530 {
531
532   // --- find all the cells the points belong to, and how many of the points belong to a given cell
533
534   int cellIds[100];
535   int cellCnt[100];
536   int cnt = 0;
537   for (int i = 0; i < npts; i++)
538     {
539       vtkIdType point = pts[i];
540       int numCells = _grid->GetLinks()->GetNcells(point);
541       //MESSAGE("cells pour " << i << " " << numCells);
542       vtkIdType *cells = _grid->GetLinks()->GetCells(point);
543       for (int j = 0; j < numCells; j++)
544         {
545           int vtkCellId = cells[j];
546           bool found = false;
547           for (int k = 0; k < cnt; k++)
548             {
549               if (cellIds[k] == vtkCellId)
550                 {
551                   cellCnt[k] += 1;
552                   found = true;
553                   break;
554                 }
555             }
556           if (!found)
557             {
558               cellIds[cnt] = vtkCellId;
559               cellCnt[cnt] = 1;
560               // TODO ASSERT(cnt<100);
561               cnt++;
562             }
563         }
564     }
565
566   // --- find the volume cells: they contains all the points and are of type volume
567
568   int nvol = 0;
569   for (int i = 0; i < cnt; i++)
570     {
571       //MESSAGE("cell " << cellIds[i] << " points " << cellCnt[i]);
572       if (cellCnt[i] == npts)
573         {
574           int vtkElemId = cellIds[i];
575           int vtkType = _grid->GetCellType(vtkElemId);
576           if (SMDS_Downward::getCellDimension(vtkType) == 3)
577             {
578               ids[nvol] = vtkElemId; // store the volume id in given vector
579               nvol++;
580             }
581         }
582       if (nvol == 2)
583         break;
584     }
585
586   return nvol;
587 }
588
589 void SMDS_Down2D::setTempNodes(int cellId, int vtkId)
590 {
591   vtkIdType npts = 0;
592   vtkIdType *pts; // will refer to the point id's of the face
593   _grid->GetCellPoints(vtkId, npts, pts);
594   // MESSAGE(vtkId << " " << npts << "  " << _nbNodes);
595   //ASSERT(npts == _nbNodes);
596   for (int i = 0; i < npts; i++)
597     {
598       _tempNodes[_nbNodes * cellId + i] = pts[i];
599     }
600 }
601
602 void SMDS_Down2D::setTempNodes(int cellId, ElemByNodesType& faceByNodes)
603 {
604   for (int i = 0; i < faceByNodes.nbNodes; i++)
605     _tempNodes[_nbNodes * cellId + i] = faceByNodes.nodeIds[i];
606 }
607
608 /*! Find if all the nodes belongs to the face.
609  *
610  * @param cellId the face cell Id
611  * @param nodeSet set of node id's to be found in the face list of nodes
612  * @return
613  */
614 bool SMDS_Down2D::isInFace(int cellId, int *pts, int npts)
615 {
616   int nbFound = 0;
617   int *nodes = &_tempNodes[_nbNodes * cellId];
618   for (int j = 0; j < npts; j++)
619     {
620       int point = pts[j];
621       for (int i = 0; i < _nbNodes; i++)
622         {
623           if (nodes[i] == point)
624             {
625               nbFound++;
626               break;
627             }
628         }
629     }
630   return (nbFound == npts);
631 }
632
633 /*! Resize the downward connectivity storage vector if needed.
634  *
635  * @param nbElems total number of elements of the same type required
636  */
637 void SMDS_Down2D::allocate(int nbElems)
638 {
639   if (nbElems >= _vtkCellIds.size())
640     {
641       _cellIds.resize(_nbDownCells * (nbElems + SMDS_Mesh::chunkSize), -1);
642       _vtkCellIds.resize(nbElems + SMDS_Mesh::chunkSize, -1);
643       _upCellIds.resize(2 * (nbElems + SMDS_Mesh::chunkSize), -1);
644       _upCellTypes.resize(2 * (nbElems + SMDS_Mesh::chunkSize), -1);
645       _tempNodes.resize(_nbNodes * (nbElems + SMDS_Mesh::chunkSize), -1);
646     }
647 }
648
649 void SMDS_Down2D::compactStorage()
650 {
651   _cellIds.resize(_nbDownCells * _maxId);
652   _upCellIds.resize(2 * _maxId);
653   _upCellTypes.resize(2 * _maxId);
654   _vtkCellIds.resize(_maxId);
655   _tempNodes.clear();
656 }
657
658 void SMDS_Down2D::addUpCell(int cellId, int upCellId, unsigned char aType)
659 {
660   //ASSERT((cellId >=0)&& (cellId < _maxId));
661   int *vols = &_upCellIds[2 * cellId];
662   unsigned char *types = &_upCellTypes[2 * cellId];
663   for (int i = 0; i < 2; i++)
664     {
665       if (vols[i] < 0)
666         {
667           vols[i] = upCellId; // use non affected volume
668           types[i] = aType;
669           return;
670         }
671       if ((vols[i] == upCellId) && (types[i] == aType)) // already done
672         return;
673     }
674   ASSERT(0);
675 }
676
677 int SMDS_Down2D::getNodeSet(int cellId, int* nodeSet)
678 {
679   for (int i = 0; i < _nbNodes; i++)
680     nodeSet[i] = _tempNodes[_nbNodes * cellId + i];
681   return _nbNodes;
682 }
683
684 int SMDS_Down2D::FindEdgeByNodes(int cellId, ElemByNodesType& edgeByNodes)
685 {
686   int *edges = &_cellIds[_nbDownCells * cellId];
687   for (int i = 0; i < _nbDownCells; i++)
688     {
689       if ((edges[i] >= 0) && (edgeByNodes.vtkType == _cellTypes[i]))
690         {
691           int nodeSet[3];
692           int npts = this->_grid->getDownArray(edgeByNodes.vtkType)->getNodeSet(edges[i], nodeSet);
693           bool found = false;
694           for (int j = 0; j < npts; j++)
695             {
696               int point = edgeByNodes.nodeIds[j];
697               found = false;
698               for (int k = 0; k < npts; k++)
699                 {
700                   if (nodeSet[k] == point)
701                     {
702                       found = true;
703                       break;
704                     }
705                 }
706               if (!found)
707                 break;
708             }
709           if (found)
710             return edges[i];
711         }
712     }
713   return -1;
714 }
715
716 // ---------------------------------------------------------------------------
717
718 SMDS_Down3D::SMDS_Down3D(SMDS_UnstructuredGrid *grid, int nbDownCells) :
719   SMDS_Downward(grid, nbDownCells)
720 {
721 }
722
723 SMDS_Down3D::~SMDS_Down3D()
724 {
725 }
726
727 void SMDS_Down3D::allocate(int nbElems)
728 {
729   if (nbElems >= _vtkCellIds.size())
730     {
731       _cellIds.resize(_nbDownCells * (nbElems + SMDS_Mesh::chunkSize), -1);
732       _vtkCellIds.resize(nbElems + SMDS_Mesh::chunkSize, -1);
733     }
734 }
735
736 void SMDS_Down3D::compactStorage()
737 {
738   // nothing to do, size was known before
739 }
740
741 int SMDS_Down3D::getNumberOfUpCells(int cellId)
742 {
743   return 0;
744 }
745
746 const int* SMDS_Down3D::getUpCells(int cellId)
747 {
748   return 0;
749 }
750
751 const unsigned char* SMDS_Down3D::getUpTypes(int cellId)
752 {
753   return 0;
754 }
755
756 int SMDS_Down3D::FindFaceByNodes(int cellId, ElemByNodesType& faceByNodes)
757 {
758   int *faces = &_cellIds[_nbDownCells * cellId];
759   int faceNodeSet[10];
760   int npoints = 0;
761
762   for (int i = 0; i < _nbDownCells; i++)
763     {
764       if ((faces[i] >= 0) && (faceByNodes.vtkType == _cellTypes[i]))
765         {
766           if (npoints == 0)
767             {
768               for (int j = 0; j < faceByNodes.nbNodes; j++)
769                 faceNodeSet[j] = faceByNodes.nodeIds[j];
770               npoints = faceByNodes.nbNodes;
771             }
772
773           int nodeSet[10];
774           int npts = this->_grid->getDownArray(faceByNodes.vtkType)->getNodeSet(faces[i], nodeSet);
775           if (npts != npoints)
776             continue; // skip this face
777           bool found = false;
778           for (int j = 0; j < npts; j++)
779             {
780               int point = faceByNodes.nodeIds[j];
781               found = false;
782               for (int k = 0; k < npts; k++)
783                 {
784                   if (nodeSet[k] == point)
785                     {
786                       found = true;
787                       break; // point j is in the 2 faces, skip remaining k values
788                     }
789                 }
790               if (!found)
791                 break; // point j is not in the 2 faces, skip the remaining tests
792             }
793           if (found)
794             return faces[i];
795         }
796     }
797   return -1;
798 }
799
800 // ---------------------------------------------------------------------------
801
802 SMDS_DownEdge::SMDS_DownEdge(SMDS_UnstructuredGrid *grid) :
803   SMDS_Down1D(grid, 2)
804 {
805   _cellTypes.push_back(VTK_VERTEX);
806   _cellTypes.push_back(VTK_VERTEX);
807 }
808
809 SMDS_DownEdge::~SMDS_DownEdge()
810 {
811 }
812
813 // ---------------------------------------------------------------------------
814
815 SMDS_DownQuadEdge::SMDS_DownQuadEdge(SMDS_UnstructuredGrid *grid) :
816   SMDS_Down1D(grid, 3)
817 {
818   _cellTypes.push_back(VTK_VERTEX);
819   _cellTypes.push_back(VTK_VERTEX);
820   _cellTypes.push_back(VTK_VERTEX);
821 }
822
823 SMDS_DownQuadEdge::~SMDS_DownQuadEdge()
824 {
825 }
826
827 // ---------------------------------------------------------------------------
828
829 SMDS_DownTriangle::SMDS_DownTriangle(SMDS_UnstructuredGrid *grid) :
830   SMDS_Down2D(grid, 3)
831 {
832   _cellTypes.push_back(VTK_LINE);
833   _cellTypes.push_back(VTK_LINE);
834   _cellTypes.push_back(VTK_LINE);
835   _nbNodes = 3;
836 }
837
838 SMDS_DownTriangle::~SMDS_DownTriangle()
839 {
840 }
841
842 void SMDS_DownTriangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
843 {
844   int *nodes = &_tempNodes[_nbNodes * cellId];
845   edgesWithNodes.nbElems = 3;
846
847   edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
848   edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
849   edgesWithNodes.elems[0].nbNodes = 2;
850   edgesWithNodes.elems[0].vtkType = VTK_LINE;
851
852   edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
853   edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
854   edgesWithNodes.elems[1].nbNodes = 2;
855   edgesWithNodes.elems[1].vtkType = VTK_LINE;
856
857   edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
858   edgesWithNodes.elems[2].nodeIds[1] = nodes[0];
859   edgesWithNodes.elems[2].nbNodes = 2;
860   edgesWithNodes.elems[2].vtkType = VTK_LINE;
861 }
862
863 void SMDS_DownTriangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
864 {
865   //ASSERT((cellId >=0)&& (cellId < _maxId));
866   //ASSERT(aType == VTK_LINE);
867   int *faces = &_cellIds[_nbDownCells * cellId];
868   for (int i = 0; i < _nbDownCells; i++)
869     {
870       if (faces[i] < 0)
871         {
872           faces[i] = lowCellId;
873           return;
874         }
875       if (faces[i] == lowCellId)
876         return;
877     }
878   ASSERT(0);
879 }
880
881 // ---------------------------------------------------------------------------
882
883 SMDS_DownQuadTriangle::SMDS_DownQuadTriangle(SMDS_UnstructuredGrid *grid) :
884   SMDS_Down2D(grid, 3)
885 {
886   _cellTypes.push_back(VTK_QUADRATIC_EDGE);
887   _cellTypes.push_back(VTK_QUADRATIC_EDGE);
888   _cellTypes.push_back(VTK_QUADRATIC_EDGE);
889   _nbNodes = 6;
890 }
891
892 SMDS_DownQuadTriangle::~SMDS_DownQuadTriangle()
893 {
894 }
895
896 void SMDS_DownQuadTriangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
897 {
898   int *nodes = &_tempNodes[_nbNodes * cellId];
899   edgesWithNodes.nbElems = 3;
900
901   edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
902   edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
903   edgesWithNodes.elems[0].nodeIds[2] = nodes[3];
904   edgesWithNodes.elems[0].nbNodes = 3;
905   edgesWithNodes.elems[0].vtkType = VTK_QUADRATIC_EDGE;
906
907   edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
908   edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
909   edgesWithNodes.elems[1].nodeIds[2] = nodes[4];
910   edgesWithNodes.elems[1].nbNodes = 3;
911   edgesWithNodes.elems[1].vtkType = VTK_QUADRATIC_EDGE;
912
913   edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
914   edgesWithNodes.elems[2].nodeIds[1] = nodes[0];
915   edgesWithNodes.elems[2].nodeIds[2] = nodes[5];
916   edgesWithNodes.elems[2].nbNodes = 3;
917   edgesWithNodes.elems[2].vtkType = VTK_QUADRATIC_EDGE;
918 }
919
920 void SMDS_DownQuadTriangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
921 {
922   //ASSERT((cellId >=0)&& (cellId < _maxId));
923   //ASSERT(aType == VTK_QUADRATIC_EDGE);
924   int *faces = &_cellIds[_nbDownCells * cellId];
925   for (int i = 0; i < _nbDownCells; i++)
926     {
927       if (faces[i] < 0)
928         {
929           faces[i] = lowCellId;
930           return;
931         }
932       if (faces[i] == lowCellId)
933         return;
934     }
935   ASSERT(0);
936 }
937
938 // ---------------------------------------------------------------------------
939
940 SMDS_DownQuadrangle::SMDS_DownQuadrangle(SMDS_UnstructuredGrid *grid) :
941   SMDS_Down2D(grid, 4)
942 {
943   _cellTypes.push_back(VTK_LINE);
944   _cellTypes.push_back(VTK_LINE);
945   _cellTypes.push_back(VTK_LINE);
946   _cellTypes.push_back(VTK_LINE);
947   _nbNodes = 4;
948 }
949
950 SMDS_DownQuadrangle::~SMDS_DownQuadrangle()
951 {
952 }
953
954 void SMDS_DownQuadrangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
955 {
956   int *nodes = &_tempNodes[_nbNodes * cellId];
957   edgesWithNodes.nbElems = 4;
958
959   edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
960   edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
961   edgesWithNodes.elems[0].nbNodes = 2;
962   edgesWithNodes.elems[0].vtkType = VTK_LINE;
963
964   edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
965   edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
966   edgesWithNodes.elems[1].nbNodes = 2;
967   edgesWithNodes.elems[1].vtkType = VTK_LINE;
968
969   edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
970   edgesWithNodes.elems[2].nodeIds[1] = nodes[3];
971   edgesWithNodes.elems[2].nbNodes = 2;
972   edgesWithNodes.elems[2].vtkType = VTK_LINE;
973
974   edgesWithNodes.elems[3].nodeIds[0] = nodes[3];
975   edgesWithNodes.elems[3].nodeIds[1] = nodes[0];
976   edgesWithNodes.elems[3].nbNodes = 2;
977   edgesWithNodes.elems[3].vtkType = VTK_LINE;
978 }
979
980 void SMDS_DownQuadrangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
981 {
982   //ASSERT((cellId >=0)&& (cellId < _maxId));
983   //ASSERT(aType == VTK_LINE);
984   int *faces = &_cellIds[_nbDownCells * cellId];
985   for (int i = 0; i < _nbDownCells; i++)
986     {
987       if (faces[i] < 0)
988         {
989           faces[i] = lowCellId;
990           return;
991         }
992       if (faces[i] == lowCellId)
993         return;
994     }
995   ASSERT(0);
996 }
997
998 // ---------------------------------------------------------------------------
999
1000 SMDS_DownQuadQuadrangle::SMDS_DownQuadQuadrangle(SMDS_UnstructuredGrid *grid) :
1001   SMDS_Down2D(grid, 4)
1002 {
1003   _cellTypes.push_back(VTK_QUADRATIC_EDGE);
1004   _cellTypes.push_back(VTK_QUADRATIC_EDGE);
1005   _cellTypes.push_back(VTK_QUADRATIC_EDGE);
1006   _cellTypes.push_back(VTK_QUADRATIC_EDGE);
1007   _nbNodes = 8;
1008 }
1009
1010 SMDS_DownQuadQuadrangle::~SMDS_DownQuadQuadrangle()
1011 {
1012 }
1013
1014 void SMDS_DownQuadQuadrangle::computeEdgesWithNodes(int cellId, ListElemByNodesType& edgesWithNodes)
1015 {
1016   int *nodes = &_tempNodes[_nbNodes * cellId];
1017   edgesWithNodes.nbElems = 4;
1018
1019   edgesWithNodes.elems[0].nodeIds[0] = nodes[0];
1020   edgesWithNodes.elems[0].nodeIds[1] = nodes[1];
1021   edgesWithNodes.elems[0].nodeIds[2] = nodes[4];
1022   edgesWithNodes.elems[0].nbNodes = 3;
1023   edgesWithNodes.elems[0].vtkType = VTK_QUADRATIC_EDGE;
1024
1025   edgesWithNodes.elems[1].nodeIds[0] = nodes[1];
1026   edgesWithNodes.elems[1].nodeIds[1] = nodes[2];
1027   edgesWithNodes.elems[1].nodeIds[2] = nodes[5];
1028   edgesWithNodes.elems[1].nbNodes = 3;
1029   edgesWithNodes.elems[1].vtkType = VTK_QUADRATIC_EDGE;
1030
1031   edgesWithNodes.elems[2].nodeIds[0] = nodes[2];
1032   edgesWithNodes.elems[2].nodeIds[1] = nodes[3];
1033   edgesWithNodes.elems[2].nodeIds[2] = nodes[6];
1034   edgesWithNodes.elems[2].nbNodes = 3;
1035   edgesWithNodes.elems[2].vtkType = VTK_QUADRATIC_EDGE;
1036
1037   edgesWithNodes.elems[3].nodeIds[0] = nodes[3];
1038   edgesWithNodes.elems[3].nodeIds[1] = nodes[0];
1039   edgesWithNodes.elems[3].nodeIds[2] = nodes[7];
1040   edgesWithNodes.elems[3].nbNodes = 3;
1041   edgesWithNodes.elems[3].vtkType = VTK_QUADRATIC_EDGE;
1042 }
1043
1044 void SMDS_DownQuadQuadrangle::addDownCell(int cellId, int lowCellId, unsigned char aType)
1045 {
1046   //ASSERT((cellId >=0)&& (cellId < _maxId));
1047   //ASSERT(aType == VTK_QUADRATIC_EDGE);
1048   int *faces = &_cellIds[_nbDownCells * cellId];
1049   for (int i = 0; i < _nbDownCells; i++)
1050     {
1051       if (faces[i] < 0)
1052         {
1053           faces[i] = lowCellId;
1054           return;
1055         }
1056       if (faces[i] == lowCellId)
1057         return;
1058     }
1059   ASSERT(0);
1060 }
1061
1062 // ---------------------------------------------------------------------------
1063
1064 SMDS_DownTetra::SMDS_DownTetra(SMDS_UnstructuredGrid *grid) :
1065   SMDS_Down3D(grid, 4)
1066 {
1067   _cellTypes.push_back(VTK_TRIANGLE);
1068   _cellTypes.push_back(VTK_TRIANGLE);
1069   _cellTypes.push_back(VTK_TRIANGLE);
1070   _cellTypes.push_back(VTK_TRIANGLE);
1071 }
1072
1073 SMDS_DownTetra::~SMDS_DownTetra()
1074 {
1075 }
1076
1077 void SMDS_DownTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
1078 {
1079   //ASSERT((cellId >=0)&& (cellId < _maxId));
1080   //ASSERT(aType == VTK_TRIANGLE);
1081   int *faces = &_cellIds[_nbDownCells * cellId];
1082   for (int i = 0; i < _nbDownCells; i++)
1083     {
1084       if (faces[i] < 0)
1085         {
1086           faces[i] = lowCellId;
1087           return;
1088         }
1089       if (faces[i] == lowCellId)
1090         return;
1091     }
1092   ASSERT(0);
1093 }
1094
1095 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
1096  * The linear tetrahedron is defined by four points.
1097  * @see vtkTetra.h in Filtering.
1098  * @param cellId volumeId in vtkUnstructuredGrid
1099  * @param facesWithNodes vector of face descriptors to be filled
1100  */
1101 void SMDS_DownTetra::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1102 {
1103   // --- find point id's of the volume
1104
1105   vtkIdType npts = 0;
1106   vtkIdType *nodes; // will refer to the point id's of the volume
1107   _grid->GetCellPoints(cellId, npts, nodes);
1108
1109   // --- create all the ordered list of node id's for each face
1110
1111   facesWithNodes.nbElems = 4;
1112
1113   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1114   facesWithNodes.elems[0].nodeIds[1] = nodes[1];
1115   facesWithNodes.elems[0].nodeIds[2] = nodes[2];
1116   facesWithNodes.elems[0].nbNodes = 3;
1117   facesWithNodes.elems[0].vtkType = VTK_TRIANGLE;
1118
1119   facesWithNodes.elems[1].nodeIds[0] = nodes[0];
1120   facesWithNodes.elems[1].nodeIds[1] = nodes[1];
1121   facesWithNodes.elems[1].nodeIds[2] = nodes[3];
1122   facesWithNodes.elems[1].nbNodes = 3;
1123   facesWithNodes.elems[1].vtkType = VTK_TRIANGLE;
1124
1125   facesWithNodes.elems[2].nodeIds[0] = nodes[0];
1126   facesWithNodes.elems[2].nodeIds[1] = nodes[2];
1127   facesWithNodes.elems[2].nodeIds[2] = nodes[3];
1128   facesWithNodes.elems[2].nbNodes = 3;
1129   facesWithNodes.elems[2].vtkType = VTK_TRIANGLE;
1130
1131   facesWithNodes.elems[3].nodeIds[0] = nodes[1];
1132   facesWithNodes.elems[3].nodeIds[1] = nodes[2];
1133   facesWithNodes.elems[3].nodeIds[2] = nodes[3];
1134   facesWithNodes.elems[3].nbNodes = 3;
1135   facesWithNodes.elems[3].vtkType = VTK_TRIANGLE;
1136 }
1137
1138 // ---------------------------------------------------------------------------
1139
1140 SMDS_DownQuadTetra::SMDS_DownQuadTetra(SMDS_UnstructuredGrid *grid) :
1141   SMDS_Down3D(grid, 4)
1142 {
1143   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1144   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1145   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1146   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1147 }
1148
1149 SMDS_DownQuadTetra::~SMDS_DownQuadTetra()
1150 {
1151 }
1152
1153 void SMDS_DownQuadTetra::addDownCell(int cellId, int lowCellId, unsigned char aType)
1154 {
1155   //ASSERT((cellId >=0)&& (cellId < _maxId));
1156   //ASSERT(aType == VTK_QUADRATIC_TRIANGLE);
1157   int *faces = &_cellIds[_nbDownCells * cellId];
1158   for (int i = 0; i < _nbDownCells; i++)
1159     {
1160       if (faces[i] < 0)
1161         {
1162           faces[i] = lowCellId;
1163           return;
1164         }
1165       if (faces[i] == lowCellId)
1166         return;
1167     }
1168   ASSERT(0);
1169 }
1170
1171 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
1172  * The ordering of the ten points defining the quadratic tetrahedron cell is point id's (0-3,4-9)
1173  * where id's 0-3 are the four tetrahedron vertices;
1174  * and point id's 4-9 are the mid-edge nodes between (0,1), (1,2), (2,0), (0,3), (1,3), and (2,3).
1175  * @see vtkQuadraticTetra.h in Filtering.
1176  * @param cellId volumeId in vtkUnstructuredGrid
1177  * @param facesWithNodes vector of face descriptors to be filled
1178  */
1179 void SMDS_DownQuadTetra::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1180 {
1181   // --- find point id's of the volume
1182
1183   vtkIdType npts = 0;
1184   vtkIdType *nodes; // will refer to the point id's of the volume
1185   _grid->GetCellPoints(cellId, npts, nodes);
1186
1187   // --- create all the ordered list of node id's for each face
1188
1189   facesWithNodes.nbElems = 4;
1190
1191   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1192   facesWithNodes.elems[0].nodeIds[1] = nodes[1];
1193   facesWithNodes.elems[0].nodeIds[2] = nodes[2];
1194   facesWithNodes.elems[0].nodeIds[3] = nodes[4];
1195   facesWithNodes.elems[0].nodeIds[4] = nodes[5];
1196   facesWithNodes.elems[0].nodeIds[5] = nodes[6];
1197   facesWithNodes.elems[0].nbNodes = 6;
1198   facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_TRIANGLE;
1199
1200   facesWithNodes.elems[1].nodeIds[0] = nodes[0];
1201   facesWithNodes.elems[1].nodeIds[1] = nodes[1];
1202   facesWithNodes.elems[1].nodeIds[2] = nodes[3];
1203   facesWithNodes.elems[1].nodeIds[3] = nodes[4];
1204   facesWithNodes.elems[1].nodeIds[4] = nodes[7];
1205   facesWithNodes.elems[1].nodeIds[5] = nodes[8];
1206   facesWithNodes.elems[1].nbNodes = 6;
1207   facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_TRIANGLE;
1208
1209   facesWithNodes.elems[2].nodeIds[0] = nodes[0];
1210   facesWithNodes.elems[2].nodeIds[1] = nodes[2];
1211   facesWithNodes.elems[2].nodeIds[2] = nodes[3];
1212   facesWithNodes.elems[2].nodeIds[3] = nodes[6];
1213   facesWithNodes.elems[2].nodeIds[4] = nodes[7];
1214   facesWithNodes.elems[2].nodeIds[5] = nodes[9];
1215   facesWithNodes.elems[2].nbNodes = 6;
1216   facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_TRIANGLE;
1217
1218   facesWithNodes.elems[3].nodeIds[0] = nodes[1];
1219   facesWithNodes.elems[3].nodeIds[1] = nodes[2];
1220   facesWithNodes.elems[3].nodeIds[2] = nodes[3];
1221   facesWithNodes.elems[3].nodeIds[3] = nodes[5];
1222   facesWithNodes.elems[3].nodeIds[4] = nodes[8];
1223   facesWithNodes.elems[3].nodeIds[5] = nodes[9];
1224   facesWithNodes.elems[3].nbNodes = 6;
1225   facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_TRIANGLE;
1226 }
1227
1228 // ---------------------------------------------------------------------------
1229
1230 SMDS_DownPyramid::SMDS_DownPyramid(SMDS_UnstructuredGrid *grid) :
1231   SMDS_Down3D(grid, 5)
1232 {
1233   _cellTypes.push_back(VTK_QUAD);
1234   _cellTypes.push_back(VTK_TRIANGLE);
1235   _cellTypes.push_back(VTK_TRIANGLE);
1236   _cellTypes.push_back(VTK_TRIANGLE);
1237   _cellTypes.push_back(VTK_TRIANGLE);
1238 }
1239
1240 SMDS_DownPyramid::~SMDS_DownPyramid()
1241 {
1242 }
1243
1244 void SMDS_DownPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
1245 {
1246   //ASSERT((cellId >=0) && (cellId < _maxId));
1247   int *faces = &_cellIds[_nbDownCells * cellId];
1248   if (aType == VTK_QUAD)
1249     {
1250       if (faces[0] < 0)
1251         {
1252           faces[0] = lowCellId;
1253           return;
1254         }
1255       if (faces[0] == lowCellId)
1256         return;
1257     }
1258   else
1259     {
1260       //ASSERT(aType == VTK_TRIANGLE);
1261       for (int i = 1; i < _nbDownCells; i++)
1262         {
1263           if (faces[i] < 0)
1264             {
1265               faces[i] = lowCellId;
1266               return;
1267             }
1268           if (faces[i] == lowCellId)
1269             return;
1270         }
1271     }
1272   ASSERT(0);
1273 }
1274
1275 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
1276  * The pyramid is defined by the five points (0-4) where (0,1,2,3) is the base of the pyramid which,
1277  * using the right hand rule, forms a quadrilateral whose normal points in the direction of the
1278  * pyramid apex at vertex #4.
1279  * @see vtkPyramid.h in Filtering.
1280  * @param cellId volumeId in vtkUnstructuredGrid
1281  * @param facesWithNodes vector of face descriptors to be filled
1282  */
1283 void SMDS_DownPyramid::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1284 {
1285   // --- find point id's of the volume
1286
1287   vtkIdType npts = 0;
1288   vtkIdType *nodes; // will refer to the point id's of the volume
1289   _grid->GetCellPoints(cellId, npts, nodes);
1290
1291   // --- create all the ordered list of node id's for each face
1292
1293   facesWithNodes.nbElems = 5;
1294
1295   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1296   facesWithNodes.elems[0].nodeIds[1] = nodes[1];
1297   facesWithNodes.elems[0].nodeIds[2] = nodes[2];
1298   facesWithNodes.elems[0].nodeIds[3] = nodes[3];
1299   facesWithNodes.elems[0].nbNodes = 4;
1300   facesWithNodes.elems[0].vtkType = VTK_QUAD;
1301
1302   facesWithNodes.elems[1].nodeIds[0] = nodes[0];
1303   facesWithNodes.elems[1].nodeIds[1] = nodes[1];
1304   facesWithNodes.elems[1].nodeIds[2] = nodes[4];
1305   facesWithNodes.elems[1].nbNodes = 3;
1306   facesWithNodes.elems[1].vtkType = VTK_TRIANGLE;
1307
1308   facesWithNodes.elems[2].nodeIds[0] = nodes[1];
1309   facesWithNodes.elems[2].nodeIds[1] = nodes[2];
1310   facesWithNodes.elems[2].nodeIds[2] = nodes[4];
1311   facesWithNodes.elems[2].nbNodes = 3;
1312   facesWithNodes.elems[2].vtkType = VTK_TRIANGLE;
1313
1314   facesWithNodes.elems[3].nodeIds[0] = nodes[2];
1315   facesWithNodes.elems[3].nodeIds[1] = nodes[3];
1316   facesWithNodes.elems[3].nodeIds[2] = nodes[4];
1317   facesWithNodes.elems[3].nbNodes = 3;
1318   facesWithNodes.elems[3].vtkType = VTK_TRIANGLE;
1319
1320   facesWithNodes.elems[4].nodeIds[0] = nodes[3];
1321   facesWithNodes.elems[4].nodeIds[1] = nodes[0];
1322   facesWithNodes.elems[4].nodeIds[2] = nodes[4];
1323   facesWithNodes.elems[4].nbNodes = 3;
1324   facesWithNodes.elems[4].vtkType = VTK_TRIANGLE;
1325 }
1326
1327 // ---------------------------------------------------------------------------
1328
1329 SMDS_DownQuadPyramid::SMDS_DownQuadPyramid(SMDS_UnstructuredGrid *grid) :
1330   SMDS_Down3D(grid, 5)
1331 {
1332   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1333   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1334   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1335   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1336   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1337 }
1338
1339 SMDS_DownQuadPyramid::~SMDS_DownQuadPyramid()
1340 {
1341 }
1342
1343 void SMDS_DownQuadPyramid::addDownCell(int cellId, int lowCellId, unsigned char aType)
1344 {
1345   //ASSERT((cellId >=0) && (cellId < _maxId));
1346   int *faces = &_cellIds[_nbDownCells * cellId];
1347   if (aType == VTK_QUADRATIC_QUAD)
1348     {
1349       if (faces[0] < 0)
1350         {
1351           faces[0] = lowCellId;
1352           return;
1353         }
1354       if (faces[0] == lowCellId)
1355         return;
1356     }
1357   else
1358     {
1359       //ASSERT(aType == VTK_QUADRATIC_TRIANGLE);
1360       for (int i = 1; i < _nbDownCells; i++)
1361         {
1362           if (faces[i] < 0)
1363             {
1364               faces[i] = lowCellId;
1365               return;
1366             }
1367           if (faces[i] == lowCellId)
1368             return;
1369         }
1370     }
1371   ASSERT(0);
1372 }
1373
1374 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
1375  * The ordering of the thirteen points defining the quadratic pyramid cell is point id's (0-4,5-12)
1376  * where point id's 0-4 are the five corner vertices of the pyramid; followed
1377  * by eight mid-edge nodes (5-12). Note that these mid-edge nodes lie on the edges defined by
1378  * 5(0,1), 6(1,2), 7(2,3), 8(3,0), 9(0,4), 10(1,4), 11(2,4), 12(3,4).
1379  * @see vtkQuadraticPyramid.h in Filtering.
1380  * @param cellId volumeId in vtkUnstructuredGrid
1381  * @param facesWithNodes vector of face descriptors to be filled
1382  */
1383 void SMDS_DownQuadPyramid::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1384 {
1385   // --- find point id's of the volume
1386
1387   vtkIdType npts = 0;
1388   vtkIdType *nodes; // will refer to the point id's of the volume
1389   _grid->GetCellPoints(cellId, npts, nodes);
1390
1391   // --- create all the ordered list of node id's for each face
1392
1393   facesWithNodes.nbElems = 5;
1394
1395   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1396   facesWithNodes.elems[0].nodeIds[1] = nodes[1];
1397   facesWithNodes.elems[0].nodeIds[2] = nodes[2];
1398   facesWithNodes.elems[0].nodeIds[3] = nodes[3];
1399   facesWithNodes.elems[0].nodeIds[4] = nodes[5];
1400   facesWithNodes.elems[0].nodeIds[5] = nodes[6];
1401   facesWithNodes.elems[0].nodeIds[6] = nodes[7];
1402   facesWithNodes.elems[0].nodeIds[7] = nodes[8];
1403   facesWithNodes.elems[0].nbNodes = 8;
1404   facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_QUAD;
1405
1406   facesWithNodes.elems[1].nodeIds[0] = nodes[0];
1407   facesWithNodes.elems[1].nodeIds[1] = nodes[1];
1408   facesWithNodes.elems[1].nodeIds[2] = nodes[4];
1409   facesWithNodes.elems[1].nodeIds[3] = nodes[5];
1410   facesWithNodes.elems[1].nodeIds[4] = nodes[9];
1411   facesWithNodes.elems[1].nodeIds[5] = nodes[10];
1412   facesWithNodes.elems[1].nbNodes = 6;
1413   facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_TRIANGLE;
1414
1415   facesWithNodes.elems[2].nodeIds[0] = nodes[1];
1416   facesWithNodes.elems[2].nodeIds[1] = nodes[2];
1417   facesWithNodes.elems[2].nodeIds[2] = nodes[4];
1418   facesWithNodes.elems[2].nodeIds[3] = nodes[6];
1419   facesWithNodes.elems[2].nodeIds[4] = nodes[10];
1420   facesWithNodes.elems[2].nodeIds[5] = nodes[11];
1421   facesWithNodes.elems[2].nbNodes = 6;
1422   facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_TRIANGLE;
1423
1424   facesWithNodes.elems[3].nodeIds[0] = nodes[2];
1425   facesWithNodes.elems[3].nodeIds[1] = nodes[3];
1426   facesWithNodes.elems[3].nodeIds[2] = nodes[4];
1427   facesWithNodes.elems[3].nodeIds[3] = nodes[7];
1428   facesWithNodes.elems[3].nodeIds[4] = nodes[11];
1429   facesWithNodes.elems[3].nodeIds[5] = nodes[12];
1430   facesWithNodes.elems[3].nbNodes = 6;
1431   facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_TRIANGLE;
1432
1433   facesWithNodes.elems[4].nodeIds[0] = nodes[3];
1434   facesWithNodes.elems[4].nodeIds[1] = nodes[0];
1435   facesWithNodes.elems[4].nodeIds[2] = nodes[4];
1436   facesWithNodes.elems[4].nodeIds[3] = nodes[8];
1437   facesWithNodes.elems[4].nodeIds[4] = nodes[9];
1438   facesWithNodes.elems[4].nodeIds[5] = nodes[12];
1439   facesWithNodes.elems[4].nbNodes = 6;
1440   facesWithNodes.elems[4].vtkType = VTK_QUADRATIC_TRIANGLE;
1441 }
1442
1443 // ---------------------------------------------------------------------------
1444
1445 SMDS_DownPenta::SMDS_DownPenta(SMDS_UnstructuredGrid *grid) :
1446   SMDS_Down3D(grid, 5)
1447 {
1448   _cellTypes.push_back(VTK_QUAD);
1449   _cellTypes.push_back(VTK_QUAD);
1450   _cellTypes.push_back(VTK_QUAD);
1451   _cellTypes.push_back(VTK_TRIANGLE);
1452   _cellTypes.push_back(VTK_TRIANGLE);
1453 }
1454
1455 SMDS_DownPenta::~SMDS_DownPenta()
1456 {
1457 }
1458
1459 void SMDS_DownPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
1460 {
1461   //ASSERT((cellId >=0) && (cellId < _maxId));
1462   int *faces = &_cellIds[_nbDownCells * cellId];
1463   if (aType == VTK_QUAD)
1464     for (int i = 0; i < 2; i++)
1465       {
1466         if (faces[i] < 0)
1467           {
1468             faces[i] = lowCellId;
1469             return;
1470           }
1471         if (faces[i] == lowCellId)
1472           return;
1473       }
1474   else
1475     {
1476       //ASSERT(aType == VTK_TRIANGLE);
1477       for (int i = 2; i < _nbDownCells; i++)
1478         {
1479           if (faces[i] < 0)
1480             {
1481               faces[i] = lowCellId;
1482               return;
1483             }
1484           if (faces[i] == lowCellId)
1485             return;
1486         }
1487     }
1488   ASSERT(0);
1489 }
1490
1491 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's.
1492  * A wedge or pentahedron consists of two triangular and three quadrilateral faces
1493  * and is defined by the six points (0-5) where (0,1,2) is the base of the wedge which,
1494  * using the right hand rule, forms a triangle whose normal points outward
1495  * (away from the triangular face (3,4,5)).
1496  * @see vtkWedge.h in Filtering
1497  * @param cellId volumeId in vtkUnstructuredGrid
1498  * @param facesWithNodes vector of face descriptors to be filled
1499  */
1500 void SMDS_DownPenta::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1501 {
1502   // --- find point id's of the volume
1503
1504   vtkIdType npts = 0;
1505   vtkIdType *nodes; // will refer to the point id's of the volume
1506   _grid->GetCellPoints(cellId, npts, nodes);
1507
1508   // --- create all the ordered list of node id's for each face
1509
1510   facesWithNodes.nbElems = 5;
1511
1512   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1513   facesWithNodes.elems[0].nodeIds[1] = nodes[2];
1514   facesWithNodes.elems[0].nodeIds[2] = nodes[5];
1515   facesWithNodes.elems[0].nodeIds[3] = nodes[3];
1516   facesWithNodes.elems[0].nbNodes = 4;
1517   facesWithNodes.elems[0].vtkType = VTK_QUAD;
1518
1519   facesWithNodes.elems[1].nodeIds[0] = nodes[1];
1520   facesWithNodes.elems[1].nodeIds[1] = nodes[2];
1521   facesWithNodes.elems[1].nodeIds[2] = nodes[5];
1522   facesWithNodes.elems[1].nodeIds[3] = nodes[4];
1523   facesWithNodes.elems[1].nbNodes = 4;
1524   facesWithNodes.elems[1].vtkType = VTK_QUAD;
1525
1526   facesWithNodes.elems[2].nodeIds[0] = nodes[0];
1527   facesWithNodes.elems[2].nodeIds[1] = nodes[1];
1528   facesWithNodes.elems[2].nodeIds[2] = nodes[4];
1529   facesWithNodes.elems[2].nodeIds[3] = nodes[3];
1530   facesWithNodes.elems[2].nbNodes = 4;
1531   facesWithNodes.elems[2].vtkType = VTK_QUAD;
1532
1533   facesWithNodes.elems[3].nodeIds[0] = nodes[0];
1534   facesWithNodes.elems[3].nodeIds[1] = nodes[1];
1535   facesWithNodes.elems[3].nodeIds[2] = nodes[2];
1536   facesWithNodes.elems[3].nbNodes = 3;
1537   facesWithNodes.elems[3].vtkType = VTK_TRIANGLE;
1538
1539   facesWithNodes.elems[4].nodeIds[0] = nodes[3];
1540   facesWithNodes.elems[4].nodeIds[1] = nodes[4];
1541   facesWithNodes.elems[4].nodeIds[2] = nodes[5];
1542   facesWithNodes.elems[4].nbNodes = 3;
1543   facesWithNodes.elems[4].vtkType = VTK_TRIANGLE;
1544 }
1545
1546 // ---------------------------------------------------------------------------
1547
1548 SMDS_DownQuadPenta::SMDS_DownQuadPenta(SMDS_UnstructuredGrid *grid) :
1549   SMDS_Down3D(grid, 5)
1550 {
1551   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1552   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1553   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1554   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1555   _cellTypes.push_back(VTK_QUADRATIC_TRIANGLE);
1556 }
1557
1558 SMDS_DownQuadPenta::~SMDS_DownQuadPenta()
1559 {
1560 }
1561
1562 void SMDS_DownQuadPenta::addDownCell(int cellId, int lowCellId, unsigned char aType)
1563 {
1564   //ASSERT((cellId >=0) && (cellId < _maxId));
1565   int *faces = &_cellIds[_nbDownCells * cellId];
1566   if (aType == VTK_QUADRATIC_QUAD)
1567     for (int i = 0; i < 2; i++)
1568       {
1569         if (faces[i] < 0)
1570           {
1571             faces[i] = lowCellId;
1572             return;
1573           }
1574         if (faces[i] == lowCellId)
1575           return;
1576       }
1577   else
1578     {
1579       //ASSERT(aType == VTK_QUADRATIC_TRIANGLE);
1580       for (int i = 2; i < _nbDownCells; i++)
1581         {
1582           if (faces[i] < 0)
1583             {
1584               faces[i] = lowCellId;
1585               return;
1586             }
1587           if (faces[i] == lowCellId)
1588             return;
1589         }
1590     }
1591   ASSERT(0);
1592 }
1593
1594 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
1595  * The quadratic wedge (or pentahedron) is defined by fifteen points.
1596  * The ordering of the fifteen points defining the cell is point id's (0-5,6-14)
1597  * where point id's 0-5 are the six corner vertices of the wedge, followed by
1598  * nine mid-edge nodes (6-14). Note that these mid-edge nodes lie on the edges defined by
1599  * (0,1), (1,2), (2,0), (3,4), (4,5), (5,3), (0,3), (1,4), (2,5).
1600  * @see vtkQuadraticWedge.h in Filtering
1601  * @param cellId volumeId in vtkUnstructuredGrid
1602  * @param facesWithNodes vector of face descriptors to be filled
1603  */
1604 void SMDS_DownQuadPenta::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1605 {
1606   // --- find point id's of the volume
1607
1608   vtkIdType npts = 0;
1609   vtkIdType *nodes; // will refer to the point id's of the volume
1610   _grid->GetCellPoints(cellId, npts, nodes);
1611
1612   // --- create all the ordered list of node id's for each face
1613
1614   facesWithNodes.nbElems = 5;
1615
1616   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1617   facesWithNodes.elems[0].nodeIds[1] = nodes[2];
1618   facesWithNodes.elems[0].nodeIds[2] = nodes[5];
1619   facesWithNodes.elems[0].nodeIds[3] = nodes[3];
1620   facesWithNodes.elems[0].nodeIds[4] = nodes[8];
1621   facesWithNodes.elems[0].nodeIds[5] = nodes[14];
1622   facesWithNodes.elems[0].nodeIds[6] = nodes[11];
1623   facesWithNodes.elems[0].nodeIds[7] = nodes[12];
1624   facesWithNodes.elems[0].nbNodes = 8;
1625   facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_QUAD;
1626
1627   facesWithNodes.elems[1].nodeIds[0] = nodes[1];
1628   facesWithNodes.elems[1].nodeIds[1] = nodes[2];
1629   facesWithNodes.elems[1].nodeIds[2] = nodes[5];
1630   facesWithNodes.elems[1].nodeIds[3] = nodes[4];
1631   facesWithNodes.elems[1].nodeIds[4] = nodes[7];
1632   facesWithNodes.elems[1].nodeIds[5] = nodes[14];
1633   facesWithNodes.elems[1].nodeIds[6] = nodes[10];
1634   facesWithNodes.elems[1].nodeIds[7] = nodes[13];
1635   facesWithNodes.elems[1].nbNodes = 8;
1636   facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_QUAD;
1637
1638   facesWithNodes.elems[2].nodeIds[0] = nodes[0];
1639   facesWithNodes.elems[2].nodeIds[1] = nodes[1];
1640   facesWithNodes.elems[2].nodeIds[2] = nodes[4];
1641   facesWithNodes.elems[2].nodeIds[3] = nodes[3];
1642   facesWithNodes.elems[2].nodeIds[4] = nodes[6];
1643   facesWithNodes.elems[2].nodeIds[5] = nodes[13];
1644   facesWithNodes.elems[2].nodeIds[6] = nodes[9];
1645   facesWithNodes.elems[2].nodeIds[7] = nodes[12];
1646   facesWithNodes.elems[2].nbNodes = 8;
1647   facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_QUAD;
1648
1649   facesWithNodes.elems[3].nodeIds[0] = nodes[0];
1650   facesWithNodes.elems[3].nodeIds[1] = nodes[1];
1651   facesWithNodes.elems[3].nodeIds[2] = nodes[2];
1652   facesWithNodes.elems[3].nodeIds[3] = nodes[6];
1653   facesWithNodes.elems[3].nodeIds[4] = nodes[7];
1654   facesWithNodes.elems[3].nodeIds[5] = nodes[8];
1655   facesWithNodes.elems[3].nbNodes = 6;
1656   facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_TRIANGLE;
1657
1658   facesWithNodes.elems[4].nodeIds[0] = nodes[3];
1659   facesWithNodes.elems[4].nodeIds[1] = nodes[4];
1660   facesWithNodes.elems[4].nodeIds[2] = nodes[5];
1661   facesWithNodes.elems[4].nodeIds[3] = nodes[9];
1662   facesWithNodes.elems[4].nodeIds[4] = nodes[10];
1663   facesWithNodes.elems[4].nodeIds[5] = nodes[11];
1664   facesWithNodes.elems[4].nbNodes = 6;
1665   facesWithNodes.elems[4].vtkType = VTK_QUADRATIC_TRIANGLE;
1666 }
1667
1668 // ---------------------------------------------------------------------------
1669
1670 SMDS_DownHexa::SMDS_DownHexa(SMDS_UnstructuredGrid *grid) :
1671   SMDS_Down3D(grid, 6)
1672 {
1673   _cellTypes.push_back(VTK_QUAD);
1674   _cellTypes.push_back(VTK_QUAD);
1675   _cellTypes.push_back(VTK_QUAD);
1676   _cellTypes.push_back(VTK_QUAD);
1677   _cellTypes.push_back(VTK_QUAD);
1678   _cellTypes.push_back(VTK_QUAD);
1679 }
1680
1681 SMDS_DownHexa::~SMDS_DownHexa()
1682 {
1683 }
1684
1685 void SMDS_DownHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
1686 {
1687   //ASSERT((cellId >=0)&& (cellId < _maxId));
1688   int *faces = &_cellIds[_nbDownCells * cellId];
1689   for (int i = 0; i < _nbDownCells; i++)
1690     {
1691       if (faces[i] < 0)
1692         {
1693           faces[i] = lowCellId;
1694           return;
1695         }
1696       if (faces[i] == lowCellId)
1697         return;
1698     }
1699   ASSERT(0);
1700   // MESSAGE("-------------------------------------> trop de faces ! " << cellId << " " << lowCellId);
1701 }
1702
1703 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
1704  * The hexahedron is defined by the eight points (0-7), where (0,1,2,3) is the base
1705  * of the hexahedron which, using the right hand rule, forms a quadrilateral whose normal
1706  * points in the direction of the opposite face (4,5,6,7).
1707  * @see vtkHexahedron.h in Filtering
1708  * @param cellId volumeId in vtkUnstructuredGrid
1709  * @param facesWithNodes vector of face descriptors to be filled
1710  */
1711 void SMDS_DownHexa::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1712 {
1713   // --- find point id's of the volume
1714
1715   vtkIdType npts = 0;
1716   vtkIdType *nodes; // will refer to the point id's of the volume
1717   _grid->GetCellPoints(cellId, npts, nodes);
1718
1719   // --- create all the ordered list of node id's for each face
1720
1721   facesWithNodes.nbElems = 6;
1722
1723   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1724   facesWithNodes.elems[0].nodeIds[1] = nodes[1];
1725   facesWithNodes.elems[0].nodeIds[2] = nodes[2];
1726   facesWithNodes.elems[0].nodeIds[3] = nodes[3];
1727   facesWithNodes.elems[0].nbNodes = 4;
1728   facesWithNodes.elems[0].vtkType = VTK_QUAD;
1729
1730   facesWithNodes.elems[1].nodeIds[0] = nodes[4];
1731   facesWithNodes.elems[1].nodeIds[1] = nodes[5];
1732   facesWithNodes.elems[1].nodeIds[2] = nodes[6];
1733   facesWithNodes.elems[1].nodeIds[3] = nodes[7];
1734   facesWithNodes.elems[1].nbNodes = 4;
1735   facesWithNodes.elems[1].vtkType = VTK_QUAD;
1736
1737   facesWithNodes.elems[2].nodeIds[0] = nodes[0];
1738   facesWithNodes.elems[2].nodeIds[1] = nodes[1];
1739   facesWithNodes.elems[2].nodeIds[2] = nodes[5];
1740   facesWithNodes.elems[2].nodeIds[3] = nodes[4];
1741   facesWithNodes.elems[2].nbNodes = 4;
1742   facesWithNodes.elems[2].vtkType = VTK_QUAD;
1743
1744   facesWithNodes.elems[3].nodeIds[0] = nodes[1];
1745   facesWithNodes.elems[3].nodeIds[1] = nodes[2];
1746   facesWithNodes.elems[3].nodeIds[2] = nodes[6];
1747   facesWithNodes.elems[3].nodeIds[3] = nodes[5];
1748   facesWithNodes.elems[3].nbNodes = 4;
1749   facesWithNodes.elems[3].vtkType = VTK_QUAD;
1750
1751   facesWithNodes.elems[4].nodeIds[0] = nodes[2];
1752   facesWithNodes.elems[4].nodeIds[1] = nodes[6];
1753   facesWithNodes.elems[4].nodeIds[2] = nodes[7];
1754   facesWithNodes.elems[4].nodeIds[3] = nodes[3];
1755   facesWithNodes.elems[4].nbNodes = 4;
1756   facesWithNodes.elems[4].vtkType = VTK_QUAD;
1757
1758   facesWithNodes.elems[5].nodeIds[0] = nodes[3];
1759   facesWithNodes.elems[5].nodeIds[1] = nodes[7];
1760   facesWithNodes.elems[5].nodeIds[2] = nodes[4];
1761   facesWithNodes.elems[5].nodeIds[3] = nodes[0];
1762   facesWithNodes.elems[5].nbNodes = 4;
1763   facesWithNodes.elems[5].vtkType = VTK_QUAD;
1764 }
1765
1766 // ---------------------------------------------------------------------------
1767
1768 SMDS_DownQuadHexa::SMDS_DownQuadHexa(SMDS_UnstructuredGrid *grid) :
1769   SMDS_Down3D(grid, 6)
1770 {
1771   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1772   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1773   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1774   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1775   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1776   _cellTypes.push_back(VTK_QUADRATIC_QUAD);
1777 }
1778
1779 SMDS_DownQuadHexa::~SMDS_DownQuadHexa()
1780 {
1781 }
1782
1783 void SMDS_DownQuadHexa::addDownCell(int cellId, int lowCellId, unsigned char aType)
1784 {
1785   //ASSERT((cellId >=0)&& (cellId < _maxId));
1786   int *faces = &_cellIds[_nbDownCells * cellId];
1787   for (int i = 0; i < _nbDownCells; i++)
1788     {
1789       if (faces[i] < 0)
1790         {
1791           faces[i] = lowCellId;
1792           return;
1793         }
1794       if (faces[i] == lowCellId)
1795         return;
1796     }
1797   ASSERT(0);
1798 }
1799
1800 /*! Create a list of faces described by a vtk Type and  an ordered set of Node Id's
1801  * The ordering of the twenty points defining the quadratic hexahedron cell is point id's (0-7,8-19)
1802  * where point id's 0-7 are the eight corner vertices of the cube, followed by twelve mid-edge nodes (8-19).
1803  * Note that these mid-edge nodes lie on the edges defined by
1804  * (0,1), (1,2), (2,3), (3,0), (4,5), (5,6), (6,7), (7,4), (0,4), (1,5), (2,6), (3,7).
1805  * @see vtkQuadraticHexahedron.h in Filtering
1806  * @param cellId volumeId in vtkUnstructuredGrid
1807  * @param facesWithNodes vector of face descriptors to be filled
1808  */
1809 void SMDS_DownQuadHexa::computeFacesWithNodes(int cellId, ListElemByNodesType& facesWithNodes)
1810 {
1811   // --- find point id's of the volume
1812
1813   vtkIdType npts = 0;
1814   vtkIdType *nodes; // will refer to the point id's of the volume
1815   _grid->GetCellPoints(cellId, npts, nodes);
1816
1817   // --- create all the ordered list of node id's for each face
1818
1819   facesWithNodes.nbElems = 6;
1820
1821   facesWithNodes.elems[0].nodeIds[0] = nodes[0];
1822   facesWithNodes.elems[0].nodeIds[1] = nodes[1];
1823   facesWithNodes.elems[0].nodeIds[2] = nodes[2];
1824   facesWithNodes.elems[0].nodeIds[3] = nodes[3];
1825   facesWithNodes.elems[0].nodeIds[4] = nodes[8];
1826   facesWithNodes.elems[0].nodeIds[5] = nodes[9];
1827   facesWithNodes.elems[0].nodeIds[6] = nodes[10];
1828   facesWithNodes.elems[0].nodeIds[7] = nodes[11];
1829   facesWithNodes.elems[0].nbNodes = 8;
1830   facesWithNodes.elems[0].vtkType = VTK_QUADRATIC_QUAD;
1831
1832   facesWithNodes.elems[1].nodeIds[0] = nodes[4];
1833   facesWithNodes.elems[1].nodeIds[1] = nodes[5];
1834   facesWithNodes.elems[1].nodeIds[2] = nodes[6];
1835   facesWithNodes.elems[1].nodeIds[3] = nodes[7];
1836   facesWithNodes.elems[1].nodeIds[4] = nodes[12];
1837   facesWithNodes.elems[1].nodeIds[5] = nodes[13];
1838   facesWithNodes.elems[1].nodeIds[6] = nodes[14];
1839   facesWithNodes.elems[1].nodeIds[7] = nodes[15];
1840   facesWithNodes.elems[1].nbNodes = 8;
1841   facesWithNodes.elems[1].vtkType = VTK_QUADRATIC_QUAD;
1842
1843   facesWithNodes.elems[2].nodeIds[0] = nodes[0];
1844   facesWithNodes.elems[2].nodeIds[1] = nodes[1];
1845   facesWithNodes.elems[2].nodeIds[2] = nodes[5];
1846   facesWithNodes.elems[2].nodeIds[3] = nodes[4];
1847   facesWithNodes.elems[2].nodeIds[4] = nodes[8];
1848   facesWithNodes.elems[2].nodeIds[5] = nodes[17];
1849   facesWithNodes.elems[2].nodeIds[6] = nodes[12];
1850   facesWithNodes.elems[2].nodeIds[7] = nodes[16];
1851   facesWithNodes.elems[2].nbNodes = 8;
1852   facesWithNodes.elems[2].vtkType = VTK_QUADRATIC_QUAD;
1853
1854   facesWithNodes.elems[3].nodeIds[0] = nodes[1];
1855   facesWithNodes.elems[3].nodeIds[1] = nodes[2];
1856   facesWithNodes.elems[3].nodeIds[2] = nodes[6];
1857   facesWithNodes.elems[3].nodeIds[3] = nodes[5];
1858   facesWithNodes.elems[3].nodeIds[4] = nodes[9];
1859   facesWithNodes.elems[3].nodeIds[5] = nodes[18];
1860   facesWithNodes.elems[3].nodeIds[6] = nodes[13];
1861   facesWithNodes.elems[3].nodeIds[7] = nodes[17];
1862   facesWithNodes.elems[3].nbNodes = 8;
1863   facesWithNodes.elems[3].vtkType = VTK_QUADRATIC_QUAD;
1864
1865   facesWithNodes.elems[4].nodeIds[0] = nodes[2];
1866   facesWithNodes.elems[4].nodeIds[1] = nodes[6];
1867   facesWithNodes.elems[4].nodeIds[2] = nodes[7];
1868   facesWithNodes.elems[4].nodeIds[3] = nodes[3];
1869   facesWithNodes.elems[4].nodeIds[4] = nodes[18];
1870   facesWithNodes.elems[4].nodeIds[5] = nodes[14];
1871   facesWithNodes.elems[4].nodeIds[6] = nodes[19];
1872   facesWithNodes.elems[4].nodeIds[7] = nodes[10];
1873   facesWithNodes.elems[4].nbNodes = 8;
1874   facesWithNodes.elems[4].vtkType = VTK_QUADRATIC_QUAD;
1875
1876   facesWithNodes.elems[5].nodeIds[0] = nodes[3];
1877   facesWithNodes.elems[5].nodeIds[1] = nodes[7];
1878   facesWithNodes.elems[5].nodeIds[2] = nodes[4];
1879   facesWithNodes.elems[5].nodeIds[3] = nodes[0];
1880   facesWithNodes.elems[5].nodeIds[4] = nodes[19];
1881   facesWithNodes.elems[5].nodeIds[5] = nodes[15];
1882   facesWithNodes.elems[5].nodeIds[6] = nodes[16];
1883   facesWithNodes.elems[5].nodeIds[7] = nodes[11];
1884   facesWithNodes.elems[5].nbNodes = 8;
1885   facesWithNodes.elems[5].vtkType = VTK_QUADRATIC_QUAD;
1886 }
1887
1888 // ---------------------------------------------------------------------------
1889