Salome HOME
Merge from BR_phase16 branch (09/12/09)
authorvsr <vsr@opencascade.com>
Wed, 9 Dec 2009 15:46:26 +0000 (15:46 +0000)
committervsr <vsr@opencascade.com>
Wed, 9 Dec 2009 15:46:26 +0000 (15:46 +0000)
32 files changed:
doc/salome/gui/SMESH/images/mesh_order_123.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/mesh_order_123_res.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/mesh_order_213.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/mesh_order_213_res.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/mesh_order_321.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/mesh_order_321_res.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/mesh_order_preview.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/constructing_meshes.doc
doc/salome/gui/SMESH/input/tui_creating_meshes.doc
idl/SMESH_Mesh.idl
src/SMESH/SMESH_Gen.cxx
src/SMESH/SMESH_Gen.hxx
src/SMESH/SMESH_Mesh.cxx
src/SMESH/SMESH_Mesh.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_subMesh.cxx
src/SMESH/SMESH_subMesh.hxx
src/SMESHGUI/Makefile.am
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_ComputeDlg.cxx
src/SMESHGUI/SMESHGUI_ComputeDlg.h
src/SMESHGUI/SMESHGUI_MeshOrderDlg.cxx [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_MeshOrderDlg.h [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_MeshOrderOp.cxx [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_MeshOrderOp.h [new file with mode: 0644]
src/SMESHGUI/SMESH_msg_en.ts
src/SMESH_I/SMESH_2smeshpy.cxx
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_I/SMESH_Mesh_i.hxx
src/SMESH_SWIG/smeshDC.py

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 (file)
index 0000000..952f207
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_123.png differ
diff --git a/doc/salome/gui/SMESH/images/mesh_order_123_res.png b/doc/salome/gui/SMESH/images/mesh_order_123_res.png
new file mode 100644 (file)
index 0000000..7b7588c
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_123_res.png differ
diff --git a/doc/salome/gui/SMESH/images/mesh_order_213.png b/doc/salome/gui/SMESH/images/mesh_order_213.png
new file mode 100644 (file)
index 0000000..959ca38
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_213.png differ
diff --git a/doc/salome/gui/SMESH/images/mesh_order_213_res.png b/doc/salome/gui/SMESH/images/mesh_order_213_res.png
new file mode 100644 (file)
index 0000000..ca36759
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_213_res.png differ
diff --git a/doc/salome/gui/SMESH/images/mesh_order_321.png b/doc/salome/gui/SMESH/images/mesh_order_321.png
new file mode 100644 (file)
index 0000000..7ad61fa
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_321.png differ
diff --git a/doc/salome/gui/SMESH/images/mesh_order_321_res.png b/doc/salome/gui/SMESH/images/mesh_order_321_res.png
new file mode 100644 (file)
index 0000000..0514470
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_321_res.png differ
diff --git a/doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png b/doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png
new file mode 100644 (file)
index 0000000..6df59a1
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_no_concurrent.png differ
diff --git a/doc/salome/gui/SMESH/images/mesh_order_preview.png b/doc/salome/gui/SMESH/images/mesh_order_preview.png
new file mode 100644 (file)
index 0000000..f4b5e3b
Binary files /dev/null and b/doc/salome/gui/SMESH/images/mesh_order_preview.png differ
index 625cff3..6251855 100644 (file)
@@ -152,10 +152,89 @@ evaluation will be displayed in the following information box:
 
 \image html mesh_evaluation_succeed.png
 
+</li>
 
-Consider trying a sample script for construction of a mesh from our 
-\ref tui_creating_meshes_page "TUI Scripts" section.
+</ol>
+
+\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.
+<em>To change submesh priority:</em>
+<ol>
+<li>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:
+<ul>
+<li><i>3D</i> <b>Tetrahedron (Netgen)</b> with Hypothesis<b>Max Element Volume</b></li>
+<li><i>2D</i> <b>Triangle (Mefisto)</b> with Hypothesis<b>Max Element Area</b>
 </li>
+<li><i>1D</i> <b>Wire discretisation</b> with <b>Number of Segments</b>=20</li>
+</ul>
+The first submesh object <b>Submesh_1</b> created on <b>Face_1</b>
+is:
+<ul>
+<li><i>2D</i> Netgen 1D-2D with Hypothesis <b>Netgen Simple parameters</b>
+(Number of Segments = 4)</li>
+</ul>
+The second submesh object <b>Submesh_2</b> created on <b>Face_2</b>
+is:
+<ul>
+<li><i>2D</i> Netgen 1D-2D with Hypothesis <b>Netgen Simple parameters</b>
+(Number of Segments = 8)</li>
+</ul>
+
+And the last third submesh object <b>Submesh_3</b> created on <b>Face_3</b>
+is:
+<ul>
+<li><i>2D</i> Netgen 1D-2D with Hypothesis <b>Netgen Simple parameters</b>
+(Number of Segments = 12)</li>
+</ul>
+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
+<center><em>"Mesh order SubMesh_1, SubMesh_2, SubMesh_3"</em></center>
+\image html mesh_order_123_res.png
+<center><em>"Result mesh with order SubMesh_1, SubMesh_2, SubMesh_3 "</em></center>
+
+The next mesh computation with:
+\image html mesh_order_213.png
+<center><em>"Mesh order SubMesh_2, SubMesh_1, SubMesh_3"</em></center>
+\image html mesh_order_213_res.png
+<center><em>"Result mesh with order SubMesh_2, SubMesh_1, SubMesh_3 "</em></center>
+
+And the last mesh computation with:
+\image html mesh_order_321.png
+<center><em>"Mesh order SubMesh_3, SubMesh_2, SubMesh_1"</em></center>
+\image html mesh_order_321_res.png
+<center><em>"Result mesh with order SubMesh_3, SubMesh_2, SubMesh_1 "</em></center>
+
+As we can see each mesh computation has different number of result
+elements and different mesh descretisation on shared edges (edges,
+that shared between <b>Face_1</b>, <b>Face_2</b> and <b>Face_3</b>)
+
+Additionally, submesh priority (order of algorithms to be applied) can
+be modified not only in separate dialog box, but in <b>Preview</b>
+also. This helps to preview different mesh results, modifying submesh
+order.
+\image html mesh_order_preview.png
+<center><em>"Preview with submesh priority list box"</em></center>
+
+If no concurrent submeshes under Mesh object user will see the
+following information dialog box
+\image html mesh_order_no_concurrent.png
+<center><em>"No concurrent submeshes detected"</em></center>
+and no mesh order list box appear in Preview dialog box.
+
 </ol>
 
+Consider trying a sample script for construction of a mesh from our 
+\ref tui_creating_meshes_page "TUI Scripts" section.
+
 */
index 87f740e..359ffd7 100644 (file)
@@ -83,6 +83,67 @@ quadra.Compute()
 \endcode
 
 <br>
+<h2>Change priority of submeshes in Mesh</h2>
+
+\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
+
+<br>
 \anchor tui_editing_mesh
 <h2>Editing of a mesh</h2>
 
index 8a5c37d..c58b7fa 100644 (file)
@@ -263,6 +263,10 @@ module SMESH
   interface SMESH_GroupOnGeom;
   interface SMESH_subMesh;
   interface SMESH_MeshEditor;
+
+  typedef sequence<SMESH_subMesh>     submesh_array;
+  typedef sequence<submesh_array>     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
      */
index 10ec57e..0706b5f 100644 (file)
@@ -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);
index ab610a0..b26a204 100644 (file)
@@ -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
index 67d78b4..6b2a69b 100644 (file)
@@ -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<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
+    std::list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
+    for ( ; smIt != smList.end(); smIt++ )
     {
-      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
+      const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
+      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
       std::list<const SMESHDS_Hypothesis*>::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<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
+    std::list<SMESH_subMesh*>::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<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
+      const std::list<const SMESHDS_Hypothesis*>& 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<SMESH_subMesh*>& theListToSort) const
+{
+  if ( !_mySubMeshOrder.size() || theListToSort.size() < 2)
+    return true;
+  
+  bool res = false;
+  std::list<SMESH_subMesh*> 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 <int, SMESH_subMesh *>::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<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
+  std::list<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
+
+  // check positions where ordered submeshes should be in result list
+  std::set<int> setOfPos; // remember positions of in set
+  std::list<SMESH_subMesh*>::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<SMESH_subMesh*> 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_subMesh*> SMESH_Mesh::getAncestorsSubMeshes
+  (const TopoDS_Shape& theSubShape) const
+{
+  std::list<SMESH_subMesh*> listOfSubMesh;
+  TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape ));
+  for (; it.More(); it.Next() ) {
+    int index = _myMeshDS->ShapeToIndex(it.Value());
+    map <int, SMESH_subMesh *>::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;
+}
index 26339eb..b93e8b5 100644 (file)
@@ -40,8 +40,8 @@
 #include <TopoDS_Shape.hxx>
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 
-#include <list>
 #include <map>
+#include <list>
 
 class SMESH_Gen;
 class SMESHDS_Document;
@@ -51,6 +51,9 @@ class SMESH_subMesh;
 class SMESH_HypoFilter;
 class TopoDS_Solid;
 
+typedef std::list<int> TListOfInt;
+typedef std::list<TListOfInt> 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<SMESH_subMesh*>& theListToSort) const;
+
   //
   
   ostream& Dump(ostream & save);
   
 private:
+
+  void fillAncestorsMap(const TopoDS_Shape& theShape);
+  std::list<SMESH_subMesh*> 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 <int, SMESH_subMesh*> _mapSubMesh;
   std::map <int, SMESH_Group*>   _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&) {};
