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