Salome HOME
7ee9c920811b5e1cfd7ed65c6c765833bb89e53a
[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
22 #include "SMDS_Mesh.hxx"
23 #include "SMDS_VtkCellIterator.hxx"
24
25 #include <utilities.h>
26
27 #include <vtkCell.h>
28
29 #include <cstdarg>
30
31 #include <boost/make_shared.hpp>
32
33 namespace
34 {
35   /*!
36    * \brief Cell type features
37    */
38   struct CellProps
39   {
40     SMDSAbs_EntityType   myEntity;
41     SMDSAbs_ElementType  myType;
42     SMDSAbs_GeometryType myGeom;
43     bool                 myIsPoly;
44     bool                 myIsQuadratic;
45     int                  myNbCornerNodes;
46     int                  myNbNodes;
47     int                  myNbEdges;
48     int                  myNbFaces;
49
50     CellProps() :
51       myEntity( SMDSEntity_Last ), myType( SMDSAbs_All ), myGeom( SMDSGeom_NONE ),
52       myIsPoly( 0 ), myNbCornerNodes( 0 ),
53       myNbNodes( 0 ), myNbEdges( 0 ), myNbFaces ( 0 )
54     {
55     }
56     void Set( SMDSAbs_EntityType   Entity,
57               SMDSAbs_ElementType  Type,
58               SMDSAbs_GeometryType Geom,
59               bool                 IsPoly,
60               int                  NbCornerNodes,
61               int                  NbNodes,
62               int                  NbEdges,
63               int                  NbFaces)
64     {
65       myEntity        = Entity;
66       myType          = Type;
67       myGeom          = Geom;
68       myIsPoly        = IsPoly;
69       myIsQuadratic   = ( NbNodes > NbCornerNodes );
70       myNbCornerNodes = NbCornerNodes;
71       myNbNodes       = NbNodes;
72       myNbEdges       = NbEdges;
73       myNbFaces       = NbFaces;
74     }
75   };
76
77   //! return vector a CellProps
78   const CellProps& getCellProps( VTKCellType vtkType )
79   {
80     static std::vector< CellProps > theCellProps;
81     if ( theCellProps.empty() )
82     {
83       theCellProps.resize( VTK_NUMBER_OF_CELL_TYPES );
84       CellProps* p = & theCellProps[0];
85       p[ VTK_VERTEX ].
86         Set( SMDSEntity_0D, SMDSAbs_0DElement, SMDSGeom_POINT,
87              /*isPoly=*/0,/*nbCN=*/1,/*nbN=*/1,/*nbE=*/0,/*nbF=*/0 );
88       p[ VTK_LINE ].
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 );
94       p[ VTK_TRIANGLE ].
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 );
103       p[ VTK_QUAD].
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 );
112       p[ VTK_POLYGON ].
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 );
118       p[ VTK_TETRA ].
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 );
124       p[ VTK_PYRAMID ].
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 );
130       p[ VTK_HEXAHEDRON ].
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 );
139       p[ VTK_WEDGE ].
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 );
151       p[ VTK_POLYHEDRON ].
152         Set( SMDSEntity_Polyhedra, SMDSAbs_Volume, SMDSGeom_POLYHEDRA,
153              /*isPoly=*/1,/*nbCN=*/-1,/*nbN=*/-1,/*nbE=*/-1,/*nbF=*/-1 );
154       p[ VTK_POLY_VERTEX].
155         Set( SMDSEntity_Ball, SMDSAbs_Ball, SMDSGeom_BALL,
156              /*isPoly=*/0,/*nbCN=*/1,/*nbN=*/1,/*nbE=*/0,/*nbF=*/0 );
157     }
158     return theCellProps[ vtkType ];
159
160   } // getCellProps()
161
162   //! return vector a CellProps
163   const CellProps& getCellProps( SMDSAbs_EntityType entity )
164   {
165     return getCellProps( SMDS_MeshCell::toVtkType( entity ));
166   }
167   
168 } // namespace
169
170 void SMDS_MeshCell::InitStaticMembers()
171 {
172   getCellProps( SMDSEntity_Ball );
173   toVtkOrder( SMDSEntity_Ball );
174   reverseSmdsOrder( SMDSEntity_Ball, 1 );
175   interlacedSmdsOrder( SMDSEntity_Ball, 1 );
176   fromVtkOrder( SMDSEntity_Ball );
177 }
178
179 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity, int theNbNodes, ... )
180 {
181   ASSERT( getCellProps( theEntity ).myNbNodes == theNbNodes ||
182           getCellProps( theEntity ).myIsPoly);
183
184   va_list vl;
185   va_start( vl, theNbNodes );
186
187   vtkIdType vtkIds[ VTK_CELL_SIZE ];
188   typedef const SMDS_MeshNode* node_t;
189
190   const std::vector<int>& interlace = toVtkOrder( theEntity );
191   if ((int) interlace.size() == theNbNodes )
192   {
193     const SMDS_MeshNode* nodes[ VTK_CELL_SIZE ];
194     for ( int i = 0; i < theNbNodes; i++ )
195       nodes[i] = va_arg( vl, node_t );
196
197     for ( int i = 0; i < theNbNodes; i++ )
198       vtkIds[i] = nodes[ interlace[i] ]->GetVtkID();
199   }
200   else
201   {
202     for ( int i = 0; i < theNbNodes; i++ )
203       vtkIds[i] = va_arg( vl, node_t )->GetVtkID();
204   }
205   va_end( vl );
206
207   int vtkType = toVtkType( theEntity );
208   int   vtkID = getGrid()->InsertNextLinkedCell( vtkType, theNbNodes, vtkIds );
209   setVtkID( vtkID );
210 }
211
212 void SMDS_MeshCell::init( SMDSAbs_EntityType                       theEntity,
213                           const std::vector<const SMDS_MeshNode*>& nodes )
214 {
215   std::vector< vtkIdType > vtkIds( nodes.size() );
216   for ( size_t i = 0; i < nodes.size(); ++i )
217     vtkIds[i] = nodes[i]->GetVtkID();
218
219   int vtkType = toVtkType( theEntity );
220   int   vtkID = getGrid()->InsertNextLinkedCell( vtkType, nodes.size(), &vtkIds[0] );
221   setVtkID( vtkID );
222 }
223
224 void SMDS_MeshCell::init( SMDSAbs_EntityType            theEntity,
225                           const std::vector<vtkIdType>& vtkNodeIds )
226 {
227   int vtkType = toVtkType( theEntity );
228   int   vtkID = getGrid()->InsertNextLinkedCell( vtkType, vtkNodeIds.size(),
229                                                  const_cast< vtkIdType* > ( &vtkNodeIds[0] ));
230   setVtkID( vtkID );
231 }
232
233 bool SMDS_MeshCell::ChangeNodes(const SMDS_MeshNode* nodes[], const int theNbNodes)
234 {
235   vtkIdType npts = 0;
236   vtkIdType* pts = 0;
237   getGrid()->GetCellPoints( GetVtkID(), npts, pts );
238   if ( theNbNodes != npts )
239   {
240     MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << theNbNodes);
241     return false;
242   }
243   const std::vector<int>& interlace = toVtkOrder((VTKCellType) GetVtkType() );
244   if ((int) interlace.size() != theNbNodes )
245     for ( int i = 0; i < theNbNodes; i++ )
246     {
247       pts[i] = nodes[i]->GetVtkID();
248     }
249   else
250     for ( int i = 0; i < theNbNodes; i++ )
251     {
252       pts[i] = nodes[ interlace[i] ]->GetVtkID();
253     }
254
255   return true;
256 }
257
258 ///////////////////////////////////////////////////////////////////////////////
259 ///Return The number of nodes owned by the current element
260 ///////////////////////////////////////////////////////////////////////////////
261 int SMDS_MeshCell::NbNodes() const
262 {
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 );
267   return npts;
268 }
269
270 int SMDS_MeshCell::NbFaces() const
271 {
272   if ( GetVtkType() == VTK_POLYHEDRON )
273     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbFaces();
274   return getCellProps( GetVtkType() ).myNbFaces;
275 }
276
277 int SMDS_MeshCell::NbEdges() const
278 {
279   switch ( GetEntityType() )
280   {
281   case SMDSEntity_Polyhedra:
282     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbEdges();
283   case SMDSEntity_Polygon:
284     return NbNodes();
285   case SMDSEntity_Quad_Polygon:
286     return NbNodes() / 2;
287   default:;
288   }
289   return getCellProps( GetVtkType() ).myNbEdges;
290 }
291
292 int SMDS_MeshCell::NbCornerNodes() const
293 {
294   switch ( GetVtkType() )
295   {
296   case VTK_POLYHEDRON:
297     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbCornerNodes();
298   case VTK_POLYGON:
299     return NbNodes();
300   case VTK_QUADRATIC_POLYGON:
301     return NbNodes() / 2;
302   default:;
303   }
304   return getCellProps( GetVtkType() ).myNbCornerNodes;
305 }
306
307 ///////////////////////////////////////////////////////////////////////////////
308 /// Create an iterator which iterate on nodes owned by the element.
309 ///////////////////////////////////////////////////////////////////////////////
310 SMDS_ElemIteratorPtr SMDS_MeshCell::nodesIterator() const
311 {
312   if ( GetVtkType() == VTK_POLYHEDRON )
313     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodesIterator();
314
315   return boost::make_shared< SMDS_VtkCellIterator<> >( GetMesh(), GetVtkID(), GetEntityType());
316 }
317
318 ///////////////////////////////////////////////////////////////////////////////
319 /// Create an iterator which iterate on nodes owned by the element.
320 ///////////////////////////////////////////////////////////////////////////////
321 SMDS_NodeIteratorPtr SMDS_MeshCell::nodeIterator() const
322 {
323   if ( GetVtkType() == VTK_POLYHEDRON )
324     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodeIterator();
325
326   return SMDS_NodeIteratorPtr
327     (new SMDS_VtkCellIterator<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
328 }
329
330 SMDS_NodeIteratorPtr SMDS_MeshCell::interlacedNodesIterator() const
331 {
332   bool canInterlace = ( GetType() == SMDSAbs_Face || GetType() == SMDSAbs_Edge );
333   return canInterlace ? nodesIteratorToUNV() : nodeIterator();
334 }
335
336 SMDS_NodeIteratorPtr SMDS_MeshCell::nodesIteratorToUNV() const
337 {
338   return SMDS_NodeIteratorPtr
339     (new SMDS_VtkCellIteratorToUNV<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
340 }
341
342 SMDSAbs_ElementType SMDS_MeshCell::GetType() const
343 {
344   return getCellProps( GetVtkType() ).myType;
345 }
346
347 SMDSAbs_EntityType SMDS_MeshCell::GetEntityType() const
348 {
349   return toSmdsType( (VTKCellType) GetVtkType() );
350 }
351
352 SMDSAbs_GeometryType SMDS_MeshCell::GetGeomType() const
353 {
354   return getCellProps( GetVtkType() ).myGeom;
355 }
356
357 VTKCellType SMDS_MeshCell::GetVtkType() const
358 {
359   return (VTKCellType) getGrid()->GetCellType( GetVtkID() );
360 }
361
362 bool SMDS_MeshCell::IsPoly() const
363 {
364   return getCellProps( GetVtkType() ).myIsPoly;
365 }
366
367 bool SMDS_MeshCell::IsQuadratic() const
368 {
369   return getCellProps( GetVtkType() ).myIsQuadratic;
370 }
371
372 const SMDS_MeshNode* SMDS_MeshCell::GetNode(const int ind) const
373 {
374   if ( GetVtkType() == VTK_POLYHEDRON )
375     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNode( ind );
376
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 ]]);
381 }
382
383 int SMDS_MeshCell::GetNodeIndex( const SMDS_MeshNode* node ) const
384 {
385   if ( GetVtkType() == VTK_POLYHEDRON )
386     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNodeIndex( node );
387
388   vtkIdType npts, *pts;
389   getGrid()->GetCellPoints( GetVtkID(), npts, pts );
390   for ( vtkIdType i = 0; i < npts; ++i )
391     if ( pts[i] == node->GetVtkID() )
392     {
393       const std::vector<int>& interlace = SMDS_MeshCell::toVtkOrder( VTKCellType( GetVtkType() ));
394       return interlace.empty() ? i : interlace[i];
395     }
396   return -1;
397 }
398
399 //================================================================================
400 /*!
401  * \brief Return VTKCellType corresponding to SMDSAbs_EntityType
402  */
403 //================================================================================
404
405 VTKCellType SMDS_MeshCell::toVtkType (SMDSAbs_EntityType smdsType)
406 {
407   static std::vector< VTKCellType > vtkTypes;
408   if ( vtkTypes.empty() )
409   {
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;
437   }
438   return vtkTypes[ smdsType ];
439 }
440
441 //================================================================================
442 /*!
443  * \brief Return indices to transform cell connectivity from SMDS to VTK
444  * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
445  */
446 //================================================================================
447
448 const std::vector< int >& SMDS_MeshCell::toVtkOrder(SMDSAbs_EntityType smdsType)
449 {
450   static std::vector< std::vector< int > > toVtkInterlaces;
451   if ( toVtkInterlaces.empty() )
452   {
453     toVtkInterlaces.resize( SMDSEntity_Last+1 );
454     // {
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 );
458     // }
459     // {
460     //   const int ids[] = {0,1};
461     //   toVtkInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
462     // }
463     // {
464     //   const int ids[] = {0,1,2};
465     //   toVtkInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
466     // }
467     // {
468     //   const int ids[] = {0,1,2};
469     //   toVtkInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
470     // }
471     // {
472     //   const int ids[] = {0,1,2,3,4,5};
473     //   toVtkInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
474     // }
475     // {
476     //   const int ids[] = {0,1,2,3};
477     //   toVtkInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
478     // }
479     // {
480     //   const int ids[] = {0,1,2,3,4,5,6,7};
481     //   toVtkInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
482     // }
483     // {
484     //   const int ids[] = {0,1,2,3,4,5,6,7,8};
485     //   toVtkInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
486     // }
487     {
488       const int ids[] = {0,2,1,3};
489       toVtkInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
490     }
491     {
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 );
494     }
495     {
496       const int ids[] = {0,3,2,1,4};
497       toVtkInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
498     }
499     {
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 );
502     }
503     {
504       const int ids[] = {0,3,2,1,4,7,6,5};
505       toVtkInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
506     }
507     {
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 );
510     }
511     {
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 );
514     }
515     {
516       const int ids[] = {0,1,2,3,4,5};
517       toVtkInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
518     }
519     {
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 );
522     }
523     {
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 );
526     }
527     {
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 );
530     }
531   }
532   return toVtkInterlaces[smdsType];
533 }
534
535 //================================================================================
536 /*!
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 ]]
540  */
541 //================================================================================
542
543 const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType,
544                                                         const size_t       nbNodes)
545 {
546   static std::vector< std::vector< int > > reverseInterlaces;
547   if ( reverseInterlaces.empty() )
548   {
549     reverseInterlaces.resize( SMDSEntity_Last+1 );
550     {
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 );
555     }
556     {
557       const int ids[] = {1,0};
558       reverseInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
559     }
560     {
561       const int ids[] = {1,0,2};
562       reverseInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
563     }
564     {
565       const int ids[] = {0,2,1};
566       reverseInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
567     }
568     {
569       const int ids[] = {0,2,1,5,4,3};
570       reverseInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
571     }
572     {
573       const int ids[] = {0,2,1,5,4,3,6};
574       reverseInterlaces[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
575     }
576     {
577       const int ids[] = {0,3,2,1};
578       reverseInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
579     }
580     {
581       const int ids[] = {0,3,2,1,7,6,5,4};
582       reverseInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
583     }
584     {
585       const int ids[] = {0,3,2,1,7,6,5,4,8};
586       reverseInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
587     }
588     {
589       const int ids[] = {0,2,1,3};
590       reverseInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
591     }
592     {
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 );
595     }
596     {
597       const int ids[] = {0,3,2,1,4};
598       reverseInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
599     }
600     {
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 );
603     }
604     {
605       const int ids[] = {0,3,2,1,4,7,6,5};
606       reverseInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
607     }
608     {
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 );
611     }
612     {
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 );
615     }
616     {
617       const int ids[] = {0,2,1,3,5,4};
618       reverseInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
619     }
620     {
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 );
623     }
624     {
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 );
627     }
628     {
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 );
631     }
632   }
633
634   if ( smdsType == SMDSEntity_Polygon )
635   {
636     if ( reverseInterlaces[ smdsType ].size() != nbNodes )
637     {
638       reverseInterlaces[ smdsType ].resize( nbNodes );
639       for ( size_t i = 0; i < nbNodes; ++i )
640         reverseInterlaces[ smdsType ][i] = nbNodes - i - 1;
641     }
642   }
643   else if ( smdsType == SMDSEntity_Quad_Polygon )
644   {
645     if ( reverseInterlaces[ smdsType ].size() != nbNodes )
646     {
647       // e.g. for 8 nodes: [ 0, 3,2,1, 7,6,5,4 ]
648       reverseInterlaces[ smdsType ].resize( nbNodes );
649       size_t pos = 0;
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;
655     }
656   }
657   
658   return reverseInterlaces[smdsType];
659 }
660
661 //================================================================================
662 /*!
663  * \brief Return indices to set nodes of a quadratic 1D or 2D element in interlaced order
664  * Usage: interlacedIDs[i] = smdsIDs[ indices[ i ]]
665  */
666 //================================================================================
667
668 const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
669                                                            const size_t       nbNodes)
670 {
671   static std::vector< std::vector< int > > interlace;
672   if ( interlace.empty() )
673   {
674     interlace.resize( SMDSEntity_Last+1 );
675     {
676       const int ids[] = {0,2,1};
677       interlace[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
678     }
679     {
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 );
683     }
684     {
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 );
688     }
689   }
690
691   if ( smdsType == SMDSEntity_Quad_Polygon )
692   {
693     if ( interlace[smdsType].size() != nbNodes )
694     {
695       interlace[smdsType].resize( nbNodes );
696       for ( size_t i = 0; i < nbNodes / 2; ++i )
697       {
698         interlace[smdsType][i*2+0] = i;
699         interlace[smdsType][i*2+1] = i + nbNodes / 2;
700       }
701     }
702   }
703   return interlace[smdsType];
704 }
705
706 //================================================================================
707 /*!
708  * \brief Return SMDSAbs_EntityType corresponding to VTKCellType
709  */
710 //================================================================================
711
712 SMDSAbs_EntityType SMDS_MeshCell::toSmdsType(VTKCellType vtkType)
713 {
714   return getCellProps( vtkType ).myEntity;
715 }
716
717 //================================================================================
718 /*!
719  * \brief Return SMDSAbs_ElementType by SMDSAbs_GeometryType
720  */
721 //================================================================================
722
723 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_GeometryType geomType)
724 {
725   switch ( geomType ) {
726   case SMDSGeom_POINT:     return SMDSAbs_0DElement;
727
728   case SMDSGeom_EDGE:      return SMDSAbs_Edge; 
729
730   case SMDSGeom_TRIANGLE:
731   case SMDSGeom_QUADRANGLE:
732   case SMDSGeom_POLYGON:   return SMDSAbs_Face;
733
734   case SMDSGeom_TETRA:
735   case SMDSGeom_PYRAMID:
736   case SMDSGeom_HEXA:
737   case SMDSGeom_PENTA:
738   case SMDSGeom_HEXAGONAL_PRISM:
739   case SMDSGeom_POLYHEDRA: return SMDSAbs_Volume;
740
741   case SMDSGeom_BALL:      return SMDSAbs_Ball;
742
743   case SMDSGeom_NONE: ;
744   }
745   return SMDSAbs_All;
746 }
747
748 //================================================================================
749 /*!
750  * \brief Return SMDSAbs_ElementType by SMDSAbs_EntityType
751  */
752 //================================================================================
753
754 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_EntityType entityType)
755 {
756   return getCellProps( entityType ).myType;
757 }
758
759 SMDSAbs_GeometryType SMDS_MeshCell::GeomType( SMDSAbs_EntityType entityType )
760 {
761   return getCellProps( entityType ).myGeom;
762 }
763
764 bool SMDS_MeshCell::IsPoly( SMDSAbs_EntityType entityType )
765 {
766   return getCellProps( entityType ).myIsPoly;
767 }
768
769 bool SMDS_MeshCell::IsQuadratic( SMDSAbs_EntityType entityType )
770 {
771   return getCellProps( entityType ).myIsQuadratic;
772 }
773
774 int SMDS_MeshCell::NbCornerNodes( SMDSAbs_EntityType entityType )
775 {
776   return getCellProps( entityType ).myNbCornerNodes;
777 }
778
779 int SMDS_MeshCell::NbNodes( SMDSAbs_EntityType entityType )
780 {
781   return getCellProps( entityType ).myNbNodes;
782 }
783
784 int SMDS_MeshCell::NbEdges( SMDSAbs_EntityType entityType )
785 {
786   return getCellProps( entityType ).myNbEdges;
787 }
788
789 int SMDS_MeshCell::NbFaces( SMDSAbs_EntityType entityType )
790 {
791   return getCellProps( entityType ).myNbFaces;
792 }
793
794 //================================================================================
795 /*!
796  * \brief Return indices to transform cell connectivity from VTK to SMDS
797  * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
798  */
799 //================================================================================
800
801 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(SMDSAbs_EntityType smdsType)
802 {
803   static std::vector< std::vector<int> > fromVtkInterlaces;
804   if ( fromVtkInterlaces.empty() )
805   {
806     fromVtkInterlaces.resize( SMDSEntity_Last+1 );
807     for ( int iSMDS = 0; iSMDS < SMDSEntity_Last; ++iSMDS )
808     {
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;
814     }
815   }
816   return fromVtkInterlaces[ smdsType ];
817 }
818
819 //================================================================================
820 /*!
821  * \brief Return indices to transform cell connectivity from SMDS to VTK
822  * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
823  */
824 //================================================================================
825
826 const std::vector<int>& SMDS_MeshCell::toVtkOrder(VTKCellType vtkType)
827 {
828   return toVtkOrder( toSmdsType( vtkType ));
829 }
830
831 //================================================================================
832 /*!
833  * \brief Return indices to transform cell connectivity from VTK to SMDS
834  * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
835  */
836 //================================================================================
837
838 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(VTKCellType vtkType)
839 {
840   return fromVtkOrder( toSmdsType( vtkType ));
841 }