Salome HOME
Join modifications from branch OCC_development_for_3_2_0a2
[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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
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 StdMeshers_Helper(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             MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1134             myErrorStatus=5; // more than one face has triangulation
1135             return;
1136           }
1137           break; // next face
1138         }
1139       }
1140     }
1141   }
1142   // 
1143   // 1. Vetrices V00, V001;
1144   //
1145   TopExp::MapShapes(aFTr, TopAbs_EDGE, aME);
1146   TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, aMVES);
1147   //
1148   // 1.1 Base vertex V000
1149   iNbE = aME.Extent();
1150   if (iNbE!=4){
1151     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1152     myErrorStatus=7; // too few edges are in base face aFTr 
1153     return;
1154   }
1155   const TopoDS_Edge& aE1=TopoDS::Edge(aME(1));
1156   aV000=TopExp::FirstVertex(aE1);
1157   //
1158   const TopTools_ListOfShape& aLE=aMVES.FindFromKey(aV000);
1159   aIt.Initialize(aLE);
1160   for (; aIt.More(); aIt.Next()) {
1161     const TopoDS_Shape& aEx=aIt.Value();
1162     aMEV.Add(aEx);
1163   }
1164   iNbEV=aMEV.Extent();
1165   if (iNbEV!=3){
1166     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1167     myErrorStatus=7; // too few edges meet in base vertex 
1168     return;
1169   }
1170   //
1171   // 1.2 Vertex V001
1172   bFound=false;
1173   for (j=1; j<=iNbEV; ++j) {
1174     const TopoDS_Shape& aEx=aMEV(j);
1175     if (!aME.Contains(aEx)) {
1176       TopoDS_Vertex aV[2];
1177       //
1178       const TopoDS_Edge& aE=TopoDS::Edge(aEx);
1179       TopExp::Vertices(aE, aV[0], aV[1]);
1180       for (i=0; i<2; ++i) {
1181         if (!aV[i].IsSame(aV000)) {
1182           aV001=aV[i];
1183           bFound=!bFound;
1184           break;
1185         }
1186       }
1187     }
1188   }
1189   //
1190   if (!bFound) {
1191     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1192     myErrorStatus=8; // can not find reper V001 
1193     return;
1194   }
1195   //DEB
1196   //gp_Pnt aP000, aP001;
1197   //
1198   //aP000=BRep_Tool::Pnt(TopoDS::Vertex(aV000));
1199   //printf("*** aP000 { %lf, %lf, %lf }\n", aP000.X(), aP000.Y(), aP000.Z());
1200   //aP001=BRep_Tool::Pnt(TopoDS::Vertex(aV001));
1201   //printf("*** aP001 { %lf, %lf, %lf }\n", aP001.X(), aP001.Y(), aP001.Z());
1202   //DEB
1203   //
1204   aME.Clear();
1205   TopExp::MapShapes(myShape, TopAbs_SHELL, aME);
1206   iNbE=aME.Extent();
1207   if (iNbE!=1) {
1208     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1209     myErrorStatus=9; // number of shells in source shape !=1 
1210     return;
1211   }
1212   //
1213   // 2. Load Block
1214   const TopoDS_Shell& aShell=TopoDS::Shell(aME(1));
1215   myBlock.Load(aShell, aV000, aV001);
1216   iErr = myBlock.ErrorStatus();
1217   if (iErr) {
1218     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
1219     myErrorStatus=100; // SMESHBlock: Load operation failed
1220     return;
1221   }
1222 }
1223 //=======================================================================
1224 //function : CheckData
1225 //purpose  : 
1226 //=======================================================================
1227 void StdMeshers_Penta_3D::CheckData()
1228 {
1229   myErrorStatus=0;
1230   //
1231   int i, iNb;
1232   int iNbEx[]={8, 12, 6};
1233   //
1234   TopAbs_ShapeEnum aST;
1235   TopAbs_ShapeEnum aSTEx[]={
1236     TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE
1237   }; 
1238   TopTools_IndexedMapOfShape aM;
1239   //
1240   if (myShape.IsNull()){
1241     MESSAGE("StdMeshers_Penta_3D::CheckData() ");
1242     myErrorStatus=2; // null shape
1243     return;
1244   }
1245   //
1246   aST=myShape.ShapeType();
1247   if (!(aST==TopAbs_SOLID || aST==TopAbs_SHELL)) {
1248     MESSAGE("StdMeshers_Penta_3D::CheckData() ");
1249     myErrorStatus=3; // not compatible type of shape
1250     return;
1251   }
1252   //
1253   for (i=0; i<3; ++i) {
1254     aM.Clear();
1255     TopExp::MapShapes(myShape, aSTEx[i], aM);
1256     iNb=aM.Extent();
1257     if (iNb!=iNbEx[i]){
1258       MESSAGE("StdMeshers_Penta_3D::CheckData() ");
1259       myErrorStatus=4; // number of subshape is not compatible
1260       return;
1261     }
1262   }
1263 }
1264
1265 //=======================================================================
1266 //function : LoadIJNodes
1267 //purpose  : Load nodes bound to theFace into column (vectors) and rows
1268 //           of theIJNodes.
1269 //           The value of theIJNodes map is a vector of ordered nodes so
1270 //           that the 0-the one lies on theBaseEdge.
1271 //           The key of theIJNodes map is a normalized parameter of each
1272 //           0-the node on theBaseEdge.
1273 //=======================================================================
1274
1275 bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
1276                                       const TopoDS_Face&     theFace,
1277                                       const TopoDS_Edge&     theBaseEdge,
1278                                       SMESHDS_Mesh*          theMesh)
1279 {
1280   // get vertices of theBaseEdge
1281   TopoDS_Vertex vfb, vlb, vft; // first and last, bottom and top vertices
1282   TopoDS_Edge eFrw = TopoDS::Edge( theBaseEdge.Oriented( TopAbs_FORWARD ));
1283   TopExp::Vertices( eFrw, vfb, vlb );
1284
1285   // find the other edges of theFace and orientation of e1
1286   TopoDS_Edge e1, e2, eTop;
1287   bool rev1, CumOri = false;
1288   TopExp_Explorer exp( theFace, TopAbs_EDGE );
1289   int nbEdges = 0;
1290   for ( ; exp.More(); exp.Next() ) {
1291     if ( ++nbEdges > 4 ) {
1292       return false; // more than 4 edges in theFace
1293     }
1294     TopoDS_Edge e = TopoDS::Edge( exp.Current() );
1295     if ( theBaseEdge.IsSame( e ))
1296       continue;
1297     TopoDS_Vertex vCommon;
1298     if ( !TopExp::CommonVertex( theBaseEdge, e, vCommon ))
1299       eTop = e;
1300     else if ( vCommon.IsSame( vfb )) {
1301       e1 = e;
1302       vft = TopExp::LastVertex( e1, CumOri );
1303       rev1 = vfb.IsSame( vft );
1304       if ( rev1 )
1305         vft = TopExp::FirstVertex( e1, CumOri );
1306     }
1307     else
1308       e2 = e;
1309   }
1310   if ( nbEdges < 4 ) {
1311     return false; // less than 4 edges in theFace
1312   }
1313
1314   // submeshes corresponding to shapes
1315   SMESHDS_SubMesh* smFace = theMesh->MeshElements( theFace );
1316   SMESHDS_SubMesh* smb = theMesh->MeshElements( theBaseEdge );
1317   SMESHDS_SubMesh* smt = theMesh->MeshElements( eTop );
1318   SMESHDS_SubMesh* sm1 = theMesh->MeshElements( e1 );
1319   SMESHDS_SubMesh* sm2 = theMesh->MeshElements( e2 );
1320   SMESHDS_SubMesh* smVfb = theMesh->MeshElements( vfb );
1321   SMESHDS_SubMesh* smVlb = theMesh->MeshElements( vlb );
1322   SMESHDS_SubMesh* smVft = theMesh->MeshElements( vft );
1323   if (!smFace || !smb || !smt || !sm1 || !sm2 || !smVfb || !smVlb || !smVft ) {
1324     MESSAGE( "NULL submesh " <<smFace<<" "<<smb<<" "<<smt<<" "<<
1325             sm1<<" "<<sm2<<" "<<smVfb<<" "<<smVlb<<" "<<smVft);
1326     return false;
1327   }
1328   if ( smb->NbNodes() != smt->NbNodes() || sm1->NbNodes() != sm2->NbNodes() ) {
1329     MESSAGE(" Diff nb of nodes on opposite edges" );
1330     return false;
1331   }
1332   if (smVfb->NbNodes() != 1 || smVlb->NbNodes() != 1 || smVft->NbNodes() != 1) {
1333     MESSAGE("Empty submesh of vertex");
1334     return false;
1335   }
1336   if ( sm1->NbNodes() * smb->NbNodes() != smFace->NbNodes() ) {
1337     // check quadratic case
1338     if ( myCreateQuadratic ) {
1339       int n1 = sm1->NbNodes()/2;
1340       int n2 = smb->NbNodes()/2;
1341       int n3 = sm1->NbNodes() - n1;
1342       int n4 = smb->NbNodes() - n2;
1343       int nf = sm1->NbNodes()*smb->NbNodes() - n3*n4;
1344       if( nf != smFace->NbNodes() ) {
1345         MESSAGE( "Wrong nb face nodes: " <<
1346                 sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes());
1347         return false;
1348       }
1349     }
1350     else {
1351       MESSAGE( "Wrong nb face nodes: " <<
1352               sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes());
1353       return false;
1354     }
1355   }
1356   // IJ size
1357   int vsize = sm1->NbNodes() + 2;
1358   int hsize = smb->NbNodes() + 2;
1359   if(myCreateQuadratic) {
1360     vsize = vsize - sm1->NbNodes()/2 -1;
1361     hsize = hsize - smb->NbNodes()/2 -1;
1362   }
1363
1364   // load nodes from theBaseEdge
1365
1366   set<const SMDS_MeshNode*> loadedNodes;
1367   const SMDS_MeshNode* nullNode = 0;
1368
1369   vector<const SMDS_MeshNode*> & nVecf = theIJNodes[ 0.];
1370   nVecf.resize( vsize, nullNode );
1371   loadedNodes.insert( nVecf[ 0 ] = smVfb->GetNodes()->next() );
1372
1373   vector<const SMDS_MeshNode*> & nVecl = theIJNodes[ 1.];
1374   nVecl.resize( vsize, nullNode );
1375   loadedNodes.insert( nVecl[ 0 ] = smVlb->GetNodes()->next() );
1376
1377   double f, l;
1378   BRep_Tool::Range( eFrw, f, l );
1379   double range = l - f;
1380   SMDS_NodeIteratorPtr nIt = smb->GetNodes();
1381   const SMDS_MeshNode* node;
1382   while ( nIt->more() ) {
1383     node = nIt->next();
1384     if(myTool->IsMedium(node))
1385       continue;
1386     const SMDS_EdgePosition* pos =
1387       dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() );
1388     if ( !pos ) {
1389       return false;
1390     }
1391     double u = ( pos->GetUParameter() - f ) / range;
1392     vector<const SMDS_MeshNode*> & nVec = theIJNodes[ u ];
1393     nVec.resize( vsize, nullNode );
1394     loadedNodes.insert( nVec[ 0 ] = node );
1395   }
1396   if ( theIJNodes.size() != hsize ) {
1397     MESSAGE( "Wrong node positions on theBaseEdge" );
1398     return false;
1399   }
1400
1401   // load nodes from e1
1402
1403   map< double, const SMDS_MeshNode*> sortedNodes; // sort by param on edge
1404   nIt = sm1->GetNodes();
1405   while ( nIt->more() ) {
1406     node = nIt->next();
1407     if(myTool->IsMedium(node))
1408       continue;
1409     const SMDS_EdgePosition* pos =
1410       dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() );
1411     if ( !pos ) {
1412       return false;
1413     }
1414     sortedNodes.insert( make_pair( pos->GetUParameter(), node ));
1415   }
1416   loadedNodes.insert( nVecf[ vsize - 1 ] = smVft->GetNodes()->next() );
1417   map< double, const SMDS_MeshNode*>::iterator u_n = sortedNodes.begin();
1418   int row = rev1 ? vsize - 1 : 0;
1419   for ( ; u_n != sortedNodes.end(); u_n++ ) {
1420     if ( rev1 ) row--;
1421     else        row++;
1422     loadedNodes.insert( nVecf[ row ] = u_n->second );
1423   }
1424
1425   // try to load the rest nodes
1426
1427   // get all faces from theFace
1428   set<const SMDS_MeshElement*> allFaces, foundFaces;
1429   SMDS_ElemIteratorPtr eIt = smFace->GetElements();
1430   while ( eIt->more() ) {
1431     const SMDS_MeshElement* e = eIt->next();
1432     if ( e->GetType() == SMDSAbs_Face )
1433       allFaces.insert( e );
1434   }
1435   // Starting from 2 neighbour nodes on theBaseEdge, look for a face
1436   // the nodes belong to, and between the nodes of the found face,
1437   // look for a not loaded node considering this node to be the next
1438   // in a column of the starting second node. Repeat, starting
1439   // from nodes next to the previous starting nodes in their columns,
1440   // and so on while a face can be found. Then go the the next pair
1441   // of nodes on theBaseEdge.
1442   StdMeshers_IJNodeMap::iterator par_nVec_1 = theIJNodes.begin();
1443   StdMeshers_IJNodeMap::iterator par_nVec_2 = par_nVec_1;
1444   // loop on columns
1445   int col = 0;
1446   for ( par_nVec_2++; par_nVec_2 != theIJNodes.end(); par_nVec_1++, par_nVec_2++ ) {
1447     col++;
1448     row = 0;
1449     const SMDS_MeshNode* n1 = par_nVec_1->second[ row ];
1450     const SMDS_MeshNode* n2 = par_nVec_2->second[ row ];
1451     const SMDS_MeshElement* face = 0;
1452     do {
1453       // look for a face by 2 nodes
1454       face = SMESH_MeshEditor::FindFaceInSet( n1, n2, allFaces, foundFaces );
1455       if ( face ) {
1456         int nbFaceNodes = face->NbNodes();
1457         if ( (!myCreateQuadratic && nbFaceNodes>4) ||
1458              (myCreateQuadratic && nbFaceNodes>8) ) {
1459           MESSAGE(" Too many nodes in a face: " << nbFaceNodes );
1460           return false;
1461         }
1462         // look for a not loaded node of the <face>
1463         bool found = false;
1464         const SMDS_MeshNode* n3 = 0; // a node defferent from n1 and n2
1465         eIt = face->nodesIterator() ;
1466         while ( !found && eIt->more() ) {
1467           node = static_cast<const SMDS_MeshNode*>( eIt->next() );
1468           if(myTool->IsMedium(node))
1469             continue;
1470           found = loadedNodes.insert( node ).second;
1471           if ( !found && node != n1 && node != n2 )
1472             n3 = node;
1473         }
1474         if ( found ) {
1475           if ( ++row > vsize - 1 ) {
1476             MESSAGE( "Too many nodes in column "<< col <<": "<< row+1);
1477             return false;
1478           }
1479           par_nVec_2->second[ row ] = node;
1480           foundFaces.insert( face );
1481           n2 = node;
1482           if ( nbFaceNodes==4 || (myCreateQuadratic && nbFaceNodes==8) ) {
1483             n1 = par_nVec_1->second[ row ];
1484           }
1485         }
1486         else if ( (nbFaceNodes==3 || (myCreateQuadratic && nbFaceNodes==6) )  &&
1487                  n3 == par_nVec_1->second[ row ] ) {
1488           n1 = n3;
1489         }
1490         else {
1491           MESSAGE( "Not quad mesh, column "<< col );
1492           return false;
1493         }
1494       }
1495     }
1496     while ( face && n1 && n2 );
1497
1498     if ( row < vsize - 1 ) {
1499       MESSAGE( "Too few nodes in column "<< col <<": "<< row+1);
1500       MESSAGE( "Base node 1: "<< par_nVec_1->second[0]);
1501       MESSAGE( "Base node 2: "<< par_nVec_2->second[0]);
1502       MESSAGE( "Current node 1: "<< n1);
1503       MESSAGE( "Current node 2: "<< n2);
1504       MESSAGE( "first base node: "<< theIJNodes.begin()->second[0]);
1505       MESSAGE( "last base node: "<< theIJNodes.rbegin()->second[0]);
1506       return false;
1507     }
1508   } // loop on columns
1509
1510   return true;
1511 }
1512
1513 //////////////////////////////////////////////////////////////////////////
1514 //
1515 //   StdMeshers_SMESHBlock
1516 //
1517 //////////////////////////////////////////////////////////////////////////
1518
1519 //=======================================================================
1520 //function : StdMeshers_SMESHBlock
1521 //purpose  : 
1522 //=======================================================================
1523 StdMeshers_SMESHBlock::StdMeshers_SMESHBlock()
1524 {
1525   myErrorStatus=1;
1526   myIsEdgeForward.resize( SMESH_Block::NbEdges(), -1 );
1527 }
1528
1529 //=======================================================================
1530 //function : IsForwadEdge
1531 //purpose  : 
1532 //=======================================================================
1533
1534 bool StdMeshers_SMESHBlock::IsForwadEdge(const int theEdgeID)
1535 {
1536   int index = myTBlock.ShapeIndex( theEdgeID );
1537   if ( !myTBlock.IsEdgeID( theEdgeID ))
1538     return false;
1539
1540   if ( myIsEdgeForward[ index ] < 0 )
1541     myIsEdgeForward[ index ] =
1542       myTBlock.IsForwardEdge( TopoDS::Edge( Shape( theEdgeID )), myShapeIDMap );
1543
1544   return myIsEdgeForward[ index ];
1545 }
1546
1547 //=======================================================================
1548 //function : ErrorStatus
1549 //purpose  : 
1550 //=======================================================================
1551 int StdMeshers_SMESHBlock::ErrorStatus() const
1552 {
1553   return myErrorStatus;
1554 }
1555
1556 //=======================================================================
1557 //function : Load
1558 //purpose  : 
1559 //=======================================================================
1560 void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell)
1561 {
1562   TopoDS_Vertex aV000, aV001;
1563   //
1564   Load(theShell, aV000, aV001);
1565 }
1566
1567 //=======================================================================
1568 //function : Load
1569 //purpose  : 
1570 //=======================================================================
1571 void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell,
1572                                  const TopoDS_Vertex& theV000,
1573                                  const TopoDS_Vertex& theV001)
1574 {
1575   myErrorStatus=0;
1576   //
1577   myShell=theShell;
1578   //
1579   bool bOk;
1580   //
1581   myShapeIDMap.Clear();  
1582   bOk = myTBlock.LoadBlockShapes(myShell, theV000, theV001, myShapeIDMap);
1583   if (!bOk) {
1584     myErrorStatus=2;
1585     return;
1586   }
1587 }
1588
1589 //=======================================================================
1590 //function : ComputeParameters
1591 //purpose  : 
1592 //=======================================================================
1593 void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt, 
1594                                               gp_XYZ& theXYZ)
1595 {
1596   ComputeParameters(thePnt, myShell, theXYZ);
1597 }
1598
1599 //=======================================================================
1600 //function : ComputeParameters
1601 //purpose  : 
1602 //=======================================================================
1603 void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt,
1604                                               const TopoDS_Shape& theShape,
1605                                               gp_XYZ& theXYZ)
1606 {
1607   myErrorStatus=0;
1608   //
1609   int aID;
1610   bool bOk;
1611   //
1612   aID = ShapeID(theShape);
1613   if (myErrorStatus) {
1614     return;
1615   }
1616   bOk = myTBlock.ComputeParameters(thePnt, theXYZ, aID);
1617   if (!bOk) {
1618     myErrorStatus=4; // problems with computation Parameters 
1619     return;
1620   }
1621 }
1622
1623 //=======================================================================
1624 //function : ComputeParameters
1625 //purpose  : 
1626 //=======================================================================
1627
1628 void StdMeshers_SMESHBlock::ComputeParameters(const double& theU,
1629                                               const TopoDS_Shape& theShape,
1630                                               gp_XYZ& theXYZ)
1631 {
1632   myErrorStatus=0;
1633   //
1634   int aID;
1635   bool bOk=false;
1636   //
1637   aID = ShapeID(theShape);
1638   if (myErrorStatus) {
1639     return;
1640   }
1641   if ( SMESH_Block::IsEdgeID( aID ))
1642       bOk = myTBlock.EdgeParameters( aID, theU, theXYZ );
1643   if (!bOk) {
1644     myErrorStatus=4; // problems with computation Parameters 
1645     return;
1646   }
1647 }
1648
1649 //=======================================================================
1650 //function : Point
1651 //purpose  : 
1652 //=======================================================================
1653  void StdMeshers_SMESHBlock::Point(const gp_XYZ& theParams,
1654                                    gp_Pnt& aP3D)
1655 {
1656   TopoDS_Shape aS;
1657   //
1658   Point(theParams, aS, aP3D);
1659 }
1660
1661 //=======================================================================
1662 //function : Point
1663 //purpose  : 
1664 //=======================================================================
1665  void StdMeshers_SMESHBlock::Point(const gp_XYZ& theParams,
1666                                    const TopoDS_Shape& theShape,
1667                                    gp_Pnt& aP3D)
1668 {
1669   myErrorStatus = 0;
1670   //
1671   int aID;
1672   bool bOk = false;
1673   gp_XYZ aXYZ(99.,99.,99.);
1674   aP3D.SetXYZ(aXYZ);
1675   //
1676   if (theShape.IsNull()) {
1677     bOk = myTBlock.ShellPoint(theParams, aXYZ);
1678   }
1679   //
1680   else {
1681     aID=ShapeID(theShape);
1682     if (myErrorStatus) {
1683       return;
1684     }
1685     //
1686     if (SMESH_Block::IsVertexID(aID)) {
1687       bOk = myTBlock.VertexPoint(aID, aXYZ);
1688     }
1689     else if (SMESH_Block::IsEdgeID(aID)) {
1690       bOk = myTBlock.EdgePoint(aID, theParams, aXYZ);
1691     }
1692     //
1693     else if (SMESH_Block::IsFaceID(aID)) {
1694       bOk = myTBlock.FacePoint(aID, theParams, aXYZ);
1695     }
1696   }
1697   if (!bOk) {
1698     myErrorStatus=4; // problems with point computation 
1699     return;
1700   }
1701   aP3D.SetXYZ(aXYZ);
1702 }
1703
1704 //=======================================================================
1705 //function : ShapeID
1706 //purpose  : 
1707 //=======================================================================
1708 int StdMeshers_SMESHBlock::ShapeID(const TopoDS_Shape& theShape)
1709 {
1710   myErrorStatus=0;
1711   //
1712   int aID=-1;
1713   TopoDS_Shape aSF, aSR;
1714   //
1715   aSF=theShape;
1716   aSF.Orientation(TopAbs_FORWARD);
1717   aSR=theShape;
1718   aSR.Orientation(TopAbs_REVERSED);
1719   //
1720   if (myShapeIDMap.Contains(aSF)) {
1721     aID=myShapeIDMap.FindIndex(aSF);
1722     return aID;
1723   }
1724   if (myShapeIDMap.Contains(aSR)) {
1725     aID=myShapeIDMap.FindIndex(aSR);
1726     return aID;
1727   }
1728   myErrorStatus=2; // unknown shape;
1729   return aID;
1730 }
1731
1732 //=======================================================================
1733 //function : Shape
1734 //purpose  : 
1735 //=======================================================================
1736 const TopoDS_Shape& StdMeshers_SMESHBlock::Shape(const int theID)
1737 {
1738   myErrorStatus=0;
1739   //
1740   int aNb;
1741   //
1742   aNb=myShapeIDMap.Extent();
1743   if (theID<1 || theID>aNb) {
1744     myErrorStatus=3; // ID is out of range
1745     return myEmptyShape;
1746   }
1747   //
1748   const TopoDS_Shape& aS=myShapeIDMap.FindKey(theID);
1749   return aS;
1750 }
1751
1752