X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_Algo.cxx;h=035c23c5919ccc309f758165820aa958c4cdbd78;hp=0f41460d5221cae09690bd068bcd36f4c725dda2;hb=e74c29b7867ca230102fc580d831dda6b81b3b4c;hpb=93c3ba77f57cf5bcc0fe4e14e9ba593650388796 diff --git a/src/SMESH/SMESH_Algo.cxx b/src/SMESH/SMESH_Algo.cxx index 0f41460d5..035c23c59 100644 --- a/src/SMESH/SMESH_Algo.cxx +++ b/src/SMESH/SMESH_Algo.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 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 @@ -178,6 +178,7 @@ const SMESH_Algo::Features& SMESH_Algo::GetFeatures( const std::string& algoType SMESH_Algo::SMESH_Algo (int hypId, int studyId, SMESH_Gen * gen) : SMESH_Hypothesis(hypId, studyId, gen) { + _compatibleAllHypFilter = _compatibleNoAuxHypFilter = NULL; _onlyUnaryInput = _requireDiscreteBoundary = _requireShape = true; _quadraticMesh = _supportSubmeshes = false; _error = COMPERR_OK; @@ -193,6 +194,8 @@ SMESH_Algo::SMESH_Algo (int hypId, int studyId, SMESH_Gen * gen) SMESH_Algo::~SMESH_Algo() { + delete _compatibleNoAuxHypFilter; + // delete _compatibleAllHypFilter; -- _compatibleNoAuxHypFilter does it!!! } //============================================================================= @@ -228,7 +231,7 @@ SMESH_3D_Algo::SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen) //============================================================================= /*! - * Usually an algoritm has nothing to save + * Usually an algorithm has nothing to save */ //============================================================================= @@ -263,10 +266,9 @@ SMESH_Algo::GetUsedHypothesis(SMESH_Mesh & aMesh, { SMESH_Algo* me = const_cast< SMESH_Algo* >( this ); me->_usedHypList.clear(); - SMESH_HypoFilter filter; - if ( InitCompatibleHypoFilter( filter, ignoreAuxiliary )) + if ( const SMESH_HypoFilter* filter = GetCompatibleHypoFilter( ignoreAuxiliary )) { - aMesh.GetHypotheses( aShape, filter, me->_usedHypList, true ); + aMesh.GetHypotheses( aShape, *filter, me->_usedHypList, true ); if ( ignoreAuxiliary && _usedHypList.size() > 1 ) me->_usedHypList.clear(); //only one compatible hypothesis allowed } @@ -288,9 +290,8 @@ SMESH_Algo::GetAppliedHypothesis(SMESH_Mesh & aMesh, { SMESH_Algo* me = const_cast< SMESH_Algo* >( this ); me->_appliedHypList.clear(); - SMESH_HypoFilter filter; - if ( InitCompatibleHypoFilter( filter, ignoreAuxiliary )) - aMesh.GetHypotheses( aShape, filter, me->_appliedHypList, false ); + if ( const SMESH_HypoFilter* filter = GetCompatibleHypoFilter( ignoreAuxiliary )) + aMesh.GetHypotheses( aShape, *filter, me->_appliedHypList, false ); return _appliedHypList; } @@ -402,7 +403,8 @@ bool SMESH_Algo::GetNodeParamOnEdge(const SMESHDS_Mesh* theMesh, bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theMesh, const TopoDS_Edge& theEdge, const bool ignoreMediumNodes, - map< double, const SMDS_MeshNode* > & theNodes) + map< double, const SMDS_MeshNode* > & theNodes, + const SMDSAbs_ElementType typeToCheck) { theNodes.clear(); @@ -410,7 +412,7 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theM return false; SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge ); - if ( !eSubMesh || ( eSubMesh->NbElements()==0 && eSubMesh->NbNodes() == 0)) + if ( !eSubMesh || ( eSubMesh->NbElements() == 0 && eSubMesh->NbNodes() == 0)) return false; // edge is not meshed int nbNodes = 0; @@ -422,62 +424,67 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theM while ( nIt->more() ) { const SMDS_MeshNode* node = nIt->next(); - if ( ignoreMediumNodes ) { - SMDS_ElemIteratorPtr elemIt = node->GetInverseElementIterator(); - if ( elemIt->more() && elemIt->next()->IsMediumNode( node )) - continue; - } + if ( ignoreMediumNodes && SMESH_MesherHelper::IsMedium( node, typeToCheck )) + continue; const SMDS_PositionPtr& pos = node->GetPosition(); if ( pos->GetTypeOfPosition() != SMDS_TOP_EDGE ) return false; const SMDS_EdgePosition* epos = static_cast(node->GetPosition()); theNodes.insert( theNodes.end(), make_pair( epos->GetUParameter(), node )); - //MESSAGE("U " << epos->GetUParameter() << " ID " << node->GetID()); ++nbNodes; } } // add vertex nodes TopoDS_Vertex v1, v2; TopExp::Vertices(theEdge, v1, v2); - const SMDS_MeshNode* n1 = VertexNode( v1, (SMESHDS_Mesh*) theMesh ); - const SMDS_MeshNode* n2 = VertexNode( v2, (SMESHDS_Mesh*) theMesh ); - //MESSAGE("Vertices ID " << n1->GetID() << " " << n2->GetID()); + const SMDS_MeshNode* n1 = VertexNode( v1, eSubMesh, 0 ); + const SMDS_MeshNode* n2 = VertexNode( v2, eSubMesh, 0 ); + const SMDS_MeshNode* nEnd[2] = { nbNodes ? theNodes.begin()->second : 0, + nbNodes ? theNodes.rbegin()->second : 0 }; Standard_Real f, l; BRep_Tool::Range(theEdge, f, l); if ( v1.Orientation() != TopAbs_FORWARD ) std::swap( f, l ); - if ( n1 && ++nbNodes ) + if ( n1 && n1 != nEnd[0] && n1 != nEnd[1] && ++nbNodes ) theNodes.insert( make_pair( f, n1 )); - if ( n2 && ++nbNodes ) + if ( n2 && n2 != nEnd[0] && n2 != nEnd[1] && ++nbNodes ) theNodes.insert( make_pair( l, n2 )); - return theNodes.size() == nbNodes; + return (int)theNodes.size() == nbNodes; } //================================================================================ /*! - * \brief Make filter recognize only compatible hypotheses - * \param theFilter - the filter to initialize - * \param ignoreAuxiliary - make filter ignore compatible auxiliary hypotheses + * \brief Returns the filter recognizing only compatible hypotheses + * \param ignoreAuxiliary - make filter ignore auxiliary hypotheses + * \retval SMESH_HypoFilter* - the filter that can be NULL */ //================================================================================ -bool SMESH_Algo::InitCompatibleHypoFilter( SMESH_HypoFilter & theFilter, - const bool ignoreAuxiliary) const +const SMESH_HypoFilter* +SMESH_Algo::GetCompatibleHypoFilter(const bool ignoreAuxiliary) const { if ( !_compatibleHypothesis.empty() ) { - theFilter.Init( theFilter.HasName( _compatibleHypothesis[0] )); - for ( int i = 1; i < _compatibleHypothesis.size(); ++i ) - theFilter.Or( theFilter.HasName( _compatibleHypothesis[ i ] )); - - if ( ignoreAuxiliary ) - theFilter.AndNot( theFilter.IsAuxiliary() ); - - return true; + if ( !_compatibleAllHypFilter ) + { + SMESH_HypoFilter* filter = new SMESH_HypoFilter(); + filter->Init( filter->HasName( _compatibleHypothesis[0] )); + for ( size_t i = 1; i < _compatibleHypothesis.size(); ++i ) + filter->Or( filter->HasName( _compatibleHypothesis[ i ] )); + + SMESH_HypoFilter* filterNoAux = new SMESH_HypoFilter( filter ); + filterNoAux->AndNot( filterNoAux->IsAuxiliary() ); + + // _compatibleNoAuxHypFilter will detele _compatibleAllHypFilter!!! + SMESH_Algo* me = const_cast< SMESH_Algo* >( this ); + me->_compatibleAllHypFilter = filter; + me->_compatibleNoAuxHypFilter = filterNoAux; + } + return ignoreAuxiliary ? _compatibleNoAuxHypFilter : _compatibleAllHypFilter; } - return false; + return 0; } //================================================================================ @@ -489,10 +496,11 @@ bool SMESH_Algo::InitCompatibleHypoFilter( SMESH_HypoFilter & theFilter, */ //================================================================================ -GeomAbs_Shape SMESH_Algo::Continuity(TopoDS_Edge E1, - TopoDS_Edge E2) +GeomAbs_Shape SMESH_Algo::Continuity(const TopoDS_Edge& theE1, + const TopoDS_Edge& theE2) { - //E1.Orientation(TopAbs_FORWARD), E2.Orientation(TopAbs_FORWARD); // avoid pb with internal edges + // avoid pb with internal edges + TopoDS_Edge E1 = theE1, E2 = theE2; if (E1.Orientation() > TopAbs_REVERSED) // INTERNAL E1.Orientation( TopAbs_FORWARD ); if (E2.Orientation() > TopAbs_REVERSED) // INTERNAL @@ -513,9 +521,7 @@ GeomAbs_Shape SMESH_Algo::Continuity(TopoDS_Edge E1, Standard_Real tol = BRep_Tool::Tolerance( V ); Standard_Real angTol = 2e-3; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif return BRepLProp::Continuity(C1, C2, u1, u2, tol, angTol); } catch (Standard_Failure) { @@ -561,7 +567,7 @@ bool SMESH_Algo::IsStraight( const TopoDS_Edge & E, if ( v1Len < std::numeric_limits< double >::min() ) return false; // E seems closed const double tol = Min( 10 * curve.Tolerance(), v1Len * 1e-2 ); - const int nbSamples = 7; + const double nbSamples = 7; for ( int i = 0; i < nbSamples; ++i ) { const double r = ( i + 1 ) / nbSamples; @@ -580,8 +586,10 @@ bool SMESH_Algo::IsStraight( const TopoDS_Edge & E, */ //================================================================================ -bool SMESH_Algo::isDegenerated( const TopoDS_Edge & E ) +bool SMESH_Algo::isDegenerated( const TopoDS_Edge & E, const bool checkLength ) { + if ( checkLength ) + return EdgeLength( E ) == 0; double f,l; TopLoc_Location loc; Handle(Geom_Curve) C = BRep_Tool::Curve( E, loc, f,l ); @@ -609,6 +617,118 @@ const SMDS_MeshNode* SMESH_Algo::VertexNode(const TopoDS_Vertex& V, return 0; } +//======================================================================= +/*! + * \brief Return the node built on a vertex. + * A node moved to other geometry by MergeNodes() is also returned. + * \param V - the vertex + * \param mesh - mesh + * \retval const SMDS_MeshNode* - found node or NULL + */ +//======================================================================= + +const SMDS_MeshNode* SMESH_Algo::VertexNode(const TopoDS_Vertex& V, + const SMESH_Mesh* mesh) +{ + const SMDS_MeshNode* node = VertexNode( V, mesh->GetMeshDS() ); + + if ( !node && mesh->HasModificationsToDiscard() ) + { + PShapeIteratorPtr edgeIt = SMESH_MesherHelper::GetAncestors( V, *mesh, TopAbs_EDGE ); + while ( const TopoDS_Shape* edge = edgeIt->next() ) + if ( SMESHDS_SubMesh* edgeSM = mesh->GetMeshDS()->MeshElements( *edge )) + if ( edgeSM->NbElements() > 0 ) + return VertexNode( V, edgeSM, mesh, /*checkV=*/false ); + } + return node; +} + +//======================================================================= +/*! + * \brief Return the node built on a vertex. + * A node moved to other geometry by MergeNodes() is also returned. + * \param V - the vertex + * \param edgeSM - sub-mesh of a meshed EDGE sharing the vertex + * \param checkV - if \c true, presence of a node on the vertex is checked + * \retval const SMDS_MeshNode* - found node or NULL + */ +//======================================================================= + +const SMDS_MeshNode* SMESH_Algo::VertexNode(const TopoDS_Vertex& V, + const SMESHDS_SubMesh* edgeSM, + const SMESH_Mesh* mesh, + const bool checkV) +{ + const SMDS_MeshNode* node = checkV ? VertexNode( V, edgeSM->GetParent() ) : 0; + + if ( !node && edgeSM ) + { + // find nodes not shared by mesh segments + typedef set< const SMDS_MeshNode* > TNodeSet; + typedef map< const SMDS_MeshNode*, const SMDS_MeshNode* > TNodeMap; + TNodeMap notSharedNodes; + TNodeSet otherShapeNodes; + vector< const SMDS_MeshNode* > segNodes(3); + SMDS_ElemIteratorPtr segIt = edgeSM->GetElements(); + while ( segIt->more() ) + { + const SMDS_MeshElement* seg = segIt->next(); + if ( seg->GetType() != SMDSAbs_Edge ) + return node; + segNodes.assign( seg->begin_nodes(), seg->end_nodes() ); + for ( int i = 0; i < 2; ++i ) + { + const SMDS_MeshNode* n1 = segNodes[i]; + const SMDS_MeshNode* n2 = segNodes[1-i]; + pair it2new = notSharedNodes.insert( make_pair( n1, n2 )); + if ( !it2new.second ) // n encounters twice + notSharedNodes.erase( it2new.first ); + if ( n1->getshapeId() != edgeSM->GetID() ) + otherShapeNodes.insert( n1 ); + } + } + if ( otherShapeNodes.size() == 1 && notSharedNodes.empty() ) // a closed EDGE + return *otherShapeNodes.begin(); + + if ( notSharedNodes.size() == 2 ) // two end nodes found + { + SMESHDS_Mesh* meshDS = edgeSM->GetParent(); + const TopoDS_Shape& E = meshDS->IndexToShape( edgeSM->GetID() ); + if ( E.IsNull() || E.ShapeType() != TopAbs_EDGE ) + return node; + const SMDS_MeshNode* n1 = notSharedNodes.begin ()->first; + const SMDS_MeshNode* n2 = notSharedNodes.rbegin()->first; + TopoDS_Shape S1 = SMESH_MesherHelper::GetSubShapeByNode( n1, meshDS ); + if ( S1.ShapeType() == TopAbs_VERTEX && SMESH_MesherHelper::IsSubShape( S1, E )) + return n2; + TopoDS_Shape S2 = SMESH_MesherHelper::GetSubShapeByNode( n2, meshDS ); + if ( S2.ShapeType() == TopAbs_VERTEX && SMESH_MesherHelper::IsSubShape( S2, E )) + return n1; + if ( edgeSM->NbElements() <= 2 || !mesh ) // one-two segments + { + gp_Pnt pV = BRep_Tool::Pnt( V ); + double dist1 = pV.SquareDistance( SMESH_TNodeXYZ( n1 )); + double dist2 = pV.SquareDistance( SMESH_TNodeXYZ( n2 )); + return dist1 < dist2 ? n1 : n2; + } + if ( mesh ) + { + SMESH_MesherHelper helper( const_cast( *mesh )); + const SMDS_MeshNode* n1i = notSharedNodes.begin ()->second; + const SMDS_MeshNode* n2i = notSharedNodes.rbegin()->second; + const TopoDS_Edge& edge = TopoDS::Edge( E ); + bool posOK = true; + double pos1 = helper.GetNodeU( edge, n1i, n2i, &posOK ); + double pos2 = helper.GetNodeU( edge, n2i, n1i, &posOK ); + double posV = BRep_Tool::Parameter( V, edge ); + if ( Abs( pos1 - posV ) < Abs( pos2 - posV )) return n1; + else return n2; + } + } + } + return node; +} + //======================================================================= //function : GetMeshError //purpose : Finds topological errors of a sub-mesh @@ -631,7 +751,7 @@ SMESH_Algo::EMeshError SMESH_Algo::GetMeshError(SMESH_subMesh* subMesh) if ( !fIt->more() ) return MEr_EMPTY; - // We check that olny links on EDGEs encouter once, the rest links, twice + // We check that only links on EDGEs encouter once, the rest links, twice set< SMESH_TLink > links; while ( fIt->more() ) {