Salome HOME
23514: EDF 16031 - SMESH freezes
[modules/smesh.git] / src / SMDS / SMDS_MeshCell.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_MeshCell.hxx"
21 #include "utilities.h"
22
23 int SMDS_MeshCell::nbCells = 0;
24
25 SMDS_MeshCell::SMDS_MeshCell() :
26   SMDS_MeshElement(-1)
27 {
28   nbCells++;
29   myVtkID = -1;
30 }
31
32 SMDS_MeshCell::~SMDS_MeshCell()
33 {
34   nbCells--;
35 }
36 //================================================================================
37 /*!
38  * \brief Return VTKCellType corresponding to SMDSAbs_EntityType
39  */
40 //================================================================================
41
42 VTKCellType SMDS_MeshCell::toVtkType (SMDSAbs_EntityType smdsType)
43 {
44   static std::vector< VTKCellType > vtkTypes;
45   if ( vtkTypes.empty() )
46   {
47     vtkTypes.resize( SMDSEntity_Last+1, VTK_EMPTY_CELL );
48     vtkTypes[ SMDSEntity_Node ]              = VTK_VERTEX;
49     vtkTypes[ SMDSEntity_0D ]                = VTK_VERTEX;
50     vtkTypes[ SMDSEntity_Edge ]              = VTK_LINE;
51     vtkTypes[ SMDSEntity_Quad_Edge ]         = VTK_QUADRATIC_EDGE;
52     vtkTypes[ SMDSEntity_Triangle ]          = VTK_TRIANGLE;
53     vtkTypes[ SMDSEntity_Quad_Triangle ]     = VTK_QUADRATIC_TRIANGLE;
54     vtkTypes[ SMDSEntity_BiQuad_Triangle ]   = VTK_BIQUADRATIC_TRIANGLE;
55     vtkTypes[ SMDSEntity_Quadrangle ]        = VTK_QUAD;
56     vtkTypes[ SMDSEntity_Quad_Quadrangle ]   = VTK_QUADRATIC_QUAD;
57     vtkTypes[ SMDSEntity_BiQuad_Quadrangle ] = VTK_BIQUADRATIC_QUAD;
58     vtkTypes[ SMDSEntity_Polygon ]           = VTK_POLYGON;
59     vtkTypes[ SMDSEntity_Quad_Polygon ]      = VTK_QUADRATIC_POLYGON;
60     vtkTypes[ SMDSEntity_Tetra ]             = VTK_TETRA;
61     vtkTypes[ SMDSEntity_Quad_Tetra ]        = VTK_QUADRATIC_TETRA;
62     vtkTypes[ SMDSEntity_Pyramid ]           = VTK_PYRAMID;
63     vtkTypes[ SMDSEntity_Quad_Pyramid ]      = VTK_QUADRATIC_PYRAMID;
64     vtkTypes[ SMDSEntity_Hexa ]              = VTK_HEXAHEDRON;
65     vtkTypes[ SMDSEntity_Quad_Hexa ]         = VTK_QUADRATIC_HEXAHEDRON;
66     vtkTypes[ SMDSEntity_TriQuad_Hexa ]      = VTK_TRIQUADRATIC_HEXAHEDRON;
67     vtkTypes[ SMDSEntity_Penta ]             = VTK_WEDGE;
68     vtkTypes[ SMDSEntity_Quad_Penta ]        = VTK_QUADRATIC_WEDGE;
69     vtkTypes[ SMDSEntity_BiQuad_Penta ]      = VTK_BIQUADRATIC_QUADRATIC_WEDGE;
70     vtkTypes[ SMDSEntity_Hexagonal_Prism ]   = VTK_HEXAGONAL_PRISM;
71     vtkTypes[ SMDSEntity_Polyhedra ]         = VTK_POLYHEDRON;
72     //vtkTypes[ SMDSEntity_Quad_Polyhedra ]    = ;
73     vtkTypes[ SMDSEntity_Ball ]              = VTK_POLY_VERTEX;
74   }
75   return vtkTypes[ smdsType ];
76 }
77
78 //================================================================================
79 /*!
80  * \brief Return indices to transform cell connectivity from SMDS to VTK
81  * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
82  */
83 //================================================================================
84
85 const std::vector< int >& SMDS_MeshCell::toVtkOrder(SMDSAbs_EntityType smdsType)
86 {
87   static std::vector< std::vector< int > > toVtkInterlaces;
88   if ( toVtkInterlaces.empty() )
89   {
90     toVtkInterlaces.resize( SMDSEntity_Last+1 );
91     // {
92     //   const int ids[] = {0};
93     //   toVtkInterlaces[SMDSEntity_0D].assign( &ids[0], &ids[0]+1 );
94     //   toVtkInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
95     // }
96     // {
97     //   const int ids[] = {0,1};
98     //   toVtkInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
99     // }
100     // {
101     //   const int ids[] = {0,1,2};
102     //   toVtkInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
103     // }
104     // {
105     //   const int ids[] = {0,1,2};
106     //   toVtkInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
107     // }
108     // {
109     //   const int ids[] = {0,1,2,3,4,5};
110     //   toVtkInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
111     // }
112     // {
113     //   const int ids[] = {0,1,2,3};
114     //   toVtkInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
115     // }
116     // {
117     //   const int ids[] = {0,1,2,3,4,5,6,7};
118     //   toVtkInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
119     // }
120     // {
121     //   const int ids[] = {0,1,2,3,4,5,6,7,8};
122     //   toVtkInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
123     // }
124     {
125       const int ids[] = {0,2,1,3};
126       toVtkInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
127     }
128     {
129       const int ids[] = {0,2,1,3,6,5,4,7,9,8};
130       toVtkInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
131     }
132     {
133       const int ids[] = {0,3,2,1,4};
134       toVtkInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
135     }
136     {
137       const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
138       toVtkInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
139     }
140     {
141       const int ids[] = {0,3,2,1,4,7,6,5};
142       toVtkInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
143     }
144     {
145       const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
146       toVtkInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
147     }
148     {
149       const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17, 21,23,24,22,20,25,26};
150       toVtkInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
151     }
152     {
153       const int ids[] = {0,1,2,3,4,5};
154       toVtkInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
155     }
156     {
157       const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}; // TODO: check
158       toVtkInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
159     }
160     {
161       const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};// TODO: check
162       toVtkInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
163     }
164     {
165       const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
166       toVtkInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
167     }
168   }
169   return toVtkInterlaces[smdsType];
170 }
171
172 //================================================================================
173 /*!
174  * \brief Return indices to reverse an SMDS cell of given type.
175  *        nbNodes is useful for polygons
176  * Usage: reverseIDs[i] = forwardIDs[ indices[ i ]]
177  */
178 //================================================================================
179
180 const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType,
181                                                         const size_t       nbNodes)
182 {
183   static std::vector< std::vector< int > > reverseInterlaces;
184   if ( reverseInterlaces.empty() )
185   {
186     reverseInterlaces.resize( SMDSEntity_Last+1 );
187     {
188       const int ids[] = {0};
189       reverseInterlaces[SMDSEntity_0D].assign( &ids[0], &ids[0]+1 );
190       reverseInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
191       reverseInterlaces[SMDSEntity_Ball].assign( &ids[0], &ids[0]+1 );
192     }
193     {
194       const int ids[] = {1,0};
195       reverseInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
196     }
197     {
198       const int ids[] = {1,0,2};
199       reverseInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
200     }
201     {
202       const int ids[] = {0,2,1};
203       reverseInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
204     }
205     {
206       const int ids[] = {0,2,1,5,4,3};
207       reverseInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
208     }
209     {
210       const int ids[] = {0,2,1,5,4,3,6};
211       reverseInterlaces[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
212     }
213     {
214       const int ids[] = {0,3,2,1};
215       reverseInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
216     }
217     {
218       const int ids[] = {0,3,2,1,7,6,5,4};
219       reverseInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
220     }
221     {
222       const int ids[] = {0,3,2,1,7,6,5,4,8};
223       reverseInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
224     }
225     {
226       const int ids[] = {0,2,1,3};
227       reverseInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
228     }
229     {
230       const int ids[] = {0,2,1,3,6,5,4,7,9,8};
231       reverseInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
232     }
233     {
234       const int ids[] = {0,3,2,1,4};
235       reverseInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
236     }
237     {
238       const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
239       reverseInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
240     }
241     {
242       const int ids[] = {0,3,2,1,4,7,6,5};
243       reverseInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
244     }
245     {
246       const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
247       reverseInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
248     }
249     {
250       const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17, 20,24,23,22,21,25,26};
251       reverseInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
252     }
253     {
254       const int ids[] = {0,2,1,3,5,4};
255       reverseInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
256     }
257     {
258       const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13};
259       reverseInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
260     }
261     {
262       const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13,15,16,17};
263       reverseInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
264     }
265    {
266       const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
267       reverseInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
268     }
269   }
270
271   if ( smdsType == SMDSEntity_Polygon )
272   {
273     if ( reverseInterlaces[ smdsType ].size() != nbNodes )
274     {
275       reverseInterlaces[ smdsType ].resize( nbNodes );
276       for ( size_t i = 0; i < nbNodes; ++i )
277         reverseInterlaces[ smdsType ][i] = nbNodes - i - 1;
278     }
279   }
280   else if ( smdsType == SMDSEntity_Quad_Polygon )
281   {
282     if ( reverseInterlaces[ smdsType ].size() != nbNodes )
283     {
284       // e.g. for 8 nodes: [ 0, 3,2,1, 7,6,5,4 ]
285       reverseInterlaces[ smdsType ].resize( nbNodes );
286       size_t pos = 0;
287       reverseInterlaces[ smdsType ][pos++] = 0;
288       for ( int i = nbNodes / 2 - 1; i > 0 ; --i ) // 3,2,1
289         reverseInterlaces[ smdsType ][pos++] = i;
290       for ( int i = nbNodes - 1, nb = nbNodes / 2; i >= nb; --i ) // 7,6,5,4
291         reverseInterlaces[ smdsType ][pos++] = i;
292     }
293   }
294   
295   return reverseInterlaces[smdsType];
296 }
297
298 //================================================================================
299 /*!
300  * \brief Return indices to set nodes of a quadratic 1D or 2D element in interlaced order
301  * Usage: interlacedIDs[i] = smdsIDs[ indices[ i ]]
302  */
303 //================================================================================
304
305 const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
306                                                            const size_t       nbNodes)
307 {
308   static std::vector< std::vector< int > > interlace;
309   if ( interlace.empty() )
310   {
311     interlace.resize( SMDSEntity_Last+1 );
312     {
313       const int ids[] = {0,2,1};
314       interlace[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
315     }
316     {
317       const int ids[] = {0,3,1,4,2,5,6};
318       interlace[SMDSEntity_Quad_Triangle  ].assign( &ids[0], &ids[0]+6 );
319       interlace[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
320     }
321     {
322       const int ids[] = {0,4,1,5,2,6,3,7,8};
323       interlace[SMDSEntity_Quad_Quadrangle  ].assign( &ids[0], &ids[0]+8 );
324       interlace[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
325     }
326   }
327
328   if ( smdsType == SMDSEntity_Quad_Polygon )
329   {
330     if ( interlace[smdsType].size() != nbNodes )
331     {
332       interlace[smdsType].resize( nbNodes );
333       for ( size_t i = 0; i < nbNodes / 2; ++i )
334       {
335         interlace[smdsType][i*2+0] = i;
336         interlace[smdsType][i*2+1] = i + nbNodes / 2;
337       }
338     }
339   }
340   return interlace[smdsType];
341 }
342
343 //================================================================================
344 /*!
345  * \brief Return SMDSAbs_EntityType corresponding to VTKCellType
346  */
347 //================================================================================
348
349 SMDSAbs_EntityType SMDS_MeshCell::toSmdsType(VTKCellType vtkType)
350 {
351   static std::vector< SMDSAbs_EntityType > smdsTypes;
352   if ( smdsTypes.empty() )
353   {
354     smdsTypes.resize( VTK_NUMBER_OF_CELL_TYPES, SMDSEntity_Last );
355     for ( int iSMDS = 0; iSMDS < SMDSEntity_Last; ++iSMDS )
356       smdsTypes[ toVtkType( SMDSAbs_EntityType( iSMDS ))] = SMDSAbs_EntityType( iSMDS );
357   }
358   return smdsTypes[ vtkType ];
359 }
360
361 //================================================================================
362 /*!
363  * \brief Return SMDSAbs_ElementType by SMDSAbs_GeometryType
364  */
365 //================================================================================
366
367 SMDSAbs_ElementType SMDS_MeshCell::toSmdsType(SMDSAbs_GeometryType geomType)
368 {
369   switch ( geomType ) {
370   case SMDSGeom_POINT:     return SMDSAbs_0DElement;
371
372   case SMDSGeom_EDGE:      return SMDSAbs_Edge; 
373
374   case SMDSGeom_TRIANGLE:
375   case SMDSGeom_QUADRANGLE:
376   case SMDSGeom_POLYGON:   return SMDSAbs_Face;
377
378   case SMDSGeom_TETRA:
379   case SMDSGeom_PYRAMID:
380   case SMDSGeom_HEXA:
381   case SMDSGeom_PENTA:
382   case SMDSGeom_HEXAGONAL_PRISM:
383   case SMDSGeom_POLYHEDRA: return SMDSAbs_Volume;
384
385   case SMDSGeom_BALL:      return SMDSAbs_Ball;
386
387   case SMDSGeom_NONE: ;
388   }
389   return SMDSAbs_All;
390 }
391
392 //================================================================================
393 /*!
394  * \brief Return SMDSAbs_ElementType by SMDSAbs_EntityType
395  */
396 //================================================================================
397
398 SMDSAbs_ElementType SMDS_MeshCell::toSmdsType(SMDSAbs_EntityType entityType)
399 {
400   switch ( entityType ) {
401   case SMDSEntity_Node:           return SMDSAbs_Node;
402
403   case SMDSEntity_0D:             return SMDSAbs_0DElement;
404
405   case SMDSEntity_Edge:
406   case SMDSEntity_Quad_Edge:      return SMDSAbs_Edge;
407
408   case SMDSEntity_Triangle:
409   case SMDSEntity_Quad_Triangle:
410   case SMDSEntity_BiQuad_Triangle:
411   case SMDSEntity_Quadrangle:
412   case SMDSEntity_Quad_Quadrangle:
413   case SMDSEntity_BiQuad_Quadrangle:
414   case SMDSEntity_Polygon:
415   case SMDSEntity_Quad_Polygon:   return SMDSAbs_Face;
416
417   case SMDSEntity_Tetra:
418   case SMDSEntity_Quad_Tetra:
419   case SMDSEntity_Pyramid:
420   case SMDSEntity_Quad_Pyramid:
421   case SMDSEntity_Hexa:
422   case SMDSEntity_Quad_Hexa:
423   case SMDSEntity_TriQuad_Hexa:
424   case SMDSEntity_Penta:
425   case SMDSEntity_Quad_Penta:
426   case SMDSEntity_BiQuad_Penta:
427   case SMDSEntity_Hexagonal_Prism:
428   case SMDSEntity_Polyhedra:
429   case SMDSEntity_Quad_Polyhedra: return SMDSAbs_Volume;
430
431   case SMDSEntity_Ball:           return SMDSAbs_Ball;
432
433   case SMDSEntity_Last:;
434   }
435   return SMDSAbs_All;
436 }
437
438
439 //================================================================================
440 /*!
441  * \brief Return indices to transform cell connectivity from VTK to SMDS
442  * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
443  */
444 //================================================================================
445
446 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(SMDSAbs_EntityType smdsType)
447 {
448   static std::vector< std::vector<int> > fromVtkInterlaces;
449   if ( fromVtkInterlaces.empty() )
450   {
451     fromVtkInterlaces.resize( SMDSEntity_Last+1 );
452     for ( int iSMDS = 0; iSMDS < SMDSEntity_Last; ++iSMDS )
453     {
454       const std::vector<int> & toVtk = toVtkOrder( SMDSAbs_EntityType( iSMDS ));
455       std::vector<int> &      toSmds = fromVtkInterlaces[ iSMDS ];
456       toSmds.resize( toVtk.size() );
457       for ( size_t i = 0; i < toVtk.size(); ++i )
458         toSmds[ toVtk[i] ] = i;
459     }
460   }
461   return fromVtkInterlaces[ smdsType ];
462 }
463
464 //================================================================================
465 /*!
466  * \brief Return indices to transform cell connectivity from SMDS to VTK
467  * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
468  */
469 //================================================================================
470
471 const std::vector<int>& SMDS_MeshCell::toVtkOrder(VTKCellType vtkType)
472 {
473   return toVtkOrder( toSmdsType( vtkType ));
474 }
475
476 //================================================================================
477 /*!
478  * \brief Return indices to transform cell connectivity from VTK to SMDS
479  * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
480  */
481 //================================================================================
482
483 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(VTKCellType vtkType)
484 {
485   return fromVtkOrder( toSmdsType( vtkType ));
486 }