1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : SMESH_subMesh.cxx
25 // Author : Paul RASCLE, EDF
29 #include "SMESH_subMesh.hxx"
31 #include "SMESH_subMeshEventListener.hxx"
32 #include "SMESH_Gen.hxx"
33 #include "SMESH_Mesh.hxx"
34 #include "SMESH_Hypothesis.hxx"
35 #include "SMESH_Algo.hxx"
36 #include "SMESH_HypoFilter.hxx"
37 #include "SMESH_MesherHelper.hxx"
39 #include "utilities.h"
42 #include <BRep_Builder.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <TopTools_MapOfShape.hxx>
47 #include <TopTools_ListOfShape.hxx>
48 #include <TopTools_ListIteratorOfListOfShape.hxx>
49 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
53 #include <BRep_Tool.hxx>
55 #include <TopTools_IndexedMapOfShape.hxx>
58 #include <Standard_Failure.hxx>
59 #include <Standard_ErrorHandler.hxx>
63 //=============================================================================
65 * default constructor:
67 //=============================================================================
69 SMESH_subMesh::SMESH_subMesh(int Id,
71 SMESHDS_Mesh * meshDS,
72 const TopoDS_Shape & aSubShape)
74 _subShape = aSubShape;
76 _subMeshDS = meshDS->MeshElements(_subShape); // may be null ...
79 _dependenceAnalysed = _alwaysComputed = false;
81 if (_subShape.ShapeType() == TopAbs_VERTEX)
84 _computeState = READY_TO_COMPUTE;
89 _computeState = NOT_READY;
93 //=============================================================================
97 //=============================================================================
99 SMESH_subMesh::~SMESH_subMesh()
101 MESSAGE("SMESH_subMesh::~SMESH_subMesh");
105 //=============================================================================
109 //=============================================================================
111 int SMESH_subMesh::GetId() const
113 //MESSAGE("SMESH_subMesh::GetId");
117 //=============================================================================
121 //=============================================================================
123 SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
125 // submesh appears in DS only when a mesher set nodes and elements on a shape
126 return _subMeshDS ? _subMeshDS : _subMeshDS = _meshDS->MeshElements(_subShape); // may be null
129 //=============================================================================
133 //=============================================================================
135 SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
137 if ( !GetSubMeshDS() )
138 _meshDS->NewSubMesh( _meshDS->ShapeToIndex( _subShape ) );
140 return GetSubMeshDS();
143 //=============================================================================
147 //=============================================================================
149 SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
151 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
152 SMESH_subMesh *firstToCompute = 0;
154 map < int, SMESH_subMesh * >::const_iterator itsub;
155 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
157 SMESH_subMesh *sm = (*itsub).second;
158 bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
167 return firstToCompute; // a subMesh of this
169 if (_computeState == READY_TO_COMPUTE)
173 return 0; // nothing to compute
176 //================================================================================
178 * \brief Allow algo->Compute() if a subshape of lower dim is meshed but
179 * none mesh entity is bound to it (PAL13615, 2nd part)
181 //================================================================================
183 void SMESH_subMesh::SetIsAlwaysComputed(bool isAlCo)
185 _alwaysComputed = isAlCo;
186 if ( _alwaysComputed )
187 _computeState = COMPUTE_OK;
189 ComputeStateEngine( CHECK_COMPUTE_STATE );
192 //=======================================================================
193 //function : IsMeshComputed
194 //purpose : check if _subMeshDS contains mesh elements
195 //=======================================================================
197 bool SMESH_subMesh::IsMeshComputed() const
199 if ( _alwaysComputed )
201 // algo may bind a submesh not to _subShape, eg 3D algo
202 // sets nodes on SHELL while _subShape may be SOLID
204 int dim = SMESH_Gen::GetShapeDim( _subShape );
205 int type = _subShape.ShapeType();
206 for ( ; type <= TopAbs_VERTEX; type++) {
207 if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
209 TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
210 for ( ; exp.More(); exp.Next() )
212 SMESHDS_SubMesh * smDS = _meshDS->MeshElements( exp.Current() );
213 if ( smDS && ( smDS->NbElements() || smDS->NbNodes()))
224 //=============================================================================
228 //=============================================================================
230 bool SMESH_subMesh::SubMeshesComputed()
232 //MESSAGE("SMESH_subMesh::SubMeshesComputed");
233 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
235 int myDim = SMESH_Gen::GetShapeDim( _subShape );
236 int dimToCheck = myDim - 1;
237 bool subMeshesComputed = true;
238 // check subMeshes with upper dimension => reverse iteration
239 map < int, SMESH_subMesh * >::const_reverse_iterator itsub;
240 for (itsub = subMeshes.rbegin(); itsub != subMeshes.rend(); itsub++)
242 SMESH_subMesh *sm = (*itsub).second;
243 if ( sm->_alwaysComputed )
245 const TopoDS_Shape & ss = sm->GetSubShape();
246 // MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense
247 // in checking of existence of edges if the algo needs only faces. Moreover,
248 // degenerated edges may have no submesh, as after computing NETGEN_2D.
249 int dim = SMESH_Gen::GetShapeDim( ss );
250 if (dim < dimToCheck)
251 break; // the rest subMeshes are all of less dimension
252 SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
253 bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
254 (ds && ( ds->NbNodes() || ds->NbElements() )));
257 int type = ss.ShapeType();
259 subMeshesComputed = false;
263 case TopAbs_COMPOUND:
265 MESSAGE("The not computed sub mesh is a COMPOUND");
268 case TopAbs_COMPSOLID:
270 MESSAGE("The not computed sub mesh is a COMPSOLID");
275 MESSAGE("The not computed sub mesh is a SHEL");
280 MESSAGE("The not computed sub mesh is a WIRE");
285 MESSAGE("The not computed sub mesh is a SOLID");
290 MESSAGE("The not computed sub mesh is a FACE");
295 MESSAGE("The not computed sub mesh is a EDGE");
300 MESSAGE("The not computed sub mesh is of unknown type");
308 return subMeshesComputed;
311 //=============================================================================
315 //=============================================================================
317 bool SMESH_subMesh::SubMeshesReady()
319 MESSAGE("SMESH_subMesh::SubMeshesReady");
320 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
322 bool subMeshesReady = true;
323 map < int, SMESH_subMesh * >::const_iterator itsub;
324 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
326 SMESH_subMesh *sm = (*itsub).second;
327 bool computeOk = ((sm->GetComputeState() == COMPUTE_OK)
328 || (sm->GetComputeState() == READY_TO_COMPUTE));
331 subMeshesReady = false;
336 return subMeshesReady;
339 //=============================================================================
341 * Construct dependence on first level subMeshes. complex shapes (compsolid,
342 * shell, wire) are not analysed the same way as simple shapes (solid, face,
344 * For collection shapes (compsolid, shell, wire) prepare a list of submeshes
345 * with possible multiples occurences. Multiples occurences corresponds to
346 * internal frontiers within shapes of the collection and must not be keeped.
347 * See FinalizeDependence.
349 //=============================================================================
351 const map < int, SMESH_subMesh * >&SMESH_subMesh::DependsOn()
353 if (_dependenceAnalysed)
356 //MESSAGE("SMESH_subMesh::DependsOn");
358 int type = _subShape.ShapeType();
362 case TopAbs_COMPOUND:
364 //MESSAGE("compound");
365 for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
368 InsertDependence(exp.Current());
370 for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More();
373 InsertDependence(exp.Current()); //only shell not in solid
375 for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();
378 InsertDependence(exp.Current());
380 for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();
383 InsertDependence(exp.Current());
387 case TopAbs_COMPSOLID:
389 //MESSAGE("compsolid");
390 for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
393 InsertDependence(exp.Current());
400 for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
403 InsertDependence(exp.Current());
410 for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
413 InsertDependence(exp.Current());
420 for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
423 InsertDependence(exp.Current());
430 for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
433 InsertDependence(exp.Current());
440 for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More();
443 InsertDependence(exp.Current());
456 _dependenceAnalysed = true;
460 //=============================================================================
462 * For simple Shapes (solid, face, edge): add subMesh into dependence list.
464 //=============================================================================
466 void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
468 //MESSAGE("SMESH_subMesh::InsertDependence");
469 SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
470 int type = aSubShape.ShapeType();
471 int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid
472 int cle = aSubMesh->GetId();
473 cle += 10000000 * ordType; // sort map by ordType then index
474 if ( _mapDepend.find( cle ) == _mapDepend.end())
476 _mapDepend[cle] = aSubMesh;
477 const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
478 _mapDepend.insert( subMap.begin(), subMap.end() );
482 //=============================================================================
486 //=============================================================================
488 const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
490 //MESSAGE("SMESH_subMesh::GetSubShape");
495 //=======================================================================
496 //function : CanAddHypothesis
497 //purpose : return true if theHypothesis can be attached to me:
498 // its dimention is checked
499 //=======================================================================
501 bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
503 int aHypDim = theHypothesis->GetDim();
504 int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
505 if ( aHypDim <= aShapeDim )
507 // if ( aHypDim < aShapeDim )
508 // return ( _father->IsMainShape( _subShape ));
513 //=======================================================================
514 //function : IsApplicableHypotesis
516 //=======================================================================
518 bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
519 const TopAbs_ShapeEnum theShapeType)
521 if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
523 return ( theHypothesis->GetShapeType() & (1<< theShapeType));
526 switch ( theShapeType ) {
531 return SMESH_Gen::GetShapeDim( theShapeType ) == theHypothesis->GetDim();
534 // Special case for algorithms, building 2D mesh on a whole shell.
535 // Before this fix there was a problem after restoring from study,
536 // because in that case algorithm is assigned before hypothesis
537 // (on shell in problem case) and hypothesis is checked on faces
538 // (because it is 2D), where we have NO_ALGO state.
539 // Now 2D hypothesis is also applicable to shells.
540 return (theHypothesis->GetDim() == 2 || theHypothesis->GetDim() == 3);
543 // case TopAbs_COMPSOLID:
544 // case TopAbs_COMPOUND:
550 //=============================================================================
554 //=============================================================================
556 SMESH_Hypothesis::Hypothesis_Status
557 SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
559 // MESSAGE("SMESH_subMesh::AlgoStateEngine");
560 //SCRUTE(_algoState);
563 // **** les retour des evenement shape sont significatifs
564 // (add ou remove fait ou non)
565 // le retour des evenement father n'indiquent pas que add ou remove fait
567 SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
569 SMESH_Gen* gen =_father->GetGen();
570 SMESH_Algo* algo = 0;
572 if (_subShape.ShapeType() == TopAbs_VERTEX )
574 if ( anHyp->GetDim() != 0) {
575 if (event == ADD_HYP || event == ADD_ALGO)
576 return SMESH_Hypothesis::HYP_BAD_DIM;
578 return SMESH_Hypothesis::HYP_OK;
581 else if ( _algoState == HYP_OK ) { // update default _algoState
582 _algoState = NO_ALGO;
583 algo = gen->GetAlgo(*_father, _subShape);
585 _algoState = MISSING_HYP;
586 if ( algo->CheckHypothesis(*_father,_subShape, aux_ret))
592 int oldAlgoState = _algoState;
593 bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE
595 bool isApplicableHyp = IsApplicableHypotesis( anHyp );
597 if (event == ADD_ALGO || event == ADD_FATHER_ALGO)
599 // -------------------------------------------
600 // check if a shape needed by algo is present
601 // -------------------------------------------
602 algo = static_cast< SMESH_Algo* >( anHyp );
603 if ( !_father->HasShapeToMesh() && algo->NeedShape() )
604 return SMESH_Hypothesis::HYP_BAD_GEOMETRY;
605 // ----------------------
606 // check mesh conformity
607 // ----------------------
608 if (isApplicableHyp && !_father->IsNotConformAllowed() && !IsConform( algo ))
609 return SMESH_Hypothesis::HYP_NOTCONFORM;
612 // ----------------------------------
613 // add a hypothesis to DS if possible
614 // ----------------------------------
615 if (event == ADD_HYP || event == ADD_ALGO)
617 if ( ! CanAddHypothesis( anHyp )) // check dimension
618 return SMESH_Hypothesis::HYP_BAD_DIM;
620 if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
621 return SMESH_Hypothesis::HYP_ALREADY_EXIST;
623 if ( !_meshDS->AddHypothesis(_subShape, anHyp))
624 return SMESH_Hypothesis::HYP_ALREADY_EXIST;
626 // Serve Propagation of 1D hypothesis
627 // NOTE: it is possible to re-implement Propagation using EventListener
628 if (event == ADD_HYP) {
629 bool isPropagationOk = true;
630 bool isPropagationHyp = ( strcmp( "Propagation", anHyp->GetName() ) == 0 );
632 if ( isPropagationHyp ) {
633 TopExp_Explorer exp (_subShape, TopAbs_EDGE);
634 TopTools_MapOfShape aMap;
635 for (; exp.More(); exp.Next()) {
636 if (aMap.Add(exp.Current())) {
637 if (!_father->BuildPropagationChain(exp.Current())) {
638 isPropagationOk = false;
643 else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated
644 TopExp_Explorer exp (_subShape, TopAbs_EDGE);
645 TopTools_MapOfShape aMap;
646 for (; exp.More(); exp.Next()) {
647 if (aMap.Add(exp.Current())) {
648 TopoDS_Shape aMainEdge;
649 if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) {
650 isPropagationOk = _father->RebuildPropagationChains();
651 } else if (_father->IsPropagationHypothesis(exp.Current())) {
652 isPropagationOk = _father->BuildPropagationChain(exp.Current());
660 if ( isPropagationOk ) {
661 if ( isPropagationHyp )
662 return ret; // nothing more to do for "Propagation" hypothesis
664 else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
665 ret = SMESH_Hypothesis::HYP_CONCURENT;
667 } // Serve Propagation of 1D hypothesis
670 // --------------------------
671 // remove a hypothesis from DS
672 // --------------------------
673 if (event == REMOVE_HYP || event == REMOVE_ALGO)
675 if (!_meshDS->RemoveHypothesis(_subShape, anHyp))
676 return SMESH_Hypothesis::HYP_OK; // nothing changes
678 // Serve Propagation of 1D hypothesis
679 // NOTE: it is possible to re-implement Propagation using EventListener
680 if (event == REMOVE_HYP)
682 bool isPropagationOk = true;
683 SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" ));
684 bool isPropagationHyp = propagFilter.IsOk( anHyp, _subShape );
686 if ( isPropagationHyp )
688 TopExp_Explorer exp (_subShape, TopAbs_EDGE);
689 TopTools_MapOfShape aMap;
690 for (; exp.More(); exp.Next()) {
691 if (aMap.Add(exp.Current()) &&
692 !_father->GetHypothesis( exp.Current(), propagFilter, true )) {
693 // no more Propagation on the current edge
694 if (!_father->RemovePropagationChain(exp.Current())) {
695 return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
699 // rebuild propagation chains, because removing one
700 // chain can resolve concurention, existing before
701 isPropagationOk = _father->RebuildPropagationChains();
703 else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated
705 isPropagationOk = _father->RebuildPropagationChains();
708 if ( isPropagationOk ) {
709 if ( isPropagationHyp )
710 return ret; // nothing more to do for "Propagation" hypothesis
712 else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
713 ret = SMESH_Hypothesis::HYP_CONCURENT;
715 } // Serve Propagation of 1D hypothesis
716 else // event == REMOVE_ALGO
718 algo = dynamic_cast<SMESH_Algo*> (anHyp);
719 if (!algo->NeedDescretBoundary())
721 // clean all mesh in the tree of the current submesh;
722 // we must perform it now because later
723 // we will have no information about the type of the removed algo
725 ComputeStateEngine( CLEAN );
731 // ------------------
732 // analyse algo state
733 // ------------------
734 if (!isApplicableHyp)
735 return ret; // not applicable hypotheses do not change algo state
740 // ----------------------------------------------------------------------
747 algo = gen->GetAlgo((*_father), _subShape);
749 if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
750 SetAlgoState(HYP_OK);
751 else if ( algo->IsStatusFatal( aux_ret )) {
752 _meshDS->RemoveHypothesis(_subShape, anHyp);
756 SetAlgoState(MISSING_HYP);
763 case ADD_FATHER_ALGO: { // Algo just added in father
764 algo = gen->GetAlgo((*_father), _subShape);
766 if ( algo == anHyp ) {
767 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
768 SetAlgoState(HYP_OK);
770 SetAlgoState(MISSING_HYP);
774 case REMOVE_FATHER_HYP:
776 case REMOVE_FATHER_ALGO: {
777 algo = gen->GetAlgo((*_father), _subShape);
780 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
781 SetAlgoState(HYP_OK);
783 SetAlgoState(MISSING_HYP);
787 case MODIF_HYP: break;
794 // ----------------------------------------------------------------------
800 algo = gen->GetAlgo((*_father), _subShape);
802 if ( algo->CheckHypothesis((*_father),_subShape, ret ))
803 SetAlgoState(HYP_OK);
804 if (SMESH_Hypothesis::IsStatusFatal( ret ))
805 _meshDS->RemoveHypothesis(_subShape, anHyp);
806 else if (!_father->IsUsedHypothesis( anHyp, this ))
808 _meshDS->RemoveHypothesis(_subShape, anHyp);
809 ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
813 case ADD_ALGO: { //already existing algo : on father ?
814 algo = gen->GetAlgo((*_father), _subShape);
816 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
817 SetAlgoState(HYP_OK);
818 else if ( algo->IsStatusFatal( aux_ret )) {
819 _meshDS->RemoveHypothesis(_subShape, anHyp);
823 SetAlgoState(MISSING_HYP);
828 case REMOVE_ALGO: { // perhaps a father algo applies ?
829 algo = gen->GetAlgo((*_father), _subShape);
830 if (algo == NULL) // no more algo applying on subShape...
832 SetAlgoState(NO_ALGO);
836 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
837 SetAlgoState(HYP_OK);
839 SetAlgoState(MISSING_HYP);
843 case MODIF_HYP: // assigned hypothesis value may become good
844 case ADD_FATHER_HYP: {
845 algo = gen->GetAlgo((*_father), _subShape);
847 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
848 SetAlgoState(HYP_OK);
850 SetAlgoState(MISSING_HYP);
853 case ADD_FATHER_ALGO: { // new father algo
854 algo = gen->GetAlgo((*_father), _subShape);
856 if ( algo == anHyp ) {
857 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
858 SetAlgoState(HYP_OK);
860 SetAlgoState(MISSING_HYP);
864 case REMOVE_FATHER_HYP: // nothing to do
866 case REMOVE_FATHER_ALGO: {
867 algo = gen->GetAlgo((*_father), _subShape);
868 if (algo == NULL) // no more applying algo on father
870 SetAlgoState(NO_ALGO);
874 if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
875 SetAlgoState(HYP_OK);
877 SetAlgoState(MISSING_HYP);
887 // ----------------------------------------------------------------------
893 algo = gen->GetAlgo((*_father), _subShape);
895 if (!algo->CheckHypothesis((*_father),_subShape, ret ))
897 if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
898 // ret should be fatal: anHyp was not added
899 ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
901 else if (!_father->IsUsedHypothesis( anHyp, this ))
902 ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
904 if (SMESH_Hypothesis::IsStatusFatal( ret ))
906 MESSAGE("do not add extra hypothesis");
907 _meshDS->RemoveHypothesis(_subShape, anHyp);
915 case ADD_ALGO: { //already existing algo : on father ?
916 algo = gen->GetAlgo((*_father), _subShape);
917 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
918 // check if algo changes
920 f.Init( SMESH_HypoFilter::IsAlgo() );
921 f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
922 f.AndNot( SMESH_HypoFilter::Is( algo ));
923 const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
925 string(algo->GetName()) != string(prevAlgo->GetName()) )
929 SetAlgoState(MISSING_HYP);
933 algo = gen->GetAlgo((*_father), _subShape);
935 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
936 SetAlgoState(HYP_OK);
938 SetAlgoState(MISSING_HYP);
942 case REMOVE_ALGO: { // perhaps a father algo applies ?
943 algo = gen->GetAlgo((*_father), _subShape);
944 if (algo == NULL) // no more algo applying on subShape...
946 SetAlgoState(NO_ALGO);
950 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
951 // check if algo remains
952 if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
956 SetAlgoState(MISSING_HYP);
960 case MODIF_HYP: // hypothesis value may become bad
961 case ADD_FATHER_HYP: { // new father hypothesis ?
962 algo = gen->GetAlgo((*_father), _subShape);
964 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
966 if (_father->IsUsedHypothesis( anHyp, this )) // new Hyp
970 SetAlgoState(MISSING_HYP);
973 case ADD_FATHER_ALGO: {
974 algo = gen->GetAlgo((*_father), _subShape);
975 if ( algo == anHyp ) { // a new algo on father
976 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
977 // check if algo changes
979 f.Init( SMESH_HypoFilter::IsAlgo() );
980 f.And( SMESH_HypoFilter::IsApplicableTo( _subShape ));
981 f.AndNot( SMESH_HypoFilter::Is( algo ));
982 const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
984 string(algo->GetName()) != string(prevAlgo->GetName()) )
988 SetAlgoState(MISSING_HYP);
992 case REMOVE_FATHER_HYP: {
993 algo = gen->GetAlgo((*_father), _subShape);
995 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
996 // is there the same local hyp or maybe a new father algo applied?
997 if ( !GetSimilarAttached( _subShape, anHyp ) )
1001 SetAlgoState(MISSING_HYP);
1004 case REMOVE_FATHER_ALGO: {
1005 algo = gen->GetAlgo((*_father), _subShape);
1006 if (algo == NULL) // no more applying algo on father
1008 SetAlgoState(NO_ALGO);
1012 if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
1013 // check if algo changes
1014 if ( string(algo->GetName()) != string( anHyp->GetName()) )
1018 SetAlgoState(MISSING_HYP);
1028 // ----------------------------------------------------------------------
1035 // detect algorithm hiding
1037 if ( ret == SMESH_Hypothesis::HYP_OK &&
1038 ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) &&
1039 algo->GetName() == anHyp->GetName() )
1042 SMESH_Gen* gen = _father->GetGen();
1043 TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1044 for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) {
1045 if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() ))
1046 if ( !upperAlgo->NeedDescretBoundary() )
1047 ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
1050 if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDescretBoundary() ) {
1051 map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
1052 for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
1053 if ( gen->GetAlgo( *_father, i_sm->second->_subShape ))
1054 ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
1058 bool stateChange = ( _algoState != oldAlgoState );
1060 if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
1061 algo->SetEventListener( this );
1063 NotifyListenersOnEvent( event, ALGO_EVENT, anHyp );
1065 if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
1066 DeleteOwnListeners();
1067 if (_subShape.ShapeType() == TopAbs_VERTEX ) {
1068 // restore default states
1069 _algoState = HYP_OK;
1070 _computeState = READY_TO_COMPUTE;
1074 if (stateChange || modifiedHyp)
1075 ComputeStateEngine(MODIF_ALGO_STATE);
1080 //=======================================================================
1081 //function : IsConform
1082 //purpose : check if a conform mesh will be produced by the Algo
1083 //=======================================================================
1085 bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
1087 // MESSAGE( "SMESH_subMesh::IsConform" );
1088 if ( !theAlgo ) return false;
1090 // Suppose that theAlgo is applicable to _subShape, do not check it here
1091 //if ( !IsApplicableHypotesis( theAlgo )) return false;
1093 // check only algo that doesn't NeedDescretBoundary(): because mesh made
1094 // on a sub-shape will be ignored by theAlgo
1095 if ( theAlgo->NeedDescretBoundary() ||
1096 !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
1099 SMESH_Gen* gen =_father->GetGen();
1101 // only local algo is to be checked
1102 //if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
1103 if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() )
1106 // check algo attached to adjacent shapes
1108 // loop on one level down sub-meshes
1109 TopoDS_Iterator itsub( _subShape );
1110 for (; itsub.More(); itsub.Next())
1112 // loop on adjacent subShapes
1113 TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
1114 for (; it.More(); it.Next())
1116 const TopoDS_Shape& adjacent = it.Value();
1117 if ( _subShape.IsSame( adjacent )) continue;
1118 if ( adjacent.ShapeType() != _subShape.ShapeType())
1121 // check algo attached to smAdjacent
1122 SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
1124 !algo->NeedDescretBoundary() &&
1125 algo->OnlyUnaryInput())
1126 return false; // NOT CONFORM MESH WILL BE PRODUCED
1133 //=============================================================================
1137 //=============================================================================
1139 void SMESH_subMesh::SetAlgoState(int state)
1144 //=============================================================================
1148 //=============================================================================
1149 SMESH_Hypothesis::Hypothesis_Status
1150 SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
1151 SMESH_Hypothesis * anHyp)
1153 //MESSAGE("SMESH_subMesh::SubMeshesAlgoStateEngine");
1154 SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
1155 //EAP: a wire (dim==1) should notify edges (dim==1)
1156 //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
1157 if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
1159 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
1161 map < int, SMESH_subMesh * >::const_iterator itsub;
1162 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
1164 SMESH_subMesh *sm = (*itsub).second;
1165 SMESH_Hypothesis::Hypothesis_Status ret2 =
1166 sm->AlgoStateEngine(event, anHyp);
1174 //=============================================================================
1178 //=============================================================================
1180 void SMESH_subMesh::CleanDependsOn()
1182 //MESSAGE("SMESH_subMesh::CleanDependsOn");
1184 const map < int, SMESH_subMesh * >&dependson = DependsOn();
1185 map < int, SMESH_subMesh * >::const_iterator its;
1186 for (its = dependson.begin(); its != dependson.end(); its++)
1188 SMESH_subMesh *sm = (*its).second;
1189 sm->ComputeStateEngine(CLEAN);
1193 //=============================================================================
1197 //=============================================================================
1199 void SMESH_subMesh::DumpAlgoState(bool isMain)
1201 int dim = SMESH_Gen::GetShapeDim(_subShape);
1202 // if (dim < 1) return;
1205 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
1207 map < int, SMESH_subMesh * >::const_iterator itsub;
1208 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
1210 SMESH_subMesh *sm = (*itsub).second;
1211 sm->DumpAlgoState(false);
1214 int type = _subShape.ShapeType();
1215 MESSAGE("dim = " << dim << " type of shape " << type);
1219 MESSAGE(" AlgoState = NO_ALGO");
1222 MESSAGE(" AlgoState = MISSING_HYP");
1225 MESSAGE(" AlgoState = HYP_OK");
1228 switch (_computeState)
1231 MESSAGE(" ComputeState = NOT_READY");
1233 case READY_TO_COMPUTE:
1234 MESSAGE(" ComputeState = READY_TO_COMPUTE");
1237 MESSAGE(" ComputeState = COMPUTE_OK");
1239 case FAILED_TO_COMPUTE:
1240 MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
1245 //================================================================================
1247 * \brief Remove nodes and elements bound to submesh
1248 * \param subMesh - submesh containing nodes and elements
1250 //================================================================================
1252 static void cleanSubMesh( SMESH_subMesh * subMesh )
1255 if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) {
1256 SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
1257 SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
1258 while (ite->more()) {
1259 const SMDS_MeshElement * elt = ite->next();
1260 //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
1261 //meshDS->RemoveElement(elt);
1262 meshDS->RemoveFreeElement(elt, subMeshDS);
1265 SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
1266 while (itn->more()) {
1267 const SMDS_MeshNode * node = itn->next();
1268 //MESSAGE( " RM node: "<<node->GetID());
1269 //meshDS->RemoveNode(node);
1270 meshDS->RemoveFreeNode(node, subMeshDS);
1276 //=============================================================================
1280 //=============================================================================
1282 bool SMESH_subMesh::ComputeStateEngine(int event)
1284 //MESSAGE("SMESH_subMesh::ComputeStateEngine");
1285 //SCRUTE(_computeState);
1288 if (_subShape.ShapeType() == TopAbs_VERTEX)
1290 if ( IsMeshComputed() )
1291 _computeState = COMPUTE_OK;
1293 _computeState = READY_TO_COMPUTE;
1294 if ( event == MODIF_ALGO_STATE )
1298 SMESH_Gen *gen = _father->GetGen();
1299 SMESH_Algo *algo = 0;
1301 SMESH_Hypothesis::Hypothesis_Status hyp_status;
1302 //algo_state oldAlgoState = (algo_state) GetAlgoState();
1304 switch (_computeState)
1307 // ----------------------------------------------------------------------
1312 case MODIF_ALGO_STATE:
1313 algo = gen->GetAlgo((*_father), _subShape);
1314 if (algo && !algo->NeedDescretBoundary())
1315 CleanDependsOn(); // clean sub-meshes with event CLEAN
1316 if ( _algoState == HYP_OK )
1317 _computeState = READY_TO_COMPUTE;
1319 case COMPUTE: // nothing to do
1323 RemoveSubMeshElementsAndNodes();
1325 case SUBMESH_COMPUTED: // nothing to do
1327 case SUBMESH_RESTORED:
1328 ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1330 case MESH_ENTITY_REMOVED:
1332 case CHECK_COMPUTE_STATE:
1333 if ( IsMeshComputed() )
1334 _computeState = COMPUTE_OK;
1342 // ----------------------------------------------------------------------
1344 case READY_TO_COMPUTE:
1347 case MODIF_ALGO_STATE:
1348 _computeState = NOT_READY;
1349 algo = gen->GetAlgo((*_father), _subShape);
1352 if (!algo->NeedDescretBoundary())
1353 CleanDependsOn(); // clean sub-meshes with event CLEAN
1354 if ( _algoState == HYP_OK )
1355 _computeState = READY_TO_COMPUTE;
1360 algo = gen->GetAlgo((*_father), _subShape);
1362 ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1365 MESSAGE("***** verify compute state *****");
1366 _computeState = NOT_READY;
1367 SetAlgoState(MISSING_HYP);
1370 // check submeshes needed
1371 if (_father->HasShapeToMesh() && algo->NeedDescretBoundary())
1372 ret = SubMeshesComputed();
1375 MESSAGE("Some SubMeshes not computed");
1376 _computeState = FAILED_TO_COMPUTE;
1381 RemoveSubMeshElementsAndNodes();
1384 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1387 if ( !_father->HasShapeToMesh() ) // no shape
1389 SMESH_MesherHelper helper( *_father );
1390 helper.SetSubShape( _subShape );
1391 helper.SetElementsOnShape( true );
1392 ret = algo->Compute(*_father, &helper );
1395 if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
1396 ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
1398 ret = algo->Compute((*_father), _subShape);
1401 catch (Standard_Failure) {
1402 MESSAGE( "Exception in algo->Compute() ");
1408 MESSAGE("problem in algo execution: failed to compute");
1409 // release ALGO from responsibilty of partially built mesh
1410 RemoveSubMeshElementsAndNodes();
1411 _computeState = FAILED_TO_COMPUTE;
1412 if (!algo->NeedDescretBoundary())
1413 UpdateSubMeshState( FAILED_TO_COMPUTE );
1416 // Show vertices location of a failed shape
1417 cout << algo->GetName() << " failed on shape with the following vertices:" << endl;
1418 TopTools_IndexedMapOfShape vMap;
1419 TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
1420 for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
1421 gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
1422 cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
1429 _computeState = COMPUTE_OK;
1430 UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
1431 if (!algo->NeedDescretBoundary())
1432 UpdateSubMeshState( COMPUTE_OK );
1438 RemoveSubMeshElementsAndNodes();
1439 _computeState = NOT_READY;
1440 algo = gen->GetAlgo((*_father), _subShape);
1443 ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1445 _computeState = READY_TO_COMPUTE;
1447 SetAlgoState(MISSING_HYP);
1450 case SUBMESH_COMPUTED: // nothing to do
1452 case SUBMESH_RESTORED:
1453 // check if a mesh is already computed that may
1454 // happen after retrieval from a file
1455 ComputeStateEngine( CHECK_COMPUTE_STATE );
1456 ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1457 algo = gen->GetAlgo(*_father, _subShape);
1458 if (algo) algo->SubmeshRestored( this );
1460 case MESH_ENTITY_REMOVED:
1462 case CHECK_COMPUTE_STATE:
1463 if ( IsMeshComputed() )
1464 _computeState = COMPUTE_OK;
1472 // ----------------------------------------------------------------------
1477 case MODIF_ALGO_STATE:
1478 ComputeStateEngine( CLEAN );
1479 algo = gen->GetAlgo((*_father), _subShape);
1480 if (algo && !algo->NeedDescretBoundary())
1481 CleanDependsOn(); // clean sub-meshes with event CLEAN
1483 case COMPUTE: // nothing to do
1486 CleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN
1487 RemoveSubMeshElementsAndNodes();
1488 _computeState = NOT_READY;
1489 if ( _algoState == HYP_OK )
1490 _computeState = READY_TO_COMPUTE;
1492 case SUBMESH_COMPUTED: // nothing to do
1494 case SUBMESH_RESTORED:
1495 ComputeStateEngine( CHECK_COMPUTE_STATE );
1496 ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1497 algo = gen->GetAlgo(*_father, _subShape);
1498 if (algo) algo->SubmeshRestored( this );
1500 case MESH_ENTITY_REMOVED:
1501 UpdateDependantsState( CHECK_COMPUTE_STATE );
1502 ComputeStateEngine( CHECK_COMPUTE_STATE );
1503 ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1505 case CHECK_COMPUTE_STATE:
1506 if ( !IsMeshComputed() )
1507 if (_algoState == HYP_OK)
1508 _computeState = READY_TO_COMPUTE;
1510 _computeState = NOT_READY;
1518 // ----------------------------------------------------------------------
1520 case FAILED_TO_COMPUTE:
1523 case MODIF_ALGO_STATE:
1524 if (_algoState == HYP_OK)
1525 _computeState = READY_TO_COMPUTE;
1527 _computeState = NOT_READY;
1529 case COMPUTE: // nothing to do
1532 CleanDependants(); // submeshes dependent on me should be cleaned as well
1533 RemoveSubMeshElementsAndNodes();
1534 if (_algoState == HYP_OK)
1535 _computeState = READY_TO_COMPUTE;
1537 _computeState = NOT_READY;
1539 case SUBMESH_COMPUTED: // allow retry compute
1540 if (_algoState == HYP_OK)
1541 _computeState = READY_TO_COMPUTE;
1543 _computeState = NOT_READY;
1545 case SUBMESH_RESTORED:
1546 ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1548 case MESH_ENTITY_REMOVED:
1550 case CHECK_COMPUTE_STATE:
1551 if ( IsMeshComputed() )
1552 _computeState = COMPUTE_OK;
1554 if (_algoState == HYP_OK)
1555 _computeState = READY_TO_COMPUTE;
1557 _computeState = NOT_READY;
1565 // ----------------------------------------------------------------------
1571 NotifyListenersOnEvent( event, COMPUTE_EVENT );
1576 //=======================================================================
1577 //function : ApplyToCollection
1578 //purpose : Apply theAlgo to all subshapes in theCollection
1579 //=======================================================================
1581 bool SMESH_subMesh::ApplyToCollection (SMESH_Algo* theAlgo,
1582 const TopoDS_Shape& theCollection)
1584 MESSAGE("SMESH_subMesh::ApplyToCollection");
1585 ASSERT ( !theAlgo->NeedDescretBoundary() );
1590 ret = theAlgo->Compute( *_father, theCollection );
1592 // set _computeState of subshapes
1593 TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
1594 for ( ; anExplorer.More(); anExplorer.Next() )
1596 const TopoDS_Shape& aSubShape = anExplorer.Current();
1597 SMESH_subMesh* subMesh = _father->GetSubMeshContaining( aSubShape );
1602 subMesh->_computeState = COMPUTE_OK;
1603 subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
1604 subMesh->UpdateSubMeshState( COMPUTE_OK );
1608 subMesh->_computeState = FAILED_TO_COMPUTE;
1616 //=======================================================================
1617 //function : UpdateSubMeshState
1619 //=======================================================================
1621 void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
1623 const map<int, SMESH_subMesh*>& smMap = DependsOn();
1624 map<int, SMESH_subMesh*>::const_iterator itsub;
1625 for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1627 SMESH_subMesh* sm = (*itsub).second;
1628 sm->_computeState = theState;
1632 //=======================================================================
1633 //function : ComputeSubMeshStateEngine
1635 //=======================================================================
1637 void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
1639 const map<int, SMESH_subMesh*>& smMap = DependsOn();
1640 map<int, SMESH_subMesh*>::const_iterator itsub;
1641 for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1643 SMESH_subMesh* sm = (*itsub).second;
1644 sm->ComputeStateEngine(event);
1648 //=======================================================================
1649 //function : UpdateDependantsState
1651 //=======================================================================
1653 void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
1655 //MESSAGE("SMESH_subMesh::UpdateDependantsState");
1656 TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1657 for (; it.More(); it.Next())
1659 const TopoDS_Shape& ancestor = it.Value();
1660 SMESH_subMesh *aSubMesh =
1661 _father->GetSubMeshContaining(ancestor);
1663 aSubMesh->ComputeStateEngine( theEvent );
1667 //=============================================================================
1671 //=============================================================================
1673 void SMESH_subMesh::CleanDependants()
1675 int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
1677 TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1678 for (; it.More(); it.Next())
1680 const TopoDS_Shape& ancestor = it.Value();
1681 if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
1682 // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
1683 // will erase mesh on other shapes in a compound
1684 if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
1685 SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
1687 aSubMesh->ComputeStateEngine(CLEAN);
1693 //=============================================================================
1697 //=============================================================================
1699 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
1701 //SCRUTE(_subShape.ShapeType());
1703 cleanSubMesh( this );
1705 // algo may bind a submesh not to _subShape, eg 3D algo
1706 // sets nodes on SHELL while _subShape may be SOLID
1708 int dim = SMESH_Gen::GetShapeDim( _subShape );
1709 int type = _subShape.ShapeType() + 1;
1710 for ( ; type <= TopAbs_EDGE; type++) {
1711 if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1713 TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1714 for ( ; exp.More(); exp.Next() )
1715 cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
1722 //=======================================================================
1723 //function : GetCollection
1724 //purpose : return a shape containing all sub-shapes of the MainShape that can be
1725 // meshed at once along with _subShape
1726 //=======================================================================
1728 TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
1730 MESSAGE("SMESH_subMesh::GetCollection");
1731 ASSERT (!theAlgo->NeedDescretBoundary());
1733 TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
1735 if ( mainShape.IsSame( _subShape ))
1738 const bool ignoreAuxiliaryHyps = false;
1739 list<const SMESHDS_Hypothesis*> aUsedHyp =
1740 theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
1742 // put in a compound all shapes with the same hypothesis assigned
1743 // and a good ComputState
1745 TopoDS_Compound aCompound;
1746 BRep_Builder aBuilder;
1747 aBuilder.MakeCompound( aCompound );
1749 TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
1750 for ( ; anExplorer.More(); anExplorer.Next() )
1752 const TopoDS_Shape& S = anExplorer.Current();
1753 SMESH_subMesh* subMesh = _father->GetSubMesh( S );
1754 SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
1756 if (subMesh->GetComputeState() == READY_TO_COMPUTE &&
1757 anAlgo == theAlgo &&
1758 anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
1760 aBuilder.Add( aCompound, S );
1767 //=======================================================================
1768 //function : GetSimilarAttached
1769 //purpose : return a hypothesis attached to theShape.
1770 // If theHyp is provided, similar but not same hypotheses
1771 // is returned; else only applicable ones having theHypType
1773 //=======================================================================
1775 const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape& theShape,
1776 const SMESH_Hypothesis * theHyp,
1777 const int theHypType)
1779 SMESH_HypoFilter hypoKind;
1780 hypoKind.Init( hypoKind.HasType( theHyp ? theHyp->GetType() : theHypType ));
1782 hypoKind.And ( hypoKind.HasDim( theHyp->GetDim() ));
1783 hypoKind.AndNot( hypoKind.Is( theHyp ));
1784 if ( theHyp->IsAuxiliary() )
1785 hypoKind.And( hypoKind.HasName( theHyp->GetName() ));
1787 hypoKind.AndNot( hypoKind.IsAuxiliary());
1790 hypoKind.And( hypoKind.IsApplicableTo( theShape ));
1793 return _father->GetHypothesis( theShape, hypoKind, false );
1796 //=======================================================================
1797 //function : CheckConcurentHypothesis
1798 //purpose : check if there are several applicable hypothesis attached to
1800 //=======================================================================
1802 SMESH_Hypothesis::Hypothesis_Status
1803 SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
1805 MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
1807 // is there local hypothesis on me?
1808 if ( GetSimilarAttached( _subShape, 0, theHypType ) )
1809 return SMESH_Hypothesis::HYP_OK;
1812 TopoDS_Shape aPrevWithHyp;
1813 const SMESH_Hypothesis* aPrevHyp = 0;
1814 TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1815 for (; it.More(); it.Next())
1817 const TopoDS_Shape& ancestor = it.Value();
1818 const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
1821 if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
1823 aPrevWithHyp = ancestor;
1826 else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
1827 return SMESH_Hypothesis::HYP_CONCURENT;
1829 return SMESH_Hypothesis::HYP_OK;
1832 return SMESH_Hypothesis::HYP_OK;
1835 //================================================================================
1837 * \brief Sets an event listener and its data to a submesh
1838 * \param listener - the listener to store
1839 * \param data - the listener data to store
1840 * \param where - the submesh to store the listener and it's data
1841 * \param deleteListener - if true then the listener will be deleted as
1842 * it is removed from where submesh
1844 * It remembers the submesh where it puts the listener in order to delete
1845 * them when HYP_OK algo_state is lost
1846 * After being set, event listener is notified on each event of where submesh.
1848 //================================================================================
1850 void SMESH_subMesh::SetEventListener(EventListener* listener,
1851 EventListenerData* data,
1852 SMESH_subMesh* where)
1854 if ( listener && where ) {
1855 where->SetEventListener( listener, data );
1856 myOwnListeners.push_back( make_pair( where, listener ));
1860 //================================================================================
1862 * \brief Sets an event listener and its data to a submesh
1863 * \param listener - the listener to store
1864 * \param data - the listener data to store
1866 * After being set, event listener is notified on each event of a submesh.
1868 //================================================================================
1870 void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* data)
1872 map< EventListener*, EventListenerData* >::iterator l_d =
1873 myEventListeners.find( listener );
1874 if ( l_d != myEventListeners.end() ) {
1875 if ( l_d->second && l_d->second->IsDeletable() )
1880 myEventListeners.insert( make_pair( listener, data ));
1883 //================================================================================
1885 * \brief Return an event listener data
1886 * \param listener - the listener whose data is
1887 * \retval EventListenerData* - found data, maybe NULL
1889 //================================================================================
1891 EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const
1893 map< EventListener*, EventListenerData* >::const_iterator l_d =
1894 myEventListeners.find( listener );
1895 if ( l_d != myEventListeners.end() )
1900 //================================================================================
1902 * \brief Notify stored event listeners on the occured event
1903 * \param event - algo_event or compute_event itself
1904 * \param eventType - algo_event or compute_event
1905 * \param subMesh - the submesh where the event occures
1906 * \param data - listener data stored in the subMesh
1907 * \param hyp - hypothesis, if eventType is algo_event
1909 //================================================================================
1911 void SMESH_subMesh::NotifyListenersOnEvent( const int event,
1912 const event_type eventType,
1913 SMESH_Hypothesis* hyp)
1915 map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.begin();
1916 for ( ; l_d != myEventListeners.end(); ++l_d )
1917 l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp );
1920 //================================================================================
1922 * \brief Unregister the listener and delete listener's data
1923 * \param listener - the event listener
1925 //================================================================================
1927 void SMESH_subMesh::DeleteEventListener(EventListener* listener)
1929 map< EventListener*, EventListenerData* >::iterator l_d =
1930 myEventListeners.find( listener );
1931 if ( l_d != myEventListeners.end() ) {
1932 if ( l_d->first && l_d->first->IsDeletable() ) delete l_d->first;
1933 if ( l_d->second && l_d->second->IsDeletable() ) delete l_d->second;
1934 myEventListeners.erase( l_d );
1938 //================================================================================
1940 * \brief Delete event listeners depending on algo of this submesh
1942 //================================================================================
1944 void SMESH_subMesh::DeleteOwnListeners()
1946 list< pair< SMESH_subMesh*, EventListener* > >::iterator sm_l;
1947 for ( sm_l = myOwnListeners.begin(); sm_l != myOwnListeners.end(); ++sm_l)
1948 sm_l->first->DeleteEventListener( sm_l->second );
1949 myOwnListeners.clear();
1952 //================================================================================
1954 * \brief Do something on a certain event
1955 * \param event - algo_event or compute_event itself
1956 * \param eventType - algo_event or compute_event
1957 * \param subMesh - the submesh where the event occures
1958 * \param data - listener data stored in the subMesh
1959 * \param hyp - hypothesis, if eventType is algo_event
1961 * The base implementation translates CLEAN event to the subMesh
1962 * stored in listener data. Also it sends SUBMESH_COMPUTED event in case of
1963 * successful COMPUTE event.
1965 //================================================================================
1967 void SMESH_subMeshEventListener::ProcessEvent(const int event,
1968 const int eventType,
1969 SMESH_subMesh* subMesh,
1970 EventListenerData* data,
1971 SMESH_Hypothesis* /*hyp*/)
1973 if ( data && !data->mySubMeshes.empty() &&
1974 eventType == SMESH_subMesh::COMPUTE_EVENT)
1976 ASSERT( data->mySubMeshes.front() != subMesh );
1978 case SMESH_subMesh::CLEAN:
1979 data->mySubMeshes.front()->ComputeStateEngine( event );
1981 case SMESH_subMesh::COMPUTE:
1982 if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK )
1983 data->mySubMeshes.front()->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );