1 // Copyright (C) 2010-2016 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SMDS_MeshCell.hxx"
21 #include "utilities.h"
23 int SMDS_MeshCell::nbCells = 0;
25 SMDS_MeshCell::SMDS_MeshCell() :
32 SMDS_MeshCell::~SMDS_MeshCell()
36 //================================================================================
38 * \brief Return VTKCellType corresponding to SMDSAbs_EntityType
40 //================================================================================
42 VTKCellType SMDS_MeshCell::toVtkType (SMDSAbs_EntityType smdsType)
44 static std::vector< VTKCellType > vtkTypes;
45 if ( vtkTypes.empty() )
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;
75 return vtkTypes[ smdsType ];
78 //================================================================================
80 * \brief Return indices to transform cell connectivity from SMDS to VTK
81 * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
83 //================================================================================
85 const std::vector< int >& SMDS_MeshCell::toVtkOrder(SMDSAbs_EntityType smdsType)
87 static std::vector< std::vector< int > > toVtkInterlaces;
88 if ( toVtkInterlaces.empty() )
90 toVtkInterlaces.resize( SMDSEntity_Last+1 );
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 );
97 // const int ids[] = {0,1};
98 // toVtkInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
101 // const int ids[] = {0,1,2};
102 // toVtkInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
105 // const int ids[] = {0,1,2};
106 // toVtkInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
109 // const int ids[] = {0,1,2,3,4,5};
110 // toVtkInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
113 // const int ids[] = {0,1,2,3};
114 // toVtkInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
117 // const int ids[] = {0,1,2,3,4,5,6,7};
118 // toVtkInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
121 // const int ids[] = {0,1,2,3,4,5,6,7,8};
122 // toVtkInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
125 const int ids[] = {0,2,1,3};
126 toVtkInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
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 );
133 const int ids[] = {0,3,2,1,4};
134 toVtkInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
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 );
141 const int ids[] = {0,3,2,1,4,7,6,5};
142 toVtkInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
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 );
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 );
153 const int ids[] = {0,1,2,3,4,5};
154 toVtkInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
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 );
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 );
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 );
169 return toVtkInterlaces[smdsType];
172 //================================================================================
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 ]]
178 //================================================================================
180 const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType,
181 const size_t nbNodes)
183 static std::vector< std::vector< int > > reverseInterlaces;
184 if ( reverseInterlaces.empty() )
186 reverseInterlaces.resize( SMDSEntity_Last+1 );
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 );
194 const int ids[] = {1,0};
195 reverseInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
198 const int ids[] = {1,0,2};
199 reverseInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
202 const int ids[] = {0,2,1};
203 reverseInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
206 const int ids[] = {0,2,1,5,4,3};
207 reverseInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
210 const int ids[] = {0,2,1,5,4,3,6};
211 reverseInterlaces[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
214 const int ids[] = {0,3,2,1};
215 reverseInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
218 const int ids[] = {0,3,2,1,7,6,5,4};
219 reverseInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
222 const int ids[] = {0,3,2,1,7,6,5,4,8};
223 reverseInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
226 const int ids[] = {0,2,1,3};
227 reverseInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
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 );
234 const int ids[] = {0,3,2,1,4};
235 reverseInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
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 );
242 const int ids[] = {0,3,2,1,4,7,6,5};
243 reverseInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
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 );
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 );
254 const int ids[] = {0,2,1,3,5,4};
255 reverseInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
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 );
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 );
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 );
271 if ( smdsType == SMDSEntity_Polygon )
273 if ( reverseInterlaces[ smdsType ].size() != nbNodes )
275 reverseInterlaces[ smdsType ].resize( nbNodes );
276 for ( size_t i = 0; i < nbNodes; ++i )
277 reverseInterlaces[ smdsType ][i] = nbNodes - i - 1;
280 else if ( smdsType == SMDSEntity_Quad_Polygon )
282 if ( reverseInterlaces[ smdsType ].size() != nbNodes )
284 // e.g. for 8 nodes: [ 0, 3,2,1, 7,6,5,4 ]
285 reverseInterlaces[ smdsType ].resize( nbNodes );
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;
295 return reverseInterlaces[smdsType];
298 //================================================================================
300 * \brief Return indices to set nodes of a quadratic 1D or 2D element in interlaced order
301 * Usage: interlacedIDs[i] = smdsIDs[ indices[ i ]]
303 //================================================================================
305 const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
306 const size_t nbNodes)
308 static std::vector< std::vector< int > > interlace;
309 if ( interlace.empty() )
311 interlace.resize( SMDSEntity_Last+1 );
313 const int ids[] = {0,2,1};
314 interlace[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
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 );
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 );
328 if ( smdsType == SMDSEntity_Quad_Polygon )
330 if ( interlace[smdsType].size() != nbNodes )
332 interlace[smdsType].resize( nbNodes );
333 for ( size_t i = 0; i < nbNodes / 2; ++i )
335 interlace[smdsType][i*2+0] = i;
336 interlace[smdsType][i*2+1] = i + nbNodes / 2;
340 return interlace[smdsType];
343 //================================================================================
345 * \brief Return SMDSAbs_EntityType corresponding to VTKCellType
347 //================================================================================
349 SMDSAbs_EntityType SMDS_MeshCell::toSmdsType(VTKCellType vtkType)
351 static std::vector< SMDSAbs_EntityType > smdsTypes;
352 if ( smdsTypes.empty() )
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 );
358 return smdsTypes[ vtkType ];
361 //================================================================================
363 * \brief Return SMDSAbs_ElementType by SMDSAbs_GeometryType
365 //================================================================================
367 SMDSAbs_ElementType SMDS_MeshCell::toSmdsType(SMDSAbs_GeometryType geomType)
369 switch ( geomType ) {
370 case SMDSGeom_POINT: return SMDSAbs_0DElement;
372 case SMDSGeom_EDGE: return SMDSAbs_Edge;
374 case SMDSGeom_TRIANGLE:
375 case SMDSGeom_QUADRANGLE:
376 case SMDSGeom_POLYGON: return SMDSAbs_Face;
379 case SMDSGeom_PYRAMID:
382 case SMDSGeom_HEXAGONAL_PRISM:
383 case SMDSGeom_POLYHEDRA: return SMDSAbs_Volume;
385 case SMDSGeom_BALL: return SMDSAbs_Ball;
387 case SMDSGeom_NONE: ;
392 //================================================================================
394 * \brief Return SMDSAbs_ElementType by SMDSAbs_EntityType
396 //================================================================================
398 SMDSAbs_ElementType SMDS_MeshCell::toSmdsType(SMDSAbs_EntityType entityType)
400 switch ( entityType ) {
401 case SMDSEntity_Node: return SMDSAbs_Node;
403 case SMDSEntity_0D: return SMDSAbs_0DElement;
405 case SMDSEntity_Edge:
406 case SMDSEntity_Quad_Edge: return SMDSAbs_Edge;
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;
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;
431 case SMDSEntity_Ball: return SMDSAbs_Ball;
433 case SMDSEntity_Last:;
439 //================================================================================
441 * \brief Return indices to transform cell connectivity from VTK to SMDS
442 * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
444 //================================================================================
446 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(SMDSAbs_EntityType smdsType)
448 static std::vector< std::vector<int> > fromVtkInterlaces;
449 if ( fromVtkInterlaces.empty() )
451 fromVtkInterlaces.resize( SMDSEntity_Last+1 );
452 for ( int iSMDS = 0; iSMDS < SMDSEntity_Last; ++iSMDS )
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;
461 return fromVtkInterlaces[ smdsType ];
464 //================================================================================
466 * \brief Return indices to transform cell connectivity from SMDS to VTK
467 * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
469 //================================================================================
471 const std::vector<int>& SMDS_MeshCell::toVtkOrder(VTKCellType vtkType)
473 return toVtkOrder( toSmdsType( vtkType ));
476 //================================================================================
478 * \brief Return indices to transform cell connectivity from VTK to SMDS
479 * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
481 //================================================================================
483 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(VTKCellType vtkType)
485 return fromVtkOrder( toSmdsType( vtkType ));