]> SALOME platform Git repositories - modules/smesh.git/blob - src/StdMeshers/StdMeshers_Penta_3D.cxx
Salome HOME
PAL13473 (Build repetitive mesh):
[modules/smesh.git] / src / StdMeshers / StdMeshers_Penta_3D.cxx
1 //  SMESH StdMeshers_Penta_3D implementaion of SMESH idl descriptions
2 //
3 //  Copyright (C) 2003  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. 
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 //
24 //  File   : StdMeshers_Penta_3D.cxx
25 //  Module : SMESH
26
27 #include "StdMeshers_Penta_3D.hxx"
28
29 #include "utilities.h"
30 #include "Utils_ExceptHandlers.hxx"
31
32 #include "SMDS_EdgePosition.hxx"
33 #include "SMDS_MeshElement.hxx"
34 #include "SMDS_VolumeOfNodes.hxx"
35 #include "SMDS_VolumeTool.hxx"
36 #include "SMESHDS_SubMesh.hxx"
37 #include "SMESH_Mesh.hxx"
38 #include "SMESH_subMesh.hxx"
39 #include "SMESH_MeshEditor.hxx"
40
41 #include <BRep_Tool.hxx>
42 #include <TopAbs_ShapeEnum.hxx>
43 #include <TopExp.hxx>
44 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
45 #include <TopTools_IndexedMapOfShape.hxx>
46 #include <TopTools_IndexedMapOfShape.hxx>
47 #include <TopTools_ListIteratorOfListOfShape.hxx>
48 #include <TopTools_ListOfShape.hxx>
49 #include <TopoDS.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Shell.hxx>
52 #include <TopoDS_Vertex.hxx>
53 #include <gp_Pnt.hxx>
54 #include <BRepTools.hxx>
55 #include <BRepTools_WireExplorer.hxx>
56 #include <TopTools_MapOfShape.hxx>
57
58 #include <stdio.h>
59 #include <algorithm>
60
61 using namespace std;
62
63 typedef map < int, int, less<int> >::iterator   \
64   StdMeshers_IteratorOfDataMapOfIntegerInteger;
65
66 enum { NB_WALL_FACES = 4 };
67
68 //=======================================================================
69 //function : StdMeshers_Penta_3D
70 //purpose  : 
71 //=======================================================================
72 StdMeshers_Penta_3D::StdMeshers_Penta_3D()
73 : myErrorStatus(1)
74 {
75   myTol3D=0.1;
76   myWallNodesMaps.resize( SMESH_Block::NbFaces() );
77   myShapeXYZ.resize( SMESH_Block::NbSubShapes() );
78   myTool = 0;
79 }
80
81 //=======================================================================
82 //function : ~StdMeshers_Penta_3D
83 //purpose  : 
84 //=======================================================================
85
86 StdMeshers_Penta_3D::~StdMeshers_Penta_3D()
87 {
88   if ( myTool )
89     delete myTool;
90 }
91
92 //=======================================================================
93 //function : Compute
94 //purpose  : 
95 //=======================================================================
96 bool StdMeshers_Penta_3D::Compute(SMESH_Mesh& aMesh, 
97                                   const TopoDS_Shape& aShape)
98 {
99   MESSAGE("StdMeshers_Penta_3D::Compute()");
100   //
101   myErrorStatus=0;
102   //
103   bool bOK=false;
104   //
105   myShape=aShape;
106   SetMesh(aMesh);
107   //
108   CheckData();
109   if (myErrorStatus){
110     return bOK;
111   }
112
113   myTool = new SMESH_MesherHelper(aMesh);
114   myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape);
115
116   //
117   MakeBlock();
118   if (myErrorStatus){
119     delete myTool; myTool = 0;
120     return bOK;
121   }
122   //
123   ClearMeshOnFxy1();
124   if (myErrorStatus) {
125     delete myTool; myTool = 0;
126     return bOK;
127   }
128   //
129   MakeNodes();
130   if (myErrorStatus){
131     delete myTool; myTool = 0;
132     return bOK;
133   }
134   //
135   MakeConnectingMap();
136   //
137   MakeMeshOnFxy1();
138   if (myErrorStatus) {
139     delete myTool; myTool = 0;
140     return bOK;
141   }
142   //
143   MakeVolumeMesh();
144   //
145   delete myTool; myTool = 0;
146   return !bOK;
147 }
148
149 //=======================================================================
150 //function : MakeNodes
151 //purpose  : 
152 //=======================================================================
153 void StdMeshers_Penta_3D::MakeNodes()
154 {
155   myErrorStatus=0;
156   //
157   const int aNbSIDs=9;
158   int i, j, k, ij, iNbN, aNodeID, aSize, iErr;
159   double aX, aY, aZ;
160   SMESH_Block::TShapeID aSID, aSIDs[aNbSIDs]={
161     SMESH_Block::ID_V000, SMESH_Block::ID_V100, 
162     SMESH_Block::ID_V110, SMESH_Block::ID_V010,
163     SMESH_Block::ID_Ex00, SMESH_Block::ID_E1y0, 
164     SMESH_Block::ID_Ex10, SMESH_Block::ID_E0y0,
165     SMESH_Block::ID_Fxy0
166   }; 
167   //
168   SMESH_Mesh* pMesh=GetMesh();
169   //
170   // 1. Define the sizes of mesh
171   //
172   // 1.1 Horizontal size
173   myJSize=0;
174   for (i=0; i<aNbSIDs; ++i) {
175     const TopoDS_Shape& aS = myBlock.Shape(aSIDs[i]);
176     SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aS);
177     ASSERT(aSubMesh);
178     SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS();
179     if(!myCreateQuadratic) {
180       iNbN = aSM->NbNodes();
181     }
182     else {
183       iNbN = 0;
184       SMDS_NodeIteratorPtr itn = aSM->GetNodes();
185       while(itn->more()) {
186         const SMDS_MeshNode* aNode = itn->next();
187         if(myTool->IsMedium(aNode))
188           continue;
189         iNbN++;
190       }
191     }
192     myJSize += iNbN;
193   }
194   //printf("***  Horizontal: number of nodes summary=%d\n", myJSize);
195   //
196   // 1.2 Vertical size
197   myISize=2;
198   {
199     const TopoDS_Shape& aS=myBlock.Shape(SMESH_Block::ID_E00z);
200     SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aS);
201     ASSERT(aSubMesh);
202     SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS();
203     if(!myCreateQuadratic) {
204       iNbN = aSM->NbNodes();
205     }
206     else {
207       iNbN = 0;
208       SMDS_NodeIteratorPtr itn = aSM->GetNodes();
209       while(itn->more()) {
210         const SMDS_MeshNode* aNode = itn->next();
211         if(myTool->IsMedium(aNode))
212           continue;
213         iNbN++;
214       }
215     }
216     myISize += iNbN;
217   }
218   //printf("***  Vertical: number of nodes on edges and vertices=%d\n", myISize);
219   //
220   aSize=myISize*myJSize;
221   myTNodes.resize(aSize);
222   //
223   StdMeshers_TNode aTNode;
224   gp_XYZ aCoords;
225   gp_Pnt aP3D;
226   //
227   // 2. Fill the repers on base face (Z=0)
228   i=0; j=0;
229   // vertices
230   for (k=0; k<aNbSIDs; ++k) {
231     aSID=aSIDs[k];
232     const TopoDS_Shape& aS = myBlock.Shape(aSID);
233     SMDS_NodeIteratorPtr ite = pMesh->GetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes();
234     while(ite->more()) {
235       const SMDS_MeshNode* aNode = ite->next();
236       if(myTool->IsMedium(aNode))
237         continue;
238       aNodeID=aNode->GetID();
239       //
240       aTNode.SetNode(aNode);
241       aTNode.SetShapeSupportID(aSID);
242       aTNode.SetBaseNodeID(aNodeID);
243       //
244       if ( SMESH_Block::IsEdgeID (aSID)) {
245         const SMDS_EdgePosition* epos =
246           static_cast<const SMDS_EdgePosition*>(aNode->GetPosition().get());
247         myBlock.ComputeParameters( epos->GetUParameter(), aS, aCoords );
248       }
249       else {
250         aX=aNode->X();
251         aY=aNode->Y();
252         aZ=aNode->Z();
253         aP3D.SetCoord(aX, aY, aZ);
254         myBlock.ComputeParameters(aP3D, aS, aCoords);
255       }
256       iErr = myBlock.ErrorStatus();
257       if (iErr) {
258         MESSAGE("StdMeshers_Penta_3D::MakeNodes()," <<
259                 "SMESHBlock: ComputeParameters operation failed");
260         myErrorStatus=101; // SMESHBlock: ComputeParameters operation failed
261         return;
262       }
263       aTNode.SetNormCoord(aCoords);
264       ij=i*myJSize+j;
265       myTNodes[ij]=aTNode;
266       ++j;
267     }
268   }
269
270   // 3.1 Fill maps of wall nodes
271   SMESH_Block::TShapeID wallFaceID[ NB_WALL_FACES ] = {
272     SMESH_Block::ID_Fx0z, SMESH_Block::ID_Fx1z,
273     SMESH_Block::ID_F0yz, SMESH_Block::ID_F1yz
274     };
275   SMESH_Block::TShapeID baseEdgeID[ NB_WALL_FACES ] = {
276     SMESH_Block::ID_Ex00, SMESH_Block::ID_Ex10,
277     SMESH_Block::ID_E0y0, SMESH_Block::ID_E1y0
278     };
279   for ( i = 0; i < NB_WALL_FACES ; ++i ) {
280     int fIndex = SMESH_Block::ShapeIndex( wallFaceID[ i ]);
281     bool ok = LoadIJNodes (myWallNodesMaps[ fIndex ],
282                            TopoDS::Face( myBlock.Shape( wallFaceID[ i ] )),
283                            TopoDS::Edge( myBlock.Shape( baseEdgeID[ i ] )),
284                            pMesh->GetMeshDS());
285     if ( !ok ) {
286       myErrorStatus = i + 1;
287       MESSAGE(" Cant LoadIJNodes() from a wall face " << myErrorStatus );
288       return;
289     }
290   }
291
292   // 3.2 find node columns for vertical edges and edge IDs
293   vector<const SMDS_MeshNode*> * verticEdgeNodes[ NB_WALL_FACES ];
294   SMESH_Block::TShapeID          verticEdgeID   [ NB_WALL_FACES ];
295   for ( i = 0; i < NB_WALL_FACES ; ++i ) { // 4 first base nodes are nodes on vertices
296     // edge ID
297     SMESH_Block::TShapeID eID, vID = aSIDs[ i ];
298     ShapeSupportID(false, vID, eID);
299     verticEdgeID[ i ] = eID;
300     // column nodes
301     StdMeshers_TNode& aTNode = myTNodes[ i ];
302     verticEdgeNodes[ i ] = 0;
303     for ( j = 0; j < NB_WALL_FACES ; ++j ) { // loop on 4 wall faces
304       int fIndex = SMESH_Block::ShapeIndex( wallFaceID[ j ]);
305       StdMeshers_IJNodeMap & ijNodes= myWallNodesMaps[ fIndex ];
306       if ( ijNodes.begin()->second[0] == aTNode.Node() )
307         verticEdgeNodes[ i ] = & ijNodes.begin()->second;
308       else if ( ijNodes.rbegin()->second[0] == aTNode.Node() )
309         verticEdgeNodes[ i ] = & ijNodes.rbegin()->second;
310       if ( verticEdgeNodes[ i ] )
311         break;
312     }
313   }
314
315   // 3.3 set XYZ of vertices, and initialize of the rest
316   SMESHDS_Mesh* aMesh = GetMesh()->GetMeshDS();
317   for ( int id = SMESH_Block::ID_V000; id < SMESH_Block::ID_Shell; ++id ) {
318     if ( SMESH_Block::IsVertexID( id )) {
319       TopoDS_Shape V = myBlock.Shape( id );
320       SMESHDS_SubMesh* sm = aMesh->MeshElements( V );
321       const SMDS_MeshNode* n = sm->GetNodes()->next();
322       myShapeXYZ[ id ].SetCoord( n->X(), n->Y(), n->Z() );
323     }
324     else
325       myShapeXYZ[ id ].SetCoord( 0., 0., 0. );
326   }
327
328
329   // 4. Fill the rest repers
330   bool bIsUpperLayer;
331   int iBNID;
332   SMESH_Block::TShapeID aSSID, aBNSSID;
333   StdMeshers_TNode aTN;
334   //
335
336   // create top face and find UV for it's corners
337   const TopoDS_Face& TopFace = TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy1));
338   SMESHDS_Mesh* meshDS = pMesh->GetMeshDS();
339   int topfaceID = meshDS->ShapeToIndex(TopFace);
340   const TopoDS_Vertex& v001 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V001));
341   SMDS_NodeIteratorPtr itn = pMesh->GetSubMeshContaining(v001)->GetSubMeshDS()->GetNodes();
342   const SMDS_MeshNode* N = itn->next();
343   gp_XY UV001 = myTool->GetNodeUV(TopFace,N);
344   const TopoDS_Vertex& v101 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V101));
345   itn = pMesh->GetSubMeshContaining(v101)->GetSubMeshDS()->GetNodes();
346   N = itn->next();
347   gp_XY UV101 = myTool->GetNodeUV(TopFace,N);
348   const TopoDS_Vertex& v011 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V011));
349   itn = pMesh->GetSubMeshContaining(v011)->GetSubMeshDS()->GetNodes();
350   N = itn->next();
351   gp_XY UV011 = myTool->GetNodeUV(TopFace,N);
352   const TopoDS_Vertex& v111 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V111));
353   itn = pMesh->GetSubMeshContaining(v111)->GetSubMeshDS()->GetNodes();
354   N = itn->next();
355   gp_XY UV111 = myTool->GetNodeUV(TopFace,N);
356
357   for (j=0; j<myJSize; ++j) { // loop on all nodes of the base face (ID_Fxy0)
358     // base node info
359     const StdMeshers_TNode& aBN = myTNodes[j];
360     aBNSSID = (SMESH_Block::TShapeID)aBN.ShapeSupportID();
361     iBNID = aBN.BaseNodeID();
362     const gp_XYZ& aBNXYZ = aBN.NormCoord();
363     bool createNode = ( aBNSSID == SMESH_Block::ID_Fxy0 ); // if base node is inside a bottom face
364     //
365     // set XYZ on horizontal edges and get node columns of faces:
366     // 2 columns for each face, between which a base node is located
367     vector<const SMDS_MeshNode*>* nColumns[8];
368     double ratio[ NB_WALL_FACES ]; // base node position between columns [0.-1.]
369     if ( createNode ) {
370       for ( k = 0; k < NB_WALL_FACES ; ++k ) {
371         ratio[ k ] = SetHorizEdgeXYZ (aBNXYZ, wallFaceID[ k ],
372                                       nColumns[k*2], nColumns[k*2+1]);
373       }
374     }
375     //
376     // XYZ on the bottom and top faces
377     const SMDS_MeshNode* n = aBN.Node();
378     myShapeXYZ[ SMESH_Block::ID_Fxy0 ].SetCoord( n->X(), n->Y(), n->Z() );
379     myShapeXYZ[ SMESH_Block::ID_Fxy1 ].SetCoord( 0., 0., 0. );
380     //
381     // first create or find a top node, then the rest ones in a column
382     for (i=myISize-1; i>0; --i) // vertical loop, from top to bottom
383     {
384       bIsUpperLayer = (i==(myISize-1));
385       gp_XY UV_Ex01, UV_Ex11, UV_E0y1, UV_E1y1;
386       if ( createNode ) // a base node is inside a top face
387       {
388         // set XYZ on vertical edges and faces
389         for ( k = 0; k < NB_WALL_FACES ; ++k ) {
390           // XYZ on a vertical edge 
391           const SMDS_MeshNode* n = (*verticEdgeNodes[ k ]) [ i ];
392           myShapeXYZ[ verticEdgeID[ k ] ].SetCoord( n->X(), n->Y(), n->Z() );
393           // XYZ on a face (part 1 from one column)
394           n = (*nColumns[k*2]) [ i ];
395           gp_XYZ xyz( n->X(), n->Y(), n->Z() );
396           myShapeXYZ[ wallFaceID[ k ]] = ( 1. - ratio[ k ]) * xyz;
397           gp_XY tmp1;
398           if( bIsUpperLayer ) {
399             tmp1 = myTool->GetNodeUV(TopFace,n);
400             tmp1 = ( 1. - ratio[ k ]) * tmp1;
401           }
402           // XYZ on a face (part 2 from other column)
403           n = (*nColumns[k*2+1]) [ i ];
404           xyz.SetCoord( n->X(), n->Y(), n->Z() );
405           myShapeXYZ[ wallFaceID[ k ]] += ratio[ k ] * xyz;
406           if( bIsUpperLayer ) {
407             gp_XY tmp2 = myTool->GetNodeUV(TopFace,n);
408             tmp1 +=  ratio[ k ] * tmp2;
409             if( k==0 )
410               UV_Ex01 = tmp1;
411             else if( k==1 )
412               UV_Ex11 = tmp1;
413             else if( k==2 )
414               UV_E0y1 = tmp1;
415             else
416               UV_E1y1 = tmp1;
417           }
418         }
419       }
420       // fill current node info
421       //   -index in aTNodes
422       ij=i*myJSize+j; 
423       //   -normalized coordinates  
424       aX=aBNXYZ.X();  
425       aY=aBNXYZ.Y();
426       //aZ=aZL[i];
427       aZ=(double)i/(double)(myISize-1);
428       aCoords.SetCoord(aX, aY, aZ);
429       //
430       //   suporting shape ID
431       ShapeSupportID(bIsUpperLayer, aBNSSID, aSSID);
432       if (myErrorStatus) {
433         MESSAGE("StdMeshers_Penta_3D::MakeNodes() ");
434         return;
435       }
436       //
437       aTN.SetShapeSupportID(aSSID);
438       aTN.SetNormCoord(aCoords);
439       aTN.SetBaseNodeID(iBNID);
440       //
441       if (aSSID!=SMESH_Block::ID_NONE){
442         // try to find the node
443         const TopoDS_Shape& aS=myBlock.Shape((int)aSSID);
444         FindNodeOnShape(aS, aCoords, i, aTN);
445       }
446       else{
447         // create node and get it id
448         CreateNode (bIsUpperLayer, aCoords, aTN);
449         //
450         if ( bIsUpperLayer ) {
451           const SMDS_MeshNode* n = aTN.Node();
452           myShapeXYZ[ SMESH_Block::ID_Fxy1 ].SetCoord( n->X(), n->Y(), n->Z() );
453           // set node on top face:
454           // find UV parameter for this node
455           //              UV_Ex11
456           //   UV011+-----+----------+UV111
457           //        |                |
458           //        |                |
459           // UV_E0y1+     +node      +UV_E1y1
460           //        |                |
461           //        |                |
462           //        |                |
463           //   UV001+-----+----------+UV101
464           //              UV_Ex01
465           gp_Pnt2d aP;
466           double u = aCoords.X(), v = aCoords.Y();
467           double u1 = ( 1. - u ), v1 = ( 1. - v );
468           aP.ChangeCoord()  = UV_Ex01 * v1;
469           aP.ChangeCoord() += UV_Ex11 * v;
470           aP.ChangeCoord() += UV_E0y1 * u1;
471           aP.ChangeCoord() += UV_E1y1 * u;
472           aP.ChangeCoord() -= UV001 * u1 * v1;
473           aP.ChangeCoord() -= UV101 * u  * v1;
474           aP.ChangeCoord() -= UV011 * u1 * v;
475           aP.ChangeCoord() -= UV111 * u  * v;
476           meshDS->SetNodeOnFace((SMDS_MeshNode*)n, topfaceID, aP.X(), aP.Y());
477         }
478       }
479       if (myErrorStatus) {
480         MESSAGE("StdMeshers_Penta_3D::MakeNodes() ");
481         return;
482       }
483       //
484       myTNodes[ij]=aTN;
485     }
486   }
487   //DEB
488   /*
489   {
490     int iSSID, iBNID, aID;
491     //
492     for (i=0; i<myISize; ++i) {
493       printf(" Layer# %d\n", i);
494       for (j=0; j<myJSize; ++j) {
495         ij=i*myJSize+j; 
496         const StdMeshers_TNode& aTN=myTNodes[ij];
497         //const StdMeshers_TNode& aTN=aTNodes[ij];
498         const gp_XYZ& aXYZ=aTN.NormCoord();
499         iSSID=aTN.ShapeSupportID();
500         iBNID=aTN.BaseNodeID();
501         //
502         const SMDS_MeshNode* aNode=aTN.Node();
503         aID=aNode->GetID(); 
504         aX=aNode->X();
505         aY=aNode->Y();
506         aZ=aNode->Z();
507         printf("*** j:%d BNID#%d iSSID:%d ID:%d { %lf %lf %lf },  { %lf %lf %lf }\n",
508                j,  iBNID, iSSID, aID, aXYZ.X(),  aXYZ.Y(), aXYZ.Z(), aX, aY, aZ);
509       }
510     }
511   }
512   */
513   //DEB t
514 }
515
516
517 //=======================================================================
518 //function : FindNodeOnShape
519 //purpose  : 
520 //=======================================================================
521
522 void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS,
523                                           const gp_XYZ&       aParams,
524                                           const int           z,
525                                           StdMeshers_TNode&   aTN)
526 {
527   myErrorStatus=0;
528   //
529   double aX, aY, aZ, aD, aTol2, minD;
530   gp_Pnt aP1, aP2;
531   //
532   SMESH_Mesh* pMesh = GetMesh();
533   aTol2 = myTol3D*myTol3D;
534   minD = 1.e100;
535   SMDS_MeshNode* pNode = NULL;
536   //
537   if ( aS.ShapeType() == TopAbs_FACE ||
538        aS.ShapeType() == TopAbs_EDGE ) {
539     // find a face ID to which aTN belongs to
540     int faceID;
541     if ( aS.ShapeType() == TopAbs_FACE )
542       faceID = myBlock.ShapeID( aS );
543     else { // edge maybe vertical or top horizontal
544       gp_XYZ aCoord = aParams;
545       if ( aCoord.Z() == 1. )
546         aCoord.SetZ( 0.5 ); // move from top down
547       else
548         aCoord.SetX( 0.5 ); // move along X
549       faceID = SMESH_Block::GetShapeIDByParams( aCoord );
550     }
551     ASSERT( SMESH_Block::IsFaceID( faceID ));
552     int fIndex = SMESH_Block::ShapeIndex( faceID );
553     StdMeshers_IJNodeMap & ijNodes = myWallNodesMaps[ fIndex ];
554     // look for a base node in ijNodes
555     const SMDS_MeshNode* baseNode = pMesh->GetMeshDS()->FindNode( aTN.BaseNodeID() );
556     StdMeshers_IJNodeMap::const_iterator par_nVec = ijNodes.begin();
557     for ( ; par_nVec != ijNodes.end(); par_nVec++ )
558       if ( par_nVec->second[ 0 ] == baseNode ) {
559         pNode = (SMDS_MeshNode*)par_nVec->second.at( z );
560         aTN.SetNode(pNode);
561         return;
562       }
563   }
564   //
565   myBlock.Point(aParams, aS, aP1);
566   //
567   SMDS_NodeIteratorPtr ite=
568     pMesh->GetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes();
569   while(ite->more()) {
570     const SMDS_MeshNode* aNode = ite->next();
571     if(myTool->IsMedium(aNode))
572       continue;
573     aX=aNode->X();
574     aY=aNode->Y();
575     aZ=aNode->Z();
576     aP2.SetCoord(aX, aY, aZ);
577     aD=(double)aP1.SquareDistance(aP2);
578     //printf("** D=%lf ", aD, aTol2);
579     if (aD < minD) {
580       pNode=(SMDS_MeshNode*)aNode;
581       aTN.SetNode(pNode);
582       minD = aD;
583       //printf(" Ok\n");
584       if (aD<aTol2)
585         return; 
586     }
587   }
588   //
589   //printf(" KO\n");
590   //aTN.SetNode(pNode);
591   //MESSAGE("StdMeshers_Penta_3D::FindNodeOnShape(), can not find the node");
592   //myErrorStatus=11; // can not find the node;
593 }
594
595
596 //=======================================================================
597 //function : SetHorizEdgeXYZ
598 //purpose  : 
599 //=======================================================================
600
601 double StdMeshers_Penta_3D::SetHorizEdgeXYZ(const gp_XYZ&                  aBaseNodeParams,
602                                             const int                      aFaceID,
603                                             vector<const SMDS_MeshNode*>*& aCol1,
604                                             vector<const SMDS_MeshNode*>*& aCol2)
605 {
606   // find base and top edges of the face
607   enum { BASE = 0, TOP };
608   vector< int > edgeVec; // 0-base, 1-top
609   SMESH_Block::GetFaceEdgesIDs( aFaceID, edgeVec );
610   //
611   int coord = SMESH_Block::GetCoordIndOnEdge( edgeVec[ BASE ] );
612   bool isForward = myBlock.IsForwadEdge( edgeVec[ BASE ] );
613
614   double param = aBaseNodeParams.Coord( coord );
615   if ( !isForward)
616     param = 1. - param;
617   //
618   // look for columns around param
619   StdMeshers_IJNodeMap & ijNodes =
620     myWallNodesMaps[ SMESH_Block::ShapeIndex( aFaceID )];
621   StdMeshers_IJNodeMap::iterator par_nVec_1 = ijNodes.begin();
622   while ( par_nVec_1->first < param )
623     par_nVec_1++;
624   StdMeshers_IJNodeMap::iterator par_nVec_2 = par_nVec_1;
625   //
626   double r = 0;
627   if ( par_nVec_1 != ijNodes.begin() ) {
628     par_nVec_1--;
629     r = ( param - par_nVec_1->first ) / ( par_nVec_2->first - par_nVec_1->first );
630   }
631   aCol1 = & par_nVec_1->second;
632   aCol2 = & par_nVec_2->second;
633
634   // top edge
635   if (1) {
636     // this variant is better for cases with curved edges and
637     // different nodes distribution on top and base edges
638     const SMDS_MeshNode* n1 = aCol1->back();
639     const SMDS_MeshNode* n2 = aCol2->back();
640     gp_XYZ xyz1( n1->X(), n1->Y(), n1->Z() );
641     gp_XYZ xyz2( n2->X(), n2->Y(), n2->Z() );
642     myShapeXYZ[ edgeVec[ 1 ] ] = ( 1. - r ) * xyz1 + r * xyz2;
643   }
644   else {
645     // this variant is better for other cases
646 //   SMESH_MesherHelper helper( *GetMesh() );
647 //   const TopoDS_Edge & edge = TopoDS::Edge( myBlock.Shape( edgeVec[ TOP ]));
648 //   double u1 = helper.GetNodeU( edge, n1 );
649 //   double u2 = helper.GetNodeU( edge, n2 );
650 //   double u = ( 1. - r ) * u1 + r * u2;
651 //   gp_XYZ topNodeParams;
652 //   myBlock.Block().EdgeParameters( edgeVec[ TOP ], u, topNodeParams );
653 //   myBlock.Block().EdgePoint( edgeVec[ TOP ],
654 //                              topNodeParams,
655 //                              myShapeXYZ[ edgeVec[ TOP ]]);
656   }
657
658   // base edge
659   myBlock.Block().EdgePoint( edgeVec[ BASE ],
660                              aBaseNodeParams,
661                              myShapeXYZ[ edgeVec[ BASE ]]);
662   return r;
663 }
664
665
666 //=======================================================================
667 //function : MakeVolumeMesh
668 //purpose  : 
669 //=======================================================================
670 void StdMeshers_Penta_3D::MakeVolumeMesh()
671 {
672   myErrorStatus=0;
673   //
674   int i, j, ij, ik, i1, i2, aSSID; 
675   //
676   SMESH_Mesh*   pMesh = GetMesh();
677   SMESHDS_Mesh* meshDS = pMesh->GetMeshDS();
678   //
679   int shapeID = meshDS->ShapeToIndex( myShape );
680   //
681   // 1. Set Node In Volume
682   ik = myISize-1;
683   for (i=1; i<ik; ++i){
684     for (j=0; j<myJSize; ++j){
685       ij=i*myJSize+j;
686       const StdMeshers_TNode& aTN = myTNodes[ij];
687       aSSID=aTN.ShapeSupportID();
688       if (aSSID==SMESH_Block::ID_NONE) {
689         SMDS_MeshNode* aNode = (SMDS_MeshNode*)aTN.Node();
690         meshDS->SetNodeInVolume(aNode, shapeID);
691       }
692     }
693   }
694   //
695   // 2. Make pentahedrons
696   int aID0, k , aJ[3];
697   vector<const SMDS_MeshNode*> aN;
698   //
699   SMDS_ElemIteratorPtr itf, aItNodes;
700   //
701   const TopoDS_Face& aFxy0=
702     TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy0));
703   SMESH_subMesh *aSubMesh0 = pMesh->GetSubMeshContaining(aFxy0);
704   SMESHDS_SubMesh *aSM0 = aSubMesh0->GetSubMeshDS();
705   //
706   itf = aSM0->GetElements();
707   while(itf->more()) {
708     const SMDS_MeshElement* pE0 = itf->next();
709     //
710     int nbFaceNodes = pE0->NbNodes();
711     if(myCreateQuadratic)
712       nbFaceNodes = nbFaceNodes/2;
713     if ( aN.size() < nbFaceNodes * 2 )
714       aN.resize( nbFaceNodes * 2 );
715     //
716     k=0;
717     aItNodes=pE0->nodesIterator();
718     while (aItNodes->more()) {
719       //const SMDS_MeshElement* pNode = aItNodes->next();
720       const SMDS_MeshNode* pNode =
721         static_cast<const SMDS_MeshNode*> (aItNodes->next());
722       if(myTool->IsMedium(pNode))
723         continue;
724       aID0 = pNode->GetID();
725       aJ[k] = GetIndexOnLayer(aID0);
726       if (myErrorStatus) {
727         MESSAGE("StdMeshers_Penta_3D::MakeVolumeMesh");
728         return;
729       }
730       //
731       ++k;
732     }
733     //
734     bool forward = true;
735     for (i=0; i<ik; ++i) {
736       i1=i;
737       i2=i+1;
738       for(j=0; j<nbFaceNodes; ++j) {
739         ij = i1*myJSize+aJ[j];
740         const StdMeshers_TNode& aTN1 = myTNodes[ij];
741         const SMDS_MeshNode* aN1 = aTN1.Node();
742         aN[j]=aN1;
743         //
744         ij=i2*myJSize+aJ[j];
745         const StdMeshers_TNode& aTN2 = myTNodes[ij];
746         const SMDS_MeshNode* aN2 = aTN2.Node();
747         aN[j+nbFaceNodes] = aN2;
748       }
749       // check if volume orientation will be ok
750       if ( i == 0 ) {
751         SMDS_VolumeTool vTool;
752         switch ( nbFaceNodes ) {
753         case 3: {
754           SMDS_VolumeOfNodes tmpVol (aN[0], aN[1], aN[2],
755                                      aN[3], aN[4], aN[5]);
756           vTool.Set( &tmpVol );
757           break;
758         }
759         case 4: {
760           SMDS_VolumeOfNodes tmpVol(aN[0], aN[1], aN[2], aN[3],
761                                     aN[4], aN[5], aN[6], aN[7]);
762           vTool.Set( &tmpVol );
763           break;
764         }
765         default:
766           continue;
767         }
768         forward = vTool.IsForward();
769       }
770       // add volume
771       SMDS_MeshVolume* aV = 0;
772       switch ( nbFaceNodes ) {
773       case 3:
774         if ( forward ) {
775           //aV = meshDS->AddVolume(aN[0], aN[1], aN[2],
776           //                       aN[3], aN[4], aN[5]);
777           aV = myTool->AddVolume(aN[0], aN[1], aN[2], aN[3], aN[4], aN[5]);
778         }
779         else {
780           //aV = meshDS->AddVolume(aN[0], aN[2], aN[1],
781           //                       aN[3], aN[5], aN[4]);
782           aV = myTool->AddVolume(aN[0], aN[2], aN[1], aN[3], aN[5], aN[4]);
783         }
784         break;
785       case 4:
786         if ( forward ) {
787           //aV = meshDS->AddVolume(aN[0], aN[1], aN[2], aN[3],
788           //                       aN[4], aN[5], aN[6], aN[7]);
789           aV = myTool->AddVolume(aN[0], aN[1], aN[2], aN[3],
790                                  aN[4], aN[5], aN[6], aN[7]);
791         }
792         else {
793           //aV = meshDS->AddVolume(aN[0], aN[3], aN[2], aN[1],
794           //                       aN[4], aN[7], aN[6], aN[5]);
795           aV = myTool->AddVolume(aN[0], aN[3], aN[2], aN[1],
796                                  aN[4], aN[7], aN[6], aN[5]);
797         }
798         break;
799       default:
800         continue;
801       }
802       meshDS->SetMeshElementOnShape(aV, shapeID);
803     }
804   }
805 }
806
807 //=======================================================================
808 //function : MakeMeshOnFxy1
809 //purpose  : 
810 //=======================================================================
811 void StdMeshers_Penta_3D::MakeMeshOnFxy1()
812 {
813   myErrorStatus=0;
814   //
815   int aID0, aJ, aLevel, ij, aNbNodes, k;
816   //
817   SMDS_NodeIteratorPtr itn;
818   SMDS_ElemIteratorPtr itf, aItNodes;
819   SMDSAbs_ElementType aElementType;
820   //
821   const TopoDS_Face& aFxy0=
822     TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy0));
823   const TopoDS_Face& aFxy1=
824     TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy1));
825   SMESH_MesherHelper faceHelper( *GetMesh() );
826   faceHelper.IsQuadraticSubMesh(aFxy1);
827   //
828   SMESH_Mesh* pMesh = GetMesh();
829   SMESHDS_Mesh * meshDS = pMesh->GetMeshDS();
830   //
831   SMESH_subMesh *aSubMesh0 = pMesh->GetSubMeshContaining(aFxy0);
832   SMESHDS_SubMesh *aSM0 = aSubMesh0->GetSubMeshDS();
833   //
834   // set nodes on aFxy1
835   aLevel = myISize-1;
836   itn = aSM0->GetNodes();
837   aNbNodes = aSM0->NbNodes();
838   //printf("** aNbNodes=%d\n", aNbNodes);
839
840   //
841   // set elements on aFxy1
842   vector<const SMDS_MeshNode*> aNodes1;
843   //
844   itf = aSM0->GetElements();
845   while(itf->more()) {
846     const SMDS_MeshElement* pE0 = itf->next();
847     aElementType = pE0->GetType();
848     if (!aElementType==SMDSAbs_Face) {
849       continue;
850     }
851     aNbNodes = pE0->NbNodes();
852     if(myCreateQuadratic)
853       aNbNodes = aNbNodes/2;
854     if ( aNodes1.size() < aNbNodes )
855       aNodes1.resize( aNbNodes );
856     //
857     k = aNbNodes-1; // reverse a face
858     aItNodes = pE0->nodesIterator();
859     while (aItNodes->more()) {
860       //const SMDS_MeshElement* pNode = aItNodes->next();
861       const SMDS_MeshNode* pNode =
862         static_cast<const SMDS_MeshNode*> (aItNodes->next());
863       if(myTool->IsMedium(pNode))
864         continue;
865       aID0 = pNode->GetID();
866       aJ = GetIndexOnLayer(aID0);
867       if (myErrorStatus) {
868         MESSAGE("StdMeshers_Penta_3D::MakeMeshOnFxy1() ");
869         return;
870       }
871       //
872       ij = aLevel*myJSize + aJ;
873       const StdMeshers_TNode& aTN1 = myTNodes[ij];
874       const SMDS_MeshNode* aN1 = aTN1.Node();
875       aNodes1[k] = aN1;
876       --k;
877     }
878     SMDS_MeshFace * face = 0;
879     switch ( aNbNodes ) {
880     case 3:
881       face = faceHelper.AddFace(aNodes1[0], aNodes1[1], aNodes1[2]);
882       break;
883     case 4:
884       face = faceHelper.AddFace(aNodes1[0], aNodes1[1], aNodes1[2], aNodes1[3]);
885       break;
886     default:
887       continue;
888     }
889     meshDS->SetMeshElementOnShape(face, aFxy1);
890   }
891 }
892
893 //=======================================================================
894 //function : ClearMeshOnFxy1
895 //purpose  : 
896 //=======================================================================
897 void StdMeshers_Penta_3D::ClearMeshOnFxy1()
898 {
899   myErrorStatus=0;
900   //
901   SMESH_subMesh* aSubMesh;
902   SMESH_Mesh* pMesh=GetMesh();
903   //
904   const TopoDS_Shape& aFxy1=myBlock.Shape(SMESH_Block::ID_Fxy1);
905   aSubMesh = pMesh->GetSubMeshContaining(aFxy1);
906   if (aSubMesh)
907     aSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN );
908 }
909
910 //=======================================================================
911 //function : GetIndexOnLayer
912 //purpose  : 
913 //=======================================================================
914 int StdMeshers_Penta_3D::GetIndexOnLayer(const int aID)
915 {
916   myErrorStatus=0;
917   //
918   int j=-1;
919   StdMeshers_IteratorOfDataMapOfIntegerInteger aMapIt;
920   //
921   aMapIt=myConnectingMap.find(aID);
922   if (aMapIt==myConnectingMap.end()) {
923     myErrorStatus=200;
924     return j;
925   }
926   j=(*aMapIt).second;
927   return j;
928 }
929
930 //=======================================================================
931 //function : MakeConnectingMap
932 //purpose  : 
933 //=======================================================================
934 void StdMeshers_Penta_3D::MakeConnectingMap()
935 {
936   int j, aBNID;
937   //
938   for (j=0; j<myJSize; ++j) {
939     const StdMeshers_TNode& aBN=myTNodes[j];
940     aBNID=aBN.BaseNodeID();
941     myConnectingMap[aBNID]=j;
942   }
943 }
944
945 //=======================================================================
946 //function : CreateNode
947 //purpose  : 
948 //=======================================================================
949 void StdMeshers_Penta_3D::CreateNode(const bool bIsUpperLayer,
950                                      const gp_XYZ& aParams,
951                                      StdMeshers_TNode& aTN)
952 {
953   myErrorStatus=0;
954   //
955   // int iErr;
956   double aX, aY, aZ;
957   //
958   gp_Pnt aP;
959   //
960   SMDS_MeshNode* pNode=NULL; 
961   aTN.SetNode(pNode);  
962   //
963 //   if (bIsUpperLayer) {
964 //     // point on face Fxy1
965 //     const TopoDS_Shape& aS=myBlock.Shape(SMESH_Block::ID_Fxy1);
966 //     myBlock.Point(aParams, aS, aP);
967 //   }
968 //   else {
969 //     // point inside solid
970 //     myBlock.Point(aParams, aP);
971 //   }
972   if (bIsUpperLayer) {
973     double u = aParams.X(), v = aParams.Y();
974     double u1 = ( 1. - u ), v1 = ( 1. - v );
975     aP.ChangeCoord()  = myShapeXYZ[ SMESH_Block::ID_Ex01 ] * v1;
976     aP.ChangeCoord() += myShapeXYZ[ SMESH_Block::ID_Ex11 ] * v;
977     aP.ChangeCoord() += myShapeXYZ[ SMESH_Block::ID_E0y1 ] * u1;
978     aP.ChangeCoord() += myShapeXYZ[ SMESH_Block::ID_E1y1 ] * u;
979
980     aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V001 ] * u1 * v1;
981     aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V101 ] * u  * v1;
982     aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V011 ] * u1 * v;
983     aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V111 ] * u  * v;
984   }
985   else {
986     SMESH_Block::ShellPoint( aParams, myShapeXYZ, aP.ChangeCoord() );
987   }
988   //
989 //   iErr=myBlock.ErrorStatus();
990 //   if (iErr) {
991 //     myErrorStatus=12; // can not find the node point;
992 //     return;
993 //   }
994   //
995   aX=aP.X(); aY=aP.Y(); aZ=aP.Z(); 
996   //
997   SMESH_Mesh* pMesh = GetMesh();
998   SMESHDS_Mesh* pMeshDS = pMesh->GetMeshDS();
999   //
1000   pNode = pMeshDS->AddNode(aX, aY, aZ);
1001   
1002   aTN.SetNode(pNode);
1003 }
1004
1005 //=======================================================================
1006 //function : ShapeSupportID
1007 //purpose  : 
1008 //=======================================================================
1009 void StdMeshers_Penta_3D::ShapeSupportID(const bool bIsUpperLayer,
1010                                          const SMESH_Block::TShapeID aBNSSID,
1011                                          SMESH_Block::TShapeID& aSSID)
1012 {
1013   myErrorStatus=0;
1014   //
1015   switch (aBNSSID) {
1016     case SMESH_Block::ID_V000:
1017       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_V001 : SMESH_Block::ID_E00z;
1018       break;
1019     case SMESH_Block::ID_V100:
1020       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_V101 : SMESH_Block::ID_E10z;
1021       break; 
1022     case SMESH_Block::ID_V110:
1023       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_V111 : SMESH_Block::ID_E11z;
1024       break;
1025     case SMESH_Block::ID_V010:
1026       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_V011 : SMESH_Block::ID_E01z;
1027       break;
1028     case SMESH_Block::ID_Ex00:
1029       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_Ex01 : SMESH_Block::ID_Fx0z;
1030       break;
1031     case SMESH_Block::ID_Ex10:
1032       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_Ex11 : SMESH_Block::ID_Fx1z;
1033       break; 
1034     case SMESH_Block::ID_E0y0:
1035       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_E0y1 : SMESH_Block::ID_F0yz;
1036       break; 
1037     case SMESH_Block::ID_E1y0:
1038       aSSID=(bIsUpperLayer) ?  SMESH_Block::ID_E1y1 : SMESH_Block::ID_F1yz;
1039       break; 
1040     case SMESH_Block::ID_Fxy0:
1041       aSSID=SMESH_Block::ID_NONE;//(bIsUpperLayer) ?  Shape_ID_Fxy1 : Shape_ID_NONE;
1042       break;   
1043     default:
1044       aSSID=SMESH_Block::ID_NONE;
1045       myErrorStatus=10; // Can not find supporting shape ID
1046       break;
1047   }
1048   return;
1049 }
1050 //=======================================================================
1051 //function : MakeBlock
1052 //purpose  : 
1053 //=======================================================================
1054 void StdMeshers_Penta_3D::MakeBlock()
1055 {
1056   myErrorStatus=0;
1057   //
1058   bool bFound;
1059   int i, j, iNbEV, iNbE, iErr, iCnt, iNbNodes, iNbF;
1060   //
1061   TopoDS_Vertex aV000, aV001;
1062   TopoDS_Shape aFTr;
1063   TopTools_IndexedDataMapOfShapeListOfShape aMVES;
1064   TopTools_IndexedMapOfShape aME ,aMEV, aM;
1065   TopTools_ListIteratorOfListOfShape aIt;
1066   //
1067   TopExp::MapShapes(myShape, TopAbs_FACE, aM);
1068   //
1069   // 0. Find triangulated face aFTr
1070   SMDSAbs_ElementType aElementType;
1071   SMESH_Mesh* pMesh=GetMesh();
1072   //
1073   iCnt = 0;
1074   iNbF = aM.Extent();
1075   for (i=1; i<=iNbF; ++i) {
1076     const TopoDS_Shape& aF = aM(i);
1077     SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aF);
1078     ASSERT(aSubMesh);
1079     SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS();
1080     SMDS_ElemIteratorPtr itf = aSM->GetElements();
1081     while(itf->more()) {
1082       const SMDS_MeshElement * pElement = itf->next();
1083       aElementType = pElement->GetType();
1084       if (aElementType==SMDSAbs_Face) {
1085         iNbNodes = pElement->NbNodes();
1086         if ( iNbNodes==3 || (myCreateQuadratic && iNbNodes==6) ) {
1087           aFTr = aF;
1088           ++iCnt;
1089           if (iCnt>1) {
1090             // \begin{E.A.}
1091             // The current algorithm fails if there is more that one
1092             // face wich contains triangles ...
1093             // In that case, replace return by break to try another
1094             // method (coded in "if (iCnt != 1) { ... }")
1095             //
1096             // MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1097             // myErrorStatus=5; // more than one face has triangulation
1098             // return;
1099             break;
1100             // \end{E.A.}
1101           }
1102           break; // next face
1103         }
1104       }
1105     }
1106   }
1107   //
1108   // \begin{E.A.}
1109   // The current algorithm fails if "iCnt != 1", the case "iCnt == 0"
1110   // was not reached 'cause it was not called from Hexa_3D ... Now it
1111   // can occurs and in my opinion, it is the most common case.
1112   //
1113   if (iCnt != 1) {
1114     // The suggested algorithm is the following :
1115     //
1116     // o Check that nb_of_faces == 6 and nb_of_edges == 12
1117     //   then the shape is tologically equivalent to a box
1118     // o In a box, there are three set of four // edges ...
1119     //   In the cascade notation, it seems to be the edges
1120     //   numbered : 
1121     //     - 1, 3, 5, 7
1122     //     - 2, 4, 6, 8
1123     //     - 9, 10, 11, 12
1124     // o For each one of this set, check if the four edges
1125     //   have the same number of element.
1126     // o If so, check if the "corresponding" // faces contains
1127     //   only quads. It's the faces numbered:
1128     //     - 1, 2, 3, 4
1129     //     - 1, 2, 5, 6
1130     //     - 3, 4, 5, 6
1131     // o If so, check if the opposite edges of each // faces
1132     //   have the same number of elements. It is the edges
1133     //   numbered :
1134     //     - 2 and 4, 6 and 8, 9 and 10, 11 and 12
1135     //     - 1 and 3, 5 and 7, 9 and 11, 10 and 12
1136     //     - 1 and 5, 3 and 7, 4 and 8, 2 and 6
1137     // o If so, check if the two other faces have the same
1138     //   number of elements. It is the faces numbered:
1139     //     - 5, 6
1140     //     - 3, 4
1141     //     - 1, 2
1142     //   This test should be improved to test if the nodes
1143     //   of the two faces are really "en face".
1144     // o If so, one of the two faces is a candidate to an extrusion,
1145     //   It is the faces numbered :
1146     //     - 5
1147     //     - 3
1148     //     - 1
1149     // o Finally, if there is only one candidate, let do the
1150     //   extrusion job for the corresponding face
1151     //
1152     int isOK = 0;
1153     //
1154     int iNbF = aM.Extent();
1155     if (iNbF == 6) {
1156       //
1157       int nb_f1 = pMesh->GetSubMeshContaining(aM(1))->GetSubMeshDS()->NbElements();
1158       int nb_f2 = pMesh->GetSubMeshContaining(aM(2))->GetSubMeshDS()->NbElements();
1159       int nb_f3 = pMesh->GetSubMeshContaining(aM(3))->GetSubMeshDS()->NbElements();
1160       int nb_f4 = pMesh->GetSubMeshContaining(aM(4))->GetSubMeshDS()->NbElements();
1161       int nb_f5 = pMesh->GetSubMeshContaining(aM(5))->GetSubMeshDS()->NbElements();
1162       int nb_f6 = pMesh->GetSubMeshContaining(aM(6))->GetSubMeshDS()->NbElements();
1163       //
1164       int has_only_quad_f1 = 1;
1165       int has_only_quad_f2 = 1;
1166       int has_only_quad_f3 = 1;
1167       int has_only_quad_f4 = 1;
1168       int has_only_quad_f5 = 1;
1169       int has_only_quad_f6 = 1;
1170       //
1171       for (i=1; i<=iNbF; ++i) {
1172         int ok = 1;
1173         const TopoDS_Shape& aF = aM(i);
1174         SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aF);
1175         SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS();
1176         SMDS_ElemIteratorPtr itf = aSM->GetElements();
1177         while(itf->more()) {
1178           const SMDS_MeshElement * pElement = itf->next();
1179           aElementType = pElement->GetType();
1180           if (aElementType==SMDSAbs_Face) {
1181             iNbNodes = pElement->NbNodes();
1182             if ( iNbNodes!=4 ) {
1183               ok = 0;
1184               break ;
1185             }
1186           }
1187         }
1188         if (i==1) has_only_quad_f1 = ok ;
1189         if (i==2) has_only_quad_f2 = ok ;
1190         if (i==3) has_only_quad_f3 = ok ;
1191         if (i==4) has_only_quad_f4 = ok ;
1192         if (i==5) has_only_quad_f5 = ok ;
1193         if (i==6) has_only_quad_f6 = ok ;
1194       }
1195       //
1196       TopTools_IndexedMapOfShape aE;
1197       TopExp::MapShapes(myShape, TopAbs_EDGE, aE);
1198       int iNbE = aE.Extent();
1199       if (iNbE == 12) {
1200         //
1201         int nb_e01 = pMesh->GetSubMeshContaining(aE(1))->GetSubMeshDS()->NbElements();
1202         int nb_e02 = pMesh->GetSubMeshContaining(aE(2))->GetSubMeshDS()->NbElements();
1203         int nb_e03 = pMesh->GetSubMeshContaining(aE(3))->GetSubMeshDS()->NbElements();
1204         int nb_e04 = pMesh->GetSubMeshContaining(aE(4))->GetSubMeshDS()->NbElements();
1205         int nb_e05 = pMesh->GetSubMeshContaining(aE(5))->GetSubMeshDS()->NbElements();
1206         int nb_e06 = pMesh->GetSubMeshContaining(aE(6))->GetSubMeshDS()->NbElements();
1207         int nb_e07 = pMesh->GetSubMeshContaining(aE(7))->GetSubMeshDS()->NbElements();
1208         int nb_e08 = pMesh->GetSubMeshContaining(aE(8))->GetSubMeshDS()->NbElements();
1209         int nb_e09 = pMesh->GetSubMeshContaining(aE(9))->GetSubMeshDS()->NbElements();
1210         int nb_e10 = pMesh->GetSubMeshContaining(aE(10))->GetSubMeshDS()->NbElements();
1211         int nb_e11 = pMesh->GetSubMeshContaining(aE(11))->GetSubMeshDS()->NbElements();
1212         int nb_e12 = pMesh->GetSubMeshContaining(aE(12))->GetSubMeshDS()->NbElements();
1213         //
1214         int nb_ok = 0 ;
1215         //
1216         if ( (nb_e01==nb_e03) && (nb_e03==nb_e05) && (nb_e05==nb_e07) ) {
1217           if ( has_only_quad_f1 && has_only_quad_f2 && has_only_quad_f3 && has_only_quad_f4 ) {
1218             if ( (nb_e09==nb_e10) && (nb_e08==nb_e06) && (nb_e11==nb_e12) && (nb_e04==nb_e02) ) {
1219               if (nb_f5==nb_f6) {
1220                 nb_ok += 1;
1221                 aFTr = aM(5);
1222               }
1223             }
1224           }
1225         }
1226         if ( (nb_e02==nb_e04) && (nb_e04==nb_e06) && (nb_e06==nb_e08) ) {
1227           if ( has_only_quad_f1 && has_only_quad_f2 && has_only_quad_f5 && has_only_quad_f6 ) {
1228             if ( (nb_e01==nb_e03) && (nb_e10==nb_e12) && (nb_e05==nb_e07) && (nb_e09==nb_e11) ) {
1229               if (nb_f3==nb_f4) {
1230                 nb_ok += 1;
1231                 aFTr = aM(3);
1232               }
1233             }
1234           }
1235         }
1236         if ( (nb_e09==nb_e10) && (nb_e10==nb_e11) && (nb_e11==nb_e12) ) {
1237           if ( has_only_quad_f3 && has_only_quad_f4 && has_only_quad_f5 && has_only_quad_f6 ) {
1238             if ( (nb_e01==nb_e05) && (nb_e02==nb_e06) && (nb_e03==nb_e07) && (nb_e04==nb_e08) ) {
1239               if (nb_f1==nb_f2) {
1240                 nb_ok += 1;
1241                 aFTr = aM(1);
1242               }
1243             }
1244           }
1245         }
1246         //
1247         if ( nb_ok == 1 ) {
1248           isOK = 1;
1249         }
1250         //
1251       }
1252     }
1253     if (!isOK) {
1254       myErrorStatus=5; // more than one face has triangulation
1255       return;
1256     }
1257   }
1258   // \end{E.A.}
1259   // 
1260   // 1. Vetrices V00, V001;
1261   //
1262   TopExp::MapShapes(aFTr, TopAbs_EDGE, aME);
1263   TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, aMVES);
1264   //
1265   // 1.1 Base vertex V000
1266   iNbE = aME.Extent();
1267   if (iNbE!= NB_WALL_FACES ){
1268     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1269     myErrorStatus=7; // too few edges are in base face aFTr 
1270     return;
1271   }
1272   const TopoDS_Edge& aE1=TopoDS::Edge(aME(1));
1273   aV000=TopExp::FirstVertex(aE1);
1274   //
1275   const TopTools_ListOfShape& aLE=aMVES.FindFromKey(aV000);
1276   aIt.Initialize(aLE);
1277   for (; aIt.More(); aIt.Next()) {
1278     const TopoDS_Shape& aEx=aIt.Value();
1279     aMEV.Add(aEx);
1280   }
1281   iNbEV=aMEV.Extent();
1282   if (iNbEV!=3){
1283     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1284     myErrorStatus=7; // too few edges meet in base vertex 
1285     return;
1286   }
1287   //
1288   // 1.2 Vertex V001
1289   bFound=false;
1290   for (j=1; j<=iNbEV; ++j) {
1291     const TopoDS_Shape& aEx=aMEV(j);
1292     if (!aME.Contains(aEx)) {
1293       TopoDS_Vertex aV[2];
1294       //
1295       const TopoDS_Edge& aE=TopoDS::Edge(aEx);
1296       TopExp::Vertices(aE, aV[0], aV[1]);
1297       for (i=0; i<2; ++i) {
1298         if (!aV[i].IsSame(aV000)) {
1299           aV001=aV[i];
1300           bFound=!bFound;
1301           break;
1302         }
1303       }
1304     }
1305   }
1306   //
1307   if (!bFound) {
1308     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1309     myErrorStatus=8; // can not find reper V001 
1310     return;
1311   }
1312   //DEB
1313   //gp_Pnt aP000, aP001;
1314   //
1315   //aP000=BRep_Tool::Pnt(TopoDS::Vertex(aV000));
1316   //printf("*** aP000 { %lf, %lf, %lf }\n", aP000.X(), aP000.Y(), aP000.Z());
1317   //aP001=BRep_Tool::Pnt(TopoDS::Vertex(aV001));
1318   //printf("*** aP001 { %lf, %lf, %lf }\n", aP001.X(), aP001.Y(), aP001.Z());
1319   //DEB
1320   //
1321   aME.Clear();
1322   TopExp::MapShapes(myShape, TopAbs_SHELL, aME);
1323   iNbE=aME.Extent();
1324   if (iNbE!=1) {
1325     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1326     myErrorStatus=9; // number of shells in source shape !=1 
1327     return;
1328   }
1329   //
1330   // 2. Load Block
1331   const TopoDS_Shell& aShell=TopoDS::Shell(aME(1));
1332   myBlock.Load(aShell, aV000, aV001);
1333   iErr = myBlock.ErrorStatus();
1334   if (iErr) {
1335     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1336     myErrorStatus=100; // SMESHBlock: Load operation failed
1337     return;
1338   }
1339 }
1340 //=======================================================================
1341 //function : CheckData
1342 //purpose  : 
1343 //=======================================================================
1344 void StdMeshers_Penta_3D::CheckData()
1345 {
1346   myErrorStatus=0;
1347   //
1348   int i, iNb;
1349   int iNbEx[]={8, 12, 6};
1350   //
1351   TopAbs_ShapeEnum aST;
1352   TopAbs_ShapeEnum aSTEx[]={
1353     TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE
1354   }; 
1355   TopTools_IndexedMapOfShape aM;
1356   //
1357   if (myShape.IsNull()){
1358     MESSAGE("StdMeshers_Penta_3D::CheckData() ");
1359     myErrorStatus=2; // null shape
1360     return;
1361   }
1362   //
1363   aST=myShape.ShapeType();
1364   if (!(aST==TopAbs_SOLID || aST==TopAbs_SHELL)) {
1365     MESSAGE("StdMeshers_Penta_3D::CheckData() ");
1366     myErrorStatus=3; // not compatible type of shape
1367     return;
1368   }
1369   //
1370   for (i=0; i<3; ++i) {
1371     aM.Clear();
1372     TopExp::MapShapes(myShape, aSTEx[i], aM);
1373     iNb=aM.Extent();
1374     if (iNb!=iNbEx[i]){
1375       MESSAGE("StdMeshers_Penta_3D::CheckData() ");
1376       myErrorStatus=4; // number of subshape is not compatible
1377       return;
1378     }
1379   }
1380 }
1381
1382 //=======================================================================
1383 //function : LoadIJNodes
1384 //purpose  : Load nodes bound to theFace into column (vectors) and rows
1385 //           of theIJNodes.
1386 //           The value of theIJNodes map is a vector of ordered nodes so
1387 //           that the 0-the one lies on theBaseEdge.
1388 //           The key of theIJNodes map is a normalized parameter of each
1389 //           0-the node on theBaseEdge.
1390 //=======================================================================
1391
1392 bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
1393                                       const TopoDS_Face&     theFace,
1394                                       const TopoDS_Edge&     theBaseEdge,
1395                                       SMESHDS_Mesh*          theMesh)
1396 {
1397   // get vertices of theBaseEdge
1398   TopoDS_Vertex vfb, vlb, vft; // first and last, bottom and top vertices
1399   TopoDS_Edge eFrw = TopoDS::Edge( theBaseEdge.Oriented( TopAbs_FORWARD ));
1400   TopExp::Vertices( eFrw, vfb, vlb );
1401
1402   // find the other edges of theFace and orientation of e1
1403   TopoDS_Edge e1, e2, eTop;
1404   bool rev1, CumOri = false;
1405   TopExp_Explorer exp( theFace, TopAbs_EDGE );
1406   int nbEdges = 0;
1407   for ( ; exp.More(); exp.Next() ) {
1408     if ( ++nbEdges > NB_WALL_FACES ) {
1409       return false; // more than 4 edges in theFace
1410     }
1411     TopoDS_Edge e = TopoDS::Edge( exp.Current() );
1412     if ( theBaseEdge.IsSame( e ))
1413       continue;
1414     TopoDS_Vertex vCommon;
1415     if ( !TopExp::CommonVertex( theBaseEdge, e, vCommon ))
1416       eTop = e;
1417     else if ( vCommon.IsSame( vfb )) {
1418       e1 = e;
1419       vft = TopExp::LastVertex( e1, CumOri );
1420       rev1 = vfb.IsSame( vft );
1421       if ( rev1 )
1422         vft = TopExp::FirstVertex( e1, CumOri );
1423     }
1424     else
1425       e2 = e;
1426   }
1427   if ( nbEdges < NB_WALL_FACES ) {
1428     return false; // less than 4 edges in theFace
1429   }
1430
1431   // submeshes corresponding to shapes
1432   SMESHDS_SubMesh* smFace = theMesh->MeshElements( theFace );
1433   SMESHDS_SubMesh* smb = theMesh->MeshElements( theBaseEdge );
1434   SMESHDS_SubMesh* smt = theMesh->MeshElements( eTop );
1435   SMESHDS_SubMesh* sm1 = theMesh->MeshElements( e1 );
1436   SMESHDS_SubMesh* sm2 = theMesh->MeshElements( e2 );
1437   SMESHDS_SubMesh* smVfb = theMesh->MeshElements( vfb );
1438   SMESHDS_SubMesh* smVlb = theMesh->MeshElements( vlb );
1439   SMESHDS_SubMesh* smVft = theMesh->MeshElements( vft );
1440   if (!smFace || !smb || !smt || !sm1 || !sm2 || !smVfb || !smVlb || !smVft ) {
1441     MESSAGE( "NULL submesh " <<smFace<<" "<<smb<<" "<<smt<<" "<<
1442             sm1<<" "<<sm2<<" "<<smVfb<<" "<<smVlb<<" "<<smVft);
1443     return false;
1444   }
1445   if ( smb->NbNodes() != smt->NbNodes() || sm1->NbNodes() != sm2->NbNodes() ) {
1446     MESSAGE(" Diff nb of nodes on opposite edges" );
1447     return false;
1448   }
1449   if (smVfb->NbNodes() != 1 || smVlb->NbNodes() != 1 || smVft->NbNodes() != 1) {
1450     MESSAGE("Empty submesh of vertex");
1451     return false;
1452   }
1453   if ( sm1->NbNodes() * smb->NbNodes() != smFace->NbNodes() ) {
1454     // check quadratic case
1455     if ( myCreateQuadratic ) {
1456       int n1 = sm1->NbNodes()/2;
1457       int n2 = smb->NbNodes()/2;
1458       int n3 = sm1->NbNodes() - n1;
1459       int n4 = smb->NbNodes() - n2;
1460       int nf = sm1->NbNodes()*smb->NbNodes() - n3*n4;
1461       if( nf != smFace->NbNodes() ) {
1462         MESSAGE( "Wrong nb face nodes: " <<
1463                 sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes());
1464         return false;
1465       }
1466     }
1467     else {
1468       MESSAGE( "Wrong nb face nodes: " <<
1469               sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes());
1470       return false;
1471     }
1472   }
1473   // IJ size
1474   int vsize = sm1->NbNodes() + 2;
1475   int hsize = smb->NbNodes() + 2;
1476   if(myCreateQuadratic) {
1477     vsize = vsize - sm1->NbNodes()/2 -1;
1478     hsize = hsize - smb->NbNodes()/2 -1;
1479   }
1480
1481   // load nodes from theBaseEdge
1482
1483   set<const SMDS_MeshNode*> loadedNodes;
1484   const SMDS_MeshNode* nullNode = 0;
1485
1486   vector<const SMDS_MeshNode*> & nVecf = theIJNodes[ 0.];
1487   nVecf.resize( vsize, nullNode );
1488   loadedNodes.insert( nVecf[ 0 ] = smVfb->GetNodes()->next() );
1489
1490   vector<const SMDS_MeshNode*> & nVecl = theIJNodes[ 1.];
1491   nVecl.resize( vsize, nullNode );
1492   loadedNodes.insert( nVecl[ 0 ] = smVlb->GetNodes()->next() );
1493
1494   double f, l;
1495   BRep_Tool::Range( eFrw, f, l );
1496   double range = l - f;
1497   SMDS_NodeIteratorPtr nIt = smb->GetNodes();
1498   const SMDS_MeshNode* node;
1499   while ( nIt->more() ) {
1500     node = nIt->next();
1501     if(myTool->IsMedium(node))
1502       continue;
1503     const SMDS_EdgePosition* pos =
1504       dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() );
1505     if ( !pos ) {
1506       return false;
1507     }
1508     double u = ( pos->GetUParameter() - f ) / range;
1509     vector<const SMDS_MeshNode*> & nVec = theIJNodes[ u ];
1510     nVec.resize( vsize, nullNode );
1511     loadedNodes.insert( nVec[ 0 ] = node );
1512   }
1513   if ( theIJNodes.size() != hsize ) {
1514     MESSAGE( "Wrong node positions on theBaseEdge" );
1515     return false;
1516   }
1517
1518   // load nodes from e1
1519
1520   map< double, const SMDS_MeshNode*> sortedNodes; // sort by param on edge
1521   nIt = sm1->GetNodes();
1522   while ( nIt->more() ) {
1523     node = nIt->next();
1524     if(myTool->IsMedium(node))
1525       continue;
1526     const SMDS_EdgePosition* pos =
1527       dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() );
1528     if ( !pos ) {
1529       return false;
1530     }
1531     sortedNodes.insert( make_pair( pos->GetUParameter(), node ));
1532   }
1533   loadedNodes.insert( nVecf[ vsize - 1 ] = smVft->GetNodes()->next() );
1534   map< double, const SMDS_MeshNode*>::iterator u_n = sortedNodes.begin();
1535   int row = rev1 ? vsize - 1 : 0;
1536   for ( ; u_n != sortedNodes.end(); u_n++ ) {
1537     if ( rev1 ) row--;
1538     else        row++;
1539     loadedNodes.insert( nVecf[ row ] = u_n->second );
1540   }
1541
1542   // try to load the rest nodes
1543
1544   // get all faces from theFace
1545   map<int,const SMDS_MeshElement*> allFaces, foundFaces;
1546   SMDS_ElemIteratorPtr eIt = smFace->GetElements();
1547   while ( eIt->more() ) {
1548     const SMDS_MeshElement* e = eIt->next();
1549     if ( e->GetType() == SMDSAbs_Face )
1550       allFaces.insert( make_pair(e->GetID(),e) );
1551   }
1552   // Starting from 2 neighbour nodes on theBaseEdge, look for a face
1553   // the nodes belong to, and between the nodes of the found face,
1554   // look for a not loaded node considering this node to be the next
1555   // in a column of the starting second node. Repeat, starting
1556   // from nodes next to the previous starting nodes in their columns,
1557   // and so on while a face can be found. Then go the the next pair
1558   // of nodes on theBaseEdge.
1559   StdMeshers_IJNodeMap::iterator par_nVec_1 = theIJNodes.begin();
1560   StdMeshers_IJNodeMap::iterator par_nVec_2 = par_nVec_1;
1561   // loop on columns
1562   int col = 0;
1563   for ( par_nVec_2++; par_nVec_2 != theIJNodes.end(); par_nVec_1++, par_nVec_2++ ) {
1564     col++;
1565     row = 0;
1566     const SMDS_MeshNode* n1 = par_nVec_1->second[ row ];
1567     const SMDS_MeshNode* n2 = par_nVec_2->second[ row ];
1568     const SMDS_MeshElement* face = 0;
1569     do {
1570       // look for a face by 2 nodes
1571       face = SMESH_MeshEditor::FindFaceInSet( n1, n2, allFaces, foundFaces );
1572       if ( face ) {
1573         int nbFaceNodes = face->NbNodes();
1574         if ( (!myCreateQuadratic && nbFaceNodes>4) ||
1575              (myCreateQuadratic && nbFaceNodes>8) ) {
1576           MESSAGE(" Too many nodes in a face: " << nbFaceNodes );
1577           return false;
1578         }
1579         // look for a not loaded node of the <face>
1580         bool found = false;
1581         const SMDS_MeshNode* n3 = 0; // a node defferent from n1 and n2
1582         eIt = face->nodesIterator() ;
1583         while ( !found && eIt->more() ) {
1584           node = static_cast<const SMDS_MeshNode*>( eIt->next() );
1585           if(myTool->IsMedium(node))
1586             continue;
1587           found = loadedNodes.insert( node ).second;
1588           if ( !found && node != n1 && node != n2 )
1589             n3 = node;
1590         }
1591         if ( found ) {
1592           if ( ++row > vsize - 1 ) {
1593             MESSAGE( "Too many nodes in column "<< col <<": "<< row+1);
1594             return false;
1595           }
1596           par_nVec_2->second[ row ] = node;
1597           foundFaces.insert( make_pair(face->GetID(),face) );
1598           n2 = node;
1599           if ( nbFaceNodes==4 || (myCreateQuadratic && nbFaceNodes==8) ) {
1600             n1 = par_nVec_1->second[ row ];
1601           }
1602         }
1603         else if ( (nbFaceNodes==3 || (myCreateQuadratic && nbFaceNodes==6) )  &&
1604                  n3 == par_nVec_1->second[ row ] ) {
1605           n1 = n3;
1606         }
1607         else {
1608           MESSAGE( "Not quad mesh, column "<< col );
1609           return false;
1610         }
1611       }
1612     }
1613     while ( face && n1 && n2 );
1614
1615     if ( row < vsize - 1 ) {
1616       MESSAGE( "Too few nodes in column "<< col <<": "<< row+1);
1617       MESSAGE( "Base node 1: "<< par_nVec_1->second[0]);
1618       MESSAGE( "Base node 2: "<< par_nVec_2->second[0]);
1619       MESSAGE( "Current node 1: "<< n1);
1620       MESSAGE( "Current node 2: "<< n2);
1621       MESSAGE( "first base node: "<< theIJNodes.begin()->second[0]);
1622       MESSAGE( "last base node: "<< theIJNodes.rbegin()->second[0]);
1623       return false;
1624     }
1625   } // loop on columns
1626
1627   return true;
1628 }
1629
1630 //////////////////////////////////////////////////////////////////////////
1631 //
1632 //   StdMeshers_SMESHBlock
1633 //
1634 //////////////////////////////////////////////////////////////////////////
1635
1636 //=======================================================================
1637 //function : StdMeshers_SMESHBlock
1638 //purpose  : 
1639 //=======================================================================
1640 StdMeshers_SMESHBlock::StdMeshers_SMESHBlock()
1641 {
1642   myErrorStatus=1;
1643   myIsEdgeForward.resize( SMESH_Block::NbEdges(), -1 );
1644 }
1645
1646 //=======================================================================
1647 //function : IsForwadEdge
1648 //purpose  : 
1649 //=======================================================================
1650
1651 bool StdMeshers_SMESHBlock::IsForwadEdge(const int theEdgeID)
1652 {
1653   int index = myTBlock.ShapeIndex( theEdgeID );
1654   if ( !myTBlock.IsEdgeID( theEdgeID ))
1655     return false;
1656
1657   if ( myIsEdgeForward[ index ] < 0 )
1658     myIsEdgeForward[ index ] =
1659       myTBlock.IsForwardEdge( TopoDS::Edge( Shape( theEdgeID )), myShapeIDMap );
1660
1661   return myIsEdgeForward[ index ];
1662 }
1663
1664 //=======================================================================
1665 //function : ErrorStatus
1666 //purpose  : 
1667 //=======================================================================
1668 int StdMeshers_SMESHBlock::ErrorStatus() const
1669 {
1670   return myErrorStatus;
1671 }
1672
1673 //=======================================================================
1674 //function : Load
1675 //purpose  : 
1676 //=======================================================================
1677 void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell)
1678 {
1679   TopoDS_Vertex aV000, aV001;
1680   //
1681   Load(theShell, aV000, aV001);
1682 }
1683
1684 //=======================================================================
1685 //function : Load
1686 //purpose  : 
1687 //=======================================================================
1688 void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell,
1689                                  const TopoDS_Vertex& theV000,
1690                                  const TopoDS_Vertex& theV001)
1691 {
1692   myErrorStatus=0;
1693   //
1694   myShell=theShell;
1695   //
1696   bool bOk;
1697   //
1698   myShapeIDMap.Clear();  
1699   bOk = myTBlock.LoadBlockShapes(myShell, theV000, theV001, myShapeIDMap);
1700   if (!bOk) {
1701     myErrorStatus=2;
1702     return;
1703   }
1704 }
1705
1706 //=======================================================================
1707 //function : ComputeParameters
1708 //purpose  : 
1709 //=======================================================================
1710 void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt, 
1711                                               gp_XYZ& theXYZ)
1712 {
1713   ComputeParameters(thePnt, myShell, theXYZ);
1714 }
1715
1716 //=======================================================================
1717 //function : ComputeParameters
1718 //purpose  : 
1719 //=======================================================================
1720 void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt,
1721                                               const TopoDS_Shape& theShape,
1722                                               gp_XYZ& theXYZ)
1723 {
1724   myErrorStatus=0;
1725   //
1726   int aID;
1727   bool bOk;
1728   //
1729   aID = ShapeID(theShape);
1730   if (myErrorStatus) {
1731     return;
1732   }
1733   bOk = myTBlock.ComputeParameters(thePnt, theXYZ, aID);
1734   if (!bOk) {
1735     myErrorStatus=4; // problems with computation Parameters 
1736     return;
1737   }
1738 }
1739
1740 //=======================================================================
1741 //function : ComputeParameters
1742 //purpose  : 
1743 //=======================================================================
1744
1745 void StdMeshers_SMESHBlock::ComputeParameters(const double& theU,
1746                                               const TopoDS_Shape& theShape,
1747                                               gp_XYZ& theXYZ)
1748 {
1749   myErrorStatus=0;
1750   //
1751   int aID;
1752   bool bOk=false;
1753   //
1754   aID = ShapeID(theShape);
1755   if (myErrorStatus) {
1756     return;
1757   }
1758   if ( SMESH_Block::IsEdgeID( aID ))
1759       bOk = myTBlock.EdgeParameters( aID, theU, theXYZ );
1760   if (!bOk) {
1761     myErrorStatus=4; // problems with computation Parameters 
1762     return;
1763   }
1764 }
1765
1766 //=======================================================================
1767 //function : Point
1768 //purpose  : 
1769 //=======================================================================
1770  void StdMeshers_SMESHBlock::Point(const gp_XYZ& theParams,
1771                                    gp_Pnt& aP3D)
1772 {
1773   TopoDS_Shape aS;
1774   //
1775   Point(theParams, aS, aP3D);
1776 }
1777
1778 //=======================================================================
1779 //function : Point
1780 //purpose  : 
1781 //=======================================================================
1782  void StdMeshers_SMESHBlock::Point(const gp_XYZ& theParams,
1783                                    const TopoDS_Shape& theShape,
1784                                    gp_Pnt& aP3D)
1785 {
1786   myErrorStatus = 0;
1787   //
1788   int aID;
1789   bool bOk = false;
1790   gp_XYZ aXYZ(99.,99.,99.);
1791   aP3D.SetXYZ(aXYZ);
1792   //
1793   if (theShape.IsNull()) {
1794     bOk = myTBlock.ShellPoint(theParams, aXYZ);
1795   }
1796   //
1797   else {
1798     aID=ShapeID(theShape);
1799     if (myErrorStatus) {
1800       return;
1801     }
1802     //
1803     if (SMESH_Block::IsVertexID(aID)) {
1804       bOk = myTBlock.VertexPoint(aID, aXYZ);
1805     }
1806     else if (SMESH_Block::IsEdgeID(aID)) {
1807       bOk = myTBlock.EdgePoint(aID, theParams, aXYZ);
1808     }
1809     //
1810     else if (SMESH_Block::IsFaceID(aID)) {
1811       bOk = myTBlock.FacePoint(aID, theParams, aXYZ);
1812     }
1813   }
1814   if (!bOk) {
1815     myErrorStatus=4; // problems with point computation 
1816     return;
1817   }
1818   aP3D.SetXYZ(aXYZ);
1819 }
1820
1821 //=======================================================================
1822 //function : ShapeID
1823 //purpose  : 
1824 //=======================================================================
1825 int StdMeshers_SMESHBlock::ShapeID(const TopoDS_Shape& theShape)
1826 {
1827   myErrorStatus=0;
1828   //
1829   int aID=-1;
1830   TopoDS_Shape aSF, aSR;
1831   //
1832   aSF=theShape;
1833   aSF.Orientation(TopAbs_FORWARD);
1834   aSR=theShape;
1835   aSR.Orientation(TopAbs_REVERSED);
1836   //
1837   if (myShapeIDMap.Contains(aSF)) {
1838     aID=myShapeIDMap.FindIndex(aSF);
1839     return aID;
1840   }
1841   if (myShapeIDMap.Contains(aSR)) {
1842     aID=myShapeIDMap.FindIndex(aSR);
1843     return aID;
1844   }
1845   myErrorStatus=2; // unknown shape;
1846   return aID;
1847 }
1848
1849 //=======================================================================
1850 //function : Shape
1851 //purpose  : 
1852 //=======================================================================
1853 const TopoDS_Shape& StdMeshers_SMESHBlock::Shape(const int theID)
1854 {
1855   myErrorStatus=0;
1856   //
1857   int aNb;
1858   //
1859   aNb=myShapeIDMap.Extent();
1860   if (theID<1 || theID>aNb) {
1861     myErrorStatus=3; // ID is out of range
1862     return myEmptyShape;
1863   }
1864   //
1865   const TopoDS_Shape& aS=myShapeIDMap.FindKey(theID);
1866   return aS;
1867 }
1868
1869