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"
22 #include "SMDS_Mesh.hxx"
23 #include "SMDS_VtkCellIterator.hxx"
25 #include <utilities.h>
31 #include <boost/make_shared.hpp>
36 * \brief Cell type features
40 SMDSAbs_EntityType myEntity;
41 SMDSAbs_ElementType myType;
42 SMDSAbs_GeometryType myGeom;
50 myEntity( SMDSEntity_Last ), myType( SMDSAbs_All ), myGeom( SMDSGeom_NONE ),
51 myIsPoly( 0 ), myNbCornerNodes( 0 ),
52 myNbNodes( 0 ), myNbEdges( 0 ), myNbFaces ( 0 )
55 void Set( SMDSAbs_EntityType Entity,
56 SMDSAbs_ElementType Type,
57 SMDSAbs_GeometryType Geom,
68 myNbCornerNodes = NbCornerNodes;
73 bool IsQuadratic() const { return myNbNodes > myNbCornerNodes; }
76 //! return vector a CellProps
77 const CellProps& getCellProps( VTKCellType vtkType )
79 static std::vector< CellProps > theCellProps;
80 if ( theCellProps.empty() )
82 theCellProps.resize( VTK_NUMBER_OF_CELL_TYPES );
83 CellProps* p = & theCellProps[0];
85 Set( SMDSEntity_0D, SMDSAbs_0DElement, SMDSGeom_POINT,
86 /*isPoly=*/0,/*nbCN=*/1,/*nbN=*/1,/*nbE=*/0,/*nbF=*/0 );
88 Set( SMDSEntity_Edge, SMDSAbs_Edge, SMDSGeom_EDGE,
89 /*isPoly=*/0,/*nbCN=*/2,/*nbN=*/2,/*nbE=*/1,/*nbF=*/0 );
90 p[ VTK_QUADRATIC_EDGE ].
91 Set( SMDSEntity_Quad_Edge, SMDSAbs_Edge, SMDSGeom_EDGE,
92 /*isPoly=*/0,/*nbCN=*/2,/*nbN=*/3,/*nbE=*/1,/*nbF=*/0 );
94 Set( SMDSEntity_Triangle, SMDSAbs_Face, SMDSGeom_TRIANGLE,
95 /*isPoly=*/0,/*nbCN=*/3,/*nbN=*/3,/*nbE=*/3,/*nbF=*/1 );
96 p[ VTK_QUADRATIC_TRIANGLE ].
97 Set( SMDSEntity_Quad_Triangle, SMDSAbs_Face, SMDSGeom_TRIANGLE,
98 /*isPoly=*/0,/*nbCN=*/3,/*nbN=*/6,/*nbE=*/3,/*nbF=*/1 );
99 p[ VTK_BIQUADRATIC_TRIANGLE ].
100 Set( SMDSEntity_BiQuad_Triangle, SMDSAbs_Face, SMDSGeom_TRIANGLE,
101 /*isPoly=*/0,/*nbCN=*/3,/*nbN=*/7,/*nbE=*/3,/*nbF=*/1 );
103 Set( SMDSEntity_Quadrangle, SMDSAbs_Face, SMDSGeom_QUADRANGLE,
104 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/4,/*nbE=*/4,/*nbF=*/1 );
105 p[ VTK_QUADRATIC_QUAD].
106 Set( SMDSEntity_Quad_Quadrangle, SMDSAbs_Face, SMDSGeom_QUADRANGLE,
107 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/8,/*nbE=*/4,/*nbF=*/1 );
108 p[ VTK_BIQUADRATIC_QUAD].
109 Set( SMDSEntity_BiQuad_Quadrangle, SMDSAbs_Face, SMDSGeom_QUADRANGLE,
110 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/9,/*nbE=*/4,/*nbF=*/1 );
112 Set( SMDSEntity_Polygon, SMDSAbs_Face, SMDSGeom_POLYGON,
113 /*isPoly=*/1,/*nbCN=*/-1,/*nbN=*/-1,/*nbE=*/-1,/*nbF=*/1 );
114 p[ VTK_QUADRATIC_POLYGON ].
115 Set( SMDSEntity_Quad_Polygon, SMDSAbs_Face, SMDSGeom_POLYGON,
116 /*isPoly=*/1,/*nbCN=*/-2,/*nbN=*/-1,/*nbE=*/-1,/*nbF=*/1 );
118 Set( SMDSEntity_Tetra, SMDSAbs_Volume, SMDSGeom_TETRA,
119 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/4,/*nbE=*/6,/*nbF=*/4 );
120 p[ VTK_QUADRATIC_TETRA ].
121 Set( SMDSEntity_Quad_Tetra, SMDSAbs_Volume, SMDSGeom_TETRA,
122 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/10,/*nbE=*/6,/*nbF=*/4 );
124 Set( SMDSEntity_Pyramid, SMDSAbs_Volume, SMDSGeom_PYRAMID,
125 /*isPoly=*/0,/*nbCN=*/5,/*nbN=*/5,/*nbE=*/8,/*nbF=*/5 );
126 p[ VTK_QUADRATIC_PYRAMID].
127 Set( SMDSEntity_Quad_Pyramid, SMDSAbs_Volume, SMDSGeom_PYRAMID,
128 /*isPoly=*/0,/*nbCN=*/5,/*nbN=*/13,/*nbE=*/8,/*nbF=*/5 );
130 Set( SMDSEntity_Hexa, SMDSAbs_Volume, SMDSGeom_HEXA,
131 /*isPoly=*/0,/*nbCN=*/8,/*nbN=*/8,/*nbE=*/12,/*nbF=*/6 );
132 p[ VTK_QUADRATIC_HEXAHEDRON ].
133 Set( SMDSEntity_Quad_Hexa, SMDSAbs_Volume, SMDSGeom_HEXA,
134 /*isPoly=*/0,/*nbCN=*/8,/*nbN=*/20,/*nbE=*/12,/*nbF=*/6 );
135 p[ VTK_TRIQUADRATIC_HEXAHEDRON ].
136 Set( SMDSEntity_TriQuad_Hexa, SMDSAbs_Volume, SMDSGeom_HEXA,
137 /*isPoly=*/0,/*nbCN=*/8,/*nbN=*/27,/*nbE=*/12,/*nbF=*/6 );
139 Set( SMDSEntity_Penta, SMDSAbs_Volume, SMDSGeom_PENTA,
140 /*isPoly=*/0,/*nbCN=*/6,/*nbN=*/6,/*nbE=*/9,/*nbF=*/5 );
141 p[ VTK_QUADRATIC_WEDGE ].
142 Set( SMDSEntity_Quad_Penta, SMDSAbs_Volume, SMDSGeom_PENTA,
143 /*isPoly=*/0,/*nbCN=*/6,/*nbN=*/15,/*nbE=*/9,/*nbF=*/5 );
144 p[ VTK_BIQUADRATIC_QUADRATIC_WEDGE ].
145 Set( SMDSEntity_BiQuad_Penta, SMDSAbs_Volume, SMDSGeom_PENTA,
146 /*isPoly=*/0,/*nbCN=*/6,/*nbN=*/21,/*nbE=*/9,/*nbF=*/5 );
147 p[ VTK_HEXAGONAL_PRISM].
148 Set( SMDSEntity_Hexagonal_Prism, SMDSAbs_Volume, SMDSGeom_HEXAGONAL_PRISM,
149 /*isPoly=*/0,/*nbCN=*/12,/*nbN=*/12,/*nbE=*/18,/*nbF=*/8 );
151 Set( SMDSEntity_Polyhedra, SMDSAbs_Volume, SMDSGeom_POLYHEDRA,
152 /*isPoly=*/1,/*nbCN=*/-1,/*nbN=*/-1,/*nbE=*/-1,/*nbF=*/-1 );
154 Set( SMDSEntity_Ball, SMDSAbs_Ball, SMDSGeom_BALL,
155 /*isPoly=*/0,/*nbCN=*/1,/*nbN=*/1,/*nbE=*/0,/*nbF=*/0 );
157 return theCellProps[ vtkType ];
161 //! return vector a CellProps
162 const CellProps& getCellProps( SMDSAbs_EntityType entity )
164 return getCellProps( SMDS_MeshCell::toVtkType( entity ));
169 void SMDS_MeshCell::InitStaticMembers()
171 getCellProps( SMDSEntity_Ball );
172 toVtkOrder( SMDSEntity_Ball );
173 reverseSmdsOrder( SMDSEntity_Ball, 1 );
174 interlacedSmdsOrder( SMDSEntity_Ball, 1 );
175 fromVtkOrder( SMDSEntity_Ball );
178 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity, int theNbNodes, ... )
180 ASSERT( getCellProps( theEntity ).myNbNodes == theNbNodes ||
181 getCellProps( theEntity ).myIsPoly);
184 va_start( vl, theNbNodes );
186 vtkIdType vtkIds[ VTK_CELL_SIZE ];
187 typedef const SMDS_MeshNode* node_t;
189 const std::vector<int>& interlace = toVtkOrder( theEntity );
190 if ((int) interlace.size() == theNbNodes )
192 const SMDS_MeshNode* nodes[ VTK_CELL_SIZE ];
193 for ( int i = 0; i < theNbNodes; i++ )
194 nodes[i] = va_arg( vl, node_t );
196 for ( int i = 0; i < theNbNodes; i++ )
197 vtkIds[i] = nodes[ interlace[i] ]->GetVtkID();
201 for ( int i = 0; i < theNbNodes; i++ )
202 vtkIds[i] = va_arg( vl, node_t )->GetVtkID();
206 int vtkType = toVtkType( theEntity );
207 int vtkID = getGrid()->InsertNextLinkedCell( vtkType, theNbNodes, vtkIds );
211 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity,
212 const std::vector<const SMDS_MeshNode*>& nodes )
214 std::vector< vtkIdType > vtkIds( nodes.size() );
215 for ( size_t i = 0; i < nodes.size(); ++i )
216 vtkIds[i] = nodes[i]->GetVtkID();
218 int vtkType = toVtkType( theEntity );
219 int vtkID = getGrid()->InsertNextLinkedCell( vtkType, nodes.size(), &vtkIds[0] );
223 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity,
224 const std::vector<vtkIdType>& vtkNodeIds )
226 int vtkType = toVtkType( theEntity );
227 int vtkID = getGrid()->InsertNextLinkedCell( vtkType, vtkNodeIds.size(),
228 const_cast< vtkIdType* > ( &vtkNodeIds[0] ));
232 bool SMDS_MeshCell::ChangeNodes(const SMDS_MeshNode* nodes[], const int theNbNodes)
236 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
237 if ( theNbNodes != npts )
239 MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << theNbNodes);
242 const std::vector<int>& interlace = toVtkOrder((VTKCellType) GetVtkType() );
243 if ((int) interlace.size() != theNbNodes )
244 for ( int i = 0; i < theNbNodes; i++ )
246 pts[i] = nodes[i]->GetVtkID();
249 for ( int i = 0; i < theNbNodes; i++ )
251 pts[i] = nodes[ interlace[i] ]->GetVtkID();
257 ///////////////////////////////////////////////////////////////////////////////
258 ///Return The number of nodes owned by the current element
259 ///////////////////////////////////////////////////////////////////////////////
260 int SMDS_MeshCell::NbNodes() const
262 if ( GetEntityType() == SMDSEntity_Polyhedra )
263 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbNodes();
264 vtkIdType *pts, npts;
265 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
269 int SMDS_MeshCell::NbFaces() const
271 if ( GetEntityType() == SMDSEntity_Polyhedra )
272 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbFaces();
273 return getCellProps( GetVtkType() ).myNbFaces;
276 int SMDS_MeshCell::NbEdges() const
278 switch ( GetEntityType() )
280 case SMDSEntity_Polyhedra:
281 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbEdges();
282 case SMDSEntity_Polygon:
284 case SMDSEntity_Quad_Polygon:
285 return NbNodes() / 2;
288 return getCellProps( GetVtkType() ).myNbEdges;
291 int SMDS_MeshCell::NbCornerNodes() const
293 switch ( GetEntityType() )
295 case SMDSEntity_Polyhedra:
296 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbCornerNodes();
297 case SMDSEntity_Polygon:
299 case SMDSEntity_Quad_Polygon:
300 return NbNodes() / 2;
303 return getCellProps( GetVtkType() ).myNbCornerNodes;
306 ///////////////////////////////////////////////////////////////////////////////
307 /// Create an iterator which iterate on nodes owned by the element.
308 ///////////////////////////////////////////////////////////////////////////////
309 SMDS_ElemIteratorPtr SMDS_MeshCell::nodesIterator() const
311 if ( GetEntityType() == SMDSEntity_Polyhedra )
312 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodesIterator();
314 return boost::make_shared< SMDS_VtkCellIterator<> >( GetMesh(), GetVtkID(), GetEntityType());
317 ///////////////////////////////////////////////////////////////////////////////
318 /// Create an iterator which iterate on nodes owned by the element.
319 ///////////////////////////////////////////////////////////////////////////////
320 SMDS_NodeIteratorPtr SMDS_MeshCell::nodeIterator() const
322 if ( GetEntityType() == SMDSEntity_Polyhedra )
323 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodeIterator();
325 return SMDS_NodeIteratorPtr
326 (new SMDS_VtkCellIterator<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
329 SMDS_NodeIteratorPtr SMDS_MeshCell::interlacedNodesIterator() const
331 bool canInterlace = ( GetType() == SMDSAbs_Face || GetType() == SMDSAbs_Edge );
332 return canInterlace ? nodesIteratorToUNV() : nodeIterator();
335 SMDS_NodeIteratorPtr SMDS_MeshCell::nodesIteratorToUNV() const
337 return SMDS_NodeIteratorPtr
338 (new SMDS_VtkCellIteratorToUNV<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
341 SMDSAbs_ElementType SMDS_MeshCell::GetType() const
343 return ElemType( GetEntityType() );
346 SMDSAbs_EntityType SMDS_MeshCell::GetEntityType() const
348 return toSmdsType( (VTKCellType) GetVtkType() );
351 SMDSAbs_GeometryType SMDS_MeshCell::GetGeomType() const
353 return getCellProps( GetVtkType() ).myGeom;
356 VTKCellType SMDS_MeshCell::GetVtkType() const
358 return (VTKCellType) getGrid()->GetCellType( GetVtkID() );
361 bool SMDS_MeshCell::IsPoly() const
363 return getCellProps( GetVtkType() ).myIsPoly;
366 bool SMDS_MeshCell::IsQuadratic() const
368 return getCellProps( GetVtkType() ).IsQuadratic();
371 const SMDS_MeshNode* SMDS_MeshCell::GetNode(const int ind) const
373 if ( GetEntityType() == SMDSEntity_Polyhedra )
374 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNode( ind );
376 vtkIdType npts, *pts;
377 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
378 const std::vector<int>& interlace = SMDS_MeshCell::fromVtkOrder( VTKCellType( GetVtkType() ));
379 return GetMesh()->FindNodeVtk( pts[ interlace.empty() ? ind : interlace[ ind ]]);
382 int SMDS_MeshCell::GetNodeIndex( const SMDS_MeshNode* node ) const
384 if ( GetEntityType() == SMDSEntity_Polyhedra )
385 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNodeIndex( node );
387 vtkIdType npts, *pts;
388 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
389 for ( vtkIdType i = 0; i < npts; ++i )
390 if ( pts[i] == node->GetVtkID() )
392 const std::vector<int>& interlace = SMDS_MeshCell::toVtkOrder( VTKCellType( GetVtkType() ));
393 return interlace.empty() ? i : interlace[i];
398 //================================================================================
400 * \brief Return VTKCellType corresponding to SMDSAbs_EntityType
402 //================================================================================
404 VTKCellType SMDS_MeshCell::toVtkType (SMDSAbs_EntityType smdsType)
406 static std::vector< VTKCellType > vtkTypes;
407 if ( vtkTypes.empty() )
409 vtkTypes.resize( SMDSEntity_Last+1, VTK_EMPTY_CELL );
410 vtkTypes[ SMDSEntity_Node ] = VTK_VERTEX;
411 vtkTypes[ SMDSEntity_0D ] = VTK_VERTEX;
412 vtkTypes[ SMDSEntity_Edge ] = VTK_LINE;
413 vtkTypes[ SMDSEntity_Quad_Edge ] = VTK_QUADRATIC_EDGE;
414 vtkTypes[ SMDSEntity_Triangle ] = VTK_TRIANGLE;
415 vtkTypes[ SMDSEntity_Quad_Triangle ] = VTK_QUADRATIC_TRIANGLE;
416 vtkTypes[ SMDSEntity_BiQuad_Triangle ] = VTK_BIQUADRATIC_TRIANGLE;
417 vtkTypes[ SMDSEntity_Quadrangle ] = VTK_QUAD;
418 vtkTypes[ SMDSEntity_Quad_Quadrangle ] = VTK_QUADRATIC_QUAD;
419 vtkTypes[ SMDSEntity_BiQuad_Quadrangle ] = VTK_BIQUADRATIC_QUAD;
420 vtkTypes[ SMDSEntity_Polygon ] = VTK_POLYGON;
421 vtkTypes[ SMDSEntity_Quad_Polygon ] = VTK_QUADRATIC_POLYGON;
422 vtkTypes[ SMDSEntity_Tetra ] = VTK_TETRA;
423 vtkTypes[ SMDSEntity_Quad_Tetra ] = VTK_QUADRATIC_TETRA;
424 vtkTypes[ SMDSEntity_Pyramid ] = VTK_PYRAMID;
425 vtkTypes[ SMDSEntity_Quad_Pyramid ] = VTK_QUADRATIC_PYRAMID;
426 vtkTypes[ SMDSEntity_Hexa ] = VTK_HEXAHEDRON;
427 vtkTypes[ SMDSEntity_Quad_Hexa ] = VTK_QUADRATIC_HEXAHEDRON;
428 vtkTypes[ SMDSEntity_TriQuad_Hexa ] = VTK_TRIQUADRATIC_HEXAHEDRON;
429 vtkTypes[ SMDSEntity_Penta ] = VTK_WEDGE;
430 vtkTypes[ SMDSEntity_Quad_Penta ] = VTK_QUADRATIC_WEDGE;
431 vtkTypes[ SMDSEntity_BiQuad_Penta ] = VTK_BIQUADRATIC_QUADRATIC_WEDGE;
432 vtkTypes[ SMDSEntity_Hexagonal_Prism ] = VTK_HEXAGONAL_PRISM;
433 vtkTypes[ SMDSEntity_Polyhedra ] = VTK_POLYHEDRON;
434 //vtkTypes[ SMDSEntity_Quad_Polyhedra ] = ;
435 vtkTypes[ SMDSEntity_Ball ] = VTK_POLY_VERTEX;
437 return vtkTypes[ smdsType ];
440 //================================================================================
442 * \brief Return indices to transform cell connectivity from SMDS to VTK
443 * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
445 //================================================================================
447 const std::vector< int >& SMDS_MeshCell::toVtkOrder(SMDSAbs_EntityType smdsType)
449 static std::vector< std::vector< int > > toVtkInterlaces;
450 if ( toVtkInterlaces.empty() )
452 toVtkInterlaces.resize( SMDSEntity_Last+1 );
454 // const int ids[] = {0};
455 // toVtkInterlaces[SMDSEntity_0D].assign( &ids[0], &ids[0]+1 );
456 // toVtkInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
459 // const int ids[] = {0,1};
460 // toVtkInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
463 // const int ids[] = {0,1,2};
464 // toVtkInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
467 // const int ids[] = {0,1,2};
468 // toVtkInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
471 // const int ids[] = {0,1,2,3,4,5};
472 // toVtkInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
475 // const int ids[] = {0,1,2,3};
476 // toVtkInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
479 // const int ids[] = {0,1,2,3,4,5,6,7};
480 // toVtkInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
483 // const int ids[] = {0,1,2,3,4,5,6,7,8};
484 // toVtkInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
487 const int ids[] = {0,2,1,3};
488 toVtkInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
491 const int ids[] = {0,2,1,3,6,5,4,7,9,8};
492 toVtkInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
495 const int ids[] = {0,3,2,1,4};
496 toVtkInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
499 const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
500 toVtkInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
503 const int ids[] = {0,3,2,1,4,7,6,5};
504 toVtkInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
507 const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
508 toVtkInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
511 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};
512 toVtkInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
515 const int ids[] = {0,1,2,3,4,5};
516 toVtkInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
519 const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}; // TODO: check
520 toVtkInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
523 const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};// TODO: check
524 toVtkInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
527 const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
528 toVtkInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
531 return toVtkInterlaces[smdsType];
534 //================================================================================
536 * \brief Return indices to reverse an SMDS cell of given type.
537 * nbNodes is useful for polygons
538 * Usage: reverseIDs[i] = forwardIDs[ indices[ i ]]
540 //================================================================================
542 const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType,
543 const size_t nbNodes)
545 static std::vector< std::vector< int > > reverseInterlaces;
546 if ( reverseInterlaces.empty() )
548 reverseInterlaces.resize( SMDSEntity_Last+1 );
550 const int ids[] = {0};
551 reverseInterlaces[SMDSEntity_0D].assign( &ids[0], &ids[0]+1 );
552 reverseInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
553 reverseInterlaces[SMDSEntity_Ball].assign( &ids[0], &ids[0]+1 );
556 const int ids[] = {1,0};
557 reverseInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
560 const int ids[] = {1,0,2};
561 reverseInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
564 const int ids[] = {0,2,1};
565 reverseInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
568 const int ids[] = {0,2,1,5,4,3};
569 reverseInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
572 const int ids[] = {0,2,1,5,4,3,6};
573 reverseInterlaces[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
576 const int ids[] = {0,3,2,1};
577 reverseInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
580 const int ids[] = {0,3,2,1,7,6,5,4};
581 reverseInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
584 const int ids[] = {0,3,2,1,7,6,5,4,8};
585 reverseInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
588 const int ids[] = {0,2,1,3};
589 reverseInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
592 const int ids[] = {0,2,1,3,6,5,4,7,9,8};
593 reverseInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
596 const int ids[] = {0,3,2,1,4};
597 reverseInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
600 const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
601 reverseInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
604 const int ids[] = {0,3,2,1,4,7,6,5};
605 reverseInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
608 const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
609 reverseInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
612 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};
613 reverseInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
616 const int ids[] = {0,2,1,3,5,4};
617 reverseInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
620 const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13};
621 reverseInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
624 const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13,15,16,17};
625 reverseInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
628 const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
629 reverseInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
633 if ( smdsType == SMDSEntity_Polygon )
635 if ( reverseInterlaces[ smdsType ].size() != nbNodes )
637 reverseInterlaces[ smdsType ].resize( nbNodes );
638 for ( size_t i = 0; i < nbNodes; ++i )
639 reverseInterlaces[ smdsType ][i] = nbNodes - i - 1;
642 else if ( smdsType == SMDSEntity_Quad_Polygon )
644 if ( reverseInterlaces[ smdsType ].size() != nbNodes )
646 // e.g. for 8 nodes: [ 0, 3,2,1, 7,6,5,4 ]
647 reverseInterlaces[ smdsType ].resize( nbNodes );
649 reverseInterlaces[ smdsType ][pos++] = 0;
650 for ( int i = nbNodes / 2 - 1; i > 0 ; --i ) // 3,2,1
651 reverseInterlaces[ smdsType ][pos++] = i;
652 for ( int i = nbNodes - 1, nb = nbNodes / 2; i >= nb; --i ) // 7,6,5,4
653 reverseInterlaces[ smdsType ][pos++] = i;
657 return reverseInterlaces[smdsType];
660 //================================================================================
662 * \brief Return indices to set nodes of a quadratic 1D or 2D element in interlaced order
663 * Usage: interlacedIDs[i] = smdsIDs[ indices[ i ]]
665 //================================================================================
667 const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
668 const size_t nbNodes)
670 static std::vector< std::vector< int > > interlace;
671 if ( interlace.empty() )
673 interlace.resize( SMDSEntity_Last+1 );
675 const int ids[] = {0,2,1};
676 interlace[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
679 const int ids[] = {0,3,1,4,2,5,6};
680 interlace[SMDSEntity_Quad_Triangle ].assign( &ids[0], &ids[0]+6 );
681 interlace[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
684 const int ids[] = {0,4,1,5,2,6,3,7,8};
685 interlace[SMDSEntity_Quad_Quadrangle ].assign( &ids[0], &ids[0]+8 );
686 interlace[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
690 if ( smdsType == SMDSEntity_Quad_Polygon )
692 if ( interlace[smdsType].size() != nbNodes )
694 interlace[smdsType].resize( nbNodes );
695 for ( size_t i = 0; i < nbNodes / 2; ++i )
697 interlace[smdsType][i*2+0] = i;
698 interlace[smdsType][i*2+1] = i + nbNodes / 2;
702 return interlace[smdsType];
705 //================================================================================
707 * \brief Return SMDSAbs_EntityType corresponding to VTKCellType
709 //================================================================================
711 SMDSAbs_EntityType SMDS_MeshCell::toSmdsType(VTKCellType vtkType)
713 return getCellProps( vtkType ).myEntity;
716 //================================================================================
718 * \brief Return SMDSAbs_ElementType by SMDSAbs_GeometryType
720 //================================================================================
722 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_GeometryType geomType)
724 switch ( geomType ) {
725 case SMDSGeom_POINT: return SMDSAbs_0DElement;
727 case SMDSGeom_EDGE: return SMDSAbs_Edge;
729 case SMDSGeom_TRIANGLE:
730 case SMDSGeom_QUADRANGLE:
731 case SMDSGeom_POLYGON: return SMDSAbs_Face;
734 case SMDSGeom_PYRAMID:
737 case SMDSGeom_HEXAGONAL_PRISM:
738 case SMDSGeom_POLYHEDRA: return SMDSAbs_Volume;
740 case SMDSGeom_BALL: return SMDSAbs_Ball;
742 case SMDSGeom_NONE: ;
747 //================================================================================
749 * \brief Return SMDSAbs_ElementType by SMDSAbs_EntityType
751 //================================================================================
753 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_EntityType entityType)
755 return getCellProps( entityType ).myType;
758 SMDSAbs_GeometryType SMDS_MeshCell::GeomType( SMDSAbs_EntityType entityType )
760 return getCellProps( entityType ).myGeom;
763 bool SMDS_MeshCell::IsPoly( SMDSAbs_EntityType entityType )
765 return getCellProps( entityType ).myIsPoly;
768 bool SMDS_MeshCell::IsQuadratic( SMDSAbs_EntityType entityType )
770 return getCellProps( entityType ).IsQuadratic();
773 int SMDS_MeshCell::NbCornerNodes( SMDSAbs_EntityType entityType )
775 return getCellProps( entityType ).myNbCornerNodes;
778 int SMDS_MeshCell::NbNodes( SMDSAbs_EntityType entityType )
780 return getCellProps( entityType ).myNbNodes;
783 int SMDS_MeshCell::NbEdges( SMDSAbs_EntityType entityType )
785 return getCellProps( entityType ).myNbEdges;
788 int SMDS_MeshCell::NbFaces( SMDSAbs_EntityType entityType )
790 return getCellProps( entityType ).myNbFaces;
793 //================================================================================
795 * \brief Return indices to transform cell connectivity from VTK to SMDS
796 * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
798 //================================================================================
800 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(SMDSAbs_EntityType smdsType)
802 static std::vector< std::vector<int> > fromVtkInterlaces;
803 if ( fromVtkInterlaces.empty() )
805 fromVtkInterlaces.resize( SMDSEntity_Last+1 );
806 for ( int iSMDS = 0; iSMDS < SMDSEntity_Last; ++iSMDS )
808 const std::vector<int> & toVtk = toVtkOrder( SMDSAbs_EntityType( iSMDS ));
809 std::vector<int> & toSmds = fromVtkInterlaces[ iSMDS ];
810 toSmds.resize( toVtk.size() );
811 for ( size_t i = 0; i < toVtk.size(); ++i )
812 toSmds[ toVtk[i] ] = i;
815 return fromVtkInterlaces[ smdsType ];
818 //================================================================================
820 * \brief Return indices to transform cell connectivity from SMDS to VTK
821 * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
823 //================================================================================
825 const std::vector<int>& SMDS_MeshCell::toVtkOrder(VTKCellType vtkType)
827 return toVtkOrder( toSmdsType( vtkType ));
830 //================================================================================
832 * \brief Return indices to transform cell connectivity from VTK to SMDS
833 * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
835 //================================================================================
837 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(VTKCellType vtkType)
839 return fromVtkOrder( toSmdsType( vtkType ));