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