X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FControls%2FSMESH_Controls.cxx;h=faaf3dac179fc12da09395e7fc92f6e2f5cfead6;hp=f18cadd34e8b27efae988682a905489a7b505afc;hb=499f29d24922cec66e41b41a0039a954993bc6df;hpb=6d32f944a0a115b6419184c50b57bf7c4eef5786 diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index f18cadd34..faaf3dac1 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2022 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 @@ -34,7 +34,9 @@ #include "SMESHDS_Mesh.hxx" #include "SMESH_MeshAlgos.hxx" #include "SMESH_OctreeNode.hxx" +#include "SMESH_Comment.hxx" +#include #include #include @@ -126,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; @@ -142,13 +144,13 @@ namespace { // Case 1 Case 2 // | | | | | // | | | | | - // +-----+------+ +-----+------+ + // +-----+------+ +-----+------+ // | | | | // | | | | // result should be 2 in both cases // int aResult0 = 0, aResult1 = 0; - // last node, it is a medium one in a quadratic edge + // last node, it is a medium one in a quadratic edge const SMDS_MeshNode* aLastNode = anEdge->GetNode( anEdge->NbNodes() - 1 ); const SMDS_MeshNode* aNode0 = anEdge->GetNode( 0 ); const SMDS_MeshNode* aNode1 = anEdge->GetNode( 1 ); @@ -224,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(); @@ -321,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 || @@ -345,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 )); } @@ -491,7 +493,7 @@ double MaxElementLength2D::GetValue( const TSequenceOfXYZ& P ) // } // } // { // polygons - + // } if( myPrecision >= 0 ) @@ -765,19 +767,9 @@ double AspectRatio::GetValue( long theId ) { double aVal = 0; myCurrElement = myMesh->FindElement( theId ); - if ( myCurrElement && myCurrElement->GetVtkType() == VTK_QUAD ) - { - // issue 21723 - vtkUnstructuredGrid* grid = const_cast( myMesh )->GetGrid(); - if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->GetVtkID() )) - aVal = Round( vtkMeshQuality::QuadAspectRatio( avtkCell )); - } - else - { - TSequenceOfXYZ P; - if ( GetPoints( myCurrElement, P )) - aVal = Round( GetValue( P )); - } + TSequenceOfXYZ P; + if ( GetPoints( myCurrElement, P )) + aVal = Round( GetValue( P )); return aVal; } @@ -850,7 +842,7 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P ) // // alpha = sqrt( 1/32 ) // L = max( L1, L2, L3, L4, D1, D2 ) - // C1 = sqrt( ( L1^2 + L1^2 + L1^2 + L1^2 ) / 4 ) + // C1 = sqrt( L1^2 + L1^2 + L1^2 + L1^2 ) // C2 = min( S1, S2, S3, S4 ) // Li - lengths of the edges // Di - lengths of the diagonals @@ -861,10 +853,10 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P ) Max( aLen[ 2 ], Max( aLen[ 3 ], Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) ); - double C1 = sqrt( ( aLen[0] * aLen[0] + - aLen[1] * aLen[1] + - aLen[2] * aLen[2] + - aLen[3] * aLen[3] ) / 4. ); + double C1 = sqrt( aLen[0] * aLen[0] + + aLen[1] * aLen[1] + + aLen[2] * aLen[2] + + aLen[3] * aLen[3] ); double C2 = Min( anArea[ 0 ], Min( anArea[ 1 ], Min( anArea[ 2 ], anArea[ 3 ] ) ) ); @@ -894,24 +886,24 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P ) // // alpha = sqrt( 1/32 ) // L = max( L1, L2, L3, L4, D1, D2 ) - // C1 = sqrt( ( L1^2 + L1^2 + L1^2 + L1^2 ) / 4 ) + // C1 = sqrt( L1^2 + L1^2 + L1^2 + L1^2 ) // C2 = min( S1, S2, S3, S4 ) // Li - lengths of the edges // Di - lengths of the diagonals // Si - areas of the triangles const double alpha = sqrt( 1 / 32. ); double L = Max( aLen[ 0 ], - Max( aLen[ 1 ], - Max( aLen[ 2 ], - Max( aLen[ 3 ], - Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) ); - double C1 = sqrt( ( aLen[0] * aLen[0] + - aLen[1] * aLen[1] + - aLen[2] * aLen[2] + - aLen[3] * aLen[3] ) / 4. ); + Max( aLen[ 1 ], + Max( aLen[ 2 ], + Max( aLen[ 3 ], + Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) ); + double C1 = sqrt( aLen[0] * aLen[0] + + aLen[1] * aLen[1] + + aLen[2] * aLen[2] + + aLen[3] * aLen[3] ); double C2 = Min( anArea[ 0 ], - Min( anArea[ 1 ], - Min( anArea[ 2 ], anArea[ 3 ] ) ) ); + Min( anArea[ 1 ], + Min( anArea[ 2 ], anArea[ 3 ] ) ) ); if ( C2 <= theEps ) return theInf; return alpha * L * C1 / C2; @@ -1006,6 +998,102 @@ namespace{ return aHeight; } + //================================================================================ + /*! + * \brief Standard quality of a tetrahedron but not normalized + */ + //================================================================================ + + double tetQualityByHomardMethod( const gp_XYZ & p1, + const gp_XYZ & p2, + const gp_XYZ & p3, + const gp_XYZ & p4 ) + { + gp_XYZ edgeVec[6]; + edgeVec[0] = ( p1 - p2 ); + edgeVec[1] = ( p2 - p3 ); + edgeVec[2] = ( p3 - p1 ); + edgeVec[3] = ( p4 - p1 ); + edgeVec[4] = ( p4 - p2 ); + edgeVec[5] = ( p4 - p3 ); + + double maxEdgeLen2 = edgeVec[0].SquareModulus(); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[1].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[2].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[3].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[4].SquareModulus() ); + maxEdgeLen2 = Max( maxEdgeLen2, edgeVec[5].SquareModulus() ); + double maxEdgeLen = Sqrt( maxEdgeLen2 ); + + gp_XYZ cross01 = edgeVec[0] ^ edgeVec[1]; + double sumArea = ( cross01 ).Modulus(); // actually double area + sumArea += ( edgeVec[0] ^ edgeVec[3] ).Modulus(); + sumArea += ( edgeVec[1] ^ edgeVec[4] ).Modulus(); + sumArea += ( edgeVec[2] ^ edgeVec[5] ).Modulus(); + + double sixVolume = Abs( cross01 * edgeVec[4] ); // 6 * volume + double quality = maxEdgeLen * sumArea / sixVolume; // not normalized!!! + return quality; + } + + //================================================================================ + /*! + * \brief HOMARD method of hexahedron quality + * 1. Decompose the hexa into 24 tetra: each face is splitted into 4 triangles by + * adding the diagonals and every triangle is connected to the center of the hexa. + * 2. Compute the quality of every tetra with the same formula as for the standard quality, + * except that the factor for the normalization is not the same because the final goal + * is to have a quality equal to 1 for a perfect cube. So the formula is: + * qual = max(lengthes of 6 edges) * (sum of surfaces of 4 faces) / (7.6569*6*volume) + * 3. The quality of the hexa is the highest value of the qualities of the 24 tetra + */ + //================================================================================ + + double hexQualityByHomardMethod( const TSequenceOfXYZ& P ) + { + gp_XYZ quadCenter[6]; + quadCenter[0] = ( P(1) + P(2) + P(3) + P(4) ) / 4.; + quadCenter[1] = ( P(5) + P(6) + P(7) + P(8) ) / 4.; + quadCenter[2] = ( P(1) + P(2) + P(6) + P(5) ) / 4.; + quadCenter[3] = ( P(2) + P(3) + P(7) + P(6) ) / 4.; + quadCenter[4] = ( P(3) + P(4) + P(8) + P(7) ) / 4.; + quadCenter[5] = ( P(1) + P(4) + P(8) + P(5) ) / 4.; + + gp_XYZ hexCenter = ( P(1) + P(2) + P(3) + P(4) + P(5) + P(6) + P(7) + P(8) ) / 8.; + + // quad 1 ( 1 2 3 4 ) + double quality = tetQualityByHomardMethod( P(1), P(2), quadCenter[0], hexCenter ); + quality = Max( quality, tetQualityByHomardMethod( P(2), P(3), quadCenter[0], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(3), P(4), quadCenter[0], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(4), P(1), quadCenter[0], hexCenter )); + // quad 2 ( 5 6 7 8 ) + quality = Max( quality, tetQualityByHomardMethod( P(5), P(6), quadCenter[1], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(6), P(7), quadCenter[1], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(7), P(8), quadCenter[1], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(8), P(5), quadCenter[1], hexCenter )); + // quad 3 ( 1 2 6 5 ) + quality = Max( quality, tetQualityByHomardMethod( P(1), P(2), quadCenter[2], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(2), P(6), quadCenter[2], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(6), P(5), quadCenter[2], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(5), P(1), quadCenter[2], hexCenter )); + // quad 4 ( 2 3 7 6 ) + quality = Max( quality, tetQualityByHomardMethod( P(2), P(3), quadCenter[3], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(3), P(7), quadCenter[3], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(7), P(6), quadCenter[3], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(6), P(2), quadCenter[3], hexCenter )); + // quad 5 ( 3 4 8 7 ) + quality = Max( quality, tetQualityByHomardMethod( P(3), P(4), quadCenter[4], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(4), P(8), quadCenter[4], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(8), P(7), quadCenter[4], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(7), P(3), quadCenter[4], hexCenter )); + // quad 6 ( 1 4 8 5 ) + quality = Max( quality, tetQualityByHomardMethod( P(1), P(4), quadCenter[5], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(4), P(8), quadCenter[5], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(8), P(5), quadCenter[5], hexCenter )); + quality = Max( quality, tetQualityByHomardMethod( P(5), P(1), quadCenter[5], hexCenter )); + + return quality / 7.65685424949; + } } double AspectRatio3D::GetValue( long theId ) @@ -1091,7 +1179,7 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P ) case 5:{ { gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 3 ),P( 5 )}; - aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality); + aQuality = GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])); } { gp_XYZ aXYZ[4] = {P( 1 ),P( 3 ),P( 4 ),P( 5 )}; @@ -1110,7 +1198,7 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P ) case 6:{ { gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 4 ),P( 6 )}; - aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality); + aQuality = GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])); } { gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 4 ),P( 3 )}; @@ -1135,9 +1223,13 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P ) break; } case 8:{ + + return hexQualityByHomardMethod( P ); // bos #23982 + + { gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 3 )}; - aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])),aQuality); + aQuality = GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[4])); } { gp_XYZ aXYZ[4] = {P( 1 ),P( 2 ),P( 5 ),P( 4 )}; @@ -1272,7 +1364,7 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P ) case 12: { gp_XYZ aXYZ[8] = {P( 1 ),P( 2 ),P( 4 ),P( 5 ),P( 7 ),P( 8 ),P( 10 ),P( 11 )}; - aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[8])),aQuality); + aQuality = GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[8])); } { gp_XYZ aXYZ[8] = {P( 2 ),P( 3 ),P( 5 ),P( 6 ),P( 8 ),P( 9 ),P( 11 ),P( 12 )}; @@ -1880,7 +1972,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; @@ -1917,7 +2009,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; @@ -1932,7 +2024,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 ); @@ -2054,7 +2146,7 @@ double Deflection2D::GetBadRate( double Value, int /*nbNodes*/ ) const */ //================================================================================ -double MultiConnection::GetValue( const TSequenceOfXYZ& P ) +double MultiConnection::GetValue( const TSequenceOfXYZ& /*P*/ ) { return 0; } @@ -2081,7 +2173,7 @@ SMDSAbs_ElementType MultiConnection::GetType() const */ //================================================================================ -double MultiConnection2D::GetValue( const TSequenceOfXYZ& P ) +double MultiConnection2D::GetValue( const TSequenceOfXYZ& /*P*/ ) { return 0; } @@ -2101,7 +2193,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; @@ -2123,7 +2215,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)) { @@ -2286,7 +2378,19 @@ bool BadOrientedVolume::IsSatisfy( long theId ) return false; SMDS_VolumeTool vTool( myMesh->FindElement( theId )); - return !vTool.IsForward(); + + bool isOk = true; + if ( vTool.IsPoly() ) + { + isOk = true; + for ( int i = 0; i < vTool.NbFaces() && isOk; ++i ) + isOk = vTool.IsFaceExternal( i ); + } + else + { + isOk = vTool.IsForward(); + } + return !isOk; } SMDSAbs_ElementType BadOrientedVolume::GetType() const @@ -2365,16 +2469,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; } @@ -2387,29 +2497,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; } @@ -2436,6 +2536,15 @@ SMDSAbs_ElementType CoincidentNodes::GetType() const return SMDSAbs_Node; } +void CoincidentNodes::SetTolerance( const double theToler ) +{ + if ( myToler != theToler ) + { + SetMesh(0); + myToler = theToler; + } +} + void CoincidentNodes::SetMesh( const SMDS_Mesh* theMesh ) { myMeshModifTracer.SetMesh( theMesh ); @@ -2563,20 +2672,16 @@ 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 ) { - TColStd_MapOfInteger aMap; - for ( int i = 0; i < 2; i++ ) + SMDS_ElemIteratorPtr anElemIter = theNodes[ 0 ]->GetInverseElementIterator(SMDSAbs_Face); + while( anElemIter->more() ) { - SMDS_ElemIteratorPtr anElemIter = theNodes[ i ]->GetInverseElementIterator(SMDSAbs_Face); - while( anElemIter->more() ) + if ( const SMDS_MeshElement* anElem = anElemIter->next()) { - if ( const SMDS_MeshElement* anElem = anElemIter->next()) - { - const int anId = anElem->GetID(); - if ( anId != theFaceId && !aMap.Add( anId )) - return false; - } + const smIdType anId = anElem->GetID(); + if ( anId != theFaceId && anElem->GetNodeIndex( theNodes[1] ) >= 0 ) + return false; } } return true; @@ -2738,14 +2843,14 @@ bool FreeFaces::IsSatisfy( long theId ) SMDS_MeshElement* aVol = (SMDS_MeshElement*)volItr->next(); TItrMapOfVolume itr = mapOfVol.insert( std::make_pair( aVol, 0 )).first; (*itr).second++; - } + } } int nbVol = 0; TItrMapOfVolume volItr = mapOfVol.begin(); TItrMapOfVolume volEnd = mapOfVol.end(); for ( ; volItr != volEnd; ++volItr ) if ( (*volItr).second >= nbNode ) - nbVol++; + nbVol++; // face is not free if number of volumes constructed on their nodes more than one return (nbVol < 2); } @@ -2859,8 +2964,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) ); } } @@ -3011,7 +3116,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 @@ -3038,7 +3143,7 @@ void ConnectedElements::SetMesh( const SMDS_Mesh* theMesh ) } } -void ConnectedElements::SetNode( int nodeID ) +void ConnectedElements::SetNode( smIdType nodeID ) { myNodeID = nodeID; myXYZ.clear(); @@ -3098,7 +3203,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: @@ -3123,7 +3228,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 ); } } @@ -3154,7 +3259,7 @@ namespace double dot = v1 * v2; // cos * |v1| * |v2| double l1 = v1.SquareMagnitude(); double l2 = v2.SquareMagnitude(); - return (( dot * cos >= 0 ) && + return (( dot * cos >= 0 ) && ( dot * dot ) / l1 / l2 >= ( cos * cos )); } } @@ -3270,56 +3375,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; } } @@ -3327,13 +3432,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(); } //======================================================================= @@ -3343,8 +3449,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; @@ -3382,8 +3488,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() ); } } @@ -3432,8 +3538,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; @@ -3809,7 +3915,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 @@ -3822,18 +3928,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 ); } @@ -3869,7 +3975,7 @@ bool ManifoldPart::findConnected ( const ManifoldPart::TDataMapFacePtrInt& theAllFacePtrInt, SMDS_MeshFace* theStartFace, ManifoldPart::TMapOfLink& theNonManifold, - TColStd_MapOfInteger& theResFaces ) + TIDsMap& theResFaces ) { theResFaces.Clear(); if ( !theAllFacePtrInt.size() ) @@ -3937,7 +4043,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; @@ -4168,7 +4274,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(); ) @@ -4235,18 +4343,20 @@ 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 ); } TopAbs_ShapeEnum ShapeType() const { return myShape.ShapeType(); } const TopoDS_Shape& Shape() const { return myShape; } const Bnd_B3d* GetBndBox() const { return & myBox; } + double Tolerance() const { return myTol; } bool IsChecked() { return myFlags & theIsCheckedFlag; } bool IsSetFlag( int flag ) const { return myFlags & flag; } 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); @@ -4254,16 +4364,20 @@ private: bool isOutOfFace (const gp_Pnt& p); bool isOutOfEdge (const gp_Pnt& p); bool isOutOfVertex(const gp_Pnt& p); + bool isOutOfNone (const gp_Pnt& /*p*/) { return true; } bool isBox (const TopoDS_Shape& s); + 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; }; @@ -4275,6 +4389,8 @@ struct ElementsOnShape::OctreeClassifier : public SMESH_Octree std::vector< ElementsOnShape::Classifier >& cls ); void GetClassifiersAtPoint( const gp_XYZ& p, std::vector< ElementsOnShape::Classifier* >& classifiers ); + size_t GetSize(); + protected: OctreeClassifier() {} SMESH_Octree* newChild() const { return new OctreeClassifier; } @@ -4300,6 +4416,21 @@ ElementsOnShape::~ElementsOnShape() Predicate* ElementsOnShape::clone() const { + size_t size = sizeof( *this ); + if ( myOctree ) + size += myOctree->GetSize(); + if ( !myClassifiers.empty() ) + size += sizeof( myClassifiers[0] ) * myClassifiers.size(); + if ( !myWorkClassifiers.empty() ) + size += sizeof( myWorkClassifiers[0] ) * myWorkClassifiers.size(); + if ( size > 1e+9 ) // 1G + { +#ifdef _DEBUG_ + std::cout << "Avoid ElementsOnShape::clone(), too large: " << size << " bytes " << std::endl; +#endif + return 0; + } + ElementsOnShape* cln = new ElementsOnShape(); cln->SetAllNodes ( myAllNodesFlag ); cln->SetTolerance( myToler ); @@ -4324,9 +4455,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 ); } } @@ -4456,12 +4590,13 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshElement* elem) for ( size_t i = 0; i < myClassifiers.size(); ++i ) myWorkClassifiers[ i ] = & myClassifiers[ i ]; myOctree = new OctreeClassifier( myWorkClassifiers ); + + SMESHUtils::FreeVector( myWorkClassifiers ); } - SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator(); - while (aNodeItr->more() && (isSatisfy == myAllNodesFlag)) + for ( int i = 0, nb = elem->NbNodes(); i < nb && (isSatisfy == myAllNodesFlag); ++i ) { - SMESH_TNodeXYZ aPnt( aNodeItr->next() ); + SMESH_TNodeXYZ aPnt( elem->GetNode( i )); centerXYZ += aPnt; isNodeOut = true; @@ -4497,11 +4632,17 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshElement* elem) centerXYZ /= elem->NbNodes(); isSatisfy = false; if ( myOctree ) + { + myWorkClassifiers.clear(); + myOctree->GetClassifiersAtPoint( centerXYZ, myWorkClassifiers ); for ( size_t i = 0; i < myWorkClassifiers.size() && !isSatisfy; ++i ) isSatisfy = ! myWorkClassifiers[i]->IsOut( centerXYZ ); + } else + { for ( size_t i = 0; i < myClassifiers.size() && !isSatisfy; ++i ) isSatisfy = ! myClassifiers[i].IsOut( centerXYZ ); + } } return isSatisfy; @@ -4547,6 +4688,7 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshNode* node, isNodeOut = false; if ( okShape ) *okShape = myWorkClassifiers[i]->Shape(); + myWorkClassifiers[i]->GetParams( myU, myV ); break; } } @@ -4557,7 +4699,8 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshNode* node, { isNodeOut = false; if ( okShape ) - *okShape = myWorkClassifiers[i]->Shape(); + *okShape = myClassifiers[i].Shape(); + myClassifiers[i].GetParams( myU, myV ); break; } } @@ -4586,7 +4729,7 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape, } else { - mySolidClfr = new BRepClass3d_SolidClassifier(theShape); + mySolidClfr = new BRepClass3d_SolidClassifier( prepareSolid( theShape )); myIsOutFun = & ElementsOnShape::Classifier::isOutOfSolid; } break; @@ -4595,17 +4738,29 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape, { Standard_Real u1,u2,v1,v2; Handle(Geom_Surface) surf = BRep_Tool::Surface( TopoDS::Face( theShape )); - surf->Bounds( u1,u2,v1,v2 ); - myProjFace.Init(surf, u1,u2, v1,v2, myTol ); - myIsOutFun = & ElementsOnShape::Classifier::isOutOfFace; + if ( surf.IsNull() ) + myIsOutFun = & ElementsOnShape::Classifier::isOutOfNone; + else + { + surf->Bounds( u1,u2,v1,v2 ); + myProjFace = new GeomAPI_ProjectPointOnSurf; + myProjFace->Init( surf, u1,u2, v1,v2, myTol ); + myIsOutFun = & ElementsOnShape::Classifier::isOutOfFace; + } break; } case TopAbs_EDGE: { Standard_Real u1, u2; Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( theShape ), u1, u2); - myProjEdge.Init(curve, u1, u2); - myIsOutFun = & ElementsOnShape::Classifier::isOutOfEdge; + if ( curve.IsNull() ) + myIsOutFun = & ElementsOnShape::Classifier::isOutOfNone; + else + { + myProjEdge = new GeomAPI_ProjectPointOnCurve; + myProjEdge->Init( curve, u1, u2 ); + myIsOutFun = & ElementsOnShape::Classifier::isOutOfEdge; + } break; } case TopAbs_VERTEX: @@ -4627,7 +4782,15 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape, else { Bnd_Box box; - BRepBndLib::Add( myShape, box ); + if ( myShape.ShapeType() == TopAbs_FACE ) + { + BRepAdaptor_Surface SA( TopoDS::Face( myShape ), /*useBoundaries=*/false ); + if ( SA.GetType() == GeomAbs_BSplineSurface ) + BRepBndLib::AddOptimal( myShape, box, + /*useTriangulation=*/true, /*useShapeTolerance=*/true ); + } + if ( box.IsVoid() ) + BRepBndLib::Add( myShape, box ); myBox.Clear(); myBox.Add( box.CornerMin() ); myBox.Add( box.CornerMax() ); @@ -4645,30 +4808,50 @@ 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 ) +{ + // try to limit tolerance of theSolid down to myTol (issue #19026) + + // check if tolerance of theSolid is more than myTol + bool tolIsOk = true; // max tolerance is at VERTEXes + for ( TopExp_Explorer exp( theSolid, TopAbs_VERTEX ); exp.More() && tolIsOk; exp.Next() ) + tolIsOk = ( myTol >= BRep_Tool::Tolerance( TopoDS::Vertex( exp.Current() ))); + if ( tolIsOk ) + return theSolid; + + // make a copy to prevent the original shape from changes + TopoDS_Shape resultShape = BRepBuilderAPI_Copy( theSolid ); + + if ( !GEOMUtils::FixShapeTolerance( resultShape, TopAbs_SHAPE, myTol )) + return theSolid; + return resultShape; } -bool ElementsOnShape::Classifier::isOutOfSolid (const gp_Pnt& p) +bool ElementsOnShape::Classifier::isOutOfSolid( const gp_Pnt& p ) { if ( isOutOfBox( p )) return true; mySolidClfr->Perform( p, myTol ); return ( mySolidClfr->State() != TopAbs_IN && mySolidClfr->State() != TopAbs_ON ); } -bool ElementsOnShape::Classifier::isOutOfBox (const gp_Pnt& p) +bool ElementsOnShape::Classifier::isOutOfBox( const gp_Pnt& p ) { return myBox.IsOut( p.XYZ() ); } -bool ElementsOnShape::Classifier::isOutOfFace (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; @@ -4676,19 +4859,22 @@ bool ElementsOnShape::Classifier::isOutOfFace (const gp_Pnt& p) return true; } -bool ElementsOnShape::Classifier::isOutOfEdge (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) +bool ElementsOnShape::Classifier::isOutOfVertex( const gp_Pnt& p ) { return ( myVertexXYZ.Distance( p ) > myTol ); } -bool ElementsOnShape::Classifier::isBox (const TopoDS_Shape& theShape) +bool ElementsOnShape::Classifier::isBox(const TopoDS_Shape& theShape ) { TopTools_IndexedMapOfShape vMap; TopExp::MapShapes( theShape, TopAbs_VERTEX, vMap ); @@ -4770,6 +4956,19 @@ OctreeClassifier::GetClassifiersAtPoint( const gp_XYZ& point, } } +size_t ElementsOnShape::OctreeClassifier::GetSize() +{ + size_t res = sizeof( *this ); + if ( !myClassifiers.empty() ) + res += sizeof( myClassifiers[0] ) * myClassifiers.size(); + + if ( !isLeaf() ) + for (int i = 0; i < nbChildren(); i++) + res += ((OctreeClassifier*) myChildren[i])->GetSize(); + + return res; +} + void ElementsOnShape::OctreeClassifier::buildChildrenData() { // distribute myClassifiers among myChildren @@ -4816,7 +5015,8 @@ void ElementsOnShape::OctreeClassifier::buildChildrenData() for ( int i = 0; i < nbChildren(); i++ ) { OctreeClassifier* child = static_cast( myChildren[ i ]); - child->myIsLeaf = ( child->myClassifiers.size() <= 5 ); + child->myIsLeaf = ( child->myClassifiers.size() <= 5 || + child->maxSize() < child->myClassifiers[0]->Tolerance() ); } } @@ -4843,8 +5043,13 @@ BelongToGeom::BelongToGeom() Predicate* BelongToGeom::clone() const { - BelongToGeom* cln = new BelongToGeom( *this ); - cln->myElementsOnShapePtr.reset( static_cast( myElementsOnShapePtr->clone() )); + BelongToGeom* cln = 0; + if ( myElementsOnShapePtr ) + if ( ElementsOnShape* eos = static_cast( myElementsOnShapePtr->clone() )) + { + cln = new BelongToGeom( *this ); + cln->myElementsOnShapePtr.reset( eos ); + } return cln; } @@ -4855,6 +5060,8 @@ void BelongToGeom::SetMesh( const SMDS_Mesh* theMesh ) myMeshDS = dynamic_cast(theMesh); init(); } + if ( myElementsOnShapePtr ) + myElementsOnShapePtr->SetMesh( myMeshDS ); } void BelongToGeom::SetGeom( const TopoDS_Shape& theShape ) @@ -5014,8 +5221,13 @@ LyingOnGeom::LyingOnGeom() Predicate* LyingOnGeom::clone() const { - LyingOnGeom* cln = new LyingOnGeom( *this ); - cln->myElementsOnShapePtr.reset( static_cast( myElementsOnShapePtr->clone() )); + LyingOnGeom* cln = 0; + if ( myElementsOnShapePtr ) + if ( ElementsOnShape* eos = static_cast( myElementsOnShapePtr->clone() )) + { + cln = new LyingOnGeom( *this ); + cln->myElementsOnShapePtr.reset( eos ); + } return cln; } @@ -5026,6 +5238,8 @@ void LyingOnGeom::SetMesh( const SMDS_Mesh* theMesh ) myMeshDS = dynamic_cast(theMesh); init(); } + if ( myElementsOnShapePtr ) + myElementsOnShapePtr->SetMesh( myMeshDS ); } void LyingOnGeom::SetGeom( const TopoDS_Shape& theShape )