Back to index

salome-smesh  6.5.0
StdMeshers_FaceSide.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File      : StdMeshers_FaceSide.hxx
00024 // Created   : Wed Jan 31 18:41:25 2007
00025 // Author    : Edward AGAPOV (eap)
00026 // Module    : SMESH
00027 //
00028 #include "StdMeshers_FaceSide.hxx"
00029 
00030 #include "SMDS_EdgePosition.hxx"
00031 #include "SMDS_MeshNode.hxx"
00032 #include "SMESHDS_Mesh.hxx"
00033 #include "SMESHDS_SubMesh.hxx"
00034 #include "SMESH_Algo.hxx"
00035 #include "SMESH_Mesh.hxx"
00036 #include "SMESH_MesherHelper.hxx"
00037 #include "SMESH_ComputeError.hxx"
00038 #include "SMESH_Block.hxx"
00039 
00040 #include <Adaptor2d_Curve2d.hxx>
00041 #include <BRepAdaptor_CompCurve.hxx>
00042 #include <BRep_Builder.hxx>
00043 #include <BRep_Tool.hxx>
00044 #include <GCPnts_AbscissaPoint.hxx>
00045 #include <Geom2dAdaptor_Curve.hxx>
00046 #include <TopExp.hxx>
00047 #include <TopExp_Explorer.hxx>
00048 #include <TopoDS.hxx>
00049 #include <TopoDS_Face.hxx>
00050 #include <TopoDS_Vertex.hxx>
00051 #include <TopoDS_Wire.hxx>
00052 
00053 #include <map>
00054 
00055 #include "utilities.h"
00056 
00057 //================================================================================
00063 //================================================================================
00064 
00065 StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
00066                                          const TopoDS_Edge& theEdge,
00067                                          SMESH_Mesh*        theMesh,
00068                                          const bool         theIsForward,
00069                                          const bool         theIgnoreMediumNodes)
00070 {
00071   list<TopoDS_Edge> edges(1,theEdge);
00072   *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward, theIgnoreMediumNodes );
00073 }
00074 
00075 //================================================================================
00081 //================================================================================
00082 
00083 StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
00084                                          list<TopoDS_Edge>& theEdges,
00085                                          SMESH_Mesh*        theMesh,
00086                                          const bool         theIsForward,
00087                                          const bool         theIgnoreMediumNodes)
00088 {
00089   int nbEdges = theEdges.size();
00090   myEdge.resize      ( nbEdges );
00091   myEdgeID.resize    ( nbEdges );
00092   myC2d.resize       ( nbEdges );
00093   myC3dAdaptor.resize( nbEdges );
00094   myFirst.resize     ( nbEdges );
00095   myLast.resize      ( nbEdges );
00096   myNormPar.resize   ( nbEdges );
00097   myEdgeLength.resize( nbEdges );
00098   myIsUniform.resize ( nbEdges, true );
00099   myLength             = 0;
00100   myNbPonits           = myNbSegments = 0;
00101   myMesh               = theMesh;
00102   myMissingVertexNodes = false;
00103   myIgnoreMediumNodes  = theIgnoreMediumNodes;
00104   myDefaultPnt2d       = gp_Pnt2d( 1e+100, 1e+100 );
00105   if ( nbEdges == 0 ) return;
00106 
00107   SMESHDS_Mesh* meshDS = theMesh->GetMeshDS();
00108 
00109   int nbDegen = 0;
00110   list<TopoDS_Edge>::iterator edge = theEdges.begin();
00111   TopoDS_Iterator vExp;
00112   for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
00113   {
00114     int i = theIsForward ? index : nbEdges-index-1;
00115     myEdgeLength[i] = SMESH_Algo::EdgeLength( *edge );
00116     if ( myEdgeLength[i] < DBL_MIN ) nbDegen++;
00117     myLength += myEdgeLength[i];
00118     myEdge[i] = *edge;
00119     myEdgeID[i] = meshDS->ShapeToIndex( *edge );
00120     if ( !theIsForward ) myEdge[i].Reverse();
00121 
00122     if ( theFace.IsNull() )
00123       BRep_Tool::Range( *edge, myFirst[i], myLast[i] );
00124     else
00125       myC2d[i] = BRep_Tool::CurveOnSurface( *edge, theFace, myFirst[i], myLast[i] );
00126     if ( myEdge[i].Orientation() == TopAbs_REVERSED )
00127       std::swap( myFirst[i], myLast[i] );
00128 
00129     if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( *edge )) {
00130       int nbN = sm->NbNodes();
00131       if ( theIgnoreMediumNodes ) {
00132         SMDS_ElemIteratorPtr elemIt = sm->GetElements();
00133         if ( elemIt->more() && elemIt->next()->IsQuadratic() )
00134           nbN -= sm->NbElements();
00135       }
00136       myNbPonits += nbN;
00137       myNbSegments += sm->NbElements();
00138     }
00139     // TopExp::FirstVertex() and TopExp::LastVertex() return NULL from INTERNAL edge
00140     vExp.Initialize( *edge );
00141     if ( vExp.Value().Orientation() == TopAbs_REVERSED ) vExp.Next();
00142     if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))
00143       myNbPonits += 1; // for the first end
00144     else
00145       myMissingVertexNodes = true;
00146 
00147     // check if edge has non-uniform parametrization (issue 0020705)
00148     if ( !myC2d[i].IsNull() && myEdgeLength[i] > DBL_MIN)
00149     {
00150       Geom2dAdaptor_Curve A2dC( myC2d[i],
00151                                 std::min( myFirst[i], myLast[i] ),
00152                                 std::max( myFirst[i], myLast[i] ));
00153       double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2., p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.;
00154       double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 );
00155       double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 );
00156       //cout<<"len = "<<len<<"  d2 = "<<d2<<"  fabs(2*d2/len-1.0) = "<<fabs(2*d2/len-1.0)<<endl;
00157       myIsUniform[i] = !( fabs(2*d2/myEdgeLength[i]-1.0) > 0.01 || fabs(2*d4/d2-1.0) > 0.01 );
00158       if ( !myIsUniform[i] )
00159       {
00160         double fp,lp;
00161         TopLoc_Location L;
00162         Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],L,fp,lp);
00163         myC3dAdaptor[i].Load( C3d, fp,lp );
00164       }
00165     }
00166   }
00167   vExp.Initialize( theEdges.back() );
00168   if ( vExp.Value().Orientation() != TopAbs_REVERSED ) vExp.Next();
00169   if ( vExp.More() )
00170   {
00171     if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS ))
00172       myNbPonits++; // for the last end
00173     else
00174       myMissingVertexNodes = true;
00175   }
00176   if ( nbEdges > 1 && myLength > DBL_MIN ) {
00177     const double degenNormLen = 1.e-5;
00178     double totLength = myLength;
00179     if ( nbDegen )
00180       totLength += myLength * degenNormLen * nbDegen;
00181     double prevNormPar = 0;
00182     for ( int i = 0; i < nbEdges; ++i ) {
00183       if ( myEdgeLength[ i ] < DBL_MIN )
00184         myEdgeLength[ i ] = myLength * degenNormLen;
00185       myNormPar[ i ] = prevNormPar + myEdgeLength[i]/totLength;
00186       prevNormPar = myNormPar[ i ];
00187     }
00188   }
00189   myNormPar[nbEdges-1] = 1.;
00190   //dump();
00191 }
00192 
00193 //================================================================================
00199 //================================================================================
00200 
00201 StdMeshers_FaceSide::StdMeshers_FaceSide(const SMDS_MeshNode* theNode,
00202                                          const gp_Pnt2d thePnt2d,
00203                                          const StdMeshers_FaceSide* theSide)
00204 {
00205   myC2d.resize(1);
00206   myLength = 0;
00207   myMesh = theSide->GetMesh();
00208   myDefaultPnt2d = thePnt2d;
00209 
00210   myPoints = theSide->GetUVPtStruct();
00211   myNbPonits = myNbSegments = myPoints.size();
00212   std::vector<uvPtStruct>::iterator it = myPoints.begin();
00213   for(; it!=myPoints.end(); it++) {
00214     (*it).u = thePnt2d.X();
00215     (*it).v = thePnt2d.Y();
00216     (*it).y = 0.0;
00217     (*it).node = theNode;
00218   }
00219 }
00220 
00221 //================================================================================
00226 //================================================================================
00227 
00228 const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
00229                                                              double constValue) const
00230 {
00231   if ( myPoints.empty() ) {
00232 
00233     if ( NbEdges() == 0 ) return myPoints;
00234 
00235     SMESHDS_Mesh* meshDS = myMesh->GetMeshDS();
00236     SMESH_MesherHelper helper(*myMesh);
00237     bool paramOK;
00238 
00239     // sort nodes of all edges putting them into a map
00240 
00241     map< double, const SMDS_MeshNode*> u2node;
00242     //int nbOnDegen = 0;
00243     for ( int i = 0; i < myEdge.size(); ++i )
00244     {
00245       // Put 1st vertex node of a current edge
00246       TopoDS_Vertex VV[2]; // TopExp::FirstVertex() returns NULL for INTERNAL edge
00247       VV[0] = SMESH_MesherHelper::IthVertex( 0, myEdge[i]);
00248       VV[1] = SMESH_MesherHelper::IthVertex( 1, myEdge[i]);
00249       const SMDS_MeshNode* node = SMESH_Algo::VertexNode( VV[0], meshDS );
00250       double prevNormPar = ( i == 0 ? 0 : myNormPar[ i-1 ]); // normalized param
00251       if ( node ) { // nodes on internal vertices may be missing
00252         u2node.insert( u2node.end(), make_pair( prevNormPar, node ));
00253       }
00254       else if ( i == 0 ) {
00255         MESSAGE(" NO NODE on VERTEX" );
00256         return myPoints;
00257       }
00258 
00259       // Put internal nodes
00260       if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( myEdge[i] ))
00261       {
00262         vector< pair< double, const SMDS_MeshNode*> > u2nodeVec;
00263         u2nodeVec.reserve( sm->NbNodes() );
00264         SMDS_NodeIteratorPtr nItr = sm->GetNodes();
00265         double paramSize = myLast[i] - myFirst[i];
00266         double r = myNormPar[i] - prevNormPar;
00267         if ( !myIsUniform[i] )
00268           while ( nItr->more() )
00269           {
00270             const SMDS_MeshNode* node = nItr->next();
00271             if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
00272               continue;
00273             double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );
00274             double aLenU = GCPnts_AbscissaPoint::Length
00275               ( const_cast<GeomAdaptor_Curve&>( myC3dAdaptor[i]), myFirst[i], u );
00276             if ( myEdgeLength[i] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6"
00277             {
00278               u2nodeVec.clear();
00279               break;
00280             }
00281             double normPar = prevNormPar + r*aLenU/myEdgeLength[i];
00282             u2nodeVec.push_back( make_pair( normPar, node ));
00283           }
00284         nItr = sm->GetNodes();
00285         if ( u2nodeVec.empty() )
00286           while ( nItr->more() )
00287           {
00288             const SMDS_MeshNode* node = nItr->next();
00289             if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
00290               continue;
00291             double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );
00292 
00293             // paramSize is signed so orientation is taken into account
00294             double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize;
00295             u2nodeVec.push_back( make_pair( normPar, node ));
00296           }
00297         for ( size_t j = 0; j < u2nodeVec.size(); ++j )
00298         u2node.insert( u2node.end(), u2nodeVec[j] );
00299       }
00300 
00301       // Put 2nd vertex node for a last edge
00302       if ( i+1 == myEdge.size() ) {
00303         node = SMESH_Algo::VertexNode( VV[1], meshDS );
00304         if ( !node ) {
00305           MESSAGE(" NO NODE on VERTEX" );
00306           return myPoints;
00307         }
00308         u2node.insert( u2node.end(), make_pair( 1., node ));
00309       }
00310     }
00311     if ( u2node.size() != myNbPonits ) {
00312       MESSAGE("Wrong node parameters on edges, u2node.size():"
00313               <<u2node.size()<<" !=  myNbPonits:"<<myNbPonits);
00314       return myPoints;
00315     }
00316 
00317     // fill array of UVPtStruct
00318 
00319     vector<uvPtStruct>* points = const_cast<vector<uvPtStruct>*>( &myPoints );
00320     points->resize( myNbPonits );
00321 
00322     int EdgeIndex = 0;
00323     double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ];
00324     map< double, const SMDS_MeshNode*>::iterator u_node = u2node.begin();
00325     for (int i = 0 ; u_node != u2node.end(); ++u_node, ++i ) {
00326       UVPtStruct & uvPt = (*points)[i];
00327       uvPt.node = u_node->second;
00328       uvPt.x = uvPt.y = uvPt.normParam = u_node->first;
00329       if ( isXConst ) uvPt.x = constValue;
00330       else            uvPt.y = constValue;
00331       const SMDS_EdgePosition* epos =
00332         dynamic_cast<const SMDS_EdgePosition*>(uvPt.node->GetPosition());
00333       if (( myNormPar[ EdgeIndex ] < uvPt.normParam ) ||
00334           ( epos && uvPt.node->getshapeId() != myEdgeID[ EdgeIndex ])) // for myMissingVertexNodes
00335       {
00336         prevNormPar = myNormPar[ EdgeIndex ];
00337         ++EdgeIndex;
00338 #ifdef _DEBUG_
00339         if ( EdgeIndex >= myEdge.size() ) {
00340           dump("DEBUG");
00341           MESSAGE ( "WRONg EdgeIndex " << 1+EdgeIndex
00342                     << " myNormPar.size()="<<myNormPar.size()
00343                     << " myNormPar["<< EdgeIndex<<"]="<< myNormPar[ EdgeIndex ]
00344                     << " uvPt.normParam="<<uvPt.normParam );
00345         }
00346 #endif
00347         paramSize = myNormPar[ EdgeIndex ] - prevNormPar;
00348       }
00349       if ( epos ) {
00350         uvPt.param = epos->GetUParameter();
00351       }
00352       else {
00353         double r = ( uvPt.normParam - prevNormPar )/ paramSize;
00354 //         uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r;
00355         uvPt.param = ( r > 0.5 ? myLast[EdgeIndex] : myFirst[EdgeIndex] );
00356       }
00357       if ( !myC2d[ EdgeIndex ].IsNull() ) {
00358         gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param );
00359         uvPt.u = p.X();
00360         uvPt.v = p.Y();
00361       }
00362       else {
00363         uvPt.u = uvPt.v = 1e+100;
00364       }
00365     }
00366   }
00367   return myPoints;
00368 }
00369 
00370 //================================================================================
00376 //================================================================================
00377 
00378 const vector<UVPtStruct>& StdMeshers_FaceSide::SimulateUVPtStruct(int    nbSeg,
00379                                                                   bool   isXConst,
00380                                                                   double constValue) const
00381 {
00382   if ( myFalsePoints.empty() ) {
00383 
00384     if ( NbEdges() == 0 ) return myFalsePoints;
00385 
00386     vector<uvPtStruct>* points = const_cast<vector<uvPtStruct>*>( &myFalsePoints );
00387     points->resize( nbSeg+1 );
00388 
00389     int EdgeIndex = 0;
00390     double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ];
00391     for (int i = 0 ; i < myFalsePoints.size(); ++i ) {
00392       double normPar = double(i) / double(nbSeg);
00393       UVPtStruct & uvPt = (*points)[i];
00394       uvPt.node = 0;
00395       uvPt.x = uvPt.y = uvPt.param = uvPt.normParam = normPar;
00396       if ( isXConst ) uvPt.x = constValue;
00397       else            uvPt.y = constValue;
00398       if ( myNormPar[ EdgeIndex ] < normPar ) {
00399         prevNormPar = myNormPar[ EdgeIndex ];
00400         ++EdgeIndex;
00401         paramSize = myNormPar[ EdgeIndex ] - prevNormPar;
00402       }
00403       double r = ( normPar - prevNormPar )/ paramSize;
00404       uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r;
00405       if ( !myC2d[ EdgeIndex ].IsNull() ) {
00406         gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param );
00407         uvPt.u = p.X();
00408         uvPt.v = p.Y();
00409       }
00410       else {
00411         uvPt.u = uvPt.v = 1e+100;
00412       }
00413     }
00414   }
00415   return myFalsePoints;
00416 }
00417 
00418 //=======================================================================
00419 //function : GetOrderedNodes
00420 //purpose  : Return nodes in the order they encounter while walking along the side
00421 //=======================================================================
00422 
00423 std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes() const
00424 {
00425   vector<const SMDS_MeshNode*> resultNodes;
00426   if ( myPoints.empty() )
00427   {
00428     if ( NbEdges() == 0 ) return resultNodes;
00429 
00430     SMESHDS_Mesh* meshDS = myMesh->GetMeshDS();
00431     SMESH_MesherHelper helper(*myMesh);
00432     bool paramOK;
00433 
00434     // Sort nodes of all edges putting them into a map
00435 
00436     map< double, const SMDS_MeshNode*> u2node;
00437     for ( int i = 0; i < myEdge.size(); ++i )
00438     {
00439       // Put 1st vertex node of a current edge
00440       TopoDS_Vertex VV[2]; // TopExp::FirstVertex() returns NULL for INTERNAL edge
00441       VV[0] = SMESH_MesherHelper::IthVertex( 0, myEdge[i]);
00442       VV[1] = SMESH_MesherHelper::IthVertex( 1, myEdge[i]);
00443       const SMDS_MeshNode* node = SMESH_Algo::VertexNode( VV[0], meshDS );
00444       double prevNormPar = ( i == 0 ? 0 : myNormPar[ i-1 ]); // normalized param
00445       if ( node ) { // nodes on internal vertices may be missing
00446         u2node.insert( make_pair( prevNormPar, node ));
00447       }
00448       else if ( i == 0 ) {
00449         MESSAGE(" NO NODE on VERTEX" );
00450         return resultNodes;
00451       }
00452 
00453       // Put internal nodes
00454       if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( myEdge[i] ))
00455       {
00456         SMDS_NodeIteratorPtr nItr = sm->GetNodes();
00457         double paramSize = myLast[i] - myFirst[i];
00458         double r = myNormPar[i] - prevNormPar;
00459         while ( nItr->more() )
00460         {
00461           const SMDS_MeshNode* node = nItr->next();
00462           if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
00463             continue;
00464           double u = helper.GetNodeU( myEdge[i], node, 0, &paramOK );
00465 
00466           // paramSize is signed so orientation is taken into account
00467           double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize;
00468           u2node.insert( u2node.end(), make_pair( normPar, node ));
00469         }
00470       }
00471 
00472       // Put 2nd vertex node for a last edge
00473       if ( i+1 == myEdge.size() ) {
00474         node = SMESH_Algo::VertexNode( VV[1], meshDS );
00475         if ( !node ) {
00476           return resultNodes;
00477         }
00478         u2node.insert( u2node.end(), make_pair( 1., node ));
00479       }
00480     }
00481 
00482     // Fill the result vector
00483 
00484     if ( u2node.size() == myNbPonits )
00485     {
00486       resultNodes.reserve( u2node.size() );
00487       map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin();
00488       for ( ; u2n != u2node.end(); ++u2n )
00489         resultNodes.push_back( u2n->second );
00490     }
00491   }
00492   else
00493   {
00494     resultNodes.resize( myPoints.size() );
00495     for ( size_t i = 0; i < myPoints.size(); ++i )
00496       resultNodes[i] = myPoints[i].node;
00497   }
00498 
00499   return resultNodes;
00500 }
00501 
00502 //================================================================================
00507 //================================================================================
00508 
00509 template <typename T > void reverse(vector<T> & vec)
00510 {
00511   for ( int f=0, r=vec.size()-1; f < r; ++f, --r )
00512     std::swap( vec[f], vec[r] );
00513 }
00514 
00515 //================================================================================
00519 //================================================================================
00520 
00521 void StdMeshers_FaceSide::Reverse()
00522 {
00523   int nbEdges = myEdge.size();
00524   for ( int i = nbEdges-1; i >= 0; --i ) {
00525     std::swap( myFirst[i], myLast[i] );
00526     myEdge[i].Reverse();
00527     if ( i > 0 ) // at the first loop 1. is overwritten
00528       myNormPar[i] = 1 - myNormPar[i-1];
00529   }
00530   if ( nbEdges > 1 ) {
00531     reverse( myEdge );
00532     reverse( myEdgeID );
00533     reverse( myC2d );
00534     reverse( myC3dAdaptor );
00535     reverse( myFirst );
00536     reverse( myLast );
00537     reverse( myNormPar );
00538     reverse( myEdgeLength );
00539     reverse( myIsUniform );
00540   }
00541   if ( nbEdges > 0 )
00542   {
00543     myNormPar[nbEdges-1]=1.;
00544     myPoints.clear();
00545     myFalsePoints.clear();
00546   }
00547 }
00548 
00549 //================================================================================
00553 //================================================================================
00554 
00555 void StdMeshers_FaceSide::dump(const char* msg) const
00556 {
00557 #ifdef _DEBUG_
00558   if (msg) MESSAGE ( std::endl << msg );
00559   MESSAGE_BEGIN ("NB EDGES: "<< myEdge.size() );
00560   MESSAGE_ADD ( "nbPoints: "<<myNbPonits<<" vecSize: " << myPoints.size()<<" "<<myFalsePoints.size() );
00561   for ( int i=0; i<myEdge.size(); ++i)
00562   {
00563     MESSAGE_ADD ( "\t"<<i+1 );
00564     MESSAGE_ADD ( "\tEDGE: " );
00565     if (myEdge[i].IsNull()) {
00566       MESSAGE_ADD ( "NULL" );
00567     }
00568     else {
00569       TopAbs::Print(myEdge[i].Orientation(),cout)<<" "<<myEdge[i].TShape().operator->()<<endl;
00570       MESSAGE_ADD ( "\tV1: " << TopExp::FirstVertex( myEdge[i], 1).TShape().operator->()
00571                  << "  V2: " << TopExp::LastVertex( myEdge[i], 1).TShape().operator->() );
00572     }
00573     MESSAGE_ADD ( "\tC2d: ");
00574     
00575     if (myC2d[i].IsNull()) {
00576       MESSAGE_ADD ( "NULL" );
00577     }
00578     else {
00579       MESSAGE_ADD ( myC2d[i].operator->() );
00580     }
00581       
00582     MESSAGE_ADD ( "\tF: "<<myFirst[i]<< " L: "<< myLast[i] );
00583     MESSAGE_END ( "\tnormPar: "<<myNormPar[i]<<endl );
00584   }
00585 #endif
00586 }
00587 
00588 //================================================================================
00593 //================================================================================
00594 
00595 struct Adaptor2dCurve2d : public Adaptor2d_Curve2d
00596 {
00597   const StdMeshers_FaceSide* mySide;
00598   Adaptor2dCurve2d(const StdMeshers_FaceSide* faceSide):mySide(faceSide) {}
00599   gp_Pnt2d Value(const Standard_Real U) const { return mySide->Value2d( U ); }
00600   Standard_Real FirstParameter() const { return 0; }
00601   Standard_Real LastParameter() const { return 1; }
00602 };
00603 
00604 Adaptor2d_Curve2d* StdMeshers_FaceSide::GetCurve2d() const
00605 {
00606   return new Adaptor2dCurve2d( this );
00607 }
00608 
00609 //================================================================================
00613 //================================================================================
00614 
00615 BRepAdaptor_CompCurve* StdMeshers_FaceSide::GetCurve3d() const
00616 {
00617   if ( myEdge.empty() )
00618     return 0;
00619 
00620   TopoDS_Wire aWire;
00621   BRep_Builder aBuilder;
00622   aBuilder.MakeWire(aWire);
00623   for ( int i=0; i<myEdge.size(); ++i )
00624     aBuilder.Add( aWire, myEdge[i] );
00625 
00626   if ( myEdge.size() == 2 && FirstVertex().IsSame( LastVertex() ))
00627     aWire.Closed(true); // issue 0021141
00628 
00629   return new BRepAdaptor_CompCurve( aWire );
00630 }
00631 
00632 
00633 //================================================================================
00639 //================================================================================
00640 
00641 gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const
00642 {
00643   if ( !myC2d[0].IsNull() ) {
00644     int i = EdgeIndex( U );
00645     double prevU = i ? myNormPar[ i-1 ] : 0;
00646     double r = ( U - prevU )/ ( myNormPar[ i ] - prevU );
00647 
00648     double par = myFirst[i] * ( 1 - r ) + myLast[i] * r;
00649     
00650     // check parametrization of curve
00651     if( !myIsUniform[i] )
00652     {
00653       double aLen3dU = r * myEdgeLength[i] * ( myFirst[i]>myLast[i] ? -1. : 1.);
00654       GCPnts_AbscissaPoint AbPnt
00655         ( const_cast<GeomAdaptor_Curve&>( myC3dAdaptor[i]), aLen3dU, myFirst[i] );
00656       if( AbPnt.IsDone() ) {
00657         par = AbPnt.Parameter();
00658       }
00659     }
00660     return myC2d[ i ]->Value(par);
00661 
00662   }
00663   return myDefaultPnt2d;
00664 }
00665 
00666 //================================================================================
00670 //================================================================================
00671 
00672 TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace,
00673                                               SMESH_Mesh &       theMesh,
00674                                               const bool         theIgnoreMediumNodes,
00675                                               TError &           theError)
00676 {
00677   TopoDS_Vertex V1;
00678   list< TopoDS_Edge > edges, internalEdges;
00679   list< int > nbEdgesInWires;
00680   int nbWires = SMESH_Block::GetOrderedEdges (theFace, V1, edges, nbEdgesInWires);
00681 
00682   // split list of all edges into separate wires
00683   TSideVector wires( nbWires );
00684   list< int >::iterator nbE = nbEdgesInWires.begin();
00685   list< TopoDS_Edge >::iterator from = edges.begin(), to = from;
00686   for ( int iW = 0; iW < nbWires; ++iW, ++nbE )
00687   {
00688     std::advance( to, *nbE );
00689     if ( *nbE == 0 ) // Issue 0020676
00690     {
00691       --nbWires;
00692       --iW;
00693       wires.resize( nbWires );
00694       continue;
00695     }
00696     list< TopoDS_Edge > wireEdges( from, to );
00697     // assure that there is a node on the first vertex
00698     // as StdMeshers_FaceSide::GetUVPtStruct() requires
00699     if ( wireEdges.front().Orientation() != TopAbs_INTERNAL ) // Issue 0020676
00700     {
00701       while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true),
00702                                        theMesh.GetMeshDS()))
00703       {
00704         wireEdges.splice(wireEdges.end(), wireEdges,
00705                          wireEdges.begin(), ++wireEdges.begin());
00706         if ( from->IsSame( wireEdges.front() )) {
00707           theError = TError
00708             ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices"));
00709           return TSideVector(0);
00710         }
00711       }
00712     }
00713     else if ( *nbE > 1 ) // Issue 0020676 (Face_pb_netgen.brep) - several internal edges in a wire
00714     {
00715       internalEdges.splice( internalEdges.end(), wireEdges, ++wireEdges.begin(), wireEdges.end());
00716     }
00717 
00718     StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh,
00719                                                          /*isForward=*/true, theIgnoreMediumNodes);
00720     wires[ iW ] = StdMeshers_FaceSidePtr( wire );
00721     from = to;
00722   }
00723   while ( !internalEdges.empty() )
00724   {
00725     StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, internalEdges.back(), &theMesh,
00726                                                          /*isForward=*/true, theIgnoreMediumNodes);
00727     wires.push_back( StdMeshers_FaceSidePtr( wire ));
00728     internalEdges.pop_back();
00729   }
00730   return wires;
00731 }
00732 
00733 //================================================================================
00737 //================================================================================
00738 
00739 TopoDS_Vertex StdMeshers_FaceSide::FirstVertex(int i) const
00740 {
00741   TopoDS_Vertex v;
00742   if ( i < NbEdges() )
00743   {
00744     v = myEdge[i].Orientation() <= TopAbs_REVERSED ? // FORWARD || REVERSED
00745         TopExp::FirstVertex( myEdge[i], 1 )        :
00746         TopoDS::Vertex( TopoDS_Iterator( myEdge[i] ).Value() );
00747   }
00748   return v;
00749 }
00750 
00751 //================================================================================
00755 //================================================================================
00756 
00757 TopoDS_Vertex StdMeshers_FaceSide::LastVertex(int i) const
00758 {
00759   TopoDS_Vertex v;
00760   if ( i < NbEdges() )
00761   {
00762     const TopoDS_Edge& edge = i<0 ? myEdge[ NbEdges() + i ] : myEdge[i];
00763     if ( edge.Orientation() <= TopAbs_REVERSED ) // FORWARD || REVERSED
00764       v = TopExp::LastVertex( edge, 1 );
00765     else
00766       for ( TopoDS_Iterator vIt( edge ); vIt.More(); vIt.Next() )
00767         v = TopoDS::Vertex( vIt.Value() );
00768   }
00769   return v;
00770 }
00771