Salome HOME
0020279: [CEA 334] control the "random" use when using mesh algorithms
[modules/smesh.git] / src / StdMeshers / StdMeshers_CompositeHexa_3D.cxx
1 //  SMESH SMESH : 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 // File      : StdMeshers_CompositeHexa_3D.cxx
23 // Module    : SMESH
24 // Created   : Tue Nov 25 11:04:59 2008
25 // Author    : Edward AGAPOV (eap)
26
27 #include "StdMeshers_CompositeHexa_3D.hxx"
28
29 #include "SMDS_Mesh.hxx"
30 #include "SMDS_MeshNode.hxx"
31 #include "SMDS_SetIterator.hxx"
32 #include "SMESH_Block.hxx"
33 #include "SMESH_Comment.hxx"
34 #include "SMESH_ComputeError.hxx"
35 #include "SMESH_Mesh.hxx"
36 #include "SMESH_MesherHelper.hxx"
37 #include "SMESH_subMesh.hxx"
38
39 #include <BRepAdaptor_Surface.hxx>
40 #include <BRep_Tool.hxx>
41 #include <Standard_ErrorHandler.hxx>
42 #include <Standard_Failure.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <TopTools_MapIteratorOfMapOfShape.hxx>
45 #include <TopTools_MapOfShape.hxx>
46 #include <TopoDS.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS_Face.hxx>
49 #include <TopoDS_Vertex.hxx>
50 #include <gp_Pnt.hxx>
51 #include <gp_Pnt2d.hxx>
52 #include <gp_Vec.hxx>
53 #include <gp_XYZ.hxx>
54
55 #include <list>
56 #include <set>
57 #include <vector>
58
59
60 #ifdef _DEBUG_
61
62 // #define DEB_FACES
63 // #define DEB_GRID
64 #define DUMP_VERT(msg,V) \
65 // { TopoDS_Vertex v = V; gp_Pnt p = BRep_Tool::Pnt(v);\
66 //   cout << msg << "( "<< p.X()<<", "<<p.Y()<<", "<<p.Z()<<" )"<<endl;}
67
68 #else
69
70 #define DUMP_VERT(msg,v)
71
72 #endif
73
74 //================================================================================
75 // text for message about an internal error
76 #define ERR_LI(txt) SMESH_Comment(txt) << ":" << __LINE__
77
78 // order corresponds to right order of edges in CASCADE face
79 enum EQuadSides{ Q_BOTTOM=0, Q_RIGHT, Q_TOP, Q_LEFT,   Q_CHILD, Q_PARENT };
80
81 enum EBoxSides{ B_BOTTOM=0, B_RIGHT, B_TOP, B_LEFT, B_FRONT, B_BACK, B_UNDEFINED };
82
83 //================================================================================
84 /*!
85  * \brief Convertor of a pair of integers to a sole index
86  */
87 struct _Indexer
88 {
89   int _xSize, _ySize;
90   _Indexer( int xSize, int ySize ): _xSize(xSize), _ySize(ySize) {}
91   int size() const { return _xSize * _ySize; }
92   int operator()(const int x, const int y) const { return y * _xSize + x; }
93 };
94
95 //================================================================================
96 /*!
97  * \brief Wrapper of a composite or an ordinary edge.
98  */
99 class _FaceSide
100 {
101 public:
102   _FaceSide(const _FaceSide& other);
103   _FaceSide(const TopoDS_Edge& edge=TopoDS_Edge());
104   _FaceSide(const list<TopoDS_Edge>& edges);
105   _FaceSide* GetSide(const int i);
106   const _FaceSide* GetSide(const int i) const;
107   int size() { return myChildren.size(); }
108   int NbVertices() const;
109   TopoDS_Vertex FirstVertex() const;
110   TopoDS_Vertex LastVertex() const;
111   TopoDS_Vertex Vertex(int i) const;
112   bool Contain( const _FaceSide& side, int* which=0 ) const;
113   bool Contain( const TopoDS_Vertex& vertex ) const;
114   void AppendSide( const _FaceSide& side );
115   void SetBottomSide( int i );
116   int GetNbSegments(SMESH_Mesh& mesh) const;
117   bool StoreNodes(SMESH_Mesh& mesh, vector<const SMDS_MeshNode*>& myGrid, bool reverse );
118   void SetID(EQuadSides id) { myID = id; }
119   static inline const TopoDS_TShape* ptr(const TopoDS_Shape& theShape)
120   { return theShape.TShape().operator->(); }
121   void Dump() const;
122
123 private:
124
125
126   TopoDS_Edge       myEdge;
127   list< _FaceSide > myChildren;
128   int               myNbChildren;
129
130   //set<const TopoDS_TShape*> myVertices;
131   TopTools_MapOfShape myVertices;
132
133   EQuadSides        myID; // debug
134 };
135 //================================================================================
136 /*!
137  * \brief Class corresponding to a meshed composite face of a box.
138  *        Provides simplified access to it's sub-mesh data.
139  */
140 class _QuadFaceGrid
141 {
142   typedef list< _QuadFaceGrid > TChildren;
143 public:
144   _QuadFaceGrid();
145
146 public: //** Methods to find and orient faces of 6 sides of the box **//
147   
148   //!< initialization
149   bool Init(const TopoDS_Face& f);
150
151   //!< try to unite self with other face
152   bool AddContinuousFace( const _QuadFaceGrid& f );
153
154   //!< Try to set the side as bottom hirizontal side
155   bool SetBottomSide(const _FaceSide& side, int* sideIndex=0);
156
157   //!< Return face adjacent to i-th side of this face
158   _QuadFaceGrid* FindAdjacentForSide(int i, vector<_QuadFaceGrid>& faces) const; // (0<i<4)
159
160   //!< Reverse edges in order to have the bottom edge going along axes of the unit box
161   void ReverseEdges(/*int e1, int e2*/);
162
163   bool IsComplex() const { return !myChildren.empty(); }
164
165   typedef SMDS_SetIterator< const _QuadFaceGrid&, TChildren::const_iterator > TChildIterator;
166
167   TChildIterator GetChildren() const
168   { return TChildIterator( myChildren.begin(), myChildren.end()); }
169
170 public: //** Loading and access to mesh **//
171
172   //!< Load nodes of a mesh
173   bool LoadGrid( SMESH_Mesh& mesh );
174
175   //!< Return number of segments on the hirizontal sides
176   int GetNbHoriSegments(SMESH_Mesh& mesh, bool withBrothers=false) const;
177
178   //!< Return number of segments on the vertical sides
179   int GetNbVertSegments(SMESH_Mesh& mesh, bool withBrothers=false) const;
180
181   //!< Return a node by its position
182   const SMDS_MeshNode* GetNode(int iHori, int iVert) const;
183
184   //!< Return node coordinates by its position
185   gp_XYZ GetXYZ(int iHori, int iVert) const;
186
187 public: //** Access to member fields **//
188
189   //!< Return i-th face side (0<i<4)
190   const _FaceSide& GetSide(int i) const;
191
192   //!< Return it's face, NULL if it is composite
193   TopoDS_Face GetFace() const { return myFace; }
194
195   //!< Return normal to the face at vertex v
196   bool GetNormal( const TopoDS_Vertex& v, gp_Vec& n ) const;
197
198   SMESH_ComputeErrorPtr GetError() const { return myError; }
199
200   void SetID(EBoxSides id) { myID = id; }
201
202   void DumpGrid() const;
203
204   void DumpVertices() const;
205
206 private:
207
208   bool error(std::string& text, int code = COMPERR_ALGO_FAILED)
209   { myError = SMESH_ComputeError::New( code, text ); return false; }
210
211   bool error(const SMESH_ComputeErrorPtr& err)
212   { myError = err; return ( !myError || myError->IsOK() ); }
213
214   bool loadCompositeGrid(SMESH_Mesh& mesh);
215
216   bool fillGrid(SMESH_Mesh&                    theMesh,
217                 vector<const SMDS_MeshNode*> & theGrid,
218                 const _Indexer&                theIndexer,
219                 int                            theX,
220                 int                            theY);
221
222   bool locateChildren();
223
224   void setBrothers( set< _QuadFaceGrid* >& notLocatedBrothers );
225
226   TopoDS_Face myFace;
227   _FaceSide   mySides;
228   bool        myReverse;
229
230   TChildren   myChildren;
231
232   _QuadFaceGrid* myLeftBottomChild;
233   _QuadFaceGrid* myRightBrother;
234   _QuadFaceGrid* myUpBrother;
235
236   _Indexer    myIndexer;
237   vector<const SMDS_MeshNode*>  myGrid;
238
239   SMESH_ComputeErrorPtr         myError;
240
241   EBoxSides   myID; // debug
242 };
243
244 //================================================================================
245 /*!
246  * \brief Constructor
247  */
248 //================================================================================
249
250 StdMeshers_CompositeHexa_3D::StdMeshers_CompositeHexa_3D(int hypId, int studyId, SMESH_Gen* gen)
251   :SMESH_3D_Algo(hypId, studyId, gen)
252 {
253   _name = "CompositeHexa_3D";
254   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);       // 1 bit /shape type
255 }
256
257 //================================================================================
258 /*!
259  * \brief always return true
260  */
261 //================================================================================
262
263 bool StdMeshers_CompositeHexa_3D::CheckHypothesis(SMESH_Mesh&         aMesh,
264                                                   const TopoDS_Shape& aShape,
265                                                   Hypothesis_Status&  aStatus)
266 {
267   aStatus = HYP_OK;
268   return true;
269 }
270
271 //================================================================================
272 /*!
273  * \brief Computes hexahedral mesh on a box with composite sides
274  *  \param aMesh - mesh to compute
275  *  \param aShape - shape to mesh
276  *  \retval bool - succes sign
277  */
278 //================================================================================
279
280 bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
281                                           const TopoDS_Shape& theShape)
282 {
283   SMESH_MesherHelper helper( theMesh );
284   _quadraticMesh = helper.IsQuadraticSubMesh( theShape );
285   helper.SetElementsOnShape( true );
286
287   // -------------------------
288   // Try to find 6 side faces
289   // -------------------------
290   vector< _QuadFaceGrid > boxFaces; boxFaces.reserve( 6 );
291   TopExp_Explorer exp;
292   int iFace, nbFaces = 0;
293   for ( exp.Init(theShape, TopAbs_FACE); exp.More(); exp.Next(), ++nbFaces )
294   {
295     _QuadFaceGrid f;
296     if ( !f.Init( TopoDS::Face( exp.Current() )))
297       return error (COMPERR_BAD_SHAPE);
298     bool isContinuous = false;
299     for ( int i=0; i < boxFaces.size() && !isContinuous; ++i )
300       isContinuous = boxFaces[ i ].AddContinuousFace( f );
301     if ( !isContinuous )
302       boxFaces.push_back( f );
303   }
304   // Check what we have
305   if ( boxFaces.size() != 6 && nbFaces != 6)
306     return error
307       (COMPERR_BAD_SHAPE,
308        SMESH_Comment("Can't find 6 sides of a box. Number of found sides - ")<<boxFaces.size());
309
310   if ( boxFaces.size() != 6 && nbFaces == 6 ) { // strange ordinary box with continuous faces
311     boxFaces.resize( 6 );
312     iFace = 0;
313     for ( exp.Init(theShape, TopAbs_FACE); exp.More(); exp.Next(), ++iFace )
314       boxFaces[ iFace ].Init( TopoDS::Face( exp.Current() ) );
315   }
316   // ----------------------------------------
317   // Find out position of faces within a box
318   // ----------------------------------------
319
320   _QuadFaceGrid *fBottom, *fTop, *fFront, *fBack, *fLeft, *fRight;
321   // start from a bottom face
322   fBottom = &boxFaces[0];
323   // find vertical faces
324   fFront = fBottom->FindAdjacentForSide( Q_BOTTOM, boxFaces );
325   fLeft  = fBottom->FindAdjacentForSide( Q_RIGHT, boxFaces );
326   fBack  = fBottom->FindAdjacentForSide( Q_TOP, boxFaces );
327   fRight = fBottom->FindAdjacentForSide( Q_LEFT, boxFaces );
328   // check the found
329   if ( !fFront || !fBack || !fLeft || !fRight )
330     return error(COMPERR_BAD_SHAPE);
331   // top face
332   fTop = 0;
333   for ( int i=1; i < boxFaces.size() && !fTop; ++i ) {
334     fTop = & boxFaces[ i ];
335     if ( fTop==fFront || fTop==fLeft || fTop==fBack || fTop==fRight )
336       fTop = 0;
337   }
338   // set bottom of the top side
339   if ( !fTop->SetBottomSide( fFront->GetSide( Q_TOP ) )) {
340     if ( !fFront->IsComplex() )
341       return error( ERR_LI("Error in StdMeshers_CompositeHexa_3D::Compute()"));
342     else {
343       _QuadFaceGrid::TChildIterator chIt = fFront->GetChildren();
344       while ( chIt.more() ) {
345         const _QuadFaceGrid& frontChild = chIt.next();
346         if ( fTop->SetBottomSide( frontChild.GetSide( Q_TOP )))
347           break;
348       }
349     }
350   }
351   if ( !fTop )
352     return error(COMPERR_BAD_SHAPE);
353
354   fBottom->SetID( B_BOTTOM );
355   fBack  ->SetID( B_BACK );
356   fLeft  ->SetID( B_LEFT );
357   fFront ->SetID( B_FRONT );
358   fRight ->SetID( B_RIGHT );
359   fTop   ->SetID( B_TOP );
360
361   // orient bottom egde of faces along axes of the unit box
362   fBottom->ReverseEdges();
363   fBack  ->ReverseEdges();
364   fLeft  ->ReverseEdges();
365
366   // ------------------------------------------
367   // Fill columns of nodes with existing nodes
368   // ------------------------------------------
369
370   // let faces load their grids
371   if ( !fBottom->LoadGrid( theMesh )) return error( fBottom->GetError() );
372   if ( !fBack  ->LoadGrid( theMesh )) return error( fBack  ->GetError() );
373   if ( !fLeft  ->LoadGrid( theMesh )) return error( fLeft  ->GetError() );
374   if ( !fFront ->LoadGrid( theMesh )) return error( fFront ->GetError() );
375   if ( !fRight ->LoadGrid( theMesh )) return error( fRight ->GetError() );
376   if ( !fTop   ->LoadGrid( theMesh )) return error( fTop   ->GetError() );
377
378   int x, xSize = fBottom->GetNbHoriSegments(theMesh) + 1, X = xSize - 1;
379   int y, ySize = fBottom->GetNbVertSegments(theMesh) + 1, Y = ySize - 1;
380   int z, zSize = fFront ->GetNbVertSegments(theMesh) + 1, Z = zSize - 1;
381   _Indexer colIndex( xSize, ySize );
382   vector< vector< const SMDS_MeshNode* > > columns( colIndex.size() );
383
384   // fill node columns by front and back box sides
385   for ( x = 0; x < xSize; ++x ) {
386     vector< const SMDS_MeshNode* >& column0 = columns[ colIndex( x, 0 )];
387     vector< const SMDS_MeshNode* >& column1 = columns[ colIndex( x, Y )];
388     column0.resize( zSize );
389     column1.resize( zSize );
390     for ( z = 0; z < zSize; ++z ) {
391       column0[ z ] = fFront->GetNode( x, z );
392       column1[ z ] = fBack ->GetNode( x, z );
393     }
394   }
395   // fill node columns by left and right box sides
396   for ( y = 1; y < ySize-1; ++y ) {
397     vector< const SMDS_MeshNode* >& column0 = columns[ colIndex( 0, y )];
398     vector< const SMDS_MeshNode* >& column1 = columns[ colIndex( X, y )];
399     column0.resize( zSize );
400     column1.resize( zSize );
401     for ( z = 0; z < zSize; ++z ) {
402       column0[ z ] = fLeft ->GetNode( y, z );
403       column1[ z ] = fRight->GetNode( y, z );
404     }
405   }
406   // get nodes from top and bottom box sides
407   for ( x = 1; x < xSize-1; ++x ) {
408     for ( y = 1; y < ySize-1; ++y ) {
409       vector< const SMDS_MeshNode* >& column = columns[ colIndex( x, y )];
410       column.resize( zSize );
411       column.front() = fBottom->GetNode( x, y );
412       column.back()  = fTop   ->GetNode( x, y );
413     }
414   }
415
416   // ----------------------------
417   // Add internal nodes of a box
418   // ----------------------------
419   // projection points of internal nodes on box subshapes by which
420   // coordinates of internal nodes are computed
421   vector<gp_XYZ> pointsOnShapes( SMESH_Block::ID_Shell );
422
423   // projections on vertices are constant
424   pointsOnShapes[ SMESH_Block::ID_V000 ] = fBottom->GetXYZ( 0, 0 );
425   pointsOnShapes[ SMESH_Block::ID_V100 ] = fBottom->GetXYZ( X, 0 );
426   pointsOnShapes[ SMESH_Block::ID_V010 ] = fBottom->GetXYZ( 0, Y );
427   pointsOnShapes[ SMESH_Block::ID_V110 ] = fBottom->GetXYZ( X, Y );
428   pointsOnShapes[ SMESH_Block::ID_V001 ] = fTop->GetXYZ( 0, 0 );
429   pointsOnShapes[ SMESH_Block::ID_V101 ] = fTop->GetXYZ( X, 0 );
430   pointsOnShapes[ SMESH_Block::ID_V011 ] = fTop->GetXYZ( 0, Y );
431   pointsOnShapes[ SMESH_Block::ID_V111 ] = fTop->GetXYZ( X, Y );
432
433   for ( x = 1; x < xSize-1; ++x )
434   {
435     gp_XYZ params; // normalized parameters of internal node within a unit box
436     params.SetCoord( 1, x / double(X) );
437     for ( y = 1; y < ySize-1; ++y )
438     {
439       params.SetCoord( 2, y / double(Y) );
440       // column to fill during z loop
441       vector< const SMDS_MeshNode* >& column = columns[ colIndex( x, y )];
442       // points projections on horizontal edges
443       pointsOnShapes[ SMESH_Block::ID_Ex00 ] = fBottom->GetXYZ( x, 0 );
444       pointsOnShapes[ SMESH_Block::ID_Ex10 ] = fBottom->GetXYZ( x, Y );
445       pointsOnShapes[ SMESH_Block::ID_E0y0 ] = fBottom->GetXYZ( 0, y );
446       pointsOnShapes[ SMESH_Block::ID_E1y0 ] = fBottom->GetXYZ( X, y );
447       pointsOnShapes[ SMESH_Block::ID_Ex01 ] = fTop->GetXYZ( x, 0 );
448       pointsOnShapes[ SMESH_Block::ID_Ex11 ] = fTop->GetXYZ( x, Y );
449       pointsOnShapes[ SMESH_Block::ID_E0y1 ] = fTop->GetXYZ( 0, y );
450       pointsOnShapes[ SMESH_Block::ID_E1y1 ] = fTop->GetXYZ( X, y );
451       // points projections on horizontal faces
452       pointsOnShapes[ SMESH_Block::ID_Fxy0 ] = fBottom->GetXYZ( x, y );
453       pointsOnShapes[ SMESH_Block::ID_Fxy1 ] = fTop   ->GetXYZ( x, y );
454       for ( z = 1; z < zSize-1; ++z ) // z loop
455       {
456         params.SetCoord( 3, z / double(Z) );
457         // point projections on vertical edges
458         pointsOnShapes[ SMESH_Block::ID_E00z ] = fFront->GetXYZ( 0, z );    
459         pointsOnShapes[ SMESH_Block::ID_E10z ] = fFront->GetXYZ( X, z );    
460         pointsOnShapes[ SMESH_Block::ID_E01z ] = fBack->GetXYZ( 0, z );    
461         pointsOnShapes[ SMESH_Block::ID_E11z ] = fBack->GetXYZ( X, z );
462         // point projections on vertical faces
463         pointsOnShapes[ SMESH_Block::ID_Fx0z ] = fFront->GetXYZ( x, z );    
464         pointsOnShapes[ SMESH_Block::ID_Fx1z ] = fBack ->GetXYZ( x, z );    
465         pointsOnShapes[ SMESH_Block::ID_F0yz ] = fLeft ->GetXYZ( y, z );    
466         pointsOnShapes[ SMESH_Block::ID_F1yz ] = fRight->GetXYZ( y, z );
467
468         // compute internal node coordinates
469         gp_XYZ coords;
470         SMESH_Block::ShellPoint( params, pointsOnShapes, coords );
471         column[ z ] = helper.AddNode( coords.X(), coords.Y(), coords.Z() );
472
473 #ifdef DEB_GRID
474         // debug
475         //cout << "----------------------------------------------------------------------"<<endl;
476         //for ( int id = SMESH_Block::ID_V000; id < SMESH_Block::ID_Shell; ++id)
477         //{
478         //  gp_XYZ p = pointsOnShapes[ id ];
479         //  SMESH_Block::DumpShapeID( id,cout)<<" ( "<<p.X()<<", "<<p.Y()<<", "<<p.Z()<<" )"<<endl;
480         //}
481         //cout << "Params: ( "<< params.X()<<", "<<params.Y()<<", "<<params.Z()<<" )"<<endl;
482         //cout << "coords: ( "<< coords.X()<<", "<<coords.Y()<<", "<<coords.Z()<<" )"<<endl;
483 #endif
484       }
485     }
486   }
487   // faces no more needed, free memory
488   boxFaces.clear();
489
490   // ----------------
491   // Add hexahedrons
492   // ----------------
493   for ( x = 0; x < xSize-1; ++x ) {
494     for ( y = 0; y < ySize-1; ++y ) {
495       vector< const SMDS_MeshNode* >& col00 = columns[ colIndex( x, y )];
496       vector< const SMDS_MeshNode* >& col10 = columns[ colIndex( x+1, y )];
497       vector< const SMDS_MeshNode* >& col01 = columns[ colIndex( x, y+1 )];
498       vector< const SMDS_MeshNode* >& col11 = columns[ colIndex( x+1, y+1 )];
499       for ( z = 0; z < zSize-1; ++z )
500       {
501         // bottom face normal of a hexa mush point outside the volume
502         helper.AddVolume(col00[z],   col01[z],   col11[z],   col10[z],
503                          col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
504       }
505     }
506   }
507   return true;
508 }
509
510 //================================================================================
511 /*!
512  * \brief constructor of non-initialized _QuadFaceGrid
513  */
514 //================================================================================
515
516 _QuadFaceGrid::_QuadFaceGrid():
517   myReverse(false), myRightBrother(0), myUpBrother(0), myIndexer(0,0), myID(B_UNDEFINED)
518 {
519 }
520
521 //================================================================================
522 /*!
523  * \brief Initialization
524  */
525 //================================================================================
526
527 bool _QuadFaceGrid::Init(const TopoDS_Face& f)
528 {
529   myFace         = f;
530   mySides        = _FaceSide();
531   myReverse      = false;
532   myLeftBottomChild = myRightBrother = myUpBrother = 0;
533   myChildren.clear();
534   myGrid.clear();
535   //if ( myFace.Orientation() != TopAbs_FORWARD )
536     //myFace.Reverse();
537
538   TopoDS_Vertex V;
539   list< TopoDS_Edge > edges;
540   list< int > nbEdgesInWire;
541   int nbWire = SMESH_Block::GetOrderedEdges (myFace, V, edges, nbEdgesInWire);
542   if ( nbWire != 1 )
543     return false;
544
545   list< TopoDS_Edge >::iterator edgeIt = edges.begin();
546   if ( nbEdgesInWire.front() == 4 ) // exactly 4 edges
547   {
548     for ( ; edgeIt != edges.end(); ++edgeIt )
549       mySides.AppendSide( _FaceSide( *edgeIt ));
550   }
551   else if ( nbEdgesInWire.front() > 4 ) { // more than 4 edges - try to unite some
552     list< TopoDS_Edge > sideEdges;
553     while ( !edges.empty()) {
554       sideEdges.clear();
555       sideEdges.splice( sideEdges.end(), edges, edges.begin());// edges.front()->sideEdges.back()
556       while ( !edges.empty() ) {
557         if ( SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() )) {
558           sideEdges.splice( sideEdges.end(), edges, edges.begin());
559         }
560         else if ( SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() )) {
561           sideEdges.splice( sideEdges.begin(), edges, --edges.end());
562         }
563         else {
564           break;
565         }
566       }
567       mySides.AppendSide( _FaceSide( sideEdges ));
568     }
569   }
570   if (mySides.size() != 4)
571     return false;
572
573 #ifdef _DEBUG_
574   mySides.GetSide( Q_BOTTOM )->SetID( Q_BOTTOM );
575   mySides.GetSide( Q_RIGHT  )->SetID( Q_RIGHT );
576   mySides.GetSide( Q_TOP    )->SetID( Q_TOP );
577   mySides.GetSide( Q_LEFT   )->SetID( Q_LEFT );
578 #endif
579
580   return true;
581 }
582
583 //================================================================================
584 /*!
585  * \brief Try to unite self with other ordinary face
586  */
587 //================================================================================
588
589 bool _QuadFaceGrid::AddContinuousFace( const _QuadFaceGrid& other )
590 {
591   for ( int i = 0; i < 4; ++i ) {
592     const _FaceSide& otherSide = other.GetSide( i );
593     int iMyCommon;
594     if ( mySides.Contain( otherSide, &iMyCommon ) ) {
595       // check if normals of two faces are collinear at all vertices of a otherSide
596       const double angleTol = PI / 180 / 2;
597       int iV, nbV = otherSide.NbVertices(), nbCollinear = 0;
598       for ( iV = 0; iV < nbV; ++iV )
599       {
600         TopoDS_Vertex v = otherSide.Vertex( iV );
601         gp_Vec n1, n2;
602         if ( !GetNormal( v, n1 ) || !other.GetNormal( v, n2 ))
603           continue;
604         if ( n1 * n2 < 0 )
605           n1.Reverse();
606         if ( n1.Angle(n2) < angleTol )
607           nbCollinear++;
608         else
609           break;
610       }
611       if ( nbCollinear > 1 ) { // this face becomes composite if not yet is
612         DUMP_VERT("Cont 1", mySides.GetSide(iMyCommon)->FirstVertex());
613         DUMP_VERT("Cont 2", mySides.GetSide(iMyCommon)->LastVertex());
614         DUMP_VERT("Cont 3", otherSide.FirstVertex());
615         DUMP_VERT("Cont 4", otherSide.LastVertex());
616         if ( myChildren.empty() ) {
617           myChildren.push_back( *this );
618           myFace.Nullify();
619         }
620         myChildren.push_back( other );
621         int otherBottomIndex = ( 4 + i - iMyCommon + 2 ) % 4;
622         myChildren.back().SetBottomSide( other.GetSide( otherBottomIndex ));
623         // collect vertices in mySides
624         mySides.AppendSide( other.GetSide(0) );
625         mySides.AppendSide( other.GetSide(1) );
626         mySides.AppendSide( other.GetSide(2) );
627         mySides.AppendSide( other.GetSide(3) );
628         return true;
629       }
630     }
631   }
632   return false;
633 }
634
635 //================================================================================
636 /*!
637  * \brief Try to set the side as bottom hirizontal side
638  */
639 //================================================================================
640
641 bool _QuadFaceGrid::SetBottomSide(const _FaceSide& bottom, int* sideIndex)
642 {
643   myLeftBottomChild = myRightBrother = myUpBrother = 0;
644
645   int myBottomIndex;
646   if ( myChildren.empty() )
647   {
648     if ( mySides.Contain( bottom, &myBottomIndex )) {
649       mySides.SetBottomSide( myBottomIndex );
650       if ( sideIndex )
651         *sideIndex = myBottomIndex;
652       return true;
653     }
654   }
655   else
656   {
657     TChildren::iterator childFace = myChildren.begin(), childEnd = myChildren.end();
658     for ( ; childFace != childEnd; ++childFace )
659     {
660       if ( childFace->SetBottomSide( bottom, &myBottomIndex ))
661       {
662         TChildren::iterator orientedCild = childFace;
663         for ( childFace = myChildren.begin(); childFace != childEnd; ++childFace ) {
664           if ( childFace != orientedCild )
665             childFace->SetBottomSide( childFace->GetSide( myBottomIndex ));
666         }
667         if ( sideIndex )
668           *sideIndex = myBottomIndex;
669         return true;
670       }
671     }
672   }
673   return false;
674 }
675
676 //================================================================================
677 /*!
678  * \brief Return face adjacent to i-th side of this face, (0<i<4)
679  */
680 //================================================================================
681
682 _QuadFaceGrid* _QuadFaceGrid::FindAdjacentForSide(int i, vector<_QuadFaceGrid>& faces) const
683 {
684   for ( int iF = 0; iF < faces.size(); ++iF ) {
685     _QuadFaceGrid* f  = &faces[ iF ];
686     if ( f != this && f->SetBottomSide( GetSide( i )))
687       return f;
688   }
689   return (_QuadFaceGrid*) 0;
690 }
691
692 //================================================================================
693 /*!
694  * \brief Return i-th side
695  */
696 //================================================================================
697
698 const _FaceSide& _QuadFaceGrid::GetSide(int i) const
699 {
700   if ( myChildren.empty() )
701     return *mySides.GetSide(i);
702
703   _QuadFaceGrid* me = const_cast<_QuadFaceGrid*>(this);
704   if ( !me->locateChildren() || !myLeftBottomChild )
705     return *mySides.GetSide(i);
706
707   const _QuadFaceGrid* child = myLeftBottomChild;
708   switch ( i ){
709   case Q_BOTTOM:
710   case Q_LEFT:
711     break;
712   case Q_RIGHT:
713     while ( child->myRightBrother )
714       child = child->myRightBrother;
715     break;
716   case Q_TOP:
717     while ( child->myUpBrother )
718       child = child->myUpBrother;
719     break;
720   default: ;
721   }
722   return child->GetSide( i );
723 }
724
725 //================================================================================
726 /*!
727  * \brief Reverse edges in order to have them oriented along axes of the unit box
728  */
729 //================================================================================
730
731 void _QuadFaceGrid::ReverseEdges(/*int e1, int e2*/)
732 {
733   myReverse = !myReverse;
734
735 // #ifdef DEB_FACES
736 //   if ( !myFace.IsNull() )
737 //     TopAbs::Print(myFace.Orientation(), cout);
738 // #endif
739
740   if ( myChildren.empty() )
741   {
742 //     mySides.GetSide( e1 )->Reverse();
743 //     mySides.GetSide( e2 )->Reverse();
744     DumpVertices();
745   }
746   else
747   {
748     DumpVertices();
749     TChildren::iterator child = myChildren.begin(), childEnd = myChildren.end();
750     for ( ; child != childEnd; ++child )
751       child->ReverseEdges( /*e1, e2*/ );
752   }
753 }
754
755 //================================================================================
756 /*!
757  * \brief Load nodes of a mesh
758  */
759 //================================================================================
760
761 bool _QuadFaceGrid::LoadGrid( SMESH_Mesh& mesh )
762 {
763   if ( !myChildren.empty() )
764   {
765     // Let child faces load their grids
766     TChildren::iterator child = myChildren.begin(), childEnd = myChildren.end();
767     for ( ; child != childEnd; ++child ) {
768       child->SetID( myID );
769       if ( !child->LoadGrid( mesh ) )
770         return error( child->GetError() );
771     }
772     // Fill myGrid with nodes of patches
773     return loadCompositeGrid( mesh );
774   }
775
776   // ---------------------------------------
777   // Fill myGrid with nodes bound to myFace
778   // ---------------------------------------
779
780   if ( !myGrid.empty() )
781     return true;
782
783   myIndexer._xSize = 1 + mySides.GetSide( Q_BOTTOM )->GetNbSegments( mesh );
784   myIndexer._ySize = 1 + mySides.GetSide( Q_LEFT   )->GetNbSegments( mesh );
785
786   myGrid.resize( myIndexer.size() );
787
788   // strore nodes bound to the bottom edge
789   mySides.GetSide( Q_BOTTOM )->StoreNodes( mesh, myGrid, myReverse );
790
791   // store the rest nodes row by row
792
793   SMESHDS_SubMesh* faceSubMesh = mesh.GetSubMesh( myFace )->GetSubMeshDS();
794
795   SMDS_MeshNode dummy(0,0,0);
796   const SMDS_MeshElement* firstQuad = &dummy;// most left face above the last row of found nodes
797   
798   int nbFoundNodes = myIndexer._xSize;
799   while ( nbFoundNodes != myGrid.size() )
800   {
801     // first and last nodes of the last filled row of nodes
802     const SMDS_MeshNode* n1down = myGrid[ nbFoundNodes - myIndexer._xSize ];
803     const SMDS_MeshNode* n2down = myGrid[ nbFoundNodes - myIndexer._xSize + 1];
804     const SMDS_MeshNode* n1downLast = myGrid[ nbFoundNodes-1 ];
805
806     // find the first face above the row by the first two left nodes
807     //
808     // n1up     n2up
809     //     o---o
810     //     |   |
811     //     o---o  o  o  o  o
812     //n1down    n2down
813     //
814     TIDSortedElemSet emptySet, avoidSet;
815     avoidSet.insert( firstQuad );
816     firstQuad = SMESH_MeshEditor::FindFaceInSet( n1down, n2down, emptySet, avoidSet);
817     while ( firstQuad && !faceSubMesh->Contains( firstQuad )) {
818       avoidSet.insert( firstQuad );
819       firstQuad = SMESH_MeshEditor::FindFaceInSet( n1down, n2down, emptySet, avoidSet);
820     }
821     if ( !firstQuad || !faceSubMesh->Contains( firstQuad ))
822       return error(ERR_LI("Error in _QuadFaceGrid::LoadGrid()"));
823
824     // find the node of quad bound to the left geom edge
825     int i2down = firstQuad->GetNodeIndex( n2down );
826     const SMDS_MeshNode* n1up = firstQuad->GetNode(( i2down+2 ) % 4 );
827     myGrid[ nbFoundNodes++ ] = n1up;
828     // the 4-the node of the first quad
829     int i1down = firstQuad->GetNodeIndex( n1down );
830     const SMDS_MeshNode* n2up = firstQuad->GetNode(( i1down+2 ) % 4 );
831     myGrid[ nbFoundNodes++ ] = n2up;
832
833     n1down = n2down;
834     n1up   = n2up;
835     const SMDS_MeshElement* quad = firstQuad;
836
837     // find the rest nodes by remaining faces above the row
838     //
839     //             n1up
840     //     o---o--o
841     //     |   |  | ->
842     //     o---o--o  o  o  o
843     //                      n1downLast
844     //
845     while ( n1down != n1downLast )
846     {
847       // next face
848       avoidSet.clear(); avoidSet.insert( quad );
849       quad = SMESH_MeshEditor::FindFaceInSet( n1down, n1up, emptySet, avoidSet );
850       if ( !quad || quad->NbNodes() % 4 > 0)
851         return error(ERR_LI("Error in _QuadFaceGrid::LoadGrid()"));
852
853       // next node
854       if ( quad->GetNode( i1down ) != n1down ) // check already found index
855         i1down = quad->GetNodeIndex( n1down );
856       n2up = quad->GetNode(( i1down+2 ) % 4 );
857       myGrid[ nbFoundNodes++ ] = n2up;
858
859       n1down = myGrid[ nbFoundNodes - myIndexer._xSize - 1 ];
860       n1up   = n2up;
861     }
862   }
863
864   DumpGrid(); // debug
865
866   return true;
867 }
868
869 //================================================================================
870 /*!
871  * \brief Find out mutual location of children: find their right and up brothers
872  */
873 //================================================================================
874
875 bool _QuadFaceGrid::locateChildren()
876 {
877   if ( myLeftBottomChild )
878     return true;
879
880   TChildren::iterator child = myChildren.begin(), childEnd = myChildren.end();
881
882   // find a child sharing it's first bottom vertex with no other brother
883   myLeftBottomChild = 0;
884   for ( ; !myLeftBottomChild && child != childEnd; ++child )
885   {
886     TopoDS_Vertex leftVertex = child->GetSide( Q_BOTTOM ).FirstVertex();
887     bool sharedVertex = false;
888     TChildren::iterator otherChild = myChildren.begin();
889     for ( ; otherChild != childEnd && !sharedVertex; ++otherChild )
890       if ( otherChild != child )
891         sharedVertex = otherChild->mySides.Contain( leftVertex );
892     if ( !sharedVertex ) {
893       myLeftBottomChild = & (*child);
894       DUMP_VERT("0 left bottom Vertex: ",leftVertex );
895     }
896   }
897   if (!myLeftBottomChild)
898     return error(ERR_LI("Error in locateChildren()"));
899
900   set< _QuadFaceGrid* > notLocatedChilren;
901   for (child = myChildren.begin() ; child != childEnd; ++child )
902     notLocatedChilren.insert( & (*child));
903
904   // connect myLeftBottomChild to it's right and upper brothers
905   notLocatedChilren.erase( myLeftBottomChild );
906   myLeftBottomChild->setBrothers( notLocatedChilren );
907   if ( !notLocatedChilren.empty() )
908     return error(ERR_LI("Error in locateChildren()"));
909
910   return true;
911 }
912
913 //================================================================================
914 /*!
915  * \brief Fill myGrid with nodes of patches
916  */
917 //================================================================================
918
919 bool _QuadFaceGrid::loadCompositeGrid(SMESH_Mesh& mesh)
920 {
921   // Find out mutual location of children: find their right and up brothers
922   if ( !locateChildren() )
923     return false;
924
925   // Load nodes according to mutual location of children
926
927   // grid size
928   myIndexer._xSize = 1 + myLeftBottomChild->GetNbHoriSegments(mesh, /*withBrothers=*/true);
929   myIndexer._ySize = 1 + myLeftBottomChild->GetNbVertSegments(mesh, /*withBrothers=*/true);
930
931   myGrid.resize( myIndexer.size() );
932
933   int fromX = myReverse ? myIndexer._xSize : 0;
934   if (!myLeftBottomChild->fillGrid( mesh, myGrid, myIndexer, fromX, 0 ))
935     return error( myLeftBottomChild->GetError() );
936
937   DumpGrid();
938
939   return true;
940 }
941
942 //================================================================================
943 /*!
944  * \brief Find right an upper brothers among notLocatedBrothers
945  */
946 //================================================================================
947
948 void _QuadFaceGrid::setBrothers( set< _QuadFaceGrid* >& notLocatedBrothers )
949 {
950   if ( !notLocatedBrothers.empty() )
951   {
952     // find right brother
953     TopoDS_Vertex rightVertex = GetSide( Q_BOTTOM ).LastVertex();
954     DUMP_VERT("1 right bottom Vertex: ",rightVertex );
955     set< _QuadFaceGrid* >::iterator brIt, brEnd = notLocatedBrothers.end();
956     for ( brIt = notLocatedBrothers.begin(); !myRightBrother && brIt != brEnd; ++brIt )
957     {
958       _QuadFaceGrid* brother = *brIt;
959       TopoDS_Vertex brotherLeftVertex = brother->GetSide( Q_BOTTOM ).FirstVertex();
960       DUMP_VERT( "brother left bottom: ", brotherLeftVertex );
961       if ( rightVertex.IsSame( brotherLeftVertex )) {
962         myRightBrother = brother;
963         notLocatedBrothers.erase( myRightBrother );
964       }
965     }
966     // find upper brother
967     TopoDS_Vertex upVertex = GetSide( Q_LEFT ).FirstVertex();
968     DUMP_VERT("1 left up Vertex: ",upVertex);
969     brIt = notLocatedBrothers.begin(), brEnd = notLocatedBrothers.end();
970     for ( ; !myUpBrother && brIt != brEnd; ++brIt )
971     {
972       _QuadFaceGrid* brother = *brIt;
973       TopoDS_Vertex brotherLeftVertex = brother->GetSide( Q_BOTTOM ).FirstVertex();
974       DUMP_VERT("brother left bottom: ", brotherLeftVertex);
975       if ( upVertex.IsSame( brotherLeftVertex )) {
976         myUpBrother = brother;
977         notLocatedBrothers.erase( myUpBrother );
978       }
979     }
980     // recursive call
981     if ( myRightBrother )
982       myRightBrother->setBrothers( notLocatedBrothers );
983     if ( myUpBrother )
984       myUpBrother->setBrothers( notLocatedBrothers );
985   }
986 }
987
988 //================================================================================
989 /*!
990  * \brief Store nodes of a simple face into grid starting from (x,y) position
991  */
992 //================================================================================
993
994 bool _QuadFaceGrid::fillGrid(SMESH_Mesh&                    theMesh,
995                              vector<const SMDS_MeshNode*> & theGrid,
996                              const _Indexer&                theIndexer,
997                              int                            theX,
998                              int                            theY)
999 {
1000   if ( myGrid.empty() && !LoadGrid( theMesh ))
1001     return false;
1002
1003   // store my own grid in the global grid
1004
1005   int fromX = myReverse ? theX - myIndexer._xSize: theX;
1006
1007   for ( int i = 0, x = fromX; i < myIndexer._xSize; ++i, ++x )
1008     for ( int j = 0, y = theY; j < myIndexer._ySize; ++j, ++y )
1009       theGrid[ theIndexer( x, y )] = myGrid[ myIndexer( i, j )];
1010
1011   // store grids of my right and upper brothers
1012
1013   if ( myRightBrother )
1014   {
1015     if ( myReverse )
1016       fromX += 1;
1017     else
1018       fromX += myIndexer._xSize - 1;
1019     if ( !myRightBrother->fillGrid( theMesh, theGrid, theIndexer, fromX, theY ))
1020       return error( myRightBrother->GetError() );
1021   }
1022   if ( myUpBrother )
1023   {
1024     if ( !myUpBrother->fillGrid( theMesh, theGrid, theIndexer,
1025                                  theX, theY + myIndexer._ySize - 1))
1026       return error( myUpBrother->GetError() );
1027   }
1028   return true;
1029 }
1030
1031 //================================================================================
1032 /*!
1033  * \brief Return number of segments on the hirizontal sides
1034  */
1035 //================================================================================
1036
1037 int _QuadFaceGrid::GetNbHoriSegments(SMESH_Mesh& mesh, bool withBrothers) const
1038 {
1039   int nbSegs = 0;
1040   if ( myLeftBottomChild )
1041   {
1042     nbSegs += myLeftBottomChild->GetNbHoriSegments( mesh, true );
1043   }
1044   else
1045   {
1046     nbSegs = mySides.GetSide( Q_BOTTOM )->GetNbSegments(mesh);
1047     if ( withBrothers && myRightBrother )
1048       nbSegs += myRightBrother->GetNbHoriSegments( mesh, withBrothers );
1049   }
1050   return nbSegs;
1051 }
1052
1053 //================================================================================
1054 /*!
1055  * \brief Return number of segments on the vertical sides
1056  */
1057 //================================================================================
1058
1059 int _QuadFaceGrid::GetNbVertSegments(SMESH_Mesh& mesh, bool withBrothers) const
1060 {
1061   int nbSegs = 0;
1062   if ( myLeftBottomChild )
1063   {
1064     nbSegs += myLeftBottomChild->GetNbVertSegments( mesh, true );
1065   }
1066   else
1067   {
1068     nbSegs = mySides.GetSide( Q_LEFT )->GetNbSegments(mesh);
1069     if ( withBrothers && myUpBrother )
1070       nbSegs += myUpBrother->GetNbVertSegments( mesh, withBrothers );
1071   }
1072   return nbSegs;
1073 }
1074
1075 //================================================================================
1076 /*!
1077  * \brief Return a node by its position
1078  */
1079 //================================================================================
1080
1081 const SMDS_MeshNode* _QuadFaceGrid::GetNode(int iHori, int iVert) const
1082 {
1083   return myGrid[ myIndexer( iHori, iVert )];
1084 }
1085
1086 //================================================================================
1087 /*!
1088  * \brief Return node coordinates by its position
1089  */
1090 //================================================================================
1091
1092 gp_XYZ _QuadFaceGrid::GetXYZ(int iHori, int iVert) const
1093 {
1094   const SMDS_MeshNode* n = myGrid[ myIndexer( iHori, iVert )];
1095   return gp_XYZ( n->X(), n->Y(), n->Z() );
1096 }
1097
1098 //================================================================================
1099 /*!
1100  * \brief Return normal to the face at vertex v
1101  */
1102 //================================================================================
1103
1104 bool _QuadFaceGrid::GetNormal( const TopoDS_Vertex& v, gp_Vec& n ) const
1105 {
1106   if ( myChildren.empty() )
1107   {
1108     if ( mySides.Contain( v )) {
1109       try {
1110         gp_Pnt2d uv = BRep_Tool::Parameters( v, myFace );
1111         BRepAdaptor_Surface surface( myFace );
1112         gp_Pnt p; gp_Vec d1u, d1v;
1113         surface.D1( uv.X(), uv.Y(), p, d1u, d1v );
1114         n = d1u.Crossed( d1v );
1115         return true;
1116       }
1117       catch (Standard_Failure) {
1118         return false;
1119       }
1120     }
1121   }
1122   else
1123   {
1124     TChildren::const_iterator child = myChildren.begin(), childEnd = myChildren.end();
1125     for ( ; child != childEnd; ++child )
1126       if ( child->GetNormal( v, n ))
1127         return true;
1128   }
1129   return false;
1130 }
1131
1132 //================================================================================
1133 /*!
1134  * \brief Dumps coordinates of grid nodes
1135  */
1136 //================================================================================
1137
1138 void _QuadFaceGrid::DumpGrid() const
1139 {
1140 #ifdef DEB_GRID
1141   const char* names[] = { "B_BOTTOM", "B_RIGHT", "B_TOP", "B_LEFT", "B_FRONT", "B_BACK" };
1142   cout << "****** Face " << names[ myID ] << endl;
1143
1144   if ( myChildren.empty() || !myGrid.empty() )
1145   {
1146     cout << "x size: " << myIndexer._xSize << "; y size: " << myIndexer._ySize << endl;
1147     for ( int y = 0; y < myIndexer._ySize; ++y ) {
1148       cout << "-- row " << y << endl;
1149       for ( int x = 0; x < myIndexer._xSize; ++x ) {
1150         const SMDS_MeshNode* n = myGrid[ myIndexer( x, y ) ];
1151         cout << x << " ( " << n->X() << ", " << n->Y() << ", " << n->Z() << " )" << endl;
1152       }
1153     }
1154   }
1155   else
1156   {
1157     cout << "Nb children: " << myChildren.size() << endl;
1158     TChildren::const_iterator child = myChildren.begin(), childEnd = myChildren.end();
1159     for ( int i=0; child != childEnd; ++child, ++i ) {
1160       cout << "   *** SUBFACE " << i+1 << endl;
1161       ((_QuadFaceGrid&)(*child)).SetID( myID );
1162       child->DumpGrid();
1163     }
1164   }
1165 #endif
1166 }
1167
1168 //================================================================================
1169 /*!
1170  * \brief Dump vertices
1171  */
1172 //================================================================================
1173
1174 void _QuadFaceGrid::DumpVertices() const
1175 {
1176 #ifdef DEB_FACES
1177   cout << "****** Face ";
1178   const char* names[] = { "B_BOTTOM", "B_RIGHT", "B_TOP", "B_LEFT", "B_FRONT", "B_BACK" };
1179   if ( myID >= B_BOTTOM && myID < B_BACK )
1180     cout << names[ myID ] << endl;
1181   else
1182     cout << "UNDEFINED" << endl;
1183
1184   if ( myChildren.empty() )
1185   {
1186     for ( int i = 0; i < 4; ++i )
1187     {
1188       cout << "  Side "; mySides.GetSide( i )->Dump();
1189     }
1190   }
1191   else
1192   {
1193     cout << "-- Nb children: " << myChildren.size() << endl;
1194     TChildren::const_iterator child = myChildren.begin(), childEnd = myChildren.end();
1195     for ( int i=0; child != childEnd; ++child, ++i ) {
1196       cout << "   *** SUBFACE " << i+1 << endl;
1197       ((_QuadFaceGrid&)(*child)).SetID( myID );
1198       child->DumpVertices();
1199     }
1200   }
1201 #endif
1202 }
1203
1204 //=======================================================================
1205 //function : _FaceSide
1206 //purpose  : copy constructor
1207 //=======================================================================
1208
1209 _FaceSide::_FaceSide(const _FaceSide& other)
1210 {
1211   myEdge = other.myEdge;
1212   myChildren = other.myChildren;
1213   myNbChildren = other.myNbChildren;
1214   myVertices.Assign( other.myVertices );
1215   myID = other.myID;
1216 }
1217
1218 //================================================================================
1219 /*!
1220  * \brief Construct a face side of one edge
1221  */
1222 //================================================================================
1223
1224 _FaceSide::_FaceSide(const TopoDS_Edge& edge):
1225   myEdge( edge ), myNbChildren(0)
1226 {
1227   if ( !edge.IsNull() )
1228     for ( TopExp_Explorer exp( edge, TopAbs_VERTEX ); exp.More(); exp.Next() )
1229       //myVertices.insert( ptr ( exp.Current() ));
1230       myVertices.Add( exp.Current() );
1231 }
1232
1233 //================================================================================
1234 /*!
1235  * \brief Construct a face side of several edges
1236  */
1237 //================================================================================
1238
1239 _FaceSide::_FaceSide(const list<TopoDS_Edge>& edges):
1240   myNbChildren(0)
1241 {
1242   list<TopoDS_Edge>::const_iterator edge = edges.begin(), eEnd = edges.end();
1243   for ( ; edge != eEnd; ++edge ) {
1244     myChildren.push_back( _FaceSide( *edge ));
1245     myNbChildren++;
1246 //     myVertices.insert( myChildren.back().myVertices.begin(),
1247 //                        myChildren.back().myVertices.end() );
1248     myVertices.Add( myChildren.back().FirstVertex() );
1249     myVertices.Add( myChildren.back().LastVertex() );
1250     myChildren.back().SetID( Q_CHILD ); // not to splice them
1251   }
1252 }
1253
1254 //=======================================================================
1255 //function : GetSide
1256 //purpose  : 
1257 //=======================================================================
1258
1259 _FaceSide* _FaceSide::GetSide(const int i)
1260 {
1261   if ( i >= myNbChildren )
1262     return 0;
1263
1264   list< _FaceSide >::iterator side = myChildren.begin();
1265   if ( i )
1266     std::advance( side, i );
1267   return & (*side);
1268 }
1269
1270 //=======================================================================
1271 //function : GetSide
1272 //purpose  : 
1273 //=======================================================================
1274
1275 const _FaceSide* _FaceSide::GetSide(const int i) const
1276 {
1277   return const_cast< _FaceSide* >(this)->GetSide(i);
1278 }
1279
1280 //=======================================================================
1281 //function : NbVertices
1282 //purpose  : return nb of vertices in the side
1283 //=======================================================================
1284
1285 int _FaceSide::NbVertices() const
1286 {
1287   if ( myChildren.empty() )
1288     return myVertices.Extent();
1289 //     return myVertices.size();
1290
1291   return myNbChildren + 1;
1292 }
1293
1294 //=======================================================================
1295 //function : FirstVertex
1296 //purpose  : 
1297 //=======================================================================
1298
1299 TopoDS_Vertex _FaceSide::FirstVertex() const
1300 {
1301   if ( myChildren.empty() )
1302     return TopExp::FirstVertex( myEdge, Standard_True );
1303
1304   return myChildren.front().FirstVertex();
1305 }
1306
1307 //=======================================================================
1308 //function : LastVertex
1309 //purpose  : 
1310 //=======================================================================
1311
1312 TopoDS_Vertex _FaceSide::LastVertex() const
1313 {
1314   if ( myChildren.empty() )
1315     return TopExp::LastVertex( myEdge, Standard_True );
1316
1317   return myChildren.back().LastVertex();
1318 }
1319
1320 //=======================================================================
1321 //function : Vertex
1322 //purpose  : 
1323 //=======================================================================
1324
1325 TopoDS_Vertex _FaceSide::Vertex(int i) const
1326 {
1327   if ( myChildren.empty() )
1328     return i ? LastVertex() : FirstVertex();
1329       
1330   if ( i >= myNbChildren )
1331     return myChildren.back().LastVertex();
1332   
1333   return GetSide(i)->FirstVertex();
1334 }
1335
1336 //=======================================================================
1337 //function : Contain
1338 //purpose  : 
1339 //=======================================================================
1340
1341 bool _FaceSide::Contain( const _FaceSide& side, int* which ) const
1342 {
1343   if ( !which || myChildren.empty() )
1344   {
1345     if ( which )
1346       *which = 0;
1347     int nbCommon = 0;
1348 //     set<const TopoDS_TShape*>::iterator v, vEnd = side.myVertices.end();
1349 //     for ( v = side.myVertices.begin(); v != vEnd; ++v )
1350 //       nbCommon += ( myVertices.find( *v ) != myVertices.end() );
1351     TopTools_MapIteratorOfMapOfShape vIt ( side.myVertices );
1352     for ( ; vIt.More(); vIt.Next() )
1353       nbCommon += ( myVertices.Contains( vIt.Key() ));
1354     return (nbCommon > 1);
1355   }
1356   list< _FaceSide >::const_iterator mySide = myChildren.begin(), sideEnd = myChildren.end();
1357   for ( int i = 0; mySide != sideEnd; ++mySide, ++i ) {
1358     if ( mySide->Contain( side )) {
1359       *which = i;
1360       return true;
1361     }
1362   }
1363   return false;
1364 }
1365
1366 //=======================================================================
1367 //function : Contain
1368 //purpose  : 
1369 //=======================================================================
1370
1371 bool _FaceSide::Contain( const TopoDS_Vertex& vertex ) const
1372 {
1373   return myVertices.Contains( vertex );
1374 //   return myVertices.find( ptr( vertex )) != myVertices.end();
1375 }
1376
1377 //=======================================================================
1378 //function : AppendSide
1379 //purpose  : 
1380 //=======================================================================
1381
1382 void _FaceSide::AppendSide( const _FaceSide& side )
1383 {
1384   if ( !myEdge.IsNull() )
1385   {
1386     myChildren.push_back( *this );
1387     myNbChildren = 1;
1388     myEdge.Nullify();
1389   }
1390   myChildren.push_back( side );
1391   myNbChildren++;
1392   //myVertices.insert( side.myVertices.begin(), side.myVertices.end() );
1393   TopTools_MapIteratorOfMapOfShape vIt ( side.myVertices );
1394   for ( ; vIt.More(); vIt.Next() )
1395     myVertices.Add( vIt.Key() );
1396
1397   myID = Q_PARENT;
1398   myChildren.back().SetID( EQuadSides( myNbChildren-1 ));
1399 }
1400
1401 //=======================================================================
1402 //function : SetBottomSide
1403 //purpose  : 
1404 //=======================================================================
1405
1406 void _FaceSide::SetBottomSide( int i )
1407 {
1408   if ( i > 0 && myID == Q_PARENT ) {
1409     list< _FaceSide >::iterator sideEnd, side = myChildren.begin();
1410     std::advance( side, i );
1411     myChildren.splice( myChildren.begin(), myChildren, side, myChildren.end() );
1412
1413     side = myChildren.begin(), sideEnd = myChildren.end();
1414     for ( int i = 0; side != sideEnd; ++side, ++i ) {
1415       side->SetID( EQuadSides(i) );
1416       side->SetBottomSide(i);
1417     }
1418   }
1419 }
1420
1421 //=======================================================================
1422 //function : GetNbSegments
1423 //purpose  : 
1424 //=======================================================================
1425
1426 int _FaceSide::GetNbSegments(SMESH_Mesh& mesh) const
1427 {
1428   int nb = 0;
1429   if ( myChildren.empty() )
1430   {
1431     nb = mesh.GetSubMesh(myEdge)->GetSubMeshDS()->NbElements();
1432   }
1433   else
1434   {
1435     list< _FaceSide >::const_iterator side = myChildren.begin(), sideEnd = myChildren.end();
1436     for ( ; side != sideEnd; ++side )
1437       nb += side->GetNbSegments(mesh);
1438   }
1439   return nb;
1440 }
1441
1442 //=======================================================================
1443 //function : StoreNodes
1444 //purpose  : 
1445 //=======================================================================
1446
1447 bool _FaceSide::StoreNodes(SMESH_Mesh&                   mesh,
1448                            vector<const SMDS_MeshNode*>& myGrid,
1449                            bool                          reverse )
1450 {
1451   list< TopoDS_Edge > edges;
1452   if ( myChildren.empty() )
1453   {
1454     edges.push_back( myEdge );
1455   }
1456   else
1457   {
1458     list< _FaceSide >::const_iterator side = myChildren.begin(), sideEnd = myChildren.end();
1459     for ( ; side != sideEnd; ++side )
1460       if ( reverse )
1461         edges.push_front( side->myEdge );
1462       else
1463         edges.push_back ( side->myEdge );
1464   }
1465   int nbNodes = 0;
1466   list< TopoDS_Edge >::iterator edge = edges.begin(), eEnd = edges.end();
1467   for ( ; edge != eEnd; ++edge )
1468   {
1469     map< double, const SMDS_MeshNode* > nodes;
1470     bool ok = SMESH_Algo::GetSortedNodesOnEdge( mesh.GetMeshDS(),
1471                                                 *edge,
1472                                                 /*ignoreMediumNodes=*/true,
1473                                                 nodes);
1474     if ( !ok ) return false;
1475
1476     bool forward = ( edge->Orientation() == TopAbs_FORWARD );
1477     if ( reverse ) forward = !forward;
1478     if ( forward )
1479     {
1480       map< double, const SMDS_MeshNode* >::iterator u_node, nEnd = nodes.end();
1481       for ( u_node = nodes.begin(); u_node != nEnd; ++u_node )
1482         myGrid[ nbNodes++ ] = u_node->second;
1483     }
1484     else 
1485     {
1486       map< double, const SMDS_MeshNode* >::reverse_iterator u_node, nEnd = nodes.rend();
1487       for ( u_node = nodes.rbegin(); u_node != nEnd; ++u_node )
1488         myGrid[ nbNodes++ ] = u_node->second;
1489     }
1490     nbNodes--; // node on vertex present in two adjacent edges
1491   }
1492   return nbNodes > 0;
1493 }
1494
1495 //=======================================================================
1496 //function : Dump
1497 //purpose  : dump end vertices
1498 //=======================================================================
1499
1500 void _FaceSide::Dump() const
1501 {
1502   if ( myChildren.empty() )
1503   {
1504     const char* sideNames[] = { "Q_BOTTOM", "Q_RIGHT", "Q_TOP", "Q_LEFT", "Q_CHILD", "Q_PARENT" };
1505     if ( myID >= Q_BOTTOM && myID < Q_PARENT )
1506       cout << sideNames[ myID ] << endl;
1507     else
1508       cout << "<UNDEFINED ID>" << endl;
1509     TopoDS_Vertex f = FirstVertex();
1510     TopoDS_Vertex l = LastVertex();
1511     gp_Pnt pf = BRep_Tool::Pnt(f);
1512     gp_Pnt pl = BRep_Tool::Pnt(l);
1513     cout << "\t ( "<< ptr( f ) << " - " << ptr( l )<< " )"
1514          << "\t ( "<< pf.X()<<", "<<pf.Y()<<", "<<pf.Z()<<" ) - "
1515          << " ( "<< pl.X()<<", "<<pl.Y()<<", "<<pl.Z()<<" )"<<endl;
1516   }
1517   else
1518   {
1519     list< _FaceSide >::const_iterator side = myChildren.begin(), sideEnd = myChildren.end();
1520     for ( ; side != sideEnd; ++side ) {
1521       side->Dump();
1522       cout << "\t";
1523     }
1524   }
1525 }