X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FControls%2FSMESH_Controls.cxx;h=b78c2f0f7a60ae7b3949ca041b21e4bbfcec65f4;hp=f9540e0046d526846c6e05291de07438572c5509;hb=101919845f4f9504b3abad75a027b2938cb11924;hpb=bd4e115a78b52e3fbc016e5e30bb0e19b2a9e7d6 diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index f9540e004..b78c2f0f7 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2013 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 @@ -33,6 +33,7 @@ #include "SMESHDS_GroupBase.hxx" #include "SMESHDS_Mesh.hxx" #include "SMESH_OctreeNode.hxx" +#include "SMESH_MeshAlgos.hxx" #include #include @@ -65,12 +66,16 @@ #include #include +#include /* AUXILIARY METHODS */ -namespace{ +namespace { + + const double theEps = 1e-100; + const double theInf = 1e+100; inline gp_XYZ gpXYZ(const SMDS_MeshNode* aNode ) { @@ -208,10 +213,13 @@ using namespace SMESH::Controls; * FUNCTORS */ +//================================================================================ /* Class : NumericalFunctor Description : Base class for numerical functors */ +//================================================================================ + NumericalFunctor::NumericalFunctor(): myMesh(NULL) { @@ -231,7 +239,11 @@ bool NumericalFunctor::GetPoints(const int theId, if ( myMesh == 0 ) return false; - return GetPoints( myMesh->FindElement( theId ), theRes ); + const SMDS_MeshElement* anElem = myMesh->FindElement( theId ); + if ( !anElem || anElem->GetType() != this->GetType() ) + return false; + + return GetPoints( anElem, theRes ); } bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem, @@ -239,7 +251,7 @@ bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem, { theRes.clear(); - if ( anElem == 0) + if ( anElem == 0 ) return false; theRes.reserve( anElem->NbNodes() ); @@ -320,7 +332,8 @@ void NumericalFunctor::GetHistogram(int nbIntervals, std::vector& nbEvents, std::vector& funValues, const vector& elements, - const double* minmax) + const double* minmax, + const bool isLogarithmic) { if ( nbIntervals < 1 || !myMesh || @@ -373,8 +386,15 @@ void NumericalFunctor::GetHistogram(int nbIntervals, for ( int i = 0; i < nbIntervals; ++i ) { // find end value of i-th interval - double r = (i+1) / double( nbIntervals ); - funValues[i+1] = funValues.front() * (1-r) + funValues.back() * r; + double r = (i+1) / double(nbIntervals); + if (isLogarithmic && funValues.front() > 1e-07 && funValues.back() > 1e-07) { + double logmin = log10(funValues.front()); + double lval = logmin + r * (log10(funValues.back()) - logmin); + funValues[i+1] = pow(10.0, lval); + } + else { + funValues[i+1] = funValues.front() * (1-r) + funValues.back() * r; + } // count values in the i-th interval if there are any if ( min != values.end() && *min <= funValues[i+1] ) @@ -390,9 +410,11 @@ void NumericalFunctor::GetHistogram(int nbIntervals, } //======================================================================= -//function : GetValue -//purpose : -//======================================================================= +/* + Class : Volume + Description : Functor calculating volume of a 3D element +*/ +//================================================================================ double Volume::GetValue( long theElementId ) { @@ -404,86 +426,72 @@ double Volume::GetValue( long theElementId ) return 0; } -//======================================================================= -//function : GetBadRate -//purpose : meaningless as it is not quality control functor -//======================================================================= - double Volume::GetBadRate( double Value, int /*nbNodes*/ ) const { return Value; } -//======================================================================= -//function : GetType -//purpose : -//======================================================================= - SMDSAbs_ElementType Volume::GetType() const { return SMDSAbs_Volume; } - +//======================================================================= /* Class : MaxElementLength2D Description : Functor calculating maximum length of 2D element */ +//================================================================================ -double MaxElementLength2D::GetValue( long theElementId ) +double MaxElementLength2D::GetValue( const TSequenceOfXYZ& P ) { - TSequenceOfXYZ P; - if( GetPoints( theElementId, P ) ) { - double aVal = 0; - const SMDS_MeshElement* aElem = myMesh->FindElement( theElementId ); - SMDSAbs_ElementType aType = aElem->GetType(); - int len = P.size(); - switch( aType ) { - case SMDSAbs_Face: - if( len == 3 ) { // triangles - double L1 = getDistance(P( 1 ),P( 2 )); - double L2 = getDistance(P( 2 ),P( 3 )); - double L3 = getDistance(P( 3 ),P( 1 )); - aVal = Max(L1,Max(L2,L3)); - break; - } - else if( len == 4 ) { // quadrangles - double L1 = getDistance(P( 1 ),P( 2 )); - double L2 = getDistance(P( 2 ),P( 3 )); - double L3 = getDistance(P( 3 ),P( 4 )); - double L4 = getDistance(P( 4 ),P( 1 )); - double D1 = getDistance(P( 1 ),P( 3 )); - double D2 = getDistance(P( 2 ),P( 4 )); - aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2)); - break; - } - else if( len == 6 ) { // quadratic triangles - double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 )); - double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 )); - double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 )); - aVal = Max(L1,Max(L2,L3)); - break; - } - else if( len == 8 || len == 9 ) { // quadratic quadrangles - double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 )); - double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 )); - double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 )); - double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 )); - double D1 = getDistance(P( 1 ),P( 5 )); - double D2 = getDistance(P( 3 ),P( 7 )); - aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2)); - break; - } - } + if(P.size() == 0) + return 0.; + double aVal = 0; + int len = P.size(); + if( len == 3 ) { // triangles + double L1 = getDistance(P( 1 ),P( 2 )); + double L2 = getDistance(P( 2 ),P( 3 )); + double L3 = getDistance(P( 3 ),P( 1 )); + aVal = Max(L1,Max(L2,L3)); + } + else if( len == 4 ) { // quadrangles + double L1 = getDistance(P( 1 ),P( 2 )); + double L2 = getDistance(P( 2 ),P( 3 )); + double L3 = getDistance(P( 3 ),P( 4 )); + double L4 = getDistance(P( 4 ),P( 1 )); + double D1 = getDistance(P( 1 ),P( 3 )); + double D2 = getDistance(P( 2 ),P( 4 )); + aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2)); + } + else if( len == 6 ) { // quadratic triangles + double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 )); + double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 )); + double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 )); + aVal = Max(L1,Max(L2,L3)); + } + else if( len == 8 || len == 9 ) { // quadratic quadrangles + double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 )); + double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 )); + double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 )); + double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 )); + double D1 = getDistance(P( 1 ),P( 5 )); + double D2 = getDistance(P( 3 ),P( 7 )); + aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2)); + } - if( myPrecision >= 0 ) - { - double prec = pow( 10., (double)myPrecision ); - aVal = floor( aVal * prec + 0.5 ) / prec; - } - return aVal; + if( myPrecision >= 0 ) + { + double prec = pow( 10., (double)myPrecision ); + aVal = floor( aVal * prec + 0.5 ) / prec; } - return 0.; + return aVal; +} + +double MaxElementLength2D::GetValue( long theElementId ) +{ + TSequenceOfXYZ P; + return GetPoints( theElementId, P ) ? GetValue(P) : 0.0; } double MaxElementLength2D::GetBadRate( double Value, int /*nbNodes*/ ) const @@ -496,10 +504,12 @@ SMDSAbs_ElementType MaxElementLength2D::GetType() const return SMDSAbs_Face; } +//======================================================================= /* Class : MaxElementLength3D Description : Functor calculating maximum length of 3D element */ +//================================================================================ double MaxElementLength3D::GetValue( long theElementId ) { @@ -670,11 +680,12 @@ SMDSAbs_ElementType MaxElementLength3D::GetType() const return SMDSAbs_Volume; } - +//======================================================================= /* Class : MinimumAngle Description : Functor for calculation of minimum angle */ +//================================================================================ double MinimumAngle::GetValue( const TSequenceOfXYZ& P ) { @@ -707,10 +718,13 @@ SMDSAbs_ElementType MinimumAngle::GetType() const } +//================================================================================ /* Class : AspectRatio Description : Functor for calculating aspect ratio */ +//================================================================================ + double AspectRatio::GetValue( long theId ) { double aVal = 0; @@ -761,8 +775,8 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P ) double maxLen = Max( aLen[ 0 ], Max( aLen[ 1 ], aLen[ 2 ] ) ); double half_perimeter = ( aLen[0] + aLen[1] + aLen[2] ) / 2.; double anArea = getArea( P( 1 ), P( 2 ), P( 3 ) ); - if ( anArea <= Precision::Confusion() ) - return 0.; + if ( anArea <= theEps ) + return theInf; return alfa * maxLen * half_perimeter / anArea; } else if ( nbNodes == 6 ) { // quadratic triangles @@ -781,8 +795,8 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P ) double maxLen = Max( aLen[ 0 ], Max( aLen[ 1 ], aLen[ 2 ] ) ); double half_perimeter = ( aLen[0] + aLen[1] + aLen[2] ) / 2.; double anArea = getArea( P(1), P(3), P(5) ); - if ( anArea <= Precision::Confusion() ) - return 0.; + if ( anArea <= theEps ) + return theInf; return alfa * maxLen * half_perimeter / anArea; } else if( nbNodes == 4 ) { // quadrangle @@ -825,8 +839,8 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P ) double C2 = Min( anArea[ 0 ], Min( anArea[ 1 ], Min( anArea[ 2 ], anArea[ 3 ] ) ) ); - if ( C2 <= Precision::Confusion() ) - return 0.; + if ( C2 <= theEps ) + return theInf; return alpha * L * C1 / C2; } else if( nbNodes == 8 || nbNodes == 9 ) { // nbNodes==8 - quadratic quadrangle @@ -869,8 +883,8 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P ) double C2 = Min( anArea[ 0 ], Min( anArea[ 1 ], Min( anArea[ 2 ], anArea[ 3 ] ) ) ); - if ( C2 <= Precision::Confusion() ) - return 0.; + if ( C2 <= theEps ) + return theInf; return alpha * L * C1 / C2; } return 0; @@ -891,10 +905,13 @@ SMDSAbs_ElementType AspectRatio::GetType() const } +//================================================================================ /* Class : AspectRatio3D Description : Functor for calculating aspect ratio */ +//================================================================================ + namespace{ inline double getHalfPerimeter(double theTria[3]){ @@ -1261,10 +1278,13 @@ SMDSAbs_ElementType AspectRatio3D::GetType() const } +//================================================================================ /* Class : Warping Description : Functor for calculating warping */ +//================================================================================ + double Warping::GetValue( const TSequenceOfXYZ& P ) { if ( P.size() != 4 ) @@ -1277,7 +1297,11 @@ double Warping::GetValue( const TSequenceOfXYZ& P ) double A3 = ComputeA( P( 3 ), P( 4 ), P( 1 ), G ); double A4 = ComputeA( P( 4 ), P( 1 ), P( 2 ), G ); - return Max( Max( A1, A2 ), Max( A3, A4 ) ); + 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::ComputeA( const gp_XYZ& thePnt1, @@ -1288,8 +1312,8 @@ double Warping::ComputeA( const gp_XYZ& thePnt1, double aLen1 = gp_Pnt( thePnt1 ).Distance( gp_Pnt( thePnt2 ) ); double aLen2 = gp_Pnt( thePnt2 ).Distance( gp_Pnt( thePnt3 ) ); double L = Min( aLen1, aLen2 ) * 0.5; - if ( L < Precision::Confusion()) - return 0.; + if ( L < theEps ) + return theInf; gp_XYZ GI = ( thePnt2 + thePnt1 ) / 2. - theG; gp_XYZ GJ = ( thePnt3 + thePnt2 ) / 2. - theG; @@ -1318,10 +1342,13 @@ SMDSAbs_ElementType Warping::GetType() const } +//================================================================================ /* Class : Taper Description : Functor for calculating taper */ +//================================================================================ + double Taper::GetValue( const TSequenceOfXYZ& P ) { if ( P.size() != 4 ) @@ -1334,15 +1361,19 @@ double Taper::GetValue( const TSequenceOfXYZ& P ) double J4 = getArea( P( 3 ), P( 4 ), P( 1 ) ) / 2.; double JA = 0.25 * ( J1 + J2 + J3 + J4 ); - if ( JA <= Precision::Confusion() ) - return 0.; + if ( JA <= theEps ) + return theInf; double T1 = fabs( ( J1 - JA ) / JA ); double T2 = fabs( ( J2 - JA ) / JA ); double T3 = fabs( ( J3 - JA ) / JA ); double T4 = fabs( ( J4 - JA ) / JA ); - return Max( Max( T1, T2 ), Max( T3, T4 ) ); + double val = Max( Max( T1, T2 ), Max( T3, T4 ) ); + + const double eps = 0.01; + + return val < eps ? 0. : val; } double Taper::GetBadRate( double Value, int /*nbNodes*/ ) const @@ -1358,11 +1389,13 @@ SMDSAbs_ElementType Taper::GetType() const return SMDSAbs_Face; } - +//================================================================================ /* Class : Skew Description : Functor for calculating skew in degrees */ +//================================================================================ + static inline double skewAngle( const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3 ) { gp_XYZ p12 = ( p2 + p1 ) / 2.; @@ -1380,7 +1413,7 @@ double Skew::GetValue( const TSequenceOfXYZ& P ) return 0.; // Compute skew - static double PI2 = M_PI / 2.; + const double PI2 = M_PI / 2.; if ( P.size() == 3 ) { double A0 = fabs( PI2 - skewAngle( P( 3 ), P( 1 ), P( 2 ) ) ); @@ -1400,11 +1433,11 @@ double Skew::GetValue( const TSequenceOfXYZ& P ) double A = v1.Magnitude() <= gp::Resolution() || v2.Magnitude() <= gp::Resolution() ? 0. : fabs( PI2 - v1.Angle( v2 ) ); - //BUG SWP12743 - if ( A < Precision::Angular() ) - return 0.; + double val = A * 180. / M_PI; - return A * 180. / M_PI; + const double eps = 0.1; // val is in degrees + + return val < eps ? 0. : val; } } @@ -1422,10 +1455,13 @@ SMDSAbs_ElementType Skew::GetType() const } +//================================================================================ /* Class : Area Description : Functor for calculating area */ +//================================================================================ + double Area::GetValue( const TSequenceOfXYZ& P ) { double val = 0.0; @@ -1455,11 +1491,13 @@ SMDSAbs_ElementType Area::GetType() const return SMDSAbs_Face; } - +//================================================================================ /* Class : Length Description : Functor for calculating length of edge */ +//================================================================================ + double Length::GetValue( const TSequenceOfXYZ& P ) { switch ( P.size() ) { @@ -1480,10 +1518,12 @@ SMDSAbs_ElementType Length::GetType() const return SMDSAbs_Edge; } +//================================================================================ /* Class : Length2D Description : Functor for calculating length of edge */ +//================================================================================ double Length2D::GetValue( long theElementId) { @@ -1791,10 +1831,13 @@ void Length2D::GetValues(TValues& theValues){ } } +//================================================================================ /* Class : MultiConnection Description : Functor for calculating number of faces conneted to the edge */ +//================================================================================ + double MultiConnection::GetValue( const TSequenceOfXYZ& P ) { return 0; @@ -1815,10 +1858,13 @@ SMDSAbs_ElementType MultiConnection::GetType() const return SMDSAbs_Edge; } +//================================================================================ /* Class : MultiConnection2D Description : Functor for calculating number of faces conneted to the edge */ +//================================================================================ + double MultiConnection2D::GetValue( const TSequenceOfXYZ& P ) { return 0; @@ -1962,10 +2008,13 @@ void MultiConnection2D::GetValues(MValues& theValues){ } +//================================================================================ /* Class : BallDiameter Description : Functor returning diameter of a ball element */ +//================================================================================ + double BallDiameter::GetValue( long theId ) { double diameter = 0; @@ -1994,10 +2043,12 @@ SMDSAbs_ElementType BallDiameter::GetType() const PREDICATES */ +//================================================================================ /* Class : BadOrientedVolume Description : Predicate bad oriented volumes */ +//================================================================================ BadOrientedVolume::BadOrientedVolume() { @@ -2044,9 +2095,11 @@ bool BareBorderVolume::IsSatisfy(long theElementId ) return false; } +//================================================================================ /* Class : BareBorderFace */ +//================================================================================ bool BareBorderFace::IsSatisfy(long theElementId ) { @@ -2084,9 +2137,11 @@ bool BareBorderFace::IsSatisfy(long theElementId ) return ok; } +//================================================================================ /* Class : OverConstrainedVolume */ +//================================================================================ bool OverConstrainedVolume::IsSatisfy(long theElementId ) { @@ -2104,9 +2159,11 @@ bool OverConstrainedVolume::IsSatisfy(long theElementId ) return false; } +//================================================================================ /* Class : OverConstrainedFace */ +//================================================================================ bool OverConstrainedFace::IsSatisfy(long theElementId ) { @@ -2137,10 +2194,12 @@ bool OverConstrainedFace::IsSatisfy(long theElementId ) return false; } +//================================================================================ /* Class : CoincidentNodes Description : Predicate of Coincident nodes */ +//================================================================================ CoincidentNodes::CoincidentNodes() { @@ -2182,11 +2241,13 @@ void CoincidentNodes::SetMesh( const SMDS_Mesh* theMesh ) } } +//================================================================================ /* Class : CoincidentElements Description : Predicate of Coincident Elements Note : This class is suitable only for visualization of Coincident Elements */ +//================================================================================ CoincidentElements::CoincidentElements() { @@ -2237,10 +2298,12 @@ SMDSAbs_ElementType CoincidentElements3D::GetType() const } +//================================================================================ /* Class : FreeBorders Description : Predicate for free borders */ +//================================================================================ FreeBorders::FreeBorders() { @@ -2263,10 +2326,13 @@ SMDSAbs_ElementType FreeBorders::GetType() const } +//================================================================================ /* Class : FreeEdges Description : Predicate for free Edges */ +//================================================================================ + FreeEdges::FreeEdges() { myMesh = 0; @@ -2398,11 +2464,12 @@ void FreeEdges::GetBoreders(TBorders& theBorders) } } - +//================================================================================ /* Class : FreeNodes Description : Predicate for free nodes */ +//================================================================================ FreeNodes::FreeNodes() { @@ -2429,10 +2496,12 @@ SMDSAbs_ElementType FreeNodes::GetType() const } +//================================================================================ /* Class : FreeFaces Description : Predicate for free faces */ +//================================================================================ FreeFaces::FreeFaces() { @@ -2485,10 +2554,12 @@ SMDSAbs_ElementType FreeFaces::GetType() const return SMDSAbs_Face; } +//================================================================================ /* Class : LinearOrQuadratic Description : Predicate to verify whether a mesh element is linear */ +//================================================================================ LinearOrQuadratic::LinearOrQuadratic() { @@ -2519,10 +2590,12 @@ SMDSAbs_ElementType LinearOrQuadratic::GetType() const return myType; } +//================================================================================ /* Class : GroupColor Description : Functor for check color of group to whic mesh element belongs to */ +//================================================================================ GroupColor::GroupColor() { @@ -2591,6 +2664,7 @@ void GroupColor::SetMesh( const SMDS_Mesh* theMesh ) void GroupColor::SetColorStr( const TCollection_AsciiString& theStr ) { + Kernel_Utils::Localizer loc; TCollection_AsciiString aStr = theStr; aStr.RemoveAll( ' ' ); aStr.RemoveAll( '\t' ); @@ -2611,6 +2685,7 @@ void GroupColor::SetColorStr( const TCollection_AsciiString& theStr ) // Purpose : Get range as a string. // Example: "1,2,3,50-60,63,67,70-" //======================================================================= + void GroupColor::GetColorStr( TCollection_AsciiString& theResStr ) const { theResStr.Clear(); @@ -2619,10 +2694,12 @@ void GroupColor::GetColorStr( TCollection_AsciiString& theResStr ) const theResStr += TCollection_AsciiString( ";" ) + TCollection_AsciiString( myColor.Blue() ); } +//================================================================================ /* Class : ElemGeomType Description : Predicate to check element geometry type */ +//================================================================================ ElemGeomType::ElemGeomType() { @@ -2645,43 +2722,7 @@ bool ElemGeomType::IsSatisfy( long theId ) const SMDSAbs_ElementType anElemType = anElem->GetType(); if ( myType != SMDSAbs_All && anElemType != myType ) return false; - const int aNbNode = anElem->NbNodes(); - bool isOk = false; - switch( anElemType ) - { - case SMDSAbs_Node: - isOk = (myGeomType == SMDSGeom_POINT); - break; - - case SMDSAbs_Edge: - isOk = (myGeomType == SMDSGeom_EDGE); - break; - - case SMDSAbs_Face: - if ( myGeomType == SMDSGeom_TRIANGLE ) - isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 6 : aNbNode == 3)); - else if ( myGeomType == SMDSGeom_QUADRANGLE ) - isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? ( aNbNode == 8 || aNbNode == 9 ) : aNbNode == 4)); - else if ( myGeomType == SMDSGeom_POLYGON ) - isOk = anElem->IsPoly(); - break; - - case SMDSAbs_Volume: - if ( myGeomType == SMDSGeom_TETRA ) - isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 10 : aNbNode == 4)); - else if ( myGeomType == SMDSGeom_PYRAMID ) - isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 13 : aNbNode == 5)); - else if ( myGeomType == SMDSGeom_PENTA ) - isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 15 : aNbNode == 6)); - else if ( myGeomType == SMDSGeom_HEXA ) - isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? ( aNbNode == 20 || aNbNode == 27 ): aNbNode == 8)); - else if ( myGeomType == SMDSGeom_HEXAGONAL_PRISM ) - isOk = (anElem->GetEntityType() == SMDSEntity_Hexagonal_Prism ); - else if ( myGeomType == SMDSGeom_POLYHEDRA ) - isOk = anElem->IsPoly(); - break; - default: break; - } + bool isOk = ( anElem->GetGeomType() == myGeomType ); return isOk; } @@ -2705,6 +2746,196 @@ SMDSAbs_GeometryType ElemGeomType::GetGeomType() const return myGeomType; } +//================================================================================ +/* + Class : ElemEntityType + Description : Predicate to check element entity type +*/ +//================================================================================ + +ElemEntityType::ElemEntityType(): + myMesh( 0 ), + myType( SMDSAbs_All ), + myEntityType( SMDSEntity_0D ) +{ +} + +void ElemEntityType::SetMesh( const SMDS_Mesh* theMesh ) +{ + myMesh = theMesh; +} + +bool ElemEntityType::IsSatisfy( long theId ) +{ + if ( !myMesh ) return false; + const SMDS_MeshElement* anElem = myMesh->FindElement( theId ); + return ( anElem && + myEntityType == anElem->GetEntityType() && + ( myType == SMDSAbs_Edge || myType == SMDSAbs_Face || myType == SMDSAbs_Volume )); +} + +void ElemEntityType::SetType( SMDSAbs_ElementType theType ) +{ + myType = theType; +} + +SMDSAbs_ElementType ElemEntityType::GetType() const +{ + return myType; +} + +void ElemEntityType::SetElemEntityType( SMDSAbs_EntityType theEntityType ) +{ + myEntityType = theEntityType; +} + +SMDSAbs_EntityType ElemEntityType::GetElemEntityType() const +{ + return myEntityType; +} + +//================================================================================ +/*! + * \brief Class ConnectedElements + */ +//================================================================================ + +ConnectedElements::ConnectedElements(): + myNodeID(0), myType( SMDSAbs_All ), myOkIDsReady( false ) {} + +SMDSAbs_ElementType ConnectedElements::GetType() const +{ return myType; } + +int ConnectedElements::GetNode() const +{ return myXYZ.empty() ? myNodeID : 0; } // myNodeID can be found by myXYZ + +std::vector ConnectedElements::GetPoint() const +{ return myXYZ; } + +void ConnectedElements::clearOkIDs() +{ myOkIDsReady = false; myOkIDs.clear(); } + +void ConnectedElements::SetType( SMDSAbs_ElementType theType ) +{ + if ( myType != theType || myMeshModifTracer.IsMeshModified() ) + clearOkIDs(); + myType = theType; +} + +void ConnectedElements::SetMesh( const SMDS_Mesh* theMesh ) +{ + myMeshModifTracer.SetMesh( theMesh ); + if ( myMeshModifTracer.IsMeshModified() ) + { + clearOkIDs(); + if ( !myXYZ.empty() ) + SetPoint( myXYZ[0], myXYZ[1], myXYZ[2] ); // find a node near myXYZ it in a new mesh + } +} + +void ConnectedElements::SetNode( int nodeID ) +{ + myNodeID = nodeID; + myXYZ.clear(); + + bool isSameDomain = false; + if ( myOkIDsReady && myMeshModifTracer.GetMesh() && !myMeshModifTracer.IsMeshModified() ) + if ( const SMDS_MeshNode* n = myMeshModifTracer.GetMesh()->FindNode( myNodeID )) + { + SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator( myType ); + while ( !isSameDomain && eIt->more() ) + isSameDomain = IsSatisfy( eIt->next()->GetID() ); + } + if ( !isSameDomain ) + clearOkIDs(); +} + +void ConnectedElements::SetPoint( double x, double y, double z ) +{ + myXYZ.resize(3); + myXYZ[0] = x; + myXYZ[1] = y; + myXYZ[2] = z; + myNodeID = 0; + + bool isSameDomain = false; + + // find myNodeID by myXYZ if possible + if ( myMeshModifTracer.GetMesh() ) + { + auto_ptr searcher + ( SMESH_MeshAlgos::GetElementSearcher( (SMDS_Mesh&) *myMeshModifTracer.GetMesh() )); + + vector< const SMDS_MeshElement* > foundElems; + searcher->FindElementsByPoint( gp_Pnt(x,y,z), SMDSAbs_All, foundElems ); + + if ( !foundElems.empty() ) + { + myNodeID = foundElems[0]->GetNode(0)->GetID(); + if ( myOkIDsReady && !myMeshModifTracer.IsMeshModified() ) + isSameDomain = IsSatisfy( foundElems[0]->GetID() ); + } + } + if ( !isSameDomain ) + clearOkIDs(); +} + +bool ConnectedElements::IsSatisfy( long theElementId ) +{ + // Here we do NOT check if the mesh has changed, we do it in Set...() only!!! + + if ( !myOkIDsReady ) + { + if ( !myMeshModifTracer.GetMesh() ) + return false; + const SMDS_MeshNode* node0 = myMeshModifTracer.GetMesh()->FindNode( myNodeID ); + if ( !node0 ) + return false; + + list< const SMDS_MeshNode* > nodeQueue( 1, node0 ); + std::set< int > checkedNodeIDs; + // algo: + // foreach node in nodeQueue: + // foreach element sharing a node: + // add ID of an element of myType to myOkIDs; + // push all element nodes absent from checkedNodeIDs to nodeQueue; + while ( !nodeQueue.empty() ) + { + const SMDS_MeshNode* node = nodeQueue.front(); + nodeQueue.pop_front(); + + // loop on elements sharing the node + SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(); + while ( eIt->more() ) + { + // keep elements of myType + const SMDS_MeshElement* element = eIt->next(); + if ( element->GetType() == myType ) + myOkIDs.insert( myOkIDs.end(), element->GetID() ); + + // enqueue nodes of the element + SMDS_ElemIteratorPtr nIt = element->nodesIterator(); + while ( nIt->more() ) + { + const SMDS_MeshNode* n = static_cast< const SMDS_MeshNode* >( nIt->next() ); + if ( checkedNodeIDs.insert( n->GetID() ).second ) + nodeQueue.push_back( n ); + } + } + } + if ( myType == SMDSAbs_Node ) + std::swap( myOkIDs, checkedNodeIDs ); + + size_t totalNbElems = myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType ); + if ( myOkIDs.size() == totalNbElems ) + myOkIDs.clear(); + + myOkIDsReady = true; + } + + return myOkIDs.empty() ? true : myOkIDs.count( theElementId ); +} + //================================================================================ /*! * \brief Class CoplanarFaces @@ -2737,30 +2968,37 @@ void CoplanarFaces::SetMesh( const SMDS_Mesh* theMesh ) return; const double radianTol = myToler * M_PI / 180.; - typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TFaceIt; - std::set checkedFaces, checkedNodes; - std::list faceQueue( 1, face ); + std::set< SMESH_TLink > checkedLinks; + + std::list< pair< const SMDS_MeshElement*, gp_Vec > > faceQueue; + faceQueue.push_back( make_pair( face, myNorm )); while ( !faceQueue.empty() ) { - face = faceQueue.front(); - if ( checkedFaces.insert( face ).second ) + face = faceQueue.front().first; + myNorm = faceQueue.front().second; + faceQueue.pop_front(); + + for ( int i = 0, nbN = face->NbCornerNodes(); i < nbN; ++i ) { - gp_Vec norm = getNormale( static_cast(face), &normOK ); - if (!normOK || myNorm.Angle( norm ) <= radianTol) + const SMDS_MeshNode* n1 = face->GetNode( i ); + const SMDS_MeshNode* n2 = face->GetNode(( i+1 )%nbN); + if ( !checkedLinks.insert( SMESH_TLink( n1, n2 )).second ) + continue; + SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator(SMDSAbs_Face); + while ( fIt->more() ) { - myCoplanarIDs.insert( face->GetID() ); - std::set neighborFaces; - for ( int i = 0; i < face->NbCornerNodes(); ++i ) + const SMDS_MeshElement* f = fIt->next(); + if ( f->GetNodeIndex( n2 ) > -1 ) { - const SMDS_MeshNode* n = face->GetNode( i ); - if ( checkedNodes.insert( n ).second ) - neighborFaces.insert( TFaceIt( n->GetInverseElementIterator(SMDSAbs_Face)), - TFaceIt()); + gp_Vec norm = getNormale( static_cast(f), &normOK ); + if (!normOK || myNorm.Angle( norm ) <= radianTol) + { + myCoplanarIDs.insert( f->GetID() ); + faceQueue.push_back( make_pair( f, norm )); + } } - faceQueue.insert( faceQueue.end(), neighborFaces.begin(), neighborFaces.end() ); } } - faceQueue.pop_front(); } } } @@ -2770,7 +3008,7 @@ bool CoplanarFaces::IsSatisfy( long theElementId ) } /* - *Class : RangeOfIds + *Class : RangeOfIds *Description : Predicate for Range of Ids. * Range may be specified with two ways. * 1. Using AddToRange method @@ -3558,7 +3796,6 @@ void ManifoldPart::getFacesByLink( const ManifoldPart::Link& theLink, ElementsOnSurface::ElementsOnSurface() { - myMesh = 0; myIds.Clear(); myType = SMDSAbs_All; mySurf.Nullify(); @@ -3568,15 +3805,13 @@ ElementsOnSurface::ElementsOnSurface() ElementsOnSurface::~ElementsOnSurface() { - myMesh = 0; } void ElementsOnSurface::SetMesh( const SMDS_Mesh* theMesh ) { - if ( myMesh == theMesh ) - return; - myMesh = theMesh; - process(); + myMeshModifTracer.SetMesh( theMesh ); + if ( myMeshModifTracer.IsMeshModified()) + process(); } bool ElementsOnSurface::IsSatisfy( long theElementId ) @@ -3631,32 +3866,14 @@ void ElementsOnSurface::process() if ( mySurf.IsNull() ) return; - if ( myMesh == 0 ) + if ( !myMeshModifTracer.GetMesh() ) return; - if ( myType == SMDSAbs_Face || myType == SMDSAbs_All ) - { - myIds.ReSize( myMesh->NbFaces() ); - SMDS_FaceIteratorPtr anIter = myMesh->facesIterator(); - for(; anIter->more(); ) - process( anIter->next() ); - } - - if ( myType == SMDSAbs_Edge || myType == SMDSAbs_All ) - { - myIds.ReSize( myIds.Extent() + myMesh->NbEdges() ); - SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator(); - for(; anIter->more(); ) - process( anIter->next() ); - } + myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType )); - if ( myType == SMDSAbs_Node ) - { - myIds.ReSize( myMesh->NbNodes() ); - SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator(); - for(; anIter->more(); ) - process( anIter->next() ); - } + SMDS_ElemIteratorPtr anIter = myMeshModifTracer.GetMesh()->elementsIterator( myType ); + for(; anIter->more(); ) + process( anIter->next() ); } void ElementsOnSurface::process( const SMDS_MeshElement* theElemPtr ) @@ -3719,23 +3936,11 @@ ElementsOnShape::ElementsOnShape() myToler(Precision::Confusion()), myAllNodesFlag(false) { - myCurShapeType = TopAbs_SHAPE; } ElementsOnShape::~ElementsOnShape() { -} - -void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh) -{ - myMeshModifTracer.SetMesh( theMesh ); - if ( myMeshModifTracer.IsMeshModified()) - SetShape(myShape, myType); -} - -bool ElementsOnShape::IsSatisfy (long theElementId) -{ - return myIds.Contains(theElementId); + clearClassifiers(); } SMDSAbs_ElementType ElementsOnShape::GetType() const @@ -3758,188 +3963,163 @@ double ElementsOnShape::GetTolerance() const void ElementsOnShape::SetAllNodes (bool theAllNodes) { - if (myAllNodesFlag != theAllNodes) { - myAllNodesFlag = theAllNodes; - SetShape(myShape, myType); - } + myAllNodesFlag = theAllNodes; +} + +void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh) +{ + myMesh = theMesh; } void ElementsOnShape::SetShape (const TopoDS_Shape& theShape, const SMDSAbs_ElementType theType) { - myType = theType; + myType = theType; myShape = theShape; - myIds.Clear(); - - const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh(); + if ( myShape.IsNull() ) return; - if ( !myMesh ) return; - - switch (myType) + TopTools_IndexedMapOfShape shapesMap; + TopAbs_ShapeEnum shapeTypes[4] = { TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX }; + TopExp_Explorer sub; + for ( int i = 0; i < 4; ++i ) { - case SMDSAbs_All: - myIds.ReSize(myMesh->NbEdges() + myMesh->NbFaces() + myMesh->NbVolumes()); - break; - case SMDSAbs_Node: - myIds.ReSize(myMesh->NbNodes()); - break; - case SMDSAbs_Edge: - myIds.ReSize(myMesh->NbEdges()); - break; - case SMDSAbs_Face: - myIds.ReSize(myMesh->NbFaces()); - break; - case SMDSAbs_Volume: - myIds.ReSize(myMesh->NbVolumes()); - break; - default: - break; + if ( shapesMap.IsEmpty() ) + for ( sub.Init( myShape, shapeTypes[i] ); sub.More(); sub.Next() ) + shapesMap.Add( sub.Current() ); + if ( i > 0 ) + for ( sub.Init( myShape, shapeTypes[i], shapeTypes[i-1] ); sub.More(); sub.Next() ) + shapesMap.Add( sub.Current() ); } - myShapesMap.Clear(); - addShape(myShape); + clearClassifiers(); + myClassifiers.resize( shapesMap.Extent() ); + for ( int i = 0; i < shapesMap.Extent(); ++i ) + myClassifiers[ i ] = new TClassifier( shapesMap( i+1 ), myToler ); } -void ElementsOnShape::addShape (const TopoDS_Shape& theShape) +void ElementsOnShape::clearClassifiers() { - if (theShape.IsNull() || myMeshModifTracer.GetMesh() == 0) - return; + for ( size_t i = 0; i < myClassifiers.size(); ++i ) + delete myClassifiers[ i ]; + myClassifiers.clear(); +} - if (!myShapesMap.Add(theShape)) return; +bool ElementsOnShape::IsSatisfy (long elemId) +{ + const SMDS_MeshElement* elem = + ( myType == SMDSAbs_Node ? myMesh->FindNode( elemId ) : myMesh->FindElement( elemId )); + if ( !elem || myClassifiers.empty() ) + return false; - myCurShapeType = theShape.ShapeType(); - switch (myCurShapeType) + for ( size_t i = 0; i < myClassifiers.size(); ++i ) { - case TopAbs_COMPOUND: - case TopAbs_COMPSOLID: - case TopAbs_SHELL: - case TopAbs_WIRE: + SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator(); + bool isSatisfy = myAllNodesFlag; + + gp_XYZ centerXYZ (0, 0, 0); + + while (aNodeItr->more() && (isSatisfy == myAllNodesFlag)) { - TopoDS_Iterator anIt (theShape, Standard_True, Standard_True); - for (; anIt.More(); anIt.Next()) addShape(anIt.Value()); + SMESH_TNodeXYZ aPnt ( aNodeItr->next() ); + centerXYZ += aPnt; + isSatisfy = ! myClassifiers[i]->IsOut( aPnt ); } - break; - case TopAbs_SOLID: + + // Check the center point for volumes MantisBug 0020168 + if (isSatisfy && + myAllNodesFlag && + myClassifiers[i]->ShapeType() == TopAbs_SOLID) { - myCurSC.Load(theShape); - process(); + centerXYZ /= elem->NbNodes(); + isSatisfy = ! myClassifiers[i]->IsOut( centerXYZ ); } + if ( isSatisfy ) + return true; + } + + return false; +} + +TopAbs_ShapeEnum ElementsOnShape::TClassifier::ShapeType() const +{ + return myShape.ShapeType(); +} + +bool ElementsOnShape::TClassifier::IsOut(const gp_Pnt& p) +{ + return (this->*myIsOutFun)( p ); +} + +void ElementsOnShape::TClassifier::Init (const TopoDS_Shape& theShape, double theTol) +{ + myShape = theShape; + myTol = theTol; + switch ( myShape.ShapeType() ) + { + case TopAbs_SOLID: { + mySolidClfr.Load(theShape); + myIsOutFun = & ElementsOnShape::TClassifier::isOutOfSolid; break; - case TopAbs_FACE: - { - TopoDS_Face aFace = TopoDS::Face(theShape); - BRepAdaptor_Surface SA (aFace, true); - Standard_Real - u1 = SA.FirstUParameter(), - u2 = SA.LastUParameter(), - v1 = SA.FirstVParameter(), - v2 = SA.LastVParameter(); - Handle(Geom_Surface) surf = BRep_Tool::Surface(aFace); - myCurProjFace.Init(surf, u1,u2, v1,v2); - myCurFace = aFace; - process(); - } + } + case TopAbs_FACE: { + 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::TClassifier::isOutOfFace; break; - case TopAbs_EDGE: - { - TopoDS_Edge anEdge = TopoDS::Edge(theShape); - Standard_Real u1, u2; - Handle(Geom_Curve) curve = BRep_Tool::Curve(anEdge, u1, u2); - myCurProjEdge.Init(curve, u1, u2); - process(); - } + } + 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::TClassifier::isOutOfEdge; break; - case TopAbs_VERTEX: - { - TopoDS_Vertex aV = TopoDS::Vertex(theShape); - myCurPnt = BRep_Tool::Pnt(aV); - process(); - } + } + case TopAbs_VERTEX:{ + myVertexXYZ = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) ); + myIsOutFun = & ElementsOnShape::TClassifier::isOutOfVertex; break; + } default: - break; + throw SALOME_Exception("Programmer error in usage of ElementsOnShape::TClassifier"); } } -void ElementsOnShape::process() +bool ElementsOnShape::TClassifier::isOutOfSolid (const gp_Pnt& p) { - const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh(); - if (myShape.IsNull() || myMesh == 0) - return; - - SMDS_ElemIteratorPtr anIter = myMesh->elementsIterator(myType); - while (anIter->more()) - process(anIter->next()); + mySolidClfr.Perform( p, myTol ); + return ( mySolidClfr.State() != TopAbs_IN && mySolidClfr.State() != TopAbs_ON ); } -void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr) +bool ElementsOnShape::TClassifier::isOutOfFace (const gp_Pnt& p) { - if (myShape.IsNull()) - return; - - SMDS_ElemIteratorPtr aNodeItr = theElemPtr->nodesIterator(); - bool isSatisfy = myAllNodesFlag; - - gp_XYZ centerXYZ (0, 0, 0); - - while (aNodeItr->more() && (isSatisfy == myAllNodesFlag)) + myProjFace.Perform( p ); + if ( myProjFace.IsDone() && myProjFace.LowerDistance() <= myTol ) { - SMESH_TNodeXYZ aPnt ( aNodeItr->next() ); - centerXYZ += aPnt; - - switch (myCurShapeType) - { - case TopAbs_SOLID: - { - myCurSC.Perform(aPnt, myToler); - isSatisfy = (myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON); - } - break; - case TopAbs_FACE: - { - myCurProjFace.Perform(aPnt); - isSatisfy = (myCurProjFace.IsDone() && myCurProjFace.LowerDistance() <= myToler); - if (isSatisfy) - { - // check relatively the face - Quantity_Parameter u, v; - myCurProjFace.LowerDistanceParameters(u, v); - gp_Pnt2d aProjPnt (u, v); - BRepClass_FaceClassifier aClsf (myCurFace, aProjPnt, myToler); - isSatisfy = (aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON); - } - } - break; - case TopAbs_EDGE: - { - myCurProjEdge.Perform(aPnt); - isSatisfy = (myCurProjEdge.NbPoints() > 0 && myCurProjEdge.LowerDistance() <= myToler); - } - break; - case TopAbs_VERTEX: - { - isSatisfy = (myCurPnt.Distance(aPnt) <= myToler); - } - break; - default: - { - isSatisfy = false; - } - } + // check relatively to the face + Quantity_Parameter u, v; + myProjFace.LowerDistanceParameters(u, v); + gp_Pnt2d aProjPnt (u, v); + BRepClass_FaceClassifier aClsf ( TopoDS::Face( myShape ), aProjPnt, myTol ); + if ( aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON ) + return false; } + return true; +} - if (isSatisfy && myCurShapeType == TopAbs_SOLID) { // Check the center point for volumes MantisBug 0020168 - centerXYZ /= theElemPtr->NbNodes(); - gp_Pnt aCenterPnt (centerXYZ); - myCurSC.Perform(aCenterPnt, myToler); - if ( !(myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON)) - isSatisfy = false; - } +bool ElementsOnShape::TClassifier::isOutOfEdge (const gp_Pnt& p) +{ + myProjEdge.Perform( p ); + return ! ( myProjEdge.NbPoints() > 0 && myProjEdge.LowerDistance() <= myTol ); +} - if (isSatisfy) - myIds.Add(theElemPtr->GetID()); +bool ElementsOnShape::TClassifier::isOutOfVertex(const gp_Pnt& p) +{ + return ( myVertexXYZ.Distance( p ) > myTol ); } + TSequenceOfXYZ::TSequenceOfXYZ() {}