From b03a1e600155a03e2ae01e31960837e51831db70 Mon Sep 17 00:00:00 2001 From: vsr Date: Wed, 9 Dec 2009 15:46:26 +0000 Subject: [PATCH] Merge from BR_phase16 branch (09/12/09) --- .../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 | 83 +++- .../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/SMESH/SMESH_subMesh.cxx | 26 ++ src/SMESH/SMESH_subMesh.hxx | 9 + src/SMESHGUI/Makefile.am | 10 +- src/SMESHGUI/SMESHGUI.cxx | 11 +- src/SMESHGUI/SMESHGUI_ComputeDlg.cxx | 66 ++- src/SMESHGUI/SMESHGUI_ComputeDlg.h | 14 + src/SMESHGUI/SMESHGUI_MeshOrderDlg.cxx | 332 ++++++++++++++ src/SMESHGUI/SMESHGUI_MeshOrderDlg.h | 114 +++++ src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx | 325 ++++++++++++++ src/SMESHGUI/SMESHGUI_MeshOrderOp.h | 96 ++++ src/SMESHGUI/SMESH_msg_en.ts | 35 ++ src/SMESH_I/SMESH_2smeshpy.cxx | 31 +- src/SMESH_I/SMESH_Gen_i.cxx | 55 ++- src/SMESH_I/SMESH_Mesh_i.cxx | 424 ++++++++++++++++++ src/SMESH_I/SMESH_Mesh_i.hxx | 19 +- src/SMESH_SWIG/smeshDC.py | 12 + 32 files changed, 1944 insertions(+), 111 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} zf_~u-(#-V8tG&Iw_K@8qjGPo!V%?OcBa@CiLz7W|=4U@J@YR!JrEVZT?>@xPP~gNq zis}CKt$_?f&+OmFan_6DxAv3dBd)Py8 z{sn4r=6C_hm;!zg;5C`lBjFs`9^(m4l6eR84G7>mAL@OX>1^|pc#RZhuilRqD$o;C z9fn$;QoefJr=@l{miN9|vgkfvP?A2sl}hl3;kq^SRU&q^+5;(0%FEe%II-Q zVtmb<3+pg+*w7{WpxKGbIQsK#IIym^c4!9;*S_&JF6%yA8{Vam%%03Wna$UCJR|J4 z`smT4!PVI1sgc2+b@gU$${zOO--cDXb7ykDoq zqH48K4<_TY-u5^wKKG<`t)CW$px8BIYq{UApha>$%p3f!fw=cOJXPUQ$I)Pc`Q6Xs z%*H0hb_;7dsLT)^VoQNJ?}Q5a+c2`Czk3bmrcP8ltLWeM$i`Sb=71olTd=z*(oW8@ zm!=iJ*N3_CvbgeSi$(iAoBAx1JzS%KiiUtdY<1X&jZXCP5u_|4rT+LSlSUhkJeBUL znpl4ou#Q`rF8y_I&KMnHfweHdhd-`>QO%k@j{dBE0|;#nke8JW&zk1d)zx)C*jr5x zPA1mH)=xKnee-o4$K71Lvxl$Mz-fTN?qcb0UA1n%oS7fBzj-6qN(`;^g2NbSyL49- z>PU3%-n&*nXg;lYB#vHst50i0$@W$^*+r{v8&bGZN+kS1@G`(xKiWP7A3Qui6na3| zP0{)yMJpnZ7X1*w&l1hH<`^iDYX_wQ6dU(!pe{2<@}3p4{TpC6b6EZtb^opG;d_-k zkfovx{y91_;&^}`o;qdi=O?Y4bp&!ifH}BKtz^+PhpcVpf=~ysBPO!fPZv#^{R}{E zCB0GQ4p0Bv|9nSQ_TAg8(ctQoFBwl_!2&6hE`ckf=~9Gb>v2DqTWYDg#>W?VA$?Sd z=3!E_6CoU{r_7IqVU9)jy3F4V2G#i7vrw_WDc|aUaouE9d0t2$FXFs0`ZeK(=s1m~ z6ta1c$`NR&k(fmHU2c+Ppm(0YFuVq7gnaz6Oq!I2$c3@QUxP6n;FP+5-+EL>|00AI zm5a?e3TSW&R7AS(Ng~a|m7?CKt^L((gtE~UFs!Jng9c_*nK7KVQO;3=H3T>HARYX8 zjfHWO<9R6!!;vC|^oH)s+w+~00@vep_N{69_q`sAk0KlxM>A8F5~3!9r`+z|8Wc)= zfG?TF=Bh1-Tg}I96xk)W^ri!EI(>;O84*Q7%YyQO=rUT9gVC zwm^9(5F>9aF@eiDvI`wA%PD?wbZ3kCTm*K6%~V08YDrj{SLUEZt^%9aJdg$R#w)t z{j$?8yzyF09Ay+|qUMjcI9_r2e2(G=I4K&Y4s{j=wHiP}z@1_8#*u%=DOTQCKtS7p zYUQITQvpolI4=rU`pS@@DDa>D;NyiKF=T+(Ni#aEl)H2Psq!XE5LoDm@8B=!b%Z5D>)pof(i{mXQuWIbf1{zt zHKq9E7Q(e>tkuOR(LOC_R@qoUTolUwDK^V=Ur&tUDFt&F zw!bw0m{OkVFjJ2IU!?(ZO+y34o5y(%CmDeey{SfDMCrsfa6K@v#+|5wFS&dni^lk? zZnWd`0s6dshgnv93G)TDsQ+w)|6P*)?vDRgsS}!-&7{FEP%Xj^IUrFB2slv~_rEuc z{~$U{N&hMe!keb3=p<#IO~Z2}8Qgo=t8-XiJTfxUB7S!o(`lzf>H!Y=uGQGuWk<$Y zXD>fEKja{XHH|DHjXC}N1fo}@9TMmQ(ev$@H_GO4$nKf%SN6BZ0_!kU{q0d`4)-mf zZ^E@}3Tri_zp^8FoQkwxqB%foH6HewQg;7TrYD41SVJ!XxRg~BLSqZIjFMALe?2)W z9jGTaucNdM=WAVMG*+0CPGwp1LGp4>R27NbJN2eo%M8$8wxl52@npQ~FY(~RCG$?;V65Vnl%=b8kdF zkIEleri}24DNaz%=B-*(TC$VwYAwEN_Yi*Qdl;PA<1+}7i?|t(Iq?Xd?Xn8*Hn~jG zAUTZXs|Y;#N^9DKJmlHk6J?`Lv|h>H|;Y|ah|vzD(Jw8Rp(o-mYnwEU23}< zyA^o@&Ru>3&O@G|#NVq=psk*n)+#mV_@Bo8cdAP6gV2t;8rX~^*XEqs7%czjrO%Ad z!kRrxW;B}dXO%rqo?DojMi~|A!%OAeoyazRnWuGCYBeh6zg$dB3sHn}??mLSE1ktg zg}U3{sGg^LZU2~-(BJ)B*I(KdVKhne&bs$plRKcg>j{NzBX1N8Hx)TK0{ONkPh^#F zspg|IGjSh2sO*r*lOxoCkqTJ$w0=w3hKV1RCgY2;{xZi_diXSDjx7PMX8{+^F7%banQ5Ytrheo5j zRBGg=F17=FCvCdOeygPupNokR-=s|B#! zcX#(eoi${lQ}^{M?bvza1_Y8!<}*<~Ka`clJ4pL21v%9y`y`VCj6$L0LU^_n7jd5R z_Xu0PJ&Gj_vbb?d!xit5B@7m;&7-g?znXEbj`o^^-@e(ZFoqo;^_CMIy5nIH7K&vu zv8+G@77C+UKT~M$t=ZVh4p=&urf~abhpLF=cEXn$7b7G6Ux{Z3#}P6rWK;$dF(GWT z1BZ}r^JRtX?hxmZmIXDIPE*pOTTUwV=KH-#pv03SCZ3Q~{J+V>@PFvTL+#3JpB>3` zBsrB&y)wPDhcdggMMa@9g`dLg5K47_bYkFok@26*tmxRdc$t}<{=Z6<&}y!6kYzL9 zF2BG<+{>^JLH+Ld6)i9u>K&lcsh=0W`bUm87LU{sO4w=^0E4e{9)t?fzo)0u%zH-p 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. +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: +
      +
    • 3D Tetrahedron (Netgen) with HypothesisMax Element Volume
    • +
    • 2D Triangle (Mefisto) with HypothesisMax Element Area +
    • +
    • 1D Wire discretisation with Number of Segments=20
    • +
    +The first submesh object Submesh_1 created on Face_1 +is: +
      +
    • 2D Netgen 1D-2D with Hypothesis Netgen Simple parameters +(Number of Segments = 4)
    • +
    +The second submesh object Submesh_2 created on Face_2 +is: +
      +
    • 2D Netgen 1D-2D with Hypothesis Netgen Simple parameters +(Number of Segments = 8)
    • +
    + +And the last third submesh object Submesh_3 created on Face_3 +is: +
      +
    • 2D Netgen 1D-2D with Hypothesis Netgen Simple parameters +(Number of Segments = 12)
    • +
    +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):