Salome HOME
23514: EDF 16031 - SMESH freezes
[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     case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
174       nbFaces = 5;
175       break;
176     case VTK_HEXAHEDRON:
177     case VTK_QUADRATIC_HEXAHEDRON:
178     case VTK_TRIQUADRATIC_HEXAHEDRON:
179       nbFaces = 6;
180       break;
181     case VTK_POLYHEDRON:
182       {
183         vtkIdType nFaces = 0;
184         vtkIdType* ptIds = 0;
185         grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
186         nbFaces = nFaces;
187         break;
188       }
189     case VTK_HEXAGONAL_PRISM:
190       nbFaces = 8;
191       break;
192     default:
193       MESSAGE("invalid volume type")
194       ;
195       nbFaces = 0;
196       break;
197   }
198   return nbFaces;
199 }
200
201 int SMDS_VtkVolume::NbNodes() const
202 {
203   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
204   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
205   vtkIdType nbPoints = 0;
206   if (aVtkType != VTK_POLYHEDRON)
207   {
208     vtkIdType *pts;
209     grid->GetCellPoints( myVtkID, nbPoints, pts );
210   }
211   else
212   {
213     vtkIdType nFaces = 0;
214     vtkIdType* ptIds = 0;
215     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
216     int id = 0;
217     for (int i = 0; i < nFaces; i++)
218     {
219       int nodesInFace = ptIds[id];
220       nbPoints += nodesInFace;
221       id += (nodesInFace + 1);
222     }
223   }
224   return nbPoints;
225 }
226
227 int SMDS_VtkVolume::NbEdges() const
228 {
229   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
230   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
231   int nbEdges = 6;
232   switch (aVtkType)
233   {
234     case VTK_TETRA:
235     case VTK_QUADRATIC_TETRA:
236       nbEdges = 6;
237       break;
238     case VTK_PYRAMID:
239     case VTK_QUADRATIC_PYRAMID:
240       nbEdges = 8;
241       break;
242     case VTK_WEDGE:
243     case VTK_QUADRATIC_WEDGE:
244     case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
245       nbEdges = 9;
246       break;
247     case VTK_HEXAHEDRON:
248     case VTK_QUADRATIC_HEXAHEDRON:
249     case VTK_TRIQUADRATIC_HEXAHEDRON:
250       nbEdges = 12;
251       break;
252     case VTK_POLYHEDRON:
253       {
254         vtkIdType nFaces = 0;
255         vtkIdType* ptIds = 0;
256         grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
257         nbEdges = 0;
258         int id = 0;
259         for (int i = 0; i < nFaces; i++)
260           {
261             int edgesInFace = ptIds[id];
262             id += (edgesInFace + 1);
263             nbEdges += edgesInFace;
264           }
265         nbEdges = nbEdges / 2;
266         break;
267       }
268     case VTK_HEXAGONAL_PRISM:
269       nbEdges = 18;
270       break;
271     default:
272       MESSAGE("invalid volume type")
273       ;
274       nbEdges = 0;
275       break;
276   }
277   return nbEdges;
278 }
279
280 /*! polyhedron only,
281  *  1 <= face_ind <= NbFaces()
282  */
283 int SMDS_VtkVolume::NbFaceNodes(const int face_ind) const
284 {
285   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
286   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
287   int nbNodes = 0;
288   if (aVtkType == VTK_POLYHEDRON)
289   {
290     vtkIdType nFaces = 0;
291     vtkIdType* ptIds = 0;
292     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
293     int id = 0;
294     for (int i = 0; i < nFaces; i++)
295     {
296       int nodesInFace = ptIds[id];
297       id += (nodesInFace + 1);
298       if (i == face_ind - 1)
299       {
300         nbNodes = nodesInFace;
301         break;
302       }
303     }
304   }
305   return nbNodes;
306 }
307
308 /*! polyhedron only,
309  *  1 <= face_ind <= NbFaces()
310  *  1 <= node_ind <= NbFaceNodes()
311  */
312 const SMDS_MeshNode* SMDS_VtkVolume::GetFaceNode(const int face_ind, const int node_ind) const
313 {
314   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
315   vtkUnstructuredGrid* grid = mesh->getGrid();
316   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
317   const SMDS_MeshNode* node = 0;
318   if (aVtkType == VTK_POLYHEDRON)
319   {
320     vtkIdType nFaces = 0;
321     vtkIdType* ptIds = 0;
322     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
323     int id = 0;
324     for (int i = 0; i < nFaces; i++)
325     {
326       int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
327       if (i == face_ind - 1) // first face is number 1
328       {
329         if ((node_ind > 0) && (node_ind <= nodesInFace))
330           node = mesh->FindNodeVtk(ptIds[id + node_ind]); // ptIds[id+1] : first node
331         break;
332       }
333       id += (nodesInFace + 1);
334     }
335   }
336   return node;
337 }
338
339 /*! polyhedron only,
340  *  return number of nodes for each face
341  */
342 std::vector<int> SMDS_VtkVolume::GetQuantities() const
343 {
344   std::vector<int> quantities;
345   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
346   vtkUnstructuredGrid* grid = mesh->getGrid();
347   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
348   if (aVtkType == VTK_POLYHEDRON)
349   {
350     vtkIdType nFaces = 0;
351     vtkIdType* ptIds = 0;
352     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
353     int id = 0;
354     for (int i = 0; i < nFaces; i++)
355     {
356       int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
357       quantities.push_back(nodesInFace);
358       id += (nodesInFace + 1);
359     }
360   }
361   return quantities;
362 }
363
364 SMDS_ElemIteratorPtr SMDS_VtkVolume::elementsIterator(SMDSAbs_ElementType type) const
365 {
366   switch (type)
367   {
368     case SMDSAbs_Node:
369       {
370         SMDSAbs_EntityType aType = this->GetEntityType();
371         if (aType == SMDSEntity_Polyhedra)
372           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorPolyH(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
373         else
374           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
375       }
376     default:
377       MESSAGE("ERROR : Iterator not implemented");
378       return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
379   }
380 }
381
382 SMDS_NodeIteratorPtr SMDS_VtkVolume::nodesIteratorToUNV() const
383 {
384   return SMDS_NodeIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
385 }
386
387 SMDS_NodeIteratorPtr SMDS_VtkVolume::interlacedNodesIterator() const
388 {
389   return SMDS_NodeIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
390 }
391
392 SMDSAbs_ElementType SMDS_VtkVolume::GetType() const
393 {
394   return SMDSAbs_Volume;
395 }
396
397 /*!
398  * \brief Return node by its index
399  * \param ind - node index
400  * \retval const SMDS_MeshNode* - the node
401  */
402 const SMDS_MeshNode* SMDS_VtkVolume::GetNode(const int ind) const
403 {
404   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
405   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
406   if ( aVtkType == VTK_POLYHEDRON)
407   {
408     vtkIdType nFaces = 0;
409     vtkIdType* ptIds = 0;
410     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
411     int id = 0, nbPoints = 0;
412     for (int i = 0; i < nFaces; i++)
413     {
414       int nodesInFace = ptIds[id];
415       if ( ind < nbPoints + nodesInFace )
416         return SMDS_Mesh::_meshList[myMeshId]->FindNodeVtk( ptIds[ ind + i ]);
417       nbPoints += nodesInFace;
418       id += (nodesInFace + 1);
419     }
420     return 0;
421   }
422   vtkIdType npts, *pts;
423   grid->GetCellPoints( this->myVtkID, npts, pts );
424   const std::vector<int>& interlace = SMDS_MeshCell::fromVtkOrder( VTKCellType( aVtkType ));
425   return SMDS_Mesh::_meshList[myMeshId]->FindNodeVtk( pts[ interlace.empty() ? ind : interlace[ind]] );
426 }
427 /*!
428  * \brief Check if a node belongs to the element
429  * \param node - the node to check
430  * \retval int - node index within the element, -1 if not found
431  */
432 int SMDS_VtkVolume::GetNodeIndex( const SMDS_MeshNode* node ) const
433 {
434   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
435   const  vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
436   if ( aVtkType == VTK_POLYHEDRON)
437   {
438     vtkIdType nFaces = 0;
439     vtkIdType* ptIds = 0;
440     grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
441     int id = 0;
442     for (int iF = 0; iF < nFaces; iF++)
443     {
444       int nodesInFace = ptIds[id];
445       for ( vtkIdType i = 0; i < nodesInFace; ++i )
446         if ( ptIds[id+i+1] == node->getVtkId() )
447           return id+i-iF;
448       id += (nodesInFace + 1);
449     }
450     return -1;
451   }
452   vtkIdType npts, *pts;
453   grid->GetCellPoints( this->myVtkID, npts, pts );
454   for ( vtkIdType i = 0; i < npts; ++i )
455     if ( pts[i] == node->getVtkId() )
456     {
457       const std::vector<int>& interlace = SMDS_MeshCell::toVtkOrder( VTKCellType( aVtkType ));
458       return interlace.empty() ? i : interlace[i];
459     }
460   return -1;
461 }
462
463 bool SMDS_VtkVolume::IsQuadratic() const
464 {
465   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
466   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
467   // TODO quadratic polyhedrons ?
468   switch (aVtkType)
469   {
470     case VTK_QUADRATIC_TETRA:
471     case VTK_QUADRATIC_PYRAMID:
472     case VTK_QUADRATIC_WEDGE:
473     case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
474     case VTK_QUADRATIC_HEXAHEDRON:
475     case VTK_TRIQUADRATIC_HEXAHEDRON:
476       return true;
477       break;
478     default:
479       return false;
480   }
481 }
482
483 bool SMDS_VtkVolume::IsPoly() const
484 {
485   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
486   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
487   return (aVtkType == VTK_POLYHEDRON);
488 }
489
490 bool SMDS_VtkVolume::IsMediumNode(const SMDS_MeshNode* node) const
491 {
492   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
493   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
494   int rankFirstMedium = 0;
495   switch (aVtkType)
496   {
497     case VTK_QUADRATIC_TETRA:
498       rankFirstMedium = 4; // medium nodes are of rank 4 to 9
499       break;
500     case VTK_QUADRATIC_PYRAMID:
501       rankFirstMedium = 5; // medium nodes are of rank 5 to 12
502       break;
503     case VTK_QUADRATIC_WEDGE:
504     case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
505       rankFirstMedium = 6; // medium nodes are of rank 6 to 14
506       break;
507     case VTK_QUADRATIC_HEXAHEDRON:
508     case VTK_TRIQUADRATIC_HEXAHEDRON:
509       rankFirstMedium = 8; // medium nodes are of rank 8 to 19
510       break;
511     default:
512       return false;
513   }
514   vtkIdType npts = 0;
515   vtkIdType* pts = 0;
516   grid->GetCellPoints(myVtkID, npts, pts);
517   vtkIdType nodeId = node->getVtkId();
518   for (int rank = 0; rank < npts; rank++)
519   {
520     if (pts[rank] == nodeId)
521     {
522       if (rank < rankFirstMedium)
523         return false;
524       else
525         return true;
526     }
527   }
528   MESSAGE("======================================================");
529   MESSAGE("= IsMediumNode: node does not belong to this element =");
530   MESSAGE("======================================================");
531   return false;
532 }
533
534 int SMDS_VtkVolume::NbCornerNodes() const
535 {
536   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
537   vtkIdType aVtkType = grid->GetCellType(myVtkID);
538   switch (aVtkType)
539   {
540   case VTK_QUADRATIC_TETRA:             return 4;
541   case VTK_QUADRATIC_PYRAMID:           return 5;
542   case VTK_QUADRATIC_WEDGE:
543   case VTK_BIQUADRATIC_QUADRATIC_WEDGE: return 6;
544   case VTK_QUADRATIC_HEXAHEDRON:
545   case VTK_TRIQUADRATIC_HEXAHEDRON:     return 8;
546   default:;
547   }
548   return NbNodes();
549 }
550
551 SMDSAbs_EntityType SMDS_VtkVolume::GetEntityType() const
552 {
553   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
554   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
555
556   SMDSAbs_EntityType aType = SMDSEntity_Tetra;
557   switch (aVtkType)
558   {
559     case VTK_TETRA:
560       aType = SMDSEntity_Tetra;
561       break;
562     case VTK_PYRAMID:
563       aType = SMDSEntity_Pyramid;
564       break;
565     case VTK_WEDGE:
566       aType = SMDSEntity_Penta;
567       break;
568     case VTK_HEXAHEDRON:
569       aType = SMDSEntity_Hexa;
570       break;
571     case VTK_QUADRATIC_TETRA:
572       aType = SMDSEntity_Quad_Tetra;
573       break;
574     case VTK_QUADRATIC_PYRAMID:
575       aType = SMDSEntity_Quad_Pyramid;
576       break;
577     case VTK_QUADRATIC_WEDGE:
578       aType = SMDSEntity_Quad_Penta;
579       break;
580     case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
581       aType = SMDSEntity_BiQuad_Penta;
582       break;
583     case VTK_QUADRATIC_HEXAHEDRON:
584       aType = SMDSEntity_Quad_Hexa;
585       break;
586     case VTK_TRIQUADRATIC_HEXAHEDRON:
587       aType = SMDSEntity_TriQuad_Hexa;
588       break;
589     case VTK_HEXAGONAL_PRISM:
590       aType = SMDSEntity_Hexagonal_Prism;
591       break;
592     case VTK_POLYHEDRON:
593       aType = SMDSEntity_Polyhedra;
594       break;
595     default:
596       aType = SMDSEntity_Polyhedra;
597       break;
598   }
599   return aType;
600 }
601
602 SMDSAbs_GeometryType SMDS_VtkVolume::GetGeomType() const
603 {
604   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
605   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
606
607   SMDSAbs_GeometryType aType = SMDSGeom_NONE;
608   switch (aVtkType)
609   {
610     case VTK_TETRA:
611     case VTK_QUADRATIC_TETRA:
612       aType = SMDSGeom_TETRA;
613       break;
614     case VTK_PYRAMID:
615     case VTK_QUADRATIC_PYRAMID:
616       aType = SMDSGeom_PYRAMID;
617       break;
618     case VTK_WEDGE:
619     case VTK_QUADRATIC_WEDGE:
620     case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
621       aType = SMDSGeom_PENTA;
622       break;
623     case VTK_HEXAHEDRON:
624     case VTK_QUADRATIC_HEXAHEDRON:
625     case VTK_TRIQUADRATIC_HEXAHEDRON:
626       aType = SMDSGeom_HEXA;
627       break;
628     case VTK_HEXAGONAL_PRISM:
629       aType = SMDSGeom_HEXAGONAL_PRISM;
630       break;
631     case VTK_POLYHEDRON:
632       aType = SMDSGeom_POLYHEDRA;
633       break;
634     default:
635       aType = SMDSGeom_POLYHEDRA;
636       break;
637   }
638   return aType;
639 }
640
641 vtkIdType SMDS_VtkVolume::GetVtkType() const
642 {
643   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
644   vtkIdType aType = grid->GetCellType(myVtkID);
645   return aType;
646 }
647
648 void SMDS_VtkVolume::gravityCenter(SMDS_UnstructuredGrid* grid,
649                                    const vtkIdType *      nodeIds,
650                                    int                    nbNodes,
651                                    double*                result)
652 {
653   for (int j = 0; j < 3; j++)
654     result[j] = 0;
655   if (nbNodes <= 0)
656     return;
657   for (int i = 0; i < nbNodes; i++)
658     {
659       double *coords = grid->GetPoint(nodeIds[i]);
660       for (int j = 0; j < 3; j++)
661         result[j] += coords[j];
662     }
663   for (int j = 0; j < 3; j++)
664     result[j] = result[j] / nbNodes;
665   return;
666 }
667
668 bool SMDS_VtkVolume::isForward(double* a, double* b, double* c, double* d)
669 {
670   double u[3], v[3], w[3];
671   for (int j = 0; j < 3; j++)
672   {
673     u[j] = b[j] - a[j];
674     v[j] = c[j] - a[j];
675     w[j] = d[j] - a[j];
676   }
677   double prodmixte = ((u[1]*v[2] - u[2]*v[1]) * w[0]
678                       + (u[2]*v[0] - u[0]*v[2]) * w[1]
679                       + (u[0]*v[1] - u[1]*v[0]) * w[2] );
680   return (prodmixte < 0);
681 }
682
683 /*! For polyhedron only
684  *  @return actual number of nodes (not the sum of nodes of all faces)
685  */
686 int SMDS_VtkVolume::NbUniqueNodes() const
687 {
688   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
689   return grid->GetCell(myVtkID)->GetNumberOfPoints();
690 }
691
692 /*! For polyhedron use only
693  *  @return iterator on actual nodes (not through the faces)
694  */
695 SMDS_ElemIteratorPtr SMDS_VtkVolume::uniqueNodesIterator() const
696 {
697   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
698 }