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