\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.
+
*/
\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>
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
{
/*!
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
*/
if ( algo && !algo->NeedDescretBoundary() )
{
if ( algo->SupportSubmeshes() )
- smWithAlgoSupportingSubmeshes.push_back( smToCompute );
+ smWithAlgoSupportingSubmeshes.push_front( smToCompute );
else
{
smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE );
}
}
}
+
+ // ------------------------------------------------------------
+ // 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 )
{
// ----------------------------------------------------------
// 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)
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);
}
}
}
+
+ // ------------------------------------------------------------
+ // 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;
// ----------------------------------------------------------
// 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);
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
_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
{
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())
{
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"));
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
}
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;
}
}
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 )
{
{
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 )
{
aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
_mapSubMesh[index] = aSubMesh;
+ ClearMeshOrder();
}
return aSubMesh;
}
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;
+}
#include <TopoDS_Shape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-#include <list>
#include <map>
+#include <list>
class SMESH_Gen;
class SMESHDS_Document;
class SMESH_HypoFilter;
class TopoDS_Solid;
+typedef std::list<int> TListOfInt;
+typedef std::list<TListOfInt> TListOfListOfInt;
+
class SMESH_EXPORT SMESH_Mesh
{
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)
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&) {};
{
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++ )
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 ) )
( 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();
+}
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:
// ==================================================================
SMESHGUI_MeshInfosBox.h \
SMESHGUI_Make2DFrom3DOp.h \
SMESHGUI_FindElemByPointDlg.h \
+ SMESHGUI_MeshOrderDlg.h \
+ SMESHGUI_MeshOrderOp.h \
SMESH_SMESHGUI.hxx
# Libraries targets
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 \
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)
#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"
case 701: // COMPUTE MESH
case 711: // PRECOMPUTE MESH
case 712: // EVALUATE MESH
+ case 713: // MESH ORDER
{
if (checkLock(aStudy)) break;
startOperation( theCommandID );
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" );
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 );
createTool( 701, meshTb );
createTool( 711, meshTb );
createTool( 712, meshTb );
+ createTool( 713, meshTb );
createTool( separator(), meshTb );
createTool( 801, meshTb );
createTool( 806, meshTb );
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
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;
#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>
SMESHGUI_PrecomputeOp::SMESHGUI_PrecomputeOp()
: SMESHGUI_BaseComputeOp(),
myDlg( 0 ),
+ myOrderMgr( 0 ),
myActiveDlg( 0 ),
myPreviewDisplayer( 0 )
{
{
delete myDlg;
myDlg = 0;
+ delete myOrderMgr;
+ myOrderMgr = 0;
myActiveDlg = 0;
if ( myPreviewDisplayer )
delete myPreviewDisplayer;
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() ) );
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 );
}
void SMESHGUI_PrecomputeOp::onCompute()
{
myDlg->hide();
+ if (myOrderMgr && myOrderMgr->IsOrderChanged())
+ myOrderMgr->SetMeshOrder();
myMapShapeId.clear();
myActiveDlg = computeDlg();
computeMesh();
return;
}
+ bool isRestoreOrder = false;
if ( myActiveDlg == myDlg && !myMesh->_is_nil() && myMapShapeId.count() )
{
// ask to remove already computed mesh elements
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();
}
_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();
//================================================================================
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" ) );
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 );
return myPreviewMode->currentId();
}
+//================================================================================
+/*!
+ * \brief Returns current preview mesh mode
+*/
+//================================================================================
+
+SMESHGUI_MeshOrderBox* SMESHGUI_PrecomputeDlg::getMeshOrderBox() const
+{
+ return myOrderBox;
+}
+
//================================================================================
/*!
// Qt includes
#include <QMap>
+#include <QList>
#include <QPointer>
#include <QGroupBox>
protected slots:
};
+class SMESHGUI_MeshOrderMgr;
+
/*!
* \brief Operation to preview and compute a mesh and show computation errors
*/
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;
};
/*!
friend class SMESHGUI_PrecomputeOp;
};
+class SMESHGUI_MeshOrderBox;
+
/*!
* \brief Dialog to preview and compute a mesh and show computation errors
*/
void setPreviewModes( const QList<int>& );
int getPreviewMode() const;
+
+ SMESHGUI_MeshOrderBox* getMeshOrderBox() const;
signals:
void preview();
private:
+ SMESHGUI_MeshOrderBox* myOrderBox;
QPushButton* myPreviewBtn;
QtxComboBox* myPreviewMode;
};
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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
<source>MEN_2D_FROM_3D</source>
<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>
<source>STB_2D_FROM_3D</source>
<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>
<source>TOP_2D_FROM_3D</source>
<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>
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>
<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>
Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand );
myObjects.insert( make_pair( subMeshID, subMesh ));
}
+
id_mesh->second->Process( aCommand );
return aCommand;
}
// 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
{
"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 );
}
//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++ ) {
aDataset->WriteOnDisk( smIDs );
aDataset->CloseOnDisk();
//
- delete smIDs;
+ delete[] smIDs;
}
// Store node positions on sub-shapes (SMDS_Position):
}
}
}
-
}
}
}
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)
#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>
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()";
+ }
+}
public:
SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
SMESH_Gen_i* myGen_i,
- CORBA::Long studyId );
+ CORBA::Long studyId );
virtual ~SMESH_Mesh_i();
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
*/
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;
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):