From 4afb03c808d53f6accb0dfb7e2f9499b3e28abcb Mon Sep 17 00:00:00 2001 From: ptv Date: Tue, 29 Sep 2009 08:17:04 +0000 Subject: [PATCH] 0020427: EDF 868 SMESH : Be able to define the submeshing order --- .../gui/SMESH/images/mesh_order_123.png | Bin 0 -> 5488 bytes .../gui/SMESH/images/mesh_order_123_res.png | Bin 0 -> 29778 bytes .../gui/SMESH/images/mesh_order_213.png | Bin 0 -> 5801 bytes .../gui/SMESH/images/mesh_order_213_res.png | Bin 0 -> 32707 bytes .../gui/SMESH/images/mesh_order_321.png | Bin 0 -> 5948 bytes .../gui/SMESH/images/mesh_order_321_res.png | Bin 0 -> 35243 bytes .../SMESH/images/mesh_order_no_concurrent.png | Bin 0 -> 4435 bytes .../gui/SMESH/images/mesh_order_preview.png | Bin 0 -> 4849 bytes .../gui/SMESH/input/constructing_meshes.doc | 1 + .../gui/SMESH/input/tui_creating_meshes.doc | 61 +++ idl/SMESH_Mesh.idl | 20 + src/SMESH/SMESH_Gen.cxx | 32 +- src/SMESH/SMESH_Gen.hxx | 2 +- src/SMESH/SMESH_Mesh.cxx | 231 +++++++---- src/SMESH/SMESH_Mesh.hxx | 24 +- src/SMESH/SMESH_MeshEditor.cxx | 23 +- src/SMESHGUI/Makefile.am | 10 +- src/SMESHGUI/SMESHGUI.cxx | 11 +- src/SMESHGUI/SMESHGUI_ComputeDlg.cxx | 164 +++++--- src/SMESHGUI/SMESHGUI_ComputeDlg.h | 14 + src/SMESHGUI/SMESHGUI_MeshOrderDlg.cxx | 332 +++++++++++++++ src/SMESHGUI/SMESHGUI_MeshOrderDlg.h | 114 ++++++ src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx | 318 +++++++++++++++ src/SMESHGUI/SMESHGUI_MeshOrderOp.h | 96 +++++ src/SMESHGUI/SMESH_msg_en.ts | 35 ++ src/SMESH_I/SMESH_2smeshpy.cxx | 31 +- src/SMESH_I/SMESH_Mesh_i.cxx | 382 ++++++++++++++++++ src/SMESH_I/SMESH_Mesh_i.hxx | 19 +- src/SMESH_SWIG/smeshDC.py | 12 + 29 files changed, 1776 insertions(+), 156 deletions(-) create mode 100644 doc/salome/gui/SMESH/images/mesh_order_123.png create mode 100644 doc/salome/gui/SMESH/images/mesh_order_123_res.png create mode 100644 doc/salome/gui/SMESH/images/mesh_order_213.png create mode 100644 doc/salome/gui/SMESH/images/mesh_order_213_res.png create mode 100644 doc/salome/gui/SMESH/images/mesh_order_321.png create mode 100644 doc/salome/gui/SMESH/images/mesh_order_321_res.png create mode 100644 doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png create mode 100644 doc/salome/gui/SMESH/images/mesh_order_preview.png create mode 100644 src/SMESHGUI/SMESHGUI_MeshOrderDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_MeshOrderDlg.h create mode 100644 src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx create mode 100644 src/SMESHGUI/SMESHGUI_MeshOrderOp.h 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 0000000000000000000000000000000000000000..952f207960af886f0ce867c80752dfc7468f6f9a GIT binary patch literal 5488 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