index f7d2b40..a0d0770 100644 (file)
@@ -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<const SMDS_MeshNode *> nodes;
       int nbFaceNodes = vTool.NbFaceNodes(iface);
       const SMDS_MeshNode** faceNodes = vTool.GetFaceNodes(iface);
-      if (vTool.IsFaceExternal(iface)) 
-      {
-        int inode = 0;
-        for ( ; inode < nbFaceNodes; inode += isQuad ? 2 : 1)
-          nodes.push_back(faceNodes[inode]);
-        if (isQuad)
-          for ( inode = 1; inode < nbFaceNodes; inode += 2)
-            nodes.push_back(faceNodes[inode]);
-      }
-      else
-      {
-        int inode = nbFaceNodes-1;
-        for ( ; inode >=0; inode -= isQuad ? 2 : 1)
+      int inode = 0;
+      for ( ; inode < nbFaceNodes; inode += isQuad ? 2 : 1)
+        nodes.push_back(faceNodes[inode]);
+      if (isQuad)
+        for ( inode = 1; inode < nbFaceNodes; inode += 2)
           nodes.push_back(faceNodes[inode]);
-        if (isQuad)
-          for ( inode = nbFaceNodes-2; inode >=0; inode -= 2)
-            nodes.push_back(faceNodes[inode]);
-      }
 
       // add new face based on volume nodes
       if (aMesh->FindFace( nodes ) )
