-// 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
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
#include "SMESH_ControlsDef.hxx"
#include "SMESHDS_GroupBase.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_OctreeNode.hxx"
+#include "SMESH_MeshAlgos.hxx"
#include <BRepAdaptor_Surface.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <set>
#include <limits>
+#include <Basics_Utils.hxx>
/*
AUXILIARY METHODS
* FUNCTORS
*/
+//================================================================================
/*
Class : NumericalFunctor
Description : Base class for numerical functors
*/
+//================================================================================
+
NumericalFunctor::NumericalFunctor():
myMesh(NULL)
{
* \param minmax - boundaries of diapason of values to divide into intervals
*/
//================================================================================
+
void NumericalFunctor::GetHistogram(int nbIntervals,
std::vector<int>& nbEvents,
std::vector<double>& funValues,
}
//=======================================================================
-//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( const TSequenceOfXYZ& P )
{
if(P.size() == 0)
Class : MaxElementLength3D
Description : Functor calculating maximum length of 3D element
*/
+//================================================================================
double MaxElementLength3D::GetValue( long theElementId )
{
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;
}
+//================================================================================
/*
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,
}
+//================================================================================
/*
Class : Taper
Description : Functor for calculating taper
*/
+//================================================================================
+
double Taper::GetValue( const TSequenceOfXYZ& P )
{
if ( P.size() != 4 )
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 < theEps )
- return theInf;
+ 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;
}
+//================================================================================
/*
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()
{
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 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<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 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<SMESH_ElementSearcher> 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