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