Salome HOME
Update of CheckDone
[modules/smesh.git] / src / StdMeshers / StdMeshers_PolyhedronPerSolid_3D.cxx
1 // Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File      : StdMeshers_PolyhedronPerSolid_3D.cxx
24 // Module    : SMESH
25 // Created   : Fri Oct 20 11:37:07 2006
26 // Author    : Edward AGAPOV (eap)
27 //
28 #include "StdMeshers_PolyhedronPerSolid_3D.hxx"
29
30 #include "SMESHDS_Mesh.hxx"
31 #include "SMESH_ControlsDef.hxx"
32 #include "SMESH_Gen.hxx"
33 #include "SMESH_Mesh.hxx"
34 #include "SMESH_MeshAlgos.hxx"
35 #include "SMESH_MeshEditor.hxx"
36 #include "SMESH_MesherHelper.hxx"
37 #include "SMESH_ProxyMesh.hxx"
38 #include "SMESH_subMesh.hxx"
39 #include "StdMeshers_PolygonPerFace_2D.hxx"
40 #include "StdMeshers_Regular_1D.hxx"
41 #include "StdMeshers_ViscousLayers.hxx"
42
43 #include <TopExp_Explorer.hxx>
44
45 #include <vector>
46 #include <set>
47
48 namespace
49 {
50   struct _EdgeMesher : public StdMeshers_Regular_1D
51   {
52     _EdgeMesher( int hypId, SMESH_Gen* gen )
53       : StdMeshers_Regular_1D( hypId, gen )
54     {
55       _hypType = NB_SEGMENTS;
56       _ivalue[ NB_SEGMENTS_IND ] = 1;
57     }
58   };
59
60   //=======================================================================
61   //function : addHexa
62   //purpose  :
63   //=======================================================================
64
65   const SMDS_MeshElement* addHexa( std::vector< const SMDS_MeshElement* >& faces,
66                                    const std::vector< int > &              quantities,
67                                    SMESH_MesherHelper &                    helper )
68   {
69     const SMDS_MeshElement* newHexa = 0;
70
71     // check nb of nodes in faces
72     for ( size_t i = 0; i < quantities.size(); ++i )
73       if ( quantities[ i ] != 4 )
74         return newHexa;
75
76     // look for a top face
77     const SMDS_MeshElement* topFace = 0;
78     const SMDS_MeshElement* botFace = faces[0];
79     std::vector< const SMDS_MeshNode* > nodes( 16 ); // last 8 is a working buffer
80     nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
81     for ( size_t iF = 1; iF < faces.size() &&  !topFace; ++iF )
82     {
83       bool hasCommonNode = false;
84       for ( int iN = 0; iN < quantities[ 0 ] &&  !hasCommonNode; ++iN )
85         hasCommonNode = ( faces[ iF ]->GetNodeIndex( nodes[ iN ]) >= 0 );
86
87       if ( !hasCommonNode )
88         topFace = faces[ iF ];
89     }
90
91     nodes.resize( 8 ); // set top nodes after hexa nodes - [8-11]
92     nodes.insert( nodes.end(), topFace->begin_nodes(), topFace->end_nodes() );
93     nodes.resize( 12 );
94     nodes.insert( nodes.end(), nodes.begin() + 8, nodes.begin() + 12 );
95
96     // find corresponding nodes of top and bottom by finding a side face including 2 node of each
97     SMESHDS_Mesh* mesh = helper.GetMeshDS();
98     const SMDS_MeshElement* sideFace = 0;
99     size_t i;
100     for ( i = 8; i < nodes.size()-1 &&  !sideFace; ++i )
101     {
102       sideFace = mesh->FindFace( nodes[0], nodes[1], nodes[ i ], nodes[ i + 1 ]);
103     }
104     if ( !sideFace )
105       return newHexa;
106
107     --i; // restore after ++i in the loop
108     bool botOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 0 ], nodes[ 1 ] );
109     bool topOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ i ], nodes[ i + 1 ] );
110     if ( botOriRight == topOriRight )
111     {
112       nodes[ 4 ] = nodes[ i + 1 ];
113       nodes[ 5 ] = nodes[ i + 0 ];
114       nodes[ 6 ] = nodes[ i + 3 ];
115       nodes[ 7 ] = nodes[ i + 2 ];
116     }
117     else
118     {
119       nodes[ 4 ] = nodes[ i + 0 ];
120       nodes[ 5 ] = nodes[ i + 1 ];
121       nodes[ 6 ] = nodes[ i + 2 ];
122       nodes[ 7 ] = nodes[ i + 3 ];
123     }
124
125     newHexa = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ],
126                                 nodes[ 4 ], nodes[ 5 ], nodes[ 6 ], nodes[ 7 ]);
127
128     return newHexa;
129   }
130
131   //=======================================================================
132   //function : addTetra
133   //purpose  :
134   //=======================================================================
135
136   const SMDS_MeshElement* addTetra( std::vector< const SMDS_MeshElement* >& faces,
137                                     const std::vector< int > &              quantities,
138                                     SMESH_MesherHelper &                    helper )
139   {
140     const SMDS_MeshElement* newTetra = 0;
141
142     // check nb of nodes in faces
143     for ( size_t i = 0; i < quantities.size(); ++i )
144       if ( quantities[ i ] != 3 )
145         return newTetra;
146
147     const SMDS_MeshElement* botFace = faces[0];
148
149     std::vector< const SMDS_MeshNode* > nodes( 6 );
150     nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
151     nodes.resize( 3 );
152
153     const SMDS_MeshNode* topNode = 0;
154     for ( size_t i = 0; i < 3 &&  !topNode; ++i )
155     {
156       topNode = faces[ 1 ]->GetNode( i );
157       if ( botFace->GetNodeIndex( topNode ) >= 0 )
158         topNode = 0;
159     }
160     if ( !topNode )
161       return newTetra;
162
163     nodes.push_back( topNode );
164
165     newTetra = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
166
167     return newTetra;
168   }
169
170   //=======================================================================
171   //function : addPenta
172   //purpose  :
173   //=======================================================================
174
175   const SMDS_MeshElement* addPenta( std::vector< const SMDS_MeshElement* >& faces,
176                                     const std::vector< int > &              quantities,
177                                     SMESH_MesherHelper &                    helper )
178   {
179     const SMDS_MeshElement* newPenta = 0;
180
181     // check nb of nodes in faces and find triangle faces
182     int trias[2] = { -1, -1 };
183     for ( size_t i = 0; i < quantities.size(); ++i )
184       if ( quantities[ i ] != 4 )
185       {
186         if ( quantities[ i ] != 3 )
187           return newPenta;
188         int iTria = ( trias[0] != -1 );
189         if ( trias[ iTria ] != -1 )
190           return newPenta;
191         trias[ iTria ] = i;
192       }
193     if ( trias[1] == -1 )
194       return newPenta;
195
196     int iSide = trias[0] + 1;
197     if ( iSide == trias[1] )
198       ++iSide;
199     if (iSide == 5)
200       // use first side (otherwise, out of bounds)
201       iSide = 0;
202
203     const SMDS_MeshElement* botFace  = faces[ trias[0]];
204     const SMDS_MeshElement* topFace  = faces[ trias[1]];
205     const SMDS_MeshElement* sideFace = faces[ iSide ];
206     const SMDS_MeshNode* nodes[ 6 ] = { 0,0,0,0,0,0 };
207     for ( int i = 0 ; i < 3; ++i )
208     {
209       const SMDS_MeshNode* botNode = botFace->GetNode( i );
210       if ( sideFace->GetNodeIndex( botNode ) < 0 )
211         nodes[2] = botNode;
212       else
213         nodes[ bool( nodes[0] )] = botNode;
214
215       const SMDS_MeshNode* topNode = topFace->GetNode( i );
216       if ( sideFace->GetNodeIndex( topNode ) < 0 )
217         nodes[5] = topNode;
218       else
219         nodes[ 3 + bool( nodes[3]) ] = topNode;
220     }
221     bool botOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 0 ], nodes[ 1 ]);
222     bool topOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 3 ], nodes[ 4 ]);
223     if ( botOriRight == topOriRight )
224       std::swap( nodes[ 3 ], nodes[ 4 ]);
225
226     newPenta = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ],
227                                  nodes[ 3 ], nodes[ 4 ], nodes[ 5 ]);
228
229     return newPenta;
230   }
231
232   //=======================================================================
233   //function : addPyra
234   //purpose  :
235   //=======================================================================
236
237   const SMDS_MeshElement* addPyra( std::vector< const SMDS_MeshElement* >& faces,
238                                    const std::vector< int > &              quantities,
239                                    SMESH_MesherHelper &                    helper )
240   {
241     const SMDS_MeshElement* newPyra = 0;
242
243     // check nb of nodes in faces
244     int iBot = -1;
245     for ( size_t i = 0; i < quantities.size(); ++i )
246       if ( quantities[ i ] != 3 )
247       {
248         if ( quantities[ i ] != 4 || iBot != -1 )
249           return newPyra;
250         iBot = i;
251       }
252
253     const SMDS_MeshElement* botFace = faces[ iBot ];
254
255     std::vector< const SMDS_MeshNode* > nodes( 8 );
256     nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
257     nodes.resize( 4 );
258
259     const SMDS_MeshNode* topNode = 0;
260     for ( size_t i = 0; i < 4 &&  !topNode; ++i )
261     {
262       topNode = faces[ 1 ]->GetNode( i );
263       if ( botFace->GetNodeIndex( topNode ) >= 0 )
264         topNode = 0;
265     }
266     if ( !topNode )
267       return newPyra;
268
269     nodes.push_back( topNode );
270
271     newPyra = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ], nodes[4] );
272
273     return newPyra;
274   }
275
276   //=======================================================================
277   //function : addHPrism
278   //purpose  : add hexagonal prism
279   //=======================================================================
280
281   const SMDS_MeshElement* addHPrism( std::vector< const SMDS_MeshElement* >& faces,
282                                      const std::vector< int > &              quantities,
283                                      SMESH_MesherHelper &                    helper )
284   {
285     const SMDS_MeshElement* newHexPrism = 0;
286
287     // check nb of nodes in faces and find hexagons
288     int hexa[2] = { -1, -1 };
289     for ( size_t i = 0; i < quantities.size(); ++i )
290       if ( quantities[ i ] != 4 )
291       {
292         if ( quantities[ i ] != 6 )
293           return newHexPrism;
294         int iHex = ( hexa[0] != -1 );
295         if ( hexa[ iHex ] != -1 )
296           return newHexPrism;
297         hexa[ iHex ] = i;
298       }
299     if ( hexa[1] == -1 )
300       return newHexPrism;
301
302     const SMDS_MeshElement* botFace = faces[ hexa[ 0 ]];
303     const SMDS_MeshElement* topFace = faces[ hexa[ 1 ]];
304     std::vector< const SMDS_MeshNode* > nodes( 24 ); // last 12 is a working buffer
305
306     nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
307     nodes.resize( 12 ); // set top nodes after hexa nodes - [12-17]
308     nodes.insert( nodes.end(), topFace->begin_nodes(), topFace->end_nodes() );
309     nodes.resize( 18 );
310     nodes.insert( nodes.end(), nodes.begin() + 12, nodes.begin() + 18 );
311
312     // find corresponding nodes of top and bottom by finding a side face including 2 node of each
313     SMESHDS_Mesh* mesh = helper.GetMeshDS();
314     const SMDS_MeshElement* sideFace = 0;
315     size_t i;
316     for ( i = 12; i < nodes.size()-1 &&  !sideFace; ++i )
317     {
318       sideFace = mesh->FindFace( nodes[0], nodes[1], nodes[ i ], nodes[ i + 1 ]);
319     }
320     if ( !sideFace )
321       return newHexPrism;
322
323     --i; // restore after ++i in the loop
324     bool botOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 0 ], nodes[ 1 ] );
325     bool topOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ i ], nodes[ i + 1 ] );
326     if ( botOriRight == topOriRight )
327     {
328       nodes[ 6  ] = nodes[ i + 1 ];
329       nodes[ 7  ] = nodes[ i + 0 ];
330       nodes[ 8  ] = nodes[ i + 5 ];
331       nodes[ 9  ] = nodes[ i + 4 ];
332       nodes[ 10 ] = nodes[ i + 3 ];
333       nodes[ 11 ] = nodes[ i + 2 ];
334     }
335     else
336     {
337       nodes[ 6  ] = nodes[ i + 0 ];
338       nodes[ 7  ] = nodes[ i + 1 ];
339       nodes[ 8  ] = nodes[ i + 2 ];
340       nodes[ 9  ] = nodes[ i + 3 ];
341       nodes[ 10 ] = nodes[ i + 4 ];
342       nodes[ 11 ] = nodes[ i + 5 ];
343     }
344
345     newHexPrism = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ],
346                                     nodes[ 3 ], nodes[ 4 ], nodes[ 5 ],
347                                     nodes[ 6 ], nodes[ 7 ], nodes[ 8 ],
348                                     nodes[ 9 ], nodes[10 ], nodes[11 ]);
349
350     return newHexPrism;
351   }
352
353   //=======================================================================
354   //function : addPoly
355   //purpose  :
356   //=======================================================================
357
358   const SMDS_MeshElement* addPoly( std::vector< const SMDS_MeshElement* >& faces,
359                                    const std::vector< int > &              quantities,
360                                    SMESH_MesherHelper &                    helper )
361   {
362     const SMDS_MeshElement* newPoly = 0;
363
364     std::vector< const SMDS_MeshNode* > nodes;
365     for ( size_t iF = 0; iF < faces.size(); ++iF )
366       nodes.insert( nodes.end(), faces[iF]->begin_nodes(), faces[iF]->end_nodes() );
367
368     newPoly = helper.AddPolyhedralVolume( nodes, quantities );
369
370     return newPoly;
371   }
372
373 } // namespace
374
375 //=======================================================================
376 //function : StdMeshers_PolyhedronPerSolid_3D
377 //purpose  :
378 //=======================================================================
379
380 StdMeshers_PolyhedronPerSolid_3D::StdMeshers_PolyhedronPerSolid_3D(int        hypId,
381                                                                    SMESH_Gen* gen)
382   :SMESH_3D_Algo(hypId, gen),
383    myEdgeMesher( new _EdgeMesher( gen->GetANewId(), gen )),
384    myFaceMesher( new StdMeshers_PolygonPerFace_2D( gen->GetANewId(), gen ))
385 {
386   _name = "PolyhedronPerSolid_3D";
387   _requireDiscreteBoundary = false;
388   _supportSubmeshes = true;
389   _compatibleHypothesis.push_back("ViscousLayers");
390   _neededLowerHyps[0] = _neededLowerHyps[1] = _neededLowerHyps[2] = true;
391 }
392
393 //=======================================================================
394 //function : ~StdMeshers_PolyhedronPerSolid_3D
395 //purpose  :
396 //=======================================================================
397
398 StdMeshers_PolyhedronPerSolid_3D::~StdMeshers_PolyhedronPerSolid_3D()
399 {
400   delete myEdgeMesher;
401   delete myFaceMesher;
402 }
403
404 //=======================================================================
405 //function : CheckHypothesis
406 //purpose  :
407 //=======================================================================
408
409 bool StdMeshers_PolyhedronPerSolid_3D::CheckHypothesis(SMESH_Mesh&         theMesh,
410                                                        const TopoDS_Shape& theShape,
411                                                        Hypothesis_Status&  theStatus)
412 {
413   myViscousLayersHyp = NULL;
414
415   const std::list<const SMESHDS_Hypothesis*>& hyps =
416     GetUsedHypothesis( theMesh, theShape, /*ignoreAuxiliary=*/false);
417   std::list <const SMESHDS_Hypothesis* >::const_iterator h = hyps.begin();
418   if ( h == hyps.end())
419   {
420     theStatus = SMESH_Hypothesis::HYP_OK;
421     return true;
422   }
423
424   // only StdMeshers_ViscousLayers can be used
425   theStatus = HYP_OK;
426   for ( ; h != hyps.end(); ++h )
427   {
428     if ( !(myViscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h )))
429       break;
430   }
431   if ( !myViscousLayersHyp )
432     theStatus = HYP_INCOMPATIBLE;
433   else
434     error( myViscousLayersHyp->CheckHypothesis( theMesh, theShape, theStatus ));
435
436   return theStatus == HYP_OK;
437 }
438
439 //=======================================================================
440 //function : Compute
441 //purpose  :
442 //=======================================================================
443
444 bool StdMeshers_PolyhedronPerSolid_3D::Compute(SMESH_Mesh&         theMesh,
445                                                const TopoDS_Shape& theShape)
446 {
447   const SMDS_MeshElement* newVolume = 0;
448
449   SMESH_subMesh* sm = theMesh.GetSubMesh( theShape );
450   SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true,
451                                                             /*complexFirst=*/false);
452   while ( smIt->more() )
453   {
454     sm = smIt->next();
455     if ( !sm->IsEmpty() )
456       continue;
457
458     const TopoDS_Shape & shape = sm->GetSubShape();
459     switch ( shape.ShapeType() )
460     {
461     case TopAbs_VERTEX:
462       sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
463       break;
464
465     case TopAbs_EDGE:
466       sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
467       if ( sm->IsEmpty() )
468         myEdgeMesher->Compute( theMesh, shape );
469       break;
470
471     case TopAbs_FACE:
472       sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
473       if ( sm->IsEmpty() && !myFaceMesher->Compute( theMesh, shape ))
474       {
475         sm->GetComputeError() = myFaceMesher->GetComputeError();
476         sm->GetComputeError()->myAlgo = myFaceMesher;
477         return false;
478       }
479       break;
480
481     case TopAbs_SOLID:
482     {
483       SMESH_MesherHelper helper( theMesh );
484       helper.SetElementsOnShape( true );
485       _quadraticMesh = helper.IsQuadraticSubMesh( shape );
486
487       SMESH_ProxyMesh::Ptr proxymesh( new SMESH_ProxyMesh( theMesh ));
488       if ( myViscousLayersHyp )
489       {
490         proxymesh = myViscousLayersHyp->Compute( theMesh, theShape );
491         if ( !proxymesh )
492           return false;
493       }
494
495       std::vector< const SMDS_MeshElement* > faces;
496       faces.reserve( 20 );
497
498       for ( TopExp_Explorer faceEx( shape, TopAbs_FACE ); faceEx.More(); faceEx.Next() )
499       {
500         const SMESHDS_SubMesh* smDS = proxymesh->GetSubMesh( faceEx.Current() );
501         for ( SMDS_ElemIteratorPtr faceIt = smDS->GetElements(); faceIt->more(); )
502           faces.push_back( faceIt->next() );
503       }
504
505       bool useMediumNodes = false;
506       if ( !_quadraticMesh && theMesh.GetMeshDS()->GetMeshInfo().NbFaces( ORDER_QUADRATIC ))
507         for ( size_t i = 0; i < faces.size() &&  !useMediumNodes ; ++i )
508           useMediumNodes = faces[ i ]->IsQuadratic();
509
510       std::vector< int > quantities( faces.size() );
511       std::set< const SMDS_MeshNode* > nodes;
512       for ( size_t i = 0; i < faces.size(); ++i )
513       {
514         quantities[ i ] = useMediumNodes ? faces[ i ]->NbNodes() : faces[ i ]->NbCornerNodes();
515         for ( int iN = 0; iN < quantities[ i ]; ++iN )
516           nodes.insert( faces[ i ]->GetNode( iN ));
517       }
518
519       const size_t nbNodes = nodes.size(), nbFaces = faces.size();
520       if (      nbNodes == 8  && nbFaces == 6 ) newVolume = addHexa  ( faces, quantities, helper );
521       else if ( nbNodes == 4  && nbFaces == 4 ) newVolume = addTetra ( faces, quantities, helper );
522       else if ( nbNodes == 6  && nbFaces == 5 ) newVolume = addPenta ( faces, quantities, helper );
523       else if ( nbNodes == 5  && nbFaces == 5 ) newVolume = addPyra  ( faces, quantities, helper );
524       else if ( nbNodes == 12 && nbFaces == 8 ) newVolume = addHPrism( faces, quantities, helper );
525       if ( !newVolume )
526         newVolume = addPoly ( faces, quantities, helper );
527
528       if ( newVolume )
529       {
530         SMESH::Controls::BadOrientedVolume checker;
531         checker.SetMesh( theMesh.GetMeshDS() );
532         if ( checker.IsSatisfy( newVolume->GetID() ))
533         {
534           SMESH_MeshEditor editor( &theMesh );
535           editor.Reorient( newVolume );
536         }
537       }
538     }
539     default:;
540
541     } // switch ( shape.ShapeType() )
542   } // loop on sub-meshes
543
544   return newVolume;
545 }
546
547 //=======================================================================
548 //function : Evaluate
549 //purpose  :
550 //=======================================================================
551
552 bool StdMeshers_PolyhedronPerSolid_3D::Evaluate(SMESH_Mesh&         theMesh,
553                                                 const TopoDS_Shape& theShape,
554                                                 MapShapeNbElems&    theResMap)
555 {
556   _quadraticMesh = false;
557
558   SMESH_subMesh* sm = theMesh.GetSubMesh( theShape );
559   SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true,
560                                                             /*complexFirst=*/false);
561   while ( smIt->more() )
562   {
563     sm = smIt->next();
564
565     MapShapeNbElems::iterator sm2vec = theResMap.find( sm );
566     if ( sm2vec != theResMap.end() && !sm2vec->second.empty() )
567       continue;
568
569     const TopoDS_Shape & shape = sm->GetSubShape();
570     switch ( shape.ShapeType() )
571     {
572     case TopAbs_EDGE:
573       myEdgeMesher->Evaluate( theMesh, shape, theResMap );
574       break;
575
576     case TopAbs_FACE:
577     {
578       myFaceMesher->Evaluate( theMesh, shape, theResMap );
579       std::vector<smIdType> & quantities = theResMap[ sm ];
580       _quadraticMesh = ( !quantities.empty() &&
581                          ( quantities[ SMDSEntity_Quad_Triangle   ] +
582                            quantities[ SMDSEntity_Quad_Quadrangle ] +
583                            quantities[ SMDSEntity_Quad_Polygon    ]));
584       break;
585     }
586
587     case TopAbs_SOLID:
588     {
589       std::vector<smIdType> & quantities = theResMap[ sm ];
590       quantities.resize( SMDSEntity_Last, 0 );
591
592       SMESH_MesherHelper helper( theMesh );
593       const int nbNodes = helper.Count( shape, TopAbs_VERTEX, /*ignoreSame=*/true );
594       const int nbFaces = helper.Count( shape, TopAbs_FACE,   /*ignoreSame=*/false );
595
596       if (      nbNodes == 8 && nbFaces == 6 )
597         quantities[ _quadraticMesh ? SMDSEntity_Quad_Hexa : SMDSEntity_Hexa ] = 1;
598       else if ( nbNodes == 4 && nbFaces == 4 )
599         quantities[ _quadraticMesh ? SMDSEntity_Quad_Tetra : SMDSEntity_Tetra ] = 1;
600       else if ( nbNodes == 6 && nbFaces == 5 )
601         quantities[ _quadraticMesh ? SMDSEntity_Quad_Penta : SMDSEntity_Penta ] = 1;
602       else if ( nbNodes == 5 && nbFaces == 5 )
603         quantities[ _quadraticMesh ? SMDSEntity_Quad_Pyramid : SMDSEntity_Pyramid ] = 1;
604       else if ( nbNodes == 12 && nbFaces == 8 )
605         quantities[ /*_quadraticMesh ? SMDSEntity_Quad_Pyramid :*/ SMDSEntity_Hexagonal_Prism ] = 1;
606       else
607         quantities[ /*_quadraticMesh ? SMDSEntity_Quad_Polyhedra : */SMDSEntity_Polyhedra ] = 1;
608
609       return true;
610     }
611     default:;
612
613     } // switch ( shape.ShapeType() )
614   } // loop on sub-meshes
615
616   return false;
617 }