Salome HOME
Update of CheckDone
[modules/smesh.git] / src / SMDS / SMDS_MeshCell.cxx
1 // Copyright (C) 2010-2021  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   static std::vector< CellProps > theCellProps;
78
79   //! initialize theCellProps
80   void initCellProps()
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=*/18,/*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
158   //! return vector a CellProps
159   const CellProps& getCellProps( VTKCellType vtkType )
160   {
161     return theCellProps[ vtkType ];
162   } // getCellProps()
163
164   //! return vector a CellProps
165   const CellProps& getCellProps( SMDSAbs_EntityType entity )
166   {
167     return getCellProps( SMDS_MeshCell::toVtkType( entity ));
168   }
169
170
171   static std::vector< VTKCellType > theVtkTypes; //!< VTK types by SMDS ones
172
173   void initVtkTypes()
174   {
175     theVtkTypes.resize( SMDSEntity_Last+1, VTK_EMPTY_CELL );
176     theVtkTypes[ SMDSEntity_Node ]              = VTK_VERTEX;
177     theVtkTypes[ SMDSEntity_0D ]                = VTK_VERTEX;
178     theVtkTypes[ SMDSEntity_Edge ]              = VTK_LINE;
179     theVtkTypes[ SMDSEntity_Quad_Edge ]         = VTK_QUADRATIC_EDGE;
180     theVtkTypes[ SMDSEntity_Triangle ]          = VTK_TRIANGLE;
181     theVtkTypes[ SMDSEntity_Quad_Triangle ]     = VTK_QUADRATIC_TRIANGLE;
182     theVtkTypes[ SMDSEntity_BiQuad_Triangle ]   = VTK_BIQUADRATIC_TRIANGLE;
183     theVtkTypes[ SMDSEntity_Quadrangle ]        = VTK_QUAD;
184     theVtkTypes[ SMDSEntity_Quad_Quadrangle ]   = VTK_QUADRATIC_QUAD;
185     theVtkTypes[ SMDSEntity_BiQuad_Quadrangle ] = VTK_BIQUADRATIC_QUAD;
186     theVtkTypes[ SMDSEntity_Polygon ]           = VTK_POLYGON;
187     theVtkTypes[ SMDSEntity_Quad_Polygon ]      = VTK_QUADRATIC_POLYGON;
188     theVtkTypes[ SMDSEntity_Tetra ]             = VTK_TETRA;
189     theVtkTypes[ SMDSEntity_Quad_Tetra ]        = VTK_QUADRATIC_TETRA;
190     theVtkTypes[ SMDSEntity_Pyramid ]           = VTK_PYRAMID;
191     theVtkTypes[ SMDSEntity_Quad_Pyramid ]      = VTK_QUADRATIC_PYRAMID;
192     theVtkTypes[ SMDSEntity_Hexa ]              = VTK_HEXAHEDRON;
193     theVtkTypes[ SMDSEntity_Quad_Hexa ]         = VTK_QUADRATIC_HEXAHEDRON;
194     theVtkTypes[ SMDSEntity_TriQuad_Hexa ]      = VTK_TRIQUADRATIC_HEXAHEDRON;
195     theVtkTypes[ SMDSEntity_Penta ]             = VTK_WEDGE;
196     theVtkTypes[ SMDSEntity_Quad_Penta ]        = VTK_QUADRATIC_WEDGE;
197     theVtkTypes[ SMDSEntity_BiQuad_Penta ]      = VTK_BIQUADRATIC_QUADRATIC_WEDGE;
198     theVtkTypes[ SMDSEntity_Hexagonal_Prism ]   = VTK_HEXAGONAL_PRISM;
199     theVtkTypes[ SMDSEntity_Polyhedra ]         = VTK_POLYHEDRON;
200     //theVtkTypes[ SMDSEntity_Quad_Polyhedra ]    = ;
201     theVtkTypes[ SMDSEntity_Ball ]              = VTK_POLY_VERTEX;
202   }
203
204
205   //! indices to transform cell connectivity from SMDS to VTK
206   static std::vector< std::vector< int > > theToVtkInterlaces;
207
208   void initToVtkInterlaces()
209   {
210     theToVtkInterlaces.resize( SMDSEntity_Last+1 );
211     // {
212     //   const int ids[] = {0};
213     //   theToVtkInterlaces[SMDSEntity_0D].assign( &ids[0], &ids[0]+1 );
214     //   theToVtkInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
215     // }
216     // {
217     //   const int ids[] = {0,1};
218     //   theToVtkInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
219     // }
220     // {
221     //   const int ids[] = {0,1,2};
222     //   theToVtkInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
223     // }
224     // {
225     //   const int ids[] = {0,1,2};
226     //   theToVtkInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
227     // }
228     // {
229     //   const int ids[] = {0,1,2,3,4,5};
230     //   theToVtkInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
231     // }
232     // {
233     //   const int ids[] = {0,1,2,3};
234     //   theToVtkInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
235     // }
236     // {
237     //   const int ids[] = {0,1,2,3,4,5,6,7};
238     //   theToVtkInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
239     // }
240     // {
241     //   const int ids[] = {0,1,2,3,4,5,6,7,8};
242     //   theToVtkInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
243     // }
244     {
245       const int ids[] = {0,2,1,3};
246       theToVtkInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
247     }
248     {
249       const int ids[] = {0,2,1,3,6,5,4,7,9,8};
250       theToVtkInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
251     }
252     {
253       const int ids[] = {0,3,2,1,4};
254       theToVtkInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
255     }
256     {
257       const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
258       theToVtkInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
259     }
260     {
261       const int ids[] = {0,3,2,1,4,7,6,5};
262       theToVtkInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
263     }
264     {
265       const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
266       theToVtkInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
267     }
268     {
269       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};
270       theToVtkInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
271     }
272     {
273       const int ids[] = {0,1,2,3,4,5};
274       theToVtkInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
275     }
276     {
277       const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}; // TODO: check
278       theToVtkInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
279     }
280     {
281       const int ids[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};// TODO: check
282       theToVtkInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
283     }
284     {
285       const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
286       theToVtkInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
287     }
288   }
289
290
291   //! indices to reverse an SMDS cell
292   static std::vector< std::vector< int > > theReverseInterlaces;
293
294   void initReverseInterlaces()
295   {
296     theReverseInterlaces.resize( SMDSEntity_Last+1 );
297     {
298       const int ids[] = {0};
299       theReverseInterlaces[SMDSEntity_0D  ].assign( &ids[0], &ids[0]+1 );
300       theReverseInterlaces[SMDSEntity_Node].assign( &ids[0], &ids[0]+1 );
301       theReverseInterlaces[SMDSEntity_Ball].assign( &ids[0], &ids[0]+1 );
302     }
303     {
304       const int ids[] = {1,0};
305       theReverseInterlaces[SMDSEntity_Edge].assign( &ids[0], &ids[0]+2 );
306     }
307     {
308       const int ids[] = {1,0,2};
309       theReverseInterlaces[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
310     }
311     {
312       const int ids[] = {0,2,1};
313       theReverseInterlaces[SMDSEntity_Triangle].assign( &ids[0], &ids[0]+3 );
314     }
315     {
316       const int ids[] = {0,2,1,5,4,3};
317       theReverseInterlaces[SMDSEntity_Quad_Triangle].assign( &ids[0], &ids[0]+6 );
318     }
319     {
320       const int ids[] = {0,2,1,5,4,3,6};
321       theReverseInterlaces[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
322     }
323     {
324       const int ids[] = {0,3,2,1};
325       theReverseInterlaces[SMDSEntity_Quadrangle].assign( &ids[0], &ids[0]+4 );
326     }
327     {
328       const int ids[] = {0,3,2,1,7,6,5,4};
329       theReverseInterlaces[SMDSEntity_Quad_Quadrangle].assign( &ids[0], &ids[0]+8 );
330     }
331     {
332       const int ids[] = {0,3,2,1,7,6,5,4,8};
333       theReverseInterlaces[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
334     }
335     {
336       const int ids[] = {0,2,1,3};
337       theReverseInterlaces[SMDSEntity_Tetra].assign( &ids[0], &ids[0]+4 );
338     }
339     {
340       const int ids[] = {0,2,1,3,6,5,4,7,9,8};
341       theReverseInterlaces[SMDSEntity_Quad_Tetra].assign( &ids[0], &ids[0]+10 );
342     }
343     {
344       const int ids[] = {0,3,2,1,4};
345       theReverseInterlaces[SMDSEntity_Pyramid].assign( &ids[0], &ids[0]+5 );
346     }
347     {
348       const int ids[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
349       theReverseInterlaces[SMDSEntity_Quad_Pyramid].assign( &ids[0], &ids[0]+13 );
350     }
351     {
352       const int ids[] = {0,3,2,1,4,7,6,5};
353       theReverseInterlaces[SMDSEntity_Hexa].assign( &ids[0], &ids[0]+8 );
354     }
355     {
356       const int ids[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
357       theReverseInterlaces[SMDSEntity_Quad_Hexa].assign( &ids[0], &ids[0]+20 );
358     }
359     {
360       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};
361       theReverseInterlaces[SMDSEntity_TriQuad_Hexa].assign( &ids[0], &ids[0]+27 );
362     }
363     {
364       const int ids[] = {0,2,1,3,5,4};
365       theReverseInterlaces[SMDSEntity_Penta].assign( &ids[0], &ids[0]+6 );
366     }
367     {
368       const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13};
369       theReverseInterlaces[SMDSEntity_Quad_Penta].assign( &ids[0], &ids[0]+15 );
370     }
371     {
372       const int ids[] = {0,2,1,3,5,4, 8,7,6,11,10,9,12,14,13,15,16,17};
373       theReverseInterlaces[SMDSEntity_BiQuad_Penta].assign( &ids[0], &ids[0]+18 );
374     }
375     {
376       const int ids[] = {0,5,4,3,2,1,6,11,10,9,8,7};
377       theReverseInterlaces[SMDSEntity_Hexagonal_Prism].assign( &ids[0], &ids[0]+12 );
378     }
379   }
380
381
382   //! indices to set nodes of a quadratic 1D or 2D element in interlaced order
383   static std::vector< std::vector< int > > theQuadInterlace;
384
385   void initQuadInterlace()
386   {
387     theQuadInterlace.resize( SMDSEntity_Last+1 );
388     {
389       const int ids[] = {0,2,1};
390       theQuadInterlace[SMDSEntity_Quad_Edge].assign( &ids[0], &ids[0]+3 );
391     }
392     {
393       const int ids[] = {0,3,1,4,2,5,6};
394       theQuadInterlace[SMDSEntity_Quad_Triangle  ].assign( &ids[0], &ids[0]+6 );
395       theQuadInterlace[SMDSEntity_BiQuad_Triangle].assign( &ids[0], &ids[0]+7 );
396     }
397     {
398       const int ids[] = {0,4,1,5,2,6,3,7,8};
399       theQuadInterlace[SMDSEntity_Quad_Quadrangle  ].assign( &ids[0], &ids[0]+8 );
400       theQuadInterlace[SMDSEntity_BiQuad_Quadrangle].assign( &ids[0], &ids[0]+9 );
401     }
402   }
403
404
405   //! indices to transform cell connectivity from VTK to SMDS
406   static std::vector< std::vector<int> > theFromVtkInterlaces;
407
408   void initFromVtkInterlaces()
409   {
410     theFromVtkInterlaces.resize( SMDSEntity_Last+1 );
411     for ( int iSMDS = 0; iSMDS < SMDSEntity_Last; ++iSMDS )
412     {
413       const std::vector<int> & toVtk = SMDS_MeshCell::toVtkOrder( SMDSAbs_EntityType( iSMDS ));
414       std::vector<int> &      toSmds = theFromVtkInterlaces[ iSMDS ];
415       toSmds.resize( toVtk.size() );
416       for ( size_t i = 0; i < toVtk.size(); ++i )
417         toSmds[ toVtk[i] ] = i;
418     }
419   }
420
421 } // namespace
422
423 void SMDS_MeshCell::InitStaticMembers()
424 {
425   if ( theCellProps.empty() )
426   {
427     initCellProps();
428     initVtkTypes();
429     initToVtkInterlaces();
430     initReverseInterlaces();
431     initQuadInterlace();
432     initFromVtkInterlaces();
433   }
434 }
435
436 void SMDS_MeshCell::init( SMDSAbs_EntityType theEntity, int theNbNodes, ... )
437 {
438   ASSERT( getCellProps( theEntity ).myNbNodes == theNbNodes ||
439           getCellProps( theEntity ).myIsPoly);
440
441   va_list vl;
442   va_start( vl, theNbNodes );
443
444   vtkIdType vtkIds[ VTK_CELL_SIZE ];
445   typedef const SMDS_MeshNode* node_t;
446
447   const std::vector<int>& interlace = toVtkOrder( theEntity );
448   if ((int) interlace.size() == theNbNodes )
449   {
450     const SMDS_MeshNode* nodes[ VTK_CELL_SIZE ];
451     for ( int i = 0; i < theNbNodes; i++ )
452       nodes[i] = va_arg( vl, node_t );
453
454     for ( int i = 0; i < theNbNodes; i++ )
455       vtkIds[i] = nodes[ interlace[i] ]->GetVtkID();
456   }
457   else
458   {
459     for ( int i = 0; i < theNbNodes; i++ )
460       vtkIds[i] = va_arg( vl, node_t )->GetVtkID();
461   }
462   va_end( vl );
463
464   int     vtkType = toVtkType( theEntity );
465   vtkIdType vtkID = getGrid()->InsertNextLinkedCell( vtkType, theNbNodes, vtkIds );
466   setVtkID( vtkID );
467 }
468
469 void SMDS_MeshCell::init( SMDSAbs_EntityType                       theEntity,
470                           const std::vector<const SMDS_MeshNode*>& nodes )
471 {
472   std::vector< vtkIdType > vtkIds( nodes.size() );
473   for ( size_t i = 0; i < nodes.size(); ++i )
474     vtkIds[i] = nodes[i]->GetVtkID();
475
476   int     vtkType = toVtkType( theEntity );
477   vtkIdType vtkID = getGrid()->InsertNextLinkedCell( vtkType, nodes.size(), &vtkIds[0] );
478   setVtkID( vtkID );
479 }
480
481 void SMDS_MeshCell::init( SMDSAbs_EntityType            theEntity,
482                           const std::vector<vtkIdType>& vtkNodeIds )
483 {
484   int     vtkType = toVtkType( theEntity );
485   vtkIdType vtkID = getGrid()->InsertNextLinkedCell( vtkType, vtkNodeIds.size(),
486                                                      const_cast< vtkIdType* > ( &vtkNodeIds[0] ));
487   setVtkID( vtkID );
488 }
489
490 bool SMDS_MeshCell::ChangeNodes(const SMDS_MeshNode* nodes[], const int theNbNodes)
491 {
492   vtkIdType npts = 0;
493   vtkIdType *pts(nullptr);
494   vtkIdType const *tmp(nullptr);
495   getGrid()->GetCellPoints( GetVtkID(), npts, tmp );
496   pts = const_cast<vtkIdType *>(tmp);
497   if ( theNbNodes != npts )
498   {
499     MESSAGE("ChangeNodes problem: not the same number of nodes " << npts << " -> " << theNbNodes);
500     return false;
501   }
502   const std::vector<int>& interlace = toVtkOrder((VTKCellType) GetVtkType() );
503   if ((int) interlace.size() != theNbNodes )
504     for ( int i = 0; i < theNbNodes; i++ )
505     {
506       pts[i] = nodes[i]->GetVtkID();
507     }
508   else
509     for ( int i = 0; i < theNbNodes; i++ )
510     {
511       pts[i] = nodes[ interlace[i] ]->GetVtkID();
512     }
513
514   return true;
515 }
516
517 ///////////////////////////////////////////////////////////////////////////////
518 ///Return The number of nodes owned by the current element
519 ///////////////////////////////////////////////////////////////////////////////
520 int SMDS_MeshCell::NbNodes() const
521 {
522   if ( GetVtkType() == VTK_POLYHEDRON )
523     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbNodes();
524   vtkIdType npts = getGrid()->GetCells()->GetCellSize( GetVtkID() );
525   return npts;
526 }
527
528 int SMDS_MeshCell::NbFaces() const
529 {
530   if ( GetVtkType() == VTK_POLYHEDRON )
531     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbFaces();
532   return getCellProps( GetVtkType() ).myNbFaces;
533 }
534
535 int SMDS_MeshCell::NbEdges() const
536 {
537   switch ( GetEntityType() )
538   {
539   case SMDSEntity_Polyhedra:
540     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbEdges();
541   case SMDSEntity_Polygon:
542     return NbNodes();
543   case SMDSEntity_Quad_Polygon:
544     return NbNodes() / 2;
545   default:;
546   }
547   return getCellProps( GetVtkType() ).myNbEdges;
548 }
549
550 int SMDS_MeshCell::NbCornerNodes() const
551 {
552   switch ( GetVtkType() )
553   {
554   case VTK_POLYHEDRON:
555     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::NbCornerNodes();
556   case VTK_POLYGON:
557     return NbNodes();
558   case VTK_QUADRATIC_POLYGON:
559     return NbNodes() / 2;
560   default:;
561   }
562   return getCellProps( GetVtkType() ).myNbCornerNodes;
563 }
564
565 ///////////////////////////////////////////////////////////////////////////////
566 /// Create an iterator which iterate on nodes owned by the element.
567 ///////////////////////////////////////////////////////////////////////////////
568 SMDS_ElemIteratorPtr SMDS_MeshCell::nodesIterator() const
569 {
570   if ( GetVtkType() == VTK_POLYHEDRON )
571     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodesIterator();
572
573   return boost::make_shared< SMDS_VtkCellIterator<> >( GetMesh(), GetVtkID(), GetEntityType());
574 }
575
576 ///////////////////////////////////////////////////////////////////////////////
577 /// Create an iterator which iterate on nodes owned by the element.
578 ///////////////////////////////////////////////////////////////////////////////
579 SMDS_NodeIteratorPtr SMDS_MeshCell::nodeIterator() const
580 {
581   if ( GetVtkType() == VTK_POLYHEDRON )
582     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::nodeIterator();
583
584   return SMDS_NodeIteratorPtr
585     (new SMDS_VtkCellIterator<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
586 }
587
588 SMDS_NodeIteratorPtr SMDS_MeshCell::interlacedNodesIterator() const
589 {
590   bool canInterlace = ( GetType() == SMDSAbs_Face || GetType() == SMDSAbs_Edge );
591   return canInterlace ? nodesIteratorToUNV() : nodeIterator();
592 }
593
594 SMDS_NodeIteratorPtr SMDS_MeshCell::nodesIteratorToUNV() const
595 {
596   return SMDS_NodeIteratorPtr
597     (new SMDS_VtkCellIteratorToUNV<SMDS_NodeIterator>( GetMesh(), GetVtkID(), GetEntityType()));
598 }
599
600 SMDSAbs_ElementType SMDS_MeshCell::GetType() const
601 {
602   return getCellProps( GetVtkType() ).myType;
603 }
604
605 SMDSAbs_EntityType SMDS_MeshCell::GetEntityType() const
606 {
607   return toSmdsType( (VTKCellType) GetVtkType() );
608 }
609
610 SMDSAbs_GeometryType SMDS_MeshCell::GetGeomType() const
611 {
612   return getCellProps( GetVtkType() ).myGeom;
613 }
614
615 VTKCellType SMDS_MeshCell::GetVtkType() const
616 {
617   return (VTKCellType) getGrid()->GetCellType( GetVtkID() );
618 }
619
620 bool SMDS_MeshCell::IsPoly() const
621 {
622   return getCellProps( GetVtkType() ).myIsPoly;
623 }
624
625 bool SMDS_MeshCell::IsQuadratic() const
626 {
627   return getCellProps( GetVtkType() ).myIsQuadratic;
628 }
629
630 const SMDS_MeshNode* SMDS_MeshCell::GetNode(const int ind) const
631 {
632   if ( GetVtkType() == VTK_POLYHEDRON )
633     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNode( ind );
634
635   vtkIdType npts;
636   vtkIdType const *pts;
637   getGrid()->GetCellPoints( GetVtkID(), npts, pts );
638   const std::vector<int>& interlace = SMDS_MeshCell::fromVtkOrder( VTKCellType( GetVtkType() ));
639   return GetMesh()->FindNodeVtk( pts[ interlace.empty() ? ind : interlace[ ind ]]);
640 }
641
642 int SMDS_MeshCell::GetNodeIndex( const SMDS_MeshNode* node ) const
643 {
644   if ( !node || node->IsNull() )
645     return -1;
646
647   if ( GetVtkType() == VTK_POLYHEDRON )
648     return static_cast< const SMDS_MeshVolume* >( this )->SMDS_MeshVolume::GetNodeIndex( node );
649
650   vtkIdType npts;
651   vtkIdType const *pts;
652   getGrid()->GetCellPoints( GetVtkID(), npts, pts );
653   for ( vtkIdType i = 0; i < npts; ++i )
654     if ( pts[i] == node->GetVtkID() )
655     {
656       const std::vector<int>& interlace = SMDS_MeshCell::toVtkOrder( VTKCellType( GetVtkType() ));
657       return interlace.empty() ? i : interlace[i];
658     }
659   return -1;
660 }
661
662 //================================================================================
663 /*!
664  * \brief Return VTKCellType corresponding to SMDSAbs_EntityType
665  */
666 //================================================================================
667
668 VTKCellType SMDS_MeshCell::toVtkType (SMDSAbs_EntityType smdsType)
669 {
670   return theVtkTypes[ smdsType ];
671 }
672
673 //================================================================================
674 /*!
675  * \brief Return indices to transform cell connectivity from SMDS to VTK
676  * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
677  */
678 //================================================================================
679
680 const std::vector< int >& SMDS_MeshCell::toVtkOrder(SMDSAbs_EntityType smdsType)
681 {
682   return theToVtkInterlaces[ smdsType ];
683 }
684
685 //================================================================================
686 /*!
687  * \brief Return indices to reverse an SMDS cell of given type.
688  *        nbNodes is useful for polygons
689  * Usage: reverseIDs[i] = forwardIDs[ indices[ i ]]
690  */
691 //================================================================================
692
693 const std::vector<int>& SMDS_MeshCell::reverseSmdsOrder(SMDSAbs_EntityType smdsType,
694                                                         const size_t       nbNodes)
695 {
696   if ( smdsType == SMDSEntity_Polygon )
697   {
698     if ( theReverseInterlaces[ smdsType ].size() != nbNodes )
699     {
700       theReverseInterlaces[ smdsType ].resize( nbNodes );
701       for ( size_t i = 0; i < nbNodes; ++i )
702         theReverseInterlaces[ smdsType ][i] = nbNodes - i - 1;
703     }
704   }
705   else if ( smdsType == SMDSEntity_Quad_Polygon )
706   {
707     if ( theReverseInterlaces[ smdsType ].size() != nbNodes )
708     {
709       // e.g. for 8 nodes: [ 0, 3,2,1, 7,6,5,4 ]
710       theReverseInterlaces[ smdsType ].resize( nbNodes );
711       size_t pos = 0;
712       theReverseInterlaces[ smdsType ][pos++] = 0;
713       for ( int i = nbNodes / 2 - 1; i > 0 ; --i ) // 3,2,1
714         theReverseInterlaces[ smdsType ][pos++] = i;
715       for ( int i = nbNodes - 1, nb = nbNodes / 2; i >= nb; --i ) // 7,6,5,4
716         theReverseInterlaces[ smdsType ][pos++] = i;
717     }
718   }
719
720   return theReverseInterlaces[ smdsType ];
721 }
722
723 //================================================================================
724 /*!
725  * \brief Return indices to set nodes of a quadratic 1D or 2D element in interlaced order
726  * Usage: interlacedIDs[i] = smdsIDs[ indices[ i ]]
727  */
728 //================================================================================
729
730 const std::vector<int>& SMDS_MeshCell::interlacedSmdsOrder(SMDSAbs_EntityType smdsType,
731                                                            const size_t       nbNodes)
732 {
733   if ( smdsType == SMDSEntity_Quad_Polygon )
734   {
735     if ( theQuadInterlace[smdsType].size() != nbNodes )
736     {
737       theQuadInterlace[smdsType].resize( nbNodes );
738       for ( size_t i = 0; i < nbNodes / 2; ++i )
739       {
740         theQuadInterlace[smdsType][i*2+0] = i;
741         theQuadInterlace[smdsType][i*2+1] = i + nbNodes / 2;
742       }
743     }
744   }
745   return theQuadInterlace[smdsType];
746 }
747
748 //================================================================================
749 /*!
750  * \brief Return SMDSAbs_EntityType corresponding to VTKCellType
751  */
752 //================================================================================
753
754 SMDSAbs_EntityType SMDS_MeshCell::toSmdsType(VTKCellType vtkType)
755 {
756   return getCellProps( vtkType ).myEntity;
757 }
758
759 //================================================================================
760 /*!
761  * \brief Return SMDSAbs_ElementType by SMDSAbs_GeometryType
762  */
763 //================================================================================
764
765 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_GeometryType geomType)
766 {
767   switch ( geomType ) {
768   case SMDSGeom_POINT:     return SMDSAbs_0DElement;
769
770   case SMDSGeom_EDGE:      return SMDSAbs_Edge;
771
772   case SMDSGeom_TRIANGLE:
773   case SMDSGeom_QUADRANGLE:
774   case SMDSGeom_POLYGON:   return SMDSAbs_Face;
775
776   case SMDSGeom_TETRA:
777   case SMDSGeom_PYRAMID:
778   case SMDSGeom_HEXA:
779   case SMDSGeom_PENTA:
780   case SMDSGeom_HEXAGONAL_PRISM:
781   case SMDSGeom_POLYHEDRA: return SMDSAbs_Volume;
782
783   case SMDSGeom_BALL:      return SMDSAbs_Ball;
784
785   case SMDSGeom_NONE: ;
786   }
787   return SMDSAbs_All;
788 }
789
790 //================================================================================
791 /*!
792  * \brief Return SMDSAbs_ElementType by SMDSAbs_EntityType
793  */
794 //================================================================================
795
796 SMDSAbs_ElementType SMDS_MeshCell::ElemType(SMDSAbs_EntityType entityType)
797 {
798   return getCellProps( entityType ).myType;
799 }
800
801 SMDSAbs_GeometryType SMDS_MeshCell::GeomType( SMDSAbs_EntityType entityType )
802 {
803   return getCellProps( entityType ).myGeom;
804 }
805
806 bool SMDS_MeshCell::IsPoly( SMDSAbs_EntityType entityType )
807 {
808   return getCellProps( entityType ).myIsPoly;
809 }
810
811 bool SMDS_MeshCell::IsQuadratic( SMDSAbs_EntityType entityType )
812 {
813   return getCellProps( entityType ).myIsQuadratic;
814 }
815
816 int SMDS_MeshCell::NbCornerNodes( SMDSAbs_EntityType entityType )
817 {
818   return getCellProps( entityType ).myNbCornerNodes;
819 }
820
821 int SMDS_MeshCell::NbNodes( SMDSAbs_EntityType entityType )
822 {
823   return getCellProps( entityType ).myNbNodes;
824 }
825
826 int SMDS_MeshCell::NbEdges( SMDSAbs_EntityType entityType )
827 {
828   return getCellProps( entityType ).myNbEdges;
829 }
830
831 int SMDS_MeshCell::NbFaces( SMDSAbs_EntityType entityType )
832 {
833   return getCellProps( entityType ).myNbFaces;
834 }
835
836 //================================================================================
837 /*!
838  * \brief Return indices to transform cell connectivity from VTK to SMDS
839  * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
840  */
841 //================================================================================
842
843 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(SMDSAbs_EntityType smdsType)
844 {
845   return theFromVtkInterlaces[ smdsType ];
846 }
847
848 //================================================================================
849 /*!
850  * \brief Return indices to transform cell connectivity from SMDS to VTK
851  * Usage: vtkIDs[i] = smdsIDs[ indices[ i ]]
852  */
853 //================================================================================
854
855 const std::vector<int>& SMDS_MeshCell::toVtkOrder(VTKCellType vtkType)
856 {
857   return toVtkOrder( toSmdsType( vtkType ));
858 }
859
860 //================================================================================
861 /*!
862  * \brief Return indices to transform cell connectivity from VTK to SMDS
863  * Usage: smdsIDs[i] = vtkIDs[ indices[ i ]]
864  */
865 //================================================================================
866
867 const std::vector<int>& SMDS_MeshCell::fromVtkOrder(VTKCellType vtkType)
868 {
869   return fromVtkOrder( toSmdsType( vtkType ));
870 }