Salome HOME
IMP 23373: [CEA 1170] Optimization of a 3D mesh using MG-Tetra
[modules/smesh.git] / src / SMDS / SMDS_VtkVolume.cxx
1 // Copyright (C) 2010-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SMDS_VtkVolume.hxx"
21 #include "SMDS_MeshNode.hxx"
22 #include "SMDS_Mesh.hxx"
23 #include "SMDS_VtkCellIterator.hxx"
24
25 #include "utilities.h"
26
27 #include <vector>
28
29 SMDS_VtkVolume::SMDS_VtkVolume()
30 {
31 }
32
33 SMDS_VtkVolume::SMDS_VtkVolume(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh)
34 {
35   init(nodeIds, mesh);
36 }
37 /*!
38  * typed used are vtk types (@see vtkCellType.h)
39  * see GetEntityType() for conversion in SMDS type (@see SMDSAbs_ElementType.hxx)
40  */
41 void SMDS_VtkVolume::init(const std::vector<vtkIdType>& nodeIds, SMDS_Mesh* mesh)
42 {
43   SMDS_MeshVolume::init();
44   myMeshId = mesh->getMeshId();
45   vtkIdType aType = VTK_TETRA;
46   switch (nodeIds.size()) // cases are in order of usage frequency
47   {
48     case 4:  aType = VTK_TETRA;                  break;
49     case 8:  aType = VTK_HEXAHEDRON;             break;
50     case 5:  aType = VTK_PYRAMID;                break;
51     case 6:  aType = VTK_WEDGE;                  break;
52     case 10: aType = VTK_QUADRATIC_TETRA;        break;
53     case 20: aType = VTK_QUADRATIC_HEXAHEDRON;   break;
54     case 13: aType = VTK_QUADRATIC_PYRAMID;      break;
55     case 15: aType = VTK_QUADRATIC_WEDGE;        break;
56     case 12: aType = VTK_HEXAGONAL_PRISM;        break;
57     case 27: aType = VTK_TRIQUADRATIC_HEXAHEDRON;break;
58     default: aType = VTK_HEXAHEDRON;
59   }
60   myVtkID = mesh->getGrid()->InsertNextLinkedCell(aType, nodeIds.size(), (vtkIdType *) &nodeIds[0]);
61   mesh->setMyModified();
62 }
63
64 void SMDS_VtkVolume::initPoly(const std::vector<vtkIdType>& nodeIds,
65                               const std::vector<int>&       nbNodesPerFace,
66                               SMDS_Mesh*                    mesh)
67 {
68   SMDS_MeshVolume::init();
69   SMDS_UnstructuredGrid* grid = mesh->getGrid();
70   //double center[3];
71   //this->gravityCenter(grid, &nodeIds[0], nodeIds.size(), &center[0]);
72   std::vector<vtkIdType> ptIds;
73   vtkIdType nbFaces = nbNodesPerFace.size();
74   int k = 0;
75   for (int i = 0; i < nbFaces; i++)
76   {
77     int nf = nbNodesPerFace[i];
78     ptIds.push_back(nf);
79     // EAP: a right approach is:
80     // - either the user should care of order of nodes or
81     // - the user should use a service method arranging nodes if he
82     //   don't want or can't to do it by him-self
83     // The method below works OK only with planar faces and convex polyhedrones
84     //
85     // double a[3];
86     // double b[3];
87     // double c[3];
88     // grid->GetPoints()->GetPoint(nodeIds[k], a);
89     // grid->GetPoints()->GetPoint(nodeIds[k + 1], b);
90     // grid->GetPoints()->GetPoint(nodeIds[k + 2], c);
91     // bool isFaceForward = this->isForward(a, b, c, center);
92     const vtkIdType *facePts = &nodeIds[k];
93     //if (isFaceForward)
94     for (int n = 0; n < nf; n++)
95       ptIds.push_back(facePts[n]);
96     // else
97     //   for (int n = nf - 1; n >= 0; n--)
98     //     ptIds.push_back(facePts[n]);
99     k += nf;
100   }
101   myVtkID = grid->InsertNextLinkedCell(VTK_POLYHEDRON, nbFaces, &ptIds[0]);
102   mesh->setMyModified();
103 }
104
105 bool SMDS_VtkVolume::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
106 {
107   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
108   vtkIdType npts = 0;
109   vtkIdType* pts = 0;
110   grid->GetCellPoints(myVtkID, npts, pts);
111   if (nbNodes != npts)
112   {
113     MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << nbNodes);
114     return false;
115   }
116   for (int i = 0; i < nbNodes; i++)
117   {
118     pts[i] = nodes[i]->getVtkId();
119   }
120   SMDS_Mesh::_meshList[myMeshId]->setMyModified();
121   return true;
122 }
123
124 /*!
125  * Reorder in VTK order a list of nodes given in SMDS order.
126  * To be used before ChangeNodes: lists are given or computed in SMDS order.
127  */
128 bool SMDS_VtkVolume::vtkOrder(const SMDS_MeshNode* nodes[], const int nbNodes)
129 {
130   if (nbNodes != this->NbNodes())
131   {
132     MESSAGE("vtkOrder, wrong number of nodes " << nbNodes << " instead of "<< this->NbNodes());
133     return false;
134   }
135   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
136   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
137   const std::vector<int>& interlace = SMDS_MeshCell::toVtkOrder( VTKCellType( aVtkType ));
138   if ( !interlace.empty() )
139   {
140     ASSERT( (int)interlace.size() == nbNodes );
141     std::vector<const SMDS_MeshNode*> initNodes( nodes, nodes+nbNodes );
142     for ( size_t i = 0; i < interlace.size(); ++i )
143       nodes[i] = initNodes[ interlace[i] ];
144   }
145   return true;
146 }
147
148 SMDS_VtkVolume::~SMDS_VtkVolume()
149 {
150 }
151
152 void SMDS_VtkVolume::Print(ostream & OS) const
153 {
154   OS << "volume <" << GetID() << "> : ";
155 }
156
157 int SMDS_VtkVolume::NbFaces() const
158 {
159   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
160   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
161   int nbFaces = 4;
162   switch (aVtkType)
163   {
164     case VTK_TETRA:
165     case VTK_QUADRATIC_TETRA:
166       nbFaces = 4;
167       break;
168     case VTK_PYRAMID:
169     case VTK_WEDGE:
170     case VTK_QUADRATIC_PYRAMID:
171     case VTK_QUADRATIC_WEDGE:
172       nbFaces = 5;
173       break;
174     case VTK_HEXAHEDRON:
175     case VTK_QUADRATIC_HEXAHEDRON:
176     case VTK_TRIQUADRATIC_HEXAHEDRON:
177       nbFaces = 6;
178       break;
179     case VTK_POLYHEDRON:
180       {
181         vtkIdType nFaces = 0;
182         vtkIdType* ptIds = 0;
183         grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
184         nbFaces = nFaces;
185         break;
186       }
187     case VTK_HEXAGONAL_PRISM:
188       nbFaces = 8;
189       break;
190     default:
191       MESSAGE("invalid volume type")
192       ;
193       nbFaces = 0;
194       break;
195   }
196   return nbFaces;
197 }
198
199 int SMDS_VtkVolume::NbNodes() const
200 {
201   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
202   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
203   vtkIdType nbPoints = 0;
204   if (aVtkType != VTK_POLYHEDRON)
205   {
206     vtkIdType *pts;
207     grid->GetCellPoints( myVtkID, nbPoints, pts );
208   }
209   else
210   {
211     vtkIdType nFaces = 0;
212     vtkIdType* ptIds = 0;
213     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
214     int id = 0;
215     for (int i = 0; i < nFaces; i++)
216     {
217       int nodesInFace = ptIds[id];
218       nbPoints += nodesInFace;
219       id += (nodesInFace + 1);
220     }
221   }
222   return nbPoints;
223 }
224
225 int SMDS_VtkVolume::NbEdges() const
226 {
227   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
228   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
229   int nbEdges = 6;
230   switch (aVtkType)
231   {
232     case VTK_TETRA:
233     case VTK_QUADRATIC_TETRA:
234       nbEdges = 6;
235       break;
236     case VTK_PYRAMID:
237     case VTK_QUADRATIC_PYRAMID:
238       nbEdges = 8;
239       break;
240     case VTK_WEDGE:
241     case VTK_QUADRATIC_WEDGE:
242       nbEdges = 9;
243       break;
244     case VTK_HEXAHEDRON:
245     case VTK_QUADRATIC_HEXAHEDRON:
246     case VTK_TRIQUADRATIC_HEXAHEDRON:
247       nbEdges = 12;
248       break;
249     case VTK_POLYHEDRON:
250       {
251         vtkIdType nFaces = 0;
252         vtkIdType* ptIds = 0;
253         grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
254         nbEdges = 0;
255         int id = 0;
256         for (int i = 0; i < nFaces; i++)
257           {
258             int edgesInFace = ptIds[id];
259             id += (edgesInFace + 1);
260             nbEdges += edgesInFace;
261           }
262         nbEdges = nbEdges / 2;
263         break;
264       }
265     case VTK_HEXAGONAL_PRISM:
266       nbEdges = 18;
267       break;
268     default:
269       MESSAGE("invalid volume type")
270       ;
271       nbEdges = 0;
272       break;
273   }
274   return nbEdges;
275 }
276
277 /*! polyhedron only,
278  *  1 <= face_ind <= NbFaces()
279  */
280 int SMDS_VtkVolume::NbFaceNodes(const int face_ind) const
281 {
282   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
283   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
284   int nbNodes = 0;
285   if (aVtkType == VTK_POLYHEDRON)
286   {
287     vtkIdType nFaces = 0;
288     vtkIdType* ptIds = 0;
289     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
290     int id = 0;
291     for (int i = 0; i < nFaces; i++)
292     {
293       int nodesInFace = ptIds[id];
294       id += (nodesInFace + 1);
295       if (i == face_ind - 1)
296       {
297         nbNodes = nodesInFace;
298         break;
299       }
300     }
301   }
302   return nbNodes;
303 }
304
305 /*! polyhedron only,
306  *  1 <= face_ind <= NbFaces()
307  *  1 <= node_ind <= NbFaceNodes()
308  */
309 const SMDS_MeshNode* SMDS_VtkVolume::GetFaceNode(const int face_ind, const int node_ind) const
310 {
311   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
312   vtkUnstructuredGrid* grid = mesh->getGrid();
313   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
314   const SMDS_MeshNode* node = 0;
315   if (aVtkType == VTK_POLYHEDRON)
316   {
317     vtkIdType nFaces = 0;
318     vtkIdType* ptIds = 0;
319     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
320     int id = 0;
321     for (int i = 0; i < nFaces; i++)
322     {
323       int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
324       if (i == face_ind - 1) // first face is number 1
325       {
326         if ((node_ind > 0) && (node_ind <= nodesInFace))
327           node = mesh->FindNodeVtk(ptIds[id + node_ind]); // ptIds[id+1] : first node
328         break;
329       }
330       id += (nodesInFace + 1);
331     }
332   }
333   return node;
334 }
335
336 /*! polyhedron only,
337  *  return number of nodes for each face
338  */
339 std::vector<int> SMDS_VtkVolume::GetQuantities() const
340 {
341   std::vector<int> quantities;
342   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
343   vtkUnstructuredGrid* grid = mesh->getGrid();
344   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
345   if (aVtkType == VTK_POLYHEDRON)
346   {
347     vtkIdType nFaces = 0;
348     vtkIdType* ptIds = 0;
349     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
350     int id = 0;
351     for (int i = 0; i < nFaces; i++)
352     {
353       int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
354       quantities.push_back(nodesInFace);
355       id += (nodesInFace + 1);
356     }
357   }
358   return quantities;
359 }
360
361 SMDS_ElemIteratorPtr SMDS_VtkVolume::elementsIterator(SMDSAbs_ElementType type) const
362 {
363   switch (type)
364   {
365     case SMDSAbs_Node:
366       {
367         SMDSAbs_EntityType aType = this->GetEntityType();
368         if (aType == SMDSEntity_Polyhedra)
369           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorPolyH(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
370         else
371           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
372       }
373     default:
374       MESSAGE("ERROR : Iterator not implemented");
375       return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
376   }
377 }
378
379 SMDS_NodeIteratorPtr SMDS_VtkVolume::nodesIteratorToUNV() const
380 {
381   return SMDS_NodeIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
382 }
383
384 SMDS_NodeIteratorPtr SMDS_VtkVolume::interlacedNodesIterator() const
385 {
386   return SMDS_NodeIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
387 }
388
389 SMDSAbs_ElementType SMDS_VtkVolume::GetType() const
390 {
391   return SMDSAbs_Volume;
392 }
393
394 /*!
395  * \brief Return node by its index
396  * \param ind - node index
397  * \retval const SMDS_MeshNode* - the node
398  */
399 const SMDS_MeshNode* SMDS_VtkVolume::GetNode(const int ind) const
400 {
401   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
402   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
403   if ( aVtkType == VTK_POLYHEDRON)
404   {
405     vtkIdType nFaces = 0;
406     vtkIdType* ptIds = 0;
407     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
408     int id = 0, nbPoints = 0;
409     for (int i = 0; i < nFaces; i++)
410     {
411       int nodesInFace = ptIds[id];
412       if ( ind < nbPoints + nodesInFace )
413         return SMDS_Mesh::_meshList[myMeshId]->FindNodeVtk( ptIds[ ind + i ]);
414       nbPoints += nodesInFace;
415       id += (nodesInFace + 1);
416     }
417     return 0;
418   }
419   vtkIdType npts, *pts;
420   grid->GetCellPoints( this->myVtkID, npts, pts );
421   const std::vector<int>& interlace = SMDS_MeshCell::fromVtkOrder( VTKCellType( aVtkType ));
422   return SMDS_Mesh::_meshList[myMeshId]->FindNodeVtk( pts[ interlace.empty() ? ind : interlace[ind]] );
423 }
424 /*!
425  * \brief Check if a node belongs to the element
426  * \param node - the node to check
427  * \retval int - node index within the element, -1 if not found
428  */
429 int SMDS_VtkVolume::GetNodeIndex( const SMDS_MeshNode* node ) const
430 {
431   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
432   const  vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
433   if ( aVtkType == VTK_POLYHEDRON)
434   {
435     vtkIdType nFaces = 0;
436     vtkIdType* ptIds = 0;
437     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
438     int id = 0;
439     for (int iF = 0; iF < nFaces; iF++)
440     {
441       int nodesInFace = ptIds[id];
442       for ( vtkIdType i = 0; i < nodesInFace; ++i )
443         if ( ptIds[id+i+1] == node->getVtkId() )
444           return id+i-iF;
445       id += (nodesInFace + 1);
446     }
447     return -1;
448   }
449   vtkIdType npts, *pts;
450   grid->GetCellPoints( this->myVtkID, npts, pts );
451   for ( vtkIdType i = 0; i < npts; ++i )
452     if ( pts[i] == node->getVtkId() )
453     {
454       const std::vector<int>& interlace = SMDS_MeshCell::toVtkOrder( VTKCellType( aVtkType ));
455       return interlace.empty() ? i : interlace[i];
456     }
457   return -1;
458 }
459
460 bool SMDS_VtkVolume::IsQuadratic() const
461 {
462   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
463   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
464   // TODO quadratic polyhedrons ?
465   switch (aVtkType)
466   {
467     case VTK_QUADRATIC_TETRA:
468     case VTK_QUADRATIC_PYRAMID:
469     case VTK_QUADRATIC_WEDGE:
470     case VTK_QUADRATIC_HEXAHEDRON:
471     case VTK_TRIQUADRATIC_HEXAHEDRON:
472       return true;
473       break;
474     default:
475       return false;
476   }
477 }
478
479 bool SMDS_VtkVolume::IsPoly() const
480 {
481   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
482   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
483   return (aVtkType == VTK_POLYHEDRON);
484 }
485
486 bool SMDS_VtkVolume::IsMediumNode(const SMDS_MeshNode* node) const
487 {
488   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
489   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
490   int rankFirstMedium = 0;
491   switch (aVtkType)
492   {
493     case VTK_QUADRATIC_TETRA:
494       rankFirstMedium = 4; // medium nodes are of rank 4 to 9
495       break;
496     case VTK_QUADRATIC_PYRAMID:
497       rankFirstMedium = 5; // medium nodes are of rank 5 to 12
498       break;
499     case VTK_QUADRATIC_WEDGE:
500       rankFirstMedium = 6; // medium nodes are of rank 6 to 14
501       break;
502     case VTK_QUADRATIC_HEXAHEDRON:
503     case VTK_TRIQUADRATIC_HEXAHEDRON:
504       rankFirstMedium = 8; // medium nodes are of rank 8 to 19
505       break;
506     default:
507       return false;
508   }
509   vtkIdType npts = 0;
510   vtkIdType* pts = 0;
511   grid->GetCellPoints(myVtkID, npts, pts);
512   vtkIdType nodeId = node->getVtkId();
513   for (int rank = 0; rank < npts; rank++)
514   {
515     if (pts[rank] == nodeId)
516     {
517       if (rank < rankFirstMedium)
518         return false;
519       else
520         return true;
521     }
522   }
523   MESSAGE("======================================================");
524   MESSAGE("= IsMediumNode: node does not belong to this element =");
525   MESSAGE("======================================================");
526   return false;
527 }
528
529 int SMDS_VtkVolume::NbCornerNodes() const
530 {
531   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
532   vtkIdType aVtkType = grid->GetCellType(myVtkID);
533   switch (aVtkType)
534   {
535   case VTK_QUADRATIC_TETRA:         return 4;
536   case VTK_QUADRATIC_PYRAMID:       return 5;
537   case VTK_QUADRATIC_WEDGE:         return 6;
538   case VTK_QUADRATIC_HEXAHEDRON:
539   case VTK_TRIQUADRATIC_HEXAHEDRON: return 8;
540   default:;
541   }
542   return NbNodes();
543 }
544
545 SMDSAbs_EntityType SMDS_VtkVolume::GetEntityType() const
546 {
547   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
548   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
549
550   SMDSAbs_EntityType aType = SMDSEntity_Tetra;
551   switch (aVtkType)
552   {
553     case VTK_TETRA:
554       aType = SMDSEntity_Tetra;
555       break;
556     case VTK_PYRAMID:
557       aType = SMDSEntity_Pyramid;
558       break;
559     case VTK_WEDGE:
560       aType = SMDSEntity_Penta;
561       break;
562     case VTK_HEXAHEDRON:
563       aType = SMDSEntity_Hexa;
564       break;
565     case VTK_QUADRATIC_TETRA:
566       aType = SMDSEntity_Quad_Tetra;
567       break;
568     case VTK_QUADRATIC_PYRAMID:
569       aType = SMDSEntity_Quad_Pyramid;
570       break;
571     case VTK_QUADRATIC_WEDGE:
572       aType = SMDSEntity_Quad_Penta;
573       break;
574     case VTK_QUADRATIC_HEXAHEDRON:
575       aType = SMDSEntity_Quad_Hexa;
576       break;
577     case VTK_TRIQUADRATIC_HEXAHEDRON:
578       aType = SMDSEntity_TriQuad_Hexa;
579       break;
580     case VTK_HEXAGONAL_PRISM:
581       aType = SMDSEntity_Hexagonal_Prism;
582       break;
583     case VTK_POLYHEDRON:
584       aType = SMDSEntity_Polyhedra;
585       break;
586     default:
587       aType = SMDSEntity_Polyhedra;
588       break;
589   }
590   return aType;
591 }
592
593 SMDSAbs_GeometryType SMDS_VtkVolume::GetGeomType() const
594 {
595   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
596   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
597
598   SMDSAbs_GeometryType aType = SMDSGeom_NONE;
599   switch (aVtkType)
600   {
601     case VTK_TETRA:
602     case VTK_QUADRATIC_TETRA:
603       aType = SMDSGeom_TETRA;
604       break;
605     case VTK_PYRAMID:
606     case VTK_QUADRATIC_PYRAMID:
607       aType = SMDSGeom_PYRAMID;
608       break;
609     case VTK_WEDGE:
610     case VTK_QUADRATIC_WEDGE:
611       aType = SMDSGeom_PENTA;
612       break;
613     case VTK_HEXAHEDRON:
614     case VTK_QUADRATIC_HEXAHEDRON:
615     case VTK_TRIQUADRATIC_HEXAHEDRON:
616       aType = SMDSGeom_HEXA;
617       break;
618     case VTK_HEXAGONAL_PRISM:
619       aType = SMDSGeom_HEXAGONAL_PRISM;
620       break;
621     case VTK_POLYHEDRON:
622       aType = SMDSGeom_POLYHEDRA;
623       break;
624     default:
625       aType = SMDSGeom_POLYHEDRA;
626       break;
627   }
628   return aType;
629 }
630
631 vtkIdType SMDS_VtkVolume::GetVtkType() const
632 {
633   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
634   vtkIdType aType = grid->GetCellType(myVtkID);
635   return aType;
636 }
637
638 void SMDS_VtkVolume::gravityCenter(SMDS_UnstructuredGrid* grid,
639                                    const vtkIdType *      nodeIds,
640                                    int                    nbNodes,
641                                    double*                result)
642 {
643   for (int j = 0; j < 3; j++)
644     result[j] = 0;
645   if (nbNodes <= 0)
646     return;
647   for (int i = 0; i < nbNodes; i++)
648     {
649       double *coords = grid->GetPoint(nodeIds[i]);
650       for (int j = 0; j < 3; j++)
651         result[j] += coords[j];
652     }
653   for (int j = 0; j < 3; j++)
654     result[j] = result[j] / nbNodes;
655   return;
656 }
657
658 bool SMDS_VtkVolume::isForward(double* a, double* b, double* c, double* d)
659 {
660   double u[3], v[3], w[3];
661   for (int j = 0; j < 3; j++)
662   {
663     u[j] = b[j] - a[j];
664     v[j] = c[j] - a[j];
665     w[j] = d[j] - a[j];
666   }
667   double prodmixte = ((u[1]*v[2] - u[2]*v[1]) * w[0]
668                       + (u[2]*v[0] - u[0]*v[2]) * w[1]
669                       + (u[0]*v[1] - u[1]*v[0]) * w[2] );
670   return (prodmixte < 0);
671 }
672
673 /*! For polyhedron only
674  *  @return actual number of nodes (not the sum of nodes of all faces)
675  */
676 int SMDS_VtkVolume::NbUniqueNodes() const
677 {
678   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
679   return grid->GetCell(myVtkID)->GetNumberOfPoints();
680 }
681
682 /*! For polyhedron use only
683  *  @return iterator on actual nodes (not through the faces)
684  */
685 SMDS_ElemIteratorPtr SMDS_VtkVolume::uniqueNodesIterator() const
686 {
687   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
688 }