-// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021 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
#include "SMESHDS_Mesh.hxx"
#include "SMESHDS_SubMesh.hxx"
#include "SMESH_Algo.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_ComputeError.hxx"
#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
#include "SMESH_MesherHelper.hxx"
-#include "SMESH_ComputeError.hxx"
-#include "SMESH_Block.hxx"
#include <Adaptor2d_Curve2d.hxx>
#include <BRepAdaptor_CompCurve.hxx>
* \brief Constructor of a side of one edge
* \param theFace - the face
* \param theEdge - the edge
- */
+ */
//================================================================================
StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
SMESH_Mesh* theMesh,
const bool theIsForward,
const bool theIgnoreMediumNodes,
+ SMESH_MesherHelper* theFaceHelper,
SMESH_ProxyMesh::Ptr theProxyMesh)
{
std::list<TopoDS_Edge> edges(1,theEdge);
- *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward,
- theIgnoreMediumNodes, theProxyMesh );
+ StdMeshers_FaceSide tmp( theFace, edges, theMesh, theIsForward,
+ theIgnoreMediumNodes, theFaceHelper, theProxyMesh );
+ *this = tmp;
+
+ tmp.myHelper = NULL;
}
//================================================================================
*/
//================================================================================
-StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
- std::list<TopoDS_Edge>& theEdges,
- SMESH_Mesh* theMesh,
- const bool theIsForward,
- const bool theIgnoreMediumNodes,
- SMESH_ProxyMesh::Ptr theProxyMesh)
+StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace,
+ const std::list<TopoDS_Edge>& theEdges,
+ SMESH_Mesh* theMesh,
+ const bool theIsForward,
+ const bool theIgnoreMediumNodes,
+ SMESH_MesherHelper* theFaceHelper,
+ SMESH_ProxyMesh::Ptr theProxyMesh)
{
int nbEdges = theEdges.size();
myEdge.resize ( nbEdges );
myMissingVertexNodes = false;
myIgnoreMediumNodes = theIgnoreMediumNodes;
myDefaultPnt2d = gp_Pnt2d( 1e+100, 1e+100 );
+ myHelper = NULL;
if ( !myProxyMesh ) myProxyMesh.reset( new SMESH_ProxyMesh( *theMesh ));
+ if ( theFaceHelper && theFaceHelper->GetSubShape() == myFace )
+ {
+ myHelper = new SMESH_MesherHelper( * myProxyMesh->GetMesh() );
+ myHelper->CopySubShapeInfo( *theFaceHelper );
+ }
if ( nbEdges == 0 ) return;
SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
int nbDegen = 0;
- std::list<TopoDS_Edge>::iterator edge = theEdges.begin();
+ std::list<TopoDS_Edge>::const_iterator edge = theEdges.begin();
for ( int index = 0; edge != theEdges.end(); ++index, ++edge )
{
int i = theIsForward ? index : nbEdges-index-1;
myC3dAdaptor[i].Load( C3d, 0, 0.5 * BRep_Tool::Tolerance( V ));
}
}
+ else if ( myEdgeLength[i] > DBL_MIN )
+ {
+ Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],myFirst[i], myLast[i] );
+ myC3dAdaptor[i].Load( C3d, myFirst[i], myLast[i] );
+ if ( myEdge[i].Orientation() == TopAbs_REVERSED )
+ std::swap( myFirst[i], myLast[i] );
+ }
+
// reverse a proxy sub-mesh
if ( !theIsForward )
reverseProxySubmesh( myEdge[i] );
} // loop on edges
+ // orient seam edges (#19982)
+ const double tol = Precision::Confusion();
+ if ( NbEdges() > 1 && !myC2d[0].IsNull() )
+ for ( int i = 0; i < NbEdges(); ++i )
+ {
+ int iPrev = SMESH_MesherHelper::WrapIndex( i - 1, NbEdges() );
+ if ( !BRep_Tool::IsClosed( myEdge[i], myFace ) || !myC2d[iPrev] )
+ continue;
+ gp_Pnt2d pLastPrev = myC2d[iPrev]->Value( myLast[iPrev] );
+ gp_Pnt2d pFirst = myC2d[i]->Value( myFirst[i] );
+ if ( pLastPrev.IsEqual( pFirst, tol ))
+ continue; // OK
+ pFirst = myC2d[i]->Value( myLast[i] );
+ if ( pLastPrev.IsEqual( pFirst, tol ))
+ {
+ std::swap( myFirst[i], myLast[i] );
+ continue;
+ }
+ TopoDS_Edge E = myEdge[i];
+ E.Reverse();
+ Handle(Geom2d_Curve) c2dRev = BRep_Tool::CurveOnSurface( E, myFace, myFirst[i], myLast[i] );
+ pFirst = c2dRev->Value( myFirst[i] );
+ if ( pLastPrev.IsEqual( pFirst, tol ))
+ {
+ myC2d[i] = c2dRev;
+ continue;
+ }
+ pFirst = c2dRev->Value( myLast[i] );
+ if ( pLastPrev.IsEqual( pFirst, tol ))
+ {
+ myC2d[i] = c2dRev;
+ std::swap( myFirst[i], myLast[i] );
+ }
+ }
+
// count nodes and segments
NbPoints( /*update=*/true );
const double theUFirst,
const double theULast)
{
+ myEdge.resize ( 1 );
+ myEdgeID.resize ( 1, 0 );
myC2d.push_back ( theC2d );
+ myC3dAdaptor.resize ( 1 );
myFirst.push_back ( theUFirst );
myLast.push_back ( theULast );
myNormPar.push_back ( 1. );
myIsUniform.push_back( true );
- myEdgeID.push_back ( 0 );
+ myHelper = NULL;
myLength = 0;
myProxyMesh = theSide->myProxyMesh;
myDefaultPnt2d = *thePnt2d1;
}
myFace = theFace;
+ myHelper = NULL;
myPoints = theSideNodes;
myNbPonits = myPoints.size();
myNbSegments = myNbPonits + 1;
myEdgeLength.resize( 1, myLength );
}
+//================================================================================
+/*!
+ * \brief Destructor
+ */
+//================================================================================
+
+StdMeshers_FaceSide::~StdMeshers_FaceSide()
+{
+ delete myHelper; myHelper = NULL;
+}
+
//================================================================================
/*
* Return info on nodes on the side
if ( NbEdges() == 0 ) return myPoints;
StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
- //SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
- SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
- SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
- fHelper.SetSubShape( myFace );
- bool paramOK;
+ bool paramOK = true;
double eps = 1e-100;
+ SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+ SMESH_MesherHelper& fHelper = *FaceHelper();
+
// sort nodes of all edges by putting them into a map
map< double, const SMDS_MeshNode*> u2node;
for ( size_t j = 0; j < u2nodeVec.size(); ++j )
u2node.insert( u2node.end(), u2nodeVec[j] );
}
+ continue;
} // loop on myEdge's
// Add 2nd VERTEX node for a last EDGE
else
{
node = VertexNode( iE );
- while ( !node && iE > 0 )
- node = VertexNode( --iE );
- if ( !node )
- return myPoints;
+ if ( myProxyMesh->GetMesh()->HasModificationsToDiscard() )
+ while ( !node && iE > 1 ) // check intermediate VERTEXes
+ node = VertexNode( --iE );
}
- if ( u2node.rbegin()->second == node &&
- !fHelper.IsRealSeam ( node->getshapeId() ) &&
- !fHelper.IsDegenShape( node->getshapeId() ))
- u2node.erase( --u2node.end() );
+ if ( node )
+ {
+ if ( u2node.rbegin()->second == node &&
+ !fHelper.IsRealSeam ( node->getshapeId() ) &&
+ !fHelper.IsDegenShape( node->getshapeId() ))
+ u2node.erase( --u2node.end() );
- u2node.insert( u2node.end(), make_pair( 1., node ));
+ u2node.insert( u2node.end(), make_pair( 1., node ));
+ }
}
if ((int) u2node.size() + nbProxyNodes != myNbPonits &&
(int) u2node.size() + nbProxyNodes != NbPoints( /*update=*/true ))
{
- MESSAGE("Wrong node parameters on edges, u2node.size():"
- <<u2node.size()<<" != myNbPonits:"<<myNbPonits);
+ return myPoints;
+ }
+ if (( u2node.size() > 0 ) &&
+ ( u2node.begin()->first < 0 || u2node.rbegin()->first > 1 ))
+ {
return myPoints;
}
if ( proxySubMesh[ iE ] ) // copy data from a proxy sub-mesh
{
const UVPtStructVec& edgeUVPtStruct = proxySubMesh[iE]->GetUVPtStructVec();
- std::copy( edgeUVPtStruct.begin(), edgeUVPtStruct.end(), & points[iPt] );
+ UVPtStruct* pointsPtr = & points[iPt];
+ std::copy( edgeUVPtStruct.begin(), edgeUVPtStruct.end(), pointsPtr );
// check orientation
double du1 = edgeUVPtStruct.back().param - edgeUVPtStruct[0].param;
double du2 = myLast[iE] - myFirst[iE];
if ( du1 * du2 < 0 )
{
- std::reverse( & points[iPt], & points[iPt + edgeUVPtStruct.size()]);
+ std::reverse( pointsPtr, pointsPtr + edgeUVPtStruct.size());
for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i )
- points[iPt+i].normParam = 1. - points[iPt+i].normParam;
+ pointsPtr[i].normParam = 1. - pointsPtr[i].normParam;
}
// update normalized params
if ( myEdge.size() > 1 ) {
- for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i, ++iPt )
+ for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i )
{
- UVPtStruct & uvPt = points[iPt];
+ UVPtStruct & uvPt = pointsPtr[i];
uvPt.normParam = prevNormPar + uvPt.normParam * paramSize;
uvPt.x = uvPt.y = uvPt.normParam;
}
- --iPt; // to point to the 1st VERTEX of the next EDGE
+ iPt += edgeUVPtStruct.size() - 1; // to point to the 1st VERTEX of the next EDGE
+ }
+ // update UV on a seam EDGE
+ if ( fHelper.IsRealSeam( myEdgeID[ iE ]))
+ {
+ // check if points lye on the EDGE
+ const UVPtStruct& pm = edgeUVPtStruct[ edgeUVPtStruct.size()/2 ];
+ gp_Pnt pNode = SMESH_TNodeXYZ( pm.node );
+ gp_Pnt pCurv = myC3dAdaptor[ iE ].Value( pm.param );
+ double tol = BRep_Tool::Tolerance( myEdge[ iE ]) * 10;
+ bool isPointOnEdge = ( pNode.SquareDistance( pCurv ) < tol * tol );
+ if ( isPointOnEdge )
+ for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i )
+ pointsPtr[i].SetUV( myC2d[ iE ]->Value( pointsPtr[i].param ).XY() );
}
}
else
for ( ; u_node != u2node.end(); ++u_node, ++iPt )
{
if ( myNormPar[ iE ]-eps < u_node->first )
- break; // u_node is at VERTEX of the next EDGE
+ break; // u_node is at VERTEX of the next EDGE
UVPtStruct & uvPt = points[iPt];
uvPt.node = u_node->second;
uvPt.normParam = u_node->first;
uvPt.x = uvPt.y = uvPt.normParam;
// -- U ----------------------------------------------
- const SMDS_EdgePosition* epos =
- dynamic_cast<const SMDS_EdgePosition*>(uvPt.node->GetPosition());
+ SMDS_EdgePositionPtr epos = uvPt.node->GetPosition();
if ( epos && uvPt.node->getshapeId() == myEdgeID[iE] ) {
uvPt.param = epos->GetUParameter();
}
if ( NbEdges() == 0 ) return resultNodes;
//SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
- SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
- SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
- fHelper.SetSubShape( myFace );
+ SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+ SMESH_MesherHelper& fHelper = * FaceHelper();
bool paramOK = true;
// Sort nodes of all edges putting them into a map
iE = theEdgeInd % NbEdges();
iEnd = iE + 1;
}
- for ( iE = 0; iE < iEnd; ++iE )
+ for ( ; iE < iEnd; ++iE )
{
double prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
if ( mesh->HasModificationsToDiscard() ) // check nb of nodes on the EDGE sub-mesh
{
int iQuad = sm->NbElements() ? sm->GetElements()->next()->IsQuadratic() : 0;
- int nbExpect = sm->NbElements() - 1 + iQuad * sm->NbElements();
+ smIdType nbExpect = sm->NbElements() - 1 + iQuad * sm->NbElements();
if ( nbExpect != sm->NbNodes() ) // some nodes are moved from the EDGE by MergeNodes()
{
// add nodes of all segments
// since creation of this side
//=======================================================================
-int StdMeshers_FaceSide::NbPoints(const bool update) const
+smIdType StdMeshers_FaceSide::NbPoints(const bool update) const
{
if ( !myPoints.empty() )
return myPoints.size();
}
}
- SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
- helper.SetSubShape( myFace );
+ SMESH_MesherHelper* helper = FaceHelper();
std::set< const SMDS_MeshNode* > vNodes;
const int nbV = NbEdges() + !IsClosed();
if ( const SMDS_MeshNode* n = VertexNode( i ))
{
if ( !vNodes.insert( n ).second &&
- ( helper.IsRealSeam ( n->getshapeId() ) ||
- helper.IsDegenShape( n->getshapeId() )))
+ ( helper->IsRealSeam ( n->getshapeId() ) ||
+ helper->IsDegenShape( n->getshapeId() )))
me->myNbPonits++;
}
else
// since creation of this side
//=======================================================================
-int StdMeshers_FaceSide::NbSegments(const bool update) const
+smIdType StdMeshers_FaceSide::NbSegments(const bool update) const
{
return NbPoints( update ), myNbSegments;
}
MESSAGE_ADD ( "\tF: "<<myFirst[i]<< " L: "<< myLast[i] );
MESSAGE_END ( "\tnormPar: "<<myNormPar[i]<<endl );
}
+#else
+ (void)msg; // unused in release mode
#endif
}
// check parametrization of curve
if( !myIsUniform[i] )
{
- double aLen3dU = r * myEdgeLength[i] * ( myFirst[i]>myLast[i] ? -1. : 1.);
+ 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() ) {
SMESH_Mesh & theMesh,
const bool theIgnoreMediumNodes,
TError & theError,
+ SMESH_MesherHelper* theFaceHelper,
SMESH_ProxyMesh::Ptr theProxyMesh,
const bool theCheckVertexNodes)
{
+ SMESH_MesherHelper helper( theMesh );
+ if ( theFaceHelper && theFaceHelper->GetSubShape() == theFace )
+ helper.CopySubShapeInfo( *theFaceHelper );
+
list< TopoDS_Edge > edges, internalEdges;
list< int > nbEdgesInWires;
int nbWires = SMESH_Block::GetOrderedEdges (theFace, edges, nbEdgesInWires);
StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh,
/*isForward=*/true, theIgnoreMediumNodes,
- theProxyMesh );
+ &helper, theProxyMesh );
wires[ iW ] = StdMeshers_FaceSidePtr( wire );
from = to;
}
{
StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, internalEdges.back(), &theMesh,
/*isForward=*/true, theIgnoreMediumNodes,
- theProxyMesh );
+ &helper, theProxyMesh );
wires.push_back( StdMeshers_FaceSidePtr( wire ));
internalEdges.pop_back();
}
{
return myEdge.empty() ? false : FirstVertex().IsSame( LastVertex() );
}
+
+//================================================================================
+/*!
+ * \brief Return a helper initialized with the FACE
+ */
+//================================================================================
+
+SMESH_MesherHelper* StdMeshers_FaceSide::FaceHelper() const
+{
+ StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
+ if ( !myHelper && myProxyMesh )
+ {
+ me->myHelper = new SMESH_MesherHelper( *myProxyMesh->GetMesh() );
+ me->myHelper->SetSubShape( myFace );
+ }
+ return me->myHelper;
+}