]> SALOME platform Git repositories - modules/smesh.git/commitdiff
Salome HOME
WinTC
authormaintenance team <salome-mnt@opencascade.com>
Thu, 9 Sep 2010 12:08:58 +0000 (12:08 +0000)
committermaintenance team <salome-mnt@opencascade.com>
Thu, 9 Sep 2010 12:08:58 +0000 (12:08 +0000)
src/StdMeshers/StdMeshers_FaceSide.cxx

index 19859a2b3c283f67aeb4d5a80b9adf8172491750..26f0493d72539cf5e6dbd0e2123d55bc080df74c 100644 (file)
-//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
-//
-//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-
-//  SMESH SMESH : implementaion of SMESH idl descriptions
-// File      : StdMeshers_FaceSide.hxx
-// Created   : Wed Jan 31 18:41:25 2007
-// Author    : Edward AGAPOV (eap)
-// Module    : SMESH
-//
-#include "StdMeshers_FaceSide.hxx"
-
-#include "SMDS_EdgePosition.hxx"
-#include "SMDS_MeshNode.hxx"
-#include "SMESHDS_Mesh.hxx"
-#include "SMESHDS_SubMesh.hxx"
-#include "SMESH_Algo.hxx"
-#include "SMESH_Mesh.hxx"
-#include "SMESH_MesherHelper.hxx"
-#include "SMESH_ComputeError.hxx"
-#include "SMESH_Block.hxx"
-
-#include <Adaptor2d_Curve2d.hxx>
-#include <BRepAdaptor_CompCurve.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <BRep_Builder.hxx>
-#include <BRep_Tool.hxx>
-#include <TopExp.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS_Wire.hxx>
-
-#include <GCPnts_AbscissaPoint.hxx>
-#include <Geom2dAdaptor_Curve.hxx>
-
-#include <map>
-
-#include "utilities.h"
-
-//================================================================================
-/*!
- * \brief Constructor of a side of one edge
-  * \param theFace - the face
-  * \param theEdge - the edge
- */
-//================================================================================
-
-StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
-                                         const TopoDS_Edge& theEdge,
-                                         SMESH_Mesh*        theMesh,
-                                         const bool         theIsForward,
-                                         const bool         theIgnoreMediumNodes)
-{
-  list<TopoDS_Edge> edges(1,theEdge);
-  *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward, theIgnoreMediumNodes );
-}
-
-//================================================================================
-/*!
- * \brief Constructor of a side of several edges
-  * \param theFace - the face
-  * \param theEdge - the edge
- */
-//================================================================================
-
-StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
-                                         list<TopoDS_Edge>& theEdges,
-                                         SMESH_Mesh*        theMesh,
-                                         const bool         theIsForward,
-                                         const bool         theIgnoreMediumNodes)
-{
-  int nbEdges = theEdges.size();
-  myEdge.resize( nbEdges );
-  myC2d.resize( nbEdges );
-  myC3dAdaptor.resize( nbEdges );
-  myFirst.resize( nbEdges );
-  myLast.resize( nbEdges );
-  myNormPar.resize( nbEdges );
-  myEdgeLength.resize( nbEdges );
-  myIsUniform.resize( nbEdges, true );
-  myLength = 0;
-  myNbPonits = myNbSegments = 0;
-  myMesh = theMesh;
-  myMissingVertexNodes = false;
-  myIgnoreMediumNodes = theIgnoreMediumNodes;
-  myDefaultPnt2d = gp_Pnt2d( 1e+100, 1e+100 );
-  if ( nbEdges == 0 ) return;
-
-  SMESHDS_Mesh* meshDS = theMesh->GetMeshDS();
-
-  int nbDegen = 0;
-  list<TopoDS_Edge>::iterator edge = theEdges.begin();
-  TopoDS_Iterator vExp;
-  for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
-  {
-    int i = theIsForward ? index : nbEdges - index - 1;
-    myEdgeLength[i] = SMESH_Algo::EdgeLength( *edge );
-    if ( myEdgeLength[i] < DBL_MIN ) nbDegen++;
-    myLength += myEdgeLength[i];
-    myEdge[i] = *edge;
-    if ( !theIsForward ) myEdge[i].Reverse();
-
-    if ( theFace.IsNull() )
-      BRep_Tool::Range( *edge, myFirst[i], myLast[i] );
-    else
-      myC2d[i] = BRep_Tool::CurveOnSurface( *edge, theFace, myFirst[i], myLast[i] );
-    if ( myEdge[i].Orientation() == TopAbs_REVERSED )
-      std::swap( myFirst[i], myLast[i] );
-
-    if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( *edge )) {
-      int nbN = sm->NbNodes();
-      if ( theIgnoreMediumNodes ) {
-        SMDS_ElemIteratorPtr elemIt = sm->GetElements();
-        if ( elemIt->more() && elemIt->next()->IsQuadratic() )
-          nbN -= sm->NbElements();
-      }
-      myNbPonits += nbN;
-      myNbSegments += sm->NbElements();
-    }
-    // TopExp::FirstVertex() and TopExp::LastVertex() return NULL from INTERNAL edge
-    vExp.Initialize( *edge );
-    if ( vExp.Value().Orientation() == TopAbs_REVERSED ) vExp.Next();
-    if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))
-      myNbPonits += 1; // for the first end
-    else
-      myMissingVertexNodes = true;
-
-    // check if edge has non-uniform parametrization (issue 0020705)
-    if ( !myC2d[i].IsNull() && myEdgeLength[i] > DBL_MIN)
-    {
-      Geom2dAdaptor_Curve A2dC( myC2d[i] );
-      double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2., p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;
-      double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 );
-      double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 );
-      //cout<<"len = "<<len<<"  d2 = "<<d2<<"  fabs(2*d2/len-1.0) = "<<fabs(2*d2/len-1.0)<<endl;
-      myIsUniform[i] = !( fabs(2*d2/myEdgeLength[i]-1.0) > 0.01 || fabs(2*d4/d2-1.0) > 0.01 );
-      if ( !myIsUniform[i] )
-      {
-        double fp,lp;
-        TopLoc_Location L;
-        Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],L,fp,lp);
-        myC3dAdaptor[i].Load( C3d, fp,lp );
-      }
-    }
-  }
-  vExp.Initialize( theEdges.back() );
-  if ( vExp.Value().Orientation() != TopAbs_REVERSED ) vExp.Next();
-  if ( vExp.More() )
-  {
-    if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))
-      myNbPonits++; // for the last end
-    else
-      myMissingVertexNodes = true;
-  }
-  if ( nbEdges > 1 && myLength > DBL_MIN ) {
-    const double degenNormLen = 1.e-5;
-    double totLength = myLength;
-    if ( nbDegen )
-      totLength += myLength * degenNormLen * nbDegen;
-    double prevNormPar = 0;
-    for ( int i = 0; i < nbEdges; ++i ) {
-      if ( myEdgeLength[ i ] < DBL_MIN )
-        myEdgeLength[ i ] = myLength * degenNormLen;
-      myNormPar[ i ] = prevNormPar + myEdgeLength[i]/totLength;
-      prevNormPar = myNormPar[ i ];
-    }
-  }
-  myNormPar[nbEdges-1] = 1.;
-  //dump();
-}
-
-//================================================================================
-/*!
- * \brief Constructor of a side for vertex using data from other FaceSide
-  * \param theVertex - the vertex
-  * \param theSide - the side
- */
-//================================================================================
-
-StdMeshers_FaceSide::StdMeshers_FaceSide(const SMDS_MeshNode* theNode,
-                                         const gp_Pnt2d thePnt2d,
-                                         const StdMeshers_FaceSide* theSide)
-{
-  myC2d.resize(1);
-  myLength = 0;
-  myMesh = theSide->GetMesh();
-  myDefaultPnt2d = thePnt2d;
-
-  myPoints = theSide->GetUVPtStruct();
-  myNbPonits = myNbSegments = myPoints.size();
-  std::vector<uvPtStruct>::iterator it = myPoints.begin();
-  for(; it!=myPoints.end(); it++) {
-    (*it).u = thePnt2d.X();
-    (*it).v = thePnt2d.Y();
-    (*it).y = 0.0;
-    (*it).node = theNode;
-  }
-}
-
-//================================================================================
-/*!
- * \brief Return info on nodes on the side
-  * \retval UVPtStruct* - array of data structures
- */
-//================================================================================
-
-const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
-                                                             double constValue) const
-{
-  if ( myPoints.empty() ) {
-
-    if ( NbEdges() == 0 ) return myPoints;
-
-    SMESHDS_Mesh* meshDS = myMesh->GetMeshDS();
-    SMESH_MesherHelper helper(*myMesh);
-    bool paramOK;
-
-    // sort nodes of all edges putting them into a map
-
-    map< double, const SMDS_MeshNode*> u2node;
-    //int nbOnDegen = 0;
-    for ( int i = 0; i < myEdge.size(); ++i )
-    {
-      // Put 1st vertex node of a current edge
-      TopoDS_Vertex VV[2]; // TopExp::FirstVertex() returns NULL for INTERNAL edge
-      for ( TopoDS_Iterator vIt(myEdge[i]); vIt.More(); vIt.Next() )
-        VV[ VV[0].IsNull() ? 0 : 1 ] = TopoDS::Vertex(vIt.Value());
-      if ( VV[0].Orientation() == TopAbs_REVERSED ) std::swap ( VV[0], VV[1] );
-      const SMDS_MeshNode* node = SMESH_Algo::VertexNode( VV[0], meshDS );
-      double prevNormPar = ( i == 0 ? 0 : myNormPar[ i-1 ]); // normalized param
-      if ( node ) { // internal nodes may be missing
-        u2node.insert( make_pair( prevNormPar, node ));
-      }
-      else if ( i == 0 ) {
-        MESSAGE(" NO NODE on VERTEX" );
-        return myPoints;
-      }
-
-      // Put internal nodes
-      SMESHDS_SubMesh* sm = meshDS->MeshElements( myEdge[i] );
-      if ( !sm ) continue;
-      vector< pair< double, const SMDS_MeshNode*> > u2nodeVec;
-      u2nodeVec.reserve( sm->NbNodes() );
-      SMDS_NodeIteratorPtr nItr = sm->GetNodes();
-      double paramSize = myLast[i] - myFirst[i];
-      double r = myNormPar[i] - prevNormPar;
-      if ( !myIsUniform[i] )
-        while ( nItr->more() )
-        {
-          const SMDS_MeshNode* node = nItr->next();
-          if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
-            continue;
-          double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );
-          double aLenU = GCPnts_AbscissaPoint::Length
-            ( const_cast<GeomAdaptor_Curve&>( myC3dAdaptor[i]), myFirst[i], u );
-          if ( myEdgeLength[i] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6"
-          {
-            u2nodeVec.clear();
-            break;
-          }
-          double normPar = prevNormPar + r*aLenU/myEdgeLength[i];
-          u2nodeVec.push_back( make_pair( normPar, node ));
-        }
-      nItr = sm->GetNodes();
-      if ( u2nodeVec.empty() )
-        while ( nItr->more() )
-        {
-          const SMDS_MeshNode* node = nItr->next();
-          if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
-            continue;
-          double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );
-
-          // paramSize is signed so orientation is taken into account
-          double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize;
-          u2nodeVec.push_back( make_pair( normPar, node ));
-        }
-      u2node.insert( u2nodeVec.begin(), u2nodeVec.end() );
-
-      // Put 2nd vertex node for a last edge
-      if ( i+1 == myEdge.size() ) {
-        node = SMESH_Algo::VertexNode( VV[1], meshDS );
-        if ( !node ) {
-          MESSAGE(" NO NODE on VERTEX" );
-          return myPoints;
-        }
-        u2node.insert( make_pair( 1., node ));
-      }
-    }
-    if ( u2node.size() != myNbPonits ) {
-      MESSAGE("Wrong node parameters on edges, u2node.size():"
-              <<u2node.size()<<" !=  myNbPonits:"<<myNbPonits);
-      return myPoints;
-    }
-
-    // fill array of UVPtStruct
-
-    vector<uvPtStruct>* points = const_cast<vector<uvPtStruct>*>( &myPoints );
-    points->resize( myNbPonits );
-
-    int EdgeIndex = 0;
-    double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ];
-    map< double, const SMDS_MeshNode*>::iterator u_node = u2node.begin();
-    for (int i = 0 ; u_node != u2node.end(); ++u_node, ++i ) {
-      UVPtStruct & uvPt = (*points)[i];
-      uvPt.node = u_node->second;
-      uvPt.x = uvPt.y = uvPt.normParam = u_node->first;
-      if ( isXConst ) uvPt.x = constValue;
-      else            uvPt.y = constValue;
-      if ( myNormPar[ EdgeIndex ] < uvPt.normParam ) {
-        prevNormPar = myNormPar[ EdgeIndex ];
-        ++EdgeIndex;
-#ifdef _DEBUG_
-        if ( EdgeIndex >= myEdge.size() ) {
-          dump("DEBUG");
-          MESSAGE ( "WRONg EdgeIndex " << 1+EdgeIndex
-                    << " myNormPar.size()="<<myNormPar.size()
-                    << " myNormPar["<< EdgeIndex<<"]="<< myNormPar[ EdgeIndex ]
-                    << " uvPt.normParam="<<uvPt.normParam );
-        }
-#endif
-        paramSize = myNormPar[ EdgeIndex ] - prevNormPar;
-      }
-      const SMDS_EdgePosition* epos =
-        dynamic_cast<const SMDS_EdgePosition*>(uvPt.node->GetPosition().get());
-      if ( epos ) {
-        uvPt.param = epos->GetUParameter();
-      }
-      else {
-        double r = ( uvPt.normParam - prevNormPar )/ paramSize;
-//         uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r;
-        uvPt.param = ( r > 0.5 ? myLast[EdgeIndex] : myFirst[EdgeIndex] );
-      }
-      if ( !myC2d[ EdgeIndex ].IsNull() ) {
-        gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param );
-        uvPt.u = p.X();
-        uvPt.v = p.Y();
-      }
-      else {
-        uvPt.u = uvPt.v = 1e+100;
-      }
-    }
-  }
-  return myPoints;
-}
-
-//================================================================================
-/*!
- * \brief Falsificate info on nodes
-  * \param nbSeg - nb of segments on the side
-  * \retval UVPtStruct* - array of data structures
- */
-//================================================================================
-
-const vector<UVPtStruct>& StdMeshers_FaceSide::SimulateUVPtStruct(int    nbSeg,
-                                                                  bool   isXConst,
-                                                                  double constValue) const
-{
-  if ( myFalsePoints.empty() ) {
-
-    if ( NbEdges() == 0 ) return myFalsePoints;
-
-    vector<uvPtStruct>* points = const_cast<vector<uvPtStruct>*>( &myFalsePoints );
-    points->resize( nbSeg+1 );
-
-    int EdgeIndex = 0;
-    double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ];
-    for (int i = 0 ; i < myFalsePoints.size(); ++i ) {
-      double normPar = double(i) / double(nbSeg);
-      UVPtStruct & uvPt = (*points)[i];
-      uvPt.node = 0;
-      uvPt.x = uvPt.y = uvPt.param = uvPt.normParam = normPar;
-      if ( isXConst ) uvPt.x = constValue;
-      else            uvPt.y = constValue;
-      if ( myNormPar[ EdgeIndex ] < normPar ) {
-        prevNormPar = myNormPar[ EdgeIndex ];
-        ++EdgeIndex;
-        paramSize = myNormPar[ EdgeIndex ] - prevNormPar;
-      }
-      double r = ( normPar - prevNormPar )/ paramSize;
-      uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r;
-      if ( !myC2d[ EdgeIndex ].IsNull() ) {
-        gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param );
-        uvPt.u = p.X();
-        uvPt.v = p.Y();
-      }
-      else {
-        uvPt.u = uvPt.v = 1e+100;
-      }
-    }
-  }
-  return myFalsePoints;
-}
-// gp_Pnt StdMeshers_FaceSide::Value(double U) const
-// {
-// }
-
-//================================================================================
-/*!
- * \brief reverse order of vector elements
-  * \param vec - vector to reverse
- */
-//================================================================================
-
-template <typename T > void reverse(vector<T> & vec)
-{
-  for ( int f=0, r=vec.size()-1; f < r; ++f, --r )
-    std::swap( vec[f], vec[r] );
-}
-
-//================================================================================
-/*!
- * \brief Change orientation of side geometry
- */
-//================================================================================
-
-void StdMeshers_FaceSide::Reverse()
-{
-  int nbEdges = myEdge.size();
-  for ( int i = nbEdges-1; i >= 0; --i ) {
-    std::swap( myFirst[i], myLast[i] );
-    myEdge[i].Reverse();
-    if ( i > 0 ) // at the first loop 1. is overwritten
-      myNormPar[i] = 1 - myNormPar[i-1];
-  }
-  if ( nbEdges > 1 ) {
-    reverse( myEdge );
-    reverse( myC2d );
-    reverse( myC3dAdaptor );
-    reverse( myFirst );
-    reverse( myLast );
-    reverse( myNormPar );
-    reverse( myEdgeLength );
-    reverse( myIsUniform );
-  }
-  myNormPar[nbEdges-1]=1.;
-  myPoints.clear();
-  myFalsePoints.clear();
-}
-
-//================================================================================
-/*!
- * \brief Show side features
- */
-//================================================================================
-
-void StdMeshers_FaceSide::dump(const char* msg) const
-{
-#ifdef _DEBUG_
-  if (msg) MESSAGE ( std::endl << msg );
-  MESSAGE_BEGIN ("NB EDGES: "<< myEdge.size() );
-  MESSAGE_ADD ( "nbPoints: "<<myNbPonits<<" vecSize: " << myPoints.size()<<" "<<myFalsePoints.size() );
-  for ( int i=0; i<myEdge.size(); ++i)
-  {
-    MESSAGE_ADD ( "\t"<<i+1 );
-    MESSAGE_ADD ( "\tEDGE: " );
-    if (myEdge[i].IsNull()) {
-      MESSAGE_ADD ( "NULL" );
-    }
-    else {
-      TopAbs::Print(myEdge[i].Orientation(),cout)<<" "<<myEdge[i].TShape().operator->()<<endl;
-      MESSAGE_ADD ( "\tV1: " << TopExp::FirstVertex( myEdge[i], 1).TShape().operator->()
-                 << "  V2: " << TopExp::LastVertex( myEdge[i], 1).TShape().operator->() );
-    }
-    MESSAGE_ADD ( "\tC2d: ");
-    
-    if (myC2d[i].IsNull()) {
-      MESSAGE_ADD ( "NULL" );
-    }
-    else {
-      MESSAGE_ADD ( myC2d[i].operator->() );
-    }
-      
-    MESSAGE_ADD ( "\tF: "<<myFirst[i]<< " L: "<< myLast[i] );
-    MESSAGE_END ( "\tnormPar: "<<myNormPar[i]<<endl );
-  }
-#endif
-}
-
-//================================================================================
-/*!
- * \brief Creates a Adaptor2d_Curve2d to be used in SMESH_Block
-  * \retval Adaptor2d_Curve2d* - 
- */
-//================================================================================
-
-struct Adaptor2dCurve2d : public Adaptor2d_Curve2d
-{
-  const StdMeshers_FaceSide* mySide;
-  Adaptor2dCurve2d(const StdMeshers_FaceSide* faceSide):mySide(faceSide) {}
-  gp_Pnt2d Value(const Standard_Real U) const { return mySide->Value2d( U ); }
-  Standard_Real FirstParameter() const { return 0; }
-  Standard_Real LastParameter() const { return 1; }
-};
-
-Adaptor2d_Curve2d* StdMeshers_FaceSide::GetCurve2d() const
-{
-  return new Adaptor2dCurve2d( this );
-}
-
-//================================================================================
-/*!
- * \brief Creates a fully functional Adaptor_Curve
- */
-//================================================================================
-
-BRepAdaptor_CompCurve* StdMeshers_FaceSide::GetCurve3d() const
-{
-  if ( myEdge.empty() )
-    return 0;
-
-//   if ( myEdge.size() == 1 )
-//     return new BRepAdaptor_Curve( myEdge[0] );
-
-  TopoDS_Wire aWire;
-  BRep_Builder aBuilder;
-  aBuilder.MakeWire(aWire);
-  for ( int i=0; i<myEdge.size(); ++i )
-    aBuilder.Add( aWire, myEdge[i] );
-  return new BRepAdaptor_CompCurve( aWire );
-}
-
-
-//================================================================================
-/*!
- * \brief Return 2D point by normalized parameter
-  * \param U - normalized parameter value
-  * \retval gp_Pnt2d - point
- */
-//================================================================================
-
-gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const
-{
-  if ( !myC2d[0].IsNull() ) {
-    int i = EdgeIndex( U );
-    double prevU = i ? myNormPar[ i-1 ] : 0;
-    double r = ( U - prevU )/ ( myNormPar[ i ] - prevU );
-
-    double par = myFirst[i] * ( 1 - r ) + myLast[i] * r;
-    
-    // check parametrization of curve
-    if( !myIsUniform[i] )
-    {
-      double aLen3dU = r * myEdgeLength[i] * ( myFirst[i]>myLast[i] ? -1. : 1.);
-      GCPnts_AbscissaPoint AbPnt
-        ( const_cast<GeomAdaptor_Curve&>( myC3dAdaptor[i]), aLen3dU, myFirst[i] );
-      if( AbPnt.IsDone() ) {
-        par = AbPnt.Parameter();
-      }
-    }
-    return myC2d[ i ]->Value(par);
-
-  }
-  return myDefaultPnt2d;
-}
-
-//================================================================================
-/*!
- * \brief Return wires of a face as StdMeshers_FaceSide's
- */
-//================================================================================
-
-TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace,
-                                              SMESH_Mesh &       theMesh,
-                                              const bool         theIgnoreMediumNodes,
-                                              TError &           theError)
-{
-  TopoDS_Vertex V1;
-  list< TopoDS_Edge > edges;
-  list< int > nbEdgesInWires;
-  int nbWires = SMESH_Block::GetOrderedEdges (theFace, V1, edges, nbEdgesInWires);
-
-  // split list of all edges into separate wires
-  TSideVector wires( nbWires );
-  list< int >::iterator nbE = nbEdgesInWires.begin();
-  list< TopoDS_Edge >::iterator from, to;
-  from = to = edges.begin();
-  for ( int iW = 0; iW < nbWires; ++iW )
-  {
-    std::advance( to, *nbE++ );
-    if ( *nbE == 0 ) // Issue 0020676
-    {
-      --nbWires;
-      --iW;
-      wires.resize( nbWires );
-      continue;
-    }
-    list< TopoDS_Edge > wireEdges( from, to );
-    // assure that there is a node on the first vertex
-    // as StdMeshers_FaceSide::GetUVPtStruct() requires
-    if ( wireEdges.front().Orientation() != TopAbs_INTERNAL ) // Issue 0020676
-      while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true),
-                                       theMesh.GetMeshDS()))
-      {
-        wireEdges.splice(wireEdges.end(), wireEdges,
-                         wireEdges.begin(), ++wireEdges.begin());
-        if ( from->IsSame( wireEdges.front() )) {
-          theError = TError
-            ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices"));
-          return TSideVector(0);
-        }
-      }
-    const bool isForward = true;
-    StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh,
-                                                         isForward, theIgnoreMediumNodes);
-    wires[ iW ] = StdMeshers_FaceSidePtr( wire );
-    from = to;
-  }
-  return wires;
-}
-
-//================================================================================
-/*!
- * \brief Return 1st vertex of the i-the edge
- */
-//================================================================================
-
-TopoDS_Vertex StdMeshers_FaceSide::FirstVertex(int i) const
-{
-  TopoDS_Vertex v;
-  if ( i < NbEdges() )
-  {
-    v = myEdge[i].Orientation() <= TopAbs_REVERSED ? // FORWARD || REVERSED
-        TopExp::FirstVertex( myEdge[i], 1 )        :
-        TopoDS::Vertex( TopoDS_Iterator( myEdge[i] ).Value() );
-  }
-  return v;
-}
-
-//================================================================================
-/*!
- * \brief Return last vertex of the i-the edge
- */
-//================================================================================
-
-TopoDS_Vertex StdMeshers_FaceSide::LastVertex(int i) const
-{
-  TopoDS_Vertex v;
-  if ( i < NbEdges() )
-  {
-    const TopoDS_Edge& edge = i<0 ? myEdge[ NbEdges() + i ] : myEdge[i];
-    if ( edge.Orientation() <= TopAbs_REVERSED ) // FORWARD || REVERSED
-      v = TopExp::LastVertex( edge, 1 );
-    else
-      for ( TopoDS_Iterator vIt( edge ); vIt.More(); vIt.Next() )
-        v = TopoDS::Vertex( vIt.Value() );
-  }
-  return v;
-}
-
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE\r
+//\r
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,\r
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS\r
+//\r
+//  This library is free software; you can redistribute it and/or\r
+//  modify it under the terms of the GNU Lesser General Public\r
+//  License as published by the Free Software Foundation; either\r
+//  version 2.1 of the License.\r
+//\r
+//  This library is distributed in the hope that it will be useful,\r
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+//  Lesser General Public License for more details.\r
+//\r
+//  You should have received a copy of the GNU Lesser General Public\r
+//  License along with this library; if not, write to the Free Software\r
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\r
+//\r
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com\r
+//\r
+\r
+//  SMESH SMESH : implementaion of SMESH idl descriptions\r
+// File      : StdMeshers_FaceSide.hxx\r
+// Created   : Wed Jan 31 18:41:25 2007\r
+// Author    : Edward AGAPOV (eap)\r
+// Module    : SMESH\r
+//\r
+#include "StdMeshers_FaceSide.hxx"\r
+\r
+#include "SMDS_EdgePosition.hxx"\r
+#include "SMDS_MeshNode.hxx"\r
+#include "SMESHDS_Mesh.hxx"\r
+#include "SMESHDS_SubMesh.hxx"\r
+#include "SMESH_Algo.hxx"\r
+#include "SMESH_Mesh.hxx"\r
+#include "SMESH_MesherHelper.hxx"\r
+#include "SMESH_ComputeError.hxx"\r
+#include "SMESH_Block.hxx"\r
+\r
+#include <Adaptor2d_Curve2d.hxx>\r
+#include <BRepAdaptor_CompCurve.hxx>\r
+#include <BRepAdaptor_Curve.hxx>\r
+#include <BRep_Builder.hxx>\r
+#include <BRep_Tool.hxx>\r
+#include <TopExp.hxx>\r
+#include <TopExp_Explorer.hxx>\r
+#include <TopoDS.hxx>\r
+#include <TopoDS_Face.hxx>\r
+#include <TopoDS_Vertex.hxx>\r
+#include <TopoDS_Wire.hxx>\r
+\r
+#include <GCPnts_AbscissaPoint.hxx>\r
+#include <Geom2dAdaptor_Curve.hxx>\r
+\r
+#include <map>\r
+\r
+#include "utilities.h"\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Constructor of a side of one edge\r
+  * \param theFace - the face\r
+  * \param theEdge - the edge\r
+ */\r
+//================================================================================\r
+\r
+StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,\r
+                                         const TopoDS_Edge& theEdge,\r
+                                         SMESH_Mesh*        theMesh,\r
+                                         const bool         theIsForward,\r
+                                         const bool         theIgnoreMediumNodes)\r
+{\r
+  list<TopoDS_Edge> edges(1,theEdge);\r
+  *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward, theIgnoreMediumNodes );\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Constructor of a side of several edges\r
+  * \param theFace - the face\r
+  * \param theEdge - the edge\r
+ */\r
+//================================================================================\r
+\r
+StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,\r
+                                         list<TopoDS_Edge>& theEdges,\r
+                                         SMESH_Mesh*        theMesh,\r
+                                         const bool         theIsForward,\r
+                                         const bool         theIgnoreMediumNodes)\r
+{\r
+  int nbEdges = theEdges.size();\r
+  myEdge.resize( nbEdges );\r
+  myC2d.resize( nbEdges );\r
+  myC3dAdaptor.resize( nbEdges );\r
+  myFirst.resize( nbEdges );\r
+  myLast.resize( nbEdges );\r
+  myNormPar.resize( nbEdges );\r
+  myEdgeLength.resize( nbEdges );\r
+  myIsUniform.resize( nbEdges, true );\r
+  myLength = 0;\r
+  myNbPonits = myNbSegments = 0;\r
+  myMesh = theMesh;\r
+  myMissingVertexNodes = false;\r
+  myIgnoreMediumNodes = theIgnoreMediumNodes;\r
+  myDefaultPnt2d = gp_Pnt2d( 1e+100, 1e+100 );\r
+  if ( nbEdges == 0 ) return;\r
+\r
+  SMESHDS_Mesh* meshDS = theMesh->GetMeshDS();\r
+\r
+  int nbDegen = 0;\r
+  list<TopoDS_Edge>::iterator edge = theEdges.begin();\r
+  TopoDS_Iterator vExp;\r
+  for ( int index = 0; edge != theEdges.end(); ++index, ++edge )\r
+  {\r
+    int i = theIsForward ? index : nbEdges - index - 1;\r
+    myEdgeLength[i] = SMESH_Algo::EdgeLength( *edge );\r
+    if ( myEdgeLength[i] < DBL_MIN ) nbDegen++;\r
+    myLength += myEdgeLength[i];\r
+    myEdge[i] = *edge;\r
+    if ( !theIsForward ) myEdge[i].Reverse();\r
+\r
+    if ( theFace.IsNull() )\r
+      BRep_Tool::Range( *edge, myFirst[i], myLast[i] );\r
+    else\r
+      myC2d[i] = BRep_Tool::CurveOnSurface( *edge, theFace, myFirst[i], myLast[i] );\r
+    if ( myEdge[i].Orientation() == TopAbs_REVERSED )\r
+      std::swap( myFirst[i], myLast[i] );\r
+\r
+    if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( *edge )) {\r
+      int nbN = sm->NbNodes();\r
+      if ( theIgnoreMediumNodes ) {\r
+        SMDS_ElemIteratorPtr elemIt = sm->GetElements();\r
+        if ( elemIt->more() && elemIt->next()->IsQuadratic() )\r
+          nbN -= sm->NbElements();\r
+      }\r
+      myNbPonits += nbN;\r
+      myNbSegments += sm->NbElements();\r
+    }\r
+    // TopExp::FirstVertex() and TopExp::LastVertex() return NULL from INTERNAL edge\r
+    vExp.Initialize( *edge );\r
+    if ( vExp.Value().Orientation() == TopAbs_REVERSED ) vExp.Next();\r
+    if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))\r
+      myNbPonits += 1; // for the first end\r
+    else\r
+      myMissingVertexNodes = true;\r
+\r
+    // check if edge has non-uniform parametrization (issue 0020705)\r
+    if ( !myC2d[i].IsNull() && myEdgeLength[i] > DBL_MIN)\r
+    {\r
+      Geom2dAdaptor_Curve A2dC( myC2d[i] );\r
+      double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2., p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;\r
+      double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 );\r
+      double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 );\r
+      //cout<<"len = "<<len<<"  d2 = "<<d2<<"  fabs(2*d2/len-1.0) = "<<fabs(2*d2/len-1.0)<<endl;\r
+      myIsUniform[i] = !( fabs(2*d2/myEdgeLength[i]-1.0) > 0.01 || fabs(2*d4/d2-1.0) > 0.01 );\r
+      if ( !myIsUniform[i] )\r
+      {\r
+        double fp,lp;\r
+        TopLoc_Location L;\r
+        Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],L,fp,lp);\r
+        myC3dAdaptor[i].Load( C3d, fp,lp );\r
+      }\r
+    }\r
+  }\r
+  vExp.Initialize( theEdges.back() );\r
+  if ( vExp.Value().Orientation() != TopAbs_REVERSED ) vExp.Next();\r
+  if ( vExp.More() )\r
+  {\r
+    if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))\r
+      myNbPonits++; // for the last end\r
+    else\r
+      myMissingVertexNodes = true;\r
+  }\r
+  if ( nbEdges > 1 && myLength > DBL_MIN ) {\r
+    const double degenNormLen = 1.e-5;\r
+    double totLength = myLength;\r
+    if ( nbDegen )\r
+      totLength += myLength * degenNormLen * nbDegen;\r
+    double prevNormPar = 0;\r
+    for ( int i = 0; i < nbEdges; ++i ) {\r
+      if ( myEdgeLength[ i ] < DBL_MIN )\r
+        myEdgeLength[ i ] = myLength * degenNormLen;\r
+      myNormPar[ i ] = prevNormPar + myEdgeLength[i]/totLength;\r
+      prevNormPar = myNormPar[ i ];\r
+    }\r
+  }\r
+  myNormPar[nbEdges-1] = 1.;\r
+  //dump();\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Constructor of a side for vertex using data from other FaceSide\r
+  * \param theVertex - the vertex\r
+  * \param theSide - the side\r
+ */\r
+//================================================================================\r
+\r
+StdMeshers_FaceSide::StdMeshers_FaceSide(const SMDS_MeshNode* theNode,\r
+                                         const gp_Pnt2d thePnt2d,\r
+                                         const StdMeshers_FaceSide* theSide)\r
+{\r
+  myC2d.resize(1);\r
+  myLength = 0;\r
+  myMesh = theSide->GetMesh();\r
+  myDefaultPnt2d = thePnt2d;\r
+\r
+  myPoints = theSide->GetUVPtStruct();\r
+  myNbPonits = myNbSegments = myPoints.size();\r
+  std::vector<uvPtStruct>::iterator it = myPoints.begin();\r
+  for(; it!=myPoints.end(); it++) {\r
+    (*it).u = thePnt2d.X();\r
+    (*it).v = thePnt2d.Y();\r
+    (*it).y = 0.0;\r
+    (*it).node = theNode;\r
+  }\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Return info on nodes on the side\r
+  * \retval UVPtStruct* - array of data structures\r
+ */\r
+//================================================================================\r
+\r
+const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,\r
+                                                             double constValue) const\r
+{\r
+  if ( myPoints.empty() ) {\r
+\r
+    if ( NbEdges() == 0 ) return myPoints;\r
+\r
+    SMESHDS_Mesh* meshDS = myMesh->GetMeshDS();\r
+    SMESH_MesherHelper helper(*myMesh);\r
+    bool paramOK;\r
+\r
+    // sort nodes of all edges putting them into a map\r
+\r
+    map< double, const SMDS_MeshNode*> u2node;\r
+    //int nbOnDegen = 0;\r
+    for ( int i = 0; i < myEdge.size(); ++i )\r
+    {\r
+      // Put 1st vertex node of a current edge\r
+      TopoDS_Vertex VV[2]; // TopExp::FirstVertex() returns NULL for INTERNAL edge\r
+      for ( TopoDS_Iterator vIt(myEdge[i]); vIt.More(); vIt.Next() )\r
+        VV[ VV[0].IsNull() ? 0 : 1 ] = TopoDS::Vertex(vIt.Value());\r
+      if ( VV[0].Orientation() == TopAbs_REVERSED ) std::swap ( VV[0], VV[1] );\r
+      const SMDS_MeshNode* node = SMESH_Algo::VertexNode( VV[0], meshDS );\r
+      double prevNormPar = ( i == 0 ? 0 : myNormPar[ i-1 ]); // normalized param\r
+      if ( node ) { // internal nodes may be missing\r
+        u2node.insert( make_pair( prevNormPar, node ));\r
+      }\r
+      else if ( i == 0 ) {\r
+        MESSAGE(" NO NODE on VERTEX" );\r
+        return myPoints;\r
+      }\r
+\r
+      // Put internal nodes\r
+      SMESHDS_SubMesh* sm = meshDS->MeshElements( myEdge[i] );\r
+      if ( !sm ) continue;\r
+      vector< pair< double, const SMDS_MeshNode*> > u2nodeVec;\r
+      u2nodeVec.reserve( sm->NbNodes() );\r
+      SMDS_NodeIteratorPtr nItr = sm->GetNodes();\r
+      double paramSize = myLast[i] - myFirst[i];\r
+      double r = myNormPar[i] - prevNormPar;\r
+      if ( !myIsUniform[i] )\r
+        while ( nItr->more() )\r
+        {\r
+          const SMDS_MeshNode* node = nItr->next();\r
+          if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))\r
+            continue;\r
+          double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );\r
+          double aLenU = GCPnts_AbscissaPoint::Length\r
+            ( const_cast<GeomAdaptor_Curve&>( myC3dAdaptor[i]), myFirst[i], u );\r
+          if ( myEdgeLength[i] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6"\r
+          {\r
+            u2nodeVec.clear();\r
+            break;\r
+          }\r
+          double normPar = prevNormPar + r*aLenU/myEdgeLength[i];\r
+          u2nodeVec.push_back( make_pair( normPar, node ));\r
+        }\r
+      nItr = sm->GetNodes();\r
+      if ( u2nodeVec.empty() )\r
+        while ( nItr->more() )\r
+        {\r
+          const SMDS_MeshNode* node = nItr->next();\r
+          if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))\r
+            continue;\r
+          double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );\r
+\r
+          // paramSize is signed so orientation is taken into account\r
+          double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize;\r
+          u2nodeVec.push_back( make_pair( normPar, node ));\r
+        }\r
+      u2node.insert( u2nodeVec.begin(), u2nodeVec.end() );\r
+\r
+      // Put 2nd vertex node for a last edge\r
+      if ( i+1 == myEdge.size() ) {\r
+        node = SMESH_Algo::VertexNode( VV[1], meshDS );\r
+        if ( !node ) {\r
+          MESSAGE(" NO NODE on VERTEX" );\r
+          return myPoints;\r
+        }\r
+        u2node.insert( make_pair( 1., node ));\r
+      }\r
+    }\r
+    if ( u2node.size() != myNbPonits ) {\r
+      MESSAGE("Wrong node parameters on edges, u2node.size():"\r
+              <<u2node.size()<<" !=  myNbPonits:"<<myNbPonits);\r
+      return myPoints;\r
+    }\r
+\r
+    // fill array of UVPtStruct\r
+\r
+    vector<uvPtStruct>* points = const_cast<vector<uvPtStruct>*>( &myPoints );\r
+    points->resize( myNbPonits );\r
+\r
+    int EdgeIndex = 0;\r
+    double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ];\r
+    map< double, const SMDS_MeshNode*>::iterator u_node = u2node.begin();\r
+    for (int i = 0 ; u_node != u2node.end(); ++u_node, ++i ) {\r
+      UVPtStruct & uvPt = (*points)[i];\r
+      uvPt.node = u_node->second;\r
+      uvPt.x = uvPt.y = uvPt.normParam = u_node->first;\r
+      if ( isXConst ) uvPt.x = constValue;\r
+      else            uvPt.y = constValue;\r
+      if ( myNormPar[ EdgeIndex ] < uvPt.normParam ) {\r
+        prevNormPar = myNormPar[ EdgeIndex ];\r
+        ++EdgeIndex;\r
+#ifdef _DEBUG_\r
+        if ( EdgeIndex >= myEdge.size() ) {\r
+          dump("DEBUG");\r
+          MESSAGE ( "WRONg EdgeIndex " << 1+EdgeIndex\r
+                    << " myNormPar.size()="<<myNormPar.size()\r
+                    << " myNormPar["<< EdgeIndex<<"]="<< myNormPar[ EdgeIndex ]\r
+                    << " uvPt.normParam="<<uvPt.normParam );\r
+        }\r
+#endif\r
+        paramSize = myNormPar[ EdgeIndex ] - prevNormPar;\r
+      }\r
+      const SMDS_EdgePosition* epos =\r
+        dynamic_cast<const SMDS_EdgePosition*>(uvPt.node->GetPosition().get());\r
+      if ( epos ) {\r
+        uvPt.param = epos->GetUParameter();\r
+      }\r
+      else {\r
+        double r = ( uvPt.normParam - prevNormPar )/ paramSize;\r
+//         uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r;\r
+        uvPt.param = ( r > 0.5 ? myLast[EdgeIndex] : myFirst[EdgeIndex] );\r
+      }\r
+      if ( !myC2d[ EdgeIndex ].IsNull() ) {\r
+        gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param );\r
+        uvPt.u = p.X();\r
+        uvPt.v = p.Y();\r
+      }\r
+      else {\r
+        uvPt.u = uvPt.v = 1e+100;\r
+      }\r
+    }\r
+  }\r
+  return myPoints;\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Falsificate info on nodes\r
+  * \param nbSeg - nb of segments on the side\r
+  * \retval UVPtStruct* - array of data structures\r
+ */\r
+//================================================================================\r
+\r
+const vector<UVPtStruct>& StdMeshers_FaceSide::SimulateUVPtStruct(int    nbSeg,\r
+                                                                  bool   isXConst,\r
+                                                                  double constValue) const\r
+{\r
+  if ( myFalsePoints.empty() ) {\r
+\r
+    if ( NbEdges() == 0 ) return myFalsePoints;\r
+\r
+    vector<uvPtStruct>* points = const_cast<vector<uvPtStruct>*>( &myFalsePoints );\r
+    points->resize( nbSeg+1 );\r
+\r
+    int EdgeIndex = 0;\r
+    double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ];\r
+    for (int i = 0 ; i < myFalsePoints.size(); ++i ) {\r
+      double normPar = double(i) / double(nbSeg);\r
+      UVPtStruct & uvPt = (*points)[i];\r
+      uvPt.node = 0;\r
+      uvPt.x = uvPt.y = uvPt.param = uvPt.normParam = normPar;\r
+      if ( isXConst ) uvPt.x = constValue;\r
+      else            uvPt.y = constValue;\r
+      if ( myNormPar[ EdgeIndex ] < normPar ) {\r
+        prevNormPar = myNormPar[ EdgeIndex ];\r
+        ++EdgeIndex;\r
+        paramSize = myNormPar[ EdgeIndex ] - prevNormPar;\r
+      }\r
+      double r = ( normPar - prevNormPar )/ paramSize;\r
+      uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r;\r
+      if ( !myC2d[ EdgeIndex ].IsNull() ) {\r
+        gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param );\r
+        uvPt.u = p.X();\r
+        uvPt.v = p.Y();\r
+      }\r
+      else {\r
+        uvPt.u = uvPt.v = 1e+100;\r
+      }\r
+    }\r
+  }\r
+  return myFalsePoints;\r
+}\r
+// gp_Pnt StdMeshers_FaceSide::Value(double U) const\r
+// {\r
+// }\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief reverse order of vector elements\r
+  * \param vec - vector to reverse\r
+ */\r
+//================================================================================\r
+\r
+template <typename T > void reverse(vector<T> & vec)\r
+{\r
+  for ( int f=0, r=vec.size()-1; f < r; ++f, --r )\r
+    std::swap( vec[f], vec[r] );\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Change orientation of side geometry\r
+ */\r
+//================================================================================\r
+\r
+void StdMeshers_FaceSide::Reverse()\r
+{\r
+  int nbEdges = myEdge.size();\r
+  for ( int i = nbEdges-1; i >= 0; --i ) {\r
+    std::swap( myFirst[i], myLast[i] );\r
+    myEdge[i].Reverse();\r
+    if ( i > 0 ) // at the first loop 1. is overwritten\r
+      myNormPar[i] = 1 - myNormPar[i-1];\r
+  }\r
+  if ( nbEdges > 1 ) {\r
+    reverse( myEdge );\r
+    reverse( myC2d );\r
+    reverse( myC3dAdaptor );\r
+    reverse( myFirst );\r
+    reverse( myLast );\r
+    reverse( myNormPar );\r
+    reverse( myEdgeLength );\r
+    reverse( myIsUniform );\r
+  }\r
+  myNormPar[nbEdges-1]=1.;\r
+  myPoints.clear();\r
+  myFalsePoints.clear();\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Show side features\r
+ */\r
+//================================================================================\r
+\r
+void StdMeshers_FaceSide::dump(const char* msg) const\r
+{\r
+#ifdef _DEBUG_\r
+  if (msg) MESSAGE ( std::endl << msg );\r
+  MESSAGE_BEGIN ("NB EDGES: "<< myEdge.size() );\r
+  MESSAGE_ADD ( "nbPoints: "<<myNbPonits<<" vecSize: " << myPoints.size()<<" "<<myFalsePoints.size() );\r
+  for ( int i=0; i<myEdge.size(); ++i)\r
+  {\r
+    MESSAGE_ADD ( "\t"<<i+1 );\r
+    MESSAGE_ADD ( "\tEDGE: " );\r
+    if (myEdge[i].IsNull()) {\r
+      MESSAGE_ADD ( "NULL" );\r
+    }\r
+    else {\r
+      TopAbs::Print(myEdge[i].Orientation(),cout)<<" "<<myEdge[i].TShape().operator->()<<endl;\r
+      MESSAGE_ADD ( "\tV1: " << TopExp::FirstVertex( myEdge[i], 1).TShape().operator->()\r
+                 << "  V2: " << TopExp::LastVertex( myEdge[i], 1).TShape().operator->() );\r
+    }\r
+    MESSAGE_ADD ( "\tC2d: ");\r
+    \r
+    if (myC2d[i].IsNull()) {\r
+      MESSAGE_ADD ( "NULL" );\r
+    }\r
+    else {\r
+      MESSAGE_ADD ( myC2d[i].operator->() );\r
+    }\r
+      \r
+    MESSAGE_ADD ( "\tF: "<<myFirst[i]<< " L: "<< myLast[i] );\r
+    MESSAGE_END ( "\tnormPar: "<<myNormPar[i]<<endl );\r
+  }\r
+#endif\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Creates a Adaptor2d_Curve2d to be used in SMESH_Block\r
+  * \retval Adaptor2d_Curve2d* - \r
+ */\r
+//================================================================================\r
+\r
+struct Adaptor2dCurve2d : public Adaptor2d_Curve2d\r
+{\r
+  const StdMeshers_FaceSide* mySide;\r
+  Adaptor2dCurve2d(const StdMeshers_FaceSide* faceSide):mySide(faceSide) {}\r
+  gp_Pnt2d Value(const Standard_Real U) const { return mySide->Value2d( U ); }\r
+  Standard_Real FirstParameter() const { return 0; }\r
+  Standard_Real LastParameter() const { return 1; }\r
+};\r
+\r
+Adaptor2d_Curve2d* StdMeshers_FaceSide::GetCurve2d() const\r
+{\r
+  return new Adaptor2dCurve2d( this );\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Creates a fully functional Adaptor_Curve\r
+ */\r
+//================================================================================\r
+\r
+BRepAdaptor_CompCurve* StdMeshers_FaceSide::GetCurve3d() const\r
+{\r
+  if ( myEdge.empty() )\r
+    return 0;\r
+\r
+//   if ( myEdge.size() == 1 )\r
+//     return new BRepAdaptor_Curve( myEdge[0] );\r
+\r
+  TopoDS_Wire aWire;\r
+  BRep_Builder aBuilder;\r
+  aBuilder.MakeWire(aWire);\r
+  for ( int i=0; i<myEdge.size(); ++i )\r
+    aBuilder.Add( aWire, myEdge[i] );\r
+  return new BRepAdaptor_CompCurve( aWire );\r
+}\r
+\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Return 2D point by normalized parameter\r
+  * \param U - normalized parameter value\r
+  * \retval gp_Pnt2d - point\r
+ */\r
+//================================================================================\r
+\r
+gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const\r
+{\r
+  if ( !myC2d[0].IsNull() ) {\r
+    int i = EdgeIndex( U );\r
+    double prevU = i ? myNormPar[ i-1 ] : 0;\r
+    double r = ( U - prevU )/ ( myNormPar[ i ] - prevU );\r
+\r
+    double par = myFirst[i] * ( 1 - r ) + myLast[i] * r;\r
+    \r
+    // check parametrization of curve\r
+    if( !myIsUniform[i] )\r
+    {\r
+      double aLen3dU = r * myEdgeLength[i] * ( myFirst[i]>myLast[i] ? -1. : 1.);\r
+      GCPnts_AbscissaPoint AbPnt\r
+        ( const_cast<GeomAdaptor_Curve&>( myC3dAdaptor[i]), aLen3dU, myFirst[i] );\r
+      if( AbPnt.IsDone() ) {\r
+        par = AbPnt.Parameter();\r
+      }\r
+    }\r
+    return myC2d[ i ]->Value(par);\r
+\r
+  }\r
+  return myDefaultPnt2d;\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Return wires of a face as StdMeshers_FaceSide's\r
+ */\r
+//================================================================================\r
+\r
+TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace,\r
+                                              SMESH_Mesh &       theMesh,\r
+                                              const bool         theIgnoreMediumNodes,\r
+                                              TError &           theError)\r
+{\r
+  TopoDS_Vertex V1;\r
+  list< TopoDS_Edge > edges;\r
+  list< int > nbEdgesInWires;\r
+  int nbWires = SMESH_Block::GetOrderedEdges (theFace, V1, edges, nbEdgesInWires);\r
+\r
+  // split list of all edges into separate wires\r
+  TSideVector wires( nbWires );\r
+  list< int >::iterator nbE = nbEdgesInWires.begin();\r
+  list< TopoDS_Edge >::iterator from, to;\r
+  from = to = edges.begin();\r
+  for ( int iW = 0; iW < nbWires; ++iW, ++nbE )\r
+  {\r
+    std::advance( to, *nbE );\r
+    if ( *nbE == 0 ) // Issue 0020676\r
+    {\r
+      --nbWires;\r
+      --iW;\r
+      wires.resize( nbWires );\r
+      continue;\r
+    }\r
+    list< TopoDS_Edge > wireEdges( from, to );\r
+    // assure that there is a node on the first vertex\r
+    // as StdMeshers_FaceSide::GetUVPtStruct() requires\r
+    if ( wireEdges.front().Orientation() != TopAbs_INTERNAL ) // Issue 0020676\r
+      while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true),\r
+                                       theMesh.GetMeshDS()))\r
+      {\r
+        wireEdges.splice(wireEdges.end(), wireEdges,\r
+                         wireEdges.begin(), ++wireEdges.begin());\r
+        if ( from->IsSame( wireEdges.front() )) {\r
+          theError = TError\r
+            ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices"));\r
+          return TSideVector(0);\r
+        }\r
+      }\r
+    const bool isForward = true;\r
+    StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh,\r
+                                                         isForward, theIgnoreMediumNodes);\r
+    wires[ iW ] = StdMeshers_FaceSidePtr( wire );\r
+    from = to;\r
+  }\r
+  return wires;\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Return 1st vertex of the i-the edge\r
+ */\r
+//================================================================================\r
+\r
+TopoDS_Vertex StdMeshers_FaceSide::FirstVertex(int i) const\r
+{\r
+  TopoDS_Vertex v;\r
+  if ( i < NbEdges() )\r
+  {\r
+    v = myEdge[i].Orientation() <= TopAbs_REVERSED ? // FORWARD || REVERSED\r
+        TopExp::FirstVertex( myEdge[i], 1 )        :\r
+        TopoDS::Vertex( TopoDS_Iterator( myEdge[i] ).Value() );\r
+  }\r
+  return v;\r
+}\r
+\r
+//================================================================================\r
+/*!\r
+ * \brief Return last vertex of the i-the edge\r
+ */\r
+//================================================================================\r
+\r
+TopoDS_Vertex StdMeshers_FaceSide::LastVertex(int i) const\r
+{\r
+  TopoDS_Vertex v;\r
+  if ( i < NbEdges() )\r
+  {\r
+    const TopoDS_Edge& edge = i<0 ? myEdge[ NbEdges() + i ] : myEdge[i];\r
+    if ( edge.Orientation() <= TopAbs_REVERSED ) // FORWARD || REVERSED\r
+      v = TopExp::LastVertex( edge, 1 );\r
+    else\r
+      for ( TopoDS_Iterator vIt( edge ); vIt.More(); vIt.Next() )\r
+        v = TopoDS::Vertex( vIt.Value() );\r
+  }\r
+  return v;\r
+}\r
+\r