diff --git a/doc/salome/gui/SMESH/images/mesh_order_123.png b/doc/salome/gui/SMESH/images/mesh_order_123.png new file mode 100644 index 000000000..952f20796 Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_123.png differ diff --git a/doc/salome/gui/SMESH/images/mesh_order_123_res.png b/doc/salome/gui/SMESH/images/mesh_order_123_res.png new file mode 100644 index 000000000..7b7588c63 Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_123_res.png differ diff --git a/doc/salome/gui/SMESH/images/mesh_order_213.png b/doc/salome/gui/SMESH/images/mesh_order_213.png new file mode 100644 index 000000000..959ca384e Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_213.png differ diff --git a/doc/salome/gui/SMESH/images/mesh_order_213_res.png b/doc/salome/gui/SMESH/images/mesh_order_213_res.png new file mode 100644 index 000000000..ca36759a9 Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_213_res.png differ diff --git a/doc/salome/gui/SMESH/images/mesh_order_321.png b/doc/salome/gui/SMESH/images/mesh_order_321.png new file mode 100644 index 000000000..7ad61fabd Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_321.png differ diff --git a/doc/salome/gui/SMESH/images/mesh_order_321_res.png b/doc/salome/gui/SMESH/images/mesh_order_321_res.png new file mode 100644 index 000000000..051447093 Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_321_res.png differ diff --git a/doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png b/doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png new file mode 100644 index 000000000..6df59a1f1 Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png differ diff --git a/doc/salome/gui/SMESH/images/mesh_order_preview.png b/doc/salome/gui/SMESH/images/mesh_order_preview.png new file mode 100644 index 000000000..f4b5e3b98 Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_preview.png differ diff --git a/doc/salome/gui/SMESH/input/constructing_meshes.doc b/doc/salome/gui/SMESH/input/constructing_meshes.doc index 625cff3bd..62518555e 100644 --- a/doc/salome/gui/SMESH/input/constructing_meshes.doc +++ b/doc/salome/gui/SMESH/input/constructing_meshes.doc @@ -152,10 +152,89 @@ evaluation will be displayed in the following information box: \image html mesh_evaluation_succeed.png + + + + +\anchor mesh_order_anchor +It is allowed to change submesh priority in mesh computation when +there are concurrent submeshes present. I.e. user can change priority of +applying algorithms on shared subshapes of Mesh shape. +To change submesh priority: +
    +
  1. From the Mesh menu choose the "Change submesh priority" on +selected Mesh item, or invoke from popup menu. + +There are example of submesh order modifications of Mesh created on a Box +shape. The main Mesh object: + +The first submesh object Submesh_1 created on Face_1 +is: + +The second submesh object Submesh_2 created on Face_2 +is: + + +And the last third submesh object Submesh_3 created on Face_3 +is: + +The submeshes can become concurrent if thir algorithms leads to mesh shared subshape +with different algorithms (or different algorithms parameters, i.e. hypothesises). +In fact, we have three submeshes with concurrent algorithms, becase +they has different hypothesises assigned to them. + +The first mesh computation made with: +\image html mesh_order_123.png +
    "Mesh order SubMesh_1, SubMesh_2, SubMesh_3"
    +\image html mesh_order_123_res.png +
    "Result mesh with order SubMesh_1, SubMesh_2, SubMesh_3 "
    + +The next mesh computation with: +\image html mesh_order_213.png +
    "Mesh order SubMesh_2, SubMesh_1, SubMesh_3"
    +\image html mesh_order_213_res.png +
    "Result mesh with order SubMesh_2, SubMesh_1, SubMesh_3 "
    + +And the last mesh computation with: +\image html mesh_order_321.png +
    "Mesh order SubMesh_3, SubMesh_2, SubMesh_1"
    +\image html mesh_order_321_res.png +
    "Result mesh with order SubMesh_3, SubMesh_2, SubMesh_1 "
    + +As we can see each mesh computation has different number of result +elements and different mesh descretisation on shared edges (edges, +that shared between Face_1, Face_2 and Face_3) + +Additionally, submesh priority (order of algorithms to be applied) can +be modified not only in separate dialog box, but in Preview +also. This helps to preview different mesh results, modifying submesh +order. +\image html mesh_order_preview.png +
    "Preview with submesh priority list box"
    + +If no concurrent submeshes under Mesh object user will see the +following information dialog box +\image html mesh_order_no_concurrent.png +
    "No concurrent submeshes detected"
    +and no mesh order list box appear in Preview dialog box. + +
Consider trying a sample script for construction of a mesh from our \ref tui_creating_meshes_page "TUI Scripts" section. - - */ diff --git a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc index 87f740e98..359ffd7d5 100644 --- a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc +++ b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc @@ -82,6 +82,67 @@ quadra.Compute() \endcode +
+

Change priority of submeshes in Mesh

+ +\code +import salome +import geompy +import smesh +import SMESH + +Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) +[Face_1,Face_2,Face_3,Face_4,Face_5,Face_6] = geompy.SubShapeAllSorted(Box_1, geompy.ShapeType["FACE"]) + +# create Mesh object on Box shape +Mesh_1 = smesh.Mesh(Box_1) + +# assign mesh algorithms +Regular_1D = Mesh_1.Segment() +Nb_Segments_1 = Regular_1D.NumberOfSegments(20) +Nb_Segments_1.SetDistrType( 0 ) +MEFISTO_2D = Mesh_1.Triangle() +Max_Element_Area_1 = MEFISTO_2D.MaxElementArea(1200) +Tetrahedron_Netgen = Mesh_1.Tetrahedron(algo=smesh.NETGEN) +Max_Element_Volume_1 = Tetrahedron_Netgen.MaxElementVolume(40000) + +# create submesh and assign algorithms on Face_1 +Netgen_1D_2D = Mesh_1.Triangle(algo=smesh.NETGEN,geom=Face_1) +SubMesh_1 = Netgen_1D_2D.GetSubMesh() +NETGEN_2D_Simple_Parameters_1 = Netgen_1D_2D.Parameters(which=smesh.SIMPLE) +NETGEN_2D_Simple_Parameters_1.SetNumberOfSegments( 4 ) +NETGEN_2D_Simple_Parameters_1.LengthFromEdges() + +# create submesh and assign algorithms on Face_2 +Netgen_1D_2D_1 = Mesh_1.Triangle(algo=smesh.NETGEN,geom=Face_2) +SubMesh_2 = Netgen_1D_2D_1.GetSubMesh() +NETGEN_2D_Simple_Parameters_2 = Netgen_1D_2D_1.Parameters(which=smesh.SIMPLE) +NETGEN_2D_Simple_Parameters_2.SetNumberOfSegments( 8 ) +NETGEN_2D_Simple_Parameters_2.LengthFromEdges() +smeshObj_1 = smesh.CreateHypothesis('NETGEN_SimpleParameters_2D', +'NETGENEngine') + +# create submesh and assign algorithms on Face_3 +Netgen_1D_2D_2 = Mesh_1.Triangle(algo=smesh.NETGEN,geom=Face_3) +SubMesh_3 = Netgen_1D_2D_2.GetSubMesh() +NETGEN_2D_Simple_Parameters_3 = Netgen_1D_2D_2.Parameters(which=smesh.SIMPLE) +NETGEN_2D_Simple_Parameters_3.SetNumberOfSegments( 12 ) +NETGEN_2D_Simple_Parameters_3.LengthFromEdges() + +# check exisiting submesh priority order +[ [ SubMesh_1, SubMesh_3, SubMesh_2 ] ] = Mesh_1.GetMeshOrder() +# set new submesh order +isDone = Mesh_1.SetMeshOrder( [ [ SubMesh_1, SubMesh_2, SubMesh_3 ] ]) +# compute mesh +isDone = Mesh_1.Compute() + +# clear mesh result and compute with other submesh order +Mesh_1.Clear() +isDone = Mesh_1.SetMeshOrder( [ [ SubMesh_2, SubMesh_1, SubMesh_3 ] ]) +isDone = Mesh_1.Compute() + +\endcode +
\anchor tui_editing_mesh

Editing of a mesh

diff --git a/idl/SMESH_Mesh.idl b/idl/SMESH_Mesh.idl index 8a5c37daa..c58b7fa31 100644 --- a/idl/SMESH_Mesh.idl +++ b/idl/SMESH_Mesh.idl @@ -263,6 +263,10 @@ module SMESH interface SMESH_GroupOnGeom; interface SMESH_subMesh; interface SMESH_MeshEditor; + + typedef sequence submesh_array; + typedef sequence submesh_array_array; + interface SMESH_Mesh : SALOME::GenericObj, SMESH_IDSource { /*! @@ -661,6 +665,22 @@ module SMESH ElementType GetSubMeshElementType(in long ShapeID) raises (SALOME::SALOME_Exception); + + /*! + * Methods to set meshing order of submeshes + */ + + /*! + * \brief Return submesh objects list in meshing order + */ + submesh_array_array GetMeshOrder(); + + /*! + * \brief Set submesh object order + */ + boolean SetMeshOrder(in submesh_array_array theSubMeshArray); + + /*! * Get mesh description */ diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index 10ec57e1f..0706b5f2f 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -207,7 +207,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, if ( algo && !algo->NeedDescretBoundary() ) { if ( algo->SupportSubmeshes() ) - smWithAlgoSupportingSubmeshes.push_back( smToCompute ); + smWithAlgoSupportingSubmeshes.push_front( smToCompute ); else { smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE ); @@ -216,13 +216,19 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, } } } + + // ------------------------------------------------------------ + // sort list of meshes according to mesh order + // ------------------------------------------------------------ + aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes ); + // ------------------------------------------------------------ // compute submeshes under shapes with algos that DO NOT require // descretized boundaries and DO support submeshes // ------------------------------------------------------------ - list< SMESH_subMesh* >::reverse_iterator subIt, subEnd; - subIt = smWithAlgoSupportingSubmeshes.rbegin(); - subEnd = smWithAlgoSupportingSubmeshes.rend(); + list< SMESH_subMesh* >::iterator subIt, subEnd; + subIt = smWithAlgoSupportingSubmeshes.begin(); + subEnd = smWithAlgoSupportingSubmeshes.end(); // start from lower shapes for ( ; subIt != subEnd; ++subIt ) { @@ -264,7 +270,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, // ---------------------------------------------------------- // apply the algos that do not require descretized boundaries // ---------------------------------------------------------- - for ( subIt = smWithAlgoSupportingSubmeshes.rbegin(); subIt != subEnd; ++subIt ) + for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt ) { sm = *subIt; if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) @@ -353,7 +359,7 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh & aMesh, SMESH_Algo* algo = GetAlgo( aMesh, aSubShape ); if ( algo && !algo->NeedDescretBoundary() ) { if ( algo->SupportSubmeshes() ) { - smWithAlgoSupportingSubmeshes.push_back( smToCompute ); + smWithAlgoSupportingSubmeshes.push_front( smToCompute ); } else { smToCompute->Evaluate(aResMap); @@ -362,13 +368,19 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh & aMesh, } } } + + // ------------------------------------------------------------ + // sort list of meshes according to mesh order + // ------------------------------------------------------------ + aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes ); + // ------------------------------------------------------------ // compute submeshes under shapes with algos that DO NOT require // descretized boundaries and DO support submeshes // ------------------------------------------------------------ - list< SMESH_subMesh* >::reverse_iterator subIt, subEnd; - subIt = smWithAlgoSupportingSubmeshes.rbegin(); - subEnd = smWithAlgoSupportingSubmeshes.rend(); + list< SMESH_subMesh* >::iterator subIt, subEnd; + subIt = smWithAlgoSupportingSubmeshes.begin(); + subEnd = smWithAlgoSupportingSubmeshes.end(); // start from lower shapes for ( ; subIt != subEnd; ++subIt ) { sm = *subIt; @@ -405,7 +417,7 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh & aMesh, // ---------------------------------------------------------- // apply the algos that do not require descretized boundaries // ---------------------------------------------------------- - for ( subIt = smWithAlgoSupportingSubmeshes.rbegin(); subIt != subEnd; ++subIt ) + for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt ) { sm = *subIt; sm->Evaluate(aResMap); diff --git a/src/SMESH/SMESH_Gen.hxx b/src/SMESH/SMESH_Gen.hxx index ab610a00a..b26a2047d 100644 --- a/src/SMESH/SMESH_Gen.hxx +++ b/src/SMESH/SMESH_Gen.hxx @@ -148,7 +148,7 @@ public: private: - int _localId; // unique Id of created objects, within SMESH_Gen entity + int _localId; // unique Id of created objects, within SMESH_Gen entity std::map < int, StudyContextStruct * >_mapStudyContext; // hypotheses managing diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 67d78b4e6..6b2a69bcc 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -175,14 +175,8 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape) _isShapeToMesh = true; _nbSubShapes = _myMeshDS->MaxShapeIndex(); - // fill _mapAncestors - int desType, ancType; - for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- ) - for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- ) - TopExp::MapShapesAndAncestors ( aShape, - (TopAbs_ShapeEnum) desType, - (TopAbs_ShapeEnum) ancType, - _mapAncestors ); + // fill map of ancestors + fillAncestorsMap(aShape); } else { @@ -479,33 +473,6 @@ SMESH_Hypothesis::Hypothesis_Status if ( !subMesh || !subMesh->GetId()) return SMESH_Hypothesis::HYP_BAD_SUBSHAPE; - SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS(); - if ( subMeshDS && subMeshDS->IsComplexSubmesh() ) // group of sub-shapes and maybe of not sub- - { - MESSAGE("AddHypothesis() to complex submesh"); - // return the worst but not fatal state of all group memebers - SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret; - aBestRet = SMESH_Hypothesis::HYP_BAD_DIM; - aWorstNotFatal = SMESH_Hypothesis::HYP_OK; - for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next()) - { - if ( !GetMeshDS()->ShapeToIndex( itS.Value() )) - continue; // not sub-shape - ret = AddHypothesis( itS.Value(), anHypId ); - if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal ) - aWorstNotFatal = ret; - if ( ret < aBestRet ) - aBestRet = ret; - } - // bind hypotheses to a group just to know - SMESH_Hypothesis *anHyp = _gen->GetStudyContext(_studyId)->mapHypothesis[anHypId]; - GetMeshDS()->AddHypothesis( aSubShape, anHyp ); - - if ( SMESH_Hypothesis::IsStatusFatal( aBestRet )) - return aBestRet; - return aWorstNotFatal; - } - StudyContextStruct *sc = _gen->GetStudyContext(_studyId); if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end()) { @@ -586,32 +553,6 @@ SMESH_Hypothesis::Hypothesis_Status Unexpect aCatch(SalomeException); if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis"); - SMESH_subMesh *subMesh = GetSubMesh(aSubShape); - SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS(); - if ( subMeshDS && subMeshDS->IsComplexSubmesh() ) - { - // return the worst but not fatal state of all group memebers - SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret; - aBestRet = SMESH_Hypothesis::HYP_BAD_DIM; - aWorstNotFatal = SMESH_Hypothesis::HYP_OK; - for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next()) - { - if ( !GetMeshDS()->ShapeToIndex( itS.Value() )) - continue; // not sub-shape - ret = RemoveHypothesis( itS.Value(), anHypId ); - if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal ) - aWorstNotFatal = ret; - if ( ret < aBestRet ) - aBestRet = ret; - } - SMESH_Hypothesis *anHyp = _gen->GetStudyContext(_studyId)->mapHypothesis[anHypId]; - GetMeshDS()->RemoveHypothesis( aSubShape, anHyp ); - - if ( SMESH_Hypothesis::IsStatusFatal( aBestRet )) - return aBestRet; - return aWorstNotFatal; - } - StudyContextStruct *sc = _gen->GetStudyContext(_studyId); if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end()) throw SALOME_Exception(LOCALIZED("hypothesis does not exist")); @@ -625,6 +566,8 @@ SMESH_Hypothesis::Hypothesis_Status bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ); int event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP; + SMESH_subMesh *subMesh = GetSubMesh(aSubShape); + SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp); // there may appear concurrent hyps that were covered by the removed hyp @@ -709,15 +652,18 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape & aSubS } if ( andAncestors ) { - TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape )); - for (; it.More(); it.Next() ) + // user sorted submeshes of ancestors, according to stored submesh priority + const std::list smList = getAncestorsSubMeshes( aSubShape ); + std::list::const_iterator smIt = smList.begin(); + for ( ; smIt != smList.end(); smIt++ ) { - const std::list& hypList = _myMeshDS->GetHypothesis(it.Value()); + const TopoDS_Shape& curSh = (*smIt)->GetSubShape(); + const std::list& hypList = _myMeshDS->GetHypothesis(curSh); std::list::const_iterator hyp = hypList.begin(); for ( ; hyp != hypList.end(); hyp++ ) { const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp ); - if (aFilter.IsOk( h, it.Value() )) { - if ( assignedTo ) *assignedTo = it.Value(); + if (aFilter.IsOk( h, curSh )) { + if ( assignedTo ) *assignedTo = curSh; return h; } } @@ -776,14 +722,18 @@ int SMESH_Mesh::GetHypotheses(const TopoDS_Shape & aSubShape, if ( andAncestors ) { TopTools_MapOfShape map; - TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape )); - for (; it.More(); it.Next() ) + + // user sorted submeshes of ancestors, according to stored submesh priority + const std::list smList = getAncestorsSubMeshes( aSubShape ); + std::list::const_iterator smIt = smList.begin(); + for ( ; smIt != smList.end(); smIt++ ) { - if ( !map.Add( it.Value() )) + const TopoDS_Shape& curSh = (*smIt)->GetSubShape(); + if ( !map.Add( curSh )) continue; - const std::list& hypList = _myMeshDS->GetHypothesis(it.Value()); + const std::list& hypList = _myMeshDS->GetHypothesis(curSh); for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ ) - if (aFilter.IsOk( cSMESH_Hyp( *hyp ), it.Value() ) && + if (aFilter.IsOk( cSMESH_Hyp( *hyp ), curSh ) && ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) && hypTypes.insert( (*hyp)->GetName() ).second ) { @@ -842,6 +792,9 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape) { index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() ); if ( index > _nbSubShapes ) _nbSubShapes = index; // not to create sm for this group again + + // fill map of Ancestors + fillAncestorsMap(aSubShape); } } // if ( !index ) @@ -856,6 +809,7 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape) { aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape); _mapSubMesh[index] = aSubMesh; + ClearMeshOrder(); } return aSubMesh; } @@ -1580,3 +1534,138 @@ SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID ) return aGroup; } +//============================================================================= +/*! + * \brief remove submesh order from Mesh + */ +//============================================================================= + +void SMESH_Mesh::ClearMeshOrder() +{ + _mySubMeshOrder.clear(); +} + +//============================================================================= +/*! + * \brief remove submesh order from Mesh + */ +//============================================================================= + +void SMESH_Mesh::SetMeshOrder(const TListOfListOfInt& theOrder ) +{ + _mySubMeshOrder = theOrder; +} + +//============================================================================= +/*! + * \brief return submesh order if any + */ +//============================================================================= + +const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const +{ + return _mySubMeshOrder; +} + +//============================================================================= +/*! + * \brief fillAncestorsMap + */ +//============================================================================= + +void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape) +{ + // fill _mapAncestors + int desType, ancType; + for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- ) + for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- ) + TopExp::MapShapesAndAncestors ( theShape, + (TopAbs_ShapeEnum) desType, + (TopAbs_ShapeEnum) ancType, + _mapAncestors ); +} + +//============================================================================= +/*! + * \brief sort submeshes according to stored mesh order + * \param theListToSort in out list to be sorted + * \return FALSE if nothing sorted + */ +//============================================================================= + +bool SMESH_Mesh::SortByMeshOrder(std::list& theListToSort) const +{ + if ( !_mySubMeshOrder.size() || theListToSort.size() < 2) + return true; + + bool res = false; + std::list onlyOrderedList; + // collect all ordered submeshes in one list as pointers + TListOfListOfInt::const_iterator listIddIt = _mySubMeshOrder.begin(); + for( ; listIddIt != _mySubMeshOrder.end(); listIddIt++) { + const TListOfInt& listOfId = *listIddIt; + TListOfInt::const_iterator idIt = listOfId.begin(); + for ( ; idIt != listOfId.end(); idIt++ ) { + map ::const_iterator i_sm = _mapSubMesh.find(*idIt); + if ( i_sm != _mapSubMesh.end() ) + onlyOrderedList.push_back(i_sm->second); + } + } + if (!onlyOrderedList.size()) + return res; + + std::list::iterator onlyBIt = onlyOrderedList.begin(); + std::list::iterator onlyEIt = onlyOrderedList.end(); + + // check positions where ordered submeshes should be in result list + std::set setOfPos; // remember positions of in set + std::list::const_iterator smIt = theListToSort.begin(); + int i = 0; + for( ; smIt != theListToSort.end(); i++, smIt++ ) + if ( find( onlyBIt, onlyEIt, *smIt ) != onlyEIt ) + setOfPos.insert(i); + + if ( !setOfPos.size() ) + return res; + + // new list of all submeshes to be sorted + std::list aNewList; + // iterates on submeshes and insert ordered in detected positions + for ( i = 0, smIt = theListToSort.begin(); smIt != theListToSort.end(); i++, smIt++ ) + if ( setOfPos.find( i ) != setOfPos.end() && + onlyBIt != onlyEIt ) { // position of ordered submesh detected + aNewList.push_back( *onlyBIt ); // ordered submesh + onlyBIt++; + } + else + aNewList.push_back( *smIt ); // other submesh from list + + theListToSort = aNewList; + return res; +} + +//============================================================================= +/*! + * \brief sort submeshes according to stored mesh order + * \param theListToSort in out list to be sorted + * \return FALSE if nothing sorted + */ +//============================================================================= + +std::list SMESH_Mesh::getAncestorsSubMeshes + (const TopoDS_Shape& theSubShape) const +{ + std::list listOfSubMesh; + TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape )); + for (; it.More(); it.Next() ) { + int index = _myMeshDS->ShapeToIndex(it.Value()); + map ::const_iterator i_sm = _mapSubMesh.find(index); + if (i_sm != _mapSubMesh.end()) + listOfSubMesh.push_back(i_sm->second); + } + + // sort submeshes according to stored mesh order + SortByMeshOrder( listOfSubMesh ); + + return listOfSubMesh; +} diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index 26339eb09..b93e8b5e7 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -40,8 +40,8 @@ #include #include -#include #include +#include class SMESH_Gen; class SMESHDS_Document; @@ -51,6 +51,9 @@ class SMESH_subMesh; class SMESH_HypoFilter; class TopoDS_Solid; +typedef std::list TListOfInt; +typedef std::list TListOfListOfInt; + class SMESH_EXPORT SMESH_Mesh { public: @@ -248,11 +251,26 @@ public: SMDSAbs_ElementType GetElementType( const int id, const bool iselem ); + void ClearMeshOrder(); + void SetMeshOrder(const TListOfListOfInt& theOrder ); + const TListOfListOfInt& GetMeshOrder() const; + + /*! + * \brief sort submeshes according to stored mesh order + * \param theListToSort in out list to be sorted + * \return FALSE if nothing sorted + */ + bool SortByMeshOrder(std::list& theListToSort) const; + // ostream& Dump(ostream & save); private: + + void fillAncestorsMap(const TopoDS_Shape& theShape); + std::list getAncestorsSubMeshes + (const TopoDS_Shape& theSubShape) const; protected: int _id; // id given by creator (unique within the creator instance) @@ -267,13 +285,15 @@ protected: std::map _mapSubMesh; std::map _mapGroup; SMESH_Gen * _gen; - + bool _isAutoColor; double _shapeDiagonal; //!< diagonal size of bounding box of shape to mesh TopTools_IndexedDataMapOfShapeListOfShape _mapAncestors; + TListOfListOfInt _mySubMeshOrder; + protected: SMESH_Mesh() {}; SMESH_Mesh(const SMESH_Mesh&) {}; diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index f7d2b403f..a0d0770d6 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -8975,6 +8975,7 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D() { const SMDS_MeshVolume* volume = vIt->next(); SMDS_VolumeTool vTool( volume ); + vTool.SetExternalNormal(); const bool isPoly = volume->IsPoly(); const bool isQuad = volume->IsQuadratic(); for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ ) @@ -8984,24 +8985,12 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D() vector nodes; int nbFaceNodes = vTool.NbFaceNodes(iface); const SMDS_MeshNode** faceNodes = vTool.GetFaceNodes(iface); - if (vTool.IsFaceExternal(iface)) - { - int inode = 0; - for ( ; inode < nbFaceNodes; inode += isQuad ? 2 : 1) + int inode = 0; + for ( ; inode < nbFaceNodes; inode += isQuad ? 2 : 1) + nodes.push_back(faceNodes[inode]); + if (isQuad) + for ( inode = 1; inode < nbFaceNodes; inode += 2) nodes.push_back(faceNodes[inode]); - if (isQuad) - for ( inode = 1; inode < nbFaceNodes; inode += 2) - nodes.push_back(faceNodes[inode]); - } - else - { - int inode = nbFaceNodes-1; - for ( ; inode >=0; inode -= isQuad ? 2 : 1) - nodes.push_back(faceNodes[inode]); - if (isQuad) - for ( inode = nbFaceNodes-2; inode >=0; inode -= 2) - nodes.push_back(faceNodes[inode]); - } // add new face based on volume nodes if (aMesh->FindFace( nodes ) ) diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 21d167518..b8615dcc2 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -2191,3 +2191,29 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS ( new _Iterator( new SMDS_mapIterator( DependsOn() ), prepend, append )); } } + +//================================================================================ +/*! + * \brief Find common submeshes (based on shared subshapes with other + * \param theOther submesh to check + * \param theSetOfCommon set of common submesh + */ +//================================================================================ + +bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther, + std::set& theSetOfCommon ) const +{ + int oldNb = theSetOfCommon.size(); + // check main submeshes + const map ::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 ::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(); +} diff --git a/src/SMESH/SMESH_subMesh.hxx b/src/SMESH/SMESH_subMesh.hxx index b086771ab..4dbf1795a 100644 --- a/src/SMESH/SMESH_subMesh.hxx +++ b/src/SMESH/SMESH_subMesh.hxx @@ -227,6 +227,15 @@ public: void SetIsAlwaysComputed(bool isAlCo); bool IsAlwaysComputed() { return _alwaysComputed; } + + /*! + * \brief Find common submeshes (based on shared subshapes with other + * \param theOther submesh to check + * \param theCommonIds set of common submesh IDs + * NOTE: this method does not cleat set before collect common IDs + */ + bool FindIntersection( const SMESH_subMesh * theOther, + std::set& theSetOfCommon ) const; protected: // ================================================================== diff --git a/src/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 769c86a54..394a31864 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -93,6 +93,8 @@ salomeinclude_HEADERS = \ SMESHGUI_MeshInfosBox.h \ SMESHGUI_Make2DFrom3DOp.h \ SMESHGUI_FindElemByPointDlg.h \ + SMESHGUI_MeshOrderDlg.h \ + SMESHGUI_MeshOrderOp.h \ SMESH_SMESHGUI.hxx # Libraries targets @@ -162,7 +164,9 @@ dist_libSMESH_la_SOURCES = \ SMESHGUI_GroupOnShapeDlg.cxx \ SMESHGUI_FileInfoDlg.cxx \ SMESHGUI_MeshInfosBox.cxx \ - SMESHGUI_Make2DFrom3DOp.cxx + SMESHGUI_Make2DFrom3DOp.cxx \ + SMESHGUI_MeshOrderDlg.cxx \ + SMESHGUI_MeshOrderOp.cxx MOC_FILES = \ SMESHGUI_moc.cxx \ @@ -218,7 +222,9 @@ MOC_FILES = \ SMESHGUI_MeshInfosBox_moc.cxx \ SMESHGUI_Make2DFrom3DOp_moc.cxx \ SMESHGUI_FindElemByPointDlg.cxx \ - SMESHGUI_FindElemByPointDlg_moc.cxx + SMESHGUI_FindElemByPointDlg_moc.cxx \ + SMESHGUI_MeshOrderDlg_moc.cxx \ + SMESHGUI_MeshOrderOp_moc.cxx nodist_libSMESH_la_SOURCES= \ $(MOC_FILES) diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 34f6ed0d9..1b84f9acf 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -49,6 +49,7 @@ #include "SMESHGUI_MakeNodeAtPointDlg.h" #include "SMESHGUI_MeshInfosDlg.h" #include "SMESHGUI_MeshOp.h" +#include "SMESHGUI_MeshOrderOp.h" #include "SMESHGUI_MeshPatternDlg.h" #include "SMESHGUI_MoveNodesDlg.h" #include "SMESHGUI_MultiEditDlg.h" @@ -1627,6 +1628,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 701: // COMPUTE MESH case 711: // PRECOMPUTE MESH case 712: // EVALUATE MESH + case 713: // MESH ORDER { if (checkLock(aStudy)) break; startOperation( theCommandID ); @@ -2722,6 +2724,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 710, "BUILD_COMPOUND", "ICON_BUILD_COMPOUND" ); createSMESHAction( 711, "PRECOMPUTE", "ICON_PRECOMPUTE" ); createSMESHAction( 712, "EVALUATE", "ICON_COMPUTE" ); + createSMESHAction( 713, "MESH_ORDER", "ICON_COMPUTE" ); createSMESHAction( 806, "CREATE_GEO_GROUP","ICON_CREATE_GEO_GROUP" ); createSMESHAction( 801, "CREATE_GROUP", "ICON_CREATE_GROUP" ); createSMESHAction( 802, "CONSTRUCT_GROUP", "ICON_CONSTRUCT_GROUP" ); @@ -2871,6 +2874,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 701, meshId, -1 ); createMenu( 711, meshId, -1 ); createMenu( 712, meshId, -1 ); + createMenu( 713, meshId, -1 ); createMenu( separator(), meshId, -1 ); createMenu( 801, meshId, -1 ); createMenu( 806, meshId, -1 ); @@ -2976,6 +2980,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( 701, meshTb ); createTool( 711, meshTb ); createTool( 712, meshTb ); + createTool( 713, meshTb ); createTool( separator(), meshTb ); createTool( 801, meshTb ); createTool( 806, meshTb ); @@ -3107,7 +3112,8 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->insert( separator(), -1, 0 ); createPopupItem( 701, OB, mesh, "&& isComputable" ); // COMPUTE createPopupItem( 711, OB, mesh, "&& isComputable && isPreComputable" ); // PRECOMPUTE - createPopupItem( 712, OB, mesh, "&& isComputable" ); // COMPUTE + createPopupItem( 712, OB, mesh, "&& isComputable" ); // EVALUATE + createPopupItem( 713, OB, mesh, "&& isComputable" ); // MESH ORDER createPopupItem( 214, OB, mesh_group ); // UPDATE createPopupItem( 900, OB, mesh_group ); // ADV_INFO createPopupItem( 902, OB, mesh ); // STD_INFO @@ -3934,6 +3940,9 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const case 712: // Evaluate mesh op = new SMESHGUI_EvaluateOp(); break; + case 713: // Evaluate mesh + op = new SMESHGUI_MeshOrderOp(); + break; case 806: // Create group on geom op = new SMESHGUI_GroupOnShapeOp(); break; diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 43bd2cdc9..004b18496 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -32,6 +32,9 @@ #include "SMESHGUI_MeshInfosBox.h" #include "SMESHGUI_HypothesesUtils.h" #include "SMESHGUI_MeshEditPreview.h" +#include "SMESHGUI_MeshOrderOp.h" +#include "SMESHGUI_MeshOrderDlg.h" + #include "SMESH_ActorUtils.h" #include @@ -1218,6 +1221,7 @@ LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const SMESHGUI_PrecomputeOp::SMESHGUI_PrecomputeOp() : SMESHGUI_BaseComputeOp(), myDlg( 0 ), + myOrderMgr( 0 ), myActiveDlg( 0 ), myPreviewDisplayer( 0 ) { @@ -1234,6 +1238,8 @@ SMESHGUI_PrecomputeOp::~SMESHGUI_PrecomputeOp() { delete myDlg; myDlg = 0; + delete myOrderMgr; + myOrderMgr = 0; myActiveDlg = 0; if ( myPreviewDisplayer ) delete myPreviewDisplayer; @@ -1299,6 +1305,16 @@ void SMESHGUI_PrecomputeOp::startOperation() if (myMesh->_is_nil()) return; + if (myDlg->getPreviewMode() == -1) + { + // nothing to preview + SUIT_MessageBox::warning(desktop(), + tr("SMESH_WRN_WARNING"), + tr("SMESH_WRN_NOTHING_PREVIEW")); + onCancel(); + return; + } + // disconnect slot from preview dialog to have Apply from results of compute operation only disconnect( myDlg, SIGNAL( dlgOk() ), this, SLOT( onOk() ) ); disconnect( myDlg, SIGNAL( dlgApply() ), this, SLOT( onApply() ) ); @@ -1363,6 +1379,15 @@ void SMESHGUI_PrecomputeOp::initDialog() modes.append( SMESH::DIM_1D ); } + myOrderMgr = new SMESHGUI_MeshOrderMgr( myDlg->getMeshOrderBox() ); + myOrderMgr->SetMesh( myMesh ); + bool isOrder = myOrderMgr->GetMeshOrder(myPrevOrder); + myDlg->getMeshOrderBox()->setShown(isOrder); + if ( !isOrder ) { + delete myOrderMgr; + myOrderMgr = 0; + } + myDlg->setPreviewModes( modes ); } @@ -1423,6 +1448,8 @@ void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh, void SMESHGUI_PrecomputeOp::onCompute() { myDlg->hide(); + if (myOrderMgr && myOrderMgr->IsOrderChanged()) + myOrderMgr->SetMeshOrder(); myMapShapeId.clear(); myActiveDlg = computeDlg(); computeMesh(); @@ -1444,6 +1471,7 @@ void SMESHGUI_PrecomputeOp::onCancel() return; } + bool isRestoreOrder = false; if ( myActiveDlg == myDlg && !myMesh->_is_nil() && myMapShapeId.count() ) { // ask to remove already computed mesh elements @@ -1455,8 +1483,24 @@ void SMESHGUI_PrecomputeOp::onCancel() QMap::const_iterator it = myMapShapeId.constBegin(); for ( ; it != myMapShapeId.constEnd(); ++it ) myMesh->ClearSubMesh( *it ); + isRestoreOrder = true; } } + + // return previous mesh order + if (myOrderMgr && myOrderMgr->IsOrderChanged()) { + if (!isRestoreOrder) + isRestoreOrder = + (SUIT_MessageBox::question( desktop(), tr( "SMESH_WARNING" ), + tr( "SMESH_REJECT_MESH_ORDER" ), + tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 0, 1 ) == 0); + if (isRestoreOrder) + myOrderMgr->SetMeshOrder(myPrevOrder); + } + + delete myOrderMgr; + myOrderMgr = 0; + myMapShapeId.clear(); SMESHGUI_BaseComputeOp::onCancel(); } @@ -1475,6 +1519,11 @@ void SMESHGUI_PrecomputeOp::onPreview() _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh); if ( !aMeshSObj ) return; + + // set modified submesh priority if any + if (myOrderMgr && myOrderMgr->IsOrderChanged()) + myOrderMgr->SetMeshOrder(); + // Compute preview of mesh, // i.e. compute mesh till indicated dimension int dim = myDlg->getPreviewMode(); @@ -1579,7 +1628,8 @@ void SMESHGUI_PrecomputeOp::onPreview() //================================================================================ SMESHGUI_PrecomputeDlg::SMESHGUI_PrecomputeDlg( QWidget* parent ) - : SMESHGUI_Dialog( parent, false, false, OK | Cancel | Help ) + : SMESHGUI_Dialog( parent, false, false, OK | Cancel | Help ), + myOrderBox(0) { setWindowTitle( tr( "CAPTION" ) ); @@ -1588,6 +1638,9 @@ SMESHGUI_PrecomputeDlg::SMESHGUI_PrecomputeDlg( QWidget* parent ) QVBoxLayout* layout = new QVBoxLayout( main ); + myOrderBox = new SMESHGUI_MeshOrderBox( main ); + layout->addWidget(myOrderBox); + QFrame* frame = new QFrame( main ); layout->setMargin(0); layout->setSpacing(0); layout->addWidget( frame ); @@ -1644,6 +1697,17 @@ int SMESHGUI_PrecomputeDlg::getPreviewMode() const return myPreviewMode->currentId(); } +//================================================================================ +/*! + * \brief Returns current preview mesh mode +*/ +//================================================================================ + +SMESHGUI_MeshOrderBox* SMESHGUI_PrecomputeDlg::getMeshOrderBox() const +{ + return myOrderBox; +} + //================================================================================ /*! diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.h b/src/SMESHGUI/SMESHGUI_ComputeDlg.h index bc979d3fa..ab64b33e3 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.h +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.h @@ -36,6 +36,7 @@ // Qt includes #include +#include #include #include @@ -136,6 +137,8 @@ protected: protected slots: }; +class SMESHGUI_MeshOrderMgr; + /*! * \brief Operation to preview and compute a mesh and show computation errors */ @@ -170,10 +173,16 @@ private slots: void onCompute(); private: + //! private fields QMap< int, int > myMapShapeId; QPointer myActiveDlg; QPointer myDlg; SMESHGUI_MeshEditPreview* myPreviewDisplayer; + //! fields for mesh order + typedef QList TListOfInt; + typedef QList TListOfListOfInt; + TListOfListOfInt myPrevOrder; + SMESHGUI_MeshOrderMgr* myOrderMgr; }; /*! @@ -227,6 +236,8 @@ protected: friend class SMESHGUI_PrecomputeOp; }; +class SMESHGUI_MeshOrderBox; + /*! * \brief Dialog to preview and compute a mesh and show computation errors */ @@ -241,11 +252,14 @@ public: void setPreviewModes( const QList& ); int getPreviewMode() const; + + SMESHGUI_MeshOrderBox* getMeshOrderBox() const; signals: void preview(); private: + SMESHGUI_MeshOrderBox* myOrderBox; QPushButton* myPreviewBtn; QtxComboBox* myPreviewMode; }; diff --git a/src/SMESHGUI/SMESHGUI_MeshOrderDlg.cxx b/src/SMESHGUI/SMESHGUI_MeshOrderDlg.cxx new file mode 100644 index 000000000..2e4d7d09d --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_MeshOrderDlg.cxx @@ -0,0 +1,332 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// File : SMESHGUI_MeshOrderDlg.cxx +// Author : Pavel TELKOV, Open CASCADE S.A.S. +// SMESH includes +// +#include "SMESHGUI_MeshOrderDlg.h" + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPACING 6 +#define MARGIN 11 + +/*! + * Enumeartion of list widget item types (mesh name or separator) + */ +enum MeshOrderItemType { MeshItem = QListWidgetItem::UserType, SeparatorItem }; + +// ========================================================================================= +/*! + * \brief Constructor + */ +// ========================================================================================= + +SMESHGUI_MeshOrderBox::SMESHGUI_MeshOrderBox(QWidget* theParent) +: QGroupBox( theParent ), myIsChanged( false ), myUpBtn(0), myDownBtn(0) +{ + QHBoxLayout* hBoxLayout = new QHBoxLayout(this); + hBoxLayout->setMargin( MARGIN ); + hBoxLayout->setSpacing( SPACING ); + + myMeshNames = new QListWidget(this); + myMeshNames->setSelectionMode(QAbstractItemView::SingleSelection); + myMeshNames->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding )); + hBoxLayout->addWidget(myMeshNames); + + QGroupBox* btnGrp = new QGroupBox(this); + hBoxLayout->addWidget(btnGrp); + + myUpBtn = new QToolButton(btnGrp); + myDownBtn = new QToolButton(btnGrp); + myUpBtn-> setArrowType( Qt::UpArrow ); + myDownBtn->setArrowType( Qt::DownArrow ); + + QVBoxLayout* vBoxLayout = new QVBoxLayout(btnGrp); + vBoxLayout->addSpacerItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ) ); + vBoxLayout->addWidget( myUpBtn ); + vBoxLayout->addWidget( myDownBtn ); + vBoxLayout->addSpacerItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ) ); + + connect( myUpBtn, SIGNAL( clicked() ), this, SLOT( onMoveItem() ) ); + connect( myDownBtn, SIGNAL( clicked() ), this, SLOT( onMoveItem() ) ); + connect( myMeshNames, SIGNAL( itemSelectionChanged() ), this, SLOT( onSelectionChanged() ) ); + + onSelectionChanged(); +} + +// ========================================================================================= +/*! + * \brief Destructor + */ +//======================================================================= + +SMESHGUI_MeshOrderBox::~SMESHGUI_MeshOrderBox() +{ +} + +// ========================================================================================= +/*! + * \brief add separator item + */ +// ========================================================================================= + +static void addSeparator( QListWidget* theList ) +{ + QListWidgetItem* item = new QListWidgetItem( theList, SeparatorItem ); + QFrame* hline = new QFrame( theList ); + hline->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + theList->addItem( item ); + theList->setItemWidget( item, hline ); +} + +// ========================================================================================= +/*! + * \brief add sub-mesh item + */ +// ========================================================================================= + +static void addMeshItem( QListWidget* theList, + const QString& theName, + const int theId ) +{ + QListWidgetItem* item = new QListWidgetItem( theName, theList, MeshItem ); + item->setData( Qt::UserRole, theId ); + theList->addItem( item ); +} + +// ========================================================================================= +/*! + * \brief Clear submesh names and indeces + */ +// ========================================================================================= + +void SMESHGUI_MeshOrderBox::Clear() +{ + myMeshNames->clear(); + myIsChanged = false; +} + +// ========================================================================================= +/*! + * \brief Set submesh names and indeces + */ +// ========================================================================================= + +void SMESHGUI_MeshOrderBox::SetMeshes(const ListListName& theMeshNames, + const ListListId& theMeshIds) +{ + Clear(); + ListListName::const_iterator nLIt = theMeshNames.constBegin(); + ListListId::const_iterator idLIt = theMeshIds.constBegin(); + for ( ; nLIt != theMeshNames.constEnd(); ++nLIt, ++idLIt ) + { + const QStringList& names = (*nLIt); + const QList& ids = (*idLIt); + if ( myMeshNames->count() ) + addSeparator( myMeshNames ); + QStringList::const_iterator nameIt = names.constBegin(); + QList::const_iterator idIt = ids.constBegin(); + for ( ; nameIt != names.constEnd(); ++nameIt, ++idIt ) + addMeshItem( myMeshNames, *nameIt, *idIt ); + } +} + +// ========================================================================================= +/*! + * \brief cehck that item exists and not a separator + */ +// ========================================================================================= + +static bool checkItem(QListWidgetItem* theItem) +{ + return theItem && (int)theItem->type() != (int)SeparatorItem; +} + +// ========================================================================================= +/*! + * \brief Returns result (ordered by user) mesh names + */ +// ========================================================================================= + +ListListId SMESHGUI_MeshOrderBox::GetMeshIds() const +{ + ListListId aLLIds; + aLLIds.append( QList() ); + for ( int i = 0, n = myMeshNames->count(); i < n; i++ ) + { + QListWidgetItem* it = myMeshNames->item( i ); + if (checkItem( it )) + aLLIds.last().append( it->data( Qt::UserRole ).toInt() ); + else // separator before next list of mesh items + aLLIds.append( QList() ); + } + return aLLIds; +} + +// ========================================================================================= +/*! + * \brief Returns result (ordered by user) mesh indeces + */ +// ========================================================================================= + +ListListName SMESHGUI_MeshOrderBox::GetMeshNames() const +{ + ListListName aLLNames; + aLLNames.append( QStringList() ); + for ( int i = 0, n = myMeshNames->count(); i < n; i++ ) + { + QListWidgetItem* it = myMeshNames->item( i ); + if (checkItem( it )) + aLLNames.last().append( it->text() ); + else // separator before next list of mesh items + aLLNames.append( QStringList() ); + } + return aLLNames; +} + +// ========================================================================================= +/*! + * \brief update state of arrow buttons according to selection + */ +// ========================================================================================= + +void SMESHGUI_MeshOrderBox::onSelectionChanged() +{ + bool isUp = false; + bool isDown = false; + QList items = myMeshNames->selectedItems(); + if ( !items.isEmpty() ) + { + QListWidgetItem* selItem = (*(items.begin())); + if (checkItem(selItem)) + { + const int rowId = myMeshNames->row( selItem ); + isUp = checkItem( myMeshNames->item( rowId - 1 ) ); + isDown = checkItem( myMeshNames->item( rowId + 1 ) ); + } + } + myUpBtn-> setEnabled( isUp ); + myDownBtn->setEnabled( isDown ); +} + +// ========================================================================================= +/*! + * \brief move item according to clicked arrow button + */ +// ========================================================================================= + +void SMESHGUI_MeshOrderBox::onMoveItem() +{ + moveItem( sender() == myUpBtn ); +} + +// ========================================================================================= +/*! + * \brief move mesh in order up or down + */ +// ========================================================================================= + +void SMESHGUI_MeshOrderBox::moveItem(const bool theIsUp) +{ + // move selected list item up or down + QList items = myMeshNames->selectedItems(); + if ( items.isEmpty() ) + return; + QListWidgetItem * selItem = (*(items.begin())); + if (!checkItem(selItem)) + return; + int rowId = myMeshNames->row( selItem ); + if ( rowId == -1 ) + return; + + // move item in list widget + myIsChanged = true; + myMeshNames->takeItem( rowId ); + myMeshNames->insertItem(theIsUp ? rowId-1 : rowId+1, selItem ); + + // restore selection and current status + selItem->setSelected( true ); + myMeshNames->setCurrentItem( selItem ); +} + +// ========================================================================================= +/*! + * \brief returns status is order changed by user + */ +// ========================================================================================= + +bool SMESHGUI_MeshOrderBox:: IsOrderChanged() const +{ + return myIsChanged; +} + +// ========================================================================================= +/*! + * \brief Constructor + */ +// ========================================================================================= + +SMESHGUI_MeshOrderDlg::SMESHGUI_MeshOrderDlg(QWidget* theParent) +: SMESHGUI_Dialog( theParent, false, false, OK | Cancel | Help ) +{ + setWindowTitle( tr( "SMESH_MESHORDER_TITLE") ); + QFrame* main = mainFrame(); + + QVBoxLayout* aDlgLay = new QVBoxLayout (main); + aDlgLay->setMargin( 0 ); + aDlgLay->setSpacing( SPACING ); + + myBox = new SMESHGUI_MeshOrderBox( main ); + + aDlgLay->addWidget(myBox); + aDlgLay->setStretchFactor(main, 1); +} + +// ========================================================================================= +/*! + * \brief Destructor + */ +// ========================================================================================= + +SMESHGUI_MeshOrderDlg::~SMESHGUI_MeshOrderDlg() +{ +} + +// ========================================================================================= +/*! + * \brief return Box widget to show mesh order + */ +// ========================================================================================= + +SMESHGUI_MeshOrderBox* SMESHGUI_MeshOrderDlg::GetMeshOrderBox() const +{ + return myBox; +} diff --git a/src/SMESHGUI/SMESHGUI_MeshOrderDlg.h b/src/SMESHGUI/SMESHGUI_MeshOrderDlg.h new file mode 100644 index 000000000..53ad8a960 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_MeshOrderDlg.h @@ -0,0 +1,114 @@ +// Copyright (C) 2007-2009 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// File : SMESHGUI_MeshOrderDlg.h +// Author : Pavel TELKOV, Open CASCADE S.A.S. +// +#ifndef SMESHGUI_MeshOrderDlg_H +#define SMESHGUI_MeshOrderDlg_H + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" +#include "SMESHGUI_Dialog.h" + +// Qt includes +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) + +class QToolButton; +class QListWidget; + +typedef QList ListListName; +typedef QList ListId; +typedef QList ListListId; + +/*! + * \brief Reusable widget that shows and allows modify meshing order + */ + +class SMESHGUI_EXPORT SMESHGUI_MeshOrderBox : public QGroupBox +{ + Q_OBJECT + + public: + /*! Public methods */ + SMESHGUI_MeshOrderBox( QWidget* ); + ~SMESHGUI_MeshOrderBox(); + + //! Clear mesh box + void Clear(); + + //! Set mesh (submesh) names and indeces + void SetMeshes(const ListListName& theMeshNames, + const ListListId& theMeshIds); + + //! returns status is order changed by user + bool IsOrderChanged() const; + + //! Returns result (ordered by user) mesh names + ListListId GetMeshIds() const; + //! Returns result (ordered by user) mesh indeces + ListListName GetMeshNames() const; + + private slots: + /*! Private slots */ + //! update state of arrow buttons according to selection + void onSelectionChanged(); + //! move item according to clicked arrow button + void onMoveItem(); + + private: + /*! Privatemethods */ + //! move mesh in order up or down + void moveItem(const bool theIsUp); + + private: + /*! Private fields */ + bool myIsChanged; + QToolButton* myUpBtn; + QToolButton* myDownBtn; + QListWidget* myMeshNames; +}; + +/*! + * \brief Dialog contains mesh order box for modification operation + */ + +class SMESHGUI_EXPORT SMESHGUI_MeshOrderDlg : public SMESHGUI_Dialog +{ + Q_OBJECT + + public: + /*! Public methods */ + SMESHGUI_MeshOrderDlg( QWidget* ); + ~SMESHGUI_MeshOrderDlg(); + + SMESHGUI_MeshOrderBox* GetMeshOrderBox() const; + + private: + /*! Private fields */ + SMESHGUI_MeshOrderBox* myBox; +}; + +#endif // SMESHGUI_MeshOrderDlg_H diff --git a/src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx b/src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx new file mode 100644 index 000000000..00b63da3a --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx @@ -0,0 +1,325 @@ +// Copyright (C) 2007-2009 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// File : SMESHGUI_MeshOrderOp.cxx +// Author : Pavel TELKOV, Open CASCADE S.A.S. +// + +#include "SMESHGUI_MeshOrderOp.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_Utils.h" +#include "SMESHGUI_MeshUtils.h" + +// SALOME GUI includes +#include +#include +#include +#include +#include +#include + +// SALOME KERNEL includes +#include +#include + +// STL includes +#include + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_MeshOrderOp::SMESHGUI_MeshOrderOp() + : SMESHGUI_Operation(), myDlg(0), myMgr(0) +{ + myDlg = new SMESHGUI_MeshOrderDlg( desktop() ); + + myHelpFileName = "constructing_meshes_page.html#mesh_order_anchor"; +} + +//================================================================================ +/*! + * \brief Destructor +*/ +//================================================================================ + +SMESHGUI_MeshOrderOp::~SMESHGUI_MeshOrderOp() +{ +} + +//================================================================================ +/*! + * \brief Return operation dialog + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_MeshOrderOp::dlg() const +{ + return myDlg; +} + +//================================================================================ +/*! + * \brief perform it's intention action: compute 2D mesh on 3D + */ +//================================================================================ + +void SMESHGUI_MeshOrderOp::startOperation() +{ + SMESHGUI_Operation::startOperation(); + if (myMgr) + myDlg->show(); +} + +//================================================================================ +/*! + * \brief Init dialog and mesh order box + */ +//================================================================================ + +void SMESHGUI_MeshOrderOp::initDialog() +{ + if (!myDlg ) + return; + + SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_nil(); + // check selection + LightApp_SelectionMgr *Sel = selectionMgr(); + SALOME_ListIO selected; Sel->selectedObjects( selected ); + + if (selected.Extent() == 1) + aMesh = SMESH::GetMeshByIO(selected.First()); + if (aMesh->_is_nil()) { + SUIT_MessageBox::warning(desktop(), + tr("SMESH_WRN_WARNING"), + tr("SMESH_WRN_NO_AVAILABLE_DATA")); + onCancel(); + return; + } + + myMgr = new SMESHGUI_MeshOrderMgr( myDlg->GetMeshOrderBox() ); + myMgr->SetMesh( aMesh ); + if ( !myMgr->GetMeshOrder() ) { + SUIT_MessageBox::information(desktop(), + tr("SMESH_INFORMATION"), + tr("SMESH_NO_CONCURENT_MESH")); + + onCancel(); + return; + } +} + +//================================================================================ +/*! + * \brief Apply changes + */ +//================================================================================ + +bool SMESHGUI_MeshOrderOp::onApply() +{ + SUIT_OverrideCursor aWaitCursor; + bool res = myMgr ? myMgr->SetMeshOrder() : false; + + delete myMgr; + myMgr = 0; + + return res; +} + +//================================================================================ +/*! + * \brief Apply changes + */ +//================================================================================ + +void SMESHGUI_MeshOrderOp::onCancel() +{ + delete myMgr; + myMgr = 0; + + abort(); +} + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_MeshOrderMgr::SMESHGUI_MeshOrderMgr( SMESHGUI_MeshOrderBox* theBox ) +: myBox( theBox ) +{ + myMesh = SMESH::SMESH_Mesh::_nil(); +} + +//================================================================================ +/*! + * \brief Destructor +*/ +//================================================================================ + +SMESHGUI_MeshOrderMgr::~SMESHGUI_MeshOrderMgr() +{ +} + +//================================================================================ +/*! + * \brief Set root mesh object + */ +//================================================================================ + +void SMESHGUI_MeshOrderMgr::SetMesh(SMESH::SMESH_Mesh_var& theMesh) +{ + myMesh = SMESH::SMESH_Mesh::_duplicate(theMesh); + _PTR(SObject) aMeshSObj = SMESH::FindSObject(theMesh); + if ( myBox && aMeshSObj ) + myBox->setTitle( aMeshSObj->GetName().c_str() ); +} + +//================================================================================ +/*! + * \brief Check for concurents between submesh objects + */ +//================================================================================ + +bool SMESHGUI_MeshOrderMgr::GetMeshOrder() +{ + ListListId idListList; + return GetMeshOrder(idListList); +} + +//================================================================================ +/*! + * \brief Check for concurents between submesh objects + */ +//================================================================================ + +bool SMESHGUI_MeshOrderMgr::GetMeshOrder(ListListId& theIdListList) +{ + if (!myBox || myMesh->_is_nil()) + return false; + myBox->Clear(); + SMESH::submesh_array_array_var meshOrder = myMesh->GetMeshOrder(); + if ( !meshOrder.operator->() || !meshOrder->length() ) + return false; + ListListName nameListList; + for ( int i = 0, n = meshOrder->length(); i < n; i++ ) + { + QList idList; + QStringList nameList; + const SMESH::submesh_array& aSMArray = meshOrder[i]; + for ( int j = 0, jn = aSMArray.length(); j < jn; j++ ) + { + const SMESH::SMESH_subMesh_var subMesh = aSMArray[j]; + + _PTR(SObject) aSubMeshSObj = SMESH::FindSObject(subMesh); + if ( !aSubMeshSObj ) + continue; + + idList.append(subMesh->GetId() ); + nameList.append( QString(aSubMeshSObj->GetName().c_str()) ); + } + theIdListList.append(idList); + nameListList.append(nameList); + } + myBox->SetMeshes(nameListList, theIdListList); + return !theIdListList.isEmpty(); +} + +//================================================================================ +/*! + * \brief Returns status is order changed by user + */ +//================================================================================ + +bool SMESHGUI_MeshOrderMgr::IsOrderChanged() const +{ + return myBox && myBox->IsOrderChanged(); +} + +//================================================================================ +/*! + * \brief Store submesh priority order + */ +//================================================================================ + +bool SMESHGUI_MeshOrderMgr::SetMeshOrder() +{ + return myBox ? SetMeshOrder(myBox->GetMeshIds()) : false; +} + +//================================================================================ +/*! + * \brief Store submesh priority order + */ +//================================================================================ + +bool SMESHGUI_MeshOrderMgr::SetMeshOrder( const ListListId& theListListIds ) +{ + if (theListListIds.isEmpty() || myMesh->_is_nil()) + return false; + + _PTR(Study) aStudy = SMESH::GetActiveStudyDocument(); + _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh); + if ( !aStudy || !aMeshSObj ) + return false; + + std::map mapOfSubMesh; + for (int i = SMESH::Tag_FirstSubMesh; i <= SMESH::Tag_LastSubMesh; i++) { + _PTR(SObject) aSubmeshRoot; + if ( !aMeshSObj->FindSubObject( i, aSubmeshRoot ) ) + continue; + _PTR(ChildIterator) smIter = aStudy->NewChildIterator( aSubmeshRoot ); + for ( ; smIter->More(); smIter->Next() ) { + _PTR(SObject) aSmObj = smIter->Value(); + SMESH::SMESH_subMesh_var sm = + SMESH::SObjectToInterface( aSmObj ); + mapOfSubMesh[ sm->GetId() ] = SMESH::SMESH_subMesh::_duplicate(sm); + } + } + + // is it enought to set modifid attribute on root mesh objects only? + // it is seems that modifaction flag will be set on child submeshes + // automatically (see SMESH::ModifiedMesh for details) + SMESH::ModifiedMesh( aMeshSObj, false, false ); + + SMESH::submesh_array_array_var meshOrder = new SMESH::submesh_array_array(); + meshOrder->length(theListListIds.count() ); + ListListId::const_iterator it = theListListIds.constBegin(); + for ( int i = 0; it != theListListIds.constEnd(); ++it ) { + const QList& ids = *it; + SMESH::submesh_array_var subMeshList = new SMESH::submesh_array(); + subMeshList->length( ids.count() ); + QList::const_iterator subIt = ids.constBegin(); + for( int j = 0; subIt != ids.constEnd(); ++subIt ) + if ( mapOfSubMesh.find( *subIt ) != mapOfSubMesh.end() ) + subMeshList[ j++ ] = mapOfSubMesh[ *subIt ]; + + meshOrder[ i++ ] = subMeshList; + } + // update object browser + SMESHGUI::GetSMESHGUI()->updateObjBrowser( true, 0 ); + + return myMesh->SetMeshOrder(meshOrder); +} diff --git a/src/SMESHGUI/SMESHGUI_MeshOrderOp.h b/src/SMESHGUI/SMESHGUI_MeshOrderOp.h new file mode 100644 index 000000000..9c6d6f9ad --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_MeshOrderOp.h @@ -0,0 +1,96 @@ +// Copyright (C) 2007-2009 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// File : SMESHGUI_MeshOrderOp.h +// Author : Pavel TELKOV, Open CASCADE S.A.S. +// + +#ifndef SMESHGUI_MeshOrderOp_H +#define SMESHGUI_MeshOrderOp_H + + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" + +#include "SMESHGUI_Operation.h" +#include "SMESHGUI_MeshOrderDlg.h" + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Gen) +#include CORBA_SERVER_HEADER(SMESH_Mesh) + +/*! + * \brief Operator to check and modify mesh computation submesh priority (order) + */ +class SMESHGUI_EXPORT SMESHGUI_MeshOrderMgr +{ +public: + SMESHGUI_MeshOrderMgr( SMESHGUI_MeshOrderBox* ); + virtual ~SMESHGUI_MeshOrderMgr(); + //! Set root mesh object + void SetMesh( SMESH::SMESH_Mesh_var& theMesh ); + //! Check for concurents between submesh objects + bool GetMeshOrder(); + //! Check for concurents between submesh objects + bool GetMeshOrder( ListListId& theIds ); + //! Store submesh priority order + bool SetMeshOrder(); + //! Store given submesh priority order + bool SetMeshOrder( const ListListId& theIds ); + + //! Returns status is order changed by user + bool IsOrderChanged() const; + +private: + SMESH::SMESH_Mesh_var myMesh; + SMESHGUI_MeshOrderBox* myBox; +}; + +/*! + * \brief Operator to check and modify mesh computation submesh priority (order) + */ +class SMESHGUI_EXPORT SMESHGUI_MeshOrderOp: public SMESHGUI_Operation +{ + Q_OBJECT + +public: + SMESHGUI_MeshOrderOp(); + virtual ~SMESHGUI_MeshOrderOp(); + +protected: + virtual LightApp_Dialog* dlg() const; + + virtual void startOperation(); + + //! sets the dialog widgets to state just after operation start + virtual void initDialog(); + + protected slots: + virtual bool onApply(); + virtual void onCancel(); + + private: + SMESHGUI_MeshOrderDlg* myDlg; + SMESHGUI_MeshOrderMgr* myMgr; +}; + +#endif // SMESHGUI_MeshOrderOp_H diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index d65356f47..7a604d10a 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -205,6 +205,10 @@ MEN_2D_FROM_3D Create 2D mesh from 3D + + MEN_MESH_ORDER + Change submesh priority + MEN_CREATE_GROUP Create Group @@ -2063,6 +2067,10 @@ Consider saving your work before application crash STB_2D_FROM_3D Create 2D mesh from 3D + + STB_MESH_ORDER + Change submesh priority + STB_CREATE_GROUP Create Group @@ -2569,6 +2577,10 @@ Consider saving your work before application crash TOP_2D_FROM_3D Create 2D mesh from 3D + + TOP_MESH_ORDER + Change submesh priority + TOP_CREATE_GROUP Create Group @@ -3379,6 +3391,15 @@ Please, create VTK viewer and try again created during preview operation. Do you want to remove all this submeshes? + + SMESH_WRN_NOTHING_PREVIEW + No mesh preview is available + + + SMESH_REJECT_MESH_ORDER + The submesh priority changed during preview operation. +Do you want to restore original submesh priority? + SMESHGUI_ConvToQuadDlg @@ -4899,4 +4920,18 @@ It is impossible to read point coordinates from file Create Groups from Geometry + + SMESHGUI_MeshOrderDlg + + SMESH_MESHORDER_TITLE + Order of submesh in meshing process + + + + SMESHGUI_MeshOrderOp + + SMESH_NO_CONCURENT_MESH + No concurent submeshes detected + + diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 8d3cacc13..42358009e 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -261,6 +261,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand ); myObjects.insert( make_pair( subMeshID, subMesh )); } + id_mesh->second->Process( aCommand ); return aCommand; } @@ -885,6 +886,34 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // remove hyp from myHypos myHypos.remove( hyp ); } + // check for SubMesh order commands + else if ( theCommand->GetMethod() == "GetMeshOrder" || + theCommand->GetMethod() == "SetMeshOrder" ) { + // In fact arguments and result values does not support complex containers + // such as list of list + // So, here we parse it manually + // GetMeshOrder + //for(int ind = 0, n = theCommand->GetNbResultValues();indFindSubMesh( theCommand->GetResultValue(ind) ); + // SetMeshOrder + //for(int ind = 0, n = theCommand->GetNbArgs();indFindSubMesh( theCommand->GetArg(ind) ); + const bool isArg = theCommand->GetMethod() == "SetMeshOrder"; + const TCollection_AsciiString& cmdStr = theCommand->GetString(); + int begPos = (/*isArg ? cmdStr.Search( "(" ) :*/ cmdStr.Search( "[" )) + 1; + int endPos = (isArg ? cmdStr.Search( ")" ) : cmdStr.Search( "=" )) - 1; + if ( begPos != -1 && begPos < endPos && endPos <= cmdStr.Length() ) { + TCollection_AsciiString aSubStr = cmdStr.SubString( begPos, endPos ); + Standard_Integer index = 1; + TCollection_AsciiString anIDStr = aSubStr.Token("\t ,[]", index++); + while ( !anIDStr.IsEmpty() ) { + Handle(_pySubMesh) subMesh = theGen->FindSubMesh( anIDStr ); + if ( !subMesh.IsNull() ) + subMesh->Process( theCommand ); + anIDStr = aSubStr.Token("\t ,[]", index++); + } + } + } // add accessor method if necessary else { @@ -919,7 +948,7 @@ bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand ) "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes", "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces", "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor", - "Clear", "ConvertToStandalone" + "Clear", "ConvertToStandalone", "GetMeshOrder", "SetMeshOrder" ,"" }; // <- mark of end sameMethods.Insert( names ); } diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 899581804..f33cce68f 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -2722,6 +2722,40 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, //if ( shapeRefFound ) //myWriter.AddAllSubMeshes(); + // store submesh order if any + const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder(); + if ( theOrderIds.size() ) { + char order_list[ 30 ]; + strcpy( order_list, "Mesh Order" ); + // count number of submesh ids + int nbIDs = 0; + TListOfListOfInt::const_iterator idIt = theOrderIds.begin(); + for ( ; idIt != theOrderIds.end(); idIt++ ) + nbIDs += (*idIt).size(); + // number of values = number of IDs + + // number of lists (for separators) - 1 + int* smIDs = new int [ nbIDs + theOrderIds.size() - 1 ]; + idIt = theOrderIds.begin(); + for ( int i = 0; idIt != theOrderIds.end(); idIt++ ) { + const TListOfInt& idList = *idIt; + if (idIt != theOrderIds.begin()) // not first list + smIDs[ i++ ] = -1/* *idList.size()*/; // separator between lists + // dump submesh ids from current list + TListOfInt::const_iterator id_smId = idList.begin(); + for( ; id_smId != idList.end(); id_smId++ ) + smIDs[ i++ ] = *id_smId; + } + // write HDF group + aSize[ 0 ] = nbIDs + theOrderIds.size() - 1; + + aDataset = new HDFdataset( order_list, aTopGroup, HDF_INT32, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( smIDs ); + aDataset->CloseOnDisk(); + // + delete[] smIDs; + } + // groups root sub-branch SALOMEDS::SObject_var myGroupsBranch; for ( int i = GetNodeGroupsTag(); i <= GetVolumeGroupsTag(); i++ ) { @@ -2906,7 +2940,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, aDataset->WriteOnDisk( smIDs ); aDataset->CloseOnDisk(); // - delete smIDs; + delete[] smIDs; } // Store node positions on sub-shapes (SMDS_Position): @@ -3494,7 +3528,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, } } } - } } } @@ -4117,6 +4150,24 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, aGroup->CloseOnDisk(); } } + // read submeh order if any + if( aTopGroup->ExistInternalObject( "Mesh Order" ) ) { + aDataset = new HDFdataset( "Mesh Order", aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + int* smIDs = new int[ size ]; + aDataset->ReadFromDisk( smIDs ); + aDataset->CloseOnDisk(); + TListOfListOfInt anOrderIds; + anOrderIds.push_back( TListOfInt() ); + for ( int i = 0; i < size; i++ ) + if ( smIDs[ i ] < 0 ) // is separator + anOrderIds.push_back( TListOfInt() ); + else + anOrderIds.back().push_back(smIDs[ i ]); + + myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds ); + } } // close mesh group if(aTopGroup) diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index bc0369dcc..fa9dfbeb9 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -68,8 +68,11 @@ #include #include #include +#include +#include // STL Includes +#include #include #include #include @@ -3457,3 +3460,424 @@ void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr, while (theItr->more()) theInfo[ theItr->next()->GetEntityType() ]++; } + +//============================================================================= +/*! + * \brief mapping of mesh dimension into shape type + */ +//============================================================================= +static TopAbs_ShapeEnum shapeTypeByDim(const int theDim) +{ + TopAbs_ShapeEnum aType = TopAbs_SOLID; + switch ( theDim ) { + case 0: aType = TopAbs_VERTEX; break; + case 1: aType = TopAbs_EDGE; break; + case 2: aType = TopAbs_FACE; break; + case 3: + default:aType = TopAbs_SOLID; break; + } + return aType; +} + +//============================================================================= +/*! + * \brief Internal structure to collect concurent submeshes + */ +//============================================================================= +class SMESH_DimHyp +{ + public: + //! fileds + int _dim; + int _ownDim; + TopTools_MapOfShape _shapeMap; + SMESH_subMesh* _subMesh; + std::list _hypothesises; + + //! Constructors + SMESH_DimHyp(const SMESH_subMesh* theSubMesh, + const int theDim, + const TopoDS_Shape& theShape) + { + _subMesh = (SMESH_subMesh*)theSubMesh; + SetShape( theDim, theShape ); + } + + //! set shape + void SetShape(const int theDim, + const TopoDS_Shape& theShape) + { + _dim = theDim; + _ownDim = (int)SMESH_Gen::GetShapeDim(theShape); + if (_dim >= _ownDim) + _shapeMap.Add( theShape ); + else { + TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) ); + for( ; anExp.More(); anExp.Next() ) + _shapeMap.Add( anExp.Current() ); + } + } + + //! Check sharing of sub shapes + static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck, + const TopTools_MapOfShape& theToFind, + const TopAbs_ShapeEnum theType) + { + bool isShared = false; + TopTools_MapIteratorOfMapOfShape anItr( theToCheck ); + for (; !isShared && anItr.More(); anItr.Next() ) { + const TopoDS_Shape aSubSh = anItr.Key(); + // check for case when concurrent dimensions are same + isShared = theToFind.Contains( aSubSh ); + // check for subshape with concurrent dimension + TopExp_Explorer anExp( aSubSh, theType ); + for ( ; !isShared && anExp.More(); anExp.Next() ) + isShared = theToFind.Contains( anExp.Current() ); + } + return isShared; + } + + //! check algorithms + static bool checkAlgo(const SMESHDS_Hypothesis* theA1, + const SMESHDS_Hypothesis* theA2) + { + if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO || + theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ) + return false; // one of the hypothesis is not algorithm + // check algorithm names (should be equal) + return strcmp( theA1->GetName(), theA2->GetName() ) == 0; + } + + + //! Check if subhape hypothesises is concurrent + bool IsConcurrent(const SMESH_DimHyp* theOther) const + { + if ( _subMesh == theOther->_subMesh ) + return false; // same subshape - should not be + if ( (_ownDim == theOther->_dim || _dim == theOther->_ownDim ) && + ((_subMesh->GetSubMeshDS() && !(_subMesh->GetSubMeshDS()->IsComplexSubmesh())) || + (theOther->_subMesh->GetSubMeshDS() && !(theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh())) ) ) + return false; // no concurrence on shape and group (compound) + bool checkSubShape = ( _dim >= theOther->_dim ) + ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) ) + : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ; + if ( !checkSubShape ) + return false; + + // check algorithms to be same + if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() )) + return true; // different algorithms + + // check hypothesises for concurrence (skip first as algorithm) + int nbSame = 0; + // pointers should be same, becase it is referenes from mesh hypothesis partition + std::list ::const_iterator hypIt = _hypothesises.begin(); + std::list ::const_iterator otheEndIt = theOther->_hypothesises.end(); + for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ ) + if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt ) + nbSame++; + // the submeshes is concurrent if their algorithms has different parameters + return nbSame != theOther->_hypothesises.size() - 1; + } + +}; // end of SMESH_DimHyp + +typedef std::list TDimHypList; + +static void addDimHypInstance(const int theDim, + const TopoDS_Shape& theShape, + const SMESH_Algo* theAlgo, + const SMESH_subMesh* theSubMesh, + const std::list & theHypList, + TDimHypList* theDimHypListArr ) +{ + TDimHypList& listOfdimHyp = theDimHypListArr[theDim]; + if ( !listOfdimHyp.size() || listOfdimHyp.back()->_subMesh != theSubMesh ) { + SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape ); + listOfdimHyp.push_back( dimHyp ); + } + + SMESH_DimHyp* dimHyp = listOfdimHyp.back(); + dimHyp->_hypothesises.push_front(theAlgo); + std::list ::const_iterator hypIt = theHypList.begin(); + for( ; hypIt != theHypList.end(); hypIt++ ) + dimHyp->_hypothesises.push_back( *hypIt ); +} + +static void findConcurrents(const SMESH_DimHyp* theDimHyp, + const TDimHypList& theListOfDimHyp, + TListOfInt& theListOfConcurr ) +{ + TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin(); + for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) { + const SMESH_DimHyp* curDimHyp = *rIt; + if ( curDimHyp == theDimHyp ) + break; // meet own dimHyp pointer in same dimension + else if ( theDimHyp->IsConcurrent( curDimHyp ) ) + if ( find( theListOfConcurr.begin(), + theListOfConcurr.end(), + curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() ) + theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() ); + } +} + +static void unionLists(TListOfInt& theListOfId, + TListOfListOfInt& theListOfListOfId, + const int theIndx ) +{ + TListOfListOfInt::iterator it = theListOfListOfId.begin(); + for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) { + if ( i < theIndx ) + continue; //skip already treated lists + // check is other list has any same submesh object + TListOfInt& otherListOfId = *it; + if ( find_first_of( theListOfId.begin(), theListOfId.end(), + otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() ) + continue; + + // union two lists (from source into target) + TListOfInt::iterator it2 = otherListOfId.begin(); + for ( ; it2 != otherListOfId.end(); it2++ ) { + if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() ) + theListOfId.push_back(*it2); + } + // clear source list + otherListOfId.clear(); + } +} + +//! free memory allocated for dimension-hypothesis objects +static void removeDimHyps( TDimHypList* theArrOfList ) +{ + for (int i = 0; i < 4; i++ ) { + TDimHypList& listOfdimHyp = theArrOfList[i]; + TDimHypList::const_iterator it = listOfdimHyp.begin(); + for ( ; it != listOfdimHyp.end(); it++ ) + delete (*it); + } +} + +//============================================================================= +/*! + * \brief Return submesh objects list in meshing order + */ +//============================================================================= + +SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder() +{ + SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array(); + + SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS(); + if ( !aMeshDS ) + return aResult._retn(); + + ::SMESH_Mesh& mesh = GetImpl(); + TListOfListOfInt anOrder = mesh.GetMeshOrder(); + if ( !anOrder.size() ) { + + // collect submeshes detecting concurrent algorithms and hypothesises + TDimHypList* dimHypListArr = new TDimHypList[4]; // dimHyp list for each shape dimension + + map::iterator i_sm = _mapSubMesh.begin(); + for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) { + ::SMESH_subMesh* sm = (*i_sm).second; + // get shape of submesh + const TopoDS_Shape& aSubMeshShape = sm->GetSubShape(); + + // get list of assigned hypothesises + const std::list & hypList = mesh.GetHypothesisList(aSubMeshShape); + std::list ::const_iterator hypIt = hypList.begin(); + for( ; hypIt != hypList.end(); hypIt++ ) { + SMESH_Algo* anAlgo = 0; + const SMESH_Hypothesis* hyp = dynamic_cast(*hypIt); + if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO ) + anAlgo = (SMESH_Algo*)dynamic_cast(hyp); + else { + // try to find algorithm with helkp of subshapes + TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) ); + for ( ; !anAlgo && anExp.More(); anExp.Next() ) + anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() ); + } + if (!anAlgo) // shopuld not be, but... + continue; // no assigned algorithm to current submesh + int dim = anAlgo->GetDim(); + // create instance od dimension-hypiotheis for founded concurrent dimension and algorithm + for ( int j = anAlgo->NeedDescretBoundary() ? dim : 1, jn = dim; j <= jn; j++ ) + addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr ); + } + } // end iterations on submesh + + // iteartes on create dimension-hypothesises and check for concurrents + for ( int i = 0; i < 4; i++ ) { + const std::list& listOfDimHyp = dimHypListArr[i]; + // check for concurrents in own and other dimensions (step-by-step) + TDimHypList::const_iterator dhIt = listOfDimHyp.begin(); + for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) { + const SMESH_DimHyp* dimHyp = *dhIt; + TListOfInt listOfConcurr; + // looking for concurrents and collect into own list + for ( int j = i; j < 4; j++ ) + findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr ); + // check if any concurrents found + if ( listOfConcurr.size() > 0 ) { + // add own submesh to list of concurrent + listOfConcurr.push_front( dimHyp->_subMesh->GetId() ); + anOrder.push_back( listOfConcurr ); + } + } + } + + removeDimHyps(dimHypListArr); + delete[] dimHypListArr; + + // now, minimise the number of concurrent groups + // Here we assume that lists of submhes can has same submesh + // in case of multi-dimension algorithms, as result + // list with common submesh have to be union into one list + int listIndx = 0; + TListOfListOfInt::iterator listIt = anOrder.begin(); + for(; listIt != anOrder.end(); listIt++, listIndx++ ) + unionLists( *listIt, anOrder, listIndx + 1 ); + } + // convert submesh ids into interface instances + // and dump command into python + convertMeshOrder( anOrder, aResult, true ); + + return aResult._retn(); +} + +//============================================================================= +/*! + * \brief find common submeshes with given submesh + * \param theSubMeshList list of already collected submesh to check + * \param theSubMesh given submesh to intersect with other + * \param theCommonSubMeshes collected common submeshes + */ +//============================================================================= + +static void findCommonSubMesh + (std::list& theSubMeshList, + const SMESH_subMesh* theSubMesh, + std::set& theCommon ) +{ + if ( !theSubMesh ) + return; + std::list::const_iterator it = theSubMeshList.begin(); + for ( ; it != theSubMeshList.end(); it++ ) + theSubMesh->FindIntersection( *it, theCommon ); + theSubMeshList.push_back( theSubMesh ); + //theCommon.insert( theSubMesh ); +} + +//============================================================================= +/*! + * \brief Set submesh object order + * \param theSubMeshArray submesh array order + */ +//============================================================================= + +::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray) +{ + bool res = false; + ::SMESH_Mesh& mesh = GetImpl(); + + TPythonDump aPythonDump; // prevent dump of called methods + aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ "; + + TListOfListOfInt subMeshOrder; + for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ ) + { + const SMESH::submesh_array& aSMArray = theSubMeshArray[i]; + TListOfInt subMeshIds; + aPythonDump << "[ "; + // Collect subMeshes which should be clear + // do it list-by-list, because modification of submesh order + // take effect between concurrent submeshes only + std::set subMeshToClear; + std::list subMeshList; + for ( int j = 0, jn = aSMArray.length(); j < jn; j++ ) + { + const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]); + if ( j > 0 ) + aPythonDump << ", "; + aPythonDump << subMesh; + subMeshIds.push_back( subMesh->GetId() ); + // detech common parts of submeshes + if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() ) + findCommonSubMesh( subMeshList, (*_mapSubMesh.find(subMesh->GetId())).second, subMeshToClear ); + } + aPythonDump << " ]"; + subMeshOrder.push_back( subMeshIds ); + + // clear collected submeshes + std::set::iterator clrIt = subMeshToClear.begin(); + for ( ; clrIt != subMeshToClear.end(); clrIt++ ) { + SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt; + if ( sm ) + sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); + // ClearSubMesh( *clrIt ); + } + } + aPythonDump << " ])"; + + mesh.SetMeshOrder( subMeshOrder ); + res = true; + + return res; +} + +//============================================================================= +/*! + * \brief Convert submesh ids into submesh interfaces + */ +//============================================================================= + +void SMESH_Mesh_i::convertMeshOrder +(const TListOfListOfInt& theIdsOrder, + SMESH::submesh_array_array& theResOrder, + const bool theIsDump) +{ + int nbSet = theIdsOrder.size(); + TPythonDump aPythonDump; // prevent dump of called methods + if ( theIsDump ) + aPythonDump << "[ "; + theResOrder.length(nbSet); + TListOfListOfInt::const_iterator it = theIdsOrder.begin(); + int listIndx = 0; + for( ; it != theIdsOrder.end(); it++ ) { + // translate submesh identificators into submesh objects + // takeing into account real number of concurrent lists + const TListOfInt& aSubOrder = (*it); + if (!aSubOrder.size()) + continue; + if ( theIsDump ) + aPythonDump << "[ "; + // convert shape indeces into interfaces + SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array(); + aResSubSet->length(aSubOrder.size()); + TListOfInt::const_iterator subIt = aSubOrder.begin(); + for( int j = 0; subIt != aSubOrder.end(); subIt++ ) { + if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() ) + continue; + SMESH::SMESH_subMesh_var subMesh = + SMESH::SMESH_subMesh::_duplicate( (*_mapSubMeshIor.find(*subIt)).second ); + if ( theIsDump ) { + if ( j > 0 ) + aPythonDump << ", "; + aPythonDump << subMesh; + } + aResSubSet[ j++ ] = subMesh; + } + if ( theIsDump ) + aPythonDump << " ]"; + theResOrder[ listIndx++ ] = aResSubSet; + } + // correct number of lists + theResOrder.length( listIndx ); + + if ( theIsDump ) { + // finilise python dump + aPythonDump << " ]"; + aPythonDump << " = " << _this() << ".GetMeshOrder()"; + } +} diff --git a/src/SMESH_I/SMESH_Mesh_i.hxx b/src/SMESH_I/SMESH_Mesh_i.hxx index e8598de34..99513b047 100644 --- a/src/SMESH_I/SMESH_Mesh_i.hxx +++ b/src/SMESH_I/SMESH_Mesh_i.hxx @@ -58,7 +58,7 @@ class SMESH_I_EXPORT SMESH_Mesh_i: public: SMESH_Mesh_i( PortableServer::POA_ptr thePOA, SMESH_Gen_i* myGen_i, - CORBA::Long studyId ); + CORBA::Long studyId ); virtual ~SMESH_Mesh_i(); @@ -500,6 +500,16 @@ public: static void CollectMeshInfo(const SMDS_ElemIteratorPtr theItr, SMESH::long_array& theInfo); + + /*! + * \brief Return submesh objects list in meshing order + */ + virtual SMESH::submesh_array_array* GetMeshOrder(); + /*! + * \brief Set submesh object order + */ + virtual ::CORBA::Boolean SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray); + std::map _mapSubMesh_i; //NRI std::map _mapSubMesh; //NRI @@ -510,6 +520,13 @@ private: */ void checkGroupNames(); + /*! + * Convert submesh ids into submesh interfaces + */ + void convertMeshOrder(const TListOfListOfInt& theIdsOrder, + SMESH::submesh_array_array& theSubMeshOrder, + const bool theIsDump); + private: static int myIdGenerator; diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index 4789415c9..0b5579807 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -1201,6 +1201,18 @@ class Mesh: pass return ok + ## Return submesh objects list in meshing order + # @return list of list of submesh objects + # @ingroup l2_construct + def GetMeshOrder(self): + return self.mesh.GetMeshOrder() + + ## Return submesh objects list in meshing order + # @return list of list of submesh objects + # @ingroup l2_construct + def SetMeshOrder(self, submeshes): + return self.mesh.SetMeshOrder(submeshes) + ## Removes all nodes and elements # @ingroup l2_construct def Clear(self):