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