-// SMESH SMESH : implementaion of SMESH idl descriptions
-//
-// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
//
-// 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.
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
-// 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 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, or (at your option) any later version.
//
-// 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
+// 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
//
+
+// SMESH SMESH : implementaion of SMESH idl descriptions
// File : SMESH_subMesh.cxx
// Author : Paul RASCLE, EDF
// Module : SMESH
-// $Header$
#include "SMESH_subMesh.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"
+#include "Basics_Utils.hxx"
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
-#include <gp_Pnt.hxx>
-#include <TopExp_Explorer.hxx>
#include <TopoDS_Iterator.hxx>
+#include <gp_Pnt.hxx>
#include <Standard_OutOfMemory.hxx>
#include <Standard_ErrorHandler.hxx>
+#include <numeric>
+
using namespace std;
//=============================================================================
SMESHDS_Mesh * meshDS,
const TopoDS_Shape & aSubShape)
{
- _subShape = aSubShape;
- _subMeshDS = meshDS->MeshElements(_subShape); // may be null ...
- _father = father;
- _Id = Id;
- _dependenceAnalysed = _alwaysComputed = false;
-
- if (_subShape.ShapeType() == TopAbs_VERTEX)
- {
- _algoState = HYP_OK;
- _computeState = READY_TO_COMPUTE;
- }
- else
- {
- _algoState = NO_ALGO;
- _computeState = NOT_READY;
- }
+ _subShape = aSubShape;
+ _subMeshDS = meshDS->MeshElements(_subShape); // may be null ...
+ _father = father;
+ _Id = Id;
+ _dependenceAnalysed = _alwaysComputed = false;
+ _algo = 0;
+ if (_subShape.ShapeType() == TopAbs_VERTEX)
+ {
+ _algoState = HYP_OK;
+ _computeState = READY_TO_COMPUTE;
+ }
+ else
+ {
+ _algoState = NO_ALGO;
+ _computeState = NOT_READY;
+ }
+ _computeCost = 0; // how costly is to compute this sub-mesh
+ _realComputeCost = 0;
}
//=============================================================================
SMESH_subMesh::~SMESH_subMesh()
{
- MESSAGE("SMESH_subMesh::~SMESH_subMesh");
- // ****
- DeleteOwnListeners();
+ deleteOwnListeners();
}
//=============================================================================
*/
//=============================================================================
+const SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS() const
+{
+ return ((SMESH_subMesh*) this )->GetSubMeshDS();
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
{
if ( !GetSubMeshDS() ) {
//================================================================================
/*!
- * \brief Allow algo->Compute() if a subshape of lower dim is meshed but
+ * \brief Returns a current algorithm
+ */
+//================================================================================
+
+SMESH_Algo* SMESH_subMesh::GetAlgo() const
+{
+ if ( !_algo )
+ {
+ SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this );
+ me->_algo = _father->GetGen()->GetAlgo( me );
+ }
+ return _algo;
+}
+
+//================================================================================
+/*!
+ * \brief Allow algo->Compute() if a sub-shape of lower dim is meshed but
* none mesh entity is bound to it (PAL13615, 2nd part)
*/
//================================================================================
ComputeStateEngine( CHECK_COMPUTE_STATE );
}
+//=======================================================================
+/*!
+ * \brief Return true if no mesh entities is bound to the submesh
+ */
+//=======================================================================
+
+bool SMESH_subMesh::IsEmpty() const
+{
+ if (SMESHDS_SubMesh * subMeshDS = ((SMESH_subMesh*)this)->GetSubMeshDS())
+ return (!subMeshDS->NbElements() && !subMeshDS->NbNodes());
+ return true;
+}
+
//=======================================================================
//function : IsMeshComputed
//purpose : check if _subMeshDS contains mesh elements
//=============================================================================
/*!
- *
+ * Return true if all sub-meshes have been meshed
*/
//=============================================================================
-bool SMESH_subMesh::SubMeshesComputed()
+bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const
{
int myDim = SMESH_Gen::GetShapeDim( _subShape );
int dimToCheck = myDim - 1;
bool subMeshesComputed = true;
+ if ( isFailedToCompute ) *isFailedToCompute = false;
// check subMeshes with upper dimension => reverse iteration
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
while ( smIt->more() )
if ( sm->_alwaysComputed )
continue;
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)
- break; // the rest subMeshes are all of less dimension
+ if ( !_algo || _algo->NeedDiscreteBoundary() ) {
+ int dim = SMESH_Gen::GetShapeDim( ss );
+ if (dim < dimToCheck)
+ break; // the rest subMeshes are all of less dimension
+ }
SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
- (ds && ( ds->NbNodes() || ds->NbElements() )));
+ (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() )));
if (!computeOk)
{
- int type = ss.ShapeType();
-
subMeshesComputed = false;
-
- 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;
- }
- }
-
- break;
+ 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;
}
}
return subMeshesComputed;
}
-//=============================================================================
+//================================================================================
/*!
- *
+ * \brief Return cost of computing this sub-mesh. If hypotheses are not well defined,
+ * zero is returned
+ * \return int - the computation cost in abstract units.
*/
-//=============================================================================
+//================================================================================
-bool SMESH_subMesh::SubMeshesReady()
+int SMESH_subMesh::GetComputeCost() const
{
- 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 _realComputeCost;
+}
+
+//================================================================================
+/*!
+ * \brief Return cost of computing this sub-mesh. The cost depends on the shape type
+ * and number of sub-meshes this one DependsOn().
+ * \return int - the computation cost in abstract units.
+ */
+//================================================================================
+
+int SMESH_subMesh::computeCost() const
+{
+ if ( !_computeCost )
+ {
+ int computeCost;
+ switch ( _subShape.ShapeType() ) {
+ case TopAbs_SOLID:
+ case TopAbs_SHELL: computeCost = 5000; break;
+ case TopAbs_FACE: computeCost = 500; break;
+ case TopAbs_EDGE: computeCost = 2; break;
+ default: computeCost = 1;
}
+ SMESH_subMeshIteratorPtr childIt = getDependsOnIterator(/*includeSelf=*/false);
+ while ( childIt->more() )
+ computeCost += childIt->next()->computeCost();
+
+ ((SMESH_subMesh*)this)->_computeCost = computeCost;
}
- return subMeshesReady;
+ return _computeCost;
}
//=============================================================================
/*!
- * 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()
{
- 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())
- {
- InsertDependence(exp.Current()); //only shell not in solid
- }
- 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());
- }
- 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 ); 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;
}
+//================================================================================
+/*!
+ * \brief Return a key for SMESH_subMesh::_mapDepend map
+ */
+//================================================================================
+
+namespace
+{
+ int dependsOnMapKey( const SMESH_subMesh* sm )
+ {
+ int type = sm->GetSubShape().ShapeType();
+ int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid
+ int cle = sm->GetId();
+ cle += 10000000 * ordType; // sort map by ordType then index
+ return cle;
+ }
+}
+
//=============================================================================
/*!
- * 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)
{
- //MESSAGE("SMESH_subMesh::InsertDependence");
- SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
- int type = aSubShape.ShapeType();
- 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())
+ TopExp_Explorer sub( aShape, aSubType );
+ 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() );
+ }
}
}
+//================================================================================
+/*!
+ * \brief Return \c true if \a this sub-mesh depends on \a other
+ */
+//================================================================================
+
+bool SMESH_subMesh::DependsOn( const SMESH_subMesh* other ) const
+{
+ return other ? _mapDepend.count( dependsOnMapKey( other )) : false;
+}
+
//=============================================================================
/*!
- *
+ * Return a shape of \a this sub-mesh
*/
//=============================================================================
const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
{
- //MESSAGE("SMESH_subMesh::GetSubShape");
- return _subShape;
+ return _subShape;
}
-
//=======================================================================
//function : CanAddHypothesis
//purpose : return true if theHypothesis can be attached to me:
bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
{
int aHypDim = theHypothesis->GetDim();
- if(_father->HasShapeToMesh()) {
- int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
- if ( aHypDim <= aShapeDim )
- return true;
- }
- else
- //Only 3D hypothesis may be assigned to the mesh w/o geometry
- return aHypDim == 3;
-// if ( aHypDim < aShapeDim )
-// return ( _father->IsMainShape( _subShape ));
+ int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
+ // issue 21106. Forbid 3D mesh on the SHELL
+ // if (aHypDim == 3 && aShapeDim == 3) {
+ // // check case of open shell
+ // //if (_subShape.ShapeType() == TopAbs_SHELL && !_subShape.Closed())
+ // if (_subShape.ShapeType() == TopAbs_SHELL && !BRep_Tool::IsClosed(_subShape))
+ // return false;
+ // }
+ if ( aHypDim <= aShapeDim )
+ return true;
return false;
}
const TopAbs_ShapeEnum theShapeType)
{
if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
+ {
// algorithm
- return ( theHypothesis->GetShapeType() & (1<< theShapeType));
+ if ( theHypothesis->GetShapeType() & (1<< theShapeType))
+ // issue 21106. Forbid 3D mesh on the SHELL
+ return !( theHypothesis->GetDim() == 3 && theShapeType == TopAbs_SHELL );
+ else
+ return false;
+ }
// hypothesis
switch ( theShapeType ) {
return false;
}
-//=============================================================================
+//================================================================================
/*!
- *
+ * \brief Treats modification of hypotheses definition
+ * \param [in] event - what happens
+ * \param [in] anHyp - a hypothesis
+ * \return SMESH_Hypothesis::Hypothesis_Status - a treatment result.
+ *
+ * Optional description of a problematic situation (if any) can be retrieved
+ * via GetComputeError().
*/
-//=============================================================================
+//================================================================================
SMESH_Hypothesis::Hypothesis_Status
SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
{
- // MESSAGE("SMESH_subMesh::AlgoStateEngine");
- //SCRUTE(_algoState);
- //SCRUTE(event);
-
// **** 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_Gen* gen =_father->GetGen();
SMESH_Algo* algo = 0;
+ _algo = 0;
if (_subShape.ShapeType() == TopAbs_VERTEX )
{
if ( event != REMOVE_FATHER_ALGO )
{
_algoState = NO_ALGO;
- algo = gen->GetAlgo(*_father, _subShape);
+ algo = GetAlgo();
if ( algo ) {
_algoState = MISSING_HYP;
if ( event == REMOVE_FATHER_HYP ||
int oldAlgoState = _algoState;
bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE
+ SMESH_Algo* algoRequiringCleaning = 0;
bool isApplicableHyp = IsApplicableHypotesis( anHyp );
// check if a shape needed by algo is present
// -------------------------------------------
algo = static_cast< SMESH_Algo* >( anHyp );
- if(_father->GetShapeToMesh() != SMESH_Mesh::PseudoShape())
- if ( !_father->HasShapeToMesh() && algo->NeedShape() )
- return SMESH_Hypothesis::HYP_BAD_GEOMETRY;
+ if ( !_father->HasShapeToMesh() && algo->NeedShape() )
+ return SMESH_Hypothesis::HYP_NEED_SHAPE;
// ----------------------
// check mesh conformity
// ----------------------
if (isApplicableHyp && !_father->IsNotConformAllowed() && !IsConform( algo ))
return SMESH_Hypothesis::HYP_NOTCONFORM;
+
+ // check if all-dimensional algo is hidden by other local one
+ if ( event == ADD_ALGO ) {
+ SMESH_HypoFilter filter( SMESH_HypoFilter::HasType( algo->GetType() ));
+ 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() )
+ algoRequiringCleaning = curAlgo;
+ }
}
// ----------------------------------
if ( ! CanAddHypothesis( anHyp )) // check dimension
return SMESH_Hypothesis::HYP_BAD_DIM;
- if(anHyp->GetDim() == 3 && !_father->HasShapeToMesh()
- && event == ADD_ALGO) {
- //Only NETGEN_3D and GHS3D_3D can be assigned to the Mesh w/o geometryy
- bool isNetgen3D = (strcmp( "NETGEN_3D", anHyp->GetName()) == 0);
- bool isGhs3d = (strcmp( "GHS3D_3D", anHyp->GetName()) == 0);
- if( !isNetgen3D && !isGhs3d)
- return SMESH_Hypothesis::HYP_BAD_DIM;
- }
-
-
-
- if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
+ if ( !anHyp->IsAuxiliary() && getSimilarAttached( _subShape, anHyp ) )
return SMESH_Hypothesis::HYP_ALREADY_EXIST;
if ( !meshDS->AddHypothesis(_subShape, anHyp))
if (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();
- ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
- }
+ if (!algo->NeedDiscreteBoundary())
+ algoRequiringCleaning = algo;
}
}
if (!isApplicableHyp)
return ret; // not applicable hypotheses do not change algo state
+ if (( algo = GetAlgo()))
+ algo->InitComputeError();
+
switch (_algoState)
{
case ADD_HYP:
break;
case ADD_ALGO: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else if ( algo->IsStatusFatal( aux_ret )) {
meshDS->RemoveHypothesis(_subShape, anHyp);
ret = aux_ret;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
break;
}
case REMOVE_HYP:
case ADD_FATHER_HYP:
break;
case ADD_FATHER_ALGO: { // Algo just added in father
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if ( algo == anHyp ) {
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
case REMOVE_FATHER_HYP:
break;
case REMOVE_FATHER_ALGO: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
if (algo)
{
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
switch (event)
{
case ADD_HYP: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, ret ))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
if (SMESH_Hypothesis::IsStatusFatal( ret ))
meshDS->RemoveHypothesis(_subShape, anHyp);
else if (!_father->IsUsedHypothesis( anHyp, this ))
break;
}
case ADD_ALGO: { //already existing algo : on father ?
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else if ( algo->IsStatusFatal( aux_ret )) {
meshDS->RemoveHypothesis(_subShape, anHyp);
ret = aux_ret;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
break;
}
case REMOVE_HYP:
break;
case REMOVE_ALGO: { // perhaps a father algo applies ?
- algo = gen->GetAlgo((*_father), _subShape);
- if (algo == NULL) // no more algo applying on subShape...
+ algo = GetAlgo();
+ if (algo == NULL) // no more algo applying on sub-shape...
{
- SetAlgoState(NO_ALGO);
+ setAlgoState(NO_ALGO);
}
else
{
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
case MODIF_HYP: // assigned hypothesis value may become good
case ADD_FATHER_HYP: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
break;
}
case ADD_FATHER_ALGO: { // new father algo
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT( algo );
if ( algo == anHyp ) {
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
case REMOVE_FATHER_HYP: // nothing to do
break;
case REMOVE_FATHER_ALGO: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
if (algo == NULL) // no more applying algo on father
{
- SetAlgoState(NO_ALGO);
+ setAlgoState(NO_ALGO);
}
else
{
if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
switch (event)
{
case ADD_HYP: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
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, this ))
+ 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 ?
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
// check if algo changes
SMESH_HypoFilter f;
f.Init( SMESH_HypoFilter::IsAlgo() );
f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
f.AndNot( SMESH_HypoFilter::Is( algo ));
- const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
+ const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true );
if (prevAlgo &&
- string(algo->GetName()) != string(prevAlgo->GetName()) )
+ string( algo->GetName()) != prevAlgo->GetName())
modifiedHyp = true;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
break;
}
case REMOVE_HYP: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
- SetAlgoState(HYP_OK);
+ setAlgoState(HYP_OK);
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
modifiedHyp = true;
break;
}
case REMOVE_ALGO: { // perhaps a father algo applies ?
- algo = gen->GetAlgo((*_father), _subShape);
- if (algo == NULL) // no more algo applying on subShape...
+ algo = GetAlgo();
+ if (algo == NULL) // no more algo applying on sub-shape...
{
- SetAlgoState(NO_ALGO);
+ setAlgoState(NO_ALGO);
}
else
{
modifiedHyp = true;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
case MODIF_HYP: // hypothesis value may become bad
case ADD_FATHER_HYP: { // new father hypothesis ?
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
{
modifiedHyp = true;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
break;
}
case ADD_FATHER_ALGO: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
if ( algo == anHyp ) { // a new algo on father
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
// check if algo changes
f.Init( SMESH_HypoFilter::IsAlgo() );
f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
f.AndNot( SMESH_HypoFilter::Is( algo ));
- const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
+ const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( this, f, true );
if (prevAlgo &&
string(algo->GetName()) != string(prevAlgo->GetName()) )
modifiedHyp = true;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
case REMOVE_FATHER_HYP: {
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
// is there the same local hyp or maybe a new father algo applied?
- if ( !GetSimilarAttached( _subShape, anHyp ) )
+ if ( !getSimilarAttached( _subShape, anHyp ) )
modifiedHyp = true;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
break;
}
case REMOVE_FATHER_ALGO: {
- algo = gen->GetAlgo((*_father), _subShape);
+ // IPAL21346. Edges not removed when Netgen 1d-2d is removed from a SOLID.
+ // CLEAN was not called at event REMOVE_ALGO because the algo is not applicable to SOLID.
+ algo = dynamic_cast<SMESH_Algo*> (anHyp);
+ if (!algo->NeedDiscreteBoundary())
+ algoRequiringCleaning = algo;
+ algo = GetAlgo();
if (algo == NULL) // no more applying algo on father
{
- SetAlgoState(NO_ALGO);
+ setAlgoState(NO_ALGO);
}
else
{
modifiedHyp = true;
}
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
}
// 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?
SMESH_Gen* gen = _father->GetGen();
- TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
- for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) {
- if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() ))
- if ( !upperAlgo->NeedDescretBoundary() )
+ const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+ for ( size_t iA = 0; ( ret == SMESH_Hypothesis::HYP_OK && iA < ancestors.size()); ++iA ) {
+ if ( SMESH_Algo* upperAlgo = ancestors[ iA ]->GetAlgo() )
+ if ( !upperAlgo->NeedDiscreteBoundary() && !upperAlgo->SupportSubmeshes())
ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
}
// is algo hiding?
- if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDescretBoundary() ) {
+ if ( ret == SMESH_Hypothesis::HYP_OK &&
+ !algo->NeedDiscreteBoundary() &&
+ !algo->SupportSubmeshes())
+ {
+ TopoDS_Shape algoAssignedTo, otherAssignedTo;
+ gen->GetAlgo( this, &algoAssignedTo );
map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
- if ( gen->GetAlgo( *_father, i_sm->second->_subShape ))
+ if ( gen->GetAlgo( i_sm->second, &otherAssignedTo ) &&
+ SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo ))
ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
}
}
+ if ( _algo ) { // get an error description set by _algo->CheckHypothesis()
+ _computeError = _algo->GetComputeError();
+ _algo->InitComputeError();
+ }
+
bool stateChange = ( _algoState != oldAlgoState );
if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
algo->SetEventListener( this );
- NotifyListenersOnEvent( event, ALGO_EVENT, anHyp );
+ if ( event == REMOVE_ALGO || event == REMOVE_FATHER_ALGO )
+ _algo = 0;
+
+ notifyListenersOnEvent( event, ALGO_EVENT, anHyp );
if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
- DeleteOwnListeners();
+ deleteOwnListeners();
SetIsAlwaysComputed( false );
if (_subShape.ShapeType() == TopAbs_VERTEX ) {
// restore default states
}
}
- if (stateChange || modifiedHyp)
- ComputeStateEngine(MODIF_ALGO_STATE);
+ if ( algoRequiringCleaning ) {
+ // added or removed algo is all-dimensional
+ ComputeStateEngine( CLEAN );
+ cleanDependsOn( algoRequiringCleaning );
+ ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+ }
+
+ if ( stateChange || modifiedHyp )
+ ComputeStateEngine( MODIF_ALGO_STATE );
+
+ _realComputeCost = ( _algoState == HYP_OK ) ? computeCost() : 0;
return ret;
}
// Suppose that theAlgo is applicable to _subShape, do not check it here
//if ( !IsApplicableHypotesis( theAlgo )) return false;
- // check only algo that doesn't NeedDescretBoundary(): because mesh made
+ // check only algo that doesn't NeedDiscreteBoundary(): because mesh made
// on a sub-shape will be ignored by theAlgo
- if ( theAlgo->NeedDescretBoundary() ||
+ if ( theAlgo->NeedDiscreteBoundary() ||
!theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
return true;
for (; itsub.More(); itsub.Next())
{
// loop on adjacent subShapes
- TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
- for (; it.More(); it.Next())
+ const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+ for ( size_t iA = 0; iA < ancestors.size(); ++iA )
{
- const TopoDS_Shape& adjacent = it.Value();
+ const TopoDS_Shape& adjacent = ancestors[ iA ]->GetSubShape();
if ( _subShape.IsSame( adjacent )) continue;
if ( adjacent.ShapeType() != _subShape.ShapeType())
break;
// check algo attached to smAdjacent
- SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
+ SMESH_Algo * algo = ancestors[ iA ]->GetAlgo();
if (algo &&
- !algo->NeedDescretBoundary() &&
+ !algo->NeedDiscreteBoundary() &&
algo->OnlyUnaryInput())
return false; // NOT CONFORM MESH WILL BE PRODUCED
}
*/
//=============================================================================
-void SMESH_subMesh::SetAlgoState(int state)
+void SMESH_subMesh::setAlgoState(algo_state state)
{
_algoState = state;
}
-//=============================================================================
+//================================================================================
/*!
+ * \brief Send an event to sub-meshes
+ * \param [in] event - the event
+ * \param [in] anHyp - an hypothesis
+ * \param [in] exitOnFatal - to stop iteration on sub-meshes if a sub-mesh
+ * reports a fatal result
+ * \return SMESH_Hypothesis::Hypothesis_Status - the worst result
*
+ * Optional description of a problematic situation (if any) can be retrieved
+ * via GetComputeError().
*/
-//=============================================================================
+//================================================================================
+
SMESH_Hypothesis::Hypothesis_Status
- SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
- SMESH_Hypothesis * anHyp)
+ SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
+ SMESH_Hypothesis * anHyp,
+ bool exitOnFatal)
{
SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
//EAP: a wire (dim==1) should notify edges (dim==1)
{
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
while ( smIt->more() ) {
- SMESH_Hypothesis::Hypothesis_Status ret2 =
- smIt->next()->AlgoStateEngine(event, anHyp);
+ SMESH_subMesh* sm = smIt->next();
+ SMESH_Hypothesis::Hypothesis_Status ret2 = sm->AlgoStateEngine(event, anHyp);
if ( ret2 > ret )
+ {
ret = ret2;
+ _computeError = sm->_computeError;
+ sm->_computeError.reset();
+ if ( exitOnFatal && SMESH_Hypothesis::IsStatusFatal( ret ))
+ break;
+ }
}
}
return ret;
}
-//=============================================================================
+//================================================================================
/*!
- *
+ * \brief Remove elements from sub-meshes.
+ * \param algoRequiringCleaning - an all-dimensional algorithm whose presence
+ * causes the cleaning.
*/
-//=============================================================================
+//================================================================================
-void SMESH_subMesh::CleanDependsOn()
+void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
{
- SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
- while ( smIt->more() )
- smIt->next()->ComputeStateEngine(CLEAN);
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,
+ /*complexShapeFirst=*/true);
+ if ( _father->NbNodes() == 0 )
+ {
+ while ( smIt->more() )
+ smIt->next()->ComputeStateEngine(CHECK_COMPUTE_STATE);
+ }
+ else if ( !algoRequiringCleaning || !algoRequiringCleaning->SupportSubmeshes() )
+ {
+ while ( smIt->more() )
+ smIt->next()->ComputeStateEngine(CLEAN);
+ }
+ 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;
+ bool toKeepPrevShapeType = false;
+ while ( smIt->more() )
+ {
+ SMESH_subMesh* sm = smIt->next();
+ sm->ComputeStateEngine(CHECK_COMPUTE_STATE);
+ if ( !sm->IsEmpty() )
+ {
+ const bool sameShapeType = ( prevShapeType == sm->GetSubShape().ShapeType() );
+ bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
+ if ( !sameShapeType )
+ {
+ // check if the algo allows presence of global algos of dimension the algo
+ // can generate it-self
+ int shapeDim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
+ keepSubMeshes = algoRequiringCleaning->NeedLowerHyps( shapeDim );
+ 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;
+ }
+ // remember all sub-meshes of sm
+ if ( keepSubMeshes )
+ {
+ SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false);
+ while ( smIt2->more() )
+ smToKeep.insert( smIt2->next() );
+ }
+ }
+ }
+ // remove elements
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
+ while ( smIt->more() )
+ {
+ SMESH_subMesh* sm = smIt->next();
+ if ( !smToKeep.count( sm ))
+ sm->ComputeStateEngine(CLEAN);
+ }
+ }
}
//=============================================================================
void SMESH_subMesh::DumpAlgoState(bool isMain)
{
- int dim = SMESH_Gen::GetShapeDim(_subShape);
-// if (dim < 1) return;
- 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 = " << dim << " type of shape " << type);
- 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;
- }
+ 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);
+ }
+ }
+ 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;
+ }
}
//================================================================================
const SMDS_MeshElement * elt = ite->next();
//MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
//meshDS->RemoveElement(elt);
- meshDS->RemoveFreeElement(elt, subMeshDS);
+ 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->NbInverseNodes() == 0 )
- meshDS->RemoveFreeNode(node, subMeshDS);
+ if ( node->NbInverseElements() == 0 )
+ meshDS->RemoveFreeNode(node, 0);
else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
meshDS->RemoveNode(node);
}
+ subMeshDS->Clear();
}
}
}
bool SMESH_subMesh::ComputeStateEngine(int event)
{
- _computeError.reset();
+ switch ( event ) {
+ case MODIF_ALGO_STATE:
+ case COMPUTE:
+ case COMPUTE_SUBMESH:
+ //case COMPUTE_CANCELED:
+ case CLEAN:
+ //case SUBMESH_COMPUTED:
+ //case SUBMESH_RESTORED:
+ //case SUBMESH_LOADED:
+ //case MESH_ENTITY_REMOVED:
+ //case CHECK_COMPUTE_STATE:
+ _computeError.reset(); break;
+ default:;
+ }
- //MESSAGE("SMESH_subMesh::ComputeStateEngine");
- //SCRUTE(_computeState);
- //SCRUTE(event);
+ if ( event == CLEAN )
+ _alwaysComputed = false; // Unset 'true' set by MergeNodes() (issue 0022182)
if (_subShape.ShapeType() == TopAbs_VERTEX)
{
_computeState = READY_TO_COMPUTE;
SMESHDS_SubMesh* smDS = GetSubMeshDS();
- if ( smDS && smDS->NbNodes() ) {
- _computeState = COMPUTE_OK;
+ if ( smDS && smDS->NbNodes() )
+ {
+ if ( event == CLEAN ) {
+ cleanDependants();
+ cleanSubMesh( this );
+ }
+ else
+ _computeState = COMPUTE_OK;
}
- else if ( event == COMPUTE && !_alwaysComputed ) {
+ else if (( event == COMPUTE || event == COMPUTE_SUBMESH )
+ && !_alwaysComputed )
+ {
const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
gp_Pnt P = BRep_Tool::Pnt(V);
if ( SMDS_MeshNode * n = _father->GetMeshDS()->AddNode(P.X(), P.Y(), P.Z()) ) {
}
}
if ( event == MODIF_ALGO_STATE )
- CleanDependants();
+ cleanDependants();
return true;
}
SMESH_Gen *gen = _father->GetGen();
switch (event)
{
case MODIF_ALGO_STATE:
- algo = gen->GetAlgo((*_father), _subShape);
- if (algo && !algo->NeedDescretBoundary())
- CleanDependsOn(); // clean sub-meshes with event CLEAN
+ algo = GetAlgo();
+ if (algo && !algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
if ( _algoState == HYP_OK )
_computeState = READY_TO_COMPUTE;
break;
- case COMPUTE: // nothing to do
+ case COMPUTE: // nothing to do
+ case COMPUTE_SUBMESH:
+ break;
+ case COMPUTE_CANCELED: // nothing to do
break;
case CLEAN:
- CleanDependants();
- RemoveSubMeshElementsAndNodes();
+ cleanDependants();
+ removeSubMeshElementsAndNodes();
break;
- case SUBMESH_COMPUTED: // nothing to do
+ case SUBMESH_COMPUTED: // nothing to do
break;
case SUBMESH_RESTORED:
ComputeSubMeshStateEngine( SUBMESH_RESTORED );
break;
case MESH_ENTITY_REMOVED:
break;
+ case SUBMESH_LOADED:
+ loadDependentMeshes();
+ ComputeSubMeshStateEngine( SUBMESH_LOADED );
+ //break;
case CHECK_COMPUTE_STATE:
if ( IsMeshComputed() )
_computeState = COMPUTE_OK;
{
case MODIF_ALGO_STATE:
_computeState = NOT_READY;
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
if (algo)
{
- if (!algo->NeedDescretBoundary())
- CleanDependsOn(); // clean sub-meshes with event CLEAN
+ if (!algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
if ( _algoState == HYP_OK )
_computeState = READY_TO_COMPUTE;
}
break;
case COMPUTE:
+ case COMPUTE_SUBMESH:
{
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
ASSERT(algo);
ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
if (!ret)
{
MESSAGE("***** verify compute state *****");
_computeState = NOT_READY;
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
break;
}
+ TopoDS_Shape shape = _subShape;
+ algo->SubMeshesToCompute().assign( 1, this );
// check submeshes needed
if (_father->HasShapeToMesh() ) {
- bool subComputed = SubMeshesComputed();
- ret = ( algo->NeedDescretBoundary() ? subComputed :
+ 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 );
+ }
+ else {
+ subComputed = SubMeshesComputed();
+ }
+ ret = ( algo->NeedDiscreteBoundary() ? subComputed :
+ algo->SupportSubmeshes() ? !subFailed :
( !subComputed || _father->IsNotConformAllowed() ));
- if (!ret) {
+ if (!ret)
+ {
_computeState = FAILED_TO_COMPUTE;
- if ( !algo->NeedDescretBoundary() )
+ if ( !algo->NeedDiscreteBoundary() && !subFailed )
_computeError =
SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,
- "Unexpected computed submesh",algo);
- break;
+ "Unexpected computed sub-mesh",algo);
+ break; // goto exit
}
}
- // compute
-// CleanDependants(); for "UseExisting_*D" algos
-// RemoveSubMeshElementsAndNodes();
+ // Compute
+
+ // to restore cout that may be redirected by algo
+ std::streambuf* coutBuffer = std::cout.rdbuf();
+
+ //cleanDependants(); for "UseExisting_*D" algos
+ //removeSubMeshElementsAndNodes();
+ loadDependentMeshes();
ret = false;
_computeState = FAILED_TO_COMPUTE;
_computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
- TopoDS_Shape shape = _subShape;
try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
OCC_CATCH_SIGNALS;
-#endif
+
algo->InitComputeError();
+
MemoryReserve aMemoryReserve;
SMDS_Mesh::CheckMemory();
+ Kernel_Utils::Localizer loc;
if ( !_father->HasShapeToMesh() ) // no shape
{
SMESH_MesherHelper helper( *_father );
}
else
{
- if (!algo->OnlyUnaryInput()) {
- shape = GetCollection( gen, algo );
- }
ret = algo->Compute((*_father), shape);
}
- if ( !ret )
- _computeError = algo->GetComputeError();
+ // algo can set _computeError of submesh
+ _computeError = SMESH_ComputeError::Worst( _computeError, algo->GetComputeError() );
+ }
+ catch ( ::SMESH_ComputeError& comperr ) {
+ cout << " SMESH_ComputeError caught" << endl;
+ if ( !_computeError ) _computeError = SMESH_ComputeError::New();
+ *_computeError = comperr;
}
catch ( std::bad_alloc& exc ) {
- printf("std::bad_alloc thrown inside algo->Compute()\n");
+ MESSAGE("std::bad_alloc thrown inside algo->Compute()");
if ( _computeError ) {
_computeError->myName = COMPERR_MEMORY_PB;
//_computeError->myComment = exc.what();
throw exc;
}
catch ( Standard_OutOfMemory& exc ) {
- printf("Standard_OutOfMemory thrown inside algo->Compute()\n");
+ MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()");
if ( _computeError ) {
_computeError->myName = COMPERR_MEMORY_PB;
//_computeError->myComment = exc.what();
}
}
catch ( SALOME_Exception& S_ex ) {
+ const int skipSalomeShift = 7; /* to skip "Salome " of
+ "Salome Exception" prefix returned
+ by SALOME_Exception::what() */
if ( !_computeError ) _computeError = SMESH_ComputeError::New();
_computeError->myName = COMPERR_SLM_EXCEPTION;
- _computeError->myComment = S_ex.what();
+ _computeError->myComment = S_ex.what() + skipSalomeShift;
}
catch ( std::exception& exc ) {
if ( !_computeError ) _computeError = SMESH_ComputeError::New();
else
ret = false;
}
- if (ret && !_alwaysComputed) { // check if anything was built
- ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() ));
+ std::cout.rdbuf( coutBuffer ); // restore cout that could be redirected by algo
+
+ // check if an error reported on any sub-shape
+ bool isComputeErrorSet = !checkComputeError( algo, ret, shape );
+ if ( isComputeErrorSet )
+ ret = false;
+ // check if anything was built
+ TopExp_Explorer subS(shape, _subShape.ShapeType());
+ if (ret)
+ {
+ for (; ret && subS.More(); subS.Next())
+ if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() &&
+ ( _subShape.ShapeType() != TopAbs_EDGE ||
+ !algo->isDegenerated( TopoDS::Edge( subS.Current() ))))
+ ret = false;
}
- bool isComputeErrorSet = !CheckComputeError( algo, shape );
+ // Set _computeError
if (!ret && !isComputeErrorSet)
{
- // Set _computeError
- if ( !_computeError )
- _computeError = SMESH_ComputeError::New();
- if ( _computeError->IsOK() )
- _computeError->myName = COMPERR_ALGO_FAILED;
- _computeState = FAILED_TO_COMPUTE;
+ for (subS.ReInit(); subS.More(); subS.Next())
+ {
+ SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+ if ( !sm->IsMeshComputed() )
+ {
+ if ( !sm->_computeError )
+ sm->_computeError = SMESH_ComputeError::New();
+ if ( sm->_computeError->IsOK() )
+ sm->_computeError->myName = COMPERR_ALGO_FAILED;
+ sm->_computeState = FAILED_TO_COMPUTE;
+ sm->_computeError->myAlgo = algo;
+ }
+ }
}
- if (ret)
+ if (ret && _computeError && _computeError->myName != COMPERR_WARNING )
{
_computeError.reset();
}
- UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
+
+ // send event SUBMESH_COMPUTED
+ if ( ret ) {
+ if ( !algo->NeedDiscreteBoundary() )
+ // send SUBMESH_COMPUTED to dependants of all sub-meshes of shape
+ for (subS.ReInit(); subS.More(); subS.Next())
+ {
+ SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+ while ( smIt->more() ) {
+ sm = smIt->next();
+ if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
+ sm->updateDependantsState( SUBMESH_COMPUTED );
+ else
+ break;
+ }
+ }
+ else
+ updateDependantsState( SUBMESH_COMPUTED );
+ }
}
break;
+ case COMPUTE_CANCELED: // nothing to do
+ break;
case CLEAN:
- CleanDependants();
- RemoveSubMeshElementsAndNodes();
+ cleanDependants();
+ removeSubMeshElementsAndNodes();
_computeState = NOT_READY;
- algo = gen->GetAlgo((*_father), _subShape);
+ algo = GetAlgo();
if (algo)
{
ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
if (ret)
_computeState = READY_TO_COMPUTE;
else
- SetAlgoState(MISSING_HYP);
+ setAlgoState(MISSING_HYP);
}
break;
case SUBMESH_COMPUTED: // nothing to do
// happen after retrieval from a file
ComputeStateEngine( CHECK_COMPUTE_STATE );
ComputeSubMeshStateEngine( SUBMESH_RESTORED );
- algo = gen->GetAlgo(*_father, _subShape);
+ algo = GetAlgo();
if (algo) algo->SubmeshRestored( this );
break;
case MESH_ENTITY_REMOVED:
break;
+ case SUBMESH_LOADED:
+ loadDependentMeshes();
+ ComputeSubMeshStateEngine( SUBMESH_LOADED );
+ //break;
case CHECK_COMPUTE_STATE:
if ( IsMeshComputed() )
_computeState = COMPUTE_OK;
+ else if ( _computeError && _computeError->IsKO() )
+ _computeState = FAILED_TO_COMPUTE;
break;
default:
ASSERT(0);
{
case MODIF_ALGO_STATE:
ComputeStateEngine( CLEAN );
- algo = gen->GetAlgo((*_father), _subShape);
- if (algo && !algo->NeedDescretBoundary())
- CleanDependsOn(); // clean sub-meshes with event CLEAN
+ algo = GetAlgo();
+ if (algo && !algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
break;
case COMPUTE: // nothing to do
break;
+ case COMPUTE_CANCELED: // nothing to do
+ break;
case CLEAN:
- CleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN
- RemoveSubMeshElementsAndNodes();
+ cleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN
+ removeSubMeshElementsAndNodes();
_computeState = NOT_READY;
if ( _algoState == HYP_OK )
_computeState = READY_TO_COMPUTE;
case SUBMESH_RESTORED:
ComputeStateEngine( CHECK_COMPUTE_STATE );
ComputeSubMeshStateEngine( SUBMESH_RESTORED );
- algo = gen->GetAlgo(*_father, _subShape);
+ algo = GetAlgo();
if (algo) algo->SubmeshRestored( this );
break;
case MESH_ENTITY_REMOVED:
- UpdateDependantsState( CHECK_COMPUTE_STATE );
- ComputeStateEngine( CHECK_COMPUTE_STATE );
+ updateDependantsState ( CHECK_COMPUTE_STATE );
+ ComputeStateEngine ( CHECK_COMPUTE_STATE );
ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
break;
case CHECK_COMPUTE_STATE:
- if ( !IsMeshComputed() )
+ if ( !IsMeshComputed() ) {
if (_algoState == HYP_OK)
_computeState = READY_TO_COMPUTE;
else
_computeState = NOT_READY;
+ }
+ break;
+ case SUBMESH_LOADED:
+ // already treated event, thanks to which _computeState == COMPUTE_OK
break;
default:
ASSERT(0);
switch (event)
{
case MODIF_ALGO_STATE:
+ if ( !IsEmpty() )
+ ComputeStateEngine( CLEAN );
+ algo = GetAlgo();
+ if (algo && !algo->NeedDiscreteBoundary())
+ cleanDependsOn( algo ); // clean sub-meshes with event CLEAN
if (_algoState == HYP_OK)
_computeState = READY_TO_COMPUTE;
else
_computeState = NOT_READY;
break;
- case COMPUTE: // nothing to do
+ case COMPUTE: // nothing to do
+ case COMPUTE_SUBMESH:
+ break;
+ case COMPUTE_CANCELED:
+ {
+ algo = GetAlgo();
+ algo->CancelCompute();
+ }
break;
case CLEAN:
- CleanDependants(); // submeshes dependent on me should be cleaned as well
- RemoveSubMeshElementsAndNodes();
+ cleanDependants(); // submeshes dependent on me should be cleaned as well
+ 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 );
else
_computeState = NOT_READY;
break;
+ // case SUBMESH_LOADED:
+ // break;
default:
ASSERT(0);
break;
break;
}
- NotifyListenersOnEvent( event, COMPUTE_EVENT );
+ notifyListenersOnEvent( event, COMPUTE_EVENT );
return ret;
}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
+{
+ _computeError.reset();
+
+ bool ret = true;
+
+ if (_subShape.ShapeType() == TopAbs_VERTEX) {
+ vector<int> aVec(SMDSEntity_Last,0);
+ aVec[SMDSEntity_Node] = 1;
+ aResMap.insert(make_pair(this,aVec));
+ return ret;
+ }
+
+ //SMESH_Gen *gen = _father->GetGen();
+ SMESH_Algo *algo = 0;
+ SMESH_Hypothesis::Hypothesis_Status hyp_status;
+
+ algo = GetAlgo();
+ if( algo && !aResMap.count( this ))
+ {
+ ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+ if (!ret) return false;
+
+ if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary() )
+ {
+ // check submeshes needed
+ bool subMeshEvaluated = true;
+ int dimToCheck = SMESH_Gen::GetShapeDim( _subShape ) - 1;
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,/*complexShapeFirst=*/true);
+ while ( smIt->more() && subMeshEvaluated )
+ {
+ SMESH_subMesh* sm = smIt->next();
+ int dim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
+ if (dim < dimToCheck) break; // the rest subMeshes are all of less dimension
+ const vector<int> & nbs = aResMap[ sm ];
+ subMeshEvaluated = (std::accumulate( nbs.begin(), nbs.end(), 0 ) > 0 );
+ }
+ if ( !subMeshEvaluated )
+ return false;
+ }
+ _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
+
+ 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)));
+ }
+
+ return ret;
+}
+
+
//=======================================================================
/*!
* \brief Update compute_state by _computeError and send proper events to
*/
//=======================================================================
-bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape)
+bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo,
+ const bool theComputeOK,
+ const TopoDS_Shape& theShape)
{
bool noErrors = true;
if ( !theShape.IsNull() )
{
// Check state of submeshes
- if ( !theAlgo->NeedDescretBoundary())
+ if ( !theAlgo->NeedDiscreteBoundary())
{
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
while ( smIt->more() )
- if ( !smIt->next()->CheckComputeError( theAlgo ))
+ if ( !smIt->next()->checkComputeError( theAlgo, theComputeOK ))
noErrors = false;
}
for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) {
SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() );
if ( sm != this ) {
- if ( !sm->CheckComputeError( theAlgo ))
+ if ( !sm->checkComputeError( theAlgo, theComputeOK, sm->GetSubShape() ))
noErrors = false;
- UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
+ updateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
}
}
}
}
{
- // Check my state
+
+ // Set my _computeState
+
if ( !_computeError || _computeError->IsOK() )
{
- _computeState = COMPUTE_OK;
+ // no error description is set to this sub-mesh, check if any mesh is computed
+ _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE;
+ if ( _computeState != COMPUTE_OK )
+ {
+ if ( _subShape.ShapeType() == TopAbs_EDGE &&
+ SMESH_Algo::isDegenerated( TopoDS::Edge( _subShape )) )
+ _computeState = COMPUTE_OK;
+ else if ( theComputeOK )
+ _computeError = SMESH_ComputeError::New(COMPERR_NO_MESH_ON_SHAPE,"",theAlgo);
+ }
}
- else
+
+ if ( _computeError && !_computeError->IsOK() )
{
if ( !_computeError->myAlgo )
_computeError->myAlgo = theAlgo;
// Show error
SMESH_Comment text;
- text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error ";
+ text << theAlgo->GetName() << " failed on sub-shape #" << _Id << " with error ";
if (_computeError->IsCommon() )
text << _computeError->CommonName();
else
if ( _computeError->myComment.size() > 0 )
text << " \"" << _computeError->myComment << "\"";
-#ifdef _DEBUG_
- cout << text << endl;
- // Show vertices location of a failed shape
- TopTools_IndexedMapOfShape vMap;
- TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
- cout << "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") << endl;
- for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
- gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
- cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " ";
- cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
- }
-#else
INFOS( text );
-#endif
- _computeState = FAILED_TO_COMPUTE;
- noErrors = false;
- }
- }
- return noErrors;
-}
-
-//=======================================================================
-//function : ApplyToCollection
-//purpose : Apply theAlgo to all subshapes in theCollection
-//=======================================================================
-
-bool SMESH_subMesh::ApplyToCollection (SMESH_Algo* theAlgo,
- const TopoDS_Shape& theCollection)
-{
- MESSAGE("SMESH_subMesh::ApplyToCollection");
- ASSERT ( !theAlgo->NeedDescretBoundary() );
-
- if ( _computeError )
- _computeError->myName = COMPERR_OK;
- bool ok = theAlgo->Compute( *_father, theCollection );
+ _computeState = _computeError->IsKO() ? FAILED_TO_COMPUTE : COMPUTE_OK;
- // set _computeState of subshapes
- TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
- for ( ; anExplorer.More(); anExplorer.Next() )
- {
- if ( SMESH_subMesh* subMesh = _father->GetSubMeshContaining( anExplorer.Current() ))
- {
- bool localOK = subMesh->CheckComputeError( theAlgo );
- if ( !ok && localOK && !subMesh->IsMeshComputed() )
- {
- subMesh->_computeError = theAlgo->GetComputeError();
- if ( subMesh->_computeError->IsOK() )
- _computeError = SMESH_ComputeError::New(COMPERR_ALGO_FAILED);
- localOK = CheckComputeError( theAlgo );
- }
- if ( localOK )
- subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
- subMesh->UpdateSubMeshState( localOK ? COMPUTE_OK : FAILED_TO_COMPUTE );
+ noErrors = false;
}
}
-
- return true;
+ return noErrors;
}
-
//=======================================================================
-//function : UpdateSubMeshState
+//function : updateSubMeshState
//purpose :
//=======================================================================
-void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
+void SMESH_subMesh::updateSubMeshState(const compute_state theState)
{
SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
while ( smIt->more() )
//purpose :
//=======================================================================
-void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
+void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf)
{
- SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
+ SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(includeSelf,false);
while ( smIt->more() )
smIt->next()->ComputeStateEngine(event);
}
//=======================================================================
-//function : UpdateDependantsState
+//function : updateDependantsState
//purpose :
//=======================================================================
-void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
+void SMESH_subMesh::updateDependantsState(const compute_event theEvent)
{
- //MESSAGE("SMESH_subMesh::UpdateDependantsState");
- TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
- for (; it.More(); it.Next())
+ const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+ for ( size_t iA = 0; iA < ancestors.size(); ++iA )
{
- const TopoDS_Shape& ancestor = it.Value();
- SMESH_subMesh *aSubMesh =
- _father->GetSubMeshContaining(ancestor);
- if (aSubMesh)
- aSubMesh->ComputeStateEngine( theEvent );
+ ancestors[ iA ]->ComputeStateEngine( theEvent );
}
}
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : cleanDependants
+//purpose :
+//=======================================================================
-void SMESH_subMesh::CleanDependants()
+void SMESH_subMesh::cleanDependants()
{
int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
- TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
- for (; it.More(); it.Next())
+ const std::vector< SMESH_subMesh * > & ancestors = GetAncestors();
+ for ( size_t iA = 0; iA < ancestors.size(); ++iA )
{
- const TopoDS_Shape& ancestor = it.Value();
- if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
+ const TopoDS_Shape& ancestor = ancestors[ iA ]->GetSubShape();
+ 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);
- }
+ if ( ancestor.ShapeType() >= TopAbs_SOLID &&
+ !ancestors[ iA ]->IsEmpty() ) // prevent infinite CLEAN via event lesteners
+ ancestors[ iA ]->ComputeStateEngine(CLEAN);
}
}
}
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : removeSubMeshElementsAndNodes
+//purpose :
+//=======================================================================
-void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
+void SMESH_subMesh::removeSubMeshElementsAndNodes()
{
- //SCRUTE(_subShape.ShapeType());
-
cleanSubMesh( this );
// algo may bind a submesh not to _subShape, eg 3D algo
}
//=======================================================================
-//function : GetCollection
+//function : getCollection
//purpose : return a shape containing all sub-shapes of the MainShape that can be
// meshed at once along with _subShape
//=======================================================================
-TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
+TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
+ SMESH_Algo* theAlgo,
+ bool & theSubComputed,
+ bool & theSubFailed,
+ std::vector<SMESH_subMesh*>& theSubs)
{
- MESSAGE("SMESH_subMesh::GetCollection");
+ theSubComputed = SubMeshesComputed( & theSubFailed );
TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
if ( mainShape.IsSame( _subShape ))
return _subShape;
- const bool ignoreAuxiliaryHyps = false;
+ const bool skipAuxHyps = false;
list<const SMESHDS_Hypothesis*> aUsedHyp =
- theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
+ theAlgo->GetUsedHypothesis( *_father, _subShape, skipAuxHyps ); // copy
// put in a compound all shapes with the same hypothesis assigned
- // and a good ComputState
+ // and a good ComputeState
TopoDS_Compound aCompound;
BRep_Builder aBuilder;
aBuilder.MakeCompound( aCompound );
- TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
- for ( ; anExplorer.More(); anExplorer.Next() )
+ theSubs.clear();
+
+ SMESH_subMeshIteratorPtr smIt = _father->GetSubMesh( mainShape )->getDependsOnIterator(false);
+ while ( smIt->more() )
{
- const TopoDS_Shape& S = anExplorer.Current();
- SMESH_subMesh* subMesh = _father->GetSubMesh( S );
+ SMESH_subMesh* subMesh = smIt->next();
+ const TopoDS_Shape& S = subMesh->_subShape;
+ if ( S.ShapeType() != this->_subShape.ShapeType() )
+ continue;
+ theSubs.push_back( subMesh );
if ( subMesh == this )
{
aBuilder.Add( aCompound, S );
}
else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
{
- SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
- if (anAlgo == theAlgo &&
- anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
+ SMESH_Algo* anAlgo = subMesh->GetAlgo();
+ if (( anAlgo->IsSameName( *theAlgo )) && // same algo
+ ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == aUsedHyp )) // same hyps
+ {
aBuilder.Add( aCompound, S );
+ if ( !subMesh->SubMeshesComputed() )
+ theSubComputed = false;
+ }
}
}
}
//=======================================================================
-//function : GetSimilarAttached
+//function : getSimilarAttached
//purpose : return a hypothesis attached to theShape.
// If theHyp is provided, similar but not same hypotheses
// is returned; else only applicable ones having theHypType
// is returned
//=======================================================================
-const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape& theShape,
+const SMESH_Hypothesis* SMESH_subMesh::getSimilarAttached(const TopoDS_Shape& theShape,
const SMESH_Hypothesis * theHyp,
const int theHypType)
{
MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
// is there local hypothesis on me?
- if ( GetSimilarAttached( _subShape, 0, theHypType ) )
+ if ( getSimilarAttached( _subShape, 0, theHypType ) )
return SMESH_Hypothesis::HYP_OK;
for (; it.More(); it.Next())
{
const TopoDS_Shape& ancestor = it.Value();
- const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
+ const SMESH_Hypothesis* hyp = getSimilarAttached( ancestor, 0, theHypType );
if ( hyp )
{
if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
return SMESH_Hypothesis::HYP_OK;
}
+//================================================================================
+/*!
+ * \brief Constructor of OwnListenerData
+ */
+//================================================================================
+
+SMESH_subMesh::OwnListenerData::OwnListenerData( SMESH_subMesh* sm, EventListener* el):
+ mySubMesh( sm ),
+ myMeshID( sm ? sm->GetFather()->GetId() : -1 ),
+ mySubMeshID( sm ? sm->GetId() : -1 ),
+ myListener( el )
+{
+}
+
//================================================================================
/*!
* \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
SMESH_subMesh* where)
{
if ( listener && where ) {
- where->SetEventListener( listener, data );
- myOwnListeners.push_back( make_pair( where, listener ));
+ where->setEventListener( listener, data );
+ _ownListeners.push_back( OwnListenerData( where, listener ));
}
}
*/
//================================================================================
-void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* data)
+void SMESH_subMesh::setEventListener(EventListener* listener,
+ EventListenerData* data)
{
map< EventListener*, EventListenerData* >::iterator l_d =
- myEventListeners.find( listener );
- if ( l_d != myEventListeners.end() ) {
+ _eventListeners.find( listener );
+ if ( l_d != _eventListeners.end() ) {
EventListenerData* curData = l_d->second;
if ( curData && curData != data && curData->IsDeletable() )
delete curData;
l_d->second = data;
}
- else
- myEventListeners.insert( make_pair( listener, data ));
+ else
+ {
+ for ( l_d = _eventListeners.begin(); l_d != _eventListeners.end(); ++l_d )
+ if ( listener->GetName() == l_d->first->GetName() )
+ {
+ EventListenerData* curData = l_d->second;
+ if ( curData && curData != data && curData->IsDeletable() )
+ delete curData;
+ if ( l_d->first != listener && l_d->first->IsDeletable() )
+ delete l_d->first;
+ _eventListeners.erase( l_d );
+ break;
+ }
+ _eventListeners.insert( make_pair( listener, data ));
+ }
}
//================================================================================
/*!
* \brief Return an event listener data
* \param listener - the listener whose data is
+ * \param myOwn - if \c true, returns a listener set by this sub-mesh,
+ * else returns a listener listening to events of this sub-mesh
+ * \retval EventListenerData* - found data, maybe NULL
+ */
+//================================================================================
+
+EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener,
+ const bool myOwn) const
+{
+ if ( myOwn )
+ {
+ list< OwnListenerData >::const_iterator d;
+ for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
+ {
+ if ( d->myListener == listener && _father->MeshExists( d->myMeshID ))
+ return d->mySubMesh->GetEventListenerData( listener, !myOwn );
+ }
+ }
+ else
+ {
+ map< EventListener*, EventListenerData* >::const_iterator l_d =
+ _eventListeners.find( listener );
+ if ( l_d != _eventListeners.end() )
+ return l_d->second;
+ }
+ return 0;
+}
+
+//================================================================================
+/*!
+ * \brief Return an event listener data
+ * \param listenerName - the listener name
+ * \param myOwn - if \c true, returns a listener set by this sub-mesh,
+ * else returns a listener listening to events of this sub-mesh
* \retval EventListenerData* - found data, maybe NULL
*/
//================================================================================
-EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const
+EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName,
+ const bool myOwn) const
{
- map< EventListener*, EventListenerData* >::const_iterator l_d =
- myEventListeners.find( listener );
- if ( l_d != myEventListeners.end() )
- return l_d->second;
+ if ( myOwn )
+ {
+ list< OwnListenerData >::const_iterator d;
+ for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
+ {
+ if ( _father->MeshExists( d->myMeshID ) && listenerName == d->myListener->GetName())
+ return d->mySubMesh->GetEventListenerData( listenerName, !myOwn );
+ }
+ }
+ else
+ {
+ map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin();
+ for ( ; l_d != _eventListeners.end(); ++l_d )
+ if ( listenerName == l_d->first->GetName() )
+ 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,
+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 );
+ list< pair< EventListener*, EventListenerData* > > eventListeners( _eventListeners.begin(),
+ _eventListeners.end());
+ list< pair< EventListener*, EventListenerData* > >::iterator l_d = eventListeners.begin();
+ for ( ; l_d != eventListeners.end(); ++l_d )
+ {
+ std::pair< EventListener*, EventListenerData* > li_da = *l_d;
+ if ( !_eventListeners.count( li_da.first )) continue;
+
+ if ( li_da.first->myBusySM.insert( this ).second )
+ {
+ const bool isDeletable = li_da.first->IsDeletable();
+
+ li_da.first->ProcessEvent( event, eventType, this, li_da.second, hyp );
+
+ if ( !isDeletable || _eventListeners.count( li_da.first ))
+ li_da.first->myBusySM.erase( this ); // a listener is hopefully not dead
+ }
+ }
}
//================================================================================
void SMESH_subMesh::DeleteEventListener(EventListener* listener)
{
map< EventListener*, EventListenerData* >::iterator l_d =
- myEventListeners.find( listener );
- if ( l_d != myEventListeners.end() ) {
- if ( l_d->first && l_d->first->IsDeletable() ) delete l_d->first;
- if ( l_d->second && l_d->second->IsDeletable() ) delete l_d->second;
- myEventListeners.erase( l_d );
+ _eventListeners.find( listener );
+ if ( l_d != _eventListeners.end() && l_d->first )
+ {
+ if ( l_d->second && l_d->second->IsDeletable() )
+ {
+ delete l_d->second;
+ }
+ l_d->first->myBusySM.erase( this );
+ if ( l_d->first->IsDeletable() )
+ {
+ l_d->first->BeforeDelete( this, l_d->second );
+ delete l_d->first;
+ }
+ _eventListeners.erase( l_d );
}
}
*/
//================================================================================
-void SMESH_subMesh::DeleteOwnListeners()
+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();
+ list< OwnListenerData >::iterator d;
+ for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
+ {
+ SMESH_Mesh* mesh = _father->FindMesh( d->myMeshID );
+ if ( !mesh || !mesh->GetSubMeshContaining( d->mySubMeshID ))
+ continue;
+ d->mySubMesh->DeleteEventListener( d->myListener );
+ }
+ _ownListeners.clear();
+}
+
+//=======================================================================
+//function : loadDependentMeshes
+//purpose : loads dependent meshes on SUBMESH_LOADED event
+//=======================================================================
+
+void SMESH_subMesh::loadDependentMeshes()
+{
+ list< OwnListenerData >::iterator d;
+ for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
+ if ( _father != d->mySubMesh->_father )
+ d->mySubMesh->_father->Load();
+
+ // map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin();
+ // for ( ; l_d != _eventListeners.end(); ++l_d )
+ // if ( l_d->second )
+ // {
+ // const list<SMESH_subMesh*>& smList = l_d->second->mySubMeshes;
+ // list<SMESH_subMesh*>::const_iterator sm = smList.begin();
+ // for ( ; sm != smList.end(); ++sm )
+ // if ( _father != (*sm)->_father )
+ // (*sm)->_father->Load();
+ // }
}
//================================================================================
(*smIt)->ComputeStateEngine( event );
break;
case SMESH_subMesh::COMPUTE:
+ case SMESH_subMesh::COMPUTE_SUBMESH:
if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK )
for ( ; smIt != smEnd; ++ smIt)
(*smIt)->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
SMESH_subMesh* prepend,
SMESH_subMesh* append): myIt(subIt),myAppend(append)
{
- myCur = prepend ? prepend : myIt->more() ? myIt->next() : 0;
+ myCur = prepend ? prepend : myIt->more() ? myIt->next() : append;
+ if ( myCur == append ) append = 0;
}
/// Return true if and only if there are other object in this iterator
virtual bool more()
//================================================================================
SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeSelf,
- const bool reverse)
+ const bool reverse) const
{
+ SMESH_subMesh *me = (SMESH_subMesh*) this;
SMESH_subMesh *prepend=0, *append=0;
if ( includeSelf ) {
- if ( reverse ) prepend = this;
- else append = this;
+ if ( reverse ) prepend = me;
+ else append = me;
}
typedef map < int, SMESH_subMesh * > TMap;
if ( reverse )
{
return SMESH_subMeshIteratorPtr
- ( new _Iterator( new SMDS_mapReverseIterator<TMap>( DependsOn() ), prepend, append ));
+ ( new _Iterator( new SMDS_mapReverseIterator<TMap>( me->DependsOn() ), prepend, append ));
}
{
return SMESH_subMeshIteratorPtr
- ( new _Iterator( new SMDS_mapIterator<TMap>( DependsOn() ), prepend, append ));
+ ( new _Iterator( new SMDS_mapIterator<TMap>( me->DependsOn() ), prepend, append ));
}
}
+
+//================================================================================
+/*!
+ * \brief Returns ancestor sub-meshes. Finds them if not yet found.
+ */
+//================================================================================
+
+const std::vector< SMESH_subMesh * > & SMESH_subMesh::GetAncestors() const
+{
+ if ( _ancestors.empty() &&
+ !_subShape.IsSame( _father->GetShapeToMesh() ))
+ {
+ const TopTools_ListOfShape& ancShapes = _father->GetAncestors( _subShape );
+
+ SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this );
+ me->_ancestors.reserve( ancShapes.Extent() );
+
+ 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() ))
+ me->_ancestors.push_back( sm );
+ }
+
+ return _ancestors;
+}
+
+//================================================================================
+/*!
+ * \brief Clears the vector of ancestor sub-meshes
+ */
+//================================================================================
+
+void SMESH_subMesh::ClearAncestors()
+{
+ _ancestors.clear();
+}
+
+//================================================================================
+/*!
+ * \brief Find common submeshes (based on shared sub-shapes with other
+ * \param theOther submesh to check
+ * \param theSetOfCommon set of common submesh
+ */
+//================================================================================
+
+bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
+ std::set<const SMESH_subMesh*>& theSetOfCommon ) const
+{
+ int 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++ )
+ if ( theOther->_mapDepend.find((*mapIt).first) != otherEnd )
+ theSetOfCommon.insert( (*mapIt).second );
+ return oldNb < theSetOfCommon.size();
+}