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