-// 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, ¶mOK );
- 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, ¶mOK );
-
- // 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, ¶mOK );\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, ¶mOK );\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