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