-// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2020 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
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// SMESH SMESH : implementaion of SMESH idl descriptions
+// SMESH SMESH : implementation of SMESH idl descriptions
// File : SMESH_subMesh.cxx
// Author : Paul RASCLE, EDF
// Module : SMESH
#include "SMESH_subMesh.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
#include "SMESH_Algo.hxx"
+#include "SMESH_Comment.hxx"
#include "SMESH_Gen.hxx"
#include "SMESH_HypoFilter.hxx"
#include "SMESH_Hypothesis.hxx"
#include "SMESH_Mesh.hxx"
#include "SMESH_MesherHelper.hxx"
#include "SMESH_subMeshEventListener.hxx"
-#include "SMESH_Comment.hxx"
-#include "SMDS_SetIterator.hxx"
-#include "SMDSAbs_ElementType.hxx"
-
-#include <Basics_OCCTVersion.hxx>
#include "utilities.h"
#include "OpUtil.hxx"
using namespace std;
+#ifdef _DEBUG_
+// enable printing algo + shape id + hypo used while meshing
+//#define PRINT_WHO_COMPUTE_WHAT
+#endif
+
//=============================================================================
/*!
* \brief Allocate some memory at construction and release it at destruction.
}
_computeCost = 0; // how costly is to compute this sub-mesh
_realComputeCost = 0;
+ _allowedSubShapes = nullptr;
}
//=============================================================================
if ( !_algo )
{
SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this );
- me->_algo = _father->GetGen()->GetAlgo( me );
+ me->_algo = _father->GetGen()->GetAlgo( me, & me->_algoShape );
}
return _algo;
}
{
if ( _alwaysComputed )
return true;
- // algo may bind a submesh not to _subShape, eg 3D algo
+ // algo may bind a sub-mesh not to _subShape, eg 3D algo
// sets nodes on SHELL while _subShape may be SOLID
SMESHDS_Mesh* meshDS = _father->GetMeshDS();
return false;
}
+//================================================================================
+/*!
+ * \brief Check if any upper level sub-shape is not computed.
+ * Used to update a sub-mesh icon
+ */
+//================================================================================
+
+bool SMESH_subMesh::IsComputedPartially() const
+{
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(/*includeSelf=*/true,
+ /*SolidFirst=*/true);
+ bool allComputed = true;
+ TopAbs_ShapeEnum readyType = TopAbs_VERTEX; // max value
+ while ( smIt->more() && allComputed )
+ {
+ SMESH_subMesh* sm = smIt->next();
+
+ if ( sm->GetSubShape().ShapeType() > readyType )
+ break; // lower dimension -> stop
+ if ( sm->GetComputeState() != SMESH_subMesh::NOT_READY )
+ readyType = sm->GetSubShape().ShapeType();
+
+ switch ( sm->GetComputeState() )
+ {
+ case SMESH_subMesh::READY_TO_COMPUTE:
+ case SMESH_subMesh::FAILED_TO_COMPUTE:
+ allComputed = false;// sm->IsMeshComputed();
+ break;
+ case SMESH_subMesh::NOT_READY:
+ case SMESH_subMesh::COMPUTE_OK:
+ continue;
+ }
+ }
+ return !allComputed;
+}
+
//=============================================================================
/*!
* Return true if all sub-meshes have been meshed
int dimToCheck = myDim - 1;
bool subMeshesComputed = true;
if ( isFailedToCompute ) *isFailedToCompute = false;
- // check subMeshes with upper dimension => reverse iteration
+ // check sub-meshes with upper dimension => reverse iteration
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
while ( smIt->more() )
{
// MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense
// in checking of existence of edges if the algo needs only faces. Moreover,
- // degenerated edges may have no submesh, as after computing NETGEN_2D.
+ // degenerated edges may have no sub-mesh, as after computing NETGEN_2D.
if ( !_algo || _algo->NeedDiscreteBoundary() ) {
int dim = SMESH_Gen::GetShapeDim( ss );
if (dim < dimToCheck)
- break; // the rest subMeshes are all of less dimension
+ break; // the rest sub-meshes are all of less dimension
}
SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
- bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
- (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() )));
+ bool computeOk = ((sm->GetComputeState() == COMPUTE_OK ) ||
+ (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() )));
if (!computeOk)
{
subMeshesComputed = false;
+
if ( isFailedToCompute && !(*isFailedToCompute) )
*isFailedToCompute = ( sm->GetComputeState() == FAILED_TO_COMPUTE );
- // int type = ss.ShapeType();
-
- // switch (type)
- // {
- // case TopAbs_COMPOUND:
- // {
- // MESSAGE("The not computed sub mesh is a COMPOUND");
- // break;
- // }
- // case TopAbs_COMPSOLID:
- // {
- // MESSAGE("The not computed sub mesh is a COMPSOLID");
- // break;
- // }
- // case TopAbs_SHELL:
- // {
- // MESSAGE("The not computed sub mesh is a SHEL");
- // break;
- // }
- // case TopAbs_WIRE:
- // {
- // MESSAGE("The not computed sub mesh is a WIRE");
- // break;
- // }
- // case TopAbs_SOLID:
- // {
- // MESSAGE("The not computed sub mesh is a SOLID");
- // break;
- // }
- // case TopAbs_FACE:
- // {
- // MESSAGE("The not computed sub mesh is a FACE");
- // break;
- // }
- // case TopAbs_EDGE:
- // {
- // MESSAGE("The not computed sub mesh is a EDGE");
- // break;
- // }
- // default:
- // {
- // MESSAGE("The not computed sub mesh is of unknown type");
- // break;
- // }
- // }
-
if ( !isFailedToCompute )
break;
}
//=============================================================================
/*!
- *
- */
-//=============================================================================
-
-// bool SMESH_subMesh::SubMeshesReady()
-// {
-// bool subMeshesReady = true;
-// SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
-// while ( smIt->more() ) {
-// SMESH_subMesh *sm = smIt->next();
-// bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
-// sm->GetComputeState() == READY_TO_COMPUTE);
-// if (!computeOk)
-// {
-// subMeshesReady = false;
-// SCRUTE(sm->GetId());
-// break;
-// }
-// }
-// return subMeshesReady;
-// }
-
-//=============================================================================
-/*!
- * Construct dependence on first level subMeshes. complex shapes (compsolid,
- * shell, wire) are not analysed the same way as simple shapes (solid, face,
- * edge).
- * For collection shapes (compsolid, shell, wire) prepare a list of submeshes
- * with possible multiples occurences. Multiples occurences corresponds to
- * internal frontiers within shapes of the collection and must not be keeped.
- * See FinalizeDependence.
+ * Returns all sub-meshes this one depend on
*/
//=============================================================================
-const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
+const std::map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
{
- if (_dependenceAnalysed)
+ if ( _dependenceAnalysed || !_father->HasShapeToMesh() )
return _mapDepend;
- //MESSAGE("SMESH_subMesh::DependsOn");
-
int type = _subShape.ShapeType();
- //SCRUTE(type);
switch (type)
{
case TopAbs_COMPOUND:
+ {
+ list< TopoDS_Shape > compounds( 1, _subShape );
+ list< TopoDS_Shape >::iterator comp = compounds.begin();
+ for ( ; comp != compounds.end(); ++comp )
{
- //MESSAGE("compound");
- for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next())
- {
- insertDependence(exp.Current());
- }
- for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More(); exp.Next())
- {
- if ( BRep_Tool::IsClosed(exp.Current() ))
- insertDependence(exp.Current()); //only shell not in solid
- else
- for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next())
- insertDependence(expF.Current()); // issue 0020959: HEXA_3D fails on shell
-
- }
- for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();exp.Next())
- {
- insertDependence(exp.Current());
- }
- for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next())
- {
- insertDependence(exp.Current());
- }
- for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next())
- {
- insertDependence(exp.Current());
- }
- break;
- }
- case TopAbs_COMPSOLID:
- {
- //MESSAGE("compsolid");
- for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next())
- {
- insertDependence(exp.Current());
- }
- break;
- }
- case TopAbs_SHELL:
- {
- //MESSAGE("shell");
- for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next())
- {
- insertDependence(exp.Current());
- }
- break;
- }
- case TopAbs_WIRE:
- {
- //MESSAGE("wire");
- for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next())
- {
- insertDependence(exp.Current());
- }
- break;
- }
- case TopAbs_SOLID:
- {
- //MESSAGE("solid");
- if(_father->HasShapeToMesh()) {
- for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next())
+ for ( TopoDS_Iterator sub( *comp ); sub.More(); sub.Next() )
+ switch ( sub.Value().ShapeType() )
{
- insertDependence(exp.Current());
+ case TopAbs_COMPOUND: compounds.push_back( sub.Value() ); break;
+ case TopAbs_COMPSOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break;
+ case TopAbs_SOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break;
+ case TopAbs_SHELL: insertDependence( sub.Value(), TopAbs_FACE ); break;
+ case TopAbs_FACE: insertDependence( sub.Value(), TopAbs_FACE ); break;
+ case TopAbs_WIRE: insertDependence( sub.Value(), TopAbs_EDGE ); break;
+ case TopAbs_EDGE: insertDependence( sub.Value(), TopAbs_EDGE ); break;
+ case TopAbs_VERTEX: insertDependence( sub.Value(), TopAbs_VERTEX ); break;
+ default:;
}
- }
- break;
- }
- case TopAbs_FACE:
- {
- //MESSAGE("face");
- for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next())
- {
- insertDependence(exp.Current());
- }
- break;
- }
- case TopAbs_EDGE:
- {
- //MESSAGE("edge");
- for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next())
- {
- insertDependence(exp.Current());
- }
- break;
- }
- case TopAbs_VERTEX:
- {
- break;
- }
- default:
- {
- break;
}
}
+ break;
+ case TopAbs_COMPSOLID: insertDependence( _subShape, TopAbs_SOLID ); break;
+ case TopAbs_SOLID: insertDependence( _subShape, TopAbs_FACE );
+ { /*internal EDGE*/ insertDependence( _subShape, TopAbs_EDGE, TopAbs_WIRE ); break; }
+ case TopAbs_SHELL: insertDependence( _subShape, TopAbs_FACE ); break;
+ case TopAbs_FACE: insertDependence( _subShape, TopAbs_EDGE ); break;
+ case TopAbs_WIRE: insertDependence( _subShape, TopAbs_EDGE ); break;
+ case TopAbs_EDGE: insertDependence( _subShape, TopAbs_VERTEX ); break;
+ default:;
+ }
_dependenceAnalysed = true;
return _mapDepend;
}
*/
//================================================================================
-namespace {
- int dependsOnMapKey( const SMESH_subMesh* sm )
+namespace
+{
+ int dependsOnMapKey( TopAbs_ShapeEnum type, int shapeID )
{
- int type = sm->GetSubShape().ShapeType();
- int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid
- int cle = sm->GetId();
+ int ordType = 9 - int(type); // 2 = Vertex, 8 = CompSolid
+ int cle = shapeID;
cle += 10000000 * ordType; // sort map by ordType then index
return cle;
}
+ int dependsOnMapKey( const SMESH_subMesh* sm )
+ {
+ return dependsOnMapKey( sm->GetSubShape().ShapeType(), sm->GetId() );
+ }
}
//=============================================================================
/*!
- * For simple Shapes (solid, face, edge): add subMesh into dependence list.
+ * Add sub-meshes on sub-shapes of a given type into the dependence map.
*/
//=============================================================================
-void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape)
+void SMESH_subMesh::insertDependence(const TopoDS_Shape aShape,
+ TopAbs_ShapeEnum aSubType,
+ TopAbs_ShapeEnum avoidType)
{
- SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
- int cle = dependsOnMapKey( aSubMesh );
- if ( _mapDepend.find( cle ) == _mapDepend.end())
+ TopExp_Explorer sub( aShape, aSubType, avoidType );
+ for ( ; sub.More(); sub.Next() )
{
- _mapDepend[cle] = aSubMesh;
- const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
- _mapDepend.insert( subMap.begin(), subMap.end() );
+ SMESH_subMesh *aSubMesh = _father->GetSubMesh( sub.Current() );
+ if ( aSubMesh->GetId() == 0 )
+ continue; // not a sub-shape of the shape to mesh
+ int cle = dependsOnMapKey( aSubMesh );
+ if ( _mapDepend.find( cle ) == _mapDepend.end())
+ {
+ _mapDepend[cle] = aSubMesh;
+ const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
+ _mapDepend.insert( subMap.begin(), subMap.end() );
+ }
}
}
return other ? _mapDepend.count( dependsOnMapKey( other )) : false;
}
+//================================================================================
+/*!
+ * \brief Return \c true if \a this sub-mesh depends on a \a shape
+ */
+//================================================================================
+
+bool SMESH_subMesh::DependsOn( const int shapeID ) const
+{
+ return DependsOn( _father->GetSubMeshContaining( shapeID ));
+}
+
//=============================================================================
/*!
* Return a shape of \a this sub-mesh
//=======================================================================
//function : CanAddHypothesis
//purpose : return true if theHypothesis can be attached to me:
-// its dimention is checked
+// its dimension is checked
//=======================================================================
bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
}
//=======================================================================
-//function : IsApplicableHypotesis
-//purpose :
+//function : IsApplicableHypothesis
+//purpose : check if this sub-mesh can be computed using a hypothesis
//=======================================================================
-bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
- const TopAbs_ShapeEnum theShapeType)
+bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis) const
+{
+ if ( !_father->HasShapeToMesh() && _subShape.ShapeType() == TopAbs_SOLID )
+ return true; // true for the PseudoShape
+
+ return IsApplicableHypothesis( theHypothesis, _subShape.ShapeType() );
+}
+
+//=======================================================================
+//function : IsApplicableHypothesis
+//purpose : compare shape type and hypothesis type
+//=======================================================================
+
+bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis,
+ const TopAbs_ShapeEnum theShapeType)
{
if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
{
//================================================================================
SMESH_Hypothesis::Hypothesis_Status
- SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
+ SMESH_subMesh::AlgoStateEngine(algo_event event, SMESH_Hypothesis * anHyp)
{
// **** les retour des evenement shape sont significatifs
// (add ou remove fait ou non)
// le retour des evenement father n'indiquent pas que add ou remove fait
SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
+ if ( _Id == 0 ) return ret; // not a sub-shape of the shape to mesh
SMESHDS_Mesh* meshDS =_father->GetMeshDS();
SMESH_Algo* algo = 0;
bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE
SMESH_Algo* algoRequiringCleaning = 0;
- bool isApplicableHyp = IsApplicableHypotesis( anHyp );
+ bool isApplicableHyp = IsApplicableHypothesis( anHyp );
if (event == ADD_ALGO || event == ADD_FATHER_ALGO)
{
filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis( this, filter, true ))
- if ( !curAlgo->NeedDiscreteBoundary() )
+ if ( !curAlgo->NeedDiscreteBoundary() && curAlgo != anHyp )
algoRequiringCleaning = curAlgo;
}
}
f.AndNot( SMESH_HypoFilter::Is( algo ));
const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true );
if (prevAlgo &&
- string(algo->GetName()) != string(prevAlgo->GetName()) )
- modifiedHyp = true;
+ string( algo->GetName()) != prevAlgo->GetName())
+ {
+ oldAlgoState = NO_ALGO; // force setting event listener (#16648)
+ modifiedHyp = true;
+ }
}
else
setAlgoState(MISSING_HYP);
// detect algorithm hiding
//
- if ( ret == SMESH_Hypothesis::HYP_OK &&
- ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) &&
+ if ( ret == SMESH_Hypothesis::HYP_OK &&
+ ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) && algo &&
algo->GetName() == anHyp->GetName() )
{
// is algo hidden?
if ( !theAlgo ) return false;
// Suppose that theAlgo is applicable to _subShape, do not check it here
- //if ( !IsApplicableHypotesis( theAlgo )) return false;
+ //if ( !IsApplicableHypothesis( theAlgo )) return false;
// check only algo that doesn't NeedDiscreteBoundary(): because mesh made
// on a sub-shape will be ignored by theAlgo
!theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
return true;
- SMESH_Gen* gen =_father->GetGen();
-
// only local algo is to be checked
//if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() )
//================================================================================
SMESH_Hypothesis::Hypothesis_Status
- SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
+ SMESH_subMesh::SubMeshesAlgoStateEngine(algo_event event,
SMESH_Hypothesis * anHyp,
bool exitOnFatal)
{
}
else if ( algoRequiringCleaning && algoRequiringCleaning->SupportSubmeshes() )
{
- SMESHDS_Mesh* meshDS = _father->GetMeshDS();
-
// find sub-meshes to keep elements on
set< SMESH_subMesh* > smToKeep;
TopAbs_ShapeEnum prevShapeType = TopAbs_SHAPE;
if ( !sm->IsEmpty() )
{
const bool sameShapeType = ( prevShapeType == sm->GetSubShape().ShapeType() );
- bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
+ bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
if ( !sameShapeType )
{
// check if the algo allows presence of global algos of dimension the algo
- // can generate it-self
+ // can generate it-self;
+ // always keep a node on VERTEX, as this node can be shared by segments
+ // lying on EDGEs not shared by the VERTEX of sm, due to MergeNodes (PAL23068)
int shapeDim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
- keepSubMeshes = algoRequiringCleaning->NeedLowerHyps( shapeDim );
+ keepSubMeshes = ( algoRequiringCleaning->NeedLowerHyps( shapeDim ) || shapeDim == 0 );
prevShapeType = sm->GetSubShape().ShapeType();
toKeepPrevShapeType = keepSubMeshes;
}
if ( !keepSubMeshes )
{
- // look for an algo assigned to sm
- bool algoFound = false;
- const list<const SMESHDS_Hypothesis*>& hyps = meshDS->GetHypothesis( sm->_subShape );
- list<const SMESHDS_Hypothesis*>::const_iterator h = hyps.begin();
- for ( ; ( !algoFound && h != hyps.end() ); ++h )
- algoFound = ((*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
- keepSubMeshes = algoFound;
+ // look for a local algo used to mesh sm
+ TopoDS_Shape algoShape = SMESH_MesherHelper::GetShapeOfHypothesis
+ ( algoRequiringCleaning, _subShape, _father );
+ SMESH_HypoFilter moreLocalAlgo;
+ moreLocalAlgo.Init( SMESH_HypoFilter::IsMoreLocalThan( algoShape, *_father ));
+ moreLocalAlgo.And ( SMESH_HypoFilter::IsAlgo() );
+ bool localAlgoFound = _father->GetHypothesis( sm->_subShape, moreLocalAlgo, true );
+ keepSubMeshes = localAlgoFound;
}
// remember all sub-meshes of sm
if ( keepSubMeshes )
{
- SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false,true);
+ SMESH_subMeshIteratorPtr smIt2 = sm->getDependsOnIterator(true);
while ( smIt2->more() )
smToKeep.insert( smIt2->next() );
}
void SMESH_subMesh::DumpAlgoState(bool isMain)
{
- // if (dim < 1) return;
- if (isMain)
- {
- const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+ if (isMain)
+ {
+ const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
- map < int, SMESH_subMesh * >::const_iterator itsub;
- for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
- {
- SMESH_subMesh *sm = (*itsub).second;
- sm->DumpAlgoState(false);
- }
- }
- //int type = _subShape.ShapeType();
- MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) <<
- " type of shape " << _subShape.ShapeType());
- switch (_algoState)
- {
- case NO_ALGO:
- MESSAGE(" AlgoState = NO_ALGO");
- break;
- case MISSING_HYP:
- MESSAGE(" AlgoState = MISSING_HYP");
- break;
- case HYP_OK:
- MESSAGE(" AlgoState = HYP_OK");
- break;
- }
- switch (_computeState)
- {
- case NOT_READY:
- MESSAGE(" ComputeState = NOT_READY");
- break;
- case READY_TO_COMPUTE:
- MESSAGE(" ComputeState = READY_TO_COMPUTE");
- break;
- case COMPUTE_OK:
- MESSAGE(" ComputeState = COMPUTE_OK");
- break;
- case FAILED_TO_COMPUTE:
- MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
- break;
- }
+ map < int, SMESH_subMesh * >::const_iterator itsub;
+ for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+ {
+ SMESH_subMesh *sm = (*itsub).second;
+ sm->DumpAlgoState(false);
+ }
+ }
+ MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) <<
+ " type of shape " << _subShape.ShapeType());
+ switch (_algoState)
+ {
+ case NO_ALGO : MESSAGE(" AlgoState = NO_ALGO"); break;
+ case MISSING_HYP : MESSAGE(" AlgoState = MISSING_HYP"); break;
+ case HYP_OK : MESSAGE(" AlgoState = HYP_OK");break;
+ }
+ switch (_computeState)
+ {
+ case NOT_READY : MESSAGE(" ComputeState = NOT_READY");break;
+ case READY_TO_COMPUTE : MESSAGE(" ComputeState = READY_TO_COMPUTE");break;
+ case COMPUTE_OK : MESSAGE(" ComputeState = COMPUTE_OK");break;
+ case FAILED_TO_COMPUTE: MESSAGE(" ComputeState = FAILED_TO_COMPUTE");break;
+ }
}
//================================================================================
static void cleanSubMesh( SMESH_subMesh * subMesh )
{
if (subMesh) {
- if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) {
+ if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS())
+ {
SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
- SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
- while (ite->more()) {
- const SMDS_MeshElement * elt = ite->next();
- //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
- //meshDS->RemoveElement(elt);
- meshDS->RemoveFreeElement(elt, 0);
- }
-
- SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
- while (itn->more()) {
- const SMDS_MeshNode * node = itn->next();
- //MESSAGE( " RM node: "<<node->GetID());
- if ( node->NbInverseElements() == 0 )
- meshDS->RemoveFreeNode(node, 0);
- else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
- meshDS->RemoveNode(node);
- }
+ int nbElems = subMeshDS->NbElements();
+ if ( nbElems > 0 )
+ for ( SMDS_ElemIteratorPtr ite = subMeshDS->GetElements(); ite->more(); )
+ meshDS->RemoveFreeElement( ite->next(), subMeshDS );
+
+ int nbNodes = subMeshDS->NbNodes();
+ if ( nbNodes > 0 )
+ for ( SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); itn->more() ; )
+ {
+ const SMDS_MeshNode * node = itn->next();
+ if ( node->NbInverseElements() == 0 )
+ meshDS->RemoveFreeNode( node, subMeshDS );
+ else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
+ meshDS->RemoveNode( node );
+ }
subMeshDS->Clear();
}
}
*/
//=============================================================================
-bool SMESH_subMesh::ComputeStateEngine(int event)
+bool SMESH_subMesh::ComputeStateEngine(compute_event event)
{
switch ( event ) {
case MODIF_ALGO_STATE:
loadDependentMeshes();
ComputeSubMeshStateEngine( SUBMESH_LOADED );
//break;
+ // fall through
case CHECK_COMPUTE_STATE:
if ( IsMeshComputed() )
_computeState = COMPUTE_OK;
_computeState = READY_TO_COMPUTE;
}
break;
+
+ case COMPUTE_NOGEOM: // no geometry; can be several algos
+ if ( !_father->HasShapeToMesh() )
+ {
+ algo = GetAlgo(); // current algo
+ if ( algo )
+ {
+ // apply algos in the order of increasing dimension
+ std::list< const SMESHDS_Hypothesis * > algos = _father->GetHypothesisList( _subShape );
+ for ( int t = SMESHDS_Hypothesis::ALGO_1D; t <= SMESHDS_Hypothesis::ALGO_3D; ++t )
+ {
+ std::list<const SMESHDS_Hypothesis *>::iterator al = algos.begin();
+ for ( ; al != algos.end(); ++al )
+ if ( (*al)->GetType() == t )
+ {
+ _algo = (SMESH_Algo*) *al;
+ _computeState = READY_TO_COMPUTE;
+ if ( !ComputeStateEngine( COMPUTE ))
+ break;
+ }
+ }
+ _algo = algo; // restore
+ }
+ break;
+ }
+ // fall through
case COMPUTE:
case COMPUTE_SUBMESH:
{
if (_father->HasShapeToMesh() ) {
bool subComputed = false, subFailed = false;
if (!algo->OnlyUnaryInput()) {
- if ( event == COMPUTE /*&&
- ( algo->NeedDiscreteBoundary() || algo->SupportSubmeshes() )*/)
- shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute());
- else
- subComputed = SubMeshesComputed( & subFailed );
+ // --- commented for bos#22320 to compute all sub-shapes at once if possible;
+ // --- in case COMPUTE_SUBMESH, set of sub-shapes is limited
+ // --- by calling SetAllowedSubShapes()
+ // if ( event == COMPUTE )
+ // shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToComput;
+ // else
+ // subComputed = SubMeshesComputed( & subFailed );
+ shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute());
}
else {
subComputed = SubMeshesComputed();
MESSAGE("std::bad_alloc thrown inside algo->Compute()");
if ( _computeError ) {
_computeError->myName = COMPERR_MEMORY_PB;
- //_computeError->myComment = exc.what();
}
cleanSubMesh( this );
throw exc;
MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()");
if ( _computeError ) {
_computeError->myName = COMPERR_MEMORY_PB;
- //_computeError->myComment = exc.what();
}
cleanSubMesh( this );
throw std::bad_alloc();
ret = false;
// check if anything was built
TopExp_Explorer subS(shape, _subShape.ShapeType());
- if (ret)
+ if ( ret )
{
for (; ret && subS.More(); subS.Next())
if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() &&
!algo->isDegenerated( TopoDS::Edge( subS.Current() ))))
ret = false;
}
+#ifdef PRINT_WHO_COMPUTE_WHAT
+ for (subS.ReInit(); subS.More(); subS.Next())
+ {
+ const std::list <const SMESHDS_Hypothesis *> & hyps =
+ _algo->GetUsedHypothesis( *_father, _subShape );
+ SMESH_Comment hypStr;
+ if ( !hyps.empty() )
+ {
+ hypStr << hyps.front()->GetName() << " ";
+ ((SMESHDS_Hypothesis*)hyps.front())->SaveTo( hypStr.Stream() );
+ hypStr << " ";
+ }
+ cout << _father->GetSubMesh( subS.Current() )->GetId()
+ << " " << ( ret ? "OK" : "FAIL" )
+ << " " << _algo->GetName()
+ << " " << hypStr << endl;
+ }
+#endif
// Set _computeError
- if (!ret && !isComputeErrorSet)
+ if ( !ret && !isComputeErrorSet )
{
- for (subS.ReInit(); subS.More(); subS.Next())
+ for ( subS.ReInit(); subS.More(); subS.Next() )
{
SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
if ( !sm->IsMeshComputed() )
}
}
}
- if (ret && _computeError && _computeError->myName != COMPERR_WARNING )
+ if ( ret && _computeError && _computeError->myName != COMPERR_WARNING )
{
_computeError.reset();
}
+ // transform errors into warnings if it is caused by mesh edition (imp 0023068)
+ if (!ret && _father->GetIsModified() )
+ {
+ for (subS.ReInit(); subS.More(); subS.Next())
+ {
+ SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+ if ( !sm->IsMeshComputed() && sm->_computeError )
+ {
+ // check if there is a VERTEX w/o nodes
+ // with READY_TO_COMPUTE state (after MergeNodes())
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+ while ( smIt->more() )
+ {
+ SMESH_subMesh * vertSM = smIt->next();
+ if ( vertSM->_subShape.ShapeType() != TopAbs_VERTEX ) break;
+ if ( vertSM->GetComputeState() == READY_TO_COMPUTE )
+ {
+ SMESHDS_SubMesh * ds = vertSM->GetSubMeshDS();
+ if ( !ds || ds->NbNodes() == 0 )
+ {
+ sm->_computeState = READY_TO_COMPUTE;
+ sm->_computeError->myName = COMPERR_WARNING;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
// send event SUBMESH_COMPUTED
if ( ret ) {
if ( !algo->NeedDiscreteBoundary() )
else
updateDependantsState( SUBMESH_COMPUTED );
}
+ // let algo clear its data gathered while algo->Compute()
+ algo->CheckHypothesis((*_father), _subShape, hyp_status);
}
break;
case COMPUTE_CANCELED: // nothing to do
loadDependentMeshes();
ComputeSubMeshStateEngine( SUBMESH_LOADED );
//break;
+ // fall through
case CHECK_COMPUTE_STATE:
if ( IsMeshComputed() )
_computeState = COMPUTE_OK;
break;
case COMPUTE: // nothing to do
break;
+ case COMPUTE_SUBMESH: // nothing to do
+ break;
case COMPUTE_CANCELED: // nothing to do
break;
case CLEAN:
- cleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN
+ cleanDependants(); // clean sub-meshes, dependent on this one, with event CLEAN
removeSubMeshElementsAndNodes();
_computeState = NOT_READY;
if ( _algoState == HYP_OK )
removeSubMeshElementsAndNodes();
break;
case SUBMESH_COMPUTED: // allow retry compute
- if (_algoState == HYP_OK)
- _computeState = READY_TO_COMPUTE;
- else
- _computeState = NOT_READY;
+ if ( IsEmpty() ) // 23061
+ {
+ if (_algoState == HYP_OK)
+ _computeState = READY_TO_COMPUTE;
+ else
+ _computeState = NOT_READY;
+ }
break;
case SUBMESH_RESTORED:
ComputeSubMeshStateEngine( SUBMESH_RESTORED );
SMESH_Hypothesis::Hypothesis_Status hyp_status;
algo = GetAlgo();
- if(algo && !aResMap.count(this) )
+ if( algo && !aResMap.count( this ))
{
ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
if (!ret) return false;
- if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary())
+ if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary() )
{
// check submeshes needed
bool subMeshEvaluated = true;
return false;
}
_computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
- ret = algo->Evaluate((*_father), _subShape, aResMap);
+ if ( IsMeshComputed() )
+ {
+ vector<int> & nbEntities = aResMap[ this ];
+ nbEntities.resize( SMDSEntity_Last, 0 );
+ if ( SMESHDS_SubMesh* sm = GetSubMeshDS() )
+ {
+ nbEntities[ SMDSEntity_Node ] = sm->NbNodes();
+ SMDS_ElemIteratorPtr elemIt = sm->GetElements();
+ while ( elemIt->more() )
+ nbEntities[ elemIt->next()->GetEntityType() ]++;
+ }
+ }
+ else
+ {
+ ret = algo->Evaluate((*_father), _subShape, aResMap);
+ }
aResMap.insert( make_pair( this,vector<int>(0)));
}
//purpose :
//=======================================================================
-void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf)
+void SMESH_subMesh::ComputeSubMeshStateEngine(compute_event event, const bool includeSelf)
{
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(includeSelf,false);
while ( smIt->more() )
}
}
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : cleanDependants
+//purpose :
+//=======================================================================
void SMESH_subMesh::cleanDependants()
{
}
}
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : removeSubMeshElementsAndNodes
+//purpose :
+//=======================================================================
void SMESH_subMesh::removeSubMeshElementsAndNodes()
{
// meshed at once along with _subShape
//=======================================================================
-TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
+TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * /*theGen*/,
SMESH_Algo* theAlgo,
bool & theSubComputed,
bool & theSubFailed,
return _subShape;
const bool skipAuxHyps = false;
- list<const SMESHDS_Hypothesis*> aUsedHyp =
+ list<const SMESHDS_Hypothesis*> usedHyps =
theAlgo->GetUsedHypothesis( *_father, _subShape, skipAuxHyps ); // copy
+ std::list < TopoDS_Shape > assiShapes = theAlgo->GetAssignedShapes();
// put in a compound all shapes with the same hypothesis assigned
// and a good ComputeState
const TopoDS_Shape& S = subMesh->_subShape;
if ( S.ShapeType() != this->_subShape.ShapeType() )
continue;
- theSubs.push_back( subMesh );
+ if ( _allowedSubShapes && !_allowedSubShapes->IsEmpty() && !_allowedSubShapes->Contains( S ))
+ continue;
if ( subMesh == this )
{
aBuilder.Add( aCompound, S );
+ theSubs.push_back( subMesh );
}
else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
{
SMESH_Algo* anAlgo = subMesh->GetAlgo();
if (( anAlgo->IsSameName( *theAlgo )) && // same algo
- ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == aUsedHyp )) // same hyps
+ ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == usedHyps ) && // same hyps
+ ( anAlgo->GetAssignedShapes() == assiShapes ) && // on same sub-shapes
+ ( _algoShape == subMesh->_algoShape ))
{
aBuilder.Add( aCompound, S );
if ( !subMesh->SubMeshesComputed() )
theSubComputed = false;
+ theSubs.push_back( subMesh );
}
}
}
}
//=======================================================================
-//function : CheckConcurentHypothesis
+//function : CheckConcurrentHypothesis
//purpose : check if there are several applicable hypothesis attached to
// ancestors
//=======================================================================
SMESH_Hypothesis::Hypothesis_Status
- SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
+ SMESH_subMesh::CheckConcurrentHypothesis (const int theHypType)
{
- MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
-
// is there local hypothesis on me?
if ( getSimilarAttached( _subShape, 0, theHypType ) )
return SMESH_Hypothesis::HYP_OK;
aPrevHyp = hyp;
}
else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
- return SMESH_Hypothesis::HYP_CONCURENT;
+ return SMESH_Hypothesis::HYP_CONCURRENT;
else
return SMESH_Hypothesis::HYP_OK;
}
_eventListeners.find( listener );
if ( l_d != _eventListeners.end() ) {
EventListenerData* curData = l_d->second;
+ l_d->second = data;
if ( curData && curData != data && curData->IsDeletable() )
delete curData;
- l_d->second = data;
}
else
{
if ( listener->GetName() == l_d->first->GetName() )
{
EventListenerData* curData = l_d->second;
+ l_d->second = 0;
if ( curData && curData != data && curData->IsDeletable() )
delete curData;
if ( l_d->first != listener && l_d->first->IsDeletable() )
//================================================================================
/*!
- * \brief Notify stored event listeners on the occured event
+ * \brief Notify stored event listeners on the occurred event
* \param event - algo_event or compute_event itself
* \param eventType - algo_event or compute_event
* \param hyp - hypothesis, if eventType is algo_event
list< OwnListenerData >::iterator d;
for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
{
- if ( !_father->MeshExists( d->myMeshID ))
- continue;
- if ( _father->GetId() == d->myMeshID &&
- this->GetId() != d->mySubMeshID &&
- !_father->GetSubMeshContaining( d->mySubMeshID ))
+ SMESH_Mesh* mesh = _father->FindMesh( d->myMeshID );
+ if ( !mesh || !mesh->GetSubMeshContaining( d->mySubMeshID ))
continue;
d->mySubMesh->DeleteEventListener( d->myListener );
}
{
list< OwnListenerData >::iterator d;
for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
- if ( _father != d->mySubMesh->_father )
+ if ( _father != d->mySubMesh->_father &&
+ _father->FindMesh( d->myMeshID ))
d->mySubMesh->_father->Load();
// map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin();
* \brief Do something on a certain event
* \param event - algo_event or compute_event itself
* \param eventType - algo_event or compute_event
- * \param subMesh - the submesh where the event occures
+ * \param subMesh - the submesh where the event occurs
* \param data - listener data stored in the subMesh
* \param hyp - hypothesis, if eventType is algo_event
*
switch ( event ) {
case SMESH_subMesh::CLEAN:
for ( ; smIt != smEnd; ++ smIt)
- (*smIt)->ComputeStateEngine( event );
+ (*smIt)->ComputeStateEngine( SMESH_subMesh::compute_event( event ));
break;
case SMESH_subMesh::COMPUTE:
case SMESH_subMesh::COMPUTE_SUBMESH:
{
_Iterator(SMDS_Iterator<SMESH_subMesh*>* subIt,
SMESH_subMesh* prepend,
- SMESH_subMesh* append): myIt(subIt),myAppend(append)
+ SMESH_subMesh* append): myAppend(append), myIt(subIt)
{
myCur = prepend ? prepend : myIt->more() ? myIt->next() : append;
if ( myCur == append ) append = 0;
//================================================================================
/*!
- * \brief Return iterator on the submeshes this one depends on
- * \param includeSelf - this submesh to be returned also
- * \param reverse - if true, complex shape submeshes go first
+ * \brief Return iterator on the submeshes this one depends on
+ * \param includeSelf - this submesh to be returned also
+ * \param reverse - if true, complex shape submeshes go first
*/
//================================================================================
SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this );
me->_ancestors.reserve( ancShapes.Extent() );
+ // assure that all sub-meshes exist
+ TopoDS_Shape mainShape = _father->GetShapeToMesh();
+ if ( !mainShape.IsNull() )
+ _father->GetSubMesh( mainShape )->DependsOn();
+
TopTools_MapOfShape map;
-
+
for ( TopTools_ListIteratorOfListOfShape it( ancShapes ); it.More(); it.Next() )
if ( SMESH_subMesh* sm = _father->GetSubMeshContaining( it.Value() ))
if ( map.Add( it.Value() ))
*/
//================================================================================
-bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
+bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
std::set<const SMESH_subMesh*>& theSetOfCommon ) const
{
- int oldNb = theSetOfCommon.size();
+ size_t oldNb = theSetOfCommon.size();
+
// check main submeshes
const map <int, SMESH_subMesh*>::const_iterator otherEnd = theOther->_mapDepend.end();
if ( theOther->_mapDepend.find(this->GetId()) != otherEnd )
theSetOfCommon.insert( this );
if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() )
theSetOfCommon.insert( theOther );
+
// check common submeshes
map <int, SMESH_subMesh*>::const_iterator mapIt = _mapDepend.begin();
for( ; mapIt != _mapDepend.end(); mapIt++ )