index 21d1675..b8615dc 100644 (file)
@@ -2191,3 +2191,29 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS
       ( new _Iterator( new SMDS_mapIterator<TMap>( 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<const SMESH_subMesh*>& theSetOfCommon ) const
+{
+  int oldNb = theSetOfCommon.size();
+  // check main submeshes
+  const map <int, SMESH_subMesh*>::const_iterator otherEnd = theOther->_mapDepend.end();
+  if ( theOther->_mapDepend.find(this->GetId()) != otherEnd )
+    theSetOfCommon.insert( this );
+  if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() )
+    theSetOfCommon.insert( theOther );
+  // check common submeshes
+  map <int, SMESH_subMesh*>::const_iterator mapIt = _mapDepend.begin();
+  for( ; mapIt != _mapDepend.end(); mapIt++ )
+    if ( theOther->_mapDepend.find((*mapIt).first) != otherEnd )
+      theSetOfCommon.insert( (*mapIt).second );
+  return oldNb < theSetOfCommon.size();
+}
index b086771..4dbf179 100644 (file)
@@ -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<const SMESH_subMesh*>& theSetOfCommon ) const;
 
 protected:
   // ==================================================================
index 769c86a..394a318 100644 (file)
@@ -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)
index 34f6ed0..1b84f9a 100644 (file)
@@ -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;
index 43bd2cd..004b184 100644 (file)
@@ -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 <SMDS_SetIterator.hxx>
@@ -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<int,int>::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;
+}
+
 
 //================================================================================
 /*!
index bc979d3..ab64b33 100644 (file)
@@ -36,6 +36,7 @@
 
 // Qt includes
 #include <QMap>
+#include <QList>
 #include <QPointer>
 #include <QGroupBox>
 
@@ -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<LightApp_Dialog>      myActiveDlg;
   QPointer<SMESHGUI_PrecomputeDlg> myDlg;
   SMESHGUI_MeshEditPreview*      myPreviewDisplayer;
+  //! fields for mesh order
+  typedef QList<int>             TListOfInt;
+  typedef QList<TListOfInt>      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>& );
   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 (file)
index 0000000..2e4d7d0
--- /dev/null
@@ -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 <Qt>
+#include <QFrame>
+#include <QLabel>
+#include <QBoxLayout>
+#include <QSpacerItem>
+#include <QToolButton>
+#include <QListWidget>
+#include <QListWidgetItem>
+
+#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<int>& ids = (*idLIt);
+    if ( myMeshNames->count() )
+      addSeparator( myMeshNames );
+    QStringList::const_iterator nameIt = names.constBegin();
+    QList<int>::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<int>() );
+  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<int>() );
+  }
+  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<QListWidgetItem *> 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<QListWidgetItem *> 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 (file)
index 0000000..53ad8a9
--- /dev/null
@@ -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 <QGroupBox>
+
+// IDL includes
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Mesh)
+
+class QToolButton;
+class QListWidget;
+
+typedef QList<QStringList> ListListName;
+typedef QList<int>         ListId;
+typedef QList<ListId>  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 (file)
index 0000000..00b63da
--- /dev/null
@@ -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 <LightApp_SelectionMgr.h>
+#include <SALOME_ListIO.hxx>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_OverrideCursor.h>
+#include <SUIT_MessageBox.h>
+#include <SUIT_Desktop.h>
+
+// SALOME KERNEL includes
+#include <SALOMEDS_SObject.hxx>
+#include <SALOMEDSClient_SObject.hxx>
+
+// STL includes
+#include <set>
+
+//================================================================================
+/*!
+ * \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<int> 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<int, SMESH::SMESH_subMesh_var> 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<SMESH::SMESH_subMesh>( 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<int>& ids = *it;
+    SMESH::submesh_array_var subMeshList = new SMESH::submesh_array();
+    subMeshList->length( ids.count() );
+    QList<int>::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 (file)
index 0000000..9c6d6f9
--- /dev/null
@@ -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 <SALOMEconfig.h>
+#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
index d65356f..7a604d1 100644 (file)
             <translation>Create 2D mesh from 3D</translation>
         </message>
         <message>
+            <source>MEN_MESH_ORDER</source>
+            <translation>Change submesh priority</translation>
+        </message>
+        <message>
             <source>MEN_CREATE_GROUP</source>
             <translation>Create Group</translation>
         </message>
@@ -2064,6 +2068,10 @@ Consider saving your work before application crash</translation>
             <translation>Create 2D mesh from 3D</translation>
         </message>
         <message>
+            <source>STB_MESH_ORDER</source>
+            <translation>Change submesh priority</translation>
+        </message>
+        <message>
             <source>STB_CREATE_GROUP</source>
             <translation>Create Group</translation>
         </message>
@@ -2570,6 +2578,10 @@ Consider saving your work before application crash</translation>
             <translation>Create 2D mesh from 3D</translation>
         </message>
         <message>
+            <source>TOP_MESH_ORDER</source>
+            <translation>Change submesh priority</translation>
+        </message>
+        <message>
             <source>TOP_CREATE_GROUP</source>
             <translation>Create Group</translation>
         </message>
@@ -3379,6 +3391,15 @@ Please, create VTK viewer and try again</translation>
  created during preview operation.
  Do you want to remove all this submeshes?</translation>
         </message>
+        <message>
+            <source>SMESH_WRN_NOTHING_PREVIEW</source>
+            <translation>No mesh preview is available</translation>
+        </message>
+        <message>
+            <source>SMESH_REJECT_MESH_ORDER</source>
+            <translation>The submesh priority changed during preview operation.
+Do you want to restore original submesh priority?</translation>
+        </message>
     </context>
     <context>
         <name>SMESHGUI_ConvToQuadDlg</name>
@@ -4899,4 +4920,18 @@ It is impossible to read point coordinates from file</translation>
             <translation>Create Groups from Geometry</translation>
         </message>
     </context>
+    <context>
+        <name>SMESHGUI_MeshOrderDlg</name>
+        <message>
+            <source>SMESH_MESHORDER_TITLE</source>
+            <translation>Order of submesh in meshing process</translation>
+        </message>
+    </context>
+    <context>
+        <name>SMESHGUI_MeshOrderOp</name>
+        <message>
+            <source>SMESH_NO_CONCURENT_MESH</source>
+            <translation>No concurent submeshes detected</translation>
+        </message>
+    </context>
 </TS>
index 8d3cacc..4235800 100644 (file)
@@ -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();ind<n;ind++) {
+    //  Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue(ind) );
+    // SetMeshOrder
+    //for(int ind = 0, n = theCommand->GetNbArgs();ind<n;ind++) {
+    //  Handle(_pySubMesh) subMesh = theGen->FindSubMesh( 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 );
   }
index 8995818..f33cce6 100644 (file)
@@ -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)
index bc0369d..fa9dfbe 100644 (file)
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopoDS_Compound.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_MapIteratorOfMapOfShape.hxx>
 
 // STL Includes
+#include <algorithm>
 #include <string>
 #include <iostream>
 #include <sstream>
@@ -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<const SMESHDS_Hypothesis*> _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 SMESHDS_Hypothesis*>::const_iterator hypIt = _hypothesises.begin();
+    std::list <const SMESHDS_Hypothesis*>::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<SMESH_DimHyp*> TDimHypList;
+
+static void addDimHypInstance(const int               theDim, 
+                              const TopoDS_Shape&     theShape,
+                              const SMESH_Algo*       theAlgo,
+                              const SMESH_subMesh*    theSubMesh,
+                              const std::list <const SMESHDS_Hypothesis*>& 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 SMESHDS_Hypothesis*>::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<int, ::SMESH_subMesh*>::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 <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
+      std::list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
+      for( ; hypIt != hypList.end(); hypIt++ ) {
+        SMESH_Algo* anAlgo = 0;
+        const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
+        if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
+          anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(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<SMESH_DimHyp*>& 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<const SMESH_subMesh*>& theSubMeshList,
+  const SMESH_subMesh*             theSubMesh,
+  std::set<const SMESH_subMesh*>&  theCommon )
+{
+  if ( !theSubMesh )
+    return;
+  std::list<const SMESH_subMesh*>::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<const SMESH_subMesh*> subMeshToClear;
+    std::list<const SMESH_subMesh*> 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<const SMESH_subMesh*>::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()";
+  }
+}
index e8598de..99513b0 100644 (file)
@@ -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<int, SMESH_subMesh_i*> _mapSubMesh_i; //NRI
   std::map<int, ::SMESH_subMesh*> _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;
index 4789415..0b55798 100644 (file)
@@ -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):