X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FControls%2FSMESH_Controls.cxx;h=0474d7a57c31299632904359f51441550daea167;hp=1ef3a5f2f4018efa8b7c14ca2454928338ecaa43;hb=HEAD;hpb=b24a2d1b7692bdb21cf037b026e0273ba547cef4 diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 1ef3a5f2f..578557775 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -34,6 +34,7 @@ #include "SMESHDS_Mesh.hxx" #include "SMESH_MeshAlgos.hxx" #include "SMESH_OctreeNode.hxx" +#include "SMESH_Comment.hxx" #include #include @@ -127,7 +128,7 @@ namespace { return aDist; } - int getNbMultiConnection( const SMDS_Mesh* theMesh, const int theId ) + int getNbMultiConnection( const SMDS_Mesh* theMesh, const smIdType theId ) { if ( theMesh == 0 ) return 0; @@ -225,7 +226,7 @@ void NumericalFunctor::SetMesh( const SMDS_Mesh* theMesh ) myMesh = theMesh; } -bool NumericalFunctor::GetPoints(const int theId, +bool NumericalFunctor::GetPoints(const smIdType theId, TSequenceOfXYZ& theRes ) const { theRes.clear(); @@ -322,12 +323,12 @@ bool NumericalFunctor::IsApplicable( long theElementId ) const */ //================================================================================ -void NumericalFunctor::GetHistogram(int nbIntervals, - std::vector& nbEvents, - std::vector& funValues, - const std::vector& elements, - const double* minmax, - const bool isLogarithmic) +void NumericalFunctor::GetHistogram(int nbIntervals, + std::vector& nbEvents, + std::vector& funValues, + const std::vector& elements, + const double* minmax, + const bool isLogarithmic) { if ( nbIntervals < 1 || !myMesh || @@ -346,7 +347,7 @@ void NumericalFunctor::GetHistogram(int nbIntervals, } else { - std::vector::const_iterator id = elements.begin(); + std::vector::const_iterator id = elements.begin(); for ( ; id != elements.end(); ++id ) values.insert( GetValue( *id )); } @@ -1422,21 +1423,7 @@ bool Warping::IsApplicable( const SMDS_MeshElement* element ) const double Warping::GetValue( const TSequenceOfXYZ& P ) { - if ( P.size() != 4 ) - return 0; - - gp_XYZ G = ( P( 1 ) + P( 2 ) + P( 3 ) + P( 4 ) ) / 4.; - - double A1 = ComputeA( P( 1 ), P( 2 ), P( 3 ), G ); - double A2 = ComputeA( P( 2 ), P( 3 ), P( 4 ), G ); - double A3 = ComputeA( P( 3 ), P( 4 ), P( 1 ), G ); - double A4 = ComputeA( P( 4 ), P( 1 ), P( 2 ), G ); - - double val = Max( Max( A1, A2 ), Max( A3, A4 ) ); - - const double eps = 0.1; // val is in degrees - - return val < eps ? 0. : val; + return ComputeValue(P); } double Warping::ComputeA( const gp_XYZ& thePnt1, @@ -1463,6 +1450,25 @@ double Warping::ComputeA( const gp_XYZ& thePnt1, return asin( fabs( H / L ) ) * 180. / M_PI; } +double Warping::ComputeValue(const TSequenceOfXYZ& thePoints) const +{ + if (thePoints.size() != 4) + return 0; + + gp_XYZ G = (thePoints(1) + thePoints(2) + thePoints(3) + thePoints(4)) / 4.; + + double A1 = ComputeA(thePoints(1), thePoints(2), thePoints(3), G); + double A2 = ComputeA(thePoints(2), thePoints(3), thePoints(4), G); + double A3 = ComputeA(thePoints(3), thePoints(4), thePoints(1), G); + double A4 = ComputeA(thePoints(4), thePoints(1), thePoints(2), G); + + double val = Max(Max(A1, A2), Max(A3, A4)); + + const double eps = 0.1; // val is in degrees + + return val < eps ? 0. : val; +} + double Warping::GetBadRate( double Value, int /*nbNodes*/ ) const { // the warp is in the range [0.0,PI/2] @@ -1477,6 +1483,93 @@ SMDSAbs_ElementType Warping::GetType() const } +//================================================================================ +/* + Class : Warping3D + Description : Functor for calculating warping +*/ +//================================================================================ + +bool Warping3D::IsApplicable(const SMDS_MeshElement* element) const +{ + return NumericalFunctor::IsApplicable(element);//&& element->NbNodes() == 4; +} + +double Warping3D::GetValue(long theId) +{ + double aVal = 0; + myCurrElement = myMesh->FindElement(theId); + if (myCurrElement) + { + WValues aValues; + ProcessVolumeELement(aValues); + for (const auto& aValue: aValues) + { + aVal = Max(aVal, aValue.myWarp); + } + } + return aVal; +} + +double Warping3D::GetValue(const TSequenceOfXYZ& P) +{ + return ComputeValue(P); +} + +SMDSAbs_ElementType Warping3D::GetType() const +{ + return SMDSAbs_Volume; +} + +bool Warping3D::Value::operator<(const Warping3D::Value& x) const +{ + if (myPntIds.size() != x.myPntIds.size()) + return myPntIds.size() < x.myPntIds.size(); + + for (int anInd = 0; anInd < myPntIds.size(); ++anInd) + if (myPntIds[anInd] != x.myPntIds[anInd]) + return myPntIds[anInd] != x.myPntIds[anInd]; + + return false; +} + +// Compute value on each face of volume +void Warping3D::ProcessVolumeELement(WValues& theValues) +{ + SMDS_VolumeTool aVTool(myCurrElement); + double aCoord[3]; + for (int aFaceID = 0; aFaceID < aVTool.NbFaces(); ++aFaceID) + { + TSequenceOfXYZ aPoints; + std::set aNodes; + std::vector aNodeIds; + const SMDS_MeshNode** aNodesPtr = aVTool.GetFaceNodes(aFaceID); + + if (aNodesPtr) + { + for (int i = 0; i < aVTool.NbFaceNodes(aFaceID); ++i) + { + aNodesPtr[i]->GetXYZ(aCoord); + aPoints.push_back(gp_XYZ{ aCoord[0], aCoord[1], aCoord[2] }); + aNodeIds.push_back(aNodesPtr[i]->GetID()); + } + double aWarp = GetValue(aPoints); + Value aVal{ aWarp, aNodeIds }; + + theValues.push_back(aVal); + } + } +} + +void Warping3D::GetValues(WValues& theValues) +{ + for (SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator(); anIter->more(); ) + { + myCurrElement = anIter->next(); + ProcessVolumeELement(theValues); + } +} + //================================================================================ /* Class : Taper @@ -1971,7 +2064,7 @@ void Length2D::GetValues(TValues& theValues) { // use special nodes iterator SMDS_NodeIteratorPtr anIter = anElem->interlacedNodesIterator(); - long aNodeId[4] = { 0,0,0,0 }; + smIdType aNodeId[4] = { 0,0,0,0 }; gp_Pnt P[4]; double aLength = 0; @@ -2008,7 +2101,7 @@ void Length2D::GetValues(TValues& theValues) } else { SMDS_NodeIteratorPtr aNodesIter = anElem->nodeIterator(); - long aNodeId[2] = {0,0}; + smIdType aNodeId[2] = {0,0}; gp_Pnt P[3]; double aLength; @@ -2023,7 +2116,7 @@ void Length2D::GetValues(TValues& theValues) for( ; aNodesIter->more(); ) { aNode = aNodesIter->next(); - long anId = aNode->GetID(); + smIdType anId = aNode->GetID(); P[2] = SMESH_NodeXYZ( aNode ); @@ -2192,7 +2285,7 @@ double MultiConnection2D::GetValue( long theElementId ) if (!anIter) break; const SMDS_MeshNode *aNode, *aNode0 = 0; - TColStd_MapOfInteger aMap, aMapPrev; + NCollection_Map< smIdType, smIdHasher > aMap, aMapPrev; for (i = 0; i <= len; i++) { aMapPrev = aMap; @@ -2214,7 +2307,7 @@ double MultiConnection2D::GetValue( long theElementId ) while (anElemIter->more()) { const SMDS_MeshElement* anElem = anElemIter->next(); if (anElem != 0 && anElem->GetType() == SMDSAbs_Face) { - int anId = anElem->GetID(); + smIdType anId = anElem->GetID(); aMap.Add(anId); if (aMapPrev.Contains(anId)) { @@ -2350,6 +2443,70 @@ SMDSAbs_ElementType NodeConnectivityNumber::GetType() const return SMDSAbs_Node; } +//================================================================================ +/* + Class : ScaledJacobian + Description : Functor returning the ScaledJacobian for volumetric elements +*/ +//================================================================================ + +double ScaledJacobian::GetValue( long theElementId ) +{ + if ( theElementId && myMesh ) { + SMDS_VolumeTool aVolumeTool; + if ( aVolumeTool.Set( myMesh->FindElement( theElementId ))) + return aVolumeTool.GetScaledJacobian(); + } + return 0; + + /* + //VTK version not used because lack of implementation for HEXAGONAL_PRISM. + //Several mesh quality measures implemented in vtkMeshQuality can be accessed left here as reference + double aVal = 0; + myCurrElement = myMesh->FindElement( theElementId ); + if ( myCurrElement ) + { + VTKCellType cellType = myCurrElement->GetVtkType(); + vtkUnstructuredGrid* grid = const_cast( myMesh )->GetGrid(); + vtkCell* avtkCell = grid->GetCell( myCurrElement->GetVtkID() ); + switch ( cellType ) + { + case VTK_QUADRATIC_TETRA: + case VTK_TETRA: + aVal = Round( vtkMeshQuality::TetScaledJacobian( avtkCell )); + break; + case VTK_QUADRATIC_HEXAHEDRON: + case VTK_HEXAHEDRON: + aVal = Round( vtkMeshQuality::HexScaledJacobian( avtkCell )); + break; + case VTK_QUADRATIC_WEDGE: + case VTK_WEDGE: //Pentahedron + aVal = Round( vtkMeshQuality::WedgeScaledJacobian( avtkCell )); + break; + case VTK_QUADRATIC_PYRAMID: + case VTK_PYRAMID: + aVal = Round( vtkMeshQuality::PyramidScaledJacobian( avtkCell )); + break; + case VTK_HEXAGONAL_PRISM: + case VTK_POLYHEDRON: + default: + break; + } + } + return aVal; + */ +} + +double ScaledJacobian::GetBadRate( double Value, int /*nbNodes*/ ) const +{ + return Value; +} + +SMDSAbs_ElementType ScaledJacobian::GetType() const +{ + return SMDSAbs_Volume; +} + /* PREDICATES */ @@ -2468,16 +2625,22 @@ bool BareBorderFace::IsSatisfy(long theElementId ) bool OverConstrainedVolume::IsSatisfy(long theElementId ) { - // An element is over-constrained if it has N-1 free borders where - // N is the number of edges/faces for a 2D/3D element. - SMDS_VolumeTool myTool; - if ( myTool.Set( myMesh->FindElement(theElementId))) + // An element is over-constrained if all its nodes are on the boundary. + // A node is on the boundary if it is connected to one or more faces. + SMDS_VolumeTool myTool; + if (myTool.Set(myMesh->FindElement(theElementId))) { - int nbSharedFaces = 0; - for ( int iF = 0; iF < myTool.NbFaces(); ++iF ) - if ( !myTool.IsFreeFace( iF ) && ++nbSharedFaces > 1 ) - break; - return ( nbSharedFaces == 1 ); + auto nodes = myTool.GetNodes(); + + for (int i = 0; i < myTool.NbNodes(); ++i) + { + auto node = nodes[i]; + if (node->NbInverseElements(SMDSAbs_Face) == 0) + { + return false; + } + } + return true; } return false; } @@ -2490,29 +2653,19 @@ bool OverConstrainedVolume::IsSatisfy(long theElementId ) bool OverConstrainedFace::IsSatisfy(long theElementId ) { - // An element is over-constrained if it has N-1 free borders where - // N is the number of edges/faces for a 2D/3D element. - if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId)) - if ( face->GetType() == SMDSAbs_Face ) + // An element is over-constrained if all its nodes are on the boundary. + // A node is on the boundary if it is connected to one or more faces. + if (const SMDS_MeshElement *face = myMesh->FindElement(theElementId)) + if (face->GetType() == SMDSAbs_Face) { - int nbSharedBorders = 0; int nbN = face->NbCornerNodes(); - for ( int i = 0; i < nbN; ++i ) + for (int i = 0; i < nbN; ++i) { - // check if a link is shared by another face - const SMDS_MeshNode* n1 = face->GetNode( i ); - const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN ); - SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face ); - bool isShared = false; - while ( !isShared && fIt->more() ) - { - const SMDS_MeshElement* f = fIt->next(); - isShared = ( f != face && f->GetNodeIndex(n2) != -1 ); - } - if ( isShared && ++nbSharedBorders > 1 ) - break; + const SMDS_MeshNode *n1 = face->GetNode(i); + if (n1->NbInverseElements(SMDSAbs_Edge) == 0) + return false; } - return ( nbSharedBorders == 1 ); + return true; } return false; } @@ -2675,14 +2828,14 @@ void FreeEdges::SetMesh( const SMDS_Mesh* theMesh ) myMesh = theMesh; } -bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const int theFaceId ) +bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const smIdType theFaceId ) { SMDS_ElemIteratorPtr anElemIter = theNodes[ 0 ]->GetInverseElementIterator(SMDSAbs_Face); while( anElemIter->more() ) { if ( const SMDS_MeshElement* anElem = anElemIter->next()) { - const int anId = anElem->GetID(); + const smIdType anId = anElem->GetID(); if ( anId != theFaceId && anElem->GetNodeIndex( theNodes[1] ) >= 0 ) return false; } @@ -2967,8 +3120,8 @@ void GroupColor::SetMesh( const SMDS_Mesh* theMesh ) SMDSAbs_ElementType aGrpElType = (SMDSAbs_ElementType)aGrp->GetType(); if ( myType == aGrpElType || (myType == SMDSAbs_All && aGrpElType != SMDSAbs_Node) ) { // add elements IDS into control - int aSize = aGrp->Extent(); - for (int i = 0; i < aSize; i++) + smIdType aSize = aGrp->Extent(); + for (smIdType i = 0; i < aSize; i++) myIDs.insert( aGrp->GetID(i+1) ); } } @@ -3119,7 +3272,7 @@ ConnectedElements::ConnectedElements(): SMDSAbs_ElementType ConnectedElements::GetType() const { return myType; } -int ConnectedElements::GetNode() const +smIdType ConnectedElements::GetNode() const { return myXYZ.empty() ? myNodeID : 0; } // myNodeID can be found by myXYZ std::vector ConnectedElements::GetPoint() const @@ -3146,7 +3299,7 @@ void ConnectedElements::SetMesh( const SMDS_Mesh* theMesh ) } } -void ConnectedElements::SetNode( int nodeID ) +void ConnectedElements::SetNode( smIdType nodeID ) { myNodeID = nodeID; myXYZ.clear(); @@ -3206,7 +3359,7 @@ bool ConnectedElements::IsSatisfy( long theElementId ) return false; std::list< const SMDS_MeshNode* > nodeQueue( 1, node0 ); - std::set< int > checkedNodeIDs; + std::set< smIdType > checkedNodeIDs; // algo: // foreach node in nodeQueue: // foreach element sharing a node: @@ -3231,7 +3384,7 @@ bool ConnectedElements::IsSatisfy( long theElementId ) while ( nIt->more() ) { const SMDS_MeshNode* n = static_cast< const SMDS_MeshNode* >( nIt->next() ); - if ( checkedNodeIDs.insert( n->GetID() ).second ) + if ( checkedNodeIDs.insert( n->GetID()).second ) nodeQueue.push_back( n ); } } @@ -3378,56 +3531,56 @@ void RangeOfIds::GetRangeStr( TCollection_AsciiString& theResStr ) { theResStr.Clear(); - TColStd_SequenceOfInteger anIntSeq; - TColStd_SequenceOfAsciiString aStrSeq; + TIDsSeq anIntSeq; + NCollection_Sequence< std::string > aStrSeq; - TColStd_MapIteratorOfMapOfInteger anIter( myIds ); + TIDsMap::Iterator anIter( myIds ); for ( ; anIter.More(); anIter.Next() ) { - int anId = anIter.Key(); - TCollection_AsciiString aStr( anId ); + smIdType anId = anIter.Key(); + SMESH_Comment aStr( anId ); anIntSeq.Append( anId ); aStrSeq.Append( aStr ); } - for ( int i = 1, n = myMin.Length(); i <= n; i++ ) + for ( smIdType i = 1, n = myMin.size(); i <= n; i++ ) { - int aMinId = myMin( i ); - int aMaxId = myMax( i ); + smIdType aMinId = myMin[i]; + smIdType aMaxId = myMax[i]; - TCollection_AsciiString aStr; + SMESH_Comment aStr; if ( aMinId != IntegerFirst() ) - aStr += aMinId; + aStr << aMinId; - aStr += "-"; + aStr << "-"; - if ( aMaxId != IntegerLast() ) - aStr += aMaxId; + if ( aMaxId != std::numeric_limits::max() ) + aStr << aMaxId; // find position of the string in result sequence and insert string in it if ( anIntSeq.Length() == 0 ) { anIntSeq.Append( aMinId ); - aStrSeq.Append( aStr ); + aStrSeq.Append( (const char*)aStr ); } else { if ( aMinId < anIntSeq.First() ) { anIntSeq.Prepend( aMinId ); - aStrSeq.Prepend( aStr ); + aStrSeq.Prepend( (const char*)aStr ); } else if ( aMinId > anIntSeq.Last() ) { anIntSeq.Append( aMinId ); - aStrSeq.Append( aStr ); + aStrSeq.Append( (const char*)aStr ); } else for ( int j = 1, k = anIntSeq.Length(); j <= k; j++ ) if ( aMinId < anIntSeq( j ) ) { anIntSeq.InsertBefore( j, aMinId ); - aStrSeq.InsertBefore( j, aStr ); + aStrSeq.InsertBefore( j, (const char*)aStr ); break; } } @@ -3435,13 +3588,14 @@ void RangeOfIds::GetRangeStr( TCollection_AsciiString& theResStr ) if ( aStrSeq.Length() == 0 ) return; - - theResStr = aStrSeq( 1 ); + std::string aResStr; + aResStr = aStrSeq( 1 ); for ( int j = 2, k = aStrSeq.Length(); j <= k; j++ ) { - theResStr += ","; - theResStr += aStrSeq( j ); + aResStr += ","; + aResStr += aStrSeq( j ); } + theResStr = aResStr.c_str(); } //======================================================================= @@ -3451,8 +3605,8 @@ void RangeOfIds::GetRangeStr( TCollection_AsciiString& theResStr ) //======================================================================= bool RangeOfIds::SetRangeStr( const TCollection_AsciiString& theStr ) { - myMin.Clear(); - myMax.Clear(); + myMin.clear(); + myMax.clear(); myIds.Clear(); TCollection_AsciiString aStr = theStr; @@ -3490,8 +3644,8 @@ bool RangeOfIds::SetRangeStr( const TCollection_AsciiString& theStr ) (!aMaxStr.IsEmpty() && !aMaxStr.IsIntegerValue()) ) return false; - myMin.Append( aMinStr.IsEmpty() ? IntegerFirst() : aMinStr.IntegerValue() ); - myMax.Append( aMaxStr.IsEmpty() ? IntegerLast() : aMaxStr.IntegerValue() ); + myMin.push_back( aMinStr.IsEmpty() ? IntegerFirst() : aMinStr.IntegerValue() ); + myMax.push_back( aMaxStr.IsEmpty() ? IntegerLast() : aMaxStr.IntegerValue() ); } } @@ -3540,8 +3694,8 @@ bool RangeOfIds::IsSatisfy( long theId ) if ( myIds.Contains( theId ) ) return true; - for ( int i = 1, n = myMin.Length(); i <= n; i++ ) - if ( theId >= myMin( i ) && theId <= myMax( i ) ) + for ( size_t i = 0; i < myMin.size(); i++ ) + if ( theId >= myMin[i] && theId <= myMax[i] ) return true; return false; @@ -3917,7 +4071,7 @@ bool ManifoldPart::process() // the map of non manifold links and bad geometry TMapOfLink aMapOfNonManifold; - TColStd_MapOfInteger aMapOfTreated; + TIDsMap aMapOfTreated; // begin cycle on faces from start index and run on vector till the end // and from begin to start index to cover whole vector @@ -3930,18 +4084,18 @@ bool ManifoldPart::process() // as result next time when fi will be equal to aStartIndx SMDS_MeshFace* aFacePtr = myAllFacePtr[ fi ]; - if ( aMapOfTreated.Contains( aFacePtr->GetID() ) ) + if ( aMapOfTreated.Contains( aFacePtr->GetID()) ) continue; aMapOfTreated.Add( aFacePtr->GetID() ); - TColStd_MapOfInteger aResFaces; + TIDsMap aResFaces; if ( !findConnected( myAllFacePtrIntDMap, aFacePtr, aMapOfNonManifold, aResFaces ) ) continue; - TColStd_MapIteratorOfMapOfInteger anItr( aResFaces ); + TIDsMap::Iterator anItr( aResFaces ); for ( ; anItr.More(); anItr.Next() ) { - int aFaceId = anItr.Key(); + smIdType aFaceId = anItr.Key(); aMapOfTreated.Add( aFaceId ); myMapIds.Add( aFaceId ); } @@ -3977,7 +4131,7 @@ bool ManifoldPart::findConnected ( const ManifoldPart::TDataMapFacePtrInt& theAllFacePtrInt, SMDS_MeshFace* theStartFace, ManifoldPart::TMapOfLink& theNonManifold, - TColStd_MapOfInteger& theResFaces ) + TIDsMap& theResFaces ) { theResFaces.Clear(); if ( !theAllFacePtrInt.size() ) @@ -4045,7 +4199,7 @@ bool ManifoldPart::findConnected SMDS_MeshFace* aNextFace = *pFace; if ( aPrevFace == aNextFace ) continue; - int anNextFaceID = aNextFace->GetID(); + smIdType anNextFaceID = aNextFace->GetID(); if ( myIsOnlyManifold && theResFaces.Contains( anNextFaceID ) ) // should not be with non manifold restriction. probably bad topology continue; @@ -4276,7 +4430,9 @@ void ElementsOnSurface::process() if ( !myMeshModifTracer.GetMesh() ) return; - myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType )); + int nbElems = FromSmIdType( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType )); + if ( nbElems > 0 ) + myIds.ReSize( nbElems ); SMDS_ElemIteratorPtr anIter = myMeshModifTracer.GetMesh()->elementsIterator( myType ); for(; anIter->more(); ) @@ -4343,7 +4499,7 @@ namespace { struct ElementsOnShape::Classifier { - Classifier() { mySolidClfr = 0; myFlags = 0; } + Classifier(): mySolidClfr(0), myProjFace(0), myProjEdge(0), myFlags(0) { myU = myV = 1e100; } ~Classifier(); void Init(const TopoDS_Shape& s, double tol, const Bnd_B3d* box = 0 ); bool IsOut(const gp_Pnt& p) { return SetChecked( true ), (this->*myIsOutFun)( p ); } @@ -4356,6 +4512,7 @@ struct ElementsOnShape::Classifier void SetChecked( bool is ) { is ? SetFlag( theIsCheckedFlag ) : UnsetFlag( theIsCheckedFlag ); } void SetFlag ( int flag ) { myFlags |= flag; } void UnsetFlag( int flag ) { myFlags &= ~flag; } + void GetParams( double & u, double & v ) const { u = myU; v = myV; } private: bool isOutOfSolid (const gp_Pnt& p); @@ -4369,13 +4526,14 @@ private: TopoDS_Shape prepareSolid( const TopoDS_Shape& theSolid ); bool (Classifier::* myIsOutFun)(const gp_Pnt& p); - BRepClass3d_SolidClassifier* mySolidClfr; // ptr because of a run-time forbidden copy-constructor + BRepClass3d_SolidClassifier* mySolidClfr; Bnd_B3d myBox; - GeomAPI_ProjectPointOnSurf myProjFace; - GeomAPI_ProjectPointOnCurve myProjEdge; + GeomAPI_ProjectPointOnSurf* myProjFace; + GeomAPI_ProjectPointOnCurve* myProjEdge; gp_Pnt myVertexXYZ; TopoDS_Shape myShape; double myTol; + double myU, myV; // result of isOutOfFace() and isOutOfEdge() int myFlags; }; @@ -4423,9 +4581,10 @@ Predicate* ElementsOnShape::clone() const size += sizeof( myWorkClassifiers[0] ) * myWorkClassifiers.size(); if ( size > 1e+9 ) // 1G { -#ifdef _DEBUG_ + + if (SALOME::VerbosityActivated()) std::cout << "Avoid ElementsOnShape::clone(), too large: " << size << " bytes " << std::endl; -#endif + return 0; } @@ -4453,9 +4612,12 @@ SMDSAbs_ElementType ElementsOnShape::GetType() const void ElementsOnShape::SetTolerance (const double theToler) { - if (myToler != theToler) { + if (myToler != theToler) + { myToler = theToler; - SetShape(myShape, myType); + TopoDS_Shape s = myShape; + myShape.Nullify(); + SetShape( s, myType ); } } @@ -4683,6 +4845,7 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshNode* node, isNodeOut = false; if ( okShape ) *okShape = myWorkClassifiers[i]->Shape(); + myWorkClassifiers[i]->GetParams( myU, myV ); break; } } @@ -4694,6 +4857,7 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshNode* node, isNodeOut = false; if ( okShape ) *okShape = myClassifiers[i].Shape(); + myClassifiers[i].GetParams( myU, myV ); break; } } @@ -4736,7 +4900,8 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape, else { surf->Bounds( u1,u2,v1,v2 ); - myProjFace.Init(surf, u1,u2, v1,v2, myTol ); + myProjFace = new GeomAPI_ProjectPointOnSurf; + myProjFace->Init( surf, u1,u2, v1,v2, myTol ); myIsOutFun = & ElementsOnShape::Classifier::isOutOfFace; } break; @@ -4749,7 +4914,8 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape, myIsOutFun = & ElementsOnShape::Classifier::isOutOfNone; else { - myProjEdge.Init(curve, u1, u2); + myProjEdge = new GeomAPI_ProjectPointOnCurve; + myProjEdge->Init( curve, u1, u2 ); myIsOutFun = & ElementsOnShape::Classifier::isOutOfEdge; } break; @@ -4799,6 +4965,8 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape, ElementsOnShape::Classifier::~Classifier() { delete mySolidClfr; mySolidClfr = 0; + delete myProjFace; myProjFace = 0; + delete myProjEdge; myProjEdge = 0; } TopoDS_Shape ElementsOnShape::Classifier::prepareSolid( const TopoDS_Shape& theSolid ) @@ -4835,13 +5003,12 @@ bool ElementsOnShape::Classifier::isOutOfBox( const gp_Pnt& p ) bool ElementsOnShape::Classifier::isOutOfFace( const gp_Pnt& p ) { if ( isOutOfBox( p )) return true; - myProjFace.Perform( p ); - if ( myProjFace.IsDone() && myProjFace.LowerDistance() <= myTol ) + myProjFace->Perform( p ); + if ( myProjFace->IsDone() && myProjFace->LowerDistance() <= myTol ) { // check relatively to the face - Standard_Real u, v; - myProjFace.LowerDistanceParameters(u, v); - gp_Pnt2d aProjPnt (u, v); + myProjFace->LowerDistanceParameters( myU, myV ); + gp_Pnt2d aProjPnt( myU, myV ); BRepClass_FaceClassifier aClsf ( TopoDS::Face( myShape ), aProjPnt, myTol ); if ( aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON ) return false; @@ -4852,8 +5019,11 @@ bool ElementsOnShape::Classifier::isOutOfFace( const gp_Pnt& p ) bool ElementsOnShape::Classifier::isOutOfEdge( const gp_Pnt& p ) { if ( isOutOfBox( p )) return true; - myProjEdge.Perform( p ); - return ! ( myProjEdge.NbPoints() > 0 && myProjEdge.LowerDistance() <= myTol ); + myProjEdge->Perform( p ); + bool isOn = ( myProjEdge->NbPoints() > 0 && myProjEdge->LowerDistance() <= myTol ); + if ( isOn ) + myU = myProjEdge->LowerDistanceParameter(); + return !isOn; } bool ElementsOnShape::Classifier::isOutOfVertex( const gp_Pnt& p )