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