-// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2011 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
+// 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.
+// 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.
//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// 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_Mesh.hxx"
#include "SMESHDS_GroupBase.hxx"
+#include "SMESH_OctreeNode.hxx"
+
+#include <vtkMeshQuality.h>
+
/*
AUXILIARY METHODS
*/
if ( anElem->IsQuadratic() ) {
switch ( anElem->GetType() ) {
case SMDSAbs_Edge:
- anIter = static_cast<const SMDS_QuadraticEdge*>
+ anIter = dynamic_cast<const SMDS_VtkEdge*>
(anElem)->interlacedNodesElemIterator();
break;
case SMDSAbs_Face:
- anIter = static_cast<const SMDS_QuadraticFaceOfNodes*>
+ anIter = dynamic_cast<const SMDS_VtkFace*>
(anElem)->interlacedNodesElemIterator();
break;
default:
void NumericalFunctor::SetPrecision( const long thePrecision )
{
myPrecision = thePrecision;
+ myPrecisionValue = pow( 10., (double)( myPrecision ) );
}
double NumericalFunctor::GetValue( long theId )
{
+ double aVal = 0;
+
myCurrElement = myMesh->FindElement( theId );
+
TSequenceOfXYZ P;
if ( GetPoints( theId, P ))
- {
- double aVal = GetValue( P );
- if ( myPrecision >= 0 )
- {
- double prec = pow( 10., (double)( myPrecision ) );
- aVal = floor( aVal * prec + 0.5 ) / prec;
- }
- return aVal;
- }
+ aVal = Round( GetValue( P ));
- return 0.;
+ return aVal;
+}
+
+double NumericalFunctor::Round( const double & aVal )
+{
+ return ( myPrecision >= 0 ) ? floor( aVal * myPrecisionValue + 0.5 ) / myPrecisionValue : aVal;
}
//================================================================================
* \param nbIntervals - number of intervals
* \param nbEvents - number of mesh elements having values within i-th interval
* \param funValues - boundaries of intervals
+ * \param elements - elements to check vulue of; empty list means "of all"
+ * \param minmax - boundaries of diapason of values to divide into intervals
*/
//================================================================================
void NumericalFunctor::GetHistogram(int nbIntervals,
std::vector<int>& nbEvents,
- std::vector<double>& funValues)
+ std::vector<double>& funValues,
+ const vector<int>& elements,
+ const double* minmax)
{
if ( nbIntervals < 1 ||
!myMesh ||
// get all values sorted
std::multiset< double > values;
- SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType());
- while ( elemIt->more() )
- values.insert( GetValue( elemIt->next()->GetID() ));
+ if ( elements.empty() )
+ {
+ SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType());
+ while ( elemIt->more() )
+ values.insert( GetValue( elemIt->next()->GetID() ));
+ }
+ else
+ {
+ vector<int>::const_iterator id = elements.begin();
+ for ( ; id != elements.end(); ++id )
+ values.insert( GetValue( *id ));
+ }
+ if ( minmax )
+ {
+ funValues[0] = minmax[0];
+ funValues[nbIntervals] = minmax[1];
+ }
+ else
+ {
+ funValues[0] = *values.begin();
+ funValues[nbIntervals] = *values.rbegin();
+ }
// case nbIntervals == 1
- funValues[0] = *values.begin();
- funValues[nbIntervals] = *values.rbegin();
if ( nbIntervals == 1 )
{
nbEvents[0] = values.size();
std::multiset< double >::iterator min = values.begin(), max;
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;
+
+ // count values in the i-th interval if there are any
if ( min != values.end() && *min <= funValues[i+1] )
{
- max = values.upper_bound( funValues[i+1] ); // greater than funValues[i+1], or end()
+ // find the first value out of the interval
+ max = values.upper_bound( funValues[i+1] ); // max is greater than funValues[i+1], or end()
nbEvents[i] = std::distance( min, max );
min = max;
}
}
+ // add values larger than minmax[1]
+ nbEvents.back() += std::distance( min, values.end() );
}
//=======================================================================
aVal = Max(L1,Max(L2,L3));
break;
}
- else if( len == 8 ) { // quadratic quadrangles
+ 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 ));
aVal = Max(aVal,Max(Max(D1,D2),Max(D3,D4)));
break;
}
+ else if( len == 12 ) { // hexagonal prism
+ for ( int i1 = 1; i1 < 12; ++i1 )
+ for ( int i2 = i1+1; i1 <= 12; ++i1 )
+ aVal = Max( aVal, getDistance(P( i1 ),P( i2 )));
+ break;
+ }
else if( len == 10 ) { // quadratic tetras
double L1 = getDistance(P( 1 ),P( 5 )) + getDistance(P( 5 ),P( 2 ));
double L2 = getDistance(P( 2 ),P( 6 )) + getDistance(P( 6 ),P( 3 ));
aVal = Max(aVal,Max(Max(L7,L8),L9));
break;
}
- else if( len == 20 ) { // quadratic hexas
+ else if( len == 20 || len == 27 ) { // quadratic hexas
double L1 = getDistance(P( 1 ),P( 9 )) + getDistance(P( 9 ),P( 2 ));
double L2 = getDistance(P( 2 ),P( 10 )) + getDistance(P( 10 ),P( 3 ));
double L3 = getDistance(P( 3 ),P( 11 )) + getDistance(P( 11 ),P( 4 ));
aMin = Min(aMin,A0);
}
- return aMin * 180.0 / PI;
+ return aMin * 180.0 / M_PI;
}
double MinimumAngle::GetBadRate( double Value, int nbNodes ) const
return 0.;
return alpha * L * C1 / C2;
}
- else if( nbNodes == 8 ){ // nbNodes==8 - quadratic quadrangle
+ else if( nbNodes == 8 || nbNodes == 9 ) { // nbNodes==8 - quadratic quadrangle
// Compute lengths of the sides
std::vector< double > aLen (4);
aLen[0] = getDistance( P(1), P(3) );
double AspectRatio::GetBadRate( double Value, int /*nbNodes*/ ) const
{
// the aspect ratio is in the range [1.0,infinity]
+ // < 1.0 = very bad, zero area
// 1.0 = good
// infinity = bad
- return Value / 1000.;
+ return ( Value < 0.9 ) ? 1000 : Value / 1000.;
}
SMDSAbs_ElementType AspectRatio::GetType() const
}
+double AspectRatio3D::GetValue( long theId )
+{
+ double aVal = 0;
+ myCurrElement = myMesh->FindElement( theId );
+ if ( myCurrElement && myCurrElement->GetVtkType() == VTK_TETRA )
+ {
+ // Action from CoTech | ACTION 31.3:
+ // EURIWARE BO: Homogenize the formulas used to calculate the Controls in SMESH to fit with
+ // those of ParaView. The library used by ParaView for those calculations can be reused in SMESH.
+ vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myCurrElement->getMeshId()]->getGrid();
+ if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->getVtkId() ))
+ aVal = Round( vtkMeshQuality::TetAspectRatio( avtkCell ));
+ }
+ else
+ {
+ TSequenceOfXYZ P;
+ if ( GetPoints( myCurrElement, P ))
+ aVal = Round( GetValue( P ));
+ }
+ return aVal;
+}
+
double AspectRatio3D::GetValue( const TSequenceOfXYZ& P )
{
double aQuality = 0.0;
else if(nbNodes==13) nbNodes=5; // quadratic pyramid
else if(nbNodes==15) nbNodes=6; // quadratic pentahedron
else if(nbNodes==20) nbNodes=8; // quadratic hexahedron
+ else if(nbNodes==27) nbNodes=8; // quadratic hexahedron
else return aQuality;
}
- switch(nbNodes){
+ switch(nbNodes) {
case 4:{
double aLen[6] = {
getDistance(P( 1 ),P( 2 )), // a
}
break;
}
- }
+ case 12:
+ {
+ gp_XYZ aXYZ[8] = {P( 1 ),P( 2 ),P( 4 ),P( 5 ),P( 7 ),P( 8 ),P( 10 ),P( 11 )};
+ aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[8])),aQuality);
+ }
+ {
+ gp_XYZ aXYZ[8] = {P( 2 ),P( 3 ),P( 5 ),P( 6 ),P( 8 ),P( 9 ),P( 11 ),P( 12 )};
+ aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[8])),aQuality);
+ }
+ {
+ gp_XYZ aXYZ[8] = {P( 3 ),P( 4 ),P( 6 ),P( 1 ),P( 9 ),P( 10 ),P( 12 ),P( 7 )};
+ aQuality = std::max(GetValue(TSequenceOfXYZ(&aXYZ[0],&aXYZ[8])),aQuality);
+ }
+ break;
+ } // switch(nbNodes)
+
if ( nbNodes > 4 ) {
// avaluate aspect ratio of quadranle faces
AspectRatio aspect2D;
gp_XYZ N = GI.Crossed( GJ );
if ( N.Modulus() < gp::Resolution() )
- return PI / 2;
+ return M_PI / 2;
N.Normalize();
double H = ( thePnt2 - theG ).Dot( N );
- return asin( fabs( H / L ) ) * 180. / PI;
+ return asin( fabs( H / L ) ) * 180. / M_PI;
}
double Warping::GetBadRate( double Value, int /*nbNodes*/ ) const
return 0.;
// Compute skew
- static double PI2 = PI / 2.;
+ static double PI2 = M_PI / 2.;
if ( P.size() == 3 )
{
double A0 = fabs( PI2 - skewAngle( P( 3 ), P( 1 ), P( 2 ) ) );
double A1 = fabs( PI2 - skewAngle( P( 1 ), P( 2 ), P( 3 ) ) );
double A2 = fabs( PI2 - skewAngle( P( 2 ), P( 3 ), P( 1 ) ) );
- return Max( A0, Max( A1, A2 ) ) * 180. / PI;
+ return Max( A0, Max( A1, A2 ) ) * 180. / M_PI;
}
else
{
if ( A < Precision::Angular() )
return 0.;
- return A * 180. / PI;
+ return A * 180. / M_PI;
}
}
/*
Class : Length
- Description : Functor for calculating length off edge
+ Description : Functor for calculating length of edge
*/
double Length::GetValue( const TSequenceOfXYZ& P )
{
const SMDS_MeshFace* anElem = anIter->next();
if(anElem->IsQuadratic()) {
- const SMDS_QuadraticFaceOfNodes* F =
- static_cast<const SMDS_QuadraticFaceOfNodes*>(anElem);
+ const SMDS_VtkFace* F =
+ dynamic_cast<const SMDS_VtkFace*>(anElem);
// use special nodes iterator
- SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+ SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
long aNodeId[4];
gp_Pnt P[4];
const SMDS_MeshFace* anElem = anIter->next();
SMDS_ElemIteratorPtr aNodesIter;
if ( anElem->IsQuadratic() )
- aNodesIter = static_cast<const SMDS_QuadraticFaceOfNodes*>
+ aNodesIter = dynamic_cast<const SMDS_VtkFace*>
(anElem)->interlacedNodesElemIterator();
else
aNodesIter = anElem->nodesIterator();
return SMDSAbs_Volume;
}
+/*
+ Class : BareBorderVolume
+*/
+
+bool BareBorderVolume::IsSatisfy(long theElementId )
+{
+ SMDS_VolumeTool myTool;
+ if ( myTool.Set( myMesh->FindElement(theElementId)))
+ {
+ for ( int iF = 0; iF < myTool.NbFaces(); ++iF )
+ if ( myTool.IsFreeFace( iF ))
+ {
+ const SMDS_MeshNode** n = myTool.GetFaceNodes(iF);
+ vector< const SMDS_MeshNode*> nodes( n, n+myTool.NbFaceNodes(iF));
+ if ( !myMesh->FindElement( nodes, SMDSAbs_Face, /*Nomedium=*/false))
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ Class : BareBorderFace
+*/
+
+bool BareBorderFace::IsSatisfy(long theElementId )
+{
+ bool ok = false;
+ if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId))
+ {
+ if ( face->GetType() == SMDSAbs_Face )
+ {
+ int nbN = face->NbCornerNodes();
+ for ( int i = 0; i < nbN && !ok; ++i )
+ {
+ // check if a link is shared by another face
+ const SMDS_MeshNode* n1 = face->GetNode( i );
+ const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN );
+ SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face );
+ bool isShared = false;
+ while ( !isShared && fIt->more() )
+ {
+ const SMDS_MeshElement* f = fIt->next();
+ isShared = ( f != face && f->GetNodeIndex(n2) != -1 );
+ }
+ if ( !isShared )
+ {
+ const int iQuad = face->IsQuadratic();
+ myLinkNodes.resize( 2 + iQuad);
+ myLinkNodes[0] = n1;
+ myLinkNodes[1] = n2;
+ if ( iQuad )
+ myLinkNodes[2] = face->GetNode( i+nbN );
+ ok = !myMesh->FindElement( myLinkNodes, SMDSAbs_Edge, /*noMedium=*/false);
+ }
+ }
+ }
+ }
+ return ok;
+}
+
+/*
+ Class : OverConstrainedVolume
+*/
+
+bool OverConstrainedVolume::IsSatisfy(long theElementId )
+{
+ // An element is over-constrained if it has N-1 free borders where
+ // N is the number of edges/faces for a 2D/3D element.
+ SMDS_VolumeTool myTool;
+ if ( myTool.Set( myMesh->FindElement(theElementId)))
+ {
+ int nbSharedFaces = 0;
+ for ( int iF = 0; iF < myTool.NbFaces(); ++iF )
+ if ( !myTool.IsFreeFace( iF ) && ++nbSharedFaces > 1 )
+ break;
+ return ( nbSharedFaces == 1 );
+ }
+ return false;
+}
+
+/*
+ Class : OverConstrainedFace
+*/
+
+bool OverConstrainedFace::IsSatisfy(long theElementId )
+{
+ // An element is over-constrained if it has N-1 free borders where
+ // N is the number of edges/faces for a 2D/3D element.
+ if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId))
+ if ( face->GetType() == SMDSAbs_Face )
+ {
+ int nbSharedBorders = 0;
+ int nbN = face->NbCornerNodes();
+ for ( int i = 0; i < nbN; ++i )
+ {
+ // check if a link is shared by another face
+ const SMDS_MeshNode* n1 = face->GetNode( i );
+ const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN );
+ SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face );
+ bool isShared = false;
+ while ( !isShared && fIt->more() )
+ {
+ const SMDS_MeshElement* f = fIt->next();
+ isShared = ( f != face && f->GetNodeIndex(n2) != -1 );
+ }
+ if ( isShared && ++nbSharedBorders > 1 )
+ break;
+ }
+ return ( nbSharedBorders == 1 );
+ }
+ return false;
+}
+
+/*
+ Class : CoincidentNodes
+ Description : Predicate of Coincident nodes
+*/
+
+CoincidentNodes::CoincidentNodes()
+{
+ myToler = 1e-5;
+}
+
+bool CoincidentNodes::IsSatisfy( long theElementId )
+{
+ return myCoincidentIDs.Contains( theElementId );
+}
+
+SMDSAbs_ElementType CoincidentNodes::GetType() const
+{
+ return SMDSAbs_Node;
+}
+
+void CoincidentNodes::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMeshModifTracer.SetMesh( theMesh );
+ if ( myMeshModifTracer.IsMeshModified() )
+ {
+ TIDSortedNodeSet nodesToCheck;
+ SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(/*idInceasingOrder=*/true);
+ while ( nIt->more() )
+ nodesToCheck.insert( nodesToCheck.end(), nIt->next() );
+
+ list< list< const SMDS_MeshNode*> > nodeGroups;
+ SMESH_OctreeNode::FindCoincidentNodes ( nodesToCheck, &nodeGroups, myToler );
+
+ myCoincidentIDs.Clear();
+ list< list< const SMDS_MeshNode*> >::iterator groupIt = nodeGroups.begin();
+ for ( ; groupIt != nodeGroups.end(); ++groupIt )
+ {
+ list< const SMDS_MeshNode*>& coincNodes = *groupIt;
+ list< const SMDS_MeshNode*>::iterator n = coincNodes.begin();
+ for ( ; n != coincNodes.end(); ++n )
+ myCoincidentIDs.Add( (*n)->GetID() );
+ }
+ }
+}
+
+/*
+ Class : CoincidentElements
+ Description : Predicate of Coincident Elements
+ Note : This class is suitable only for visualization of Coincident Elements
+*/
+
+CoincidentElements::CoincidentElements()
+{
+ myMesh = 0;
+}
+
+void CoincidentElements::SetMesh( const SMDS_Mesh* theMesh )
+{
+ myMesh = theMesh;
+}
+
+bool CoincidentElements::IsSatisfy( long theElementId )
+{
+ if ( !myMesh ) return false;
+
+ if ( const SMDS_MeshElement* e = myMesh->FindElement( theElementId ))
+ {
+ if ( e->GetType() != GetType() ) return false;
+ set< const SMDS_MeshNode* > elemNodes( e->begin_nodes(), e->end_nodes() );
+ const int nbNodes = e->NbNodes();
+ SMDS_ElemIteratorPtr invIt = (*elemNodes.begin())->GetInverseElementIterator( GetType() );
+ while ( invIt->more() )
+ {
+ const SMDS_MeshElement* e2 = invIt->next();
+ if ( e2 == e || e2->NbNodes() != nbNodes ) continue;
+
+ bool sameNodes = true;
+ for ( size_t i = 0; i < elemNodes.size() && sameNodes; ++i )
+ sameNodes = ( elemNodes.count( e2->GetNode( i )));
+ if ( sameNodes )
+ return true;
+ }
+ }
+ return false;
+}
+
+SMDSAbs_ElementType CoincidentElements1D::GetType() const
+{
+ return SMDSAbs_Edge;
+}
+SMDSAbs_ElementType CoincidentElements2D::GetType() const
+{
+ return SMDSAbs_Face;
+}
+SMDSAbs_ElementType CoincidentElements3D::GetType() const
+{
+ return SMDSAbs_Volume;
+}
/*
TColStd_MapOfInteger aMap;
for ( int i = 0; i < 2; i++ )
{
- SMDS_ElemIteratorPtr anElemIter = theNodes[ i ]->GetInverseElementIterator();
+ SMDS_ElemIteratorPtr anElemIter = theNodes[ i ]->GetInverseElementIterator(SMDSAbs_Face);
while( anElemIter->more() )
{
- const SMDS_MeshElement* anElem = anElemIter->next();
- if ( anElem != 0 && anElem->GetType() == SMDSAbs_Face )
+ if ( const SMDS_MeshElement* anElem = anElemIter->next())
{
- int anId = anElem->GetID();
-
- if ( i == 0 )
- aMap.Add( anId );
- else if ( aMap.Contains( anId ) && anId != theFaceId )
+ const int anId = anElem->GetID();
+ if ( anId != theFaceId && !aMap.Add( anId ))
return false;
}
}
SMDS_ElemIteratorPtr anIter;
if ( aFace->IsQuadratic() ) {
- anIter = static_cast<const SMDS_QuadraticFaceOfNodes*>
+ anIter = dynamic_cast<const SMDS_VtkFace*>
(aFace)->interlacedNodesElemIterator();
}
else {
anIter = aFace->nodesIterator();
}
- if ( anIter == 0 )
+ if ( !anIter )
return false;
int i = 0, nbNodes = aFace->NbNodes();
long anElemId = anElem->GetID();
SMDS_ElemIteratorPtr aNodesIter;
if ( anElem->IsQuadratic() )
- aNodesIter = static_cast<const SMDS_QuadraticFaceOfNodes*>(anElem)->
+ aNodesIter = static_cast<const SMDS_VtkFace*>(anElem)->
interlacedNodesElemIterator();
else
aNodesIter = anElem->nodesIterator();
long anId = aNode->GetID();
Border aBorder(anElemId,aNodeId[1],anId);
aNodeId[1] = anId;
- //std::cout<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<"; "<<aBorder.myElemId<<endl;
UpdateBorders(aBorder,aRegistry,theBorders);
}
Border aBorder(anElemId,aNodeId[0],aNodeId[1]);
- //std::cout<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<"; "<<aBorder.myElemId<<endl;
UpdateBorders(aBorder,aRegistry,theBorders);
}
- //std::cout<<"theBorders.size() = "<<theBorders.size()<<endl;
}
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 == 4));
+ isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? ( aNbNode == 8 || aNbNode == 9 ) : aNbNode == 4));
else if ( myGeomType == SMDSGeom_POLYGON )
isOk = anElem->IsPoly();
break;
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 == 8));
+ 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;
//================================================================================
CoplanarFaces::CoplanarFaces()
- : myMesh(0), myFaceID(0), myToler(0)
+ : myFaceID(0), myToler(0)
{
}
-bool CoplanarFaces::IsSatisfy( long theElementId )
+void CoplanarFaces::SetMesh( const SMDS_Mesh* theMesh )
{
- if ( myCoplanarIDs.empty() )
+ myMeshModifTracer.SetMesh( theMesh );
+ if ( myMeshModifTracer.IsMeshModified() )
{
// Build a set of coplanar face ids
- if ( !myMesh || !myFaceID || !myToler )
- return false;
+ myCoplanarIDs.clear();
+
+ if ( !myMeshModifTracer.GetMesh() || !myFaceID || !myToler )
+ return;
- const SMDS_MeshElement* face = myMesh->FindElement( myFaceID );
+ const SMDS_MeshElement* face = myMeshModifTracer.GetMesh()->FindElement( myFaceID );
if ( !face || face->GetType() != SMDSAbs_Face )
- return false;
+ return;
bool normOK;
gp_Vec myNorm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
if (!normOK)
- return false;
+ return;
- const double radianTol = myToler * PI180;
+ const double radianTol = myToler * M_PI / 180.;
typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TFaceIt;
std::set<const SMDS_MeshElement*> checkedFaces, checkedNodes;
std::list<const SMDS_MeshElement*> faceQueue( 1, face );
faceQueue.pop_front();
}
}
+}
+bool CoplanarFaces::IsSatisfy( long theElementId )
+{
return myCoplanarIDs.count( theElementId );
}
while ( aMinStr.Search( "-" ) != -1 ) aMinStr.RemoveAll( '-' );
while ( aMaxStr.Search( "-" ) != -1 ) aMaxStr.RemoveAll( '-' );
- if ( !aMinStr.IsEmpty() && !aMinStr.IsIntegerValue() ||
- !aMaxStr.IsEmpty() && !aMaxStr.IsIntegerValue() )
+ if ( (!aMinStr.IsEmpty() && !aMinStr.IsIntegerValue()) ||
+ (!aMaxStr.IsEmpty() && !aMaxStr.IsIntegerValue()) )
return false;
myMin.Append( aMinStr.IsEmpty() ? IntegerFirst() : aMinStr.IntegerValue() );
else
{
const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
- if ( anElem == 0 || myType != anElem->GetType() && myType != SMDSAbs_All )
+ if ( anElem == 0 || (myType != anElem->GetType() && myType != SMDSAbs_All ))
return false;
}
return
myPredicate1 &&
myPredicate2 &&
- myPredicate1->IsSatisfy( theId ) ||
- myPredicate2->IsSatisfy( theId );
+ (myPredicate1->IsSatisfy( theId ) ||
+ myPredicate2->IsSatisfy( theId ));
}
void ManifoldPart::getFacesByLink( const ManifoldPart::Link& theLink,
ManifoldPart::TVectorOfFacePtr& theFaces ) const
{
- SMDS_Mesh::SetOfFaces aSetOfFaces;
+ std::set<SMDS_MeshCell *> aSetOfFaces;
// take all faces that shared first node
SMDS_ElemIteratorPtr anItr = theLink.myNode1->facesIterator();
for ( ; anItr->more(); )
SMDS_MeshFace* aFace = (SMDS_MeshFace*)anItr->next();
if ( !aFace )
continue;
- aSetOfFaces.Add( aFace );
+ aSetOfFaces.insert( aFace );
}
// take all faces that shared second node
anItr = theLink.myNode2->facesIterator();
for ( ; anItr->more(); )
{
SMDS_MeshFace* aFace = (SMDS_MeshFace*)anItr->next();
- if ( aSetOfFaces.Contains( aFace ) )
+ if ( aSetOfFaces.count( aFace ) )
theFaces.push_back( aFace );
}
}
*/
ElementsOnShape::ElementsOnShape()
- : myMesh(0),
+ : //myMesh(0),
myType(SMDSAbs_All),
myToler(Precision::Confusion()),
myAllNodesFlag(false)
void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
{
- if (myMesh != theMesh) {
- myMesh = theMesh;
+ myMeshModifTracer.SetMesh( theMesh );
+ if ( myMeshModifTracer.IsMeshModified())
SetShape(myShape, myType);
- }
}
bool ElementsOnShape::IsSatisfy (long theElementId)
myShape = theShape;
myIds.Clear();
- if (myMesh == 0) return;
+ const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
+
+ if ( !myMesh ) return;
switch (myType)
{
void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
{
- if (theShape.IsNull() || myMesh == 0)
+ if (theShape.IsNull() || myMeshModifTracer.GetMesh() == 0)
return;
if (!myShapesMap.Add(theShape)) return;
void ElementsOnShape::process()
{
+ const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
if (myShape.IsNull() || myMesh == 0)
return;
{
return myArray.size();
}
+
+TMeshModifTracer::TMeshModifTracer():
+ myMeshModifTime(0), myMesh(0)
+{
+}
+void TMeshModifTracer::SetMesh( const SMDS_Mesh* theMesh )
+{
+ if ( theMesh != myMesh )
+ myMeshModifTime = 0;
+ myMesh = theMesh;
+}
+bool TMeshModifTracer::IsMeshModified()
+{
+ bool modified = false;
+ if ( myMesh )
+ {
+ modified = ( myMeshModifTime != myMesh->GetMTime() );
+ myMeshModifTime = myMesh->GetMTime();
+ }
+ return modified;
+}