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