-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014 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
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "SMESHDS_GroupBase.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_OctreeNode.hxx"
+#include "SMESH_MeshAlgos.hxx"
+
+#include <Basics_Utils.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <TColStd_SequenceOfAsciiString.hxx>
#include <TColgp_Array1OfXYZ.hxx>
#include <TopAbs.hxx>
+#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <set>
#include <limits>
-
/*
AUXILIARY METHODS
*/
-namespace{
+namespace {
+
+ const double theEps = 1e-100;
+ const double theInf = 1e+100;
inline gp_XYZ gpXYZ(const SMDS_MeshNode* aNode )
{
* FUNCTORS
*/
+//================================================================================
/*
Class : NumericalFunctor
Description : Base class for numerical functors
*/
+//================================================================================
+
NumericalFunctor::NumericalFunctor():
myMesh(NULL)
{
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,
{
theRes.clear();
- if ( anElem == 0)
+ if ( anElem == 0 )
return false;
theRes.reserve( anElem->NbNodes() );
myCurrElement = myMesh->FindElement( theId );
TSequenceOfXYZ P;
- if ( GetPoints( theId, P ))
+ if ( GetPoints( theId, P )) // elem type is checked here
aVal = Round( GetValue( P ));
return aVal;
std::vector<int>& nbEvents,
std::vector<double>& funValues,
const vector<int>& elements,
- const double* minmax)
+ const double* minmax,
+ const bool isLogarithmic)
{
if ( nbIntervals < 1 ||
!myMesh ||
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] )
}
//=======================================================================
-//function : GetValue
-//purpose :
-//=======================================================================
+/*
+ Class : Volume
+ Description : Functor calculating volume of a 3D element
+*/
+//================================================================================
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
return SMDSAbs_Face;
}
+//=======================================================================
/*
Class : MaxElementLength3D
Description : Functor calculating maximum length of 3D element
*/
+//================================================================================
double MaxElementLength3D::GetValue( long theElementId )
{
return SMDSAbs_Volume;
}
-
+//=======================================================================
/*
Class : MinimumAngle
Description : Functor for calculation of minimum angle
*/
+//================================================================================
double MinimumAngle::GetValue( const TSequenceOfXYZ& P )
{
}
+//================================================================================
/*
Class : AspectRatio
Description : Functor for calculating aspect ratio
*/
+//================================================================================
+
double AspectRatio::GetValue( long theId )
{
double aVal = 0;
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
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
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
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;
}
+//================================================================================
/*
Class : AspectRatio3D
Description : Functor for calculating aspect ratio
*/
+//================================================================================
+
namespace{
inline double getHalfPerimeter(double theTria[3]){
}
+//================================================================================
/*
Class : Warping
Description : Functor for calculating warping
*/
+//================================================================================
+
double Warping::GetValue( const TSequenceOfXYZ& P )
{
if ( P.size() != 4 )
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,
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;
}
+//================================================================================
/*
Class : Taper
Description : Functor for calculating taper
*/
+//================================================================================
+
double Taper::GetValue( const TSequenceOfXYZ& P )
{
if ( P.size() != 4 )
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
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.;
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 ) ) );
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;
}
}
}
+//================================================================================
/*
Class : Area
Description : Functor for calculating area
*/
+//================================================================================
+
double Area::GetValue( const TSequenceOfXYZ& P )
{
double val = 0.0;
return SMDSAbs_Face;
}
-
+//================================================================================
/*
Class : Length
Description : Functor for calculating length of edge
*/
+//================================================================================
+
double Length::GetValue( const TSequenceOfXYZ& P )
{
switch ( P.size() ) {
return SMDSAbs_Edge;
}
+//================================================================================
/*
Class : Length2D
Description : Functor for calculating length of edge
*/
+//================================================================================
double Length2D::GetValue( long theElementId)
{
}
}
+//================================================================================
/*
Class : MultiConnection
Description : Functor for calculating number of faces conneted to the edge
*/
+//================================================================================
+
double MultiConnection::GetValue( const TSequenceOfXYZ& P )
{
return 0;
return SMDSAbs_Edge;
}
+//================================================================================
/*
Class : MultiConnection2D
Description : Functor for calculating number of faces conneted to the edge
*/
+//================================================================================
+
double MultiConnection2D::GetValue( const TSequenceOfXYZ& P )
{
return 0;
}
void MultiConnection2D::GetValues(MValues& theValues){
+ if ( !myMesh ) return;
SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
for(; anIter->more(); ){
const SMDS_MeshFace* anElem = anIter->next();
}
+//================================================================================
/*
Class : BallDiameter
Description : Functor returning diameter of a ball element
*/
+//================================================================================
+
double BallDiameter::GetValue( long theId )
{
double diameter = 0;
PREDICATES
*/
+//================================================================================
/*
Class : BadOrientedVolume
Description : Predicate bad oriented volumes
*/
+//================================================================================
BadOrientedVolume::BadOrientedVolume()
{
return false;
}
+//================================================================================
/*
Class : BareBorderFace
*/
+//================================================================================
bool BareBorderFace::IsSatisfy(long theElementId )
{
return ok;
}
+//================================================================================
/*
Class : OverConstrainedVolume
*/
+//================================================================================
bool OverConstrainedVolume::IsSatisfy(long theElementId )
{
return false;
}
+//================================================================================
/*
Class : OverConstrainedFace
*/
+//================================================================================
bool OverConstrainedFace::IsSatisfy(long theElementId )
{
return false;
}
+//================================================================================
/*
Class : CoincidentNodes
Description : Predicate of Coincident nodes
*/
+//================================================================================
CoincidentNodes::CoincidentNodes()
{
}
}
+//================================================================================
/*
Class : CoincidentElements
Description : Predicate of Coincident Elements
Note : This class is suitable only for visualization of Coincident Elements
*/
+//================================================================================
CoincidentElements::CoincidentElements()
{
}
+//================================================================================
/*
Class : FreeBorders
Description : Predicate for free borders
*/
+//================================================================================
FreeBorders::FreeBorders()
{
}
+//================================================================================
/*
Class : FreeEdges
Description : Predicate for free Edges
*/
+//================================================================================
+
FreeEdges::FreeEdges()
{
myMesh = 0;
}
}
-
+//================================================================================
/*
Class : FreeNodes
Description : Predicate for free nodes
*/
+//================================================================================
FreeNodes::FreeNodes()
{
}
+//================================================================================
/*
Class : FreeFaces
Description : Predicate for free faces
*/
+//================================================================================
FreeFaces::FreeFaces()
{
return SMDSAbs_Face;
}
+//================================================================================
/*
Class : LinearOrQuadratic
Description : Predicate to verify whether a mesh element is linear
*/
+//================================================================================
LinearOrQuadratic::LinearOrQuadratic()
{
return myType;
}
+//================================================================================
/*
Class : GroupColor
Description : Functor for check color of group to whic mesh element belongs to
*/
+//================================================================================
GroupColor::GroupColor()
{
void GroupColor::SetColorStr( const TCollection_AsciiString& theStr )
{
+ Kernel_Utils::Localizer loc;
TCollection_AsciiString aStr = theStr;
aStr.RemoveAll( ' ' );
aStr.RemoveAll( '\t' );
// Purpose : Get range as a string.
// Example: "1,2,3,50-60,63,67,70-"
//=======================================================================
+
void GroupColor::GetColorStr( TCollection_AsciiString& theResStr ) const
{
theResStr.Clear();
theResStr += TCollection_AsciiString( ";" ) + TCollection_AsciiString( myColor.Blue() );
}
+//================================================================================
/*
Class : ElemGeomType
Description : Predicate to check element geometry type
*/
+//================================================================================
ElemGeomType::ElemGeomType()
{
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;
}
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;
+ if ( myType == SMDSAbs_Node )
+ return myMesh->FindNode( theId );
+ const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
+ return ( anElem &&
+ myEntityType == anElem->GetEntityType() );
+}
+
+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 CoplanarFaces
+ * \brief Class ConnectedElements
*/
//================================================================================
-CoplanarFaces::CoplanarFaces()
- : myFaceID(0), myToler(0)
+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<double> 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 CoplanarFaces::SetMesh( const SMDS_Mesh* theMesh )
+
+void ConnectedElements::SetMesh( const SMDS_Mesh* theMesh )
{
myMeshModifTracer.SetMesh( theMesh );
if ( myMeshModifTracer.IsMeshModified() )
{
- // Build a set of coplanar face ids
+ clearOkIDs();
+ if ( !myXYZ.empty() )
+ SetPoint( myXYZ[0], myXYZ[1], myXYZ[2] ); // find a node near myXYZ it in a new mesh
+ }
+}
- myCoplanarIDs.clear();
+void ConnectedElements::SetNode( int nodeID )
+{
+ myNodeID = nodeID;
+ myXYZ.clear();
- if ( !myMeshModifTracer.GetMesh() || !myFaceID || !myToler )
- return;
+ 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();
+}
- const SMDS_MeshElement* face = myMeshModifTracer.GetMesh()->FindElement( myFaceID );
- if ( !face || face->GetType() != SMDSAbs_Face )
- return;
+void ConnectedElements::SetPoint( double x, double y, double z )
+{
+ myXYZ.resize(3);
+ myXYZ[0] = x;
+ myXYZ[1] = y;
+ myXYZ[2] = z;
+ myNodeID = 0;
- bool normOK;
- gp_Vec myNorm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
- if (!normOK)
- return;
+ bool isSameDomain = false;
- const double radianTol = myToler * M_PI / 180.;
- std::set< SMESH_TLink > checkedLinks;
+ // find myNodeID by myXYZ if possible
+ if ( myMeshModifTracer.GetMesh() )
+ {
+ auto_ptr<SMESH_ElementSearcher> searcher
+ ( SMESH_MeshAlgos::GetElementSearcher( (SMDS_Mesh&) *myMeshModifTracer.GetMesh() ));
- std::list< pair< const SMDS_MeshElement*, gp_Vec > > faceQueue;
- faceQueue.push_back( make_pair( face, myNorm ));
- while ( !faceQueue.empty() )
+ vector< const SMDS_MeshElement* > foundElems;
+ searcher->FindElementsByPoint( gp_Pnt(x,y,z), SMDSAbs_All, foundElems );
+
+ if ( !foundElems.empty() )
{
- face = faceQueue.front().first;
- myNorm = faceQueue.front().second;
- faceQueue.pop_front();
+ myNodeID = foundElems[0]->GetNode(0)->GetID();
+ if ( myOkIDsReady && !myMeshModifTracer.IsMeshModified() )
+ isSameDomain = IsSatisfy( foundElems[0]->GetID() );
+ }
+ }
+ if ( !isSameDomain )
+ clearOkIDs();
+}
- for ( int i = 0, nbN = face->NbCornerNodes(); i < nbN; ++i )
+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() )
{
- const SMDS_MeshNode* n1 = face->GetNode( i );
+ // 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
+ */
+//================================================================================
+
+CoplanarFaces::CoplanarFaces()
+ : myFaceID(0), myToler(0)
+{
+}
+void CoplanarFaces::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMeshModifTracer.SetMesh( theMesh );
+ if ( myMeshModifTracer.IsMeshModified() )
+ {
+ // Build a set of coplanar face ids
+
+ myCoplanarIDs.clear();
+
+ if ( !myMeshModifTracer.GetMesh() || !myFaceID || !myToler )
+ return;
+
+ const SMDS_MeshElement* face = myMeshModifTracer.GetMesh()->FindElement( myFaceID );
+ if ( !face || face->GetType() != SMDSAbs_Face )
+ return;
+
+ bool normOK;
+ gp_Vec myNorm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
+ if (!normOK)
+ return;
+
+ const double radianTol = myToler * M_PI / 180.;
+ 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().first;
+ myNorm = faceQueue.front().second;
+ faceQueue.pop_front();
+
+ for ( int i = 0, nbN = face->NbCornerNodes(); i < nbN; ++i )
+ {
+ 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;
myIds.Clear();
TCollection_AsciiString aStr = theStr;
- aStr.RemoveAll( ' ' );
- aStr.RemoveAll( '\t' );
+ //aStr.RemoveAll( ' ' );
+ //aStr.RemoveAll( '\t' );
+ for ( int i = 1; i <= aStr.Length(); ++i )
+ if ( isspace( aStr.Value( i )))
+ aStr.SetValue( i, ',');
for ( int aPos = aStr.Search( ",," ); aPos != -1; aPos = aStr.Search( ",," ) )
- aStr.Remove( aPos, 2 );
+ aStr.Remove( aPos, 1 );
TCollection_AsciiString tmpStr = aStr.Token( ",", 1 );
int i = 1;
FILTER
*/
+// #ifdef WITH_TBB
+// #include <tbb/parallel_for.h>
+// #include <tbb/enumerable_thread_specific.h>
+
+// namespace Parallel
+// {
+// typedef tbb::enumerable_thread_specific< TIdSequence > TIdSeq;
+
+// struct Predicate
+// {
+// const SMDS_Mesh* myMesh;
+// PredicatePtr myPredicate;
+// TIdSeq & myOKIds;
+// Predicate( const SMDS_Mesh* m, PredicatePtr p, TIdSeq & ids ):
+// myMesh(m), myPredicate(p->Duplicate()), myOKIds(ids) {}
+// void operator() ( const tbb::blocked_range<size_t>& r ) const
+// {
+// for ( size_t i = r.begin(); i != r.end(); ++i )
+// if ( myPredicate->IsSatisfy( i ))
+// myOKIds.local().push_back();
+// }
+// }
+// }
+// #endif
+
Filter::Filter()
{}
ElementsOnSurface::ElementsOnSurface()
{
- myMesh = 0;
myIds.Clear();
myType = SMDSAbs_All;
mySurf.Nullify();
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 )
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() );
- }
+ myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType ));
- if ( myType == SMDSAbs_Edge || myType == SMDSAbs_All )
- {
- myIds.ReSize( myIds.Extent() + myMesh->NbEdges() );
- SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
- for(; anIter->more(); )
- process( anIter->next() );
- }
-
- 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 )
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
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;
+ 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 )
+ {
+ 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() );
+ }
+
+ clearClassifiers();
+ myClassifiers.resize( shapesMap.Extent() );
+ for ( int i = 0; i < shapesMap.Extent(); ++i )
+ myClassifiers[ i ] = new TClassifier( shapesMap( i+1 ), myToler );
+}
+
+void ElementsOnShape::clearClassifiers()
+{
+ for ( size_t i = 0; i < myClassifiers.size(); ++i )
+ delete myClassifiers[ i ];
+ myClassifiers.clear();
+}
+
+bool ElementsOnShape::IsSatisfy (long elemId)
+{
+ const SMDS_MeshElement* elem =
+ ( myType == SMDSAbs_Node ? myMesh->FindNode( elemId ) : myMesh->FindElement( elemId ));
+ if ( !elem || myClassifiers.empty() )
+ return false;
- switch (myType)
+ for ( size_t i = 0; i < myClassifiers.size(); ++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;
+ SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator();
+ bool isSatisfy = myAllNodesFlag;
+
+ gp_XYZ centerXYZ (0, 0, 0);
+
+ while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
+ {
+ SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
+ centerXYZ += aPnt;
+ isSatisfy = ! myClassifiers[i]->IsOut( aPnt );
+ }
+
+ // Check the center point for volumes MantisBug 0020168
+ if (isSatisfy &&
+ myAllNodesFlag &&
+ myClassifiers[i]->ShapeType() == TopAbs_SOLID)
+ {
+ centerXYZ /= elem->NbNodes();
+ isSatisfy = ! myClassifiers[i]->IsOut( centerXYZ );
+ }
+ if ( isSatisfy )
+ return true;
}
- myShapesMap.Clear();
- addShape(myShape);
+ return false;
}
-void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
+TopAbs_ShapeEnum ElementsOnShape::TClassifier::ShapeType() const
{
- if (theShape.IsNull() || myMeshModifTracer.GetMesh() == 0)
- return;
+ return myShape.ShapeType();
+}
- if (!myShapesMap.Add(theShape)) return;
+bool ElementsOnShape::TClassifier::IsOut(const gp_Pnt& p)
+{
+ return (this->*myIsOutFun)( p );
+}
- myCurShapeType = theShape.ShapeType();
- switch (myCurShapeType)
+void ElementsOnShape::TClassifier::Init (const TopoDS_Shape& theShape, double theTol)
+{
+ myShape = theShape;
+ myTol = theTol;
+ switch ( myShape.ShapeType() )
{
- case TopAbs_COMPOUND:
- case TopAbs_COMPSOLID:
- case TopAbs_SHELL:
- case TopAbs_WIRE:
+ case TopAbs_SOLID: {
+ if ( isBox( theShape ))
{
- TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
- for (; anIt.More(); anIt.Next()) addShape(anIt.Value());
+ myIsOutFun = & ElementsOnShape::TClassifier::isOutOfBox;
}
- break;
- case TopAbs_SOLID:
+ else
{
- myCurSC.Load(theShape);
- process();
+ 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:
+ }
+ 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:{
+ myVertexXYZ = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) );
+ myIsOutFun = & ElementsOnShape::TClassifier::isOutOfVertex;
+ break;
+ }
+ default:
+ throw SALOME_Exception("Programmer error in usage of ElementsOnShape::TClassifier");
+ }
+}
+
+bool ElementsOnShape::TClassifier::isOutOfSolid (const gp_Pnt& p)
+{
+ mySolidClfr.Perform( p, myTol );
+ return ( mySolidClfr.State() != TopAbs_IN && mySolidClfr.State() != TopAbs_ON );
+}
+
+bool ElementsOnShape::TClassifier::isOutOfBox (const gp_Pnt& p)
+{
+ return myBox.IsOut( p.XYZ() );
+}
+
+bool ElementsOnShape::TClassifier::isOutOfFace (const gp_Pnt& p)
+{
+ myProjFace.Perform( p );
+ if ( myProjFace.IsDone() && myProjFace.LowerDistance() <= myTol )
+ {
+ // 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;
+}
+
+bool ElementsOnShape::TClassifier::isOutOfEdge (const gp_Pnt& p)
+{
+ myProjEdge.Perform( p );
+ return ! ( myProjEdge.NbPoints() > 0 && myProjEdge.LowerDistance() <= myTol );
+}
+
+bool ElementsOnShape::TClassifier::isOutOfVertex(const gp_Pnt& p)
+{
+ return ( myVertexXYZ.Distance( p ) > myTol );
+}
+
+bool ElementsOnShape::TClassifier::isBox (const TopoDS_Shape& theShape)
+{
+ TopTools_IndexedMapOfShape vMap;
+ TopExp::MapShapes( theShape, TopAbs_VERTEX, vMap );
+ if ( vMap.Extent() != 8 )
+ return false;
+
+ myBox.Clear();
+ for ( int i = 1; i <= 8; ++i )
+ myBox.Add( BRep_Tool::Pnt( TopoDS::Vertex( vMap( i ))).XYZ() );
+
+ gp_XYZ pMin = myBox.CornerMin(), pMax = myBox.CornerMax();
+ for ( int i = 1; i <= 8; ++i )
+ {
+ gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( vMap( i )));
+ for ( int iC = 1; iC <= 3; ++ iC )
{
- 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();
+ double d1 = Abs( pMin.Coord( iC ) - p.Coord( iC ));
+ double d2 = Abs( pMax.Coord( iC ) - p.Coord( iC ));
+ if ( Min( d1, d2 ) > myTol )
+ return false;
}
- break;
- case TopAbs_VERTEX:
+ }
+ myBox.Enlarge( myTol );
+ return true;
+}
+
+
+/*
+ Class : BelongToGeom
+ Description : Predicate for verifying whether entity belongs to
+ specified geometrical support
+*/
+
+BelongToGeom::BelongToGeom()
+ : myMeshDS(NULL),
+ myType(SMDSAbs_All),
+ myIsSubshape(false),
+ myTolerance(Precision::Confusion())
+{}
+
+void BelongToGeom::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMeshDS = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
+ init();
+}
+
+void BelongToGeom::SetGeom( const TopoDS_Shape& theShape )
+{
+ myShape = theShape;
+ init();
+}
+
+static bool IsSubShape (const TopTools_IndexedMapOfShape& theMap,
+ const TopoDS_Shape& theShape)
+{
+ if (theMap.Contains(theShape)) return true;
+
+ if (theShape.ShapeType() == TopAbs_COMPOUND ||
+ theShape.ShapeType() == TopAbs_COMPSOLID)
+ {
+ TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
+ for (; anIt.More(); anIt.Next())
{
- TopoDS_Vertex aV = TopoDS::Vertex(theShape);
- myCurPnt = BRep_Tool::Pnt(aV);
- process();
+ if (!IsSubShape(theMap, anIt.Value())) {
+ return false;
+ }
}
- break;
- default:
- break;
+ return true;
}
+
+ return false;
}
-void ElementsOnShape::process()
+void BelongToGeom::init()
{
- const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
- if (myShape.IsNull() || myMesh == 0)
- return;
+ if (!myMeshDS || myShape.IsNull()) return;
+
+ // is sub-shape of main shape?
+ TopoDS_Shape aMainShape = myMeshDS->ShapeToMesh();
+ if (aMainShape.IsNull()) {
+ myIsSubshape = false;
+ }
+ else {
+ TopTools_IndexedMapOfShape aMap;
+ TopExp::MapShapes(aMainShape, aMap);
+ myIsSubshape = IsSubShape(aMap, myShape);
+ }
- SMDS_ElemIteratorPtr anIter = myMesh->elementsIterator(myType);
- while (anIter->more())
- process(anIter->next());
+ //if (!myIsSubshape) // to be always ready to check an element not bound to geometry
+ {
+ myElementsOnShapePtr.reset(new ElementsOnShape());
+ myElementsOnShapePtr->SetTolerance(myTolerance);
+ myElementsOnShapePtr->SetAllNodes(true); // "belong", while false means "lays on"
+ myElementsOnShapePtr->SetMesh(myMeshDS);
+ myElementsOnShapePtr->SetShape(myShape, myType);
+ }
}
-void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr)
+static bool IsContains( const SMESHDS_Mesh* theMeshDS,
+ const TopoDS_Shape& theShape,
+ const SMDS_MeshElement* theElem,
+ TopAbs_ShapeEnum theFindShapeEnum,
+ TopAbs_ShapeEnum theAvoidShapeEnum = TopAbs_SHAPE )
{
- if (myShape.IsNull())
- return;
+ TopExp_Explorer anExp( theShape,theFindShapeEnum,theAvoidShapeEnum );
- SMDS_ElemIteratorPtr aNodeItr = theElemPtr->nodesIterator();
- bool isSatisfy = myAllNodesFlag;
+ while( anExp.More() )
+ {
+ const TopoDS_Shape& aShape = anExp.Current();
+ if( SMESHDS_SubMesh* aSubMesh = theMeshDS->MeshElements( aShape ) ){
+ if( aSubMesh->Contains( theElem ) )
+ return true;
+ }
+ anExp.Next();
+ }
+ return false;
+}
- gp_XYZ centerXYZ (0, 0, 0);
+bool BelongToGeom::IsSatisfy (long theId)
+{
+ if (myMeshDS == 0 || myShape.IsNull())
+ return false;
- while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
+ if (!myIsSubshape)
{
- SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
- centerXYZ += aPnt;
+ return myElementsOnShapePtr->IsSatisfy(theId);
+ }
- switch (myCurShapeType)
+ // Case of submesh
+ if (myType == SMDSAbs_Node)
+ {
+ if( const SMDS_MeshNode* aNode = myMeshDS->FindNode( theId ) )
{
- case TopAbs_SOLID:
+ if ( aNode->getshapeId() < 1 )
+ return myElementsOnShapePtr->IsSatisfy(theId);
+
+ const SMDS_PositionPtr& aPosition = aNode->GetPosition();
+ SMDS_TypeOfPosition aTypeOfPosition = aPosition->GetTypeOfPosition();
+ switch( aTypeOfPosition )
{
- myCurSC.Perform(aPnt, myToler);
- isSatisfy = (myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON);
+ case SMDS_TOP_VERTEX : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX ));
+ case SMDS_TOP_EDGE : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE ));
+ case SMDS_TOP_FACE : return ( IsContains( myMeshDS,myShape,aNode,TopAbs_FACE ));
+ case SMDS_TOP_3DSPACE: return ( IsContains( myMeshDS,myShape,aNode,TopAbs_SOLID ) ||
+ IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL ));
}
- break;
- case TopAbs_FACE:
+ }
+ }
+ else
+ {
+ if ( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ))
+ {
+ if ( anElem->getshapeId() < 1 )
+ return myElementsOnShapePtr->IsSatisfy(theId);
+
+ if( myType == SMDSAbs_All )
+ {
+ return ( IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
+ }
+ else if( myType == anElem->GetType() )
{
- myCurProjFace.Perform(aPnt);
- isSatisfy = (myCurProjFace.IsDone() && myCurProjFace.LowerDistance() <= myToler);
- if (isSatisfy)
+ switch( myType )
{
- // 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);
+ case SMDSAbs_Edge : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ));
+ case SMDSAbs_Face : return ( IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ));
+ case SMDSAbs_Volume: return ( IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID )||
+ IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL ));
}
}
- break;
- case TopAbs_EDGE:
+ }
+ }
+
+ return false;
+}
+
+void BelongToGeom::SetType (SMDSAbs_ElementType theType)
+{
+ myType = theType;
+ init();
+}
+
+SMDSAbs_ElementType BelongToGeom::GetType() const
+{
+ return myType;
+}
+
+TopoDS_Shape BelongToGeom::GetShape()
+{
+ return myShape;
+}
+
+const SMESHDS_Mesh* BelongToGeom::GetMeshDS() const
+{
+ return myMeshDS;
+}
+
+void BelongToGeom::SetTolerance (double theTolerance)
+{
+ myTolerance = theTolerance;
+ if (!myIsSubshape)
+ init();
+}
+
+double BelongToGeom::GetTolerance()
+{
+ return myTolerance;
+}
+
+/*
+ Class : LyingOnGeom
+ Description : Predicate for verifying whether entiy lying or partially lying on
+ specified geometrical support
+*/
+
+LyingOnGeom::LyingOnGeom()
+ : myMeshDS(NULL),
+ myType(SMDSAbs_All),
+ myIsSubshape(false),
+ myTolerance(Precision::Confusion())
+{}
+
+void LyingOnGeom::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMeshDS = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
+ init();
+}
+
+void LyingOnGeom::SetGeom( const TopoDS_Shape& theShape )
+{
+ myShape = theShape;
+ init();
+}
+
+void LyingOnGeom::init()
+{
+ if (!myMeshDS || myShape.IsNull()) return;
+
+ // is sub-shape of main shape?
+ TopoDS_Shape aMainShape = myMeshDS->ShapeToMesh();
+ if (aMainShape.IsNull()) {
+ myIsSubshape = false;
+ }
+ else {
+ TopTools_IndexedMapOfShape aMap;
+ TopExp::MapShapes(aMainShape, aMap);
+ myIsSubshape = IsSubShape(aMap, myShape);
+ }
+
+ if (!myIsSubshape)
+ {
+ myElementsOnShapePtr.reset(new ElementsOnShape());
+ myElementsOnShapePtr->SetTolerance(myTolerance);
+ myElementsOnShapePtr->SetAllNodes(false); // lays on, while true means "belong"
+ myElementsOnShapePtr->SetMesh(myMeshDS);
+ myElementsOnShapePtr->SetShape(myShape, myType);
+ }
+}
+
+bool LyingOnGeom::IsSatisfy( long theId )
+{
+ if ( myMeshDS == 0 || myShape.IsNull() )
+ return false;
+
+ if (!myIsSubshape)
+ {
+ return myElementsOnShapePtr->IsSatisfy(theId);
+ }
+
+ // Case of submesh
+ if( myType == SMDSAbs_Node )
+ {
+ if( const SMDS_MeshNode* aNode = myMeshDS->FindNode( theId ) )
+ {
+ const SMDS_PositionPtr& aPosition = aNode->GetPosition();
+ SMDS_TypeOfPosition aTypeOfPosition = aPosition->GetTypeOfPosition();
+ switch( aTypeOfPosition )
{
- myCurProjEdge.Perform(aPnt);
- isSatisfy = (myCurProjEdge.NbPoints() > 0 && myCurProjEdge.LowerDistance() <= myToler);
+ case SMDS_TOP_VERTEX : return IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX );
+ case SMDS_TOP_EDGE : return IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE );
+ case SMDS_TOP_FACE : return IsContains( myMeshDS,myShape,aNode,TopAbs_FACE );
+ case SMDS_TOP_3DSPACE: return IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL );
}
- break;
- case TopAbs_VERTEX:
+ }
+ }
+ else
+ {
+ if( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ) )
+ {
+ if( myType == SMDSAbs_All )
{
- isSatisfy = (myCurPnt.Distance(aPnt) <= myToler);
+ return Contains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
+ Contains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
+ Contains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
+ Contains( myMeshDS,myShape,anElem,TopAbs_SOLID );
}
- break;
- default:
+ else if( myType == anElem->GetType() )
{
- isSatisfy = false;
+ switch( myType )
+ {
+ case SMDSAbs_Edge : return Contains( myMeshDS,myShape,anElem,TopAbs_EDGE );
+ case SMDSAbs_Face : return Contains( myMeshDS,myShape,anElem,TopAbs_FACE );
+ case SMDSAbs_Volume: return Contains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
+ Contains( myMeshDS,myShape,anElem,TopAbs_SOLID );
+ }
}
}
}
- 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;
- }
+ return false;
+}
+
+void LyingOnGeom::SetType( SMDSAbs_ElementType theType )
+{
+ myType = theType;
+ init();
+}
+
+SMDSAbs_ElementType LyingOnGeom::GetType() const
+{
+ return myType;
+}
+
+TopoDS_Shape LyingOnGeom::GetShape()
+{
+ return myShape;
+}
+
+const SMESHDS_Mesh* LyingOnGeom::GetMeshDS() const
+{
+ return myMeshDS;
+}
- if (isSatisfy)
- myIds.Add(theElemPtr->GetID());
+void LyingOnGeom::SetTolerance (double theTolerance)
+{
+ myTolerance = theTolerance;
+ if (!myIsSubshape)
+ init();
+}
+
+double LyingOnGeom::GetTolerance()
+{
+ return myTolerance;
+}
+
+bool LyingOnGeom::Contains( const SMESHDS_Mesh* theMeshDS,
+ const TopoDS_Shape& theShape,
+ const SMDS_MeshElement* theElem,
+ TopAbs_ShapeEnum theFindShapeEnum,
+ TopAbs_ShapeEnum theAvoidShapeEnum )
+{
+ if (IsContains(theMeshDS, theShape, theElem, theFindShapeEnum, theAvoidShapeEnum))
+ return true;
+
+ TopTools_IndexedMapOfShape aSubShapes;
+ TopExp::MapShapes( theShape, aSubShapes );
+
+ for (int i = 1; i <= aSubShapes.Extent(); i++)
+ {
+ const TopoDS_Shape& aShape = aSubShapes.FindKey(i);
+
+ if( SMESHDS_SubMesh* aSubMesh = theMeshDS->MeshElements( aShape ) ){
+ if( aSubMesh->Contains( theElem ) )
+ return true;
+
+ SMDS_NodeIteratorPtr aNodeIt = aSubMesh->GetNodes();
+ while ( aNodeIt->more() )
+ {
+ const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(aNodeIt->next());
+ SMDS_ElemIteratorPtr anElemIt = aNode->GetInverseElementIterator();
+ while ( anElemIt->more() )
+ {
+ const SMDS_MeshElement* anElement = static_cast<const SMDS_MeshElement*>(anElemIt->next());
+ if (anElement == theElem)
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
TSequenceOfXYZ::TSequenceOfXYZ()