Y} 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 PlL~mCtq(50V;k`g1N6Ho literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..7b7588c632deae8d2b07bb719268ca4e43d0fbb6 GIT binary patch literal 29778 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

n$6wXGAdp4NW-7x8~b-GCJNQ=0XwllKo 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�iSP}c7E+v~?3~t8UX)n-* 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 T7Ow{II7mreU9L>VIN<*P?RbL+ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..7ad61fabdc205a5d83bc9ef0719d77472d4da329 GIT binary patch literal 5948 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..051447093abdfddf198b673117113294d10bb6b9 GIT binary patch literal 35243 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 L{an^LB{Ts5LVa;p literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..6df59a1f15734f3c773f30e3336cf9e8a7b37501 GIT binary patch literal 4435 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 +\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. diff --git a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc index 9048afef1..9147b3685 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 fff0c5120..7d83f4b6b 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 9d5df1eb8..8150a883d 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 57a5af6eb..dece95c33 100644 --- a/src/SMESH/SMESH_Gen.hxx +++ b/src/SMESH/SMESH_Gen.hxx @@ -157,7 +157,7 @@ class SMESH_EXPORT SMESH_Gen std::map < int, SMESH_3D_Algo * >_map3D_Algo; private: - + //! private fields int _localId; // unique Id of created objects, within SMESH_Gen entity std::map < int, StudyContextStruct * >_mapStudyContext; diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 1281522d9..676fbbf40 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 e84487512..b6ae8c91e 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -8830,6 +8830,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++ ) @@ -8839,24 +8840,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) - 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) + 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 = 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/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 1b278b946..91296bd7d 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -92,6 +92,8 @@ salomeinclude_HEADERS = \ SMESHGUI_IdValidator.h \ SMESHGUI_MeshInfosBox.h \ SMESHGUI_Make2DFrom3DOp.h \ + SMESHGUI_MeshOrderDlg.h \ + SMESHGUI_MeshOrderOp.h \ SMESH_SMESHGUI.hxx # Libraries targets @@ -161,7 +163,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 \ @@ -215,7 +219,9 @@ MOC_FILES = \ SMESHGUI_GroupOnShapeDlg_moc.cxx \ SMESHGUI_FileInfoDlg_moc.cxx \ SMESHGUI_MeshInfosBox_moc.cxx \ - SMESHGUI_Make2DFrom3DOp_moc.cxx + SMESHGUI_Make2DFrom3DOp_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 4b41c1d20..9903bb68c 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -68,6 +68,7 @@ #include "SMESHGUI_ComputeDlg.h" #include "SMESHGUI_FileInfoDlg.h" #include "SMESHGUI_Make2DFrom3DOp.h" +#include "SMESHGUI_MeshOrderOp.h" #include "SMESHGUI_Utils.h" #include "SMESHGUI_MeshUtils.h" @@ -1622,6 +1623,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 ); @@ -2711,6 +2713,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" ); @@ -2859,6 +2862,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 ); @@ -2963,6 +2967,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 ); @@ -3093,7 +3098,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 @@ -3905,6 +3911,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 5023cdc54..f555fffda 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 @@ -638,8 +641,8 @@ void SMESHGUI_BaseComputeOp::startOperation() int nbSel = selected.Extent(); if (nbSel != 1) { SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_NO_AVAILABLE_DATA")); + tr("SMESH_WRN_WARNING"), + tr("SMESH_WRN_NO_AVAILABLE_DATA")); onCancel(); return; } @@ -648,8 +651,8 @@ void SMESHGUI_BaseComputeOp::startOperation() myMesh = SMESH::GetMeshByIO(myIObject); if (myMesh->_is_nil()) { SUIT_MessageBox::warning(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_NO_AVAILABLE_DATA")); + tr("SMESH_WRN_WARNING"), + tr("SMESH_WRN_NO_AVAILABLE_DATA")); onCancel(); return; } @@ -742,9 +745,9 @@ void SMESHGUI_BaseComputeOp::computeMesh() LightApp_SelectionMgr *Sel = selectionMgr(); if ( Sel ) { - SALOME_ListIO selected; - selected.Append( myIObject ); - Sel->setSelectedObjects( selected ); + SALOME_ListIO selected; + selected.Append( myIObject ); + Sel->setSelectedObjects( selected ); } } } @@ -787,10 +790,10 @@ void SMESHGUI_BaseComputeOp::computeMesh() } void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack, - const bool theNoCompError, - SMESH::compute_error_array_var& theCompErrors, - const bool theNoHypoError, - const QString& theHypErrors ) + const bool theNoCompError, + SMESH::compute_error_array_var& theCompErrors, + const bool theNoHypoError, + const QString& theHypErrors ) { bool hasShape = myMesh->HasShapeToMesh(); SMESHGUI_ComputeDlg* aCompDlg = computeDlg(); @@ -855,29 +858,29 @@ void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack, { SMESH::ComputeError & err = theCompErrors[ row ]; - QString text = err.algoName.in(); - if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_ALGO )->setText( text ); + QString text = err.algoName.in(); + if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ALGO )->setText( text ); - text = SMESH::errorText( err.code, err.comment.in() ); - if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_ERROR )->setText( text ); + text = SMESH::errorText( err.code, err.comment.in() ); + if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ERROR )->setText( text ); - text = QString("%1").arg( err.subShapeID ); - if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_SHAPEID )->setText( text ); + text = QString("%1").arg( err.subShapeID ); + if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPEID )->setText( text ); text = hasShape ? SMESH::shapeText( err.subShapeID, myMainShape ) : QString(""); - if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_SHAPE )->setText( text ); + if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPE )->setText( text ); text = ( !hasShape || SMESH::getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : ""; - if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled + if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled text = err.hasBadMesh ? "hasBadMesh" : ""; - if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_BAD_MESH )->setText( text ); + if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_BAD_MESH )->setText( text ); if ( err.hasBadMesh ) hasBadMesh = true; //tbl->item( row, COL_ERROR )->setWordWrap( true ); // VSR: TODO ??? @@ -1192,6 +1195,7 @@ LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const SMESHGUI_PrecomputeOp::SMESHGUI_PrecomputeOp() : SMESHGUI_BaseComputeOp(), myDlg( 0 ), + myOrderMgr( 0 ), myActiveDlg( 0 ), myPreviewDisplayer( 0 ) { @@ -1208,6 +1212,8 @@ SMESHGUI_PrecomputeOp::~SMESHGUI_PrecomputeOp() { delete myDlg; myDlg = 0; + delete myOrderMgr; + myOrderMgr = 0; myActiveDlg = 0; if ( myPreviewDisplayer ) delete myPreviewDisplayer; @@ -1273,6 +1279,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() ) ); @@ -1337,6 +1353,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 ); } @@ -1381,7 +1406,7 @@ void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh, default: break; } if ( !algo->_is_nil() ) - theModeMap[ dim ] = 0; + theModeMap[ dim ] = 0; } } } @@ -1397,6 +1422,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(); @@ -1418,6 +1445,7 @@ void SMESHGUI_PrecomputeOp::onCancel() return; } + bool isRestoreOrder = false; if ( myActiveDlg == myDlg && !myMesh->_is_nil() && myMapShapeId.count() ) { // ask to remove already computed mesh elements @@ -1429,8 +1457,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(); } @@ -1449,6 +1493,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(); @@ -1491,7 +1540,7 @@ void SMESHGUI_PrecomputeOp::onPreview() myPreviewDisplayer->SetData( previewRes ); // append shape indeces with computed mesh entities for ( int i = 0, n = aShapesId->length(); i < n; i++ ) - myMapShapeId[ aShapesId[ i ] ] = 0; + myMapShapeId[ aShapesId[ i ] ] = 0; } else myPreviewDisplayer->SetVisibility(false); @@ -1553,7 +1602,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" ) ); @@ -1562,6 +1612,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 ); @@ -1618,6 +1671,17 @@ int SMESHGUI_PrecomputeDlg::getPreviewMode() const return myPreviewMode->currentId(); } +//================================================================================ +/*! + * \brief Returns current preview mesh mode +*/ +//================================================================================ + +SMESHGUI_MeshOrderBox* SMESHGUI_PrecomputeDlg::getMeshOrderBox() const +{ + return myOrderBox; +} + //================================================================================ /*! @@ -1759,16 +1823,16 @@ void SMESHGUI_BaseComputeOp::evaluateMesh() // SHOW RESULTS if ( isShowResultDlg ) showEvaluateResult( aRes, memoryLack, noCompError, aCompErrors, - noHypoError, aHypErrors); + noHypoError, aHypErrors); } void SMESHGUI_BaseComputeOp::showEvaluateResult(const SMESH::long_array& theRes, - const bool theMemoryLack, - const bool theNoCompError, - SMESH::compute_error_array_var& theCompErrors, - const bool theNoHypoError, - const QString& theHypErrors) + const bool theMemoryLack, + const bool theNoCompError, + SMESH::compute_error_array_var& theCompErrors, + const bool theNoHypoError, + const QString& theHypErrors) { bool hasShape = myMesh->HasShapeToMesh(); SMESHGUI_ComputeDlg* aCompDlg = evaluateDlg(); @@ -1825,29 +1889,29 @@ void SMESHGUI_BaseComputeOp::showEvaluateResult(const SMESH::long_array& theRes, { SMESH::ComputeError & err = theCompErrors[ row ]; - QString text = err.algoName.in(); - if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_ALGO )->setText( text ); + QString text = err.algoName.in(); + if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ALGO )->setText( text ); - text = SMESH::errorText( err.code, err.comment.in() ); - if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_ERROR )->setText( text ); + text = SMESH::errorText( err.code, err.comment.in() ); + if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ERROR )->setText( text ); - text = QString("%1").arg( err.subShapeID ); - if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_SHAPEID )->setText( text ); + text = QString("%1").arg( err.subShapeID ); + if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPEID )->setText( text ); text = hasShape ? SMESH::shapeText( err.subShapeID, myMainShape ) : QString(""); - if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_SHAPE )->setText( text ); + if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPE )->setText( text ); text = ( !hasShape || SMESH::getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : ""; - if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled + if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled text = err.hasBadMesh ? "hasBadMesh" : ""; - if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) ); - else tbl->item( row, COL_BAD_MESH )->setText( text ); + if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_BAD_MESH )->setText( text ); if ( err.hasBadMesh ) hasBadMesh = true; //tbl->item( row, COL_ERROR )->setWordWrap( true ); // VSR: TODO ??? diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.h b/src/SMESHGUI/SMESHGUI_ComputeDlg.h index 85102f3b1..333741364 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.h +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.h @@ -36,6 +36,7 @@ // Qt includes #include +#include #include #include @@ -132,6 +133,8 @@ protected: protected slots: }; +class SMESHGUI_MeshOrderMgr; + /*! * \brief Operation to preview and compute a mesh and show computation errors */ @@ -166,10 +169,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; }; /*! @@ -223,6 +232,8 @@ protected: friend class SMESHGUI_PrecomputeOp; }; +class SMESHGUI_MeshOrderBox; + /*! * \brief Dialog to preview and compute a mesh and show computation errors */ @@ -237,11 +248,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..5c26efc2c --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx @@ -0,0 +1,318 @@ +// 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); + } + } + + 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; + } + + 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 7b4f62eb6..fd6897719 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 @@ -2051,6 +2055,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 @@ -2549,6 +2557,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 @@ -3351,6 +3363,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 @@ -4840,4 +4861,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 077766762..201256ed7 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_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index e0c228dfa..63a39472c 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 @@ -3439,3 +3442,382 @@ 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 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 << "[ "; + 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() ); + } + aPythonDump << " ]"; + subMeshOrder.push_back( subMeshIds ); + } + 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++ ) { + 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 2c46676f6..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 3128c297b..ecfae71d6 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -1132,6 +1132,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): -- 2.39.2