// 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
//
//
// Module : SMESH
// $Header$
-using namespace std;
#include "SMESH_subMesh.hxx"
+
+#include "SMESH_subMeshEventListener.hxx"
#include "SMESH_Gen.hxx"
#include "SMESH_Mesh.hxx"
#include "SMESH_Hypothesis.hxx"
#include <TopTools_IndexedMapOfShape.hxx>
#endif
+#include <Standard_Failure.hxx>
+#include <Standard_ErrorHandler.hxx>
+
//=============================================================================
/*!
* default constructor:
}
else
{
- _algoState = NO_ALGO;
- _computeState = NOT_READY;
+ _algoState = NO_ALGO;
+ _computeState = NOT_READY;
}
}
SMESH_subMesh::~SMESH_subMesh()
{
- MESSAGE("SMESH_subMesh::~SMESH_subMesh");
- // ****
+ MESSAGE("SMESH_subMesh::~SMESH_subMesh");
+ // ****
}
//=============================================================================
int SMESH_subMesh::GetId() const
{
- //MESSAGE("SMESH_subMesh::GetId");
- return _Id;
+ //MESSAGE("SMESH_subMesh::GetId");
+ return _Id;
}
//=============================================================================
SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
{
- //MESSAGE("SMESH_subMesh::GetSubMeshDS");
- if (_subMeshDS==NULL)
- {
- //MESSAGE("subMesh pointer still null, trying to get it...");
- _subMeshDS = _meshDS->MeshElements(_subShape); // may be null ...
- if (_subMeshDS==NULL)
- {
- MESSAGE("problem... subMesh still empty");
- //NRI ASSERT(0);
- //NRI throw SALOME_Exception(LOCALIZED(subMesh still empty));
- }
- }
- return _subMeshDS;
+ // submesh appears in DS only when a mesher set nodes and elements on it
+ if (_subMeshDS==NULL)
+ {
+ _subMeshDS = _meshDS->MeshElements(_subShape); // may be null ...
+// if (_subMeshDS==NULL)
+// {
+// MESSAGE("problem... subMesh still empty");
+// }
+ }
+ return _subMeshDS;
}
//=============================================================================
SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
{
- //MESSAGE("SMESH_subMesh::GetFirstToCompute");
const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
SMESH_subMesh *firstToCompute = 0;
for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
{
SMESH_subMesh *sm = (*itsub).second;
- // SCRUTE(sm->GetId());
- // SCRUTE(sm->GetComputeState());
bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
if (readyToCompute)
{
firstToCompute = sm;
- //SCRUTE(sm->GetId());
break;
}
}
//MESSAGE("SMESH_subMesh::SubMeshesComputed");
const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+ int myDim = SMESH_Gen::GetShapeDim( _subShape );
+ int dimToCheck = myDim - 1;
bool subMeshesComputed = true;
map < int, SMESH_subMesh * >::const_iterator itsub;
for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
{
SMESH_subMesh *sm = (*itsub).second;
+ const TopoDS_Shape & ss = sm->GetSubShape();
+ // 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.
+ int dim = SMESH_Gen::GetShapeDim( ss );
+ if (dim < dimToCheck)
+ continue;
SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
// PAL10974.
// There are some tricks with compute states, e.g. Penta_3D leaves
// one face with READY_TO_COMPUTE state in order to be able to
// recompute 3D when a locale triangle hypo changes (see PAL7428).
// So we check if mesh is really present
- //bool computeOk = (sm->GetComputeState() == COMPUTE_OK);
- bool computeOk = ( ds && ( ds->GetNodes()->more() || ds->GetElements()->more() ));
+ bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
+ (ds && ( ds->GetNodes()->more() || ds->GetElements()->more() )));
if (!computeOk)
{
- const TopoDS_Shape & ss = sm->GetSubShape();
int type = ss.ShapeType();
subMeshesComputed = false;
int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid
int cle = aSubMesh->GetId();
cle += 10000000 * ordType; // sort map by ordType then index
- if (_mapDepend.find(cle) == _mapDepend.end())
+ if ( _mapDepend.find( cle ) == _mapDepend.end())
{
_mapDepend[cle] = aSubMesh;
- const map < int, SMESH_subMesh * >&subMap = aSubMesh->DependsOn();
- map < int, SMESH_subMesh * >::const_iterator im;
- for (im = subMap.begin(); im != subMap.end(); im++)
- {
- int clesub = (*im).first;
- SMESH_subMesh *sm = (*im).second;
- if (_mapDepend.find(clesub) == _mapDepend.end())
- _mapDepend[clesub] = sm;
- }
+ const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
+ _mapDepend.insert( subMap.begin(), subMap.end() );
}
-
}
//=============================================================================
*/
//=============================================================================
-const TopoDS_Shape & SMESH_subMesh::GetSubShape()
+const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
{
//MESSAGE("SMESH_subMesh::GetSubShape");
return _subShape;
//=======================================================================
//function : IsApplicableHypotesis
-//purpose :
+//purpose :
//=======================================================================
bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
return ( theHypothesis->GetShapeType() & (1<< theShapeType));
// hypothesis
- int aShapeDim = 100;
switch ( theShapeType ) {
- case TopAbs_EDGE: aShapeDim = 1; break;
- case TopAbs_FACE: aShapeDim = 2; break;
- case TopAbs_SHELL:aShapeDim = 3; break;
- case TopAbs_SOLID:aShapeDim = 3; break;
-// case TopAbs_VERTEX:
+ case TopAbs_EDGE:
+ case TopAbs_FACE:
+ case TopAbs_SOLID:
+ return SMESH_Gen::GetShapeDim( theShapeType ) == theHypothesis->GetDim();
+
+ case TopAbs_SHELL:
+ // Special case for algorithms, building 2D mesh on a whole shell.
+ // Before this fix there was a problem after restoring from study,
+ // because in that case algorithm is assigned before hypothesis
+ // (on shell in problem case) and hypothesis is checked on faces
+ // (because it is 2D), where we have NO_ALGO state.
+ // Now 2D hypothesis is also applicable to shells.
+ return (theHypothesis->GetDim() == 2 || theHypothesis->GetDim() == 3);
+
// case TopAbs_WIRE:
// case TopAbs_COMPSOLID:
// case TopAbs_COMPOUND:
- default: return false;
+ default:;
}
-
- return ( theHypothesis->GetDim() == aShapeDim );
+ return false;
}
//=============================================================================
return SMESH_Hypothesis::HYP_OK;
}
- SMESH_Gen* gen =_father->GetGen();
-// bool ret = false;
+ SMESH_Gen* gen =_father->GetGen();
+ SMESH_Algo* algo = 0;
int oldAlgoState = _algoState;
bool modifiedHyp = false; // if set to true, force event MODIF_ALGO_STATE
// in ComputeStateEngine
if ( ! CanAddHypothesis( anHyp ))
return SMESH_Hypothesis::HYP_BAD_DIM;
- if ( GetSimilarAttached( _subShape, anHyp ) )
+ if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
return SMESH_Hypothesis::HYP_ALREADY_EXIST;
if ( !_meshDS->AddHypothesis(_subShape, anHyp))
// Serve Propagation of 1D hypothesis
if (event == ADD_HYP) {
bool isPropagationOk = true;
- string hypName = anHyp->GetName();
+ bool isPropagationHyp = ( strcmp( "Propagation", anHyp->GetName() ) == 0 );
- if (hypName == "Propagation") {
+ if ( isPropagationHyp ) {
TopExp_Explorer exp (_subShape, TopAbs_EDGE);
TopTools_MapOfShape aMap;
for (; exp.More(); exp.Next()) {
} else {
}
- if (!isPropagationOk && ret < SMESH_Hypothesis::HYP_CONCURENT) {
+ if ( isPropagationOk ) {
+ if ( isPropagationHyp )
+ return ret; // nothing more to do for "Propagation" hypothesis
+ }
+ else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
ret = SMESH_Hypothesis::HYP_CONCURENT;
}
} // Serve Propagation of 1D hypothesis
{
bool isPropagationOk = true;
SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" ));
- if ( propagFilter.IsOk( anHyp, _subShape ))
+ bool isPropagationHyp = propagFilter.IsOk( anHyp, _subShape );
+
+ if ( isPropagationHyp )
{
TopExp_Explorer exp (_subShape, TopAbs_EDGE);
TopTools_MapOfShape aMap;
isPropagationOk = _father->RebuildPropagationChains();
}
- if (!isPropagationOk && ret < SMESH_Hypothesis::HYP_CONCURENT) {
+ if ( isPropagationOk ) {
+ if ( isPropagationHyp )
+ return ret; // nothing more to do for "Propagation" hypothesis
+ }
+ else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
ret = SMESH_Hypothesis::HYP_CONCURENT;
}
} // Serve Propagation of 1D hypothesis
+ else // event == REMOVE_ALGO
+ {
+ algo = dynamic_cast<SMESH_Algo*> (anHyp);
+ if (!algo->NeedDescretBoundary())
+ {
+ // clean all mesh in the tree of the current submesh;
+ // we must perform it now because later
+ // we will have no information about the type of the removed algo
+ CleanDependants();
+ ComputeStateEngine( CLEAN );
+ CleanDependsOn();
+ }
+ }
}
// ------------------
case ADD_HYP:
break;
case ADD_ALGO: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
SetAlgoState(HYP_OK);
+ else if ( algo->IsStatusFatal( aux_ret )) {
+ _meshDS->RemoveHypothesis(_subShape, anHyp);
+ ret = aux_ret;
+ }
else
SetAlgoState(MISSING_HYP);
break;
case ADD_FATHER_HYP:
break;
case ADD_FATHER_ALGO: { // Algo just added in father
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if ( algo == anHyp ) {
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
case REMOVE_FATHER_HYP:
break;
case REMOVE_FATHER_ALGO: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
if (algo)
{
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
switch (event)
{
case ADD_HYP: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, ret ))
SetAlgoState(HYP_OK);
if (SMESH_Hypothesis::IsStatusFatal( ret ))
_meshDS->RemoveHypothesis(_subShape, anHyp);
- else if (!_father->IsUsedHypothesis( anHyp, _subShape ))
+ else if (!_father->IsUsedHypothesis( anHyp, this ))
{
_meshDS->RemoveHypothesis(_subShape, anHyp);
ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
break;
}
case ADD_ALGO: { //already existing algo : on father ?
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
SetAlgoState(HYP_OK);
+ else if ( algo->IsStatusFatal( aux_ret )) {
+ _meshDS->RemoveHypothesis(_subShape, anHyp);
+ ret = aux_ret;
+ }
else
SetAlgoState(MISSING_HYP);
break;
case REMOVE_HYP:
break;
case REMOVE_ALGO: { // perhaps a father algo applies ?
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
if (algo == NULL) // no more algo applying on subShape...
{
SetAlgoState(NO_ALGO);
break;
}
case ADD_FATHER_HYP: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
SetAlgoState(HYP_OK);
else
SetAlgoState(MISSING_HYP);
- }
break;
+ }
case ADD_FATHER_ALGO: { // new father algo
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT( algo );
if ( algo == anHyp ) {
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
case REMOVE_FATHER_HYP: // nothing to do
break;
case REMOVE_FATHER_ALGO: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
if (algo == NULL) // no more applying algo on father
{
SetAlgoState(NO_ALGO);
switch (event)
{
case ADD_HYP: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if (!algo->CheckHypothesis((*_father),_subShape, ret ))
{
// ret should be fatal: anHyp was not added
ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
}
- else if (!_father->IsUsedHypothesis( anHyp, _subShape ))
+ else if (!_father->IsUsedHypothesis( anHyp, this ))
ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
if (SMESH_Hypothesis::IsStatusFatal( ret ))
break;
}
case ADD_ALGO: { //already existing algo : on father ?
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
// check if algo changes
SMESH_HypoFilter f;
f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
f.AndNot( SMESH_HypoFilter::Is( algo ));
const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
- if (prevAlgo &&
+ if (prevAlgo &&
string(algo->GetName()) != string(prevAlgo->GetName()) )
modifiedHyp = true;
}
break;
}
case REMOVE_HYP: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
SetAlgoState(HYP_OK);
break;
}
case REMOVE_ALGO: { // perhaps a father algo applies ?
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
if (algo == NULL) // no more algo applying on subShape...
{
SetAlgoState(NO_ALGO);
break;
}
case ADD_FATHER_HYP: { // new father hypothesis ?
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
{
- if (_father->IsUsedHypothesis( anHyp, _subShape )) // new Hyp
+ if (_father->IsUsedHypothesis( anHyp, this )) // new Hyp
modifiedHyp = true;
}
else
break;
}
case ADD_FATHER_ALGO: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
if ( algo == anHyp ) { // a new algo on father
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
// check if algo changes
f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
f.AndNot( SMESH_HypoFilter::Is( algo ));
const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
- if (prevAlgo &&
+ if (prevAlgo &&
string(algo->GetName()) != string(prevAlgo->GetName()) )
modifiedHyp = true;
}
break;
}
case REMOVE_FATHER_HYP: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
// is there the same local hyp or maybe a new father algo applied?
break;
}
case REMOVE_FATHER_ALGO: {
- SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+ algo = gen->GetAlgo((*_father), _subShape);
if (algo == NULL) // no more applying algo on father
{
SetAlgoState(NO_ALGO);
break;
}
- if ((_algoState != oldAlgoState) || modifiedHyp)
+ if ( _algoState != oldAlgoState )
+ {
+ if (_algoState == HYP_OK )
+ algo->SetEventListener( this );
+ if ( oldAlgoState == HYP_OK )
+ DeleteOwnListeners();
+ }
+ NotifyListenersOnEvent( event, ALGO_EVENT, anHyp );
+
+ if (_algoState != oldAlgoState || modifiedHyp)
ComputeStateEngine(MODIF_ALGO_STATE);
return ret;
void SMESH_subMesh::SetAlgoState(int state)
{
-// if (state != _oldAlgoState)
-// int retc = ComputeStateEngine(MODIF_ALGO_STATE);
- _algoState = state;
+ _algoState = state;
}
//=============================================================================
SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
//EAP: a wire (dim==1) should notify edges (dim==1)
//EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
- if (/*EAP:dim > 1*/ _subShape.ShapeType() < TopAbs_EDGE )
+ if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
{
const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
void SMESH_subMesh::CleanDependsOn()
{
- MESSAGE("SMESH_subMesh::CleanDependsOn");
- // **** parcourir les ancetres dans l'ordre de dépendance
-
- ComputeStateEngine(CLEAN);
+ //MESSAGE("SMESH_subMesh::CleanDependsOn");
- const map < int, SMESH_subMesh * >&dependson = DependsOn();
- map < int, SMESH_subMesh * >::const_iterator its;
- for (its = dependson.begin(); its != dependson.end(); its++)
- {
- SMESH_subMesh *sm = (*its).second;
- sm->ComputeStateEngine(CLEAN);
- }
+ const map < int, SMESH_subMesh * >&dependson = DependsOn();
+ map < int, SMESH_subMesh * >::const_iterator its;
+ for (its = dependson.begin(); its != dependson.end(); its++)
+ {
+ SMESH_subMesh *sm = (*its).second;
+ sm->ComputeStateEngine(CLEAN);
+ }
}
//=============================================================================
}
}
-//=============================================================================
+//================================================================================
/*!
- *
+ * \brief Remove nodes and elements bound to submesh
+ * \param subMesh - submesh containing nodes and elements
*/
-//=============================================================================
+//================================================================================
-static void removeSubMesh( SMESHDS_Mesh * meshDS, const TopoDS_Shape& subShape)
+static void cleanSubMesh( SMESH_subMesh * subMesh )
{
- SMESHDS_SubMesh * subMeshDS = meshDS->MeshElements(subShape);
- if (subMeshDS!=NULL)
- {
- SMDS_ElemIteratorPtr ite=subMeshDS->GetElements();
- while(ite->more())
- {
- const SMDS_MeshElement * elt = ite->next();
- //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
- meshDS->RemoveElement(elt);
- }
+ if (subMesh) {
+ 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, subMeshDS);
+ }
- SMDS_NodeIteratorPtr itn=subMeshDS->GetNodes();
- while(itn->more())
- {
- const SMDS_MeshNode * node = itn->next();
- //MESSAGE( " RM node: "<<node->GetID());
- meshDS->RemoveNode(node);
+ SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
+ while (itn->more()) {
+ const SMDS_MeshNode * node = itn->next();
+ //MESSAGE( " RM node: "<<node->GetID());
+ //meshDS->RemoveNode(node);
+ meshDS->RemoveFreeNode(node, subMeshDS);
+ }
}
}
}
SMESH_Algo *algo = 0;
bool ret = true;
SMESH_Hypothesis::Hypothesis_Status hyp_status;
+ algo_state oldAlgoState = (algo_state) GetAlgoState();
switch (_computeState)
{
case NOT_READY:
switch (event)
{
- case MODIF_HYP: // nothing to do
- break;
+ case MODIF_HYP:
case MODIF_ALGO_STATE:
- if (_algoState == HYP_OK)
+ algo = gen->GetAlgo((*_father), _subShape);
+ if (algo && !algo->NeedDescretBoundary())
+ CleanDependsOn(); // clean sub-meshes with event CLEAN
+ if (algo)
{
- _computeState = READY_TO_COMPUTE;
+ ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+ if (ret)
+ _computeState = READY_TO_COMPUTE;
}
+ if ( _computeState == READY_TO_COMPUTE )
+ SetAlgoState(HYP_OK);
+ else
+ SetAlgoState(MISSING_HYP);
break;
- case COMPUTE: // nothing to do
+ case COMPUTE: // nothing to do
break;
case CLEAN:
- RemoveSubMeshElementsAndNodes();
- break;
- case CLEANDEP:
CleanDependants();
+ RemoveSubMeshElementsAndNodes();
break;
case SUBMESH_COMPUTED: // nothing to do
break;
case READY_TO_COMPUTE:
switch (event)
{
- case MODIF_HYP: // nothing to do
- break;
+ case MODIF_HYP:
case MODIF_ALGO_STATE:
- _computeState = NOT_READY;
algo = gen->GetAlgo((*_father), _subShape);
+ if (algo && !algo->NeedDescretBoundary())
+ CleanDependsOn(); // clean sub-meshes with event CLEAN
+ _computeState = NOT_READY;
if (algo)
{
ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
- if (ret)
+ if (ret) {
+ SetAlgoState(HYP_OK); // it might be KO if BAD_PARAM_VALUE
_computeState = READY_TO_COMPUTE;
+ }
+ else
+ SetAlgoState(MISSING_HYP);
}
break;
case COMPUTE:
{
MESSAGE("***** verify compute state *****");
_computeState = NOT_READY;
+ SetAlgoState(MISSING_HYP);
break;
}
// check submeshes needed
}
// compute
CleanDependants();
- //RemoveSubMeshElementsAndNodes();
- //removeSubMesh( _meshDS, _subShape );
- if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
- ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
- else
- ret = algo->Compute((*_father), _subShape);
-
+ RemoveSubMeshElementsAndNodes();
+ {
+ try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+ OCC_CATCH_SIGNALS;
+#endif
+ if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
+ ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
+ else
+ ret = algo->Compute((*_father), _subShape);
+ }
+ catch (Standard_Failure) {
+ MESSAGE( "Exception in algo->Compute() ");
+ ret = false;
+ }
+ }
if (!ret)
{
MESSAGE("problem in algo execution: failed to compute");
+ // release ALGO from responsibilty of partially built mesh
+ RemoveSubMeshElementsAndNodes();
_computeState = FAILED_TO_COMPUTE;
if (!algo->NeedDescretBoundary())
UpdateSubMeshState( FAILED_TO_COMPUTE );
#ifdef _DEBUG_
// Show vertices location of a failed shape
+ cout << algo->GetName() << " failed on shape with the following vertices:" << endl;
TopTools_IndexedMapOfShape vMap;
TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
}
break;
case CLEAN:
+ CleanDependants();
RemoveSubMeshElementsAndNodes();
_computeState = NOT_READY;
algo = gen->GetAlgo((*_father), _subShape);
ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
if (ret)
_computeState = READY_TO_COMPUTE;
+ else
+ SetAlgoState(MISSING_HYP);
}
break;
- case CLEANDEP:
- CleanDependants();
- break;
case SUBMESH_COMPUTED: // nothing to do
break;
case SUBMESH_RESTORED:
switch (event)
{
case MODIF_HYP:
- CleanDependants(); // recursive recall with event CLEANDEP
- algo = gen->GetAlgo((*_father), _subShape);
- if (algo && !algo->NeedDescretBoundary())
- CleanDependsOn(); // remove sub-mesh with event CLEANDEP
- break;
case MODIF_ALGO_STATE:
- CleanDependants(); // recursive recall with event CLEANDEP
+ ComputeStateEngine( CLEAN );
algo = gen->GetAlgo((*_father), _subShape);
if (algo && !algo->NeedDescretBoundary())
- CleanDependsOn(); // remove sub-mesh with event CLEANDEP
+ CleanDependsOn(); // clean sub-meshes with event CLEAN
break;
- case COMPUTE: // nothing to do
+ case COMPUTE: // nothing to do
break;
case CLEAN:
+ CleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN
RemoveSubMeshElementsAndNodes();
_computeState = NOT_READY;
algo = gen->GetAlgo((*_father), _subShape);
ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
if (ret)
_computeState = READY_TO_COMPUTE;
+ else
+ SetAlgoState(MISSING_HYP);
}
break;
- case CLEANDEP:
- CleanDependants(); // recursive recall with event CLEANDEP
- break;
case SUBMESH_COMPUTED: // nothing to do
break;
case SUBMESH_RESTORED:
case COMPUTE: // nothing to do
break;
case CLEAN:
+ CleanDependants(); // submeshes dependent on me should be cleaned as well
RemoveSubMeshElementsAndNodes();
if (_algoState == HYP_OK)
_computeState = READY_TO_COMPUTE;
else
_computeState = NOT_READY;
break;
- case CLEANDEP:
- CleanDependants();
- break;
case SUBMESH_COMPUTED: // allow retry compute
if (_algoState == HYP_OK)
_computeState = READY_TO_COMPUTE;
break;
}
+ if ( _algoState != oldAlgoState || event == MODIF_HYP )
+ {
+ if ( oldAlgoState == HYP_OK )
+ DeleteOwnListeners();
+ if (_algoState == HYP_OK && algo )
+ algo->SetEventListener( this );
+ }
+ NotifyListenersOnEvent( event, COMPUTE_EVENT );
+
//SCRUTE(_computeState);
return ret;
}
void SMESH_subMesh::CleanDependants()
{
+ int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
+
TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
for (; it.More(); it.Next())
{
const TopoDS_Shape& ancestor = it.Value();
- // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEANDEP)
- // will erase mesh on other shapes in a compound
- if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
- SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
- if (aSubMesh)
- aSubMesh->ComputeStateEngine(CLEANDEP);
+ if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
+ // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
+ // will erase mesh on other shapes in a compound
+ if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
+ SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
+ if (aSubMesh)
+ aSubMesh->ComputeStateEngine(CLEAN);
+ }
}
}
- ComputeStateEngine(CLEAN);
}
//=============================================================================
{
//SCRUTE(_subShape.ShapeType());
- removeSubMesh( _meshDS, _subShape );
+ cleanSubMesh( this );
// algo may bind a submesh not to _subShape, eg 3D algo
// sets nodes on SHELL while _subShape may be SOLID
int dim = SMESH_Gen::GetShapeDim( _subShape );
int type = _subShape.ShapeType() + 1;
- for ( ; type <= TopAbs_EDGE; type++)
+ for ( ; type <= TopAbs_EDGE; type++) {
if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
{
TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
for ( ; exp.More(); exp.Next() )
- removeSubMesh( _meshDS, exp.Current() );
+ cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
}
else
break;
+ }
}
//=======================================================================
TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
for ( ; exp.More(); exp.Next() )
{
- SMESHDS_SubMesh * subMeshDS = _meshDS->MeshElements( exp.Current() );
- if ( subMeshDS != NULL &&
- (subMeshDS->GetElements()->more() || subMeshDS->GetNodes()->more())) {
+ SMESHDS_SubMesh * smDS = _meshDS->MeshElements( exp.Current() );
+ if ( smDS && ( smDS->NbElements() || smDS->NbNodes()))
return true;
- }
}
}
else
if ( mainShape.IsSame( _subShape ))
return _subShape;
+ const bool ignoreAuxiliaryHyps = false;
list<const SMESHDS_Hypothesis*> aUsedHyp =
- theAlgo->GetUsedHypothesis( *_father, _subShape ); // copy
+ theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
// put in a compound all shapes with the same hypothesis assigned
// and a good ComputState
if (subMesh->GetComputeState() == READY_TO_COMPUTE &&
anAlgo == theAlgo &&
- anAlgo->GetUsedHypothesis( *_father, S ) == aUsedHyp)
+ anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
{
aBuilder.Add( aCompound, S );
}
//=======================================================================
//function : GetSimilarAttached
-//purpose : return nb of hypotheses attached to theShape.
+//purpose : return a hypothesis attached to theShape.
// If theHyp is provided, similar but not same hypotheses
-// are countered; else only applicable ones having theHypType
-// are countered
+// is returned; else only applicable ones having theHypType
+// is returned
//=======================================================================
const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape& theShape,
const SMESH_Hypothesis * theHyp,
const int theHypType)
{
- SMESH_HypoFilter filter;
- filter.Init( SMESH_HypoFilter::HasType( theHyp ? theHyp->GetType() : theHypType ));
+ SMESH_HypoFilter hypoKind;
+ hypoKind.Init( hypoKind.HasType( theHyp ? theHyp->GetType() : theHypType ));
if ( theHyp ) {
- filter.And( SMESH_HypoFilter::HasDim( theHyp->GetDim() ));
- filter.AndNot( SMESH_HypoFilter::Is( theHyp ));
+ hypoKind.And ( hypoKind.HasDim( theHyp->GetDim() ));
+ hypoKind.AndNot( hypoKind.Is( theHyp ));
+ if ( theHyp->IsAuxiliary() )
+ hypoKind.And( hypoKind.HasName( theHyp->GetName() ));
+ else
+ hypoKind.AndNot( hypoKind.IsAuxiliary());
+ }
+ else {
+ hypoKind.And( hypoKind.IsApplicableTo( theShape ));
}
- else
- filter.And( SMESH_HypoFilter::IsApplicableTo( theShape ));
- return _father->GetHypothesis( theShape, filter, false );
+ return _father->GetHypothesis( theShape, hypoKind, false );
}
//=======================================================================
}
return SMESH_Hypothesis::HYP_OK;
}
+
+//================================================================================
+/*!
+ * \brief Sets an event listener and its data to a submesh
+ * \param listener - the listener to store
+ * \param data - the listener data to store
+ * \param where - the submesh to store the listener and it's data
+ * \param deleteListener - if true then the listener will be deleted as
+ * it is removed from where submesh
+ *
+ * It remembers the submesh where it puts the listener in order to delete
+ * them when HYP_OK algo_state is lost
+ * After being set, event listener is notified on each event of where submesh.
+ */
+//================================================================================
+
+void SMESH_subMesh::SetEventListener(EventListener* listener,
+ EventListenerData* data,
+ SMESH_subMesh* where)
+{
+ if ( listener && where ) {
+ where->SetEventListener( listener, data );
+ myOwnListeners.push_back( make_pair( where, listener ));
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Sets an event listener and its data to a submesh
+ * \param listener - the listener to store
+ * \param data - the listener data to store
+ *
+ * After being set, event listener is notified on each event of a submesh.
+ */
+//================================================================================
+
+void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* data)
+{
+ myEventListeners.insert( make_pair( listener, data ));
+}
+
+//================================================================================
+/*!
+ * \brief Return an event listener data
+ * \param listener - the listener whose data is
+ * \retval EventListenerData* - found data, maybe NULL
+ */
+//================================================================================
+
+EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const
+{
+ map< EventListener*, EventListenerData* >::const_iterator l_d =
+ myEventListeners.find( listener );
+ if ( l_d != myEventListeners.end() )
+ return l_d->second;
+ return 0;
+}
+
+//================================================================================
+/*!
+ * \brief Notify stored event listeners on the occured 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 data - listener data stored in the subMesh
+ * \param hyp - hypothesis, if eventType is algo_event
+ */
+//================================================================================
+
+void SMESH_subMesh::NotifyListenersOnEvent( const int event,
+ const event_type eventType,
+ SMESH_Hypothesis* hyp)
+{
+ map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.begin();
+ for ( ; l_d != myEventListeners.end(); ++l_d )
+ l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp );
+}
+
+//================================================================================
+/*!
+ * \brief Unregister the listener and delete listener's data
+ * \param listener - the event listener
+ */
+//================================================================================
+
+void SMESH_subMesh::DeleteEventListener(EventListener* listener)
+{
+ map< EventListener*, EventListenerData* >::iterator l_d =
+ myEventListeners.find( listener );
+ if ( l_d != myEventListeners.end() ) {
+ if ( l_d->first->IsDeletable() ) delete l_d->first;
+ if ( l_d->second->IsDeletable() ) delete l_d->second;
+ myEventListeners.erase( l_d );
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Delete event listeners depending on algo of this submesh
+ */
+//================================================================================
+
+void SMESH_subMesh::DeleteOwnListeners()
+{
+ list< pair< SMESH_subMesh*, EventListener* > >::iterator sm_l;
+ for ( sm_l = myOwnListeners.begin(); sm_l != myOwnListeners.end(); ++sm_l)
+ sm_l->first->DeleteEventListener( sm_l->second );
+ myOwnListeners.clear();
+}
+
+//================================================================================
+/*!
+ * \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 data - listener data stored in the subMesh
+ * \param hyp - hypothesis, if eventType is algo_event
+ *
+ * The base implementation translates CLEAN event to the subMesh
+ * stored in listener data. Also it sends SUBMESH_COMPUTED event in case of
+ * successful COMPUTE event.
+ */
+//================================================================================
+
+void SMESH_subMeshEventListener::ProcessEvent(const int event,
+ const int eventType,
+ SMESH_subMesh* subMesh,
+ EventListenerData* data,
+ SMESH_Hypothesis* /*hyp*/)
+{
+ if ( data && !data->mySubMeshes.empty() &&
+ eventType == SMESH_subMesh::COMPUTE_EVENT)
+ {
+ ASSERT( data->mySubMeshes.front() != subMesh );
+ switch ( event ) {
+ case SMESH_subMesh::CLEAN:
+ data->mySubMeshes.front()->ComputeStateEngine( event );
+ break;
+ case SMESH_subMesh::COMPUTE:
+ if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK )
+ data->mySubMeshes.front()->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
+ break;
+ default:;
+ }
+ }
+}