]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMDS/SMDS_VtkVolume.cxx
Salome HOME
PR: correct some warnings
[modules/smesh.git] / src / SMDS / SMDS_VtkVolume.cxx
1 #include "SMDS_VtkVolume.hxx"
2 #include "SMDS_MeshNode.hxx"
3 #include "SMDS_Mesh.hxx"
4 #include "SMDS_VtkCellIterator.hxx"
5
6 #include "utilities.h"
7
8 #include <vector>
9
10 SMDS_VtkVolume::SMDS_VtkVolume()
11 {
12 }
13
14 SMDS_VtkVolume::SMDS_VtkVolume(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
15 {
16   init(nodeIds, mesh);
17 }
18 /*!
19  * typed used are vtk types (@see vtkCellType.h)
20  * see GetEntityType() for conversion in SMDS type (@see SMDSAbs_ElementType.hxx)
21  */
22 void SMDS_VtkVolume::init(std::vector<vtkIdType> nodeIds, SMDS_Mesh* mesh)
23 {
24   vtkUnstructuredGrid* grid = mesh->getGrid();
25   myIdInShape = -1;
26   myMeshId = mesh->getMeshId();
27   vtkIdType aType = VTK_TETRA;
28   switch (nodeIds.size())
29   {
30     case 4:
31       aType = VTK_TETRA;
32       break;
33     case 5:
34       aType = VTK_PYRAMID;
35       break;
36     case 6:
37       aType = VTK_WEDGE;
38       break;
39     case 8:
40       aType = VTK_HEXAHEDRON;
41       break;
42     case 10:
43       aType = VTK_QUADRATIC_TETRA;
44       break;
45     case 13:
46       aType = VTK_QUADRATIC_PYRAMID;
47       break;
48     case 15:
49       aType = VTK_QUADRATIC_WEDGE;
50       break;
51     case 20:
52       aType = VTK_QUADRATIC_HEXAHEDRON;
53       break;
54     default:
55       aType = VTK_HEXAHEDRON;
56       break;
57   }
58   myVtkID = grid->InsertNextLinkedCell(aType, nodeIds.size(), &nodeIds[0]);
59   mesh->setMyModified();
60   //MESSAGE("SMDS_VtkVolume::init myVtkID " << myVtkID);
61 }
62
63 //#ifdef VTK_HAVE_POLYHEDRON
64 void SMDS_VtkVolume::initPoly(std::vector<vtkIdType> nodeIds, std::vector<int> nbNodesPerFace, SMDS_Mesh* mesh)
65 {
66   MESSAGE("SMDS_VtkVolume::initPoly");
67   SMDS_UnstructuredGrid* grid = mesh->getGrid();
68   // TODO is it useful to orient faces ?
69   double center[3];
70   this->gravityCenter(grid, &nodeIds[0], nodeIds.size(), &center[0]);
71   vector<vtkIdType> ptIds;
72   ptIds.clear();
73   vtkIdType nbFaces = nbNodesPerFace.size();
74   int k = 0;
75   for (int i = 0; i < nbFaces; i++)
76     {
77       int nf = nbNodesPerFace[i];
78       ptIds.push_back(nf);
79 //      double a[3];
80 //      double b[3];
81 //      double c[3];
82 //      grid->GetPoints()->GetPoint(nodeIds[k], a);
83 //      grid->GetPoints()->GetPoint(nodeIds[k + 1], b);
84 //      grid->GetPoints()->GetPoint(nodeIds[k + 2], c);
85 //      bool isFaceForward = this->isForward(a, b, c, center);
86       bool isFaceForward = true;
87       //MESSAGE("isFaceForward " << i << " " << isFaceForward);
88       vtkIdType *facePts = &nodeIds[k];
89       if (isFaceForward)
90         for (int n = 0; n < nf; n++)
91           ptIds.push_back(facePts[n]);
92       else
93         for (int n = nf - 1; n >= 0; n--)
94           ptIds.push_back(facePts[n]);
95       k += nf;
96     }
97   myVtkID = grid->InsertNextLinkedCell(VTK_POLYHEDRON, nbFaces, &ptIds[0]);
98   mesh->setMyModified();
99 }
100 //#endif
101
102 bool SMDS_VtkVolume::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
103 {
104   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
105   vtkIdType npts = 0;
106   vtkIdType* pts = 0;
107   grid->GetCellPoints(myVtkID, npts, pts);
108   if (nbNodes != npts)
109     {
110       MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << nbNodes);
111       return false;
112     }
113   for (int i = 0; i < nbNodes; i++)
114     {
115       pts[i] = nodes[i]->getVtkId();
116     }
117   SMDS_Mesh::_meshList[myMeshId]->setMyModified();
118   return true;
119 }
120
121 /*!
122  * Reorder in VTK order a list of nodes given in SMDS order.
123  * To be used before ChangeNodes: lists are given or computed in SMDS order.
124  */
125 bool SMDS_VtkVolume::vtkOrder(const SMDS_MeshNode* nodes[], const int nbNodes)
126 {
127   if (nbNodes != this->NbNodes())
128     {
129       MESSAGE("vtkOrder, wrong number of nodes " << nbNodes << " instead of "<< this->NbNodes());
130       return false;
131     }
132   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
133   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
134   switch (aVtkType)
135   {
136     case VTK_TETRA:
137       this->exchange(nodes, 1, 2);
138       break;
139     case VTK_QUADRATIC_TETRA:
140       this->exchange(nodes, 1, 2);
141       this->exchange(nodes, 4, 6);
142       this->exchange(nodes, 8, 9);
143       break;
144     case VTK_PYRAMID:
145       this->exchange(nodes, 1, 3);
146       break;
147     case VTK_WEDGE:
148       break;
149     case VTK_QUADRATIC_PYRAMID:
150       this->exchange(nodes, 1, 3);
151       this->exchange(nodes, 5, 8);
152       this->exchange(nodes, 6, 7);
153       this->exchange(nodes, 10, 12);
154       break;
155     case VTK_QUADRATIC_WEDGE:
156       break;
157     case VTK_HEXAHEDRON:
158       this->exchange(nodes, 1, 3);
159       this->exchange(nodes, 5, 7);
160       break;
161     case VTK_QUADRATIC_HEXAHEDRON:
162       this->exchange(nodes, 1, 3);
163       this->exchange(nodes, 5, 7);
164       this->exchange(nodes, 8, 11);
165       this->exchange(nodes, 9, 10);
166       this->exchange(nodes, 12, 15);
167       this->exchange(nodes, 13, 14);
168       this->exchange(nodes, 17, 19);
169       break;
170     case VTK_POLYHEDRON:
171     default:
172       break;
173   }
174   return true;
175 }
176
177 SMDS_VtkVolume::~SMDS_VtkVolume()
178 {
179 }
180
181 void SMDS_VtkVolume::Print(ostream & OS) const
182 {
183   OS << "volume <" << GetID() << "> : ";
184 }
185
186 int SMDS_VtkVolume::NbFaces() const
187 {
188   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
189   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
190   int nbFaces = 4;
191   switch (aVtkType)
192   {
193     case VTK_TETRA:
194     case VTK_QUADRATIC_TETRA:
195       nbFaces = 4;
196       break;
197     case VTK_PYRAMID:
198     case VTK_WEDGE:
199     case VTK_QUADRATIC_PYRAMID:
200     case VTK_QUADRATIC_WEDGE:
201       nbFaces = 5;
202       break;
203     case VTK_HEXAHEDRON:
204     case VTK_QUADRATIC_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     default:
216       MESSAGE("invalid volume type")
217       ;
218       nbFaces = 0;
219       break;
220   }
221   return nbFaces;
222 }
223
224 int SMDS_VtkVolume::NbNodes() const
225 {
226   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
227   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
228   int nbPoints = 0;
229   if (aVtkType != VTK_POLYHEDRON)
230     {
231       nbPoints = grid->GetCell(myVtkID)->GetNumberOfPoints();
232     }
233   else
234     {
235       vtkIdType nFaces = 0;
236       vtkIdType* ptIds = 0;
237       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
238       int id = 0;
239       for (int i = 0; i < nFaces; i++)
240         {
241           int nodesInFace = ptIds[id];
242           nbPoints += nodesInFace;
243           id += (nodesInFace + 1);
244         }
245     }
246   return nbPoints;
247 }
248
249 int SMDS_VtkVolume::NbEdges() const
250 {
251   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
252   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
253   int nbEdges = 6;
254   switch (aVtkType)
255   {
256     case VTK_TETRA:
257     case VTK_QUADRATIC_TETRA:
258       nbEdges = 6;
259       break;
260     case VTK_PYRAMID:
261     case VTK_QUADRATIC_PYRAMID:
262       nbEdges = 8;
263       break;
264     case VTK_WEDGE:
265     case VTK_QUADRATIC_WEDGE:
266       nbEdges = 9;
267       break;
268     case VTK_HEXAHEDRON:
269     case VTK_QUADRATIC_HEXAHEDRON:
270       nbEdges = 12;
271       break;
272     case VTK_POLYHEDRON:
273       {
274         vtkIdType nFaces = 0;
275         vtkIdType* ptIds = 0;
276         grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
277         nbEdges = 0;
278         int id = 0;
279         for (int i = 0; i < nFaces; i++)
280           {
281             int edgesInFace = ptIds[id];
282             id += (edgesInFace + 1);
283             nbEdges += edgesInFace;
284           }
285         nbEdges = nbEdges / 2;
286         break;
287       }
288     default:
289       MESSAGE("invalid volume type")
290       ;
291       nbEdges = 0;
292       break;
293   }
294   return nbEdges;
295 }
296
297 /*! polyhedron only,
298  *  1 <= face_ind <= NbFaces()
299  */
300 int SMDS_VtkVolume::NbFaceNodes(const int face_ind) const
301 {
302   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
303   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
304   int nbNodes = 0;
305   if (aVtkType == VTK_POLYHEDRON)
306     {
307       vtkIdType nFaces = 0;
308       vtkIdType* ptIds = 0;
309       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
310       int id = 0;
311       for (int i = 0; i < nFaces; i++)
312         {
313           int nodesInFace = ptIds[id];
314           id += (nodesInFace + 1);
315           if (i == face_ind - 1)
316             {
317               nbNodes = nodesInFace;
318               break;
319             }
320         }
321     }
322   return nbNodes;
323 }
324
325 /*! polyhedron only,
326  *  1 <= face_ind <= NbFaces()
327  *  1 <= node_ind <= NbFaceNodes()
328  */
329 const SMDS_MeshNode* SMDS_VtkVolume::GetFaceNode(const int face_ind, const int node_ind) const
330 {
331   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
332   vtkUnstructuredGrid* grid = mesh->getGrid();
333   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
334   const SMDS_MeshNode* node = 0;
335   if (aVtkType == VTK_POLYHEDRON)
336     {
337       vtkIdType nFaces = 0;
338       vtkIdType* ptIds = 0;
339       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
340       int id = 0;
341       for (int i = 0; i < nFaces; i++)
342         {
343           int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
344           if (i == face_ind - 1) // first face is number 1
345             {
346               if ((node_ind > 0) && (node_ind <= nodesInFace))
347                 node = mesh->FindNodeVtk(ptIds[id + node_ind]); // ptIds[id+1] : first node
348               break;
349             }
350           id += (nodesInFace + 1);
351         }
352     }
353   return node;
354 }
355
356 /*! polyhedron only,
357  *  return number of nodes for each face
358  */
359 const std::vector<int> SMDS_VtkVolume::GetQuantities() const
360 {
361   vector<int> quantities;
362   quantities.clear();
363   SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myMeshId];
364   vtkUnstructuredGrid* grid = mesh->getGrid();
365   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
366   if (aVtkType == VTK_POLYHEDRON)
367     {
368       vtkIdType nFaces = 0;
369       vtkIdType* ptIds = 0;
370       grid->GetFaceStream(this->myVtkID, nFaces, ptIds);
371       int id = 0;
372       for (int i = 0; i < nFaces; i++)
373         {
374           int nodesInFace = ptIds[id]; // nodeIds in ptIds[id+1 .. id+nodesInFace]
375           quantities.push_back(nodesInFace);
376           id += (nodesInFace + 1);
377         }
378     }
379   return quantities;
380 }
381
382 SMDS_ElemIteratorPtr SMDS_VtkVolume::elementsIterator(SMDSAbs_ElementType type) const
383 {
384   switch (type)
385   {
386     case SMDSAbs_Node:
387       {
388         SMDSAbs_EntityType aType = this->GetEntityType();
389         if (aType == SMDSEntity_Polyhedra)
390           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorPolyH(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
391         else
392           return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, aType));
393       }
394     default:
395       MESSAGE("ERROR : Iterator not implemented");
396       return SMDS_ElemIteratorPtr((SMDS_ElemIterator*) NULL);
397   }
398 }
399
400 SMDS_ElemIteratorPtr SMDS_VtkVolume::nodesIteratorToUNV() const
401 {
402   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
403 }
404
405 SMDS_ElemIteratorPtr SMDS_VtkVolume::interlacedNodesElemIterator() const
406 {
407   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIteratorToUNV(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
408 }
409
410 SMDSAbs_ElementType SMDS_VtkVolume::GetType() const
411 {
412   return SMDSAbs_Volume;
413 }
414
415 /*!
416  * \brief Return node by its index
417  * \param ind - node index
418  * \retval const SMDS_MeshNode* - the node
419  */
420 const SMDS_MeshNode* SMDS_VtkVolume::GetNode(const int ind) const
421 {
422   // TODO optimize if possible (vtkCellIterator)
423   return SMDS_MeshElement::GetNode(ind);
424 }
425
426 bool SMDS_VtkVolume::IsQuadratic() const
427 {
428   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
429   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
430   // TODO quadratic polyhedrons ?
431   switch (aVtkType)
432   {
433     case VTK_QUADRATIC_TETRA:
434     case VTK_QUADRATIC_PYRAMID:
435     case VTK_QUADRATIC_WEDGE:
436     case VTK_QUADRATIC_HEXAHEDRON:
437       return true;
438       break;
439     default:
440       return false;
441   }
442 }
443
444 bool SMDS_VtkVolume::IsPoly() const
445 {
446   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
447   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
448   return (aVtkType == VTK_POLYHEDRON);
449 }
450
451 bool SMDS_VtkVolume::IsMediumNode(const SMDS_MeshNode* node) const
452 {
453   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
454   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
455   int rankFirstMedium = 0;
456   switch (aVtkType)
457   {
458     case VTK_QUADRATIC_TETRA:
459       rankFirstMedium = 4; // medium nodes are of rank 4 to 9
460       break;
461     case VTK_QUADRATIC_PYRAMID:
462       rankFirstMedium = 5; // medium nodes are of rank 5 to 12
463       break;
464     case VTK_QUADRATIC_WEDGE:
465       rankFirstMedium = 6; // medium nodes are of rank 6 to 14
466       break;
467     case VTK_QUADRATIC_HEXAHEDRON:
468       rankFirstMedium = 8; // medium nodes are of rank 8 to 19
469       break;
470     default:
471       return false;
472   }
473   vtkIdType npts = 0;
474   vtkIdType* pts = 0;
475   grid->GetCellPoints(myVtkID, npts, pts);
476   vtkIdType nodeId = node->getVtkId();
477   for (int rank = 0; rank < npts; rank++)
478     {
479       if (pts[rank] == nodeId)
480         {
481           if (rank < rankFirstMedium)
482             return false;
483           else
484             return true;
485         }
486     }
487   //throw SALOME_Exception(LOCALIZED("node does not belong to this element"));
488   MESSAGE("======================================================");
489   MESSAGE("= IsMediumNode: node does not belong to this element =");
490   MESSAGE("======================================================");
491   return false;
492 }
493
494 SMDSAbs_EntityType SMDS_VtkVolume::GetEntityType() const
495 {
496   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
497   vtkIdType aVtkType = grid->GetCellType(this->myVtkID);
498
499   SMDSAbs_EntityType aType = SMDSEntity_Tetra;
500   switch (aVtkType)
501   {
502     case VTK_TETRA:
503       aType = SMDSEntity_Tetra;
504       break;
505     case VTK_PYRAMID:
506       aType = SMDSEntity_Pyramid;
507       break;
508     case VTK_WEDGE:
509       aType = SMDSEntity_Penta;
510       break;
511     case VTK_HEXAHEDRON:
512       aType = SMDSEntity_Hexa;
513       break;
514     case VTK_QUADRATIC_TETRA:
515       aType = SMDSEntity_Quad_Tetra;
516       break;
517     case VTK_QUADRATIC_PYRAMID:
518       aType = SMDSEntity_Quad_Pyramid;
519       break;
520     case VTK_QUADRATIC_WEDGE:
521       aType = SMDSEntity_Quad_Penta;
522       break;
523     case VTK_QUADRATIC_HEXAHEDRON:
524       aType = SMDSEntity_Quad_Hexa;
525       break;
526 //#ifdef VTK_HAVE_POLYHEDRON
527     case VTK_POLYHEDRON:
528       aType = SMDSEntity_Polyhedra;
529       break;
530 //#endif
531     default:
532       aType = SMDSEntity_Polyhedra;
533       break;
534   }
535   return aType;
536 }
537
538 vtkIdType SMDS_VtkVolume::GetVtkType() const
539 {
540   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
541   vtkIdType aType = grid->GetCellType(myVtkID);
542   return aType;
543 }
544
545 void SMDS_VtkVolume::gravityCenter(SMDS_UnstructuredGrid* grid, vtkIdType *nodeIds, int nbNodes, double* result)
546 {
547   for (int j = 0; j < 3; j++)
548     result[j] = 0;
549   if (nbNodes <= 0)
550     return;
551   for (int i = 0; i < nbNodes; i++)
552     {
553       double *coords = grid->GetPoint(nodeIds[i]);
554       for (int j = 0; j < 3; j++)
555         result[j] += coords[j];
556     }
557   for (int j = 0; j < 3; j++)
558     result[j] = result[j] / nbNodes;
559   //MESSAGE("center " << result[0] << " " << result[1] << " "  << result[2]);
560   return;
561 }
562
563 bool SMDS_VtkVolume::isForward(double* a, double* b, double* c, double* d)
564 {
565   double u[3], v[3], w[3];
566   for (int j = 0; j < 3; j++)
567     {
568       //MESSAGE("a,b,c,d " << a[j] << " " << b[j] << " " << c[j] << " " << d[j]);
569       u[j] = b[j] - a[j];
570       v[j] = c[j] - a[j];
571       w[j] = d[j] - a[j];
572       //MESSAGE("u,v,w " << u[j] << " " << v[j] << " " << w[j]);
573     }
574   double prodmixte = (u[2] * v[3] - u[3] * v[2]) * w[1] + (u[3] * v[1] - u[1] * v[3]) * w[2] + (u[1] * v[2] - u[2]
575       * v[1]) * w[3];
576   return (prodmixte >= 0);
577 }
578
579 /*! For polyhedron only
580  *  @return actual number of nodes (not the sum of nodes of all faces)
581  */
582 int SMDS_VtkVolume::NbUniqueNodes() const
583 {
584   vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
585   return grid->GetCell(myVtkID)->GetNumberOfPoints();
586 }
587
588 /*! For polyhedron use only
589  *  @return iterator on actual nodes (not through the faces)
590  */
591 SMDS_ElemIteratorPtr SMDS_VtkVolume::uniqueNodesIterator() const
592 {
593   MESSAGE("uniqueNodesIterator");
594   return SMDS_ElemIteratorPtr(new SMDS_VtkCellIterator(SMDS_Mesh::_meshList[myMeshId], myVtkID, GetEntityType()));
595 }