From 47a901faf4f2156e8e4b3b429bb560e4122b4c2b Mon Sep 17 00:00:00 2001 From: vsr Date: Tue, 22 Jul 2008 09:10:35 +0000 Subject: [PATCH] Merge from BR_Dev_For_4_0 branch (from tag mergeto_BR_QT4_Dev_07Jul08) --- doc/salome/gui/Makefile.am | 15 +- doc/salome/gui/SMESH/doxyfile.in | 2 +- doc/salome/gui/SMESH/doxyfile_py.in | 26 +- doc/salome/gui/SMESH/images/buildcompound.png | Bin 18585 -> 64299 bytes .../gui/SMESH/input/building_compounds.doc | 8 +- .../gui/SMESH/input/smeshpy_interface.doc | 35 +- idl/SMESH_Gen.idl | 14 + idl/SMESH_Mesh.idl | 2 + src/SMDS/SMDS_MeshInfo.hxx | 1 + src/SMDS/SMDS_MeshNode.cxx | 2 +- src/SMDS/SMDS_MeshNode.hxx | 2 +- src/SMESH/SMESH_Block.cxx | 2 + src/SMESH/SMESH_MeshEditor.cxx | 2 +- src/SMESH/SMESH_OctreeNode.hxx | 2 + src/SMESH/SMESH_Pattern.cxx | 2 + src/SMESH/SMESH_Pattern.hxx | 2 + src/SMESH/SMESH_subMesh.cxx | 2 +- src/SMESHGUI/Makefile.am | 6 +- src/SMESHGUI/SMESHGUI.cxx | 24 +- src/SMESHGUI/SMESHGUI_BuildCompoundDlg.cxx | 28 +- src/SMESHGUI/SMESHGUI_BuildCompoundDlg.h | 1 + .../SMESHGUI_ExtrusionAlongPathDlg.cxx | 14 +- src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h | 1 + src/SMESHGUI/SMESHGUI_FileInfoDlg.cxx | 77 +++++ src/SMESHGUI/SMESHGUI_FileInfoDlg.h | 43 +++ src/SMESHGUI/SMESHGUI_RevolutionDlg.cxx | 156 ++++++++- src/SMESHGUI/SMESHGUI_RevolutionDlg.h | 149 +++++---- src/SMESHGUI/SMESHGUI_Selection.cxx | 19 ++ src/SMESHGUI/SMESHGUI_Selection.h | 2 + src/SMESHGUI/SMESH_msg_en.ts | 27 +- src/SMESH_I/SMESH_2smeshpy.cxx | 3 +- src/SMESH_I/SMESH_Gen_i.cxx | 158 ++++++++- src/SMESH_I/SMESH_Gen_i.hxx | 15 + src/SMESH_I/SMESH_MeshEditor_i.cxx | 51 +++ src/SMESH_I/SMESH_Mesh_i.cxx | 26 ++ src/SMESH_I/SMESH_Mesh_i.hxx | 5 + src/SMESH_SWIG/smeshDC.py | 310 ++++++++++++++---- src/StdMeshers/StdMeshers_Distribution.hxx | 2 + src/StdMeshers/StdMeshers_FaceSide.cxx | 13 +- src/StdMeshers/StdMeshers_MEFISTO_2D.cxx | 13 +- src/StdMeshers/StdMeshers_MEFISTO_2D.hxx | 2 +- src/StdMeshers/StdMeshers_Penta_3D.cxx | 2 + src/StdMeshers/StdMeshers_ProjectionUtils.cxx | 1 + 43 files changed, 1062 insertions(+), 205 deletions(-) create mode 100644 src/SMESHGUI/SMESHGUI_FileInfoDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_FileInfoDlg.h diff --git a/doc/salome/gui/Makefile.am b/doc/salome/gui/Makefile.am index e7c5dc8ae..66ce3648e 100644 --- a/doc/salome/gui/Makefile.am +++ b/doc/salome/gui/Makefile.am @@ -27,12 +27,23 @@ EXTRA_DIST+=SMESH doxygen=@DOXYGEN@ +# Below command replaces "smeshDC" by "smesh" except cases +# "ssmeshDC", "1smeshDC" and "esmeshDC" (these sequences +# can be found in file names and must not be replaces): +# +# sed 's/\([^s1e]\)smeshDC\|^smeshDC/\1smesh/g' $${filen} > ./tmp; +# usr_docs: cd ./SMESH; \ echo "Processing smeshDC.py file: "; \ $(doxygen) ./doxyfile_py; \ - sed 's|../../../share/salome|$(top_srcdir)|' ./doxyfile > ./doxyfile1; \ - mv -f doxyfile1 doxyfile; \ + cd ./smeshpy_doc; \ + filesl=`find .`; \ + for filen in $${filesl}; do \ + sed 's/\([^s1e]\)smeshDC\|^smeshDC/\1smesh/g' $${filen} > ./tmp; \ + mv -f tmp $${filen}; \ + done; \ + cd ..; \ echo "Running doxygen in directory: "`pwd`; \ $(doxygen) ./doxyfile; diff --git a/doc/salome/gui/SMESH/doxyfile.in b/doc/salome/gui/SMESH/doxyfile.in index 37ef2d45f..3aea83cc5 100755 --- a/doc/salome/gui/SMESH/doxyfile.in +++ b/doc/salome/gui/SMESH/doxyfile.in @@ -19,7 +19,7 @@ WARNINGS = YES INPUT = @srcdir@/input FILE_PATTERNS = *.doc IMAGE_PATH = @srcdir@/images -EXAMPLE_PATH = ../../../share/salome/src/SMESH_SWIG +EXAMPLE_PATH = @top_srcdir@/src/SMESH_SWIG #--------------------------------------------------------------------------- #HTML related options #--------------------------------------------------------------------------- diff --git a/doc/salome/gui/SMESH/doxyfile_py.in b/doc/salome/gui/SMESH/doxyfile_py.in index ff847e50e..617584ed9 100755 --- a/doc/salome/gui/SMESH/doxyfile_py.in +++ b/doc/salome/gui/SMESH/doxyfile_py.in @@ -7,7 +7,7 @@ CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = NO +REPEAT_BRIEF = YES ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = YES FULL_PATH_NAMES = NO @@ -38,7 +38,7 @@ HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = YES CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO +HIDE_SCOPE_NAMES = YES SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = NO @@ -81,6 +81,7 @@ INPUT = @top_srcdir@/src/SMESH_SWIG FILE_PATTERNS = smeshDC.py IMAGE_PATH = @srcdir@/images RECURSIVE = NO +EXAMPLE_PATH = @top_srcdir@/src/SMESH_SWIG #--------------------------------------------------------------------------- #HTML related options @@ -107,19 +108,26 @@ GENERATE_RTF = NO #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES +#CLASS_DIAGRAMS = YES +CLASS_DIAGRAMS = NO HIDE_UNDOC_RELATIONS = NO -HAVE_DOT = YES -CLASS_GRAPH = YES +#HAVE_DOT = YES +HAVE_DOT = NO +#CLASS_GRAPH = YES +CLASS_GRAPH = NO COLLABORATION_GRAPH = NO GROUP_GRAPHS = NO UML_LOOK = NO -TEMPLATE_RELATIONS = YES -INCLUDE_GRAPH = YES +#TEMPLATE_RELATIONS = YES +#INCLUDE_GRAPH = YES +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO INCLUDED_BY_GRAPH = NO CALL_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES +#GRAPHICAL_HIERARCHY = YES +#DIRECTORY_GRAPH = YES +GRAPHICAL_HIERARCHY = NO +DIRECTORY_GRAPH = NO DOT_IMAGE_FORMAT = jpg DOT_PATH = DOTFILE_DIRS = diff --git a/doc/salome/gui/SMESH/images/buildcompound.png b/doc/salome/gui/SMESH/images/buildcompound.png index 79a6073f2976063b2faba4b60743127f94f086a1..1a5bea1666949ed8f290ad976a047604ec02e0c2 100755 GIT binary patch literal 64299 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 literal 18585 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 z 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 G{{I75(ashC diff --git a/doc/salome/gui/SMESH/input/building_compounds.doc b/doc/salome/gui/SMESH/input/building_compounds.doc index 5905565d5..d42f38866 100644 --- a/doc/salome/gui/SMESH/input/building_compounds.doc +++ b/doc/salome/gui/SMESH/input/building_compounds.doc @@ -34,6 +34,12 @@ become the elements of Group1 on the Compound_Mesh, or becomes Group1_2. See \ref grouping_elements_page "Creating Groups" for more information about groups. +
  • Create common groups for initial meshes checkbox permits to +automatically create groups of all elements of the same type +(nodes, edges, faces and volumes) for the resulting mesh from the +elements +of the initial meshes. +
  • You can simply unite meshes or choose to Merge coincident nodes and elements, in which case it is possible to define the \b Tolerance for this operation.
  • @@ -43,4 +49,4 @@ for this operation. \image html image160.gif -*/ \ No newline at end of file +*/ diff --git a/doc/salome/gui/SMESH/input/smeshpy_interface.doc b/doc/salome/gui/SMESH/input/smeshpy_interface.doc index 4fbf3d3b5..6e2b421c9 100644 --- a/doc/salome/gui/SMESH/input/smeshpy_interface.doc +++ b/doc/salome/gui/SMESH/input/smeshpy_interface.doc @@ -5,6 +5,37 @@ \n Python package smesh defines several classes, destined for easy and clear mesh creation and edition (see the \ref introduction_to_mesh_python_page "example"). -\n Also, please see \ref smeshDC "documentation for smesh.py" +\n Please draw your attention to the below notes before address to +the \ref smeshDC "documentation for smesh.py" -*/ \ No newline at end of file +\n 1. The main page of the \ref smeshDC "documentation for smesh.py" + contains a list of data structures and a list of functions, + provided by the package smesh.py. The first item in the data + structures list (\ref smeshDC::smeshDC "class smesh") also + represents documentation for methods of the package smesh.py itself. + +\n 2. Package smesh.py gives interface to create and manage + meshes. Please, use it to create an empty mesh or to import + it from data file. + +\n 3. Once you have created a mesh, you can manage it via its own + methods. See \ref smeshDC::Mesh "class Mesh" documentation for + them (it is also accessible by the second item "class Mesh" in the + data structures list). + +\n 4. Class Mesh allows to assign algorithms to a mesh. +\n \t Please note, that there are always available some algorithms, + included in standard Salome installation: + - REGULAR(1D), COMPOSITE(1D), MEFISTO(2D), Quadrangle(2D), Hexa(3D), etc. + +\n Also there are some algorithms, which can be installed optionally, +\n some of them are based on open-source meshers: + - NETGEN(1D-2D,2D,1D-2D-3D,3D), + +\n others are based on commercial meshers: + - GHS3D(3D). + +\n \t To add hypotheses, please use interfaces, provided by the + assigned algorithms. + +*/ diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index 96083e189..362bea45a 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -275,6 +275,20 @@ module SMESH in double theMergeTolerance) raises ( SALOME::SALOME_Exception ); + /*! + * Concatenate the given meshes into one mesh. + * Union groups with the same name and type if + * theUniteIdenticalGroups flag is true. + * Merge coincident nodes and elements if + * theMergeNodesAndElements flag is true. + * Create the groups of all elements from initial meshes. + */ + SMESH_Mesh ConcatenateWithGroups(in mesh_array theMeshesArray, + in boolean theUniteIdenticalGroups, + in boolean theMergeNodesAndElements, + in double theMergeTolerance) + raises ( SALOME::SALOME_Exception ); + /*! * \brief Return id of object, registered in current study context * diff --git a/idl/SMESH_Mesh.idl b/idl/SMESH_Mesh.idl index b04164177..fd70cc9f5 100644 --- a/idl/SMESH_Mesh.idl +++ b/idl/SMESH_Mesh.idl @@ -625,6 +625,8 @@ module SMESH */ double_array BaryCenter(in long id); + /*! Gets information about imported MED file */ + SALOME_MED::MedFileInfo GetMEDFileInfo(); }; interface SMESH_subMesh : SALOME::GenericObj, SMESH_IDSource diff --git a/src/SMDS/SMDS_MeshInfo.hxx b/src/SMDS/SMDS_MeshInfo.hxx index a7694837b..8f541c267 100644 --- a/src/SMDS/SMDS_MeshInfo.hxx +++ b/src/SMDS/SMDS_MeshInfo.hxx @@ -2,6 +2,7 @@ // Created : Mon Sep 24 18:32:41 2007 // Author : Edward AGAPOV (eap) +using namespace std; #ifndef SMDS_MeshInfo_HeaderFile #define SMDS_MeshInfo_HeaderFile diff --git a/src/SMDS/SMDS_MeshNode.cxx b/src/SMDS/SMDS_MeshNode.cxx index b7a1cb117..587aee90a 100644 --- a/src/SMDS/SMDS_MeshNode.cxx +++ b/src/SMDS/SMDS_MeshNode.cxx @@ -246,7 +246,7 @@ bool SMDS_MeshNode::emptyInverseElements() */ //================================================================================ -int SMDS_MeshNode::NbInverseNodes(SMDSAbs_ElementType type) const +int SMDS_MeshNode::NbInverseElements(SMDSAbs_ElementType type) const { if ( type == SMDSAbs_All ) return myInverseElements.Extent(); diff --git a/src/SMDS/SMDS_MeshNode.hxx b/src/SMDS/SMDS_MeshNode.hxx index d195fbdfd..585f59bf9 100644 --- a/src/SMDS/SMDS_MeshNode.hxx +++ b/src/SMDS/SMDS_MeshNode.hxx @@ -47,7 +47,7 @@ class SMDS_EXPORT SMDS_MeshNode:public SMDS_MeshElement void ClearInverseElements(); bool emptyInverseElements(); SMDS_ElemIteratorPtr GetInverseElementIterator(SMDSAbs_ElementType type=SMDSAbs_All) const; - int NbInverseNodes(SMDSAbs_ElementType type=SMDSAbs_All) const; + int NbInverseElements(SMDSAbs_ElementType type=SMDSAbs_All) const; void SetPosition(const SMDS_PositionPtr& aPos); const SMDS_PositionPtr& GetPosition() const; SMDSAbs_ElementType GetType() const; diff --git a/src/SMESH/SMESH_Block.cxx b/src/SMESH/SMESH_Block.cxx index 6a50ff019..59d48a978 100644 --- a/src/SMESH/SMESH_Block.cxx +++ b/src/SMESH/SMESH_Block.cxx @@ -21,6 +21,8 @@ // Created : Mon Aug 2 10:30:00 2004 // Author : Edward AGAPOV (eap) +using namespace std; + #include "SMESH_Block.hxx" #include diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index b858c372f..6b94beafe 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -6871,7 +6871,7 @@ int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, vector::iterator nIt = mediumNodes.begin(); for ( ; nIt != mediumNodes.end(); ++nIt ) { const SMDS_MeshNode* n = *nIt; - if ( n->NbInverseNodes() == 0 ) { + if ( n->NbInverseElements() == 0 ) { if ( n->GetPosition()->GetShapeId() != theShapeID ) meshDS->RemoveFreeNode( n, meshDS->MeshElements ( n->GetPosition()->GetShapeId() )); diff --git a/src/SMESH/SMESH_OctreeNode.hxx b/src/SMESH/SMESH_OctreeNode.hxx index 62cddf688..5a553027a 100644 --- a/src/SMESH/SMESH_OctreeNode.hxx +++ b/src/SMESH/SMESH_OctreeNode.hxx @@ -27,6 +27,8 @@ // Author : Nicolas Geimer & Aurélien Motteux (OCC) // Module : SMESH +using namespace std; + #ifndef _SMESH_OCTREENODE_HXX_ #define _SMESH_OCTREENODE_HXX_ diff --git a/src/SMESH/SMESH_Pattern.cxx b/src/SMESH/SMESH_Pattern.cxx index 4d3fe36f6..1ab83c71e 100644 --- a/src/SMESH/SMESH_Pattern.cxx +++ b/src/SMESH/SMESH_Pattern.cxx @@ -21,6 +21,8 @@ // Created : Mon Aug 2 10:30:00 2004 // Author : Edward AGAPOV (eap) +using namespace std; + #include "SMESH_Pattern.hxx" #include diff --git a/src/SMESH/SMESH_Pattern.hxx b/src/SMESH/SMESH_Pattern.hxx index 2746f15cc..d5288bb1d 100644 --- a/src/SMESH/SMESH_Pattern.hxx +++ b/src/SMESH/SMESH_Pattern.hxx @@ -21,6 +21,8 @@ // Created : Mon Aug 2 10:30:00 2004 // Author : Edward AGAPOV (eap) +using namespace std; + #ifndef SMESH_Pattern_HeaderFile #define SMESH_Pattern_HeaderFile diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index bbb5fa96a..3a1c9fa0d 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1195,7 +1195,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) while (itn->more()) { const SMDS_MeshNode * node = itn->next(); //MESSAGE( " RM node: "<GetID()); - if ( node->NbInverseNodes() == 0 ) + if ( node->NbInverseElements() == 0 ) meshDS->RemoveFreeNode(node, subMeshDS); else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another meshDS->RemoveNode(node); diff --git a/src/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 5cddef784..6e451fb7d 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -99,7 +99,8 @@ dist_libSMESH_la_SOURCES = \ SMESHGUI_BuildCompoundDlg.cxx \ SMESHGUI_ComputeDlg.cxx \ SMESHGUI_MakeNodeAtPointDlg.cxx \ - SMESHGUI_MeshEditPreview.cxx + SMESHGUI_MeshEditPreview.cxx \ + SMESHGUI_FileInfoDlg.cxx MOC_FILES = \ SMESHGUI_moc.cxx \ @@ -149,7 +150,8 @@ MOC_FILES = \ SMESHGUI_ConvToQuadOp_moc.cxx \ SMESHGUI_BuildCompoundDlg_moc.cxx \ SMESHGUI_ComputeDlg_moc.cxx \ - SMESHGUI_MakeNodeAtPointDlg_moc.cxx + SMESHGUI_MakeNodeAtPointDlg_moc.cxx \ + SMESHGUI_FileInfoDlg_moc.cxx nodist_libSMESH_la_SOURCES= \ $(MOC_FILES) diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 59c93d31a..f07927491 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -65,6 +65,7 @@ #include "SMESHGUI_MakeNodeAtPointDlg.h" #include "SMESHGUI_BuildCompoundDlg.h" #include "SMESHGUI_ComputeDlg.h" +#include "SMESHGUI_FileInfoDlg.h" #include "SMESHGUI_Utils.h" #include "SMESHGUI_MeshUtils.h" @@ -110,7 +111,7 @@ // IDL includes #include #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes) -#include CORBA_SERVER_HEADER(SMESH_MeshEditor) +#include CORBA_CLIENT_HEADER(SMESH_MeshEditor) // Qt includes // #define INCLUDE_MENUITEM_DEF // VSR commented ???????? @@ -1263,6 +1264,25 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) break; } + case 150: //MED FILE INFORMATION + { + SALOME_ListIO selected; + LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr(); + if( aSel ) + aSel->selectedObjects( selected ); + if( selected.Extent() ) + { + Handle(SALOME_InteractiveObject) anIObject = selected.First(); + SMESH::SMESH_Mesh_var aMesh = SMESH::IObjectToInterface(anIObject); + if ( !aMesh->_is_nil() ) + { + SMESHGUI_FileInfoDlg dlg( desktop(), aMesh->GetMEDFileInfo() ); + dlg.exec(); + } + } + break; + } + case 122: // EXPORT MED case 121: case 123: @@ -2409,6 +2429,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 125, "EXPORT_MED" ); createSMESHAction( 126, "EXPORT_UNV" ); createSMESHAction( 141, "EXPORT_STL" ); + createSMESHAction( 150, "FILE_INFO" ); createSMESHAction( 33, "DELETE", "ICON_DELETE", Qt::Key_Delete ); createSMESHAction( 5105, "SEL_FILTER_LIB" ); createSMESHAction( 701, "COMPUTE", "ICON_COMPUTE" ); @@ -2740,6 +2761,7 @@ void SMESHGUI::initialize( CAM_Application* app ) // popup for object browser + createPopupItem( 150, OB, mesh, "&& selcount=1 && isImported" ); // FILE INFORMATION createPopupItem( 704, OB, mesh, "&& isComputable"); // EDIT_MESHSUBMESH createPopupItem( 704, OB, subMesh, "&& isComputable" ); // EDIT_MESHSUBMESH createPopupItem( 803, OB, group ); // EDIT_GROUP diff --git a/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.cxx b/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.cxx index 6bfeddee0..dcfaa7e1b 100644 --- a/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.cxx @@ -123,12 +123,15 @@ SMESHGUI_BuildCompoundDlg::SMESHGUI_BuildCompoundDlg( SMESHGUI* theModule ) TextLabelMeshes = new QLabel(tr("MESHES"), GroupArgs); SelectButton = new QPushButton(GroupArgs); SelectButton->setIcon(image1); + SelectButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); LineEditMeshes = new QLineEdit(GroupArgs); LineEditMeshes->setReadOnly(true); TextLabelUnion = new QLabel(tr("PROCESSING_IDENTICAL_GROUPS"), GroupArgs); ComboBoxUnion = new QComboBox(GroupArgs); + CheckBoxCommon = new QCheckBox(tr("CREATE_COMMON_GROUPS"), GroupArgs); + CheckBoxMerge = new QCheckBox(tr("MERGE_NODES_AND_ELEMENTS"), GroupArgs); TextLabelTol = new QLabel(tr("SMESH_TOLERANCE"), GroupArgs); @@ -141,9 +144,10 @@ SMESHGUI_BuildCompoundDlg::SMESHGUI_BuildCompoundDlg( SMESHGUI* theModule ) GroupArgsLayout->addWidget(LineEditMeshes, 0, 2, 1, 2); GroupArgsLayout->addWidget(TextLabelUnion, 1, 0, 1, 3); GroupArgsLayout->addWidget(ComboBoxUnion, 1, 3); - GroupArgsLayout->addWidget(CheckBoxMerge, 2, 0, 1, 4); - GroupArgsLayout->addWidget(TextLabelTol, 3, 0, 1, 2); - GroupArgsLayout->addWidget(SpinBoxTol, 3, 2, 1, 2); + GroupArgsLayout->addWidget(CheckBoxCommon, 2, 0, 1, 4); + GroupArgsLayout->addWidget(CheckBoxMerge, 3, 0, 1, 4); + GroupArgsLayout->addWidget(TextLabelTol, 4, 0, 1, 2); + GroupArgsLayout->addWidget(SpinBoxTol, 4, 2, 1, 2); /***************************************************************/ GroupButtons = new QGroupBox(this); @@ -287,12 +291,18 @@ bool SMESHGUI_BuildCompoundDlg::ClickOnApply() SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen(); // concatenate meshes - SMESH::SMESH_Mesh_var aCompoundMesh = - aSMESHGen->Concatenate(myMeshArray, - !(ComboBoxUnion->currentIndex()), - CheckBoxMerge->isChecked(), - SpinBoxTol->GetValue()); - + SMESH::SMESH_Mesh_var aCompoundMesh; + if(CheckBoxCommon->isChecked()) + aCompoundMesh = aSMESHGen->ConcatenateWithGroups(myMeshArray, + !(ComboBoxUnion->currentIndex()), + CheckBoxMerge->isChecked(), + SpinBoxTol->GetValue()); + else + aCompoundMesh = aSMESHGen->Concatenate(myMeshArray, + !(ComboBoxUnion->currentIndex()), + CheckBoxMerge->isChecked(), + SpinBoxTol->GetValue()); + SMESH::SetName( SMESH::FindSObject( aCompoundMesh ), LineEditName->text() ); mySMESHGUI->updateObjBrowser(); } catch(...) { diff --git a/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.h b/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.h index f71222064..a05fd5fe3 100644 --- a/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.h +++ b/src/SMESHGUI/SMESHGUI_BuildCompoundDlg.h @@ -100,6 +100,7 @@ private: QLineEdit* LineEditMeshes; QLabel* TextLabelUnion; QComboBox* ComboBoxUnion; + QCheckBox* CheckBoxCommon; QCheckBox* CheckBoxMerge; QLabel* TextLabelTol; SMESHGUI_SpinBox* SpinBoxTol; diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx index b0656be9e..435a7f4c2 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.cxx @@ -253,11 +253,14 @@ SMESHGUI_ExtrusionAlongPathDlg::SMESHGUI_ExtrusionAlongPathDlg( SMESHGUI* theMod AngleSpin = new SMESHGUI_SpinBox(AnglesGrp); + LinearAnglesCheck = new QCheckBox(tr("LINEAR_ANGLES"), AnglesGrp); + // layouting AnglesGrpLayout->addWidget(AnglesList, 0, 0, 4, 1); AnglesGrpLayout->addWidget(AddAngleButton, 0, 1); AnglesGrpLayout->addWidget(RemoveAngleButton, 2, 1); AnglesGrpLayout->addWidget(AngleSpin, 0, 2); + AnglesGrpLayout->addWidget(LinearAnglesCheck, 4, 0); AnglesGrpLayout->setRowMinimumHeight(1, 10); AnglesGrpLayout->setRowStretch(3, 10); @@ -581,17 +584,20 @@ bool SMESHGUI_ExtrusionAlongPathDlg::ClickOnApply() try { SUIT_OverrideCursor wc; SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); + if ( LinearAnglesCheck->isChecked() ) + anAngles = aMeshEditor->LinearAnglesVariation( myPathMesh, myPathShape, anAngles ); + SMESH::SMESH_MeshEditor::Extrusion_Error retVal; if ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() ) SMESH::ListOfGroups_var groups = - aMeshEditor->ExtrusionAlongPathMakeGroups(anElementsId.inout(), myPathMesh, + aMeshEditor->ExtrusionAlongPathMakeGroups(anElementsId, myPathMesh, myPathShape, aNodeStart, - AnglesGrp->isChecked(), anAngles.inout(), + AnglesGrp->isChecked(), anAngles, BasePointGrp->isChecked(), aBasePoint, retVal); else - retVal = aMeshEditor->ExtrusionAlongPath(anElementsId.inout(), myPathMesh, + retVal = aMeshEditor->ExtrusionAlongPath(anElementsId, myPathMesh, myPathShape, aNodeStart, - AnglesGrp->isChecked(), anAngles.inout(), + AnglesGrp->isChecked(), anAngles, BasePointGrp->isChecked(), aBasePoint); //wc.stop(); diff --git a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h index 82e019157..6885b738e 100644 --- a/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h +++ b/src/SMESHGUI/SMESHGUI_ExtrusionAlongPathDlg.h @@ -113,6 +113,7 @@ private: QLineEdit* PathShapeLineEdit; QToolButton* SelectStartPointButton; QLineEdit* StartPointLineEdit; + QCheckBox* LinearAnglesCheck; QGroupBox* AnglesGrp; QListWidget* AnglesList; QToolButton* AddAngleButton; diff --git a/src/SMESHGUI/SMESHGUI_FileInfoDlg.cxx b/src/SMESHGUI/SMESHGUI_FileInfoDlg.cxx new file mode 100644 index 000000000..110b57a5d --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_FileInfoDlg.cxx @@ -0,0 +1,77 @@ +// SMESH SMESHGUI : GUI for SMESH component +// +// Copyright (C) 2003 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_FileInfoDlg.cxx +// Author : Alexandre SOLOVYOV, Open CASCADE S.A.S. (alexander.solovyov@opencascade.com) +// + +#include "SMESHGUI_FileInfoDlg.h" + +#include + +#include +#include +#include + +SMESHGUI_FileInfoDlg::SMESHGUI_FileInfoDlg( QWidget* parent, SALOME_MED::MedFileInfo* inf ) + : QtxDialog( parent, true, true, QtxDialog::OK ) +{ + setWindowTitle( tr( "CAPTION" ) ); + setSizeGripEnabled( true ); + + QLineEdit* fname = new QLineEdit( mainFrame() ); + fname->setReadOnly( true ); + QLineEdit* fsize = new QLineEdit( mainFrame() ); + fsize->setReadOnly( true ); + QLineEdit* medversion = new QLineEdit( mainFrame() ); + medversion->setReadOnly( true ); + fname->setMinimumWidth( 300 ); + + QGridLayout* lay = new QGridLayout( mainFrame() ); + lay->setMargin( 5 ); lay->setSpacing( 5 ); + lay->addWidget( new QLabel( tr( "FILE_NAME" ), mainFrame() ), 0, 0 ); + lay->addWidget( fname, 0, 1 ); + lay->addWidget( new QLabel( tr( "FILE_SIZE" ), mainFrame() ), 1, 0 ); + lay->addWidget( fsize, 1, 1 ); + lay->addWidget( new QLabel( tr( "MED_VERSION" ), mainFrame() ), 2, 0 ); + lay->addWidget( medversion, 2, 1 ); + + fname->setText( (char*)inf->fileName ); + fname->home( false ); + fsize->setText( QString::number( inf->fileSize ) ); + + QString version; + if( inf->major>=0 ) + { + version = QString::number( inf->major ); + if( inf->minor>=0 ) + { + version += "." + QString::number( inf->minor ); + if( inf->release>=0 ) + version += "." + QString::number( inf->release ); + } + } + medversion->setText( version ); +} + +SMESHGUI_FileInfoDlg::~SMESHGUI_FileInfoDlg() +{ +} diff --git a/src/SMESHGUI/SMESHGUI_FileInfoDlg.h b/src/SMESHGUI/SMESHGUI_FileInfoDlg.h new file mode 100644 index 000000000..c6c1138fa --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_FileInfoDlg.h @@ -0,0 +1,43 @@ +// SMESH SMESHGUI : GUI for SMESH component +// +// Copyright (C) 2003 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_FileInfoDlg.h +// Author : Alexandre SOLOVYOV, Open CASCADE S.A.S. (alexander.solovyov@opencascade.com) +// + +#ifndef SMESHGUI_FILEINFODLG_H +#define SMESHGUI_FILEINFODLG_H + +#include + +#include +#include CORBA_CLIENT_HEADER(MED) + +class SMESHGUI_FileInfoDlg : public QtxDialog +{ + Q_OBJECT + +public: + SMESHGUI_FileInfoDlg( QWidget*, SALOME_MED::MedFileInfo* ); + virtual ~SMESHGUI_FileInfoDlg(); +}; + +#endif // SMESHGUI_FILEINFODLG_H diff --git a/src/SMESHGUI/SMESHGUI_RevolutionDlg.cxx b/src/SMESHGUI/SMESHGUI_RevolutionDlg.cxx index 6e7587fe9..037a355b0 100644 --- a/src/SMESHGUI/SMESHGUI_RevolutionDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_RevolutionDlg.cxx @@ -32,6 +32,7 @@ #include "SMESHGUI_VTKUtils.h" #include "SMESHGUI_MeshUtils.h" #include "SMESHGUI_IdValidator.h" +#include "SMESHGUI_MeshEditPreview.h" #include #include @@ -47,10 +48,12 @@ #include #include +#include #include #include #include +#include // OCCT includes #include @@ -87,6 +90,8 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule ) mySMESHGUI( theModule ), mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ) { + mySimulation = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( mySMESHGUI )); + SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI ); QPixmap image0 ( mgr->loadPixmap("SMESH", tr("ICON_DLG_EDGE"))); QPixmap image1 ( mgr->loadPixmap("SMESH", tr("ICON_DLG_TRIANGLE"))); @@ -187,18 +192,38 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule ) GroupAxisLayout->addWidget(TextLabelDZ, 1, 6); GroupAxisLayout->addWidget(SpinBox_DZ, 1, 7); - // Controls for angle defining - TextLabelAngle = new QLabel(tr("SMESH_ANGLE"), GroupArguments); - SpinBox_Angle = new SMESHGUI_SpinBox(GroupArguments); + // Controls for angle defining & number of steps defining + GroupAngleBox = new QGroupBox(tr("SMESH_ANGLE"), GroupArguments); + GroupAngle = new QButtonGroup(GroupAngleBox); + QGridLayout* GroupAngleLayout = new QGridLayout(GroupAngleBox); + GroupAngleLayout->setSpacing(6); + GroupAngleLayout->setMargin(11); + + RadioButton3 = new QRadioButton(tr("ANGLE_BY_STEP"), GroupAngleBox); + RadioButton4 = new QRadioButton(tr("TOTAL_ANGLE"), GroupAngleBox); + GroupAngle->addButton(RadioButton3, 0); + GroupAngle->addButton(RadioButton4, 1); + + TextLabelAngle = new QLabel(tr("SMESH_ANGLE"), GroupAngleBox); + SpinBox_Angle = new SMESHGUI_SpinBox(GroupAngleBox); - // Controls for nb. steps defining - TextLabelNbSteps = new QLabel(tr("SMESH_NUMBEROFSTEPS"), GroupArguments); - SpinBox_NbSteps = new QSpinBox(GroupArguments); + TextLabelNbSteps = new QLabel(tr("SMESH_NUMBEROFSTEPS"), GroupAngleBox); + SpinBox_NbSteps = new QSpinBox(GroupAngleBox); + + GroupAngleLayout->addWidget(RadioButton3, 0, 0); + GroupAngleLayout->addWidget(RadioButton4, 0, 1); + GroupAngleLayout->addWidget(TextLabelAngle, 1, 0); + GroupAngleLayout->addWidget(SpinBox_Angle, 1, 1); + GroupAngleLayout->addWidget(TextLabelNbSteps, 2, 0); + GroupAngleLayout->addWidget(SpinBox_NbSteps, 2, 1); // Controls for tolerance defining TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), GroupArguments); SpinBox_Tolerance = new SMESHGUI_SpinBox(GroupArguments); + // Control for mesh preview + CheckBoxPreview = new QCheckBox(tr("PREVIEW"), GroupArguments); + // CheckBox for groups generation MakeGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments); MakeGroupsCheck->setChecked(true); @@ -208,12 +233,10 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule ) GroupArgumentsLayout->addWidget(LineEditElements, 0, 2); GroupArgumentsLayout->addWidget(CheckBoxMesh, 1, 0, 1, 3); GroupArgumentsLayout->addWidget(GroupAxis, 2, 0, 1, 3); - GroupArgumentsLayout->addWidget(TextLabelAngle, 3, 0, 1, 2); - GroupArgumentsLayout->addWidget(SpinBox_Angle, 3, 2); - GroupArgumentsLayout->addWidget(TextLabelNbSteps, 4, 0, 1, 2); - GroupArgumentsLayout->addWidget(SpinBox_NbSteps, 4, 2); - GroupArgumentsLayout->addWidget(TextLabelTolerance, 5, 0, 1, 2); - GroupArgumentsLayout->addWidget(SpinBox_Tolerance, 5, 2); + GroupArgumentsLayout->addWidget(GroupAngleBox, 3, 0, 1, 3); + GroupArgumentsLayout->addWidget(TextLabelTolerance, 4, 0, 1, 2); + GroupArgumentsLayout->addWidget(SpinBox_Tolerance, 4, 2); + GroupArgumentsLayout->addWidget(CheckBoxPreview, 5, 0, 1, 3); GroupArgumentsLayout->addWidget(MakeGroupsCheck, 6, 0, 1, 3); /***************************************************************/ @@ -253,6 +276,8 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule ) SpinBox_DY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); SpinBox_DZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, 3); + RadioButton3->setChecked(true); + SpinBox_Angle->RangeStepAndValidator(COORD_MIN, COORD_MAX, 5.0, 3); SpinBox_NbSteps->setRange(1, 999999); @@ -291,6 +316,10 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule ) connect(SelectPointButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); connect(SelectVectorButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(SpinBox_X, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(SpinBox_Y, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(SpinBox_Z, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(onVectorChanged())); connect(SpinBox_DY, SIGNAL(valueChanged(double)), this, SLOT(onVectorChanged())); connect(SpinBox_DZ, SIGNAL(valueChanged(double)), this, SLOT(onVectorChanged())); @@ -302,6 +331,12 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule ) connect(LineEditElements, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&))); connect(CheckBoxMesh, SIGNAL(toggled(bool)), SLOT(onSelectMesh(bool))); + connect(GroupAngle, SIGNAL(buttonClicked(int)), this, SLOT(toDisplaySimulation())); + connect(SpinBox_Angle, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(SpinBox_NbSteps, SIGNAL(valueChanged(int)), this, SLOT(toDisplaySimulation())); + connect(SpinBox_Tolerance, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation())); + connect(CheckBoxPreview, SIGNAL(toggled(bool)), this, SLOT(onDisplaySimulation(bool))); + ConstructorsClicked(0); SelectionIntoArgument(); } @@ -312,7 +347,7 @@ SMESHGUI_RevolutionDlg::SMESHGUI_RevolutionDlg( SMESHGUI* theModule ) //================================================================================= SMESHGUI_RevolutionDlg::~SMESHGUI_RevolutionDlg() { - // no need to delete child widgets, Qt does it all for us + delete mySimulation; } //================================================================================= @@ -345,6 +380,8 @@ void SMESHGUI_RevolutionDlg::Init (bool ResetControls) CheckBoxMesh->setChecked(false); onSelectMesh(false); + CheckBoxPreview->setChecked(false); + onDisplaySimulation(false); } } @@ -354,7 +391,17 @@ void SMESHGUI_RevolutionDlg::Init (bool ResetControls) //================================================================================= void SMESHGUI_RevolutionDlg::ConstructorsClicked (int constructorId) { - disconnect(mySelectionMgr, 0, this, 0); + //disconnect(mySelectionMgr, 0, this, 0); + + SALOME_ListIO io; + mySelectionMgr->selectedObjects( io ); + SALOME_ListIO aList; + mySelectionMgr->setSelectedObjects( aList ); +// LineEditElements->clear(); + myNbOkElements = 0; + buttonApply->setEnabled(false); + buttonOk->setEnabled(false); + mySimulation->SetVisibility(false); Selection_Mode aSelMode = ActorSelection; @@ -389,7 +436,8 @@ void SMESHGUI_RevolutionDlg::ConstructorsClicked (int constructorId) if (CheckBoxMesh->isChecked()) onSelectMesh(true); - connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument())); + //connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument())); + mySelectionMgr->setSelectedObjects( io ); } //================================================================================= @@ -423,6 +471,9 @@ void SMESHGUI_RevolutionDlg::ClickOnApply() long aNbSteps = (long)SpinBox_NbSteps->value(); double aTolerance = SpinBox_Tolerance->GetValue(); + if ( GroupAngle->checkedId() == 1 ) + anAngle = anAngle/aNbSteps; + try { SUIT_OverrideCursor aWaitCursor; SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); @@ -544,6 +595,7 @@ void SMESHGUI_RevolutionDlg::onTextChange (const QString& theNewText) buttonOk->setEnabled(true); buttonApply->setEnabled(true); } + onDisplaySimulation(true); myBusy = false; } @@ -714,6 +766,8 @@ void SMESHGUI_RevolutionDlg::SelectionIntoArgument() buttonOk->setEnabled(true); buttonApply->setEnabled(true); } + + onDisplaySimulation(true); } //================================================================================= @@ -729,6 +783,7 @@ void SMESHGUI_RevolutionDlg::SetEditCurrentArgument() mySelectionMgr->clearFilters(); if (send == SelectElementsButton) { + mySimulation->SetVisibility(false); myEditCurrentArgument = (QWidget*)LineEditElements; SMESH::SetPointRepresentation(false); if (CheckBoxMesh->isChecked()) { @@ -842,6 +897,7 @@ void SMESHGUI_RevolutionDlg::onSelectMesh (bool toSelectMesh) if (myEditCurrentArgument != LineEditElements) { LineEditElements->clear(); + mySimulation->SetVisibility(false); return; } @@ -870,6 +926,7 @@ void SMESHGUI_RevolutionDlg::onSelectMesh (bool toSelectMesh) LineEditElements->setReadOnly(false); LineEditElements->setValidator(myIdValidator); onTextChange(LineEditElements->text()); + mySimulation->SetVisibility(false); } SelectionIntoArgument(); @@ -908,6 +965,7 @@ void SMESHGUI_RevolutionDlg::onVectorChanged() buttonOk->setEnabled(false); buttonApply->setEnabled(false); } + onDisplaySimulation(true); } //================================================================================= @@ -925,3 +983,71 @@ void SMESHGUI_RevolutionDlg::keyPressEvent( QKeyEvent* e ) ClickOnHelp(); } } + +//================================================================================= +// function : toDisplaySimulation() +// purpose : +//================================================================================= +void SMESHGUI_RevolutionDlg::toDisplaySimulation() +{ + onDisplaySimulation(true); +} + +//================================================================================= +// function : onDisplaySimulation() +// purpose : +//================================================================================= +void SMESHGUI_RevolutionDlg::onDisplaySimulation(bool toDisplayPreview) +{ + if (CheckBoxPreview->isChecked() && toDisplayPreview) + { + //display preview + if (myNbOkElements && IsAxisOk()) + { + QStringList aListElementsId = myElementsId.split(" ", QString::SkipEmptyParts); + + SMESH::long_array_var anElementsId = new SMESH::long_array; + + anElementsId->length(aListElementsId.count()); + for (int i = 0; i < aListElementsId.count(); i++) + anElementsId[i] = aListElementsId[i].toInt(); + + SMESH::AxisStruct anAxis; + + anAxis.x = SpinBox_X->GetValue(); + anAxis.y = SpinBox_Y->GetValue(); + anAxis.z = SpinBox_Z->GetValue(); + anAxis.vx = SpinBox_DX->GetValue(); + anAxis.vy = SpinBox_DY->GetValue(); + anAxis.vz = SpinBox_DZ->GetValue(); + + double anAngle = (SpinBox_Angle->GetValue())*PI/180; + long aNbSteps = (long)SpinBox_NbSteps->value(); + double aTolerance = SpinBox_Tolerance->GetValue(); + + if (GroupAngle->checkedId() == 1) + anAngle = anAngle/aNbSteps; + + try { + SUIT_OverrideCursor aWaitCursor; + SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditPreviewer(); + aMeshEditor->RotationSweep(anElementsId.inout(), + anAxis, + anAngle, + aNbSteps, + aTolerance); + SMESH::MeshPreviewStruct_var aMeshPreviewStruct = aMeshEditor->GetPreviewData(); + mySimulation->SetData(aMeshPreviewStruct._retn()); + } catch (...) {} + } + else + { + mySimulation->SetVisibility(false); + } + } + else + { + //erase preview + mySimulation->SetVisibility(false); + } +} diff --git a/src/SMESHGUI/SMESHGUI_RevolutionDlg.h b/src/SMESHGUI/SMESHGUI_RevolutionDlg.h index 098cf7a18..206d737eb 100644 --- a/src/SMESHGUI/SMESHGUI_RevolutionDlg.h +++ b/src/SMESHGUI/SMESHGUI_RevolutionDlg.h @@ -51,6 +51,8 @@ class SMESH_Actor; class SVTK_Selector; class LightApp_SelectionMgr; class SMESH_LogicalFilter; +class SALOME_Actor; +class SMESHGUI_MeshEditPreview; //================================================================================= // class : SMESHGUI_RevolutionDlg @@ -65,83 +67,92 @@ public: ~SMESHGUI_RevolutionDlg(); private: - void Init( bool = true); - void closeEvent( QCloseEvent* ); - void enterEvent( QEvent* ); /* mouse enter the QWidget */ - void hideEvent( QHideEvent* ); /* ESC key */ - void keyPressEvent( QKeyEvent* ); - int GetConstructorId(); - bool IsAxisOk(); + void Init( bool = true); + void closeEvent( QCloseEvent* ); + void enterEvent( QEvent* ); /* mouse enter the QWidget */ + void hideEvent( QHideEvent* ); /* ESC key */ + void keyPressEvent( QKeyEvent* ); + int GetConstructorId(); + bool IsAxisOk(); - SMESHGUI* mySMESHGUI; /* Current SMESHGUI object */ - SMESHGUI_IdValidator* myIdValidator; - LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ - int myNbOkElements; /* to check when elements are defined */ - QString myElementsId; - QWidget* myEditCurrentArgument; /* Current argument */ - SVTK_Selector* mySelector; + SMESHGUI* mySMESHGUI; /* Current SMESHGUI object */ + SMESHGUI_IdValidator* myIdValidator; + LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ + int myNbOkElements; /* to check when elements are defined */ + QString myElementsId; + QWidget* myEditCurrentArgument; /* Current argument */ + SVTK_Selector* mySelector; - bool myBusy; - SMESH::SMESH_Mesh_var myMesh; - SMESH_Actor* myActor; - SMESH_LogicalFilter* myMeshOrSubMeshOrGroupFilter; + bool myBusy; + SMESH::SMESH_Mesh_var myMesh; + SMESH_Actor* myActor; + SMESH_LogicalFilter* myMeshOrSubMeshOrGroupFilter; + SMESHGUI_MeshEditPreview* mySimulation; + SALOME_Actor* myPreviewActor; - QGroupBox* ConstructorsBox; - QButtonGroup* GroupConstructors; - QRadioButton* RadioButton1; - QRadioButton* RadioButton2; - QGroupBox* GroupButtons; - QPushButton* buttonOk; - QPushButton* buttonCancel; - QPushButton* buttonApply; - QPushButton* buttonHelp; - QGroupBox* GroupArguments; - QGroupBox* GroupAxis; - QLabel* TextLabelElements; - QPushButton* SelectElementsButton; - QLineEdit* LineEditElements; - QCheckBox* CheckBoxMesh; - QCheckBox* MakeGroupsCheck; + QGroupBox* ConstructorsBox; + QButtonGroup* GroupConstructors; + QRadioButton* RadioButton1; + QRadioButton* RadioButton2; + QGroupBox* GroupButtons; + QPushButton* buttonOk; + QPushButton* buttonCancel; + QPushButton* buttonApply; + QPushButton* buttonHelp; + QGroupBox* GroupArguments; + QGroupBox* GroupAxis; + QLabel* TextLabelElements; + QPushButton* SelectElementsButton; + QLineEdit* LineEditElements; + QCheckBox* CheckBoxMesh; + QCheckBox* MakeGroupsCheck; + QGroupBox* GroupAngleBox; + QButtonGroup* GroupAngle; + QRadioButton* RadioButton3; + QRadioButton* RadioButton4; + QCheckBox* CheckBoxPreview; - QLabel* TextLabelPoint; - QPushButton* SelectPointButton; - QLabel* TextLabelX; - SMESHGUI_SpinBox* SpinBox_X; - QLabel* TextLabelY; - SMESHGUI_SpinBox* SpinBox_Y; - QLabel* TextLabelZ; - SMESHGUI_SpinBox* SpinBox_Z; - QLabel* TextLabelVector; - QPushButton* SelectVectorButton; - QLabel* TextLabelDX; - SMESHGUI_SpinBox* SpinBox_DX; - QLabel* TextLabelDY; - SMESHGUI_SpinBox* SpinBox_DY; - QLabel* TextLabelDZ; - SMESHGUI_SpinBox* SpinBox_DZ; + QLabel* TextLabelPoint; + QPushButton* SelectPointButton; + QLabel* TextLabelX; + SMESHGUI_SpinBox* SpinBox_X; + QLabel* TextLabelY; + SMESHGUI_SpinBox* SpinBox_Y; + QLabel* TextLabelZ; + SMESHGUI_SpinBox* SpinBox_Z; + QLabel* TextLabelVector; + QPushButton* SelectVectorButton; + QLabel* TextLabelDX; + SMESHGUI_SpinBox* SpinBox_DX; + QLabel* TextLabelDY; + SMESHGUI_SpinBox* SpinBox_DY; + QLabel* TextLabelDZ; + SMESHGUI_SpinBox* SpinBox_DZ; - QLabel* TextLabelAngle; - SMESHGUI_SpinBox* SpinBox_Angle; - QLabel* TextLabelNbSteps; - QSpinBox* SpinBox_NbSteps; - QLabel* TextLabelTolerance; - SMESHGUI_SpinBox* SpinBox_Tolerance; + QLabel* TextLabelAngle; + SMESHGUI_SpinBox* SpinBox_Angle; + QLabel* TextLabelNbSteps; + QSpinBox* SpinBox_NbSteps; + QLabel* TextLabelTolerance; + SMESHGUI_SpinBox* SpinBox_Tolerance; - QString myHelpFileName; + QString myHelpFileName; private slots: - void ConstructorsClicked( int ); - void ClickOnOk(); - void ClickOnCancel(); - void ClickOnApply(); - void ClickOnHelp(); - void SetEditCurrentArgument(); - void SelectionIntoArgument(); - void DeactivateActiveDialog(); - void ActivateThisDialog(); - void onTextChange( const QString& ); - void onSelectMesh( bool ); - void onVectorChanged(); + void ConstructorsClicked( int ); + void ClickOnOk(); + void ClickOnCancel(); + void ClickOnApply(); + void ClickOnHelp(); + void SetEditCurrentArgument(); + void SelectionIntoArgument(); + void DeactivateActiveDialog(); + void ActivateThisDialog(); + void onTextChange( const QString& ); + void onSelectMesh( bool ); + void onVectorChanged(); + void toDisplaySimulation(); + void onDisplaySimulation( bool ); }; #endif // SMESHGUI_REVOLUTIONDLG_H diff --git a/src/SMESHGUI/SMESHGUI_Selection.cxx b/src/SMESHGUI/SMESHGUI_Selection.cxx index af48b3008..6ec33b7ce 100644 --- a/src/SMESHGUI/SMESHGUI_Selection.cxx +++ b/src/SMESHGUI/SMESHGUI_Selection.cxx @@ -114,6 +114,8 @@ QVariant SMESHGUI_Selection::parameter( const int ind, const QString& p ) const else if ( p=="displayMode" ) val = QVariant( displayMode( ind ) ); else if ( p=="isComputable" ) val = QVariant( isComputable( ind ) ); else if ( p=="hasReference" ) val = QVariant( hasReference( ind ) ); + else if ( p=="isImported" ) val = QVariant( isImported( ind ) ); + if( val.isValid() ) return val; @@ -486,3 +488,20 @@ QString SMESHGUI_Selection::typeName( const int t ) return "Unknown"; } } + +bool SMESHGUI_Selection::isImported( const int ind ) const +{ + QString e = entry( ind ); + _PTR(SObject) SO = SMESH::GetActiveStudyDocument()->FindObjectID( e.toLatin1().constData() ); + bool res = false; + if( SO ) + { + SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( SO ) ); + if( !aMesh->_is_nil() ) + { + SALOME_MED::MedFileInfo* inf = aMesh->GetMEDFileInfo(); + res = strlen( (char*)inf->fileName ) > 0; + } + } + return res; +} diff --git a/src/SMESHGUI/SMESHGUI_Selection.h b/src/SMESHGUI/SMESHGUI_Selection.h index 2b77aaf3f..4d1ba4a63 100644 --- a/src/SMESHGUI/SMESHGUI_Selection.h +++ b/src/SMESHGUI/SMESHGUI_Selection.h @@ -70,6 +70,8 @@ public: static int type( const QString&, _PTR(Study) ); static QString typeName( const int ); + bool isImported( const int ) const; + private: QStringList myTypes; QList myActors; diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index ecad9b6c9..80b0c6106 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -2727,6 +2727,10 @@ Consider saving your work before application crash WARP_ELEMENTS Warping + + MEN_FILE_INFO + MED file information + SMESHGUI @@ -4093,7 +4097,7 @@ It is impossible to read point coordinates from file SMESHGUI_RevolutionDlg ANGLE_BY_STEP - Use Angle by Step + Angle by Step PREVIEW @@ -4113,7 +4117,7 @@ It is impossible to read point coordinates from file TOTAL_ANGLE - Use Total Angle + Total Angle @@ -4308,4 +4312,23 @@ It is impossible to read point coordinates from file Gravity center + + SMESHGUI_FileInfoDlg + + CAPTION + File information + + + FILE_NAME + File name + + + FILE_SIZE + File size (bytes) + + + MED_VERSION + MED version + + diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index f933abfb7..c9d70e0bf 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -338,7 +338,8 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) } // Concatenate( [mesh1, ...], ... ) - if ( theCommand->GetMethod() == "Concatenate" ) + if ( theCommand->GetMethod() == "Concatenate" || + theCommand->GetMethod() == "ConcatenateWithGroups") { AddMeshAccessorMethod( theCommand ); } diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index f05003b01..a27316fa3 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -1418,6 +1418,52 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe CORBA::Boolean theMergeNodesAndElements, CORBA::Double theMergeTolerance) throw ( SALOME::SALOME_Exception ) +{ + return ConcatenateCommon(theMeshesArray, + theUniteIdenticalGroups, + theMergeNodesAndElements, + theMergeTolerance, + false); +} + +//================================================================================ +/*! + * SMESH_Gen_i::ConcatenateWithGroups + * + * Concatenate the given meshes into one mesh + * Create the groups of all elements from initial meshes + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr +SMESH_Gen_i::ConcatenateWithGroups(const SMESH::mesh_array& theMeshesArray, + CORBA::Boolean theUniteIdenticalGroups, + CORBA::Boolean theMergeNodesAndElements, + CORBA::Double theMergeTolerance) + throw ( SALOME::SALOME_Exception ) +{ + return ConcatenateCommon(theMeshesArray, + theUniteIdenticalGroups, + theMergeNodesAndElements, + theMergeTolerance, + true); +} + +//================================================================================ +/*! + * SMESH_Gen_i::ConcatenateCommon + * + * Concatenate the given meshes into one mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr +SMESH_Gen_i::ConcatenateCommon(const SMESH::mesh_array& theMeshesArray, + CORBA::Boolean theUniteIdenticalGroups, + CORBA::Boolean theMergeNodesAndElements, + CORBA::Double theMergeTolerance, + CORBA::Boolean theCommonGroups) + throw ( SALOME::SALOME_Exception ) { typedef map TIDsMap; typedef list TListOfNewGroups; @@ -1458,6 +1504,23 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe const SMDS_MeshElement* aNewElem = 0; int anElemNbNodes = 0; + int anNbNodes = 0; + int anNbEdges = 0; + int anNbFaces = 0; + int anNbVolumes = 0; + + SMESH::long_array_var anIDsNodes = new SMESH::long_array(); + SMESH::long_array_var anIDsEdges = new SMESH::long_array(); + SMESH::long_array_var anIDsFaces = new SMESH::long_array(); + SMESH::long_array_var anIDsVolumes = new SMESH::long_array(); + + if( theCommonGroups ) { + anIDsNodes->length( anInitMeshDS->NbNodes() ); + anIDsEdges->length( anInitMeshDS->NbEdges() ); + anIDsFaces->length( anInitMeshDS->NbFaces() ); + anIDsVolumes->length( anInitMeshDS->NbVolumes() ); + } + for ( int j = 0; itElems->more(); j++) { anElem = itElems->next(); SMDSAbs_ElementType anElemType = anElem->GetType(); @@ -1474,6 +1537,8 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe if ( nodesMap.find(aNode->GetID()) == nodesMap.end() ) { aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z()); nodesMap.insert( make_pair(aNode->GetID(), aNewNode->GetID()) ); + if( theCommonGroups ) + anIDsNodes[anNbNodes++] = aNewNode->GetID(); } else aNewNode = aNewMeshDS->FindNode( nodesMap.find(aNode->GetID())->second ); @@ -1489,6 +1554,8 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe aNewElem = aNewMeshDS->AddPolyhedralVolume(aNodesArray, aVolume->GetQuanities()); elemsMap.insert(make_pair(anElem->GetID(), aNewElem->GetID())); + if( theCommonGroups ) + anIDsVolumes[anNbVolumes++] = aNewElem->GetID(); } } else { @@ -1497,6 +1564,14 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe anElemType, anElem->IsPoly()); elemsMap.insert(make_pair(anElem->GetID(), aNewElem->GetID())); + if( theCommonGroups ) { + if( anElemType == SMDSAbs_Edge ) + anIDsEdges[anNbEdges++] = aNewElem->GetID(); + else if( anElemType == SMDSAbs_Face ) + anIDsFaces[anNbFaces++] = aNewElem->GetID(); + else if( anElemType == SMDSAbs_Volume ) + anIDsVolumes[anNbVolumes++] = aNewElem->GetID(); + } } }//elems loop @@ -1507,12 +1582,81 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe SMESH::long_array_var anInitIDs = new SMESH::long_array(); SMESH::long_array_var anNewIDs = new SMESH::long_array(); SMESH::SMESH_Group_var aNewGroup; + + SMESH::ElementType aGroupType; + CORBA::String_var aGroupName; + if ( theCommonGroups ) { + for(aGroupType=SMESH::NODE;aGroupType<=SMESH::VOLUME;aGroupType=(SMESH::ElementType)(aGroupType+1)) { + string str = "Gr"; + SALOMEDS::SObject_var aMeshSObj = ObjectToSObject( myCurrentStudy, anInitMesh ); + if(aMeshSObj) + str += aMeshSObj->GetName(); + str += "_"; + + int anLen = 0; + + switch(aGroupType) { + case SMESH::NODE: + str += "Nodes"; + anIDsNodes->length(anNbNodes); + anLen = anNbNodes; + break; + case SMESH::EDGE: + str += "Edges"; + anIDsEdges->length(anNbEdges); + anLen = anNbEdges; + break; + case SMESH::FACE: + str += "Faces"; + anIDsFaces->length(anNbFaces); + anLen = anNbFaces; + break; + case SMESH::VOLUME: + str += "Volumes"; + anIDsVolumes->length(anNbVolumes); + anLen = anNbVolumes; + break; + default: + break; + } + + if(anLen) { + aGroupName = str.c_str(); + + // add a new group in the mesh + aNewGroup = aNewImpl->CreateGroup(aGroupType, aGroupName); + + switch(aGroupType) { + case SMESH::NODE: + aNewGroup->Add( anIDsNodes ); + break; + case SMESH::EDGE: + aNewGroup->Add( anIDsEdges ); + break; + case SMESH::FACE: + aNewGroup->Add( anIDsFaces ); + break; + case SMESH::VOLUME: + aNewGroup->Add( anIDsVolumes ); + break; + default: + break; + } + + aListOfNewGroups.clear(); + aListOfNewGroups.push_back(aNewGroup); + aGroupsMap.insert(make_pair( make_pair(aGroupName, aGroupType), aListOfNewGroups )); + } + } + } + + // check that current group name and type don't have identical ones in union mesh for (int i = 0; i < aListOfGroups->length(); i++) { aGroup = aListOfGroups[i]; aListOfNewGroups.clear(); - SMESH::ElementType aGroupType = aGroup->GetType(); - CORBA::String_var aGroupName = aGroup->GetName(); - + aGroupType = aGroup->GetType(); + aGroupName = aGroup->GetName(); + TGroupsMap::iterator anIter = aGroupsMap.find(make_pair(aGroupName, aGroupType)); // convert a list of IDs @@ -1579,7 +1723,11 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe } // Update Python script - aPythonDump << aNewMesh << " = " << this << ".Concatenate("; + aPythonDump << aNewMesh << " = " << this; + if( !theCommonGroups ) + aPythonDump << ".Concatenate("; + else + aPythonDump << ".ConcatenateWithGroups("; aPythonDump << "["; for ( int i = 0; i < theMeshesArray.length(); i++) { if (i > 0) aPythonDump << ", "; @@ -1587,7 +1735,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshe } aPythonDump << "], "; aPythonDump << theUniteIdenticalGroups << ", " - << theMergeNodesAndElements << ", " + << theMergeNodesAndElements << ", " << theMergeTolerance << ")"; return aNewMesh._retn(); diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index d97b6fbf9..f8d43bb9b 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -259,6 +259,14 @@ public: CORBA::Long theElementID) throw ( SALOME::SALOME_Exception ); + // Concatenate the given meshes into one mesh + SMESH::SMESH_Mesh_ptr ConcatenateCommon(const SMESH::mesh_array& theMeshesArray, + CORBA::Boolean theUniteIdenticalGroups, + CORBA::Boolean theMergeNodesAndElements, + CORBA::Double theMergeTolerance, + CORBA::Boolean theCommonGroups) + throw ( SALOME::SALOME_Exception ); + // Concatenate the given meshes into one mesh SMESH::SMESH_Mesh_ptr Concatenate(const SMESH::mesh_array& theMeshesArray, CORBA::Boolean theUniteIdenticalGroups, @@ -266,6 +274,13 @@ public: CORBA::Double theMergeTolerance) throw ( SALOME::SALOME_Exception ); + // Concatenate the given meshes into one mesh + // Create the groups of all elements from initial meshes + SMESH::SMESH_Mesh_ptr ConcatenateWithGroups(const SMESH::mesh_array& theMeshesArray, + CORBA::Boolean theUniteIdenticalGroups, + CORBA::Boolean theMergeNodesAndElements, + CORBA::Double theMergeTolerance) + throw ( SALOME::SALOME_Exception ); // **************************************************** // Interface inherited methods (from SALOMEDS::Driver) diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index c9f00811c..507b3a23f 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -2089,6 +2089,57 @@ SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr thePathMes const SMESH::double_array & theAngles) { SMESH::double_array_var aResult = new SMESH::double_array(); + int nbAngles = theAngles.length(); + if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() ) + { + SMESH_Mesh_i* aMeshImp = SMESH::DownCast( thePathMesh ); + TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape ); + SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape ); + if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) + return aResult._retn(); + int nbSteps = aSubMesh->GetSubMeshDS()->NbElements(); + if ( nbSteps == nbAngles ) + { + aResult.inout() = theAngles; + } + else + { + aResult->length( nbSteps ); + double rAn2St = double( nbAngles ) / double( nbSteps ); + double angPrev = 0, angle; + for ( int iSt = 0; iSt < nbSteps; ++iSt ) + { + double angCur = rAn2St * ( iSt+1 ); + double angCurFloor = floor( angCur ); + double angPrevFloor = floor( angPrev ); + if ( angPrevFloor == angCurFloor ) + angle = rAn2St * theAngles[ int( angCurFloor ) ]; + else + { + int iP = int( angPrevFloor ); + double angPrevCeil = ceil(angPrev); + angle = ( angPrevCeil - angPrev ) * theAngles[ iP ]; + + int iC = int( angCurFloor ); + if ( iC < nbAngles ) + angle += ( angCur - angCurFloor ) * theAngles[ iC ]; + + iP = int( angPrevCeil ); + while ( iC-- > iP ) + angle += theAngles[ iC ]; + } + aResult[ iSt ] = angle; + angPrev = angCur; + } + } + } + // Update Python script + TPythonDump() << "rotAngles = " << theAngles; + TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( " + << thePathMesh << ", " + << thePathShape << ", " + << "rotAngles )"; + return aResult._retn(); } diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index a52c3b0c2..3bc02f9bf 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -240,6 +240,7 @@ SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName ) THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM); } + myFile = theFileName; CreateGroupServants(); return ConvertDriverMEDReadStatus(status); @@ -2479,3 +2480,28 @@ SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list& groupIDs) const aList->length( nbGroups ); return aList._retn(); } + +//============================================================================= +/*! + * \brief Return information about imported file + */ +//============================================================================= +SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo() +{ + SALOME_MED::MedFileInfo_var res = new SALOME_MED::MedFileInfo(); + + const char* name = myFile.c_str(); + res->fileName = name; + res->fileSize = 0;//myFileInfo.size(); + int major, minor, release; + if( !MED::getMEDVersion( name, major, minor, release ) ) + { + major = -1; + minor = -1; + release = -1; + } + res->major = major; + res->minor = minor; + res->release = release; + return res._retn(); +} diff --git a/src/SMESH_I/SMESH_Mesh_i.hxx b/src/SMESH_I/SMESH_Mesh_i.hxx index 54842e09d..c4d4a7277 100644 --- a/src/SMESH_I/SMESH_Mesh_i.hxx +++ b/src/SMESH_I/SMESH_Mesh_i.hxx @@ -436,6 +436,10 @@ public: */ SMESH::double_array* BaryCenter(CORBA::Long id); + /*! + * Returns information about imported MED file + */ + virtual SALOME_MED::MedFileInfo* GetMEDFileInfo(); std::map _mapSubMesh_i; //NRI std::map _mapSubMesh; //NRI @@ -450,6 +454,7 @@ private: std::map _mapSubMeshIor; std::map _mapGroups; std::map _mapHypo; + string myFile; }; #endif diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index f4a294088..a5560ba04 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -26,6 +26,14 @@ \brief Module smesh """ +## \package smeshDC +# To get started, please look at smeshDC::smeshDC documentation for general services of smesh package. +# You can find the smeshDC::smeshDC documentation also by the first +# item in the Data Structures list on this page. +# See also the list of Data Structures and the list of Functions +# for other classes and methods of smesh python interface. + + import salome import geompyDC @@ -97,7 +105,7 @@ def GetName(obj): attr = sobj.FindAttribute("AttributeName")[1] return attr.Value() - ## Sets name to object +## Sets name to object def SetName(obj, name): ior = salome.orb.object_to_string(obj) sobj = salome.myStudy.FindObjectIOR(ior) @@ -105,7 +113,7 @@ def SetName(obj, name): attr = sobj.FindAttribute("AttributeName")[1] attr.SetValue(name) - ## Print error message if a hypothesis was not assigned. +## Print error message if a hypothesis was not assigned. def TreatHypoStatus(status, hypName, geomName, isAlgo): if isAlgo: hypType = "algorithm" @@ -142,18 +150,35 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo): print hypName, "was not assigned to",geomName,":", reason pass +## Convert angle in degrees to radians +def DegreesToRadians(AngleInDegrees): + from math import pi + return AngleInDegrees * pi / 180.0 + +## Methods of package smesh.py: general services of MESH component. +# +# This class has been designed to provide general services of the MESH component. +# All methods of this class are accessible directly from the smesh.py package. +# Use these methods to create an empty mesh, to import mesh from a file, +# and also to create patterns and filtering criteria. class smeshDC(SMESH._objref_SMESH_Gen): + ## To set current study and Geometry component def init_smesh(self,theStudy,geompyD): self.geompyD=geompyD self.SetGeomEngine(geompyD) self.SetCurrentStudy(theStudy) + ## Create an empty Mesh. This mesh can have underlying geometry. + # @param obj Geometrical object to build the mesh on. If not defined, + # the mesh will not have underlying geometry. + # @param name A name for the new mesh. + # @return instance of Mesh class. def Mesh(self, obj=0, name=0): return Mesh(self,self.geompyD,obj,name) ## Returns long value from enumeration - # Uses for SMESH.FunctorType enumeration + # To be used for SMESH.FunctorType enumeration def EnumToLong(self,theItem): return theItem._v @@ -258,15 +283,16 @@ class smeshDC(SMESH._objref_SMESH_Gen): return aMesh ## From SMESH_Gen interface + # @return list of integer values def GetSubShapesId( self, theMainObject, theListOfSubObjects ): return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects) ## From SMESH_Gen interface. Creates pattern + # @return an instance of SMESH_Pattern def GetPattern(self): return SMESH._objref_SMESH_Gen.GetPattern(self) - # Filtering. Auxiliary functions: # ------------------------------ @@ -426,8 +452,11 @@ omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshDC) ## Class to define a mesh # -# The class contains mesh shape, SMESH_Mesh, SMESH_MeshEditor -# More details. +# This class allows to define and manage a mesh. +# It has a set of methods to build a mesh on the given geometry, including definition of sub-meshes. +# Also it has methods to define groups of mesh elements, to modify a mesh (by addition of +# new nodes and elements and by changind of existing entities), to take information +# about a mesh and to export a mesh into different formats. class Mesh: geom = 0 @@ -436,7 +465,7 @@ class Mesh: ## Constructor # - # Creates mesh on the shape \a geom(or the empty mesh if geom equal to 0), + # Creates mesh on the shape \a obj (or the empty mesh if obj is equal to 0), # sets GUI name of this mesh to \a name. # @param obj Shape to be meshed or SMESH_Mesh object # @param name Study name of the mesh @@ -460,30 +489,32 @@ class Mesh: self.editor = self.mesh.GetMeshEditor() - ## Method that inits the Mesh object from SMESH_Mesh interface + ## Method that inits the Mesh object from instance of SMESH_Mesh interface # @param theMesh is SMESH_Mesh object def SetMesh(self, theMesh): self.mesh = theMesh self.geom = self.mesh.GetShapeToMesh() - ## Method that returns the mesh + ## Method that returns the mesh, that is instance of SMESH_Mesh interface # @return SMESH_Mesh object def GetMesh(self): return self.mesh ## Get mesh name + # @return name of the mesh as a string def GetName(self): name = GetName(self.GetMesh()) return name ## Set name to mesh + # @param name a new name for the mesh def SetName(self, name): SetName(self.GetMesh(), name) - ## Get the subMesh object associated to a subShape. The subMesh object - # gives access to nodes and elements IDs. - # \n SubMesh will be used instead of SubShape in a next idl version to - # adress a specific subMesh... + ## Get the subMesh object associated to \a theSubObject geometrical object. + # The subMesh object gives access to nodes and elements IDs. + # @param theSubObject A geometrical object (shape) + # @return object of type SMESH_SubMesh, representing part of mesh, which lays on the given shape def GetSubMesh(self, theSubObject, name): submesh = self.mesh.GetSubMesh(theSubObject, name) return submesh @@ -494,19 +525,18 @@ class Mesh: return self.geom ## Method that associates given shape to the mesh(entails the mesh recreation) - # @param geom shape to be meshed(GEOM_Object) + # @param geom shape to be meshed (GEOM_Object) def SetShape(self, geom): self.mesh = self.smeshpyD.CreateMesh(geom) ## Return true if hypotheses are defined well - # @param theMesh is an instance of Mesh class # @param theSubObject subshape of a mesh shape + # @return True or False def IsReadyToCompute(self, theSubObject): return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject) - ## Return errors of hypotheses definintion - # error list is empty if everything is OK - # @param theMesh is an instance of Mesh class + ## Return errors of hypotheses definition. + # Errors list is empty if everything is OK. # @param theSubObject subshape of a mesh shape # @return a list of errors def GetAlgoState(self, theSubObject): @@ -515,14 +545,14 @@ class Mesh: ## Return geometrical object the given element is built on. # The returned geometrical object, if not nil, is either found in the # study or is published by this method with the given name - # @param theMesh is an instance of Mesh class # @param theElementID an id of the mesh element # @param theGeomName user defined name of geometrical object # @return GEOM::GEOM_Object instance def GetGeometryByMeshElement(self, theElementID, theGeomName): return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName ) - ## Returns mesh dimension depending on shape one + ## Returns mesh dimension depending on that of the underlying shape + # @return mesh dimension as an integer value [0,3] def MeshDimension(self): shells = self.geompyD.SubShapeAllIDs( self.geom, geompyDC.ShapeType["SHELL"] ) if len( shells ) > 0 : @@ -536,11 +566,15 @@ class Mesh: pass ## Creates a segment discretization 1D algorithm. - # If the optional \a algo parameter is not sets, this algorithm is REGULAR. - # If the optional \a geom parameter is not sets, this algorithm is global. - # \n Otherwise, this algorithm define a submesh based on \a geom subshape. - # @param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function + # If the optional \a algo parameter is not set, this algorithm is REGULAR. + # \n If the optional \a geom parameter is not set, this algorithm is global. + # Otherwise, this algorithm define a submesh based on \a geom subshape. + # @param algo type of desired algorithm. Possible values are: + # - smesh.REGULAR, + # - smesh.PYTHON for discretization via python function, + # - smesh.COMPOSITE for meshing a set of edges on one face side as a whole. # @param geom If defined, subshape to be meshed + # @return instance of Mesh_Segment or Mesh_Segment_Python, or Mesh_CompositeSegment class def Segment(self, algo=REGULAR, geom=0): ## if Segment(geom) is called by mistake if isinstance( algo, geompyDC.GEOM._objref_GEOM_Object): @@ -581,20 +615,22 @@ class Mesh: ## Creates a triangle 2D algorithm for faces. # If the optional \a geom parameter is not sets, this algorithm is global. # \n Otherwise, this algorithm define a submesh based on \a geom subshape. - # @param algo values are: smesh.MEFISTO || smesh.NETGEN_1D2D || smesh.NETGEN_2D - # @param geom If defined, subshape to be meshed + # @param algo values are: smesh.MEFISTO || smesh.NETGEN_1D2D || smesh.NETGEN_2D || smesh.BLSURF + # @param geom If defined, subshape to be meshed (GEOM_Object) + # @return an instance of Mesh_Triangle algorithm def Triangle(self, algo=MEFISTO, geom=0): ## if Triangle(geom) is called by mistake - if ( isinstance( algo, geompyDC.GEOM._objref_GEOM_Object)): + if (isinstance(algo, geompyDC.GEOM._objref_GEOM_Object)): geom = algo algo = MEFISTO - return Mesh_Triangle(self, algo, geom) + return Mesh_Triangle(self, algo, geom) ## Creates a quadrangle 2D algorithm for faces. # If the optional \a geom parameter is not sets, this algorithm is global. # \n Otherwise, this algorithm define a submesh based on \a geom subshape. - # @param geom If defined, subshape to be meshed + # @param geom If defined, subshape to be meshed (GEOM_Object) + # @return an instance of Mesh_Quadrangle algorithm def Quadrangle(self, geom=0): return Mesh_Quadrangle(self, geom) @@ -603,7 +639,8 @@ class Mesh: # If the optional \a geom parameter is not sets, this algorithm is global. # \n Otherwise, this algorithm define a submesh based on \a geom subshape. # @param algo values are: smesh.NETGEN, smesh.GHS3D, smesh.FULL_NETGEN - # @param geom If defined, subshape to be meshed + # @param geom If defined, subshape to be meshed (GEOM_Object) + # @return an instance of Mesh_Tetrahedron algorithm def Tetrahedron(self, algo=NETGEN, geom=0): ## if Tetrahedron(geom) is called by mistake if ( isinstance( algo, geompyDC.GEOM._objref_GEOM_Object)): @@ -615,9 +652,9 @@ class Mesh: ## Creates a hexahedron 3D algorithm for solids. # If the optional \a geom parameter is not sets, this algorithm is global. # \n Otherwise, this algorithm define a submesh based on \a geom subshape. - # @param geom If defined, subshape to be meshed - ## def Hexahedron(self, geom=0): - ## return Mesh_Hexahedron(self, geom) + # @param algo possible values are: smesh.Hexa, smesh.Hexotic + # @param geom If defined, subshape to be meshed (GEOM_Object) + # @return an instance of Mesh_Hexahedron algorithm def Hexahedron(self, algo=Hexa, geom=0): ## if Hexahedron(geom, algo) or Hexahedron(geom) is called by mistake if ( isinstance(algo, geompyDC.GEOM._objref_GEOM_Object) ): @@ -626,6 +663,7 @@ class Mesh: return Mesh_Hexahedron(self, algo, geom) ## Deprecated, only for compatibility! + # @return an instance of Mesh_Netgen algorithm def Netgen(self, is3D, geom=0): return Mesh_Netgen(self, is3D, geom) @@ -633,6 +671,7 @@ class Mesh: # If the optional \a geom parameter is not sets, this algorithm is global. # Otherwise, this algorithm define a submesh based on \a geom subshape. # @param geom If defined, subshape to be meshed + # @return an instance of Mesh_Projection1D algorithm def Projection1D(self, geom=0): return Mesh_Projection1D(self, geom) @@ -640,6 +679,7 @@ class Mesh: # If the optional \a geom parameter is not sets, this algorithm is global. # Otherwise, this algorithm define a submesh based on \a geom subshape. # @param geom If defined, subshape to be meshed + # @return an instance of Mesh_Projection2D algorithm def Projection2D(self, geom=0): return Mesh_Projection2D(self, geom) @@ -647,6 +687,7 @@ class Mesh: # If the optional \a geom parameter is not sets, this algorithm is global. # Otherwise, this algorithm define a submesh based on \a geom subshape. # @param geom If defined, subshape to be meshed + # @return an instance of Mesh_Projection3D algorithm def Projection3D(self, geom=0): return Mesh_Projection3D(self, geom) @@ -654,6 +695,7 @@ class Mesh: # If the optional \a geom parameter is not sets, this algorithm is global. # Otherwise, this algorithm define a submesh based on \a geom subshape. # @param geom If defined, subshape to be meshed + # @return an instance of Mesh_Prism3D or Mesh_RadialPrism3D algorithm def Prism(self, geom=0): shape = geom if shape==0: @@ -665,6 +707,7 @@ class Mesh: return Mesh_RadialPrism3D(self, geom) ## Compute the mesh and return the status of the computation + # @return True or False def Compute(self, geom=0): if geom == 0 or not isinstance(geom, geompyDC.GEOM._objref_GEOM_Object): if self.geom == 0: @@ -732,6 +775,7 @@ class Mesh: ## Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN # The parameter \a fineness [0,-1] defines mesh fineness + # @return True or False def AutomaticTetrahedralization(self, fineness=0): dim = self.MeshDimension() # assign hypotheses @@ -747,6 +791,7 @@ class Mesh: ## Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron # The parameter \a fineness [0,-1] defines mesh fineness + # @return True or False def AutomaticHexahedralization(self, fineness=0): dim = self.MeshDimension() # assign hypotheses @@ -763,6 +808,7 @@ class Mesh: ## Assign hypothesis # @param hyp is a hypothesis to assign # @param geom is subhape of mesh geometry + # @return SMESH.Hypothesis_Status def AddHypothesis(self, hyp, geom=0): if isinstance( hyp, Mesh_Algorithm ): hyp = hyp.GetAlgorithm() @@ -778,6 +824,7 @@ class Mesh: ## Unassign hypothesis # @param hyp is a hypothesis to unassign # @param geom is subhape of mesh geometry + # @return SMESH.Hypothesis_Status def RemoveHypothesis(self, hyp, geom=0): if isinstance( hyp, Mesh_Algorithm ): hyp = hyp.GetAlgorithm() @@ -790,6 +837,7 @@ class Mesh: ## Get the list of hypothesis added on a geom # @param geom is subhape of mesh geometry + # @return sequence of SMESH_Hypothesis def GetHypothesisList(self, geom): return self.mesh.GetHypothesisList( geom ) @@ -984,14 +1032,17 @@ class Mesh: self.mesh.RemoveGroupWithContents(group) ## Get the list of groups existing in the mesh + # @return sequence of SMESH_GroupBase def GetGroups(self): return self.mesh.GetGroups() ## Get number of groups existing in the mesh + # @return quantity of groups as an integer value def NbGroups(self): return self.mesh.NbGroups() ## Get the list of names of groups existing in the mesh + # @return list of strings def GetGroupNames(self): groups = self.GetGroups() names = [] @@ -1002,18 +1053,21 @@ class Mesh: ## Union of two groups # New group is created. All mesh elements that are # present in initial groups are added to the new one + # @return an instance of SMESH_Group def UnionGroups(self, group1, group2, name): return self.mesh.UnionGroups(group1, group2, name) ## Intersection of two groups # New group is created. All mesh elements that are # present in both initial groups are added to the new one. + # @return an instance of SMESH_Group def IntersectGroups(self, group1, group2, name): return self.mesh.IntersectGroups(group1, group2, name) ## Cut of two groups # New group is created. All mesh elements that are present in # main group but do not present in tool group are added to the new one + # @return an instance of SMESH_Group def CutGroups(self, mainGroup, toolGroup, name): return self.mesh.CutGroups(mainGroup, toolGroup, name) @@ -1037,30 +1091,39 @@ class Mesh: def ClearLog(self): self.mesh.ClearLog() - def SetAutoColor(self, color): - self.mesh.SetAutoColor(color) + ## Toggle auto color mode on the object. + # @param theAutoColor flag which toggles auto color mode. + def SetAutoColor(self, theAutoColor): + self.mesh.SetAutoColor(theAutoColor) + ## Get flag of object auto color mode. + # @return True or False def GetAutoColor(self): return self.mesh.GetAutoColor() ## Get the internal Id + # @return integer value, which is the internal Id of the mesh def GetId(self): return self.mesh.GetId() ## Get the study Id + # @return integer value, which is the study Id of the mesh def GetStudyId(self): return self.mesh.GetStudyId() ## Check group names for duplications. # Consider maximum group name length stored in MED file. + # @return True or False def HasDuplicatedGroupNamesMED(self): return self.mesh.HasDuplicatedGroupNamesMED() - ## Obtain instance of SMESH_MeshEditor + ## Obtain mesh editor tool + # @return an instance of SMESH_MeshEditor def GetMeshEditor(self): return self.mesh.GetMeshEditor() ## Get MED Mesh + # @return an instance of SALOME_MED::MESH def GetMEDMesh(self): return self.mesh.GetMEDMesh() @@ -1069,125 +1132,151 @@ class Mesh: # ------------------------------------ ## Returns number of nodes in mesh + # @return an integer value def NbNodes(self): return self.mesh.NbNodes() ## Returns number of elements in mesh + # @return an integer value def NbElements(self): return self.mesh.NbElements() ## Returns number of edges in mesh + # @return an integer value def NbEdges(self): return self.mesh.NbEdges() ## Returns number of edges with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbEdgesOfOrder(self, elementOrder): return self.mesh.NbEdgesOfOrder(elementOrder) ## Returns number of faces in mesh + # @return an integer value def NbFaces(self): return self.mesh.NbFaces() ## Returns number of faces with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbFacesOfOrder(self, elementOrder): return self.mesh.NbFacesOfOrder(elementOrder) ## Returns number of triangles in mesh + # @return an integer value def NbTriangles(self): return self.mesh.NbTriangles() ## Returns number of triangles with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbTrianglesOfOrder(self, elementOrder): return self.mesh.NbTrianglesOfOrder(elementOrder) ## Returns number of quadrangles in mesh + # @return an integer value def NbQuadrangles(self): return self.mesh.NbQuadrangles() ## Returns number of quadrangles with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbQuadranglesOfOrder(self, elementOrder): return self.mesh.NbQuadranglesOfOrder(elementOrder) ## Returns number of polygons in mesh + # @return an integer value def NbPolygons(self): return self.mesh.NbPolygons() ## Returns number of volumes in mesh + # @return an integer value def NbVolumes(self): return self.mesh.NbVolumes() ## Returns number of volumes with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbVolumesOfOrder(self, elementOrder): return self.mesh.NbVolumesOfOrder(elementOrder) ## Returns number of tetrahedrons in mesh + # @return an integer value def NbTetras(self): return self.mesh.NbTetras() ## Returns number of tetrahedrons with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbTetrasOfOrder(self, elementOrder): return self.mesh.NbTetrasOfOrder(elementOrder) ## Returns number of hexahedrons in mesh + # @return an integer value def NbHexas(self): return self.mesh.NbHexas() ## Returns number of hexahedrons with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbHexasOfOrder(self, elementOrder): return self.mesh.NbHexasOfOrder(elementOrder) ## Returns number of pyramids in mesh + # @return an integer value def NbPyramids(self): return self.mesh.NbPyramids() ## Returns number of pyramids with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbPyramidsOfOrder(self, elementOrder): return self.mesh.NbPyramidsOfOrder(elementOrder) ## Returns number of prisms in mesh + # @return an integer value def NbPrisms(self): return self.mesh.NbPrisms() ## Returns number of prisms with given order in mesh # @param elementOrder is order of elements: - # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # ORDER_ANY, ORDER_LINEAR or ORDER_QUADRATIC + # @return an integer value def NbPrismsOfOrder(self, elementOrder): return self.mesh.NbPrismsOfOrder(elementOrder) ## Returns number of polyhedrons in mesh + # @return an integer value def NbPolyhedrons(self): return self.mesh.NbPolyhedrons() ## Returns number of submeshes in mesh + # @return an integer value def NbSubMesh(self): return self.mesh.NbSubMesh() ## Returns list of mesh elements ids + # @return list of integer values def GetElementsId(self): return self.mesh.GetElementsId() ## Returns list of ids of mesh elements with given type # @param elementType is required type of elements + # @return list of integer values def GetElementsByType(self, elementType): return self.mesh.GetElementsByType(elementType) ## Returns list of mesh nodes ids + # @return list of integer values def GetNodesId(self): return self.mesh.GetNodesId() @@ -1195,12 +1284,14 @@ class Mesh: # ------------------------------------ ## Returns type of mesh element + # @return value from SMESH::ElementType enumeration def GetElementType(self, id, iselem): return self.mesh.GetElementType(id, iselem) ## Returns list of submesh elements ids # @param Shape is geom object(subshape) IOR - # Shape must be subshape of a ShapeToMesh() + # Shape must be subshape of a ShapeToMesh() + # @return list of integer values def GetSubMeshElementsId(self, Shape): if ( isinstance( Shape, geompyDC.GEOM._objref_GEOM_Object)): ShapeID = Shape.GetSubShapeIndices()[0] @@ -1210,7 +1301,8 @@ class Mesh: ## Returns list of submesh nodes ids # @param Shape is geom object(subshape) IOR - # Shape must be subshape of a ShapeToMesh() + # Shape must be subshape of a ShapeToMesh() + # @return list of integer values def GetSubMeshNodesId(self, Shape, all): if ( isinstance( Shape, geompyDC.GEOM._objref_GEOM_Object)): ShapeID = Shape.GetSubShapeIndices()[0] @@ -1220,7 +1312,8 @@ class Mesh: ## Returns list of ids of submesh elements with given type # @param Shape is geom object(subshape) IOR - # Shape must be subshape of a ShapeToMesh() + # Shape must be subshape of a ShapeToMesh() + # @return list of integer values def GetSubMeshElementType(self, Shape): if ( isinstance( Shape, geompyDC.GEOM._objref_GEOM_Object)): ShapeID = Shape.GetSubShapeIndices()[0] @@ -1229,6 +1322,7 @@ class Mesh: return self.mesh.GetSubMeshElementType(ShapeID) ## Get mesh description + # @return string value def Dump(self): return self.mesh.Dump() @@ -1236,13 +1330,15 @@ class Mesh: # Get information about nodes and elements of mesh by its ids: # ----------------------------------------------------------- - ## Get XYZ coordinates of node as list of double + ## Get XYZ coordinates of node # \n If there is not node for given ID - returns empty list + # @return a list of double precision values def GetNodeXYZ(self, id): return self.mesh.GetNodeXYZ(id) ## For given node returns list of IDs of inverse elements # \n If there is not node for given ID - returns empty list + # @return list of integer values def GetNodeInverseElements(self, id): return self.mesh.GetNodeInverseElements(id) @@ -1253,37 +1349,40 @@ class Mesh: ## If given element is node returns IDs of shape from position # \n If there is not node for given ID - returns -1 + # @return integer value def GetShapeID(self, id): return self.mesh.GetShapeID(id) ## For given element returns ID of result shape after # FindShape() from SMESH_MeshEditor # \n If there is not element for given ID - returns -1 + # @return integer value def GetShapeIDForElem(self,id): return self.mesh.GetShapeIDForElem(id) ## Returns number of nodes for given element # \n If there is not element for given ID - returns -1 + # @return integer value def GetElemNbNodes(self, id): return self.mesh.GetElemNbNodes(id) ## Returns ID of node by given index for given element # \n If there is not element for given ID - returns -1 # \n If there is not node for given index - returns -2 + # @return integer value def GetElemNode(self, id, index): return self.mesh.GetElemNode(id, index) ## Returns IDs of nodes of given element + # @return list of integer values def GetElemNodes(self, id): return self.mesh.GetElemNodes(id) - ## Returns true if given node is medium node - # in given quadratic element + ## Returns true if given node is medium node in given quadratic element def IsMediumNode(self, elementID, nodeID): return self.mesh.IsMediumNode(elementID, nodeID) - ## Returns true if given node is medium node - # in one of quadratic elements + ## Returns true if given node is medium node in one of quadratic elements def IsMediumNodeOfAnyElem(self, nodeID, elementType): return self.mesh.IsMediumNodeOfAnyElem(nodeID, elementType) @@ -1304,8 +1403,8 @@ class Mesh: return self.mesh.IsQuadratic(id) ## Returns XYZ coordinates of bary center for given element - # as list of double # \n If there is not element for given ID - returns empty list + # @return a list of three double values def BaryCenter(self, id): return self.mesh.BaryCenter(id) @@ -1315,38 +1414,44 @@ class Mesh: ## Removes elements from mesh by ids # @param IDsOfElements is list of ids of elements to remove + # @return True or False def RemoveElements(self, IDsOfElements): return self.editor.RemoveElements(IDsOfElements) ## Removes nodes from mesh by ids # @param IDsOfNodes is list of ids of nodes to remove + # @return True or False def RemoveNodes(self, IDsOfNodes): return self.editor.RemoveNodes(IDsOfNodes) ## Add node to mesh by coordinates + # @return Id of the new node def AddNode(self, x, y, z): return self.editor.AddNode( x, y, z) - ## Create edge both similar and quadratic (this is determed + ## Create edge either linear or quadratic (this is determined # by number of given nodes). # @param IdsOfNodes List of node IDs for creation of element. # Needed order of nodes in this list corresponds to description # of MED. \n This description is located by the following link: # http://www.salome-platform.org/salome2/web_med_internet/logiciels/medV2.2.2_doc_html/html/modele_de_donnees.html#3. + # @return Id of the new edge def AddEdge(self, IDsOfNodes): return self.editor.AddEdge(IDsOfNodes) - ## Create face both similar and quadratic (this is determed + ## Create face either linear or quadratic (this is determined # by number of given nodes). # @param IdsOfNodes List of node IDs for creation of element. # Needed order of nodes in this list corresponds to description # of MED. \n This description is located by the following link: # http://www.salome-platform.org/salome2/web_med_internet/logiciels/medV2.2.2_doc_html/html/modele_de_donnees.html#3. + # @return Id of the new face def AddFace(self, IDsOfNodes): return self.editor.AddFace(IDsOfNodes) ## Add polygonal face to mesh by list of nodes ids + # @return Id of the new face def AddPolygonalFace(self, IdsOfNodes): return self.editor.AddPolygonalFace(IdsOfNodes) @@ -1356,6 +1461,7 @@ class Mesh: # Needed order of nodes in this list corresponds to description # of MED. \n This description is located by the following link: # http://www.salome-platform.org/salome2/web_med_internet/logiciels/medV2.2.2_doc_html/html/modele_de_donnees.html#3. + # @return Id of the new volumic element def AddVolume(self, IDsOfNodes): return self.editor.AddVolume(IDsOfNodes) @@ -1363,6 +1469,7 @@ class Mesh: # @param IdsOfNodes List of node IDs for volume creation face by face. # @param Quantities List of integer values, Quantities[i] # gives quantity of nodes in face number i. + # @return Id of the new volumic element def AddPolyhedralVolume (self, IdsOfNodes, Quantities): return self.editor.AddPolyhedralVolume(IdsOfNodes, Quantities) @@ -1371,6 +1478,7 @@ class Mesh: # # Note: The created volume will refer only to nodes # of the given faces, not to the faces itself. + # @return Id of the new volumic element def AddPolyhedralVolumeByFaces (self, IdsOfFaces): return self.editor.AddPolyhedralVolumeByFaces(IdsOfFaces) @@ -1460,6 +1568,7 @@ class Mesh: # @param x new X coordinate # @param y new Y coordinate # @param z new Z coordinate + # @return True if succeed else False def MoveNode(self, NodeID, x, y, z): return self.editor.MoveNode(NodeID, x, y, z) @@ -1498,6 +1607,7 @@ class Mesh: ## Reorient elements by ids # @param IDsOfElements if undefined reorient all mesh elements + # @return True if succeed else False def Reorient(self, IDsOfElements=None): if IDsOfElements == None: IDsOfElements = self.GetElementsId() @@ -1505,6 +1615,7 @@ class Mesh: ## Reorient all elements of the object # @param theObject is mesh, submesh or group + # @return True if succeed else False def ReorientObject(self, theObject): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -1544,6 +1655,7 @@ class Mesh: ## Split quadrangles into triangles. # @param theObject object to taking list of elements from, is mesh, submesh or group # @param theCriterion is FT_...; used to choose a diagonal for splitting. + # @return TRUE in case of success, FALSE otherwise. def QuadToTriObject (self, theObject, theCriterion): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -1560,6 +1672,7 @@ class Mesh: ## Split quadrangles into triangles. # @param theObject is object to taking list of elements from, is mesh, submesh or group + # @return TRUE in case of success, FALSE otherwise. def SplitQuadObject (self, theObject, Diag13): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -1573,7 +1686,7 @@ class Mesh: def BestSplit (self, IDOfQuad, theCriterion): return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion)) - ## Split quafrangle faces near triangular facets of volumes + ## Split quadrangle faces near triangular facets of volumes # def SplitQuadsNearTriangularFacets(self): faces_array = self.GetElementsByType(SMESH.FACE) @@ -1719,6 +1832,7 @@ class Mesh: # @param MaxNbOfIterations maximum number of iterations # @param MaxAspectRatio varies in range [1.0, inf] # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH) + # @return TRUE in case of success, FALSE otherwise. def Smooth(self, IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations, MaxAspectRatio, Method): if IDsOfElements == []: @@ -1733,6 +1847,7 @@ class Mesh: # @param MaxNbOfIterations maximum number of iterations # @param MaxAspectRatio varies in range [1.0, inf] # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH) + # @return TRUE in case of success, FALSE otherwise. def SmoothObject(self, theObject, IDsOfFixedNodes, MaxNbOfIterations, MaxxAspectRatio, Method): if ( isinstance( theObject, Mesh )): @@ -1747,6 +1862,7 @@ class Mesh: # @param MaxNbOfIterations maximum number of iterations # @param MaxAspectRatio varies in range [1.0, inf] # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH) + # @return TRUE in case of success, FALSE otherwise. def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations, MaxAspectRatio, Method): if IDsOfElements == []: @@ -1761,6 +1877,7 @@ class Mesh: # @param MaxNbOfIterations maximum number of iterations # @param MaxAspectRatio varies in range [1.0, inf] # @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH) + # @return TRUE in case of success, FALSE otherwise. def SmoothParametricObject(self, theObject, IDsOfFixedNodes, MaxNbOfIterations, MaxAspectRatio, Method): if ( isinstance( theObject, Mesh )): @@ -1776,6 +1893,7 @@ class Mesh: ## Converts all mesh from quadratic to ordinary ones, # deletes old quadratic elements, \n replacing # them with ordinary mesh elements with the same id. + # @return TRUE in case of success, FALSE otherwise. def ConvertFromQuadratic(self): return self.editor.ConvertFromQuadratic() @@ -1794,11 +1912,17 @@ class Mesh: # @param NbOfSteps number of steps # @param Tolerance tolerance # @param MakeGroups to generate new groups from existing ones - def RotationSweep(self, IDsOfElements, Axix, AngleInRadians, NbOfSteps, Tolerance, MakeGroups=False): + # @param TotalAngle gives meaning of AngleInRadians: if True then it is an anglular size + # of all steps, else - size of each step + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise + def RotationSweep(self, IDsOfElements, Axix, AngleInRadians, NbOfSteps, Tolerance, + MakeGroups=False, TotalAngle=False): if IDsOfElements == []: IDsOfElements = self.GetElementsId() if ( isinstance( Axix, geompyDC.GEOM._objref_GEOM_Object)): Axix = self.smeshpyD.GetAxisStruct(Axix) + if TotalAngle and NbOfSteps: + AngleInRadians /= NbOfSteps if MakeGroups: return self.editor.RotationSweepMakeGroups(IDsOfElements, Axix, AngleInRadians, NbOfSteps, Tolerance) @@ -1812,11 +1936,17 @@ class Mesh: # @param NbOfSteps number of steps # @param Tolerance tolerance # @param MakeGroups to generate new groups from existing ones - def RotationSweepObject(self, theObject, Axix, AngleInRadians, NbOfSteps, Tolerance, MakeGroups=False): + # @param TotalAngle gives meaning of AngleInRadians: if True then it is an anglular size + # of all steps, else - size of each step + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise + def RotationSweepObject(self, theObject, Axix, AngleInRadians, NbOfSteps, Tolerance, + MakeGroups=False, TotalAngle=False): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() if ( isinstance( Axix, geompyDC.GEOM._objref_GEOM_Object)): Axix = self.smeshpyD.GetAxisStruct(Axix) + if TotalAngle and NbOfSteps: + AngleInRadians /= NbOfSteps if MakeGroups: return self.editor.RotationSweepObjectMakeGroups(theObject, Axix, AngleInRadians, NbOfSteps, Tolerance) @@ -1828,6 +1958,7 @@ class Mesh: # @param StepVector vector, defining the direction and value of extrusion # @param NbOfSteps the number of steps # @param MakeGroups to generate new groups from existing ones + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False): if IDsOfElements == []: IDsOfElements = self.GetElementsId() @@ -1846,6 +1977,7 @@ class Mesh: # @param SewTolerance uses for comparing locations of nodes if flag # EXTRUSION_FLAG_SEW is set # @param MakeGroups to generate new groups from existing ones + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def AdvancedExtrusion(self, IDsOfElements, StepVector, NbOfSteps, ExtrFlags, SewTolerance, MakeGroups=False): if ( isinstance( StepVector, geompyDC.GEOM._objref_GEOM_Object)): StepVector = self.smeshpyD.GetDirStruct(StepVector) @@ -1861,6 +1993,7 @@ class Mesh: # @param StepVector vector, defining the direction and value of extrusion # @param NbOfSteps the number of steps # @param MakeGroups to generate new groups from existing ones + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def ExtrusionSweepObject(self, theObject, StepVector, NbOfSteps, MakeGroups=False): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -1876,6 +2009,7 @@ class Mesh: # @param StepVector vector, defining the direction and value of extrusion # @param NbOfSteps the number of steps # @param MakeGroups to generate new groups from existing ones + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def ExtrusionSweepObject1D(self, theObject, StepVector, NbOfSteps, MakeGroups=False): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -1891,6 +2025,7 @@ class Mesh: # @param StepVector vector, defining the direction and value of extrusion # @param NbOfSteps the number of steps # @param MakeGroups to generate new groups from existing ones + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def ExtrusionSweepObject2D(self, theObject, StepVector, NbOfSteps, MakeGroups=False): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -1914,6 +2049,8 @@ class Mesh: # User can specify any point as the Base Point and the shape will be rotated with respect to this point. # @param MakeGroups to generate new groups from existing ones # @param LinearVariation makes compute rotation angles as linear variation of given Angles along path steps + # @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True, + # only SMESH::Extrusion_Error otherwise def ExtrusionAlongPath(self, IDsOfElements, PathMesh, PathShape, NodeStart, HasAngles, Angles, HasRefPoint, RefPoint, MakeGroups=False, LinearVariation=False): @@ -1922,11 +2059,16 @@ class Mesh: if ( isinstance( RefPoint, geompyDC.GEOM._objref_GEOM_Object)): RefPoint = self.smeshpyD.GetPointStruct(RefPoint) pass + if ( isinstance( PathMesh, Mesh )): + PathMesh = PathMesh.GetMesh() + if HasAngles and Angles and LinearVariation: + Angles = self.editor.LinearAnglesVariation( PathMesh, PathShape, Angles ) + pass if MakeGroups: - return self.editor.ExtrusionAlongPathMakeGroups(IDsOfElements, PathMesh.GetMesh(), + return self.editor.ExtrusionAlongPathMakeGroups(IDsOfElements, PathMesh, PathShape, NodeStart, HasAngles, Angles, HasRefPoint, RefPoint) - return self.editor.ExtrusionAlongPath(IDsOfElements, PathMesh.GetMesh(), PathShape, + return self.editor.ExtrusionAlongPath(IDsOfElements, PathMesh, PathShape, NodeStart, HasAngles, Angles, HasRefPoint, RefPoint) ## Generate new elements by extrusion of the elements belong to object @@ -1942,6 +2084,8 @@ class Mesh: # User can specify any point as the Base Point and the shape will be rotated with respect to this point. # @param MakeGroups to generate new groups from existing ones # @param LinearVariation makes compute rotation angles as linear variation of given Angles along path steps + # @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True, + # only SMESH::Extrusion_Error otherwise def ExtrusionAlongPathObject(self, theObject, PathMesh, PathShape, NodeStart, HasAngles, Angles, HasRefPoint, RefPoint, MakeGroups=False, LinearVariation=False): @@ -1949,11 +2093,16 @@ class Mesh: theObject = theObject.GetMesh() if ( isinstance( RefPoint, geompyDC.GEOM._objref_GEOM_Object)): RefPoint = self.smeshpyD.GetPointStruct(RefPoint) + if ( isinstance( PathMesh, Mesh )): + PathMesh = PathMesh.GetMesh() + if HasAngles and Angles and LinearVariation: + Angles = self.editor.LinearAnglesVariation( PathMesh, PathShape, Angles ) + pass if MakeGroups: - return self.editor.ExtrusionAlongPathObjectMakeGroups(theObject, PathMesh.GetMesh(), + return self.editor.ExtrusionAlongPathObjectMakeGroups(theObject, PathMesh, PathShape, NodeStart, HasAngles, Angles, HasRefPoint, RefPoint) - return self.editor.ExtrusionAlongPathObject(theObject, PathMesh.GetMesh(), PathShape, + return self.editor.ExtrusionAlongPathObject(theObject, PathMesh, PathShape, NodeStart, HasAngles, Angles, HasRefPoint, RefPoint) @@ -1964,6 +2113,7 @@ class Mesh: # If the Mirror is geom object this parameter is unnecessary # @param Copy allows to copy element(Copy is 1) or to replace with its mirroring(Copy is 0) # @param MakeGroups to generate new groups from existing ones (if Copy) + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def Mirror(self, IDsOfElements, Mirror, theMirrorType, Copy=0, MakeGroups=False): if IDsOfElements == []: IDsOfElements = self.GetElementsId() @@ -1981,6 +2131,7 @@ class Mesh: # If the Mirror is geom object this parameter is unnecessary # @param MakeGroups to generate new groups from existing ones # @param NewMeshName is a name of new mesh to create + # @return instance of Mesh class def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType, MakeGroups=0, NewMeshName=""): if IDsOfElements == []: IDsOfElements = self.GetElementsId() @@ -1997,6 +2148,7 @@ class Mesh: # If the Mirror is geom object this parameter is unnecessary # @param Copy allows to copy element(Copy is 1) or to replace with its mirroring(Copy is 0) # @param MakeGroups to generate new groups from existing ones (if Copy) + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def MirrorObject (self, theObject, Mirror, theMirrorType, Copy=0, MakeGroups=False): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -2014,6 +2166,7 @@ class Mesh: # If the Mirror is geom object this parameter is unnecessary # @param MakeGroups to generate new groups from existing ones # @param NewMeshName is a name of new mesh to create + # @return instance of Mesh class def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType,MakeGroups=0, NewMeshName=""): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -2028,6 +2181,7 @@ class Mesh: # @param Vector direction of translation(DirStruct or vector) # @param Copy allows to copy the translated elements # @param MakeGroups to generate new groups from existing ones (if Copy) + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def Translate(self, IDsOfElements, Vector, Copy, MakeGroups=False): if IDsOfElements == []: IDsOfElements = self.GetElementsId() @@ -2043,6 +2197,7 @@ class Mesh: # @param Vector direction of translation(DirStruct or vector) # @param MakeGroups to generate new groups from existing ones # @param NewMeshName is a name of new mesh to create + # @return instance of Mesh class def TranslateMakeMesh(self, IDsOfElements, Vector, MakeGroups=False, NewMeshName=""): if IDsOfElements == []: IDsOfElements = self.GetElementsId() @@ -2056,6 +2211,7 @@ class Mesh: # @param Vector direction of translation(DirStruct or geom vector) # @param Copy allows to copy the translated elements # @param MakeGroups to generate new groups from existing ones (if Copy) + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def TranslateObject(self, theObject, Vector, Copy, MakeGroups=False): if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -2071,6 +2227,7 @@ class Mesh: # @param Vector direction of translation(DirStruct or geom vector) # @param MakeGroups to generate new groups from existing ones # @param NewMeshName is a name of new mesh to create + # @return instance of Mesh class def TranslateObjectMakeMesh(self, theObject, Vector, MakeGroups=False, NewMeshName=""): if (isinstance(theObject, Mesh)): theObject = theObject.GetMesh() @@ -2085,6 +2242,7 @@ class Mesh: # @param AngleInRadians angle of rotation(in radians) # @param Copy allows to copy the rotated elements # @param MakeGroups to generate new groups from existing ones (if Copy) + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def Rotate (self, IDsOfElements, Axis, AngleInRadians, Copy, MakeGroups=False): if IDsOfElements == []: IDsOfElements = self.GetElementsId() @@ -2101,6 +2259,7 @@ class Mesh: # @param AngleInRadians angle of rotation(in radians) # @param MakeGroups to generate new groups from existing ones # @param NewMeshName is a name of new mesh to create + # @return instance of Mesh class def RotateMakeMesh (self, IDsOfElements, Axis, AngleInRadians, MakeGroups=0, NewMeshName=""): if IDsOfElements == []: IDsOfElements = self.GetElementsId() @@ -2116,6 +2275,7 @@ class Mesh: # @param AngleInRadians angle of rotation(in radians) # @param Copy allows to copy the rotated elements # @param MakeGroups to generate new groups from existing ones (if Copy) + # @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise def RotateObject (self, theObject, Axis, AngleInRadians, Copy, MakeGroups=False): if (isinstance(theObject, Mesh)): theObject = theObject.GetMesh() @@ -2132,6 +2292,7 @@ class Mesh: # @param AngleInRadians angle of rotation(in radians) # @param MakeGroups to generate new groups from existing ones # @param NewMeshName is a name of new mesh to create + # @return instance of Mesh class def RotateObjectMakeMesh(self, theObject, Axis, AngleInRadians, MakeGroups=0,NewMeshName=""): if (isinstance( theObject, Mesh )): theObject = theObject.GetMesh() @@ -2143,19 +2304,19 @@ class Mesh: ## Find group of nodes close to each other within Tolerance. # @param Tolerance tolerance value - # @param list of group of nodes + # @return list of group of nodes def FindCoincidentNodes (self, Tolerance): return self.editor.FindCoincidentNodes(Tolerance) ## Find group of nodes close to each other within Tolerance. # @param Tolerance tolerance value # @param SubMeshOrGroup SubMesh or Group - # @param list of group of nodes + # @return list of group of nodes def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance): return self.editor.FindCoincidentNodesOnPart(SubMeshOrGroup, Tolerance) ## Merge nodes - # @param list of group of nodes + # @param GroupsOfNodes list of group of nodes def MergeNodes (self, GroupsOfNodes): self.editor.MergeNodes(GroupsOfNodes) @@ -2175,6 +2336,7 @@ class Mesh: self.editor.MergeEqualElements() ## Sew free borders + # @return SMESH::Sew_Error def SewFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1, FirstNodeID2, SecondNodeID2, LastNodeID2, CreatePolygons, CreatePolyedrs): @@ -2183,12 +2345,14 @@ class Mesh: CreatePolygons, CreatePolyedrs) ## Sew conform free borders + # @return SMESH::Sew_Error def SewConformFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1, FirstNodeID2, SecondNodeID2): return self.editor.SewConformFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1, FirstNodeID2, SecondNodeID2) ## Sew border to side + # @return SMESH::Sew_Error def SewBorderToSide (self, FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder, FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs): return self.editor.SewBorderToSide(FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder, @@ -2200,6 +2364,7 @@ class Mesh: # equal and they should have similar node connectivity. # The nodes to merge should belong to sides borders and # the first node should be linked to the second. + # @return SMESH::Sew_Error def SewSideElements (self, IDsOfSide1Elements, IDsOfSide2Elements, NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge, NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge): @@ -2217,12 +2382,14 @@ class Mesh: ## If during last operation of MeshEditor some nodes were # created this method returns list of its IDs, \n # if new nodes not created - returns empty list + # @return list of integer values (can be empty) def GetLastCreatedNodes(self): return self.editor.GetLastCreatedNodes() ## If during last operation of MeshEditor some elements were # created this method returns list of its IDs, \n # if new elements not creared - returns empty list + # @return list of integer values (can be empty) def GetLastCreatedElems(self): return self.editor.GetLastCreatedElems() @@ -2243,6 +2410,7 @@ class Mesh_Algorithm: ## Find hypothesis in study by its type name and parameters. # Find only those hypothesis, which was created in smeshpyD engine. + # @return SMESH.SMESH_Hypothesis def FindHypothesis (self, hypname, args, CompareMethod, smeshpyD): study = smeshpyD.GetCurrentStudy() #to do: find component by smeshpyD object, not by its data type @@ -2284,6 +2452,7 @@ class Mesh_Algorithm: ## Find algorithm in study by its type name. # Find only those algorithm, which was created in smeshpyD engine. + # @return SMESH.SMESH_Algo def FindAlgorithm (self, algoname, smeshpyD): study = smeshpyD.GetCurrentStudy() #to do: find component by smeshpyD object, not by its data type @@ -2438,6 +2607,7 @@ class Mesh_Segment(Mesh_Algorithm): # p=0.5 means rounding of (edge_length / l) to the nearest integer, # p=1 means rounding of (edge_length / l) to the lower integer. # Default value is 1e-07. + # @return an instance of StdMeshers_LocalLength hypothesis def LocalLength(self, l, UseExisting=0, p=1e-07): hyp = self.Hypothesis("LocalLength", [l,p], UseExisting=UseExisting, CompareMethod=self.CompareLocalLength) @@ -2445,6 +2615,7 @@ class Mesh_Segment(Mesh_Algorithm): hyp.SetPrecision(p) return hyp + ## Private method ## Check if the given "LocalLength" hypothesis has the same parameters as given arguments def CompareLocalLength(self, hyp, args): if IsEqual(hyp.GetLength(), args[0]): @@ -2456,6 +2627,7 @@ class Mesh_Segment(Mesh_Algorithm): # @param s for the scale factor (optional) # @param UseExisting if ==true - search existing hypothesis created with # same parameters, else (default) - create new + # @return an instance of StdMeshers_NumberOfSegments hypothesis def NumberOfSegments(self, n, s=[], UseExisting=0): if s == []: hyp = self.Hypothesis("NumberOfSegments", [n], UseExisting=UseExisting, @@ -2468,6 +2640,7 @@ class Mesh_Segment(Mesh_Algorithm): hyp.SetNumberOfSegments(n) return hyp + ## Private method ## Check if the given "NumberOfSegments" hypothesis has the same parameters as given arguments def CompareNumberOfSegments(self, hyp, args): if hyp.GetNumberOfSegments() == args[0]: @@ -2484,6 +2657,7 @@ class Mesh_Segment(Mesh_Algorithm): # @param end for the length of the last segment # @param UseExisting if ==true - search existing hypothesis created with # same parameters, else (default) - create new + # @return an instance of StdMeshers_Arithmetic1D hypothesis def Arithmetic1D(self, start, end, UseExisting=0): hyp = self.Hypothesis("Arithmetic1D", [start, end], UseExisting=UseExisting, CompareMethod=self.CompareArithmetic1D) @@ -2491,6 +2665,7 @@ class Mesh_Segment(Mesh_Algorithm): hyp.SetLength(end , 0) return hyp + ## Private method ## Check if the given "Arithmetic1D" hypothesis has the same parameters as given arguments def CompareArithmetic1D(self, hyp, args): if IsEqual(hyp.GetLength(1), args[0]): @@ -2503,6 +2678,7 @@ class Mesh_Segment(Mesh_Algorithm): # @param end for the length of the last segment # @param UseExisting if ==true - search existing hypothesis created with # same parameters, else (default) - create new + # @return an instance of StdMeshers_StartEndLength hypothesis def StartEndLength(self, start, end, UseExisting=0): hyp = self.Hypothesis("StartEndLength", [start, end], UseExisting=UseExisting, CompareMethod=self.CompareStartEndLength) @@ -3077,7 +3253,6 @@ class Mesh_Netgen(Mesh_Algorithm): # # More details. class Mesh_Projection1D(Mesh_Algorithm): - ## Private constructor. def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) @@ -3122,7 +3297,6 @@ class Mesh_Projection2D(Mesh_Algorithm): def __init__(self, mesh, geom=0): Mesh_Algorithm.__init__(self) self.Create(mesh, geom, "Projection_2D") - ## Define "Source Face" hypothesis, specifying a meshed face to # take a mesh pattern from, and optionally association of vertices # between the source face and a target one (where a hipothesis is assigned to) diff --git a/src/StdMeshers/StdMeshers_Distribution.hxx b/src/StdMeshers/StdMeshers_Distribution.hxx index 124e4e8bc..830fa0b1e 100644 --- a/src/StdMeshers/StdMeshers_Distribution.hxx +++ b/src/StdMeshers/StdMeshers_Distribution.hxx @@ -29,6 +29,8 @@ #ifndef _STD_MESHERS_DISTRIBUTION_HXX_ #define _STD_MESHERS_DISTRIBUTION_HXX_ +using namespace std; + #include "SMESH_StdMeshers.hxx" #include diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 5850cb74e..eccc3f5af 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -505,12 +506,20 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, return TSideVector(0); } } + // find out side orientation, which is important if there are several wires (PAL19080) + bool isForward = true; + if ( nbWires > 1 ) { + TopExp_Explorer e( theFace, TopAbs_EDGE ); + while ( ! e.Current().IsSame( wireEdges.back() )) + e.Next(); + isForward = ( e.Current().Orientation() == wireEdges.back().Orientation() ); + } + StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh, - true, theIgnoreMediumNodes); + isForward, theIgnoreMediumNodes); wires[ iW ] = StdMeshers_FaceSidePtr( wire ); from = to; } return wires; } - diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx index 7b76b3545..6307f167e 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx @@ -113,6 +113,8 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis { _hypMaxElementArea = NULL; _hypLengthFromEdges = NULL; + _edgeLength = 0; + _maxElementArea = 0; list ::const_iterator itl; const SMESHDS_Hypothesis *theHyp; @@ -121,8 +123,8 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis int nbHyp = hyps.size(); if (!nbHyp) { - aStatus = SMESH_Hypothesis::HYP_MISSING; - return false; // can't work with no hypothesis + aStatus = SMESH_Hypothesis::HYP_OK; //SMESH_Hypothesis::HYP_MISSING; + return true; // (PAL13464) can work with no hypothesis, LengthFromEdges is default one } itl = hyps.begin(); @@ -137,7 +139,6 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis _hypMaxElementArea = static_cast(theHyp); ASSERT(_hypMaxElementArea); _maxElementArea = _hypMaxElementArea->GetMaxArea(); - _edgeLength = 0; isOk = true; aStatus = SMESH_Hypothesis::HYP_OK; } @@ -146,8 +147,6 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis { _hypLengthFromEdges = static_cast(theHyp); ASSERT(_hypLengthFromEdges); - _edgeLength = 0; - _maxElementArea = 0; isOk = true; aStatus = SMESH_Hypothesis::HYP_OK; } @@ -201,7 +200,7 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh SMESH_Comment("Too few segments: ")<NbSegments()); // compute average edge length - if (_hypLengthFromEdges) + if (!_hypMaxElementArea) { _edgeLength = 0; int nbSegments = 0; @@ -215,7 +214,7 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh _edgeLength /= nbSegments; } - if (_hypLengthFromEdges && _edgeLength < DBL_MIN ) + if (/*_hypLengthFromEdges &&*/ _edgeLength < DBL_MIN ) _edgeLength = 100; Z nblf; //nombre de lignes fermees (enveloppe en tete) diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx index bc229bd2c..8ca0b72b8 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx @@ -83,7 +83,7 @@ protected: std::list myNodesOnCommonV; - SMESH_MesherHelper* myTool; // toll for working with quadratic elements + SMESH_MesherHelper* myTool; // tool for working with quadratic elements }; #endif diff --git a/src/StdMeshers/StdMeshers_Penta_3D.cxx b/src/StdMeshers/StdMeshers_Penta_3D.cxx index 4030cdfce..8f3d233a2 100644 --- a/src/StdMeshers/StdMeshers_Penta_3D.cxx +++ b/src/StdMeshers/StdMeshers_Penta_3D.cxx @@ -24,6 +24,8 @@ // File : StdMeshers_Penta_3D.cxx // Module : SMESH +using namespace std; + #include "StdMeshers_Penta_3D.hxx" #include "utilities.h" diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index 3e143481a..3b69a201f 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -25,6 +25,7 @@ // Created : Fri Oct 27 10:24:28 2006 // Author : Edward AGAPOV (eap) +using namespace std; #include "StdMeshers_ProjectionUtils.hxx" -- 2.39.2