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;
51 myEntity( SMDSEntity_Last ), myType( SMDSAbs_All ), myGeom( SMDSGeom_NONE ),
52 myIsPoly( 0 ), myNbCornerNodes( 0 ),
53 myNbNodes( 0 ), myNbEdges( 0 ), myNbFaces ( 0 )
56 void Set( SMDSAbs_EntityType Entity,
57 SMDSAbs_ElementType Type,
58 SMDSAbs_GeometryType Geom,
69 myIsQuadratic = ( NbNodes > NbCornerNodes );
70 myNbCornerNodes = NbCornerNodes;
77 //! return vector a CellProps
78 const CellProps& getCellProps( VTKCellType vtkType )
80 static std::vector< CellProps > theCellProps;
81 if ( theCellProps.empty() )
83 theCellProps.resize( VTK_NUMBER_OF_CELL_TYPES );
84 CellProps* p = & theCellProps[0];
86 Set( SMDSEntity_0D, SMDSAbs_0DElement, SMDSGeom_POINT,
87 /*isPoly=*/0,/*nbCN=*/1,/*nbN=*/1,/*nbE=*/0,/*nbF=*/0 );
89 Set( SMDSEntity_Edge, SMDSAbs_Edge, SMDSGeom_EDGE,
90 /*isPoly=*/0,/*nbCN=*/2,/*nbN=*/2,/*nbE=*/1,/*nbF=*/0 );
91 p[ VTK_QUADRATIC_EDGE ].
92 Set( SMDSEntity_Quad_Edge, SMDSAbs_Edge, SMDSGeom_EDGE,
93 /*isPoly=*/0,/*nbCN=*/2,/*nbN=*/3,/*nbE=*/1,/*nbF=*/0 );
95 Set( SMDSEntity_Triangle, SMDSAbs_Face, SMDSGeom_TRIANGLE,
96 /*isPoly=*/0,/*nbCN=*/3,/*nbN=*/3,/*nbE=*/3,/*nbF=*/1 );
97 p[ VTK_QUADRATIC_TRIANGLE ].
98 Set( SMDSEntity_Quad_Triangle, SMDSAbs_Face, SMDSGeom_TRIANGLE,
99 /*isPoly=*/0,/*nbCN=*/3,/*nbN=*/6,/*nbE=*/3,/*nbF=*/1 );
100 p[ VTK_BIQUADRATIC_TRIANGLE ].
101 Set( SMDSEntity_BiQuad_Triangle, SMDSAbs_Face, SMDSGeom_TRIANGLE,
102 /*isPoly=*/0,/*nbCN=*/3,/*nbN=*/7,/*nbE=*/3,/*nbF=*/1 );
104 Set( SMDSEntity_Quadrangle, SMDSAbs_Face, SMDSGeom_QUADRANGLE,
105 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/4,/*nbE=*/4,/*nbF=*/1 );
106 p[ VTK_QUADRATIC_QUAD].
107 Set( SMDSEntity_Quad_Quadrangle, SMDSAbs_Face, SMDSGeom_QUADRANGLE,
108 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/8,/*nbE=*/4,/*nbF=*/1 );
109 p[ VTK_BIQUADRATIC_QUAD].
110 Set( SMDSEntity_BiQuad_Quadrangle, SMDSAbs_Face, SMDSGeom_QUADRANGLE,
111 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/9,/*nbE=*/4,/*nbF=*/1 );
113 Set( SMDSEntity_Polygon, SMDSAbs_Face, SMDSGeom_POLYGON,
114 /*isPoly=*/1,/*nbCN=*/-1,/*nbN=*/-1,/*nbE=*/-1,/*nbF=*/1 );
115 p[ VTK_QUADRATIC_POLYGON ].
116 Set( SMDSEntity_Quad_Polygon, SMDSAbs_Face, SMDSGeom_POLYGON,
117 /*isPoly=*/1,/*nbCN=*/-2,/*nbN=*/-1,/*nbE=*/-1,/*nbF=*/1 );
119 Set( SMDSEntity_Tetra, SMDSAbs_Volume, SMDSGeom_TETRA,
120 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/4,/*nbE=*/6,/*nbF=*/4 );
121 p[ VTK_QUADRATIC_TETRA ].
122 Set( SMDSEntity_Quad_Tetra, SMDSAbs_Volume, SMDSGeom_TETRA,
123 /*isPoly=*/0,/*nbCN=*/4,/*nbN=*/10,/*nbE=*/6,/*nbF=*/4 );
125 Set( SMDSEntity_Pyramid, SMDSAbs_Volume, SMDSGeom_PYRAMID,
126 /*isPoly=*/0,/*nbCN=*/5,/*nbN=*/5,/*nbE=*/8,/*nbF=*/5 );
127 p[ VTK_QUADRATIC_PYRAMID].
128 Set( SMDSEntity_Quad_Pyramid, SMDSAbs_Volume, SMDSGeom_PYRAMID,
129 /*isPoly=*/0,/*nbCN=*/5,/*nbN=*/13,/*nbE=*/8,/*nbF=*/5 );
131 Set( SMDSEntity_Hexa, SMDSAbs_Volume, SMDSGeom_HEXA,
132 /*isPoly=*/0,/*nbCN=*/8,/*nbN=*/8,/*nbE=*/12,/*nbF=*/6 );
133 p[ VTK_QUADRATIC_HEXAHEDRON ].
134 Set( SMDSEntity_Quad_Hexa, SMDSAbs_Volume, SMDSGeom_HEXA,
135 /*isPoly=*/0,/*nbCN=*/8,/*nbN=*/20,/*nbE=*/12,/*nbF=*/6 );
136 p[ VTK_TRIQUADRATIC_HEXAHEDRON ].
137 Set( SMDSEntity_TriQuad_Hexa, SMDSAbs_Volume, SMDSGeom_HEXA,
138 /*isPoly=*/0,/*nbCN=*/8,/*nbN=*/27,/*nbE=*/12,/*nbF=*/6 );
140 Set( SMDSEntity_Penta, SMDSAbs_Volume, SMDSGeom_PENTA,
141 /*isPoly=*/0,/*nbCN=*/6,/*nbN=*/6,/*nbE=*/9,/*nbF=*/5 );
142 p[ VTK_QUADRATIC_WEDGE ].
143 Set( SMDSEntity_Quad_Penta, SMDSAbs_Volume, SMDSGeom_PENTA,
144 /*isPoly=*/0,/*nbCN=*/6,/*nbN=*/15,/*nbE=*/9,/*nbF=*/5 );
145 p[ VTK_BIQUADRATIC_QUADRATIC_WEDGE ].
146 Set( SMDSEntity_BiQuad_Penta, SMDSAbs_Volume, SMDSGeom_PENTA,
147 /*isPoly=*/0,/*nbCN=*/6,/*nbN=*/21,/*nbE=*/9,/*nbF=*/5 );
148 p[ VTK_HEXAGONAL_PRISM].
149 Set( SMDSEntity_Hexagonal_Prism, SMDSAbs_Volume, SMDSGeom_HEXAGONAL_PRISM,
150 /*isPoly=*/0,/*nbCN=*/12,/*nbN=*/12,/*nbE=*/18,/*nbF=*/8 );
152 Set( SMDSEntity_Polyhedra, SMDSAbs_Volume, SMDSGeom_POLYHEDRA,
153 /*isPoly=*/1,/*nbCN=*/-1,/*nbN=*/-1,/*nbE=*/-1,/*nbF=*/-1 );
155 Set( SMDSEntity_Ball, SMDSAbs_Ball, SMDSGeom_BALL,
156 /*isPoly=*/0,/*nbCN=*/1,/*nbN=*/1,/*nbE=*/0,/*nbF=*/0 );
158 return theCellProps[ vtkType ];
162 //! return vector a CellProps
163 const CellProps& getCellProps( SMDSAbs_EntityType entity )
165 return getCellProps( SMDS_MeshCell::toVtkType( entity ));
170 void SMDS_MeshCell::InitStaticMembers()
172 getCellProps( SMDSEntity_Ball );
173 toVtkOrder( SMDSEntity_Ball );
174 reverseSmdsOrder( SMDSEntity_Ball, 1 );
175 interlacedSmdsOrder( SMDSEntity_Ball, 1 );
176 fromVtkOrder( SMDSEntity_Ball );
179 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity, int theNbNodes, ... )
181 ASSERT( getCellProps( theEntity ).myNbNodes == theNbNodes ||
182 getCellProps( theEntity ).myIsPoly);
185 va_start( vl, theNbNodes );
187 vtkIdType vtkIds[ VTK_CELL_SIZE ];
188 typedef const SMDS_MeshNode* node_t;
190 const std::vector<int>& interlace = toVtkOrder( theEntity );
191 if ((int) interlace.size() == theNbNodes )
193 const SMDS_MeshNode* nodes[ VTK_CELL_SIZE ];
194 for ( int i = 0; i < theNbNodes; i++ )
195 nodes[i] = va_arg( vl, node_t );
197 for ( int i = 0; i < theNbNodes; i++ )
198 vtkIds[i] = nodes[ interlace[i] ]->GetVtkID();
202 for ( int i = 0; i < theNbNodes; i++ )
203 vtkIds[i] = va_arg( vl, node_t )->GetVtkID();
207 int vtkType = toVtkType( theEntity );
208 int vtkID = getGrid()->InsertNextLinkedCell( vtkType, theNbNodes, vtkIds );
212 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity,
213 const std::vector<const SMDS_MeshNode*>& nodes )
215 std::vector< vtkIdType > vtkIds( nodes.size() );
216 for ( size_t i = 0; i < nodes.size(); ++i )
217 vtkIds[i] = nodes[i]->GetVtkID();
219 int vtkType = toVtkType( theEntity );
220 int vtkID = getGrid()->InsertNextLinkedCell( vtkType, nodes.size(), &vtkIds[0] );
224 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity,
225 const std::vector<vtkIdType>& vtkNodeIds )
227 int vtkType = toVtkType( theEntity );
228 int vtkID = getGrid()->InsertNextLinkedCell( vtkType, vtkNodeIds.size(),
229 const_cast< vtkIdType* > ( &vtkNodeIds[0] ));
233 bool SMDS_MeshCell::ChangeNodes(const SMDS_MeshNode* nodes[], const int theNbNodes)
237 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
238 if ( theNbNodes != npts )
240 MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << theNbNodes);
243 const std::vector<int>& interlace = toVtkOrder((VTKCellType) GetVtkType() );
244 if ((int) interlace.size() != theNbNodes )
245 for ( int i = 0; i < theNbNodes; i++ )
247 pts[i] = nodes[i]->GetVtkID();
250 for ( int i = 0; i < theNbNodes; i++ )
252 pts[i] = nodes[ interlace[i] ]->GetVtkID();
258 ///////////////////////////////////////////////////////////////////////////////
259 ///Return The number of nodes owned by the current element
260 ///////////////////////////////////////////////////////////////////////////////
261 int SMDS_MeshCell::NbNodes() const
263 if ( GetVtkType() == VTK_POLYHEDRON )
264 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbNodes();
265 vtkIdType *pts, npts;
266 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
270 int SMDS_MeshCell::NbFaces() const
272 if ( GetVtkType() == VTK_POLYHEDRON )
273 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbFaces();
274 return getCellProps( GetVtkType() ).myNbFaces;
277 int SMDS_MeshCell::NbEdges() const
279 switch ( GetEntityType() )
281 case SMDSEntity_Polyhedra:
282 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbEdges();
283 case SMDSEntity_Polygon:
285 case SMDSEntity_Quad_Polygon:
286 return NbNodes() / 2;
289 return getCellProps( GetVtkType() ).myNbEdges;
292 int SMDS_MeshCell::NbCornerNodes() const
294 switch ( GetVtkType() )
297 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbCornerNodes();
300 case VTK_QUADRATIC_POLYGON:
301 return NbNodes() / 2;
304 return getCellProps( GetVtkType() ).myNbCornerNodes;
307 ///////////////////////////////////////////////////////////////////////////////
308 /// Create an iterator which iterate on nodes owned by the element.
309 ///////////////////////////////////////////////////////////////////////////////
310 SMDS_ElemIteratorPtr SMDS_MeshCell::nodesIterator() const
312 if ( GetVtkType() == VTK_POLYHEDRON )
313 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodesIterator();
315 return boost::make_shared< SMDS_VtkCellIterator<> >( GetMesh(), GetVtkID(), GetEntityType());
318 ///////////////////////////////////////////////////////////////////////////////
319 /// Create an iterator which iterate on nodes owned by the element.
320 ///////////////////////////////////////////////////////////////////////////////
321 SMDS_NodeIteratorPtr SMDS_MeshCell::nodeIterator() const
323 if ( GetVtkType() == VTK_POLYHEDRON )
324 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodeIterator();
326 return SMDS_NodeIteratorPtr
327 (new SMDS_VtkCellIterator<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
330 SMDS_NodeIteratorPtr SMDS_MeshCell::interlacedNodesIterator() const
332 bool canInterlace = ( GetType() == SMDSAbs_Face || GetType() == SMDSAbs_Edge );
333 return canInterlace ? nodesIteratorToUNV() : nodeIterator();
336 SMDS_NodeIteratorPtr SMDS_MeshCell::nodesIteratorToUNV() const
338 return SMDS_NodeIteratorPtr
339 (new SMDS_VtkCellIteratorToUNV<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
342 SMDSAbs_ElementType SMDS_MeshCell::GetType() const
344 return getCellProps( GetVtkType() ).myType;
347 SMDSAbs_EntityType SMDS_MeshCell::GetEntityType() const
349 return toSmdsType( (VTKCellType) GetVtkType() );
352 SMDSAbs_GeometryType SMDS_MeshCell::GetGeomType() const
354 return getCellProps( GetVtkType() ).myGeom;
357 VTKCellType SMDS_MeshCell::GetVtkType() const
359 return (VTKCellType) getGrid()->GetCellType( GetVtkID() );
362 bool SMDS_MeshCell::IsPoly() const
364 return getCellProps( GetVtkType() ).myIsPoly;
367 bool SMDS_MeshCell::IsQuadratic() const
369 return getCellProps( GetVtkType() ).myIsQuadratic;
372 const SMDS_MeshNode* SMDS_MeshCell::GetNode(const int ind) const
374 if ( GetVtkType() == VTK_POLYHEDRON )
375 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNode( ind );
377 vtkIdType npts, *pts;
378 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
379 const std::vector<int>& interlace = SMDS_MeshCell::fromVtkOrder( VTKCellType( GetVtkType() ));
380 return GetMesh()->FindNodeVtk( pts[ interlace.empty() ? ind : interlace[ ind ]]);
383 int SMDS_MeshCell::GetNodeIndex( const SMDS_MeshNode* node ) const
385 if ( GetVtkType() == VTK_POLYHEDRON )
386 return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNodeIndex( node );
388 vtkIdType npts, *pts;
389 getGrid()->GetCellPoints( GetVtkID(), npts, pts );
390 for ( vtkIdType i = 0; i < npts; ++i )
391 if ( pts[i] == node->GetVtkID() )
393 const std::vector<int>& interlace = SMDS_MeshCell::toVtkOrder( VTKCellType( GetVtkType() ));
394 return interlace.empty() ? i : interlace[i];
399 //================================================================================
401 * \brief Return VTKCellType corresponding to SMDSAbs_EntityType
403 //================================================================================
405 VTKCellType SMDS_MeshCell::toVtkType (SMDSAbs_EntityType smdsType)
407 static std::vector< VTKCellType > vtkTypes;
408 if ( vtkTypes.empty() )
410 vtkTypes.resize( SMDSEntity_Last+1, VTK_EMPTY_CELL );
411 vtkTypes[ SMDSEntity_Node ] = VTK_VERTEX;
412 vtkTypes[ SMDSEntity_0D ] = VTK_VERTEX;
413 vtkTypes[ SMDSEntity_Edge ] = VTK_LINE;
414 vtkTypes[ SMDSEntity_Quad_Edge ] = VTK_QUADRATIC_EDGE;
415 vtkTypes[ SMDSEntity_Triangle ] = VTK_TRIANGLE;
416 vtkTypes[ SMDSEntity_Quad_Triangle ] = VTK_QUADRATIC_TRIANGLE;
417 vtkTypes[ SMDSEntity_BiQuad_Triangle ] = VTK_BIQUADRATIC_TRIANGLE;
418 vtkTypes[ SMDSEntity_Quadrangle ] = VTK_QUAD;
419 vtkTypes[ SMDSEntity_Quad_Quadrangle ] = VTK_QUADRATIC_QUAD;
420 vtkTypes[ SMDSEntity_BiQuad_Quadrangle ] = VTK_BIQUADRATIC_QUAD;
421 vtkTypes[ SMDSEntity_Polygon ] = VTK_POLYGON;
422 vtkTypes[ SMDSEntity_Quad_Polygon ] = VTK_QUADRATIC_POLYGON;
423 vtkTypes[ SMDSEntity_Tetra ] = VTK_TETRA;
424 vtkTypes[ SMDSEntity_Quad_Tetra ] = VTK_QUADRATIC_TETRA;
425 vtkTypes[ SMDSEntity_Pyramid ] = VTK_PYRAMID;
426 vtkTypes[ SMDSEntity_Quad_Pyramid ] = VTK_QUADRATIC_PYRAMID;
427 vtkTypes[ SMDSEntity_Hexa ] = VTK_HEXAHEDRON;
428 vtkTypes[ SMDSEntity_Quad_Hexa ] = VTK_QUADRATIC_HEXAHEDRON;
429 vtkTypes[ SMDSEntity_TriQuad_Hexa ] = VTK_TRIQUADRATIC_HEXAHEDRON;
430 vtkTypes[ SMDSEntity_Penta ] = VTK_WEDGE;
431 vtkTypes[ SMDSEntity_Quad_Penta ] = VTK_QUADRATIC_WEDGE;
432 vtkTypes[ SMDSEntity_BiQuad_Penta ] = VTK_BIQUADRATIC_QUADRATIC_WEDGE;
433 vtkTypes[ SMDSEntity_Hexagonal_Prism ] = VTK_HEXAGONAL_PRISM;
434 vtkTypes[ SMDSEntity_Polyhedra ] = VTK_POLYHEDRON;
435 //vtkTypes[ SMDSEntity_Quad_Polyhedra ] = ;
436 vtkTypes[ SMDSEntity_Ball ] = VTK_POLY_VERTEX;
438 return vtkTypes[ smdsType ];
441 //================================================================================
443 * \brief Return indices to transform cell connectivity from SMDS to VTK
444 * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
446 //================================================================================
448 const std::vector< int >& SMDS_MeshCell::toVtkOrder(SMDSAbs_EntityType smdsType)
450 static std::vector< std::vector< int > > toVtkInterlaces;
451 if ( toVtkInterlaces.empty() )
453 toVtkInterlaces.resize( SMDSEntity_Last+1 );
455 // const int ids[] = {0};
456 // toVtkInterlaces[SMDSEntity_0D].assign( &ids[0], &ids[0]+1 );
457 // toVtkInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
460 // const int ids[] = {0,1};
461 // toVtkInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
464 // const int ids[] = {0,1,2};
465 // toVtkInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
468 // const int ids[] = {0,1,2};
469 // toVtkInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
472 // const int ids[] = {0,1,2,3,4,5};
473 // toVtkInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
476 // const int ids[] = {0,1,2,3};
477 // toVtkInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
480 // const int ids[] = {0,1,2,3,4,5,6,7};
481 // toVtkInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
484 // const int ids[] = {0,1,2,3,4,5,6,7,8};
485 // toVtkInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
488 const int ids[] = {0,2,1,3};
489 toVtkInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
492 const int ids[] = {0,2,1,3,6,5,4,7,9,8};
493 toVtkInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
496 const int ids[] = {0,3,2,1,4};
497 toVtkInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
500 const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
501 toVtkInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
504 const int ids[] = {0,3,2,1,4,7,6,5};
505 toVtkInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
508 const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
509 toVtkInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
512 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};
513 toVtkInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
516 const int ids[] = {0,1,2,3,4,5};
517 toVtkInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
520 const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}; // TODO: check
521 toVtkInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
524 const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};// TODO: check
525 toVtkInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
528 const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
529 toVtkInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
532 return toVtkInterlaces[smdsType];
535 //================================================================================
537 * \brief Return indices to reverse an SMDS cell of given type.
538 * nbNodes is useful for polygons
539 * Usage: reverseIDs[i] = forwardIDs[ indices[ i ]]
541 //================================================================================
543 const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType,
544 const size_t nbNodes)
546 static std::vector< std::vector< int > > reverseInterlaces;
547 if ( reverseInterlaces.empty() )
549 reverseInterlaces.resize( SMDSEntity_Last+1 );
551 const int ids[] = {0};
552 reverseInterlaces[SMDSEntity_0D].assign( &ids[0], &ids[0]+1 );
553 reverseInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
554 reverseInterlaces[SMDSEntity_Ball].assign( &ids[0], &ids[0]+1 );
557 const int ids[] = {1,0};
558 reverseInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
561 const int ids[] = {1,0,2};
562 reverseInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
565 const int ids[] = {0,2,1};
566 reverseInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
569 const int ids[] = {0,2,1,5,4,3};
570 reverseInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
573 const int ids[] = {0,2,1,5,4,3,6};
574 reverseInterlaces[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
577 const int ids[] = {0,3,2,1};
578 reverseInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
581 const int ids[] = {0,3,2,1,7,6,5,4};
582 reverseInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
585 const int ids[] = {0,3,2,1,7,6,5,4,8};
586 reverseInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
589 const int ids[] = {0,2,1,3};
590 reverseInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
593 const int ids[] = {0,2,1,3,6,5,4,7,9,8};
594 reverseInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
597 const int ids[] = {0,3,2,1,4};
598 reverseInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
601 const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
602 reverseInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
605 const int ids[] = {0,3,2,1,4,7,6,5};
606 reverseInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
609 const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
610 reverseInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
613 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};
614 reverseInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
617 const int ids[] = {0,2,1,3,5,4};
618 reverseInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
621 const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13};
622 reverseInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
625 const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13,15,16,17};
626 reverseInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
629 const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
630 reverseInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
634 if ( smdsType == SMDSEntity_Polygon )
636 if ( reverseInterlaces[ smdsType ].size() != nbNodes )
638 reverseInterlaces[ smdsType ].resize( nbNodes );
639 for ( size_t i = 0; i < nbNodes; ++i )
640 reverseInterlaces[ smdsType ][i] = nbNodes - i - 1;
643 else if ( smdsType == SMDSEntity_Quad_Polygon )
645 if ( reverseInterlaces[ smdsType ].size() != nbNodes )
647 // e.g. for 8 nodes: [ 0, 3,2,1, 7,6,5,4 ]
648 reverseInterlaces[ smdsType ].resize( nbNodes );
650 reverseInterlaces[ smdsType ][pos++] = 0;
651 for ( int i = nbNodes / 2 - 1; i > 0 ; --i ) // 3,2,1
652 reverseInterlaces[ smdsType ][pos++] = i;
653 for ( int i = nbNodes - 1, nb = nbNodes / 2; i >= nb; --i ) // 7,6,5,4
654 reverseInterlaces[ smdsType ][pos++] = i;
658 return reverseInterlaces[smdsType];
661 //================================================================================
663 * \brief Return indices to set nodes of a quadratic 1D or 2D element in interlaced order
664 * Usage: interlacedIDs[i] = smdsIDs[ indices[ i ]]
666 //================================================================================
668 const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
669 const size_t nbNodes)
671 static std::vector< std::vector< int > > interlace;
672 if ( interlace.empty() )
674 interlace.resize( SMDSEntity_Last+1 );
676 const int ids[] = {0,2,1};
677 interlace[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
680 const int ids[] = {0,3,1,4,2,5,6};
681 interlace[SMDSEntity_Quad_Triangle ].assign( &ids[0], &ids[0]+6 );
682 interlace[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
685 const int ids[] = {0,4,1,5,2,6,3,7,8};
686 interlace[SMDSEntity_Quad_Quadrangle ].assign( &ids[0], &ids[0]+8 );
687 interlace[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
691 if ( smdsType == SMDSEntity_Quad_Polygon )
693 if ( interlace[smdsType].size() != nbNodes )
695 interlace[smdsType].resize( nbNodes );
696 for ( size_t i = 0; i < nbNodes / 2; ++i )
698 interlace[smdsType][i*2+0] = i;
699 interlace[smdsType][i*2+1] = i + nbNodes / 2;
703 return interlace[smdsType];
706 //================================================================================
708 * \brief Return SMDSAbs_EntityType corresponding to VTKCellType
710 //================================================================================
712 SMDSAbs_EntityType SMDS_MeshCell::toSmdsType(VTKCellType vtkType)
714 return getCellProps( vtkType ).myEntity;
717 //================================================================================
719 * \brief Return SMDSAbs_ElementType by SMDSAbs_GeometryType
721 //================================================================================
723 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_GeometryType geomType)
725 switch ( geomType ) {
726 case SMDSGeom_POINT: return SMDSAbs_0DElement;
728 case SMDSGeom_EDGE: return SMDSAbs_Edge;
730 case SMDSGeom_TRIANGLE:
731 case SMDSGeom_QUADRANGLE:
732 case SMDSGeom_POLYGON: return SMDSAbs_Face;
735 case SMDSGeom_PYRAMID:
738 case SMDSGeom_HEXAGONAL_PRISM:
739 case SMDSGeom_POLYHEDRA: return SMDSAbs_Volume;
741 case SMDSGeom_BALL: return SMDSAbs_Ball;
743 case SMDSGeom_NONE: ;
748 //================================================================================
750 * \brief Return SMDSAbs_ElementType by SMDSAbs_EntityType
752 //================================================================================
754 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_EntityType entityType)
756 return getCellProps( entityType ).myType;
759 SMDSAbs_GeometryType SMDS_MeshCell::GeomType( SMDSAbs_EntityType entityType )
761 return getCellProps( entityType ).myGeom;
764 bool SMDS_MeshCell::IsPoly( SMDSAbs_EntityType entityType )
766 return getCellProps( entityType ).myIsPoly;
769 bool SMDS_MeshCell::IsQuadratic( SMDSAbs_EntityType entityType )
771 return getCellProps( entityType ).myIsQuadratic;
774 int SMDS_MeshCell::NbCornerNodes( SMDSAbs_EntityType entityType )
776 return getCellProps( entityType ).myNbCornerNodes;
779 int SMDS_MeshCell::NbNodes( SMDSAbs_EntityType entityType )
781 return getCellProps( entityType ).myNbNodes;
784 int SMDS_MeshCell::NbEdges( SMDSAbs_EntityType entityType )
786 return getCellProps( entityType ).myNbEdges;
789 int SMDS_MeshCell::NbFaces( SMDSAbs_EntityType entityType )
791 return getCellProps( entityType ).myNbFaces;
794 //================================================================================
796 * \brief Return indices to transform cell connectivity from VTK to SMDS
797 * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
799 //================================================================================
801 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(SMDSAbs_EntityType smdsType)
803 static std::vector< std::vector<int> > fromVtkInterlaces;
804 if ( fromVtkInterlaces.empty() )
806 fromVtkInterlaces.resize( SMDSEntity_Last+1 );
807 for ( int iSMDS = 0; iSMDS < SMDSEntity_Last; ++iSMDS )
809 const std::vector<int> & toVtk = toVtkOrder( SMDSAbs_EntityType( iSMDS ));
810 std::vector<int> & toSmds = fromVtkInterlaces[ iSMDS ];
811 toSmds.resize( toVtk.size() );
812 for ( size_t i = 0; i < toVtk.size(); ++i )
813 toSmds[ toVtk[i] ] = i;
816 return fromVtkInterlaces[ smdsType ];
819 //================================================================================
821 * \brief Return indices to transform cell connectivity from SMDS to VTK
822 * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
824 //================================================================================
826 const std::vector<int>& SMDS_MeshCell::toVtkOrder(VTKCellType vtkType)
828 return toVtkOrder( toSmdsType( vtkType ));
831 //================================================================================
833 * \brief Return indices to transform cell connectivity from VTK to SMDS
834 * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
836 //================================================================================
838 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(VTKCellType vtkType)
840 return fromVtkOrder( toSmdsType( vtkType ));