From 6df8817c1a9827149025cc942249d7083f504d3d Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 17 Sep 2018 22:24:36 +0300 Subject: [PATCH] 23586: [EDF] HYDRO: Copy mesh to new geometry --- doc/salome/gui/SMESH/images/copy_mesh_dlg.png | Bin 23114 -> 26601 bytes doc/salome/gui/SMESH/input/copy_mesh.rst | 12 +- idl/SMESH_Gen.idl | 31 + resources/CMakeLists.txt | 1 + resources/copy_mesh_with_geom.png | Bin 0 -> 636 bytes src/SMESH/SMESH_Mesh.cxx | 4 +- src/SMESH/SMESH_Mesh.hxx | 2 +- src/SMESH/SMESH_subMesh.cxx | 2 +- src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx | 295 +++++- src/SMESHGUI/SMESHGUI_CopyMeshDlg.h | 18 +- src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx | 11 + src/SMESHGUI/SMESHGUI_GEOMGenUtils.h | 2 + src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx | 10 +- src/SMESHGUI/SMESHGUI_MeshOp.cxx | 54 +- src/SMESHGUI/SMESHGUI_MeshOp.h | 5 +- src/SMESHGUI/SMESHGUI_Utils.cxx | 6 + src/SMESHGUI/SMESHGUI_Utils.h | 12 + src/SMESHGUI/SMESH_images.ts | 4 + src/SMESHGUI/SMESH_msg_en.ts | 27 + src/SMESH_I/SMESH_2smeshpy.cxx | 14 +- src/SMESH_I/SMESH_Algo_i.cxx | 24 + src/SMESH_I/SMESH_Algo_i.hxx | 9 + src/SMESH_I/SMESH_Gen_i.cxx | 888 +++++++++++++++++- src/SMESH_I/SMESH_Gen_i.hxx | 28 +- src/SMESH_I/SMESH_Gen_i_1.cxx | 116 ++- src/SMESH_I/SMESH_Group_i.cxx | 8 +- src/SMESH_I/SMESH_Hypothesis_i.hxx | 14 +- src/SMESH_I/SMESH_Mesh_i.cxx | 47 +- src/SMESH_I/SMESH_Mesh_i.hxx | 2 +- src/SMESH_I/SMESH_PythonDump.cxx | 10 + src/SMESH_I/SMESH_PythonDump.hxx | 6 + src/SMESH_I/SMESH_subMesh_i.cxx | 29 + src/SMESH_I/SMESH_subMesh_i.hxx | 22 + src/SMESH_SWIG/smeshBuilder.py | 39 +- src/StdMeshers/StdMeshers_Arithmetic1D.cxx | 39 +- src/StdMeshers/StdMeshers_Arithmetic1D.hxx | 18 +- src/StdMeshers/StdMeshers_FixedPoints1D.cxx | 26 +- src/StdMeshers/StdMeshers_FixedPoints1D.hxx | 14 +- .../StdMeshers_NumberOfSegments.cxx | 18 +- .../StdMeshers_NumberOfSegments.hxx | 17 +- .../StdMeshers_QuadrangleParams.hxx | 2 +- src/StdMeshers/StdMeshers_Reversible1D.hxx | 2 +- src/StdMeshers/StdMeshers_StartEndLength.cxx | 42 +- src/StdMeshers/StdMeshers_StartEndLength.hxx | 16 +- src/StdMeshers_I/StdMeshers_Adaptive1D_i.hxx | 6 + .../StdMeshers_Arithmetic1D_i.cxx | 122 +-- .../StdMeshers_Arithmetic1D_i.hxx | 28 +- .../StdMeshers_AutomaticLength_i.hxx | 6 + .../StdMeshers_CartesianParameters3D_i.hxx | 7 + .../StdMeshers_Deflection1D_i.hxx | 5 + .../StdMeshers_FixedPoints1D_i.cxx | 124 +-- .../StdMeshers_FixedPoints1D_i.hxx | 28 +- src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx | 36 +- src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx | 12 + .../StdMeshers_ImportSource1D_i.hxx | 11 + .../StdMeshers_ImportSource2D_i.hxx | 11 + .../StdMeshers_LayerDistribution2D_i.hxx | 11 + .../StdMeshers_LayerDistribution_i.hxx | 11 + .../StdMeshers_LengthFromEdges_i.hxx | 11 + src/StdMeshers_I/StdMeshers_LocalLength_i.hxx | 11 + .../StdMeshers_MaxElementArea_i.hxx | 12 + .../StdMeshers_MaxElementVolume_i.hxx | 11 + src/StdMeshers_I/StdMeshers_MaxLength_i.hxx | 11 + .../StdMeshers_NotConformAllowed_i.hxx | 11 + .../StdMeshers_NumberOfLayers2D_i.hxx | 11 + .../StdMeshers_NumberOfLayers_i.hxx | 11 + .../StdMeshers_NumberOfSegments_i.cxx | 127 +-- .../StdMeshers_NumberOfSegments_i.hxx | 21 +- src/StdMeshers_I/StdMeshers_ObjRefUlils.cxx | 18 + src/StdMeshers_I/StdMeshers_ObjRefUlils.hxx | 7 + .../StdMeshers_ProjectionSource1D_i.cxx | 43 + .../StdMeshers_ProjectionSource1D_i.hxx | 9 + .../StdMeshers_ProjectionSource2D_i.cxx | 45 + .../StdMeshers_ProjectionSource2D_i.hxx | 10 + .../StdMeshers_ProjectionSource3D_i.cxx | 45 + .../StdMeshers_ProjectionSource3D_i.hxx | 12 +- src/StdMeshers_I/StdMeshers_Propagation_i.hxx | 12 + .../StdMeshers_QuadrangleParams_i.cxx | 51 + .../StdMeshers_QuadrangleParams_i.hxx | 10 + .../StdMeshers_QuadranglePreference_i.hxx | 6 + .../StdMeshers_QuadraticMesh_i.hxx | 6 + .../StdMeshers_Reversible1D_i.cxx | 43 +- .../StdMeshers_Reversible1D_i.hxx | 13 +- ...StdMeshers_SegmentLengthAroundVertex_i.hxx | 10 + .../StdMeshers_StartEndLength_i.cxx | 120 +-- .../StdMeshers_StartEndLength_i.hxx | 20 +- .../StdMeshers_ViscousLayers2D_i.cxx | 52 +- .../StdMeshers_ViscousLayers2D_i.hxx | 11 + .../StdMeshers_ViscousLayers_i.cxx | 41 + .../StdMeshers_ViscousLayers_i.hxx | 9 + 90 files changed, 2471 insertions(+), 723 deletions(-) create mode 100644 resources/copy_mesh_with_geom.png diff --git a/doc/salome/gui/SMESH/images/copy_mesh_dlg.png b/doc/salome/gui/SMESH/images/copy_mesh_dlg.png index c959e680f6f20123999988deef191927db99fd4c..97ca1cac7ad153d74e006363744a9dbf17d377da 100644 GIT binary patch literal 26601 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�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%0A^n@ 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 W7p+T*Z>{P80000IsUsedHypothesis( hyp )) return; - if (_callUp) - _callUp->HypothesisModified(); + if (_callUp && hyp) + _callUp->HypothesisModified( hyp->GetID() ); SMESH_Algo *algo; const SMESH_HypoFilter* compatibleHypoKind; diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index c52b5ef2e..dbe14fed8 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -334,7 +334,7 @@ class SMESH_EXPORT SMESH_Mesh struct TCallUp // callback from SMESH to SMESH_I level { virtual void RemoveGroup (const int theGroupID)=0; - virtual void HypothesisModified ()=0; + virtual void HypothesisModified (int theHypID)=0; virtual void Load ()=0; virtual ~TCallUp() {} }; diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 7bab8d9e7..8ef0c8827 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -365,7 +365,7 @@ int SMESH_subMesh::computeCost() const */ //============================================================================= -const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() +const std::map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() { if ( _dependenceAnalysed || !_father->HasShapeToMesh() ) return _mapDepend; diff --git a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx index 4dabf6c90..b7794c02d 100644 --- a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx @@ -24,32 +24,34 @@ #include "SMESHGUI_CopyMeshDlg.h" #include "SMESHGUI.h" +#include "SMESHGUI_FilterDlg.h" +#include "SMESHGUI_GEOMGenUtils.h" +#include "SMESHGUI_IdValidator.h" +#include "SMESHGUI_MeshUtils.h" +#include "SMESHGUI_Selection.h" #include "SMESHGUI_SpinBox.h" #include "SMESHGUI_Utils.h" #include "SMESHGUI_VTKUtils.h" -#include "SMESHGUI_MeshUtils.h" -#include "SMESHGUI_IdValidator.h" -#include "SMESHGUI_FilterDlg.h" #include #include #include // SALOME GUI includes +#include +#include +#include #include -#include -#include #include #include - -#include -#include - +#include +#include #include #include -#include +#include // SALOME KERNEL includes +#include #include // OCCT includes @@ -113,7 +115,8 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule ) myFilterDlg(0), myIsApplyAndClose( false ) { - QPixmap image (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_COPY_MESH"))); + QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_COPY_MESH"))); + QPixmap image2 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_COPY_MESH_WG"))); setModal(false); setAttribute(Qt::WA_DeleteOnClose, true); @@ -126,18 +129,21 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule ) /***************************************************************/ ConstructorsBox = new QGroupBox(tr("SMESH_COPY_MESH_TITLE"), this); - QButtonGroup* GroupConstructors = new QButtonGroup(this); + GroupConstructors = new QButtonGroup(this); QHBoxLayout* ConstructorsBoxLayout = new QHBoxLayout(ConstructorsBox); ConstructorsBoxLayout->setSpacing(SPACING); ConstructorsBoxLayout->setMargin(MARGIN); QRadioButton* RadioButton1= new QRadioButton(ConstructorsBox); - RadioButton1->setIcon(image); + RadioButton1->setIcon(image1); GroupConstructors->addButton(RadioButton1, 0); + QRadioButton* RadioButton2= new QRadioButton(ConstructorsBox); + RadioButton2->setIcon(image2); + GroupConstructors->addButton(RadioButton2, 1); ConstructorsBoxLayout->addWidget(RadioButton1); + ConstructorsBoxLayout->addWidget(RadioButton2); RadioButton1->setChecked(true); - GroupConstructors->addButton(RadioButton1, 0); /***************************************************************/ GroupArguments = new QGroupBox(tr("SMESH_ARGUMENTS"), this); @@ -164,13 +170,26 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule ) // CheckBox for copying groups myCopyGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments); - myCopyGroupsCheck->setChecked(false); + myCopyGroupsCheck->setChecked(true); // CheckBox for keeping ids ( OBSOLETE ) myKeepIdsCheck = new QCheckBox(tr("SMESH_KEEP_IDS"), GroupArguments); myKeepIdsCheck->setChecked(true); myKeepIdsCheck->hide(); + // New geometry + myGeomLabel = new QLabel( tr("NEW_GEOM"), GroupArguments ); + myGeomNameEdit = new QLineEdit( GroupArguments ); + myGeomNameEdit->setReadOnly(true); + + // CheckBox to reuse hypotheses + myReuseHypCheck = new QCheckBox(tr("REUSE_HYPOTHESES"), GroupArguments); + myReuseHypCheck->setChecked(true); + + // CheckBox to copy mesh elements + myCopyElementsCheck = new QCheckBox(tr("COPY_ELEMENTS"), GroupArguments); + myCopyElementsCheck->setChecked(true); + // layout GroupArgumentsLayout->addWidget(myTextLabelElements, 0, 0); GroupArgumentsLayout->addWidget(myLineEditElements, 0, 1, 1, 5); @@ -178,8 +197,13 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule ) GroupArgumentsLayout->addWidget(myIdSourceCheck, 1, 0, 1, 6); GroupArgumentsLayout->addWidget(meshNameLabel, 2, 0); GroupArgumentsLayout->addWidget(myMeshNameEdit, 2, 1, 1, 5); - GroupArgumentsLayout->addWidget(myCopyGroupsCheck, 3, 0, 1, 6); - // GroupArgumentsLayout->addWidget(myKeepIdsCheck, 4, 0, 1, 6); + GroupArgumentsLayout->addWidget(myGeomLabel, 3, 0); + GroupArgumentsLayout->addWidget(myGeomNameEdit, 3, 1, 1, 5); + GroupArgumentsLayout->addWidget(myCopyGroupsCheck, 4, 0, 1, 6); + GroupArgumentsLayout->addWidget(myReuseHypCheck, 5, 0, 1, 6); + GroupArgumentsLayout->addWidget(myCopyElementsCheck, 6, 0, 1, 6); + // GroupArgumentsLayout->addWidget(myKeepIdsCheck, 7, 0, 1, 6); + GroupArgumentsLayout->setRowStretch( 6, 1 ); /***************************************************************/ GroupButtons = new QGroupBox(this); @@ -243,6 +267,9 @@ SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule ) this, SLOT (onTextChange(const QString&))); connect(myIdSourceCheck, SIGNAL(toggled(bool)), this, SLOT (onSelectIdSource(bool))); + connect(GroupConstructors, SIGNAL(buttonClicked(int)), + this, SLOT (onConstructor(int))); + SelectionIntoArgument(); } @@ -275,11 +302,12 @@ void SMESHGUI_CopyMeshDlg::Init (bool ResetControls) { myBusy = false; - myMeshNameEdit->setText( SMESH::UniqueMeshName("Mesh")); + if ( !isWithGeomMode() ) + myMeshNameEdit->setText( SMESH::UniqueMeshName("Mesh")); + if ( ResetControls ) { myLineEditElements->clear(); - //myElementsId = ""; myNbOkElements = 0; buttonOk->setEnabled(false); @@ -289,11 +317,98 @@ void SMESHGUI_CopyMeshDlg::Init (bool ResetControls) myMesh = SMESH::SMESH_Mesh::_nil(); myIdSourceCheck->setChecked(true); - myCopyGroupsCheck->setChecked(false); - myKeepIdsCheck->setChecked(false); - onSelectIdSource( myIdSourceCheck->isChecked() ); + onConstructor( 0 ); + } +} + +//======================================================================= +//function : onConstructor +//purpose : switch operation mode +//======================================================================= + +void SMESHGUI_CopyMeshDlg::onConstructor( int withGeom ) +{ + myGeomLabel ->setVisible( withGeom ); + myGeomNameEdit ->setVisible( withGeom ); + myReuseHypCheck ->setVisible( withGeom ); + myCopyElementsCheck->setVisible( withGeom ); + myFilterBtn ->setVisible( !withGeom ); + myIdSourceCheck ->setVisible( !withGeom ); + + if ( !withGeom ) + myMeshNameEdit->setText( SMESH::UniqueMeshName("Mesh")); + + onSelectIdSource( /*toSelectMesh=*/ myIdSourceCheck->isChecked() || withGeom ); +} + +//======================================================================= +//function : getErrorMsg +//purpose : Return an error message and entries of invalid smesh object +//======================================================================= + +QString SMESHGUI_CopyMeshDlg::getErrorMsg( SMESH::string_array_var theInvalidEntries, + QStringList & theEntriesToBrowse ) +{ + if ( theInvalidEntries->length() == 0 ) + return tr("SMESH_OPERATION_FAILED"); + + // theInvalidEntries - SObject's that hold geometry objects whose + // counterparts are not found in the newGeometry, followed by SObject's + // holding mesh sub-objects that are invalid because they depend on a not found + // preceeding sub-shape + + QString msg = tr("SUBSHAPES_NOT_FOUND_MSG") + "\n"; + + QString objString; + for ( CORBA::ULong i = 0; i < theInvalidEntries->length(); ++i ) + { + _PTR(SObject) so = SMESH::getStudy()->FindObjectID( theInvalidEntries[i].in() ); + + int objType = SMESHGUI_Selection::type( theInvalidEntries[i].in() ); + if ( objType < 0 ) // geom object + { + objString += "\n"; + if ( so ) + objString += so->GetName().c_str(); + else + objString += theInvalidEntries[i].in(); // it's something like "FACE #2" + } + else // smesh object + { + theEntriesToBrowse.push_back( theInvalidEntries[i].in() ); + + objString += "\n "; + switch ( objType ) { + case SMESH::MESH: + objString += tr("SMESH_MESH"); break; + case SMESH::HYPOTHESIS: + objString += tr("SMESH_HYPOTHESIS"); break; + case SMESH::ALGORITHM: + objString += tr("SMESH_ALGORITHM"); break; + case SMESH::SUBMESH_VERTEX: + case SMESH::SUBMESH_EDGE: + case SMESH::SUBMESH_FACE: + case SMESH::SUBMESH_SOLID: + case SMESH::SUBMESH_COMPOUND: + case SMESH::SUBMESH: + objString += tr("SMESH_SUBMESH"); break; + case SMESH::GROUP: + objString += tr("SMESH_GROUP"); break; + default:; + } + objString += " \""; + if ( so ) + objString += so->GetName().c_str(); + objString += "\" ("; + objString += theInvalidEntries[i].in(); + objString += ")"; + } } + if ( !objString.isEmpty() ) + msg += objString; + + return msg; } //================================================================================= @@ -303,13 +418,14 @@ void SMESHGUI_CopyMeshDlg::Init (bool ResetControls) bool SMESHGUI_CopyMeshDlg::ClickOnApply() { - if (SMESHGUI::isStudyLocked()) + if ( SMESHGUI::isStudyLocked() ) return false; if( !isValid() ) return false; QStringList anEntryList; + bool toShowObjects = isApplyAndClose(); try { SUIT_OverrideCursor aWaitCursor; @@ -333,16 +449,55 @@ bool SMESHGUI_CopyMeshDlg::ClickOnApply() } QByteArray meshName = myMeshNameEdit->text().toUtf8(); bool toCopyGroups = ( myCopyGroupsCheck->isChecked() ); + bool toReuseHyps = ( myReuseHypCheck->isChecked() ); + bool toCopyElems = ( myCopyElementsCheck->isChecked() ); bool toKeepIDs = ( myKeepIdsCheck->isChecked() ); SMESH::SMESH_Gen_var gen = SMESHGUI::GetSMESHGen(); - SMESH::SMESH_Mesh_var newMesh = - gen->CopyMesh(aPartToCopy, meshName.constData(), toCopyGroups, toKeepIDs); - if( !newMesh->_is_nil() ) - if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) ) + SMESH::SMESH_Mesh_var newMesh; + if ( isWithGeomMode() ) + { + SMESH::SMESH_Mesh_var srcMesh = mySelectedObject->GetMesh(); + SMESH::ListOfGroups_var newGroups; + SMESH::submesh_array_var newSubmeshes; + SMESH::ListOfHypothesis_var newHypotheses; + SMESH::string_array_var invalidEntries; + CORBA::Boolean ok = gen->CopyMeshWithGeom( srcMesh, myNewGeometry, + meshName.constData(), + toCopyGroups, toReuseHyps, toCopyElems, + newMesh.out(), + newGroups.out(), + newSubmeshes.out(), + newHypotheses.out(), + invalidEntries.out() ); + if ( !ok ) + { + if ( invalidEntries->length() > 0 ) + toShowObjects = true; + SUIT_MessageBox::warning( this, + tr("SMESH_WRN_WARNING"), + getErrorMsg( invalidEntries, anEntryList )); + } + } + else + { + newMesh = gen->CopyMesh(aPartToCopy, meshName.constData(), toCopyGroups, toKeepIDs); + } + if ( !newMesh->_is_nil() ) + if ( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) ) + { anEntryList.append( aSObject->GetID().c_str() ); + + if ( isWithGeomMode() ) + SMESH::SetName( aSObject, meshName ); + } } - catch (...) { + catch(const SALOME::SALOME_Exception & S_ex) + { + SalomeApp_Tools::QtCatchCorbaException(S_ex); + } + catch (...) + { } mySMESHGUI->updateObjBrowser(true); @@ -350,7 +505,7 @@ bool SMESHGUI_CopyMeshDlg::ClickOnApply() if( LightApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ) ) - anApp->browseObjects( anEntryList, isApplyAndClose() ); + anApp->browseObjects( anEntryList, toShowObjects ); Init(false); mySelectedObject = SMESH::SMESH_IDSource::_nil(); @@ -503,13 +658,12 @@ void SMESHGUI_CopyMeshDlg::SelectionIntoArgument() myActor = 0; QString aString = ""; - myLineEditElements->setText(aString); myNbOkElements = 0; buttonOk->setEnabled(false); buttonApply->setEnabled(false); myFilterBtn->setEnabled(false); - // get selected mesh + // get selected mesh or geometry SALOME_ListIO aList; mySelectionMgr->selectedObjects(aList); int nbSel = aList.Extent(); @@ -517,19 +671,29 @@ void SMESHGUI_CopyMeshDlg::SelectionIntoArgument() return; Handle(SALOME_InteractiveObject) IO = aList.First(); - mySelectedObject = SMESH::IObjectToInterface( IO ); - if ( mySelectedObject->_is_nil() ) - return; - myMesh = SMESH::GetMeshByIO(IO); - if (myMesh->_is_nil()) - return; + SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO(IO); + GEOM::GEOM_Object_var geom = SMESH::GetGeom(IO); - myActor = SMESH::FindActorByEntry(IO->getEntry()); - if (!myActor) - myActor = SMESH::FindActorByObject(myMesh); + if ( !mesh->_is_nil() ) + { + myMesh = mesh; + myActor = SMESH::FindActorByEntry(IO->getEntry()); + if (!myActor) + myActor = SMESH::FindActorByObject(myMesh); + + mySelectedObject = SMESH::IObjectToInterface( IO ); + if ( mySelectedObject->_is_nil() ) + return; + } + else if ( !geom->_is_nil() ) + { + myNewGeometry = geom; + } + else + return; - if (myIdSourceCheck->isChecked()) + if (myIdSourceCheck->isChecked() || isWithGeomMode() ) { SMESH::GetNameOfSelectedIObjects( mySelectionMgr, aString ); if ( aString.isEmpty() ) aString = " "; @@ -541,8 +705,23 @@ void SMESHGUI_CopyMeshDlg::SelectionIntoArgument() myNbOkElements = aString.size(); myFilterBtn->setEnabled(true); } - myLineEditElements->setText( aString ); + bool ok = !aString.isEmpty(); + if ( !mesh->_is_nil() ) + { + myLineEditElements->setText( aString ); + if ( isWithGeomMode() ) + myMeshNameEdit->setText( aString ); + } + else if ( !geom->_is_nil() ) + { + myGeomNameEdit->setText( aString ); + ok = ok && !myLineEditElements->text().isEmpty(); + } + + if ( ok && isWithGeomMode() && !myMesh->_is_nil() ) + ok = myMesh->HasShapeToMesh(); + buttonOk->setEnabled(ok); buttonApply->setEnabled(ok); @@ -554,7 +733,9 @@ void SMESHGUI_CopyMeshDlg::SelectionIntoArgument() //======================================================================= void SMESHGUI_CopyMeshDlg::onSelectIdSource (bool toSelectMesh) { - if (toSelectMesh) + if ( isWithGeomMode() ) + myTextLabelElements->setText(tr("SMESH_MESH")); + else if ( toSelectMesh ) myTextLabelElements->setText(tr("OBJECT_NAME")); else myTextLabelElements->setText(tr("ELEM_IDS")); @@ -564,7 +745,8 @@ void SMESHGUI_CopyMeshDlg::onSelectIdSource (bool toSelectMesh) } mySelectionMgr->clearFilters(); - mySelectionMgr->installFilter(myIdSourceFilter); + if ( !isWithGeomMode() ) + mySelectionMgr->installFilter(myIdSourceFilter); SMESH::SetPointRepresentation(false); if (toSelectMesh) { @@ -592,10 +774,29 @@ void SMESHGUI_CopyMeshDlg::onSelectIdSource (bool toSelectMesh) bool SMESHGUI_CopyMeshDlg::isValid() { - if ( myIdSourceCheck->isChecked() ) - return !mySelectedObject->_is_nil(); + bool ok = false; + if ( myIdSourceCheck->isChecked() || isWithGeomMode() ) + { + ok = ( !mySelectedObject->_is_nil() ); + if ( isWithGeomMode() ) + ok = ok && ( !myNewGeometry->_is_nil() ); + } + else + { + ok = ( myNbOkElements > 0 ); + } + + return ok; +} - return myNbOkElements > 0; +//======================================================================= +//function : isWithGeomMode +//purpose : Return true if the mode is "with geometry" +//======================================================================= + +bool SMESHGUI_CopyMeshDlg::isWithGeomMode() +{ + return ( GroupConstructors->checkedId() == 1 ); } //================================================================================= diff --git a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h index fe4a8f1a9..2566e7aa6 100644 --- a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h +++ b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h @@ -35,12 +35,14 @@ // IDL includes #include #include CORBA_SERVER_HEADER(SMESH_Mesh) +#include CORBA_SERVER_HEADER(SMESH_Gen) class QCheckBox; class QGroupBox; class QLabel; class QLineEdit; class QPushButton; +class QButtonGroup; class SMESHGUI; class SMESHGUI_IdValidator; @@ -56,10 +58,10 @@ class SUIT_SelectionFilter; //================================================================================= class SMESHGUI_EXPORT SMESHGUI_CopyMeshDlg : public QDialog -{ +{ Q_OBJECT -public: + public: SMESHGUI_CopyMeshDlg( SMESHGUI* ); ~SMESHGUI_CopyMeshDlg(); @@ -67,10 +69,12 @@ private: void Init( bool = true ); void enterEvent( QEvent* ); /* mouse enter the QWidget */ void keyPressEvent( QKeyEvent* ); - int GetConstructorId(); void setNewMeshName(); + QString getErrorMsg( SMESH::string_array_var invalidEntries, + QStringList & entriesToBrowse ); bool isValid(); + bool isWithGeomMode(); void setIsApplyAndClose( const bool theFlag ); bool isApplyAndClose() const; @@ -84,11 +88,14 @@ private: bool myBusy; SMESH::SMESH_Mesh_var myMesh; + GEOM::GEOM_Object_var myNewGeometry; SMESH_Actor* myActor; SUIT_SelectionFilter* myIdSourceFilter; SMESH::SMESH_IDSource_var mySelectedObject; + QButtonGroup* GroupConstructors; + QGroupBox* ConstructorsBox; QGroupBox* GroupArguments; QGroupBox* GroupButtons; @@ -99,10 +106,14 @@ private: QPushButton* buttonHelp; QLabel* myTextLabelElements; + QLabel* myGeomLabel; QLineEdit* myLineEditElements; QLineEdit* myMeshNameEdit; + QLineEdit* myGeomNameEdit; QCheckBox* myIdSourceCheck; QCheckBox* myCopyGroupsCheck; + QCheckBox* myReuseHypCheck; + QCheckBox* myCopyElementsCheck; QCheckBox* myKeepIdsCheck; QPushButton* myFilterBtn; @@ -122,6 +133,7 @@ private slots: void SelectionIntoArgument(); void DeactivateActiveDialog(); void ActivateThisDialog(); + void onConstructor( int ); void onTextChange( const QString& ); void onSelectIdSource( bool ); void setFilters(); diff --git a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx index 536742006..7a403902d 100644 --- a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.cxx @@ -111,6 +111,17 @@ namespace SMESH return aMeshShape; } + GEOM::GEOM_Object_var GetGeom( Handle(SALOME_InteractiveObject) io ) + { + GEOM::GEOM_Object_var go; + if ( !io.IsNull() && io->hasEntry() ) + { + _PTR(SObject) so = SMESH::getStudy()->FindObjectID( io->getEntry() ); + go = GetGeom( so ); + } + return go._retn(); + } + SMESHGUI_EXPORT char* GetGeomName( _PTR(SObject) smeshSO ) { if (!smeshSO) diff --git a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h index f59609e07..33031215c 100644 --- a/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h +++ b/src/SMESHGUI/SMESHGUI_GEOMGenUtils.h @@ -51,6 +51,8 @@ namespace SMESH SMESHGUI_EXPORT GEOM::GEOM_Object_var GetGeom( _PTR(SObject) ); + SMESHGUI_EXPORT GEOM::GEOM_Object_var GetGeom( Handle(SALOME_InteractiveObject) io ); + SMESHGUI_EXPORT char* GetGeomName( _PTR(SObject) smeshSO ); SMESHGUI_EXPORT GEOM::GEOM_Object_ptr GetSubShape( GEOM::GEOM_Object_ptr, long ); diff --git a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx index 7aff8c6ce..255d2f575 100644 --- a/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx +++ b/src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx @@ -523,13 +523,15 @@ namespace SMESH if(MYDEBUG) MESSAGE("Loading client meshers plugin library ..."); #ifdef WIN32 #ifdef UNICODE - LPTSTR path = new TCHAR[aClientLibName.length() + 1]; - path[aClientLibName.toWCharArray(path)] = '\0'; + LPTSTR path = new TCHAR[aClientLibName.length() + 1]; + path[aClientLibName.toWCharArray(path)] = '\0'; #else - const char* path = aClientLibName.toUtf8().data(); + QByteArray baPath = aClientLibName.toUtf8(); + const char* path = baPath.data(); #endif #else - char* path = aClientLibName.toUtf8().data(); + QByteArray baPath = aClientLibName.toUtf8(); + char* path = baPath.data(); #endif LibHandle libHandle = LoadLib( path ); if (!libHandle) { diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.cxx b/src/SMESHGUI/SMESHGUI_MeshOp.cxx index 9378e4d40..9c690f378 100644 --- a/src/SMESHGUI/SMESHGUI_MeshOp.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshOp.cxx @@ -92,6 +92,7 @@ SMESHGUI_MeshOp::SMESHGUI_MeshOp( const bool theToCreate, const bool theIsMesh ) myShapeByMeshOp( 0 ), myToCreate( theToCreate ), myIsMesh( theIsMesh ), + myIsInvalidSubMesh( false ), myHypoSet( 0 ) { if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists @@ -152,7 +153,7 @@ bool SMESHGUI_MeshOp::onApply() QStringList anEntryList; if ( myToCreate && myIsMesh ) aResult = createMesh( aMess, anEntryList ); - if ( myToCreate && !myIsMesh ) + if (( myToCreate && !myIsMesh ) || myIsInvalidSubMesh ) aResult = createSubMesh( aMess, anEntryList ); else if ( !myToCreate ) aResult = editMeshOrSubMesh( aMess ); @@ -519,6 +520,7 @@ void SMESHGUI_MeshOp::selectionDone() try { myIsOnGeometry = true; + myIsInvalidSubMesh = false; //Check geometry for mesh QString anObjEntry = myDlg->selectedObject(SMESHGUI_MeshDlg::Obj); @@ -638,11 +640,21 @@ void SMESHGUI_MeshOp::selectionDone() SMESH::SMESH_subMesh_var submeshVar = SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() ); myIsMesh = submeshVar->_is_nil(); + myIsInvalidSubMesh = ( !myIsMesh && submeshVar->GetId() < 1 ); myDlg->setTitile( myToCreate, myIsMesh ); myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, !submeshVar->_is_nil() ); myDlg->setObjectShown( SMESHGUI_MeshDlg::Geom, true ); myDlg->objectWg( SMESHGUI_MeshDlg::Mesh, SMESHGUI_MeshDlg::Btn )->hide(); - myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide(); + if ( myIsInvalidSubMesh ) + { + // it is necessary to select a new geometry + myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->show(); + myDlg->activateObject( SMESHGUI_MeshDlg::Geom ); + } + else + { + myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide(); + } myDlg->updateGeometry(); myDlg->adjustSize(); readMesh(); @@ -1877,9 +1889,9 @@ bool SMESHGUI_MeshOp::createMesh( QString& theMess, QStringList& theEntryList ) //================================================================================ /*! * \brief Creates sub-mesh - * \param theMess - Output parameter intended for returning error message - * \param theEntryList - List of entries of published objects - * \retval bool - TRUE if sub-mesh is created, FALSE otherwise + * \param theMess - Output parameter intended for returning error message + * \param theEntryList - List of entries of published objects + * \retval bool - TRUE if sub-mesh is created, FALSE otherwise * * Creates sub-mesh */ @@ -1893,11 +1905,16 @@ bool SMESHGUI_MeshOp::createSubMesh( QString& theMess, QStringList& theEntryList return false; // get mesh object - QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh ); - _PTR(SObject) pMesh = SMESH::getStudy()->FindObjectID( aMeshEntry.toUtf8().data() ); SMESH::SMESH_Mesh_var aMeshVar = - SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() ); - if (aMeshVar->_is_nil()) + SMESH::EntryToInterface( myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh )); + if ( aMeshVar->_is_nil() && myIsInvalidSubMesh ) + { + SMESH::SMESH_subMesh_var aSMVar = + SMESH::EntryToInterface( myDlg->selectedObject( SMESHGUI_MeshDlg::Obj )); + if ( !aSMVar->_is_nil() ) + aMeshVar = aSMVar->GetMesh(); + } + if ( aMeshVar->_is_nil() ) return false; // GEOM shape of the main mesh @@ -1971,8 +1988,14 @@ bool SMESHGUI_MeshOp::createSubMesh( QString& theMess, QStringList& theEntryList SUIT_OverrideCursor aWaitCursor; + QString aNameOrID = aName; + if ( myIsInvalidSubMesh ) + // pass a sub-mesh entry to mesh->GetSubMesh() to replace the invalid sub-mesh + // by a valid one in an existing SO + aNameOrID = myDlg->selectedObject(SMESHGUI_MeshDlg::Obj); + // create sub-mesh - SMESH::SMESH_subMesh_var aSubMeshVar = aMeshVar->GetSubMesh( aGeomVar, aName.toUtf8().data() ); + SMESH::SMESH_subMesh_var aSubMeshVar = aMeshVar->GetSubMesh( aGeomVar, aNameOrID.toUtf8().data() ); _PTR(SObject) aSubMeshSO = SMESH::FindSObject( aSubMeshVar.in() ); if ( aSubMeshSO ) { SMESH::SetName( aSubMeshSO, aName.toUtf8().data() ); @@ -2249,10 +2272,13 @@ void SMESHGUI_MeshOp::readMesh() myHasConcurrentSubBefore = checkSubMeshConcurrency( aMeshVar, aSubMeshVar ); } - // Get name of geometry object - CORBA::String_var name = SMESH::GetGeomName( pObj ); - if ( name.in() ) - myDlg->setObjectText( SMESHGUI_MeshDlg::Geom, name.in() ); + if ( !myIsInvalidSubMesh ) + { + // Get name of geometry object + CORBA::String_var name = SMESH::GetGeomName( pObj ); + if ( name.in() ) + myDlg->setObjectText( SMESHGUI_MeshDlg::Geom, name.in() ); + } } // Get hypotheses and algorithms assigned to the mesh/sub-mesh diff --git a/src/SMESHGUI/SMESHGUI_MeshOp.h b/src/SMESHGUI/SMESHGUI_MeshOp.h index 8ba4f8c40..48879d0f0 100644 --- a/src/SMESHGUI/SMESHGUI_MeshOp.h +++ b/src/SMESHGUI/SMESHGUI_MeshOp.h @@ -153,8 +153,11 @@ private: SMESHGUI_ShapeByMeshOp* myShapeByMeshOp; bool myToCreate; bool myIsMesh; - bool myIsOnGeometry; //!< TRUE if edited mesh accotiated with geometrical object + bool myIsOnGeometry; //!< TRUE if edited mesh is based on geometry bool myHasConcurrentSubBefore; + bool myIsInvalidSubMesh; //!< "invalid sub-mesh" is edited + // The geometry of "invalid sub-mesh" is not a sub-shape of the main shape; + // it is created for the case where a valid sub-shape not found by CopyMeshWithGeom() TDim2Type2HypList myExistingHyps; //!< all hypothesis of SMESH module TDim2Type2HypList myObjHyps; //!< hypothesis assigned to the current diff --git a/src/SMESHGUI/SMESHGUI_Utils.cxx b/src/SMESHGUI/SMESHGUI_Utils.cxx index b8e679e67..5721e5301 100644 --- a/src/SMESHGUI/SMESHGUI_Utils.cxx +++ b/src/SMESHGUI/SMESHGUI_Utils.cxx @@ -226,6 +226,12 @@ namespace SMESH return app->orb()->string_to_object(theIOR.toLatin1().data()); } + CORBA::Object_var EntryToObject( const QString& theEntry ) + { + _PTR(SObject) anObj = getStudy()->FindObjectID( theEntry.toLatin1().data() ); + return SObjectToObject(anObj); + } + int GetNameOfSelectedIObjects(LightApp_SelectionMgr* theMgr, QString& theName) { if (!theMgr) diff --git a/src/SMESHGUI/SMESHGUI_Utils.h b/src/SMESHGUI/SMESHGUI_Utils.h index 6ff20e8a2..41d2e674e 100644 --- a/src/SMESHGUI/SMESHGUI_Utils.h +++ b/src/SMESHGUI/SMESHGUI_Utils.h @@ -152,6 +152,18 @@ SMESHGUI_EXPORT return TInterface::_nil(); } +SMESHGUI_EXPORT + CORBA::Object_var EntryToObject( const QString& ); + + template typename TInterface::_var_type + EntryToInterface( const QString& theEntry ) + { + CORBA::Object_var anObj = EntryToObject( theEntry ); + if ( !CORBA::is_nil( anObj ) ) + return TInterface::_narrow( anObj ); + return TInterface::_nil(); + } + SMESHGUI_EXPORT int GetNameOfSelectedIObjects( LightApp_SelectionMgr*, QString& ); diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts index 629c0d107..9605001fb 100644 --- a/src/SMESHGUI/SMESH_images.ts +++ b/src/SMESHGUI/SMESH_images.ts @@ -35,6 +35,10 @@ ICON_COPY_MESH copy_mesh.png + + ICON_COPY_MESH_WG + copy_mesh_with_geom.png + ICON_COMPUTE mesh_compute.png diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 75d649a72..bd20246ad 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -1938,6 +1938,14 @@ add the exported data to its contents? SMESH_HYPOTHESES Hypotheses + + SMESH_HYPOTHESIS + Hypothesis + + + SMESH_ALGORITHM + Algorithm + SMESH_HYP_1 Algorithm misses a hypothesis @@ -8070,6 +8078,25 @@ as they are of improper type: NEW_NAME New Mesh Name + + NEW_GEOM + New Geometry + + + REUSE_HYPOTHESES + Reuse Hypotheses + + + COPY_ELEMENTS + Copy Mesh Elements + + + SUBSHAPES_NOT_FOUND_MSG + +Some sub-shapes not found in the new geometry. They are listed +below along with dependent mesh objects that are marked with +with red in the Object Browser. + SMESHGUI_MeasureDlg diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 6c1329704..cef6517ce 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -1006,10 +1006,10 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) AddObject( mesh ); return; } - if( method == "CreateMeshesFromMED" || - method == "CreateMeshesFromSAUV"|| - method == "CreateMeshesFromCGNS" || - method == "CreateMeshesFromGMF" ) // command result is ( [mesh1,mesh2], status ) + if ( method == "CreateMeshesFromMED" || + method == "CreateMeshesFromSAUV"|| + method == "CreateMeshesFromCGNS" || + method == "CreateMeshesFromGMF" ) // command result is ( [mesh1,mesh2], status ) { std::list< _pyID > meshIDs = theCommand->GetStudyEntries( theCommand->GetResultValue() ); std::list< _pyID >::iterator meshID = meshIDs.begin(); @@ -1027,6 +1027,12 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) theCommand->SetArg( 1, file ); } } + if ( method == "CopyMeshWithGeom" ) + { + std::list< _pyID > entries = theCommand->GetStudyEntries( theCommand->GetResultValue() ); + Handle(_pyMesh) mesh = new _pyMesh( theCommand, entries.front() ); + AddObject( mesh ); + } // CreateHypothesis() if ( method == "CreateHypothesis" ) diff --git a/src/SMESH_I/SMESH_Algo_i.cxx b/src/SMESH_I/SMESH_Algo_i.cxx index c878fe37b..1b66bb29f 100644 --- a/src/SMESH_I/SMESH_Algo_i.cxx +++ b/src/SMESH_I/SMESH_Algo_i.cxx @@ -81,3 +81,27 @@ SMESH::ListOfHypothesisName* SMESH_Algo_i::GetCompatibleHypothesis() } return listOfHypothesis._retn(); } + +//================================================================================ +/*! + * Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool SMESH_Algo_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + return false; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool SMESH_Algo_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + return true; +} diff --git a/src/SMESH_I/SMESH_Algo_i.hxx b/src/SMESH_I/SMESH_Algo_i.hxx index 0d75eb5c2..9d4f6bf56 100644 --- a/src/SMESH_I/SMESH_Algo_i.hxx +++ b/src/SMESH_I/SMESH_Algo_i.hxx @@ -53,6 +53,15 @@ public: // Gets list of compatible hypotheses SMESH::ListOfHypothesisName* GetCompatibleHypothesis(); + + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); }; #endif diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 75c9d2184..cd9c86098 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -103,6 +103,9 @@ #include "SMESH_PreMeshInfo.hxx" #include "SMESH_PythonDump.hxx" #include "SMESH_ControlsDef.hxx" + +// to pass CORBA exception through SMESH_TRY +#define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; } #include "SMESH_TryCatch.hxx" // to include after OCC headers! #include CORBA_SERVER_HEADER(SMESH_Group) @@ -110,6 +113,7 @@ #include CORBA_SERVER_HEADER(SMESH_MeshEditor) +#include #include #include @@ -138,6 +142,7 @@ #include #include #include +#include using namespace std; using SMESH::TPythonDump; @@ -440,17 +445,17 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp // load plugin library if(MYDEBUG) MESSAGE("Loading server meshers plugin library ..."); #ifdef WIN32 - #ifdef UNICODE - const wchar_t* path = Kernel_Utils::decode_s(aPlatformLibName); - #else - const char* path = aPlatformLibName.c_str(); - #endif +#ifdef UNICODE + const wchar_t* path = Kernel_Utils::decode_s(aPlatformLibName); +#else + const char* path = aPlatformLibName.c_str(); +#endif #else - const char* path = aPlatformLibName.c_str(); + const char* path = aPlatformLibName.c_str(); #endif LibHandle libHandle = LoadLib( path ); #if defined(WIN32) && defined(UNICODE) - delete path; + delete path; #endif if (!libHandle) { @@ -1938,7 +1943,7 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh, try { // get mesh servant - SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); + SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh ); ASSERT( meshServant ); if ( meshServant ) { meshServant->Load(); @@ -1960,6 +1965,7 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh, meshServant->CreateGroupServants(); // algos can create groups (issue 0020918) myLocMesh.GetMeshDS()->Modified(); UpdateIcons( theMesh ); + HighLightInvalid( theMesh, /*isInvalid=*/!ok ); return ok; } } @@ -2724,10 +2730,12 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, const char* meshName, CORBA::Boolean toCopyGroups, CORBA::Boolean toKeepIDs) + throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); TPythonDump* pyDump = new TPythonDump; // prevent dump from CreateMesh() + std::unique_ptr pyDumpDeleter( pyDump ); // 1. Get source mesh @@ -2930,7 +2938,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, << toCopyGroups << ", " << toKeepIDs << ")"; - delete pyDump; pyDump = 0; // allow dump in GetGroups() + pyDumpDeleter.reset(); // allow dump in GetGroups() if ( nbNewGroups > 0 ) // dump created groups SMESH::ListOfGroups_var groups = newMesh->GetGroups(); @@ -2938,6 +2946,868 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, return newMesh._retn(); } + +namespace // utils for CopyMeshWithGeom() +{ + typedef std::map< std::string, std::string > TStr2StrMap; + typedef std::map< std::string, std::set< std::string > > TStr2StrSetMap; + + //================================================================================ + /*! + * \brief Return a new sub-shape corresponding to an old one + */ + //================================================================================ + + struct ShapeMapper + { + SMESH_Mesh_i* mySrcMesh_i; + SMESH_Mesh_i* myNewMesh_i; + SMESH_Gen_i* myGen_i; + bool myToPublish; + bool myIsSameGeom; + + TStr2StrMap myOld2NewEntryMap; // map of study entries + + bool myGIPMapDone; + GEOM::ListOfListOfLong_var myGIPMap; // filled by GetInPlaceMap() + + // not directly relating to shape search + TStr2StrSetMap myInvalidMap; // blame shape -> invalid objects + + //================================================================================ + /*! + * \brief Constructor + */ + ShapeMapper( SMESH_Mesh_i* srcMesh_i, + SMESH_Mesh_i* newMesh_i, + SMESH_Gen_i* smeshGen_i ) + : mySrcMesh_i( srcMesh_i ), + myNewMesh_i( newMesh_i ), + myGen_i ( smeshGen_i ), + myToPublish( smeshGen_i->IsEnablePublish() ), + myGIPMapDone( false ) + { + // retrieve from the study shape mapping made thanks to + // "Set presentation parameters and sub-shapes from arguments" option + + GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh(); + GEOM::GEOM_Object_var mainShapeOld = mySrcMesh_i->GetShapeToMesh(); + SALOMEDS::SObject_wrap oldSO = myGen_i->ObjectToSObject( mainShapeOld ); + SALOMEDS::SObject_wrap newSO = myGen_i->ObjectToSObject( mainShapeNew ); + if ( newSO->_is_nil() ) + { + myToPublish = false; + return; + } + if (( myIsSameGeom = mainShapeNew->_is_equivalent( mainShapeOld ))) + return; + CORBA::String_var oldEntry = oldSO->GetID(); + CORBA::String_var newEntry = newSO->GetID(); + myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ), + std::string( newEntry.in() ))); + + SALOMEDS::Study_var study = myGen_i->getStudyServant(); + GEOM::GEOM_Gen_var geomGen = myGen_i->GetGeomEngine(); + GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations(); + GEOM::ListOfGO_var subShapes = op->GetExistingSubObjects( mainShapeNew, + /*groupsOnly=*/false ); + for ( CORBA::ULong i = 0; i < subShapes->length(); ++i ) + { + newSO = myGen_i->ObjectToSObject( subShapes[ i ]); + SALOMEDS::ChildIterator_wrap anIter = study->NewChildIterator( newSO ); + for ( ; anIter->More(); anIter->Next() ) + { + SALOMEDS::SObject_wrap so = anIter->Value(); + if ( so->ReferencedObject( oldSO.inout() )) + { + oldEntry = oldSO->GetID(); + newEntry = newSO->GetID(); + myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ), + std::string( newEntry.in() ))); + } + } + } + } + + //================================================================================ + /*! + * \brief Find a new sub-shape corresponding to an old one + */ + GEOM::GEOM_Object_ptr FindNew( GEOM::GEOM_Object_ptr oldShape ) + { + if ( myIsSameGeom ) + return GEOM::GEOM_Object::_duplicate( oldShape ); + + GEOM::GEOM_Object_var newShape; + + if ( CORBA::is_nil( oldShape )) + return newShape._retn(); + + if ( !isChildOfOld( oldShape )) + return GEOM::GEOM_Object::_duplicate( oldShape ); // shape independent of the old shape + + GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh(); + GEOM::GEOM_Gen_var geomGen = myGen_i->GetGeomEngine(); + + // try to find by entry + if ( myToPublish ) + { + CORBA::String_var oldEntry = oldShape->GetStudyEntry(); + TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry.in() ); + if ( o2nID != myOld2NewEntryMap.end() ) + { + newShape = getShapeByEntry( o2nID->second ); + } + } + + if ( newShape->_is_nil() ) + { + // try to construct a new sub-shape using myGIPMap + buildGIPMap(); + std::vector< int > newIndices; + GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices(); + for ( CORBA::ULong i = 0; i < oldIndices->length(); ++i ) + { + findNewIDs( oldIndices[i], newIndices ); + } + if ( !newIndices.empty() ) + { + try + { + if ( newIndices.size() > 1 || oldShape->GetType() == GEOM_GROUP ) + { + int groupType = getShapeType( myNewMesh_i, newIndices[0] ); + + GEOM::GEOM_IGroupOperations_wrap grOp = geomGen->GetIGroupOperations(); + newShape = grOp->CreateGroup( mainShapeNew, groupType ); + + GEOM::ListOfLong_var newIndicesList = new GEOM::ListOfLong(); + newIndicesList->length( newIndices.size() ); + for ( size_t i = 0; i < newIndices.size(); ++i ) + newIndicesList[ i ] = newIndices[ i ]; + grOp->UnionIDs( newShape, newIndicesList ); + } + else + { + GEOM::GEOM_IShapesOperations_wrap shOp = geomGen->GetIShapesOperations(); + newShape = shOp->GetSubShape( mainShapeNew, newIndices[0] ); + } + } + catch (...) + { + } + } + } + + if ( !newShape->_is_nil() && myToPublish ) + { + CORBA::String_var oldEntry, newEntry = newShape->GetStudyEntry(); + if ( !newEntry.in() || !newEntry.in()[0] ) + { + CORBA::String_var name = oldShape->GetName(); + SALOMEDS::SObject_wrap so = geomGen->AddInStudy( newShape, name, mainShapeNew ); + newEntry = newShape->GetStudyEntry(); + oldEntry = oldShape->GetStudyEntry(); + myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ), + std::string( newEntry.in() ))); + } + } + + return newShape._retn(); + } + + //================================================================================ + /*! + * \brief Return a study entry of a new shape by study entry of the old one + */ + std::string FindNew( const std::string & oldEntry ) + { + if ( myIsSameGeom ) + return oldEntry; + + TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry ); + if ( o2nID != myOld2NewEntryMap.end() ) + return o2nID->second; + + GEOM::GEOM_Object_var oldShape = getShapeByEntry( oldEntry ); + if ( oldShape->_is_nil() || !isChildOfOld( oldShape )) + return oldEntry; + + GEOM::GEOM_Object_ptr newShape = FindNew( oldShape ); + if ( newShape->_is_nil() ) + return std::string(); + + CORBA::String_var newEntry = newShape->GetStudyEntry(); + return newEntry.in(); + } + + //================================================================================ + /*! + * \brief Return a sub-shape ID of a new shape by a sub-shape ID of the old one. + * Return zero if not found or there are more than one new ID + */ + int FindNew( int oldID ) + { + if ( myIsSameGeom ) + return oldID; + + buildGIPMap(); + + int newID = 0; + + if ( 0 < oldID && oldID < (int)myGIPMap->length() ) + { + if ( myGIPMap[ oldID ].length() == 1 ) + newID = myGIPMap[ oldID ][ 0 ]; + } + return newID; + } + + //================================================================================ + /*! + * \brief Return a sub-shape ID of a new shape by an old sub-mesh. + * Return zero if the old shape is not kept as is in the new shape. + */ + int FindNewNotChanged( SMESH_subMesh* oldSM ) + { + if ( myIsSameGeom ) + return oldSM->GetId(); + + int newID = FindNew( oldSM->GetId() ); + if ( !newID ) + return 0; + + SMESH_subMesh* newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( newID ); + if ( !newSM ) + return 0; + + // consider a sub-shape as not changed if all its sub-shapes are mapped into + // one new sub-shape of the same type. + + if ( oldSM->DependsOn().size() != + newSM->DependsOn().size() ) + return 0; + + SMESH_subMeshIteratorPtr srcSMIt = oldSM->getDependsOnIterator( /*includeSelf=*/true ); + while ( srcSMIt->more() ) + { + oldSM = srcSMIt->next(); + int newSubID = FindNew( oldSM->GetId() ); + if ( getShapeType( myNewMesh_i, newSubID ) != + getShapeType( mySrcMesh_i, oldSM->GetId() )) + return 0; + } + return newID; + } + + //================================================================================ + /*! + * \brief Return shape by study entry + */ + GEOM::GEOM_Object_ptr getShapeByEntry( const std::string & entry ) + { + GEOM::GEOM_Object_var shape; + SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry.c_str() ); + if ( !so->_is_nil() ) + { + CORBA::Object_var obj = so->GetObject(); + shape = GEOM::GEOM_Object::_narrow( obj ); + } + return shape._retn(); + } + + //================================================================================ + /*! + * \brief Fill myGIPMap by calling GetInPlaceMap() + */ + void buildGIPMap() + { + if ( !myGIPMapDone ) + { + myGIPMapDone = true; + + GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh(); + GEOM::GEOM_Object_var mainShapeOld = mySrcMesh_i->GetShapeToMesh(); + GEOM::GEOM_Gen_var geomGen = myGen_i->GetGeomEngine(); + GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations(); + try + { + myGIPMap = op->GetInPlaceMap( mainShapeNew, mainShapeOld ); + } + catch( ... ) + { + myGIPMap = new GEOM::ListOfListOfLong(); + } + } + } + + //================================================================================ + /*! + * \brief Find a new sub-shape indices by an old one in myGIPMap. Return + * number of found IDs + */ + int findNewIDs( int oldID, std::vector< int >& newIDs ) + { + size_t prevNbIDs = newIDs.size(); + + if ( 0 < oldID && oldID < (int) myGIPMap->length() ) + { + for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length(); ++i ) + newIDs.push_back( myGIPMap[ oldID ][ i ]); + } + return newIDs.size() - prevNbIDs; + } + + //================================================================================ + /*! + * \brief Check if an object relates to the old shape + */ + bool isChildOfOld( GEOM::GEOM_Object_ptr oldShape ) + { + if ( CORBA::is_nil( oldShape )) + return false; + GEOM::GEOM_Object_var mainShapeOld1 = mySrcMesh_i->GetShapeToMesh(); + GEOM::GEOM_Object_var mainShapeOld2 = oldShape->GetMainShape(); + return ( mainShapeOld1->_is_equivalent( mainShapeOld2 ) || + mainShapeOld1->_is_equivalent( oldShape )); + } + + //================================================================================ + /*! + * \brief Return shape type by shape ID + */ + TopAbs_ShapeEnum getShapeType( SMESH_Mesh_i* mesh_i, int shapeID ) + { + SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS(); + const TopoDS_Shape& shape = meshDS->IndexToShape( shapeID ); + return shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType(); + } + + //================================================================================ + /*! + * \brief Store a source sub-shape for which a counterpart not found and + * a smesh object invalid due to that + */ + void AddInvalid( GEOM::GEOM_Object_var srcShape, + SALOMEDS::SObject_wrap smeshSO ) + { + CORBA::String_var geomEntry = srcShape->GetStudyEntry(); + if ( geomEntry.in()[0] && !smeshSO->_is_nil() ) + { + CORBA::String_var smeshEntry = smeshSO->GetID(); + myInvalidMap[ geomEntry.in() ].insert( smeshEntry.in() ); + } + } + + //================================================================================ + /*! + * \brief Store a source sub-shape for which a counterpart not found and + * a smesh object invalid due to that + */ + void AddInvalid( std::string geomEntry, + SALOMEDS::SObject_wrap smeshSO ) + { + if ( !geomEntry.empty() ) + { + CORBA::String_var smeshEntry = smeshSO->GetID(); + myInvalidMap[ geomEntry ].insert( smeshEntry.in() ); + } + } + + //================================================================================ + /*! + * \brief Store a source sub-shape for which a counterpart not found and + * a smesh object invalid due to that + */ + void AddInvalid( int oldGeomID, + SALOMEDS::SObject_wrap smeshSO ) + { + int shapeType = getShapeType( mySrcMesh_i, oldGeomID ); + if ( shapeType < 0 || shapeType > TopAbs_SHAPE ) + return; + + const char* typeName[] = { "COMPOUND","COMPSOLID","SOLID","SHELL", + "FACE","WIRE","EDGE","VERTEX","SHAPE" }; + + SMESH_Comment geomName( typeName[ shapeType ]); + geomName << " #" << oldGeomID; + + CORBA::String_var smeshEntry = smeshSO->GetID(); + myInvalidMap[ geomName ].insert( smeshEntry.in() ); + } + + //================================================================================ + /*! + * \brief Return entries of a source sub-shape for which a counterpart not found and + * of smesh objects invalid due to that + */ + void GetInvalid( SMESH::string_array_out & theInvalidEntries, + std::vector< SALOMEDS::SObject_wrap > & theInvalidMeshSObjects) + { + int nbSO = 0; + TStr2StrSetMap::iterator entry2entrySet = myInvalidMap.begin(); + for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet ) + { + nbSO += 1 + entry2entrySet->second.size(); + } + int iSO = theInvalidMeshSObjects.size(), iEntry = 0; + theInvalidEntries->length ( nbSO ); + theInvalidMeshSObjects.resize( theInvalidMeshSObjects.size() + nbSO - myInvalidMap.size() ); + + entry2entrySet = myInvalidMap.begin(); + for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet ) + { + theInvalidEntries[ iEntry++ ] = entry2entrySet->first.c_str(); + + std::set< std::string > & entrySet = entry2entrySet->second; + std::set< std::string >::iterator entry = entrySet.begin(); + for ( ; entry != entrySet.end(); ++entry ) + { + theInvalidEntries[ iEntry++ ] = entry->c_str(); + + SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry->c_str() ); + if ( !so->_is_nil() ) + theInvalidMeshSObjects[ iSO++ ] = so; + } + } + } + + }; // struct ShapeMapper + + //================================================================================ + /*! + * \brief Append an item to a CORBA sequence + */ + template < class CORBA_seq, class ITEM > + void append( CORBA_seq& seq, ITEM item ) + { + if ( !CORBA::is_nil( item )) + { + seq->length( 1 + seq->length() ); + seq[ seq->length() - 1 ] = item; + } + } +} + +//================================================================================ +/*! + * \brief Create a mesh by copying definitions of another mesh to a given geometry + * \param [in] sourceMesh - a mesh to copy + * \param [in] newGeometry - a new geometry + * \param [in] toCopyGroups - to create groups in the new mesh + * \param [in] toReuseHypotheses - if True, existing hypothesis will be used by the new mesh, + * otherwise new hypotheses with the same parameters will be created for the new mesh. + * \param [in] toCopyElements - to copy mesh elements of same sub-shapes of the two geometries + * \param [out] newMesh - return a new mesh + * \param [out] newGroups - return new groups + * \param [out] newSubmeshes - return new sub-meshes + * \param [out] newHypotheses - return new algorithms and hypotheses + * \param [out] invalidEntries - return study entries of objects whose + * counterparts are not found in the newGeometry, followed by entries + * of mesh sub-objects that are invalid because they depend on a not found + * preceeding sub-shape + * \return CORBA::Boolean - is a success + */ +//================================================================================ + +CORBA::Boolean SMESH_Gen_i::CopyMeshWithGeom( SMESH::SMESH_Mesh_ptr theSourceMesh, + GEOM::GEOM_Object_ptr theNewGeometry, + const char* theMeshName, + CORBA::Boolean theToCopyGroups, + CORBA::Boolean theToReuseHypotheses, + CORBA::Boolean theToCopyElements, + SMESH::SMESH_Mesh_out theNewMesh, + SMESH::ListOfGroups_out theNewGroups, + SMESH::submesh_array_out theNewSubmeshes, + SMESH::ListOfHypothesis_out theNewHypotheses, + SMESH::string_array_out theInvalidEntries) +throw ( SALOME::SALOME_Exception ) +{ + if ( CORBA::is_nil( theSourceMesh ) || + CORBA::is_nil( theNewGeometry )) + THROW_SALOME_CORBA_EXCEPTION( "NULL arguments", SALOME::BAD_PARAM ); + + if ( !theSourceMesh->HasShapeToMesh() ) + THROW_SALOME_CORBA_EXCEPTION( "Source mesh not on geometry", SALOME::BAD_PARAM ); + + bool ok = true; + SMESH_TRY; + + TPythonDump pyDump; // prevent dump from CreateMesh() + + theNewMesh = CreateMesh( theNewGeometry ); + theNewGroups = new SMESH::ListOfGroups(); + theNewSubmeshes = new SMESH::submesh_array(); + theNewHypotheses = new SMESH::ListOfHypothesis(); + theInvalidEntries = new SMESH::string_array(); + + std::vector< SALOMEDS::SObject_wrap > invalidSObjects; + + GEOM::GEOM_Object_var srcGeom = theSourceMesh->GetShapeToMesh(); + GEOM::GEOM_Object_var geom, newGeom; + SALOMEDS::SObject_wrap so; + + SMESH_Mesh_i* srcMesh_i = SMESH::DownCast( theSourceMesh ); + SMESH_Mesh_i* newMesh_i = SMESH::DownCast( theNewMesh ); + + ShapeMapper shapeMapper( srcMesh_i, newMesh_i, this ); + + // treat hypotheses of mesh and sub-meshes + SMESH::submesh_array_var smList = theSourceMesh->GetSubMeshes(); + for ( CORBA::ULong iSM = 0; iSM <= smList->length(); ++iSM ) + { + bool isSubMesh = ( iSM < smList->length() ); + if ( isSubMesh ) + { + // create a new sub-mesh + SMESH::SMESH_subMesh_var newSM; + geom = smList[iSM]->GetSubShape(); + so = ObjectToSObject( smList[iSM] ); + CORBA::String_var name; + if ( !so->_is_nil() ) + name = so->GetName(); + newGeom = shapeMapper.FindNew( geom ); + if ( newGeom->_is_nil() ) + { + newSM = createInvalidSubMesh( theNewMesh, geom, name.in() ); + shapeMapper.AddInvalid( geom, ObjectToSObject( newSM )); + ok = false; + } + else + { + newSM = theNewMesh->GetSubMesh( newGeom, name.in() ); + } + append( theNewSubmeshes, newSM ); + + if ( newGeom->_is_nil() ) + continue; // don't assign hypotheses + } + else + { + newGeom = GEOM::GEOM_Object::_duplicate( theNewGeometry ); + geom = srcGeom; + so = ObjectToSObject( theNewMesh ); + SetName( so, theMeshName, "Mesh" ); + } + + // assign hypotheses + SMESH::ListOfHypothesis_var hypList = theSourceMesh->GetHypothesisList( geom ); + for ( CORBA::ULong iHyp = 0; iHyp < hypList->length(); ++iHyp ) + { + SMESH::SMESH_Hypothesis_var hyp = hypList[ iHyp ]; + SMESH_Hypothesis_i* hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp ); + + // get geometry hyp depends on + std::vector< std::string > entryArray; + std::vector< int > subIDArray; + bool dependsOnGeom = hyp_i->getObjectsDependOn( entryArray, subIDArray ); + + if ( !theToReuseHypotheses || dependsOnGeom ) + { + // create a new hypothesis + CORBA::String_var type = hyp->GetName(); + CORBA::String_var lib = hyp->GetLibName(); + CORBA::String_var data = hyp_i->SaveTo(); + if ( data.in()[0] ) + { + hyp = CreateHypothesis( type, lib ); + hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp ); + hyp_i->LoadFrom( data.in() ); + append( theNewHypotheses, hyp ); + } + } + + // update geometry hyp depends on + if ( dependsOnGeom ) + { + for ( size_t iGeo = 0; iGeo < entryArray.size(); ++iGeo ) + { + if ( !entryArray[ iGeo ].empty() ) + { + std::string newEntry = shapeMapper.FindNew( entryArray[ iGeo ]); + if ( newEntry.empty() ) + { + ok = false; + shapeMapper.AddInvalid( entryArray[ iGeo ], ObjectToSObject( hyp )); + shapeMapper.AddInvalid( entryArray[ iGeo ], so ); // sub-mesh + } + entryArray[ iGeo ] = newEntry; + } + } + for ( size_t iGeo = 0; iGeo < subIDArray.size(); ++iGeo ) + { + if ( subIDArray[ iGeo ] > 0 ) + { + int newID = shapeMapper.FindNew( subIDArray[ iGeo ]); + if ( newID < 1 ) + { + ok = false; + shapeMapper.AddInvalid( subIDArray[ iGeo ], ObjectToSObject( hyp )); + shapeMapper.AddInvalid( subIDArray[ iGeo ], so ); // sub-mesh + } + subIDArray[ iGeo ] = newID; + } + } + if ( !hyp_i->setObjectsDependOn( entryArray, subIDArray )) + ok = false; + } + + CORBA::String_var errorText; + theNewMesh->AddHypothesis( newGeom, hyp, errorText.out() ); + if ( errorText.in()[0] ) + ok = false; + + } // loop on hypotheses + } // loop on sub-meshes and mesh + + + // copy mesh elements, keeping IDs + if ( theToCopyElements && theSourceMesh->NbNodes() > 0 ) + { + SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); + ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() ); + ::SMESH_MeshEditor::ElemFeatures elemData; + + SMESH_subMesh* srcMainSM = srcMesh_i->GetImpl().GetSubMeshContaining( 1 ); + SMESH_subMeshIteratorPtr srcSMIt = srcMainSM->getDependsOnIterator( /*includeSelf=*/true, + /*vertexLast=*/false); + while ( srcSMIt->more() ) + { + SMESH_subMesh* srcSM = srcSMIt->next(); + if ( srcSM->IsEmpty() ) + continue; // not yet computed + int newID = shapeMapper.FindNewNotChanged( srcSM ); + if ( newID < 1 ) + continue; + + SMESHDS_SubMesh* srcSMDS = srcSM->GetSubMeshDS(); + SMDS_NodeIteratorPtr nIt = srcSMDS->GetNodes(); + while ( nIt->more() ) + { + SMESH_NodeXYZ node( nIt->next() ); + const SMDS_MeshNode* newNode = newMeshDS->AddNodeWithID( node.X(), node.Y(), node.Z(), + node->GetID() ); + const SMDS_PositionPtr pos = node->GetPosition(); + const double* uv = pos->GetParameters(); + switch ( pos->GetTypeOfPosition() ) + { + case SMDS_TOP_3DSPACE: newMeshDS->SetNodeInVolume( newNode, newID ); break; + case SMDS_TOP_FACE: newMeshDS->SetNodeOnFace ( newNode, newID, uv[0], uv[1] ); break; + case SMDS_TOP_EDGE: newMeshDS->SetNodeOnEdge ( newNode, newID, uv[0] ); break; + case SMDS_TOP_VERTEX: newMeshDS->SetNodeOnVertex( newNode, newID ); break; + default: ; + } + } + SMDS_ElemIteratorPtr eIt = srcSMDS->GetElements(); + while( eIt->more() ) + { + const SMDS_MeshElement* e = eIt->next(); + elemData.Init( e, /*basicOnly=*/false ); + elemData.SetID( e->GetID() ); + elemData.myNodes.resize( e->NbNodes() ); + SMDS_NodeIteratorPtr nnIt = e->nodeIterator(); + size_t iN; + for ( iN = 0; nnIt->more(); ++iN ) + { + const SMDS_MeshNode* srcNode = nnIt->next(); + elemData.myNodes[ iN ] = newMeshDS->FindNode( srcNode->GetID() ); + if ( !elemData.myNodes[ iN ]) + break; + } + if ( iN == elemData.myNodes.size() ) + if ( const SMDS_MeshElement * newElem = editor.AddElement( elemData.myNodes, elemData )) + newMeshDS->SetMeshElementOnShape( newElem, newID ); + } + if ( SMESH_subMesh* newSM = newMesh_i->GetImpl().GetSubMeshContaining( newID )) + newSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + } + } + + + // treat groups + + TStr2StrMap old2newGroupMap; + + SALOME::GenericObj_wrap< SMESH::FilterManager > filterMgr = CreateFilterManager(); + + SMESH::ListOfGroups_var groups = theSourceMesh->GetGroups(); + CORBA::ULong nbGroups = groups->length(), nbAddedGroups = 0; + for ( CORBA::ULong i = 0; i < nbGroups + nbAddedGroups; ++i ) + { + SMESH::SMESH_Group_var stdlGroup = SMESH::SMESH_Group::_narrow ( groups[ i ]); + SMESH::SMESH_GroupOnGeom_var geomGroup = SMESH::SMESH_GroupOnGeom::_narrow ( groups[ i ]); + SMESH::SMESH_GroupOnFilter_var fltrGroup = SMESH::SMESH_GroupOnFilter::_narrow( groups[ i ]); + + CORBA::String_var name = groups[ i ]->GetName(); + SMESH::ElementType elemType = groups[ i ]->GetType(); + + SMESH::SMESH_GroupBase_var newGroup; + + if ( !stdlGroup->_is_nil() ) + { + if ( theToCopyElements ) + { + SMESH::long_array_var elemIDs = stdlGroup->GetIDs(); + stdlGroup = theNewMesh->CreateGroup( elemType, name ); + stdlGroup->Add( elemIDs ); + newGroup = SMESH::SMESH_GroupBase::_narrow( stdlGroup ); + } + } + else if ( !geomGroup->_is_nil() ) + { + GEOM::GEOM_Object_var geom = geomGroup->GetShape(); + GEOM::GEOM_Object_var newGeom = shapeMapper.FindNew( geom ); + if ( newGeom->_is_nil() ) + { + newGroup = theNewMesh->CreateGroup( elemType, name ); // just to notify the user + shapeMapper.AddInvalid( geom, ObjectToSObject( newGroup )); + ok = false; + } + else + { + newGroup = theNewMesh->CreateGroupFromGEOM( elemType, name, newGeom ); + } + } + else if ( !fltrGroup->_is_nil() ) + { + // replace geometry in a filter + SMESH::Filter_var filter = fltrGroup->GetFilter(); + SMESH::Filter::Criteria_var criteria; + filter->GetCriteria( criteria.out() ); + + bool isMissingGroup = false; + std::vector< std::string > badEntries; + + for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr ) + { + const char* thresholdID = criteria[ iCr ].ThresholdID.in(); + switch ( criteria[ iCr ].Type ) + { + case SMESH::FT_BelongToMeshGroup: + { + SALOME::GenericObj_wrap< SMESH::BelongToMeshGroup > btgg = filterMgr->CreateBelongToMeshGroup(); + btgg->SetGroupID( thresholdID ); + SMESH::SMESH_GroupBase_ptr refGroup = btgg->GetGroup(); + SALOMEDS::SObject_wrap refGroupSO = ObjectToSObject( refGroup ); + if ( refGroupSO->_is_nil() ) + break; + CORBA::String_var refID = refGroupSO->GetID(); + TStr2StrMap::iterator o2nID = old2newGroupMap.find( refID.in() ); + if ( o2nID == old2newGroupMap.end() ) + { + isMissingGroup = true; // corresponding new group not yet created + break; + } + criteria[ iCr ].ThresholdID = o2nID->second.c_str(); + + if ( o2nID->second.empty() ) // new referred group is invalid + badEntries.push_back( refID.in() ); + break; + } + case SMESH::FT_BelongToGeom: + case SMESH::FT_BelongToPlane: + case SMESH::FT_BelongToCylinder: + case SMESH::FT_BelongToGenSurface: + case SMESH::FT_LyingOnGeom: + { + std::string newID = shapeMapper.FindNew( thresholdID ); + criteria[ iCr ].ThresholdID = newID.c_str(); + if ( newID.empty() ) + badEntries.push_back( thresholdID ); + break; + } + case SMESH::FT_ConnectedElements: + { + if ( thresholdID && thresholdID[0] ) + { + std::string newID = shapeMapper.FindNew( thresholdID ); + criteria[ iCr ].ThresholdID = newID.c_str(); + if ( newID.empty() ) + badEntries.push_back( thresholdID ); + } + break; + } + default:; + } + } // loop on criteria + + if ( isMissingGroup && i < nbGroups ) + { + // to treat the group again + append( groups, SMESH::SMESH_GroupBase::_duplicate( groups[ i ])); + ++nbAddedGroups; + continue; + } + SMESH::Filter_var newFilter = filterMgr->CreateFilter(); + newFilter->SetCriteria( criteria ); + + newGroup = theNewMesh->CreateGroupFromFilter( elemType, name, newFilter ); + newFilter->UnRegister(); + + SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup ); + for ( size_t iEnt = 0; iEnt < badEntries.size(); ++iEnt ) + shapeMapper.AddInvalid( badEntries[ iEnt ], newSO ); + + if ( isMissingGroup ) // all groups treated but a referred groups still not found + { + invalidSObjects.push_back( ObjectToSObject( newGroup )); + ok = false; + } + if ( !badEntries.empty() ) + ok = false; + + } // treat a group on filter + + append( theNewGroups, newGroup ); + + // fill old2newGroupMap + SALOMEDS::SObject_wrap srcSO = ObjectToSObject( groups[i] ); + SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup ); + if ( !srcSO->_is_nil() ) + { + CORBA::String_var srcID, newID; + srcID = srcSO->GetID(); + if ( !newSO->_is_nil() ) + newID = newSO->GetID(); + old2newGroupMap.insert( std::make_pair( std::string( srcID.in() ), + std::string( newID.in() ))); + } + + if ( newGroup->_is_nil() ) + ok = false; + + } // loop on groups + + // set mesh name + SALOMEDS::SObject_wrap soNew = ObjectToSObject( theNewMesh ); + SALOMEDS::SObject_wrap soOld = ObjectToSObject( theSourceMesh ); + CORBA::String_var oldName = soOld->GetName(); + SetName( soNew, oldName.in(), "Mesh" ); + + // mark invalid objects + shapeMapper.GetInvalid( theInvalidEntries, invalidSObjects ); + + for ( size_t i = 0; i < invalidSObjects.size(); ++i ) + highLightInvalid( invalidSObjects[i].in(), true ); + + pyDump << "ok, " + << theNewMesh << ", " + << theNewGroups << ", " + << *theNewSubmeshes.ptr() << ", " + << *theNewHypotheses.ptr() << ", " + << "invalidEntries = " << this << ".CopyMeshWithGeom( " + << theSourceMesh << ", " + << theNewGeometry << ", " + << "'" << theMeshName << "', " + << theToCopyGroups << ", " + << theToReuseHypotheses << ", " + << theToCopyElements << " )"; + + SMESH_CATCH( SMESH::throwCorbaException ); + + return ok; +} + //================================================================================ /*! * \brief Get version of MED format being used. diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index 21f55355e..1209ec7af 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -246,9 +246,24 @@ public: SMESH::SMESH_Mesh_ptr CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, const char* meshName, CORBA::Boolean toCopyGroups, - CORBA::Boolean toKeepIDs); + CORBA::Boolean toKeepIDs) + throw ( SALOME::SALOME_Exception ); + + // Create a mesh by copying definitions of another mesh to a given geometry + CORBA::Boolean CopyMeshWithGeom( SMESH::SMESH_Mesh_ptr sourceMesh, + GEOM::GEOM_Object_ptr newGeometry, + const char* meshName, + CORBA::Boolean toCopyGroups, + CORBA::Boolean toReuseHypotheses, + CORBA::Boolean toCopyElements, + SMESH::SMESH_Mesh_out newMesh, + SMESH::ListOfGroups_out newGroups, + SMESH::submesh_array_out newSubmeshes, + SMESH::ListOfHypothesis_out newHypotheses, + SMESH::string_array_out invalidEntries) + throw ( SALOME::SALOME_Exception ); - // Compute mesh on a shape + // Compute mesh on a shape CORBA::Boolean Compute( SMESH::SMESH_Mesh_ptr theMesh, GEOM::GEOM_Object_ptr theShapeObject ) throw ( SALOME::SALOME_Exception ); @@ -504,6 +519,7 @@ public: GEOM::GEOM_Object_ptr theShapeObject, const char* theName = 0); void UpdateIcons(SMESH::SMESH_Mesh_ptr theMesh); + void HighLightInvalid(CORBA::Object_ptr theObject, bool isInvalid); bool AddHypothesisToShape(SMESH::SMESH_Mesh_ptr theMesh, GEOM::GEOM_Object_ptr theShapeObject, SMESH::SMESH_Hypothesis_ptr theHyp); @@ -608,6 +624,14 @@ private: SMESH::SMESH_Mesh_ptr createMesh() throw ( SALOME::SALOME_Exception ); + // Create a sub-mesh on a geometry that is not a sub-shape of the main shape + // for the case where a valid sub-shape not found by CopyMeshWithGeom() + SMESH::SMESH_subMesh_ptr createInvalidSubMesh( SMESH::SMESH_Mesh_ptr mesh, + GEOM::GEOM_Object_ptr strangerGeom, + const char* name ); + + void highLightInvalid( SALOMEDS::SObject_ptr theSObject, bool isInvalid ); + static void loadGeomData( SALOMEDS::SComponent_ptr theCompRoot ); SMESH::mesh_array* CreateMeshesFromMEDorSAUV( const char* theFileName, diff --git a/src/SMESH_I/SMESH_Gen_i_1.cxx b/src/SMESH_I/SMESH_Gen_i_1.cxx index 49e74979e..69a8f73b0 100644 --- a/src/SMESH_I/SMESH_Gen_i_1.cxx +++ b/src/SMESH_I/SMESH_Gen_i_1.cxx @@ -452,6 +452,9 @@ static void addReference (SALOMEDS::SObject_ptr theSObject, aStudyBuilder->Addreference( aReferenceSO, aToObjSO ); + // make the reference visible (invisible ref is created by createInvalidSubMesh()) + aStudyBuilder->RemoveAttribute( aReferenceSO, "AttributeDrawable" ); + // add reference to the use case tree // (to support tree representation customization and drag-n-drop) SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = aStudy->GetUseCaseBuilder(); @@ -689,6 +692,8 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishSubMesh (SMESH::SMESH_Mesh_ptr theM if ( theMesh->_is_nil() || theSubMesh->_is_nil() || theShapeObject->_is_nil() ) return SALOMEDS::SObject::_nil(); + std::string newName( theName ? theName : "" ); + SALOMEDS::SObject_wrap aSubMeshSO = ObjectToSObject( theSubMesh ); if ( aSubMeshSO->_is_nil() ) { @@ -740,15 +745,37 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishSubMesh (SMESH::SMESH_Mesh_ptr theM SetName( aRootSO, aRootName ); - // Add new submesh to corresponding sub-tree + // Add new sub-mesh to corresponding sub-tree + int tag = 0; // to use a new SObject + if ( theName && theName[0] == '0' ) + { + // theName can be an entry of an invalid sub-mesh which theSubMesh should replace + SALOMEDS::SObject_wrap aSObj = getStudyServant()->FindObjectID( theName ); + if ( aSObj ) + { + CORBA::String_var oldName = aSObj->GetName(); + newName = oldName.in(); + SALOMEDS::SObject_wrap aRootSO2 = aSObj->GetFather(); + if ( aRootSO->Tag() == aRootSO2->Tag() ) // same parent + tag = aSObj->Tag(); // to use the same SObject + else + { + CORBA::Object_var anObj = SObjectToObject( aSObj ); + SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( anObj ); + theMesh->RemoveSubMesh( sm ); + } + } + } SMESH::array_of_ElementType_var elemTypes = theSubMesh->GetTypes(); const int isEmpty = ( elemTypes->length() == 0 ); const char* pm[2] = { "ICON_SMESH_TREE_MESH", "ICON_SMESH_TREE_MESH_WARN" }; - aSubMeshSO = publish ( theSubMesh, aRootSO, 0, pm[isEmpty] ); + aSubMeshSO = publish ( theSubMesh, aRootSO, tag, pm[isEmpty] ); if ( aSubMeshSO->_is_nil() ) return aSubMeshSO._retn(); + + highLightInvalid( aSubMeshSO, false ); // now it is valid } - SetName( aSubMeshSO, theName, "SubMesh" ); + SetName( aSubMeshSO, newName.c_str(), "SubMesh" ); // Add reference to theShapeObject @@ -757,7 +784,8 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishSubMesh (SMESH::SMESH_Mesh_ptr theM // Publish hypothesis SMESH::ListOfHypothesis_var hypList = theMesh->GetHypothesisList( theShapeObject ); - for ( CORBA::ULong i = 0; i < hypList->length(); i++ ) { + for ( CORBA::ULong i = 0; i < hypList->length(); i++ ) + { SMESH::SMESH_Hypothesis_var aHyp = SMESH::SMESH_Hypothesis::_narrow( hypList[ i ]); SALOMEDS::SObject_wrap so = PublishHypothesis( aHyp ); AddHypothesisToShape( theMesh, theShapeObject, aHyp ); @@ -965,6 +993,42 @@ void SMESH_Gen_i::UpdateIcons( SMESH::SMESH_Mesh_ptr theMesh ) } } +//======================================================================= +//function : HighLightInvalid +//purpose : change font color of a object in the Object Browser +//======================================================================= + +void SMESH_Gen_i::HighLightInvalid( CORBA::Object_ptr theObject, bool isInvalid ) +{ + SALOMEDS::SObject_wrap so = ObjectToSObject(theObject); + highLightInvalid( so.in(), isInvalid ); +} + +//======================================================================= +//function : highLightInvalid +//purpose : change font color of a object in the Object Browser +//======================================================================= + +void SMESH_Gen_i::highLightInvalid( SALOMEDS::SObject_ptr theSObject, bool isInvalid ) +{ + if ( !theSObject->_is_nil() ) + { + SALOMEDS::StudyBuilder_var studyBuilder = getStudyServant()->NewBuilder(); + if ( isInvalid ) + { + SALOMEDS::Color red = { 178,34,34 }; // to differ from reference color + SALOMEDS::GenericAttribute_wrap attr = + studyBuilder->FindOrCreateAttribute( theSObject, "AttributeTextColor" ); + SALOMEDS::AttributeTextColor_wrap colorAttr = attr; + colorAttr->SetTextColor( red ); + } + else + { + studyBuilder->RemoveAttribute( theSObject, "AttributeTextColor" ); + } + } +} + //======================================================================= //function : GetMeshOrSubmeshByShape //purpose : @@ -1339,6 +1403,50 @@ char* SMESH_Gen_i::GetParameters(CORBA::Object_ptr theObject) return aResult._retn(); } +//================================================================================ +/*! + * \brief Create a sub-mesh on a geometry that is not a sub-shape of the main shape + * for the case where a valid sub-shape not found by CopyMeshWithGeom(). + * The invalid sub-mesh has GetId() < 0. + */ +//================================================================================ + +SMESH::SMESH_subMesh_ptr +SMESH_Gen_i::createInvalidSubMesh(SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theStrangerGeom, + const char* theName) +{ + SMESH::SMESH_subMesh_var subMesh; + + try + { + SMESH_Mesh_i* mesh_i = SMESH::DownCast( theMesh ); + subMesh = mesh_i->createSubMesh( theStrangerGeom ); + + if ( !subMesh->_is_nil() && CanPublishInStudy( subMesh )) + { + SALOMEDS::SObject_wrap so = PublishSubMesh( theMesh, subMesh, theStrangerGeom, theName ); + + // hide a reference to geometry + if ( !so->_is_nil() ) + { + SALOMEDS::SObject_wrap refSO; + if ( so->FindSubObject( GetRefOnShapeTag(), refSO.inout() )) + { + SALOMEDS::StudyBuilder_var studyBuilder = getStudyServant()->NewBuilder(); + SALOMEDS::GenericAttribute_wrap attr = + studyBuilder->FindOrCreateAttribute( refSO, "AttributeDrawable" ); + SALOMEDS::AttributeDrawable_wrap ga = attr; + ga->SetDrawable( false ); + } + } + } + } + catch (...) { + } + + return subMesh._retn(); +} // ============== diff --git a/src/SMESH_I/SMESH_Group_i.cxx b/src/SMESH_I/SMESH_Group_i.cxx index 354a1daf0..1c8257ddb 100644 --- a/src/SMESH_I/SMESH_Group_i.cxx +++ b/src/SMESH_I/SMESH_Group_i.cxx @@ -838,7 +838,13 @@ void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter) Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion } - TPythonDump()<< SMESH::SMESH_GroupOnFilter_var(_this()) <<".SetFilter( "<GetGen()->HighLightInvalid( me, false ); + + + TPythonDump()<< me <<".SetFilter( "<< theFilter <<" )"; } //================================================================================ diff --git a/src/SMESH_I/SMESH_Hypothesis_i.hxx b/src/SMESH_I/SMESH_Hypothesis_i.hxx index f713bfd2d..8523c787a 100644 --- a/src/SMESH_I/SMESH_Hypothesis_i.hxx +++ b/src/SMESH_I/SMESH_Hypothesis_i.hxx @@ -40,6 +40,7 @@ #include #include +#include class TCollection_AsciiString; @@ -97,7 +98,18 @@ public: // Persistence virtual char* SaveTo(); virtual void LoadFrom( const char* theStream ); - virtual void UpdateAsMeshesRestored(); // for hyps needing full data restored + virtual void UpdateAsMeshesRestored(); // for hyps needing full study data restored + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const = 0; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) = 0; protected: diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 8dc1b25b5..128dbed1c 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -2460,9 +2460,25 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theS if(MYDEBUG) MESSAGE( "createSubMesh" ); TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject); ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape); - const int subMeshId = mySubMesh->GetId(); + int subMeshId = 0; + + SMESH_subMesh_i * subMeshServant; + if ( mySubMesh ) + { + subMeshId = mySubMesh->GetId(); + subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId); + } + else // "invalid sub-mesh" + { + // The invalid sub-mesh is created for the case where a valid sub-shape not found + // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0. + if ( _mapSubMesh.empty() ) + subMeshId = -1; + else + subMeshId = _mapSubMesh.begin()->first - 1; + subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject); + } - SMESH_subMesh_i * subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId); SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this(); _mapSubMesh [subMeshId] = mySubMesh; @@ -2477,7 +2493,8 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theS else { nextId = 0; } // avoid "unused variable" warning // to track changes of GEOM groups - addGeomGroupData( theSubShapeObject, subMesh ); + if ( subMeshId > 0 ) + addGeomGroupData( theSubShapeObject, subMesh ); return subMesh._retn(); } @@ -2513,7 +2530,8 @@ bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh, if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617) { - if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end()) + if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end() && + _mapSubMesh[ subMeshId ]) { TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape(); if ( !S.IsNull() ) @@ -2735,7 +2753,7 @@ namespace SMESH_Mesh_i* _mesh; TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {} virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); } - virtual void HypothesisModified () { _mesh->onHypothesisModified(); } + virtual void HypothesisModified (int theHypID) { _mesh->onHypothesisModified( theHypID ); } virtual void Load () { _mesh->Load(); } }; } @@ -2746,13 +2764,30 @@ namespace */ //================================================================================ -void SMESH_Mesh_i::onHypothesisModified() +void SMESH_Mesh_i::onHypothesisModified(int theHypID) { if ( _preMeshInfo ) _preMeshInfo->ForgetOrLoad(); SMESH::SMESH_Mesh_var mesh = _this(); _gen_i->UpdateIcons( mesh ); + + // mark a hypothesis as valid after edition + SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent(); + SALOMEDS::SObject_wrap hypRoot; + if ( !smeshComp->_is_nil() && + smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() )) + { + SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot ); + for ( ; anIter->More(); anIter->Next() ) + { + SALOMEDS::SObject_wrap hypSO = anIter->Value(); + CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO ); + SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj ); + if ( !hyp->_is_nil() && hyp->GetId() == theHypID ) + _gen_i->HighLightInvalid( hyp, false ); + } + } } //============================================================================= diff --git a/src/SMESH_I/SMESH_Mesh_i.hxx b/src/SMESH_I/SMESH_Mesh_i.hxx index 867949a9d..7e612be13 100644 --- a/src/SMESH_I/SMESH_Mesh_i.hxx +++ b/src/SMESH_I/SMESH_Mesh_i.hxx @@ -439,7 +439,7 @@ public: const std::map& getGroups() { return _mapGroups; } // return existing group objects - void onHypothesisModified(); + void onHypothesisModified(int theHypID); // callback from _impl to forget not loaded mesh data (issue 0021208) void checkMeshLoaded(); diff --git a/src/SMESH_I/SMESH_PythonDump.cxx b/src/SMESH_I/SMESH_PythonDump.cxx index 7ffedf1d4..76a23315a 100644 --- a/src/SMESH_I/SMESH_PythonDump.cxx +++ b/src/SMESH_I/SMESH_PythonDump.cxx @@ -540,6 +540,16 @@ namespace SMESH DumpArray( theList, *this ); return *this; } + TPythonDump& TPythonDump::operator<<(const SMESH::submesh_array& theList) + { + DumpArray( theList, *this ); + return *this; + } + TPythonDump& TPythonDump::operator<<(const SMESH::ListOfHypothesis& theList) + { + DumpArray( theList, *this ); + return *this; + } TPythonDump& TPythonDump::operator<<(const SMESH::CoincidentFreeBorders& theCFB) { // dump CoincidentFreeBorders as a list of lists, each enclosed list diff --git a/src/SMESH_I/SMESH_PythonDump.hxx b/src/SMESH_I/SMESH_PythonDump.hxx index 793e4a4a1..37393b23f 100644 --- a/src/SMESH_I/SMESH_PythonDump.hxx +++ b/src/SMESH_I/SMESH_PythonDump.hxx @@ -227,6 +227,12 @@ namespace SMESH TPythonDump& operator<<(const SMESH::ListOfIDSources& theList); + TPythonDump& + operator<<(const SMESH::submesh_array& theList); + + TPythonDump& + operator<<(const SMESH::ListOfHypothesis& theList); + TPythonDump& operator<<(const SMESH::CoincidentFreeBorders& theCFB); diff --git a/src/SMESH_I/SMESH_subMesh_i.cxx b/src/SMESH_I/SMESH_subMesh_i.cxx index 4737a7b0e..92d6034e4 100644 --- a/src/SMESH_I/SMESH_subMesh_i.cxx +++ b/src/SMESH_I/SMESH_subMesh_i.cxx @@ -96,6 +96,8 @@ typedef list TListOfSubMeshes; bool getSubMeshes(::SMESH_subMesh* theSubMesh, TListOfSubMeshes& theSubMeshList) { + if ( !theSubMesh ) + return false; // "invalid sub-mesh" created by SMESH_Gen_i::CopyMeshWithGeom() size_t size = theSubMeshList.size(); // check all child sub-meshes of one complexity, @@ -582,3 +584,30 @@ SALOMEDS::TMPFile* SMESH_subMesh_i::GetVtkUgStream() SALOMEDS::TMPFile_var SeqFile; return SeqFile._retn(); } + +//======================================================================= +//function : SMESH_Invalid_subMesh_i +//purpose : constructor of "invalid sub-mesh" created by SMESH_Gen_i::CopyMeshWithGeom() +//======================================================================= + +SMESH_Invalid_subMesh_i::SMESH_Invalid_subMesh_i( PortableServer::POA_ptr thePOA, + SMESH_Gen_i* gen_i, + SMESH_Mesh_i* mesh_i, + int localId, + GEOM::GEOM_Object_ptr shape ) + : SALOME::GenericObj_i( thePOA ), + SMESH_subMesh_i( thePOA, gen_i, mesh_i, localId ) +{ + _geom = GEOM::GEOM_Object::_duplicate( shape ); +} + +//======================================================================= +//function : GetSubShape +//purpose : return geomtry which is not a sub-shape of the main shape +//======================================================================= + +GEOM::GEOM_Object_ptr SMESH_Invalid_subMesh_i::GetSubShape() + throw (SALOME::SALOME_Exception) +{ + return GEOM::GEOM_Object::_duplicate( _geom ); +} diff --git a/src/SMESH_I/SMESH_subMesh_i.hxx b/src/SMESH_I/SMESH_subMesh_i.hxx index b5a814080..cbdb796e0 100644 --- a/src/SMESH_I/SMESH_subMesh_i.hxx +++ b/src/SMESH_I/SMESH_subMesh_i.hxx @@ -130,4 +130,26 @@ protected: friend class SMESH_PreMeshInfo; }; + +class SMESH_I_EXPORT SMESH_Invalid_subMesh_i: + public virtual POA_SMESH::SMESH_subMesh, + public virtual SALOME::GenericObj_i, + public virtual SMESH_subMesh_i +{ + public: + SMESH_Invalid_subMesh_i( PortableServer::POA_ptr thePOA, + SMESH_Gen_i* gen_i, + SMESH_Mesh_i* mesh_i, + int localId, + GEOM::GEOM_Object_ptr shape); + + virtual GEOM::GEOM_Object_ptr GetSubShape() + throw (SALOME::SALOME_Exception); + + protected: + + GEOM::GEOM_Object_var _geom; + +}; + #endif diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index d0bb913c1..a93d9f732 100755 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -782,11 +782,46 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): an instance of class :class:`Mesh` """ - if (isinstance( meshPart, Mesh )): + if isinstance( meshPart, Mesh ): meshPart = meshPart.GetMesh() mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs ) return Mesh(self, self.geompyD, mesh) + def CopyMeshWithGeom( self, sourceMesh, newGeom, meshName="", toCopyGroups=True, + toReuseHypotheses=True, toCopyElements=True): + """ + Create a mesh by copying a mesh definition (hypotheses and groups) to a new geometry. + It is supposed that the new geometry is a modified geometry of *sourceMesh*. + To facilitate and speed up the operation, consider using + "Set presentation parameters and sub-shapes from arguments" option in + a dialog of geometrical operation used to create the new geometry. + + Parameters: + sourceMesh: the mesh to copy definition of. + newGeom: the new geomtry. + meshName: an optional name of the new mesh. If omitted, the mesh name is kept. + toCopyGroups: to create groups in the new mesh. + toReuseHypotheses: to reuse hypotheses of the *sourceMesh*. + toCopyElements: to copy mesh elements present on non-modified sub-shapes of + *sourceMesh*. + Returns: + tuple ( ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries ) + *invalidEntries* are study entries of objects whose + counterparts are not found in the *newGeom*, followed by entries + of mesh sub-objects that are invalid because they depend on a not found + preceeding sub-shape + """ + if isinstance( sourceMesh, Mesh ): + sourceMesh = sourceMesh.GetMesh() + + ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries = \ + SMESH._objref_SMESH_Gen.CopyMeshWithGeom( self, sourceMesh, newGeom, meshName, + toCopyGroups, + toReuseHypotheses, + toCopyElements) + return ( ok, Mesh(self, self.geompyD, newMesh), + newGroups, newSubMeshes, newHypotheses, invalidEntries ) + def GetSubShapesId( self, theMainObject, theListOfSubObjects ): """ Return IDs of sub-shapes @@ -6156,7 +6191,7 @@ class Mesh(metaclass = MeshMeta): Fill with 2D elements a hole defined by a SMESH.FreeBorder. Parameters: - FreeBorder: either a SMESH.FreeBorder or a list on node IDs. These nodes + holeNodes: either a SMESH.FreeBorder or a list on node IDs. These nodes must describe all sequential nodes of the hole border. The first and the last nodes must be the same. Use :meth:`FindFreeBorders` to get nodes of holes. groupName (string): name of a group to add new faces diff --git a/src/StdMeshers/StdMeshers_Arithmetic1D.cxx b/src/StdMeshers/StdMeshers_Arithmetic1D.cxx index 89cea269a..18f0da945 100644 --- a/src/StdMeshers/StdMeshers_Arithmetic1D.cxx +++ b/src/StdMeshers/StdMeshers_Arithmetic1D.cxx @@ -49,7 +49,7 @@ using namespace std; //============================================================================= StdMeshers_Arithmetic1D::StdMeshers_Arithmetic1D(int hypId, SMESH_Gen * gen) - :SMESH_Hypothesis(hypId, gen) + :StdMeshers_Reversible1D(hypId, gen) { _begLength = 1.; _endLength = 10.; @@ -105,21 +105,6 @@ double StdMeshers_Arithmetic1D::GetLength(bool isStartLength) const */ //============================================================================= -void StdMeshers_Arithmetic1D::SetReversedEdges( std::vector& ids ) -{ - if ( ids != _edgeIDs ) { - _edgeIDs = ids; - - NotifySubMeshesHypothesisModification(); - } -} - -//============================================================================= -/*! - * - */ -//============================================================================= - ostream & StdMeshers_Arithmetic1D::SaveTo(ostream & save) { int listSize = _edgeIDs.size(); @@ -165,28 +150,6 @@ istream & StdMeshers_Arithmetic1D::LoadFrom(istream & load) return load; } -//============================================================================= -/*! - * - */ -//============================================================================= - -ostream & operator <<(ostream & save, StdMeshers_Arithmetic1D & hyp) -{ - return hyp.SaveTo( save ); -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -istream & operator >>(istream & load, StdMeshers_Arithmetic1D & hyp) -{ - return hyp.LoadFrom( load ); -} - //================================================================================ /*! * \brief Initialize start and end length by the mesh built on the geometry diff --git a/src/StdMeshers/StdMeshers_Arithmetic1D.hxx b/src/StdMeshers/StdMeshers_Arithmetic1D.hxx index e0b9cd9b7..eb1a8f437 100644 --- a/src/StdMeshers/StdMeshers_Arithmetic1D.hxx +++ b/src/StdMeshers/StdMeshers_Arithmetic1D.hxx @@ -32,13 +32,11 @@ #include "SMESH_StdMeshers.hxx" +#include "StdMeshers_Reversible1D.hxx" #include "SMESH_Hypothesis.hxx" #include "Utils_SALOME_Exception.hxx" -#include - -class STDMESHERS_EXPORT StdMeshers_Arithmetic1D: - public SMESH_Hypothesis +class STDMESHERS_EXPORT StdMeshers_Arithmetic1D: public StdMeshers_Reversible1D { public: StdMeshers_Arithmetic1D(int hypId, SMESH_Gen* gen); @@ -48,18 +46,8 @@ public: double GetLength(bool isStartLength) const; - void SetReversedEdges( std::vector& ids); - - void SetObjectEntry( const char* entry ) { _objEntry = entry; } - - const char* GetObjectEntry() { return _objEntry.c_str(); } - - const std::vector& GetReversedEdges() const { return _edgeIDs; } - virtual std::ostream & SaveTo(std::ostream & save); virtual std::istream & LoadFrom(std::istream & load); - friend std::ostream& operator << (std::ostream & save, StdMeshers_Arithmetic1D & hyp); - friend std::istream& operator >> (std::istream & load, StdMeshers_Arithmetic1D & hyp); /*! * \brief Initialize start and end length by the mesh built on the geometry @@ -77,8 +65,6 @@ public: protected: double _begLength, _endLength; - std::vector _edgeIDs; - std::string _objEntry; }; #endif diff --git a/src/StdMeshers/StdMeshers_FixedPoints1D.cxx b/src/StdMeshers/StdMeshers_FixedPoints1D.cxx index b5934045b..be0917ef2 100644 --- a/src/StdMeshers/StdMeshers_FixedPoints1D.cxx +++ b/src/StdMeshers/StdMeshers_FixedPoints1D.cxx @@ -35,9 +35,8 @@ using namespace std; */ //============================================================================= -StdMeshers_FixedPoints1D::StdMeshers_FixedPoints1D(int hypId, - SMESH_Gen * gen) - :SMESH_Hypothesis(hypId, gen) +StdMeshers_FixedPoints1D::StdMeshers_FixedPoints1D(int hypId, SMESH_Gen * gen) + :StdMeshers_Reversible1D(hypId, gen) { _name = "FixedPoints1D"; _param_algo_dim = 1; @@ -81,27 +80,6 @@ void StdMeshers_FixedPoints1D::SetNbSegments(std::vector& listNbSeg) NotifySubMeshesHypothesisModification(); } -//============================================================================= -/*! - * - */ -//============================================================================= - -void StdMeshers_FixedPoints1D::SetReversedEdges( std::vector& ids ) -{ - if ( ids != _edgeIDs ) { - _edgeIDs = ids; - - NotifySubMeshesHypothesisModification(); - } -} - -//============================================================================= -/*! - * - */ -//============================================================================= - ostream & StdMeshers_FixedPoints1D::SaveTo(ostream & save) { int listSize = _params.size(); diff --git a/src/StdMeshers/StdMeshers_FixedPoints1D.hxx b/src/StdMeshers/StdMeshers_FixedPoints1D.hxx index 05f903013..58b9be644 100644 --- a/src/StdMeshers/StdMeshers_FixedPoints1D.hxx +++ b/src/StdMeshers/StdMeshers_FixedPoints1D.hxx @@ -29,13 +29,13 @@ #include "SMESH_StdMeshers.hxx" +#include "StdMeshers_Reversible1D.hxx" #include "SMESH_Hypothesis.hxx" #include "Utils_SALOME_Exception.hxx" #include -class STDMESHERS_EXPORT StdMeshers_FixedPoints1D: - public SMESH_Hypothesis +class STDMESHERS_EXPORT StdMeshers_FixedPoints1D: public StdMeshers_Reversible1D { public: StdMeshers_FixedPoints1D(int hypId, SMESH_Gen* gen); @@ -51,14 +51,6 @@ public: const std::vector& GetNbSegments() const { return _nbsegs; } - void SetReversedEdges( std::vector& ids); - - void SetObjectEntry( const char* entry ) { _objEntry = entry; } - - const char* GetObjectEntry() { return _objEntry.c_str(); } - - const std::vector& GetReversedEdges() const { return _edgeIDs; } - virtual std::ostream & SaveTo(std::ostream & save); virtual std::istream & LoadFrom(std::istream & load); @@ -79,8 +71,6 @@ public: protected: std::vector _params; std::vector _nbsegs; - std::vector _edgeIDs; - std::string _objEntry; }; #endif diff --git a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx index 5ba6e47d9..927613048 100644 --- a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx +++ b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx @@ -60,7 +60,7 @@ const double PRECISION = 1e-7; StdMeshers_NumberOfSegments::StdMeshers_NumberOfSegments(int hypId, SMESH_Gen * gen) - : SMESH_Hypothesis(hypId, gen), + : StdMeshers_Reversible1D(hypId, gen), _numberOfSegments(15),//issue 19923 _distrType(DT_Regular), _scaleFactor(1.), @@ -721,19 +721,3 @@ bool StdMeshers_NumberOfSegments::SetParametersByDefaults(const TDefaults& dflt { return (_numberOfSegments = dflts._nbSegments ); } - -//============================================================================= -/*! - * - */ -//============================================================================= - -void StdMeshers_NumberOfSegments::SetReversedEdges( std::vector& ids ) -{ - if ( ids != _edgeIDs ) { - _edgeIDs = ids; - - NotifySubMeshesHypothesisModification(); - } -} - diff --git a/src/StdMeshers/StdMeshers_NumberOfSegments.hxx b/src/StdMeshers/StdMeshers_NumberOfSegments.hxx index 6e9e59e3e..3a71f8e0d 100644 --- a/src/StdMeshers/StdMeshers_NumberOfSegments.hxx +++ b/src/StdMeshers/StdMeshers_NumberOfSegments.hxx @@ -29,10 +29,10 @@ #ifndef _SMESH_NUMBEROFSEGMENTS_HXX_ #define _SMESH_NUMBEROFSEGMENTS_HXX_ -#include "SMESH_StdMeshers.hxx" - +#include "StdMeshers_Reversible1D.hxx" #include "SMESH_Hypothesis.hxx" #include "Utils_SALOME_Exception.hxx" + #include /*! @@ -41,8 +41,7 @@ * It provides parameters for subdivision an edge by various * distribution types, considering the given number of resulting segments */ -class STDMESHERS_EXPORT StdMeshers_NumberOfSegments: - public SMESH_Hypothesis +class STDMESHERS_EXPORT StdMeshers_NumberOfSegments: public StdMeshers_Reversible1D { public: StdMeshers_NumberOfSegments(int hypId, SMESH_Gen* gen); @@ -171,14 +170,6 @@ public: int ConversionMode() const throw (SALOME_Exception); - void SetReversedEdges( std::vector& ids); - - void SetObjectEntry( const char* entry ) { _objEntry = entry; } - - const char* GetObjectEntry() { return _objEntry.c_str(); } - - const std::vector& GetReversedEdges() const { return _edgeIDs; } - /*! * \brief Initialize number of segments by the mesh built on the geometry * \param theMesh - the built mesh @@ -205,8 +196,6 @@ protected: std::vector _table, _distr; //!< the table for DT_TabFunc, a sequence of pairs of numbers std::string _func; //!< the expression of the function for DT_ExprFunc int _convMode; //!< flag of conversion mode: 0=exponent, 1=cut negative - std::vector _edgeIDs; //!< list of reversed edges ids - std::string _objEntry; //!< Entry of the main object to reverse edges }; #endif diff --git a/src/StdMeshers/StdMeshers_QuadrangleParams.hxx b/src/StdMeshers/StdMeshers_QuadrangleParams.hxx index 64247e0b6..392447eab 100644 --- a/src/StdMeshers/StdMeshers_QuadrangleParams.hxx +++ b/src/StdMeshers/StdMeshers_QuadrangleParams.hxx @@ -51,7 +51,7 @@ public: int GetTriaVertex() const { return _triaVertexID; } void SetObjectEntry (const char* entry) { _objEntry = entry; } - const char* GetObjectEntry() { return _objEntry.c_str(); } + const char* GetObjectEntry() const { return _objEntry.c_str(); } void SetQuadType (StdMeshers_QuadType type); StdMeshers_QuadType GetQuadType() const { return _quadType; } diff --git a/src/StdMeshers/StdMeshers_Reversible1D.hxx b/src/StdMeshers/StdMeshers_Reversible1D.hxx index 00d61a1da..e2651cd41 100644 --- a/src/StdMeshers/StdMeshers_Reversible1D.hxx +++ b/src/StdMeshers/StdMeshers_Reversible1D.hxx @@ -44,7 +44,7 @@ public: void SetObjectEntry( const char* entry ) { _objEntry = entry; } - const char* GetObjectEntry() { return _objEntry.c_str(); } + const char* GetObjectEntry() const { return _objEntry.c_str(); } const std::vector& GetReversedEdges() const { return _edgeIDs; } diff --git a/src/StdMeshers/StdMeshers_StartEndLength.cxx b/src/StdMeshers/StdMeshers_StartEndLength.cxx index a2bf0f7e1..b89af1677 100644 --- a/src/StdMeshers/StdMeshers_StartEndLength.cxx +++ b/src/StdMeshers/StdMeshers_StartEndLength.cxx @@ -47,9 +47,8 @@ using namespace std; */ //============================================================================= -StdMeshers_StartEndLength::StdMeshers_StartEndLength(int hypId, - SMESH_Gen * gen) - :SMESH_Hypothesis(hypId, gen) +StdMeshers_StartEndLength::StdMeshers_StartEndLength( int hypId, SMESH_Gen* gen ) + :StdMeshers_Reversible1D(hypId, gen) { _begLength = 1.; _endLength = 10.; @@ -105,21 +104,6 @@ double StdMeshers_StartEndLength::GetLength(bool isStartLength) const */ //============================================================================= -void StdMeshers_StartEndLength::SetReversedEdges( std::vector& ids ) -{ - if ( ids != _edgeIDs ) { - _edgeIDs = ids; - - NotifySubMeshesHypothesisModification(); - } -} - -//============================================================================= -/*! - * - */ -//============================================================================= - ostream & StdMeshers_StartEndLength::SaveTo(ostream & save) { int listSize = _edgeIDs.size(); @@ -166,28 +150,6 @@ istream & StdMeshers_StartEndLength::LoadFrom(istream & load) return load; } -//============================================================================= -/*! - * - */ -//============================================================================= - -ostream & operator <<(ostream & save, StdMeshers_StartEndLength & hyp) -{ - return hyp.SaveTo( save ); -} - -//============================================================================= -/*! - * - */ -//============================================================================= - -istream & operator >>(istream & load, StdMeshers_StartEndLength & hyp) -{ - return hyp.LoadFrom( load ); -} - //================================================================================ /*! * \brief Initialize start and end length by the mesh built on the geometry diff --git a/src/StdMeshers/StdMeshers_StartEndLength.hxx b/src/StdMeshers/StdMeshers_StartEndLength.hxx index 576d8e199..dbe7a501c 100644 --- a/src/StdMeshers/StdMeshers_StartEndLength.hxx +++ b/src/StdMeshers/StdMeshers_StartEndLength.hxx @@ -29,12 +29,13 @@ #include "SMESH_StdMeshers.hxx" +#include "StdMeshers_Reversible1D.hxx" #include "SMESH_Hypothesis.hxx" #include "Utils_SALOME_Exception.hxx" #include -class STDMESHERS_EXPORT StdMeshers_StartEndLength:public SMESH_Hypothesis +class STDMESHERS_EXPORT StdMeshers_StartEndLength: public StdMeshers_Reversible1D { public: StdMeshers_StartEndLength(int hypId, SMESH_Gen * gen); @@ -44,19 +45,8 @@ class STDMESHERS_EXPORT StdMeshers_StartEndLength:public SMESH_Hypothesis double GetLength(bool isStartLength) const; - void SetReversedEdges( std::vector& ids); - - const std::vector& GetReversedEdges() const { return _edgeIDs; } - - void SetObjectEntry( const char* entry ) { _objEntry = entry; } - - const char* GetObjectEntry() { return _objEntry.c_str(); } - virtual std::ostream & SaveTo(std::ostream & save); virtual std::istream & LoadFrom(std::istream & load); - friend std::ostream & operator <<(std::ostream & save, StdMeshers_StartEndLength & hyp); - friend std::istream & operator >>(std::istream & load, StdMeshers_StartEndLength & hyp); - /*! * \brief Initialize start and end length by the mesh built on the geometry @@ -74,8 +64,6 @@ class STDMESHERS_EXPORT StdMeshers_StartEndLength:public SMESH_Hypothesis protected: double _begLength, _endLength; - std::vector _edgeIDs; - std::string _objEntry; }; #endif diff --git a/src/StdMeshers_I/StdMeshers_Adaptive1D_i.hxx b/src/StdMeshers_I/StdMeshers_Adaptive1D_i.hxx index 060b8b42a..b83fc0ba5 100644 --- a/src/StdMeshers_I/StdMeshers_Adaptive1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_Adaptive1D_i.hxx @@ -83,6 +83,12 @@ class STDMESHERS_I_EXPORT StdMeshers_Adaptive1D_i: * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration) */ CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.cxx b/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.cxx index 9676549e2..a7cd08ead 100644 --- a/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.cxx @@ -48,7 +48,8 @@ using namespace std; StdMeshers_Arithmetic1D_i::StdMeshers_Arithmetic1D_i( PortableServer::POA_ptr thePOA, ::SMESH_Gen* theGenImpl ) : SALOME::GenericObj_i( thePOA ), - SMESH_Hypothesis_i( thePOA ) + SMESH_Hypothesis_i( thePOA ), + StdMeshers_Reversible1D_i( this ) { myBaseImpl = new ::StdMeshers_Arithmetic1D( theGenImpl->GetANewId(), theGenImpl ); @@ -131,98 +132,6 @@ CORBA::Double StdMeshers_Arithmetic1D_i::GetLength( CORBA::Boolean theIsStart) return this->GetImpl()->GetLength( theIsStart ); } -//============================================================================= -/*! - * StdMeshers_Arithmetic1D_i::SetReversedEdges - * - * Set edges to reverse - */ -//============================================================================= - -void StdMeshers_Arithmetic1D_i::SetReversedEdges( const SMESH::long_array& theIds ) -{ - ASSERT( myBaseImpl ); - try { - std::vector ids( theIds.length() ); - CORBA::Long iEnd = theIds.length(); - for ( CORBA::Long i = 0; i < iEnd; i++ ) - ids[ i ] = theIds[ i ]; - - this->GetImpl()->SetReversedEdges( ids ); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - - // Update Python script - SMESH::TPythonDump() << _this() << ".SetReversedEdges( " << theIds << " )"; -} - -//============================================================================= -/*! - * StdMeshers_Arithmetic1D_i::SetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -void StdMeshers_Arithmetic1D_i::SetObjectEntry( const char* theEntry ) -{ - ASSERT( myBaseImpl ); - string entry(theEntry); // actually needed as theEntry is spoiled by moment of dumping - try { - this->GetImpl()->SetObjectEntry( entry.c_str() ); - // Update Python script - SMESH::TPythonDump() << _this() << ".SetObjectEntry( \"" << entry.c_str() << "\" )"; - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(),SALOME::BAD_PARAM ); - } -} - -//============================================================================= -/*! - * StdMeshers_Arithmetic1D_i::GetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -char* StdMeshers_Arithmetic1D_i::GetObjectEntry() -{ - ASSERT( myBaseImpl ); - const char* entry; - try { - entry = this->GetImpl()->GetObjectEntry(); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - return CORBA::string_dup( entry ); -} - -//============================================================================= -/*! - * StdMeshers_Arithmetic1D_i::GetReversedEdges - * - * Get reversed edges - */ -//============================================================================= - -SMESH::long_array* StdMeshers_Arithmetic1D_i::GetReversedEdges() -{ - ASSERT( myBaseImpl ); - SMESH::long_array_var anArray = new SMESH::long_array; - std::vector ids = this->GetImpl()->GetReversedEdges(); - anArray->length( ids.size() ); - for ( CORBA::ULong i = 0; i < ids.size(); i++) - anArray [ i ] = ids [ i ]; - - return anArray._retn(); -} - //============================================================================= /*! * StdMeshers_Arithmetic1D_i::GetImpl @@ -261,3 +170,30 @@ std::string StdMeshers_Arithmetic1D_i::getMethodOfParameter(const int paramIndex { return paramIndex == 0 ? "SetStartLength" : "SetEndLength"; } + + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_Arithmetic1D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + return StdMeshers_Reversible1D_i::getObjectsDependOn( entryArray, subIDArray ); +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_Arithmetic1D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + return StdMeshers_Reversible1D_i::setObjectsDependOn( entryArray, subIDArray ); +} diff --git a/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.hxx b/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.hxx index f159f0c48..ad191a26a 100644 --- a/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_Arithmetic1D_i.hxx @@ -33,7 +33,7 @@ #include #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis) -#include "SMESH_Hypothesis_i.hxx" +#include "StdMeshers_Reversible1D_i.hxx" #include "StdMeshers_Arithmetic1D.hxx" // ====================================================== @@ -41,7 +41,8 @@ // ====================================================== class STDMESHERS_I_EXPORT StdMeshers_Arithmetic1D_i: public virtual POA_StdMeshers::StdMeshers_Arithmetic1D, - public virtual SMESH_Hypothesis_i + public virtual SMESH_Hypothesis_i, + public virtual StdMeshers_Reversible1D_i { public: // Constructor @@ -64,24 +65,23 @@ public: // Get length CORBA::Double GetLength(CORBA::Boolean theIsStart); - //Set Reversed Edges - void SetReversedEdges( const SMESH::long_array& theIDs); - - //Get Reversed Edges - SMESH::long_array* GetReversedEdges(); - - //Set the Entry of the Object - void SetObjectEntry( const char* theEntry); - - //Get Object Entry - char* GetObjectEntry(); - // Get implementation ::StdMeshers_Arithmetic1D* GetImpl(); // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); + protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_AutomaticLength_i.hxx b/src/StdMeshers_I/StdMeshers_AutomaticLength_i.hxx index a2b4772e6..e7d4ae450 100644 --- a/src/StdMeshers_I/StdMeshers_AutomaticLength_i.hxx +++ b/src/StdMeshers_I/StdMeshers_AutomaticLength_i.hxx @@ -66,6 +66,12 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.hxx b/src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.hxx index d9f4d603a..4f37edc3a 100644 --- a/src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.hxx @@ -141,6 +141,13 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_Deflection1D_i.hxx b/src/StdMeshers_I/StdMeshers_Deflection1D_i.hxx index 9078455c6..71277100b 100644 --- a/src/StdMeshers_I/StdMeshers_Deflection1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_Deflection1D_i.hxx @@ -65,6 +65,11 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.cxx b/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.cxx index 08829204e..7dc131acf 100644 --- a/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.cxx @@ -45,8 +45,9 @@ using namespace std; StdMeshers_FixedPoints1D_i::StdMeshers_FixedPoints1D_i( PortableServer::POA_ptr thePOA, ::SMESH_Gen* theGenImpl ) - : SALOME::GenericObj_i( thePOA ), - SMESH_Hypothesis_i( thePOA ) + : SALOME::GenericObj_i( thePOA ), + SMESH_Hypothesis_i( thePOA ), + StdMeshers_Reversible1D_i( this ) { myBaseImpl = new ::StdMeshers_FixedPoints1D(theGenImpl->GetANewId(), theGenImpl); @@ -156,98 +157,6 @@ SMESH::long_array* StdMeshers_FixedPoints1D_i::GetNbSegments() return anArray._retn(); } -//============================================================================= -/*! - * StdMeshers_FixedPoints1D_i::SetReversedEdges - * - * Set edges to reverse - */ -//============================================================================= - -void StdMeshers_FixedPoints1D_i::SetReversedEdges( const SMESH::long_array& theIds ) -{ - ASSERT( myBaseImpl ); - try { - std::vector ids( theIds.length() ); - CORBA::Long iEnd = theIds.length(); - for ( CORBA::Long i = 0; i < iEnd; i++ ) - ids[ i ] = theIds[ i ]; - - this->GetImpl()->SetReversedEdges( ids ); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - - // Update Python script - SMESH::TPythonDump() << _this() << ".SetReversedEdges( " << theIds << " )"; -} - -//============================================================================= -/*! - * StdMeshers_FixedPoints1D_i::SetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -void StdMeshers_FixedPoints1D_i::SetObjectEntry( const char* theEntry ) -{ - ASSERT( myBaseImpl ); - string entry(theEntry); // actually needed as theEntry is spoiled by moment of dumping - try { - this->GetImpl()->SetObjectEntry( entry.c_str() ); - // Update Python script - SMESH::TPythonDump() << _this() << ".SetObjectEntry( \"" << entry.c_str() << "\" )"; - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(),SALOME::BAD_PARAM ); - } -} - -//============================================================================= -/*! - * StdMeshers_FixedPoints1D_i::GetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -char* StdMeshers_FixedPoints1D_i::GetObjectEntry() -{ - ASSERT( myBaseImpl ); - const char* entry; - try { - entry = this->GetImpl()->GetObjectEntry(); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - return CORBA::string_dup( entry ); -} - -//============================================================================= -/*! - * StdMeshers_FixedPoints1D_i::GetReversedEdges - * - * Get reversed edges - */ -//============================================================================= - -SMESH::long_array* StdMeshers_FixedPoints1D_i::GetReversedEdges() -{ - ASSERT( myBaseImpl ); - SMESH::long_array_var anArray = new SMESH::long_array; - std::vector ids = this->GetImpl()->GetReversedEdges(); - anArray->length( ids.size() ); - for ( CORBA::ULong i = 0; i < ids.size(); i++) - anArray [ i ] = ids [ i ]; - - return anArray._retn(); -} - //============================================================================= /*! * StdMeshers_FixedPoints1D_i::GetImpl @@ -269,9 +178,34 @@ SMESH::long_array* StdMeshers_FixedPoints1D_i::GetReversedEdges() * * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration) */ -//================================================================================ +//================================================================================ CORBA::Boolean StdMeshers_FixedPoints1D_i::IsDimSupported( SMESH::Dimension type ) { return type == SMESH::DIM_1D; } +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_FixedPoints1D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + return StdMeshers_Reversible1D_i::getObjectsDependOn( entryArray, subIDArray ); +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_FixedPoints1D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + return StdMeshers_Reversible1D_i::setObjectsDependOn( entryArray, subIDArray ); +} diff --git a/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.hxx b/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.hxx index 98d1aff47..0a86129ac 100644 --- a/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_FixedPoints1D_i.hxx @@ -30,7 +30,7 @@ #include #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis) -#include "SMESH_Hypothesis_i.hxx" +#include "StdMeshers_Reversible1D_i.hxx" #include "StdMeshers_FixedPoints1D.hxx" // ====================================================== @@ -38,7 +38,8 @@ // ====================================================== class STDMESHERS_I_EXPORT StdMeshers_FixedPoints1D_i: public virtual POA_StdMeshers::StdMeshers_FixedPoints1D, - public virtual SMESH_Hypothesis_i + public virtual SMESH_Hypothesis_i, + public virtual StdMeshers_Reversible1D_i { public: // Constructor @@ -62,23 +63,22 @@ public: // Returns list of numbers of segments SMESH::long_array* GetNbSegments(); - //Set Reversed Edges - void SetReversedEdges( const SMESH::long_array& theIDs); - - //Get Reversed Edges - SMESH::long_array* GetReversedEdges(); - - //Set the Entry of the Object - void SetObjectEntry( const char* theEntry); - - //Get Object Entry - char* GetObjectEntry(); - // Get implementation ::StdMeshers_FixedPoints1D* GetImpl(); // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); }; #endif diff --git a/src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx b/src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx index 1d213d975..2b5f241bc 100644 --- a/src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_Geometric1D_i.cxx @@ -127,15 +127,41 @@ CORBA::Double StdMeshers_Geometric1D_i::GetCommonRatio() //================================================================================ /*! - * \brief Verify whether hypothesis supports given entity type - * \param type - dimension (see SMESH::Dimension enumeration) - * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise - * + * \brief Verify whether hypothesis supports given entity type + * \param type - dimension (see SMESH::Dimension enumeration) + * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise + * * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration) */ -//================================================================================ +//================================================================================ CORBA::Boolean StdMeshers_Geometric1D_i::IsDimSupported(::SMESH::Dimension type) { return type == SMESH::DIM_1D; } + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_Geometric1D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + return StdMeshers_Reversible1D_i::getObjectsDependOn( entryArray, subIDArray ); +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_Geometric1D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + return StdMeshers_Reversible1D_i::setObjectsDependOn( entryArray, subIDArray ); +} diff --git a/src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx b/src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx index 542e88e5e..6ccb5d70a 100644 --- a/src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_Geometric1D_i.hxx @@ -59,6 +59,18 @@ class STDMESHERS_I_EXPORT StdMeshers_Geometric1D_i: // Get implementation ::StdMeshers_Geometric1D* GetImpl(); + + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); }; #endif diff --git a/src/StdMeshers_I/StdMeshers_ImportSource1D_i.hxx b/src/StdMeshers_I/StdMeshers_ImportSource1D_i.hxx index 61d62654e..ab1e9bb6c 100644 --- a/src/StdMeshers_I/StdMeshers_ImportSource1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_ImportSource1D_i.hxx @@ -64,6 +64,17 @@ class STDMESHERS_I_EXPORT StdMeshers_ImportSource1D_i: virtual void LoadFrom( const char* theStream ); virtual void UpdateAsMeshesRestored(); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } private: SMESH::string_array_var _groupEntries; std::vector< std::string > _groupIDs; diff --git a/src/StdMeshers_I/StdMeshers_ImportSource2D_i.hxx b/src/StdMeshers_I/StdMeshers_ImportSource2D_i.hxx index 8b346df67..f377bceb1 100644 --- a/src/StdMeshers_I/StdMeshers_ImportSource2D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_ImportSource2D_i.hxx @@ -64,6 +64,17 @@ class STDMESHERS_I_EXPORT StdMeshers_ImportSource2D_i: virtual void LoadFrom( const char* theStream ); virtual void UpdateAsMeshesRestored(); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } private: SMESH::string_array_var _groupEntries; std::vector< std::string > _groupIDs; diff --git a/src/StdMeshers_I/StdMeshers_LayerDistribution2D_i.hxx b/src/StdMeshers_I/StdMeshers_LayerDistribution2D_i.hxx index 2831138b9..9b9ba7a52 100644 --- a/src/StdMeshers_I/StdMeshers_LayerDistribution2D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_LayerDistribution2D_i.hxx @@ -54,6 +54,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_LayerDistribution_i.hxx b/src/StdMeshers_I/StdMeshers_LayerDistribution_i.hxx index 69050ee70..43942228c 100644 --- a/src/StdMeshers_I/StdMeshers_LayerDistribution_i.hxx +++ b/src/StdMeshers_I/StdMeshers_LayerDistribution_i.hxx @@ -77,6 +77,17 @@ public: virtual char* SaveTo(); virtual void LoadFrom( const char* theStream ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: // restore myMethod2VarParams by parameters stored in an old study virtual void setOldParameters (const char* theParameters); diff --git a/src/StdMeshers_I/StdMeshers_LengthFromEdges_i.hxx b/src/StdMeshers_I/StdMeshers_LengthFromEdges_i.hxx index 0318fd0e1..17cde7be8 100644 --- a/src/StdMeshers_I/StdMeshers_LengthFromEdges_i.hxx +++ b/src/StdMeshers_I/StdMeshers_LengthFromEdges_i.hxx @@ -66,6 +66,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_LocalLength_i.hxx b/src/StdMeshers_I/StdMeshers_LocalLength_i.hxx index 14a01b76d..0fcd0d089 100644 --- a/src/StdMeshers_I/StdMeshers_LocalLength_i.hxx +++ b/src/StdMeshers_I/StdMeshers_LocalLength_i.hxx @@ -71,6 +71,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_MaxElementArea_i.hxx b/src/StdMeshers_I/StdMeshers_MaxElementArea_i.hxx index 7f7fe254f..0651ac899 100644 --- a/src/StdMeshers_I/StdMeshers_MaxElementArea_i.hxx +++ b/src/StdMeshers_I/StdMeshers_MaxElementArea_i.hxx @@ -63,6 +63,18 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } + protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_MaxElementVolume_i.hxx b/src/StdMeshers_I/StdMeshers_MaxElementVolume_i.hxx index d40369cb7..108b9804c 100644 --- a/src/StdMeshers_I/StdMeshers_MaxElementVolume_i.hxx +++ b/src/StdMeshers_I/StdMeshers_MaxElementVolume_i.hxx @@ -63,6 +63,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_MaxLength_i.hxx b/src/StdMeshers_I/StdMeshers_MaxLength_i.hxx index b4b633231..bd1ea6334 100644 --- a/src/StdMeshers_I/StdMeshers_MaxLength_i.hxx +++ b/src/StdMeshers_I/StdMeshers_MaxLength_i.hxx @@ -77,6 +77,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_NotConformAllowed_i.hxx b/src/StdMeshers_I/StdMeshers_NotConformAllowed_i.hxx index ee4107f10..510d0cf1a 100644 --- a/src/StdMeshers_I/StdMeshers_NotConformAllowed_i.hxx +++ b/src/StdMeshers_I/StdMeshers_NotConformAllowed_i.hxx @@ -50,6 +50,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: ::StdMeshers_NotConformAllowed* _impl; }; diff --git a/src/StdMeshers_I/StdMeshers_NumberOfLayers2D_i.hxx b/src/StdMeshers_I/StdMeshers_NumberOfLayers2D_i.hxx index 42672b838..4534245a9 100644 --- a/src/StdMeshers_I/StdMeshers_NumberOfLayers2D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_NumberOfLayers2D_i.hxx @@ -52,6 +52,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_NumberOfLayers_i.hxx b/src/StdMeshers_I/StdMeshers_NumberOfLayers_i.hxx index 77a619883..13649309f 100644 --- a/src/StdMeshers_I/StdMeshers_NumberOfLayers_i.hxx +++ b/src/StdMeshers_I/StdMeshers_NumberOfLayers_i.hxx @@ -68,6 +68,17 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.cxx b/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.cxx index c61aa3785..1c5163385 100644 --- a/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.cxx +++ b/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.cxx @@ -36,7 +36,6 @@ #include -using namespace std; //============================================================================= /*! * StdMeshers_NumberOfSegments_i::StdMeshers_NumberOfSegments_i @@ -47,8 +46,9 @@ using namespace std; StdMeshers_NumberOfSegments_i::StdMeshers_NumberOfSegments_i( PortableServer::POA_ptr thePOA, ::SMESH_Gen* theGenImpl ) - : SALOME::GenericObj_i( thePOA ), - SMESH_Hypothesis_i( thePOA ) + : SALOME::GenericObj_i( thePOA ), + SMESH_Hypothesis_i( thePOA ), + StdMeshers_Reversible1D_i( this ) { myBaseImpl = new ::StdMeshers_NumberOfSegments( theGenImpl->GetANewId(), theGenImpl ); @@ -159,100 +159,6 @@ CORBA::Long StdMeshers_NumberOfSegments_i::GetNumberOfSegments() return this->GetImpl()->GetNumberOfSegments(); } -//============================================================================= -/*! - * StdMeshers_NumberOfSegments_i::SetReversedEdges - * - * Set edges to reverse - */ -//============================================================================= - -void StdMeshers_NumberOfSegments_i::SetReversedEdges( const SMESH::long_array& theIds ) -{ - ASSERT( myBaseImpl ); - try { - std::vector ids( theIds.length() ); - CORBA::Long iEnd = theIds.length(); - for ( CORBA::Long i = 0; i < iEnd; i++ ) - ids[ i ] = theIds[ i ]; - - this->GetImpl()->SetReversedEdges( ids ); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - - // Update Python script - SMESH::TPythonDump() << _this() << ".SetReversedEdges( " << theIds << " )"; -} - -//============================================================================= -/*! - * StdMeshers_NumberOfSegments_i::SetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -void StdMeshers_NumberOfSegments_i::SetObjectEntry( const char* theEntry ) -{ - ASSERT( myBaseImpl ); - string entry(theEntry); // actually needed as theEntry is spoiled by moment of dumping - try { - this->GetImpl()->SetObjectEntry( entry.c_str() ); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - // Update Python script - SMESH::TPythonDump() << _this() << ".SetObjectEntry( \"" << entry.c_str() << "\" )"; -} - -//============================================================================= -/*! - * StdMeshers_NumberOfSegments_i::GetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -char* StdMeshers_NumberOfSegments_i::GetObjectEntry() -{ - ASSERT( myBaseImpl ); - - const char* entry; - try { - entry = this->GetImpl()->GetObjectEntry(); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - return CORBA::string_dup( entry ); -} - -//============================================================================= -/*! - * StdMeshers_NumberOfSegments_i::GetReversedEdges - * - * Get reversed edges - */ -//============================================================================= - -SMESH::long_array* StdMeshers_NumberOfSegments_i::GetReversedEdges() -{ - ASSERT( myBaseImpl ); - SMESH::long_array_var anArray = new SMESH::long_array; - std::vector ids = this->GetImpl()->GetReversedEdges(); - anArray->length( ids.size() ); - for ( size_t i = 0; i < ids.size(); i++) - anArray [ i ] = ids [ i ]; - - return anArray._retn(); -} - //============================================================================= /*! */ @@ -497,3 +403,30 @@ std::string StdMeshers_NumberOfSegments_i::getMethodOfParameter(const int paramI { return paramIndex == 0 ? "SetNumberOfSegments" : "SetScaleFactor"; } + + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_NumberOfSegments_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + return StdMeshers_Reversible1D_i::getObjectsDependOn( entryArray, subIDArray ); +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_NumberOfSegments_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + return StdMeshers_Reversible1D_i::setObjectsDependOn( entryArray, subIDArray ); +} diff --git a/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.hxx b/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.hxx index 09301653b..fc623af13 100644 --- a/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.hxx +++ b/src/StdMeshers_I/StdMeshers_NumberOfSegments_i.hxx @@ -35,7 +35,7 @@ #include CORBA_SERVER_HEADER(SMESH_Mesh) #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis) -#include "SMESH_Hypothesis_i.hxx" +#include "StdMeshers_Reversible1D_i.hxx" #include "StdMeshers_NumberOfSegments.hxx" // ====================================================== @@ -43,7 +43,8 @@ // ====================================================== class STDMESHERS_I_EXPORT StdMeshers_NumberOfSegments_i: public virtual POA_StdMeshers::StdMeshers_NumberOfSegments, - public virtual SMESH_Hypothesis_i + public virtual SMESH_Hypothesis_i, + public virtual StdMeshers_Reversible1D_i { public: // Constructor @@ -104,18 +105,16 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); - //Set Reversed Edges - void SetReversedEdges( const SMESH::long_array& theIDs); - //Get Reversed Edges - SMESH::long_array* GetReversedEdges(); + // Methods for copying mesh definition to other geometry - //Set Object Entry - void SetObjectEntry( const char* entry); - - //Get Object Entry - char* GetObjectEntry(); + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_ObjRefUlils.cxx b/src/StdMeshers_I/StdMeshers_ObjRefUlils.cxx index c7e3988b8..f9a2b7837 100644 --- a/src/StdMeshers_I/StdMeshers_ObjRefUlils.cxx +++ b/src/StdMeshers_I/StdMeshers_ObjRefUlils.cxx @@ -162,3 +162,21 @@ void StdMeshers_ObjRefUlils::SaveToStream( const std::string& studyEntry, else stream << " " << studyEntry; } + +//======================================================================= +//function : EntryToShape +//purpose : Return TopoDS_Shape by a study entry +//======================================================================= + +TopoDS_Shape StdMeshers_ObjRefUlils::EntryToShape(const std::string theEntry) +{ + TopoDS_Shape shape; + + if (SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen()) { + SALOMEDS::SObject_wrap sobj = SMESH_Gen_i::getStudyServant()->FindObjectID( theEntry.c_str() ); + CORBA::Object_var obj = gen->SObjectToObject( sobj ); + GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj ); + shape = gen->GeomObjectToShape( geom.in() ); + } + return shape; +} diff --git a/src/StdMeshers_I/StdMeshers_ObjRefUlils.hxx b/src/StdMeshers_I/StdMeshers_ObjRefUlils.hxx index fb2540c65..757cea482 100644 --- a/src/StdMeshers_I/StdMeshers_ObjRefUlils.hxx +++ b/src/StdMeshers_I/StdMeshers_ObjRefUlils.hxx @@ -65,6 +65,13 @@ public: return TopoDS_Shape(); } + /*! + * \brief Return TopoDS_Shape by a study entry + * \param theEntry - study entry + * \retval TopoDS_Shape - result TopoDS_Shape + */ + static TopoDS_Shape EntryToShape(const std::string theEntry); + /*! * \brief Return study entry of GEOM Object */ diff --git a/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.cxx b/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.cxx index 7b4048662..e0243b187 100644 --- a/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.cxx @@ -298,3 +298,46 @@ void StdMeshers_ProjectionSource1D_i::LoadFrom( const char* theStream ) str >> myShapeEntries[ i ]; } +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_ProjectionSource1D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + for ( int i = 0; i < NB_SHAPES; ++i ) + entryArray.push_back( myShapeEntries[ i ]); + + return true; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_ProjectionSource1D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + TopoDS_Shape shapes[ NB_SHAPES ]; + for ( int i = 0; i < NB_SHAPES; ++i ) + { + myShapeEntries[ i ] = entryArray[ i ]; + shapes[ i ] = StdMeshers_ObjRefUlils::EntryToShape( entryArray[ i ]); + } + + try { + GetImpl()->SetSourceEdge ( shapes[ SRC_EDGE ] ); + GetImpl()->SetVertexAssociation( shapes[ SRC_VERTEX ], + shapes[ TGT_VERTEX ]); + } + catch (...) { + return false; + } + return true; +} diff --git a/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.hxx b/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.hxx index 1b7c6981b..bbd1e5e58 100644 --- a/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_ProjectionSource1D_i.hxx @@ -109,6 +109,15 @@ public: virtual char* SaveTo(); virtual void LoadFrom( const char* theStream ); + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); private: // keep entries because the same shape can be published several times with // different names and in this case a correct name can't be restored by a TopoDS_Shape diff --git a/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.cxx b/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.cxx index ff0364603..5d3706d9f 100644 --- a/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.cxx @@ -311,3 +311,48 @@ void StdMeshers_ProjectionSource2D_i::LoadFrom( const char* theStream ) str >> myShapeEntries[ i ]; } +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_ProjectionSource2D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + for ( int i = 0; i < NB_SHAPES; ++i ) + entryArray.push_back( myShapeEntries[ i ]); + + return true; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_ProjectionSource2D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + TopoDS_Shape shapes[ NB_SHAPES ]; + for ( int i = 0; i < NB_SHAPES; ++i ) + { + myShapeEntries[ i ] = entryArray[ i ]; + shapes[ i ] = StdMeshers_ObjRefUlils::EntryToShape( entryArray[ i ]); + } + + try { + GetImpl()->SetSourceFace ( shapes[ SRC_FACE ] ); + GetImpl()->SetVertexAssociation( shapes[ SRC_VERTEX1 ], + shapes[ SRC_VERTEX2 ], + shapes[ TGT_VERTEX1 ], + shapes[ TGT_VERTEX2 ]); + } + catch (...) { + return false; + } + return true; +} diff --git a/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.hxx b/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.hxx index 2ba81dc0a..e8352df31 100644 --- a/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_ProjectionSource2D_i.hxx @@ -113,6 +113,16 @@ public: virtual char* SaveTo(); virtual void LoadFrom( const char* theStream ); + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); private: // keep entries because the same shape can be published several times with // different names and in this case a correct name can't be restored by a TopoDS_Shape diff --git a/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.cxx b/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.cxx index 062602d89..bbbf9e3cb 100644 --- a/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.cxx @@ -312,3 +312,48 @@ void StdMeshers_ProjectionSource3D_i::LoadFrom( const char* theStream ) str >> myShapeEntries[ i ]; } +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_ProjectionSource3D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + for ( int i = 0; i < NB_SHAPES; ++i ) + entryArray.push_back( myShapeEntries[ i ]); + + return true; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_ProjectionSource3D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + TopoDS_Shape shapes[ NB_SHAPES ]; + for ( int i = 0; i < NB_SHAPES; ++i ) + { + myShapeEntries[ i ] = entryArray[ i ]; + shapes[ i ] = StdMeshers_ObjRefUlils::EntryToShape( entryArray[ i ]); + } + + try { + GetImpl()->SetSource3DShape ( shapes[ SRC_SHAPE3D ] ); + GetImpl()->SetVertexAssociation( shapes[ SRC_VERTEX1 ], + shapes[ SRC_VERTEX2 ], + shapes[ TGT_VERTEX1 ], + shapes[ TGT_VERTEX2 ]); + } + catch (...) { + return false; + } + return true; +} diff --git a/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.hxx b/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.hxx index 5a25111cd..003181849 100644 --- a/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_ProjectionSource3D_i.hxx @@ -114,6 +114,17 @@ public: virtual char* SaveTo(); virtual void LoadFrom( const char* theStream ); + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); + private: // keep entries because the same shape can be published several times with // different names and in this case a correct name can't be restored by a TopoDS_Shape @@ -124,4 +135,3 @@ private: }; #endif - diff --git a/src/StdMeshers_I/StdMeshers_Propagation_i.hxx b/src/StdMeshers_I/StdMeshers_Propagation_i.hxx index 961f203d1..ae5819c31 100644 --- a/src/StdMeshers_I/StdMeshers_Propagation_i.hxx +++ b/src/StdMeshers_I/StdMeshers_Propagation_i.hxx @@ -52,6 +52,12 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; // ====================================================== @@ -69,6 +75,12 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx index 78b2841e1..aa3f947dd 100644 --- a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx +++ b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.cxx @@ -378,3 +378,54 @@ void StdMeshers_QuadrangleParams_i::LoadFrom( const char* theStream ) myBaseImpl->LoadFrom( is ); } + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_QuadrangleParams_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + const ::StdMeshers_QuadrangleParams* impl = + static_cast( myBaseImpl ); + + subIDArray.push_back( impl->GetTriaVertex() ); + + entryArray.push_back( impl->GetObjectEntry() ); + entryArray.insert( entryArray.end(), myShapeEntries.begin(), myShapeEntries.end() ); + + return true; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_QuadrangleParams_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + if ( !subIDArray.empty() ) + GetImpl()->SetTriaVertex( subIDArray[0] ); + + GetImpl()->SetObjectEntry( entryArray[0].c_str() ); + + myShapeEntries.assign( ++entryArray.begin(), entryArray.end() ); + + std::vector< TopoDS_Shape > shapes; + std::vector< gp_Pnt > points; + this->GetImpl()->GetEnforcedNodes( shapes, points ); + + shapes.clear(); + for ( size_t i = 0; i < myShapeEntries.size(); ++i ) + shapes.push_back( StdMeshers_ObjRefUlils::EntryToShape( myShapeEntries[i] )); + + this->GetImpl()->SetEnforcedNodes( shapes, points ); + + return true; +} diff --git a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx index 227dd86af..822b501e5 100644 --- a/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx +++ b/src/StdMeshers_I/StdMeshers_QuadrangleParams_i.hxx @@ -84,6 +84,16 @@ public: virtual char* SaveTo(); virtual void LoadFrom( const char* theStream ); + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); protected: std::vector myShapeEntries; diff --git a/src/StdMeshers_I/StdMeshers_QuadranglePreference_i.hxx b/src/StdMeshers_I/StdMeshers_QuadranglePreference_i.hxx index e60f07329..5e0455ac0 100644 --- a/src/StdMeshers_I/StdMeshers_QuadranglePreference_i.hxx +++ b/src/StdMeshers_I/StdMeshers_QuadranglePreference_i.hxx @@ -58,6 +58,12 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_QuadraticMesh_i.hxx b/src/StdMeshers_I/StdMeshers_QuadraticMesh_i.hxx index 71c17acad..433b73734 100644 --- a/src/StdMeshers_I/StdMeshers_QuadraticMesh_i.hxx +++ b/src/StdMeshers_I/StdMeshers_QuadraticMesh_i.hxx @@ -59,6 +59,12 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return false; } + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } }; #endif diff --git a/src/StdMeshers_I/StdMeshers_Reversible1D_i.cxx b/src/StdMeshers_I/StdMeshers_Reversible1D_i.cxx index 315f30b15..644aa7075 100644 --- a/src/StdMeshers_I/StdMeshers_Reversible1D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_Reversible1D_i.cxx @@ -139,5 +139,46 @@ SMESH::long_array* StdMeshers_Reversible1D_i::GetReversedEdges() ::StdMeshers_Reversible1D* StdMeshers_Reversible1D_i::GetImpl() { - return ( ::StdMeshers_Reversible1D* )myHyp->GetImpl(); + return static_cast<::StdMeshers_Reversible1D* >( myHyp->GetImpl() ); +} + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_Reversible1D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + const ::StdMeshers_Reversible1D* impl = ( const ::StdMeshers_Reversible1D* ) myHyp->GetImpl(); + subIDArray = impl->GetReversedEdges(); + entryArray.push_back( impl->GetObjectEntry() ); + + return true; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_Reversible1D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + std::vector< int > newIDs; + newIDs.reserve( subIDArray.size() ); + + for ( size_t i = 0; i < subIDArray.size(); ++i ) + if ( subIDArray[ i ] > 0 ) + newIDs.push_back( subIDArray[ i ]); + GetImpl()->SetReversedEdges( newIDs ); + + if ( !entryArray.empty() ) + GetImpl()->SetObjectEntry( entryArray[0].c_str() ); + + return true; } diff --git a/src/StdMeshers_I/StdMeshers_Reversible1D_i.hxx b/src/StdMeshers_I/StdMeshers_Reversible1D_i.hxx index 8e24f9102..e80041c88 100644 --- a/src/StdMeshers_I/StdMeshers_Reversible1D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_Reversible1D_i.hxx @@ -36,7 +36,7 @@ #include "StdMeshers_Reversible1D.hxx" // ====================================================== -// Common metrhods of Reversible 1D hypotheses +// Common methods of Reversible 1D hypotheses // ====================================================== class STDMESHERS_I_EXPORT StdMeshers_Reversible1D_i: public virtual POA_StdMeshers::Reversible1D @@ -59,8 +59,17 @@ class STDMESHERS_I_EXPORT StdMeshers_Reversible1D_i: // Get implementation ::StdMeshers_Reversible1D* GetImpl(); + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); private: SMESH_Hypothesis_i* myHyp; }; - #endif diff --git a/src/StdMeshers_I/StdMeshers_SegmentLengthAroundVertex_i.hxx b/src/StdMeshers_I/StdMeshers_SegmentLengthAroundVertex_i.hxx index 30ee53023..c1491a4e1 100644 --- a/src/StdMeshers_I/StdMeshers_SegmentLengthAroundVertex_i.hxx +++ b/src/StdMeshers_I/StdMeshers_SegmentLengthAroundVertex_i.hxx @@ -63,6 +63,16 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const { return 0; } + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) { return true; } protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; diff --git a/src/StdMeshers_I/StdMeshers_StartEndLength_i.cxx b/src/StdMeshers_I/StdMeshers_StartEndLength_i.cxx index aa38fc2ad..622474605 100644 --- a/src/StdMeshers_I/StdMeshers_StartEndLength_i.cxx +++ b/src/StdMeshers_I/StdMeshers_StartEndLength_i.cxx @@ -49,7 +49,8 @@ using namespace std; StdMeshers_StartEndLength_i::StdMeshers_StartEndLength_i( PortableServer::POA_ptr thePOA, ::SMESH_Gen* theGenImpl ) : SALOME::GenericObj_i( thePOA ), - SMESH_Hypothesis_i( thePOA ) + SMESH_Hypothesis_i( thePOA ), + StdMeshers_Reversible1D_i( this ) { myBaseImpl = new ::StdMeshers_StartEndLength( theGenImpl->GetANewId(), theGenImpl ); @@ -132,97 +133,6 @@ CORBA::Double StdMeshers_StartEndLength_i::GetLength( CORBA::Boolean theIsStart) return this->GetImpl()->GetLength( theIsStart ); } -//============================================================================= -/*! - * StdMeshers_StartEndLength_i::SetReversedEdges - * - * Set edges to reverse - */ -//============================================================================= - -void StdMeshers_StartEndLength_i::SetReversedEdges( const SMESH::long_array& theIds ) -{ - ASSERT( myBaseImpl ); - try { - std::vector ids( theIds.length() ); - CORBA::Long iEnd = theIds.length(); - for ( CORBA::Long i = 0; i < iEnd; i++ ) - ids[ i ] = theIds[ i ]; - - this->GetImpl()->SetReversedEdges( ids ); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), - SALOME::BAD_PARAM ); - } - - // Update Python script - SMESH::TPythonDump() << _this() << ".SetReversedEdges( " << theIds << " )"; -} - -//============================================================================= -/*! - * StdMeshers_StartEndLength_i::SetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -void StdMeshers_StartEndLength_i::SetObjectEntry( const char* theEntry ) -{ - ASSERT( myBaseImpl ); - string entry(theEntry); // actually needed as theEntry is spoiled by moment of dumping - try { - this->GetImpl()->SetObjectEntry( entry.c_str() ); - // Update Python script - SMESH::TPythonDump() << _this() << ".SetObjectEntry( '" << entry.c_str() << "' )"; - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(),SALOME::BAD_PARAM ); - } -} - -//============================================================================= -/*! - * StdMeshers_StartEndLength_i::GetObjectEntry - * - * Set the Entry for the Main Object - */ -//============================================================================= - -char* StdMeshers_StartEndLength_i::GetObjectEntry() -{ - ASSERT( myBaseImpl ); - const char* entry; - try { - entry = this->GetImpl()->GetObjectEntry(); - } - catch ( SALOME_Exception& S_ex ) { - THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM ); - } - return CORBA::string_dup( entry ); -} - -//============================================================================= -/*! - * StdMeshers_StartEndLength_i::GetReversedEdges - * - * Get reversed edges - */ -//============================================================================= - -SMESH::long_array* StdMeshers_StartEndLength_i::GetReversedEdges() -{ - ASSERT( myBaseImpl ); - SMESH::long_array_var anArray = new SMESH::long_array; - std::vector ids = this->GetImpl()->GetReversedEdges(); - anArray->length( ids.size() ); - for ( CORBA::ULong i = 0; i < ids.size(); i++) - anArray [ i ] = ids [ i ]; - - return anArray._retn(); -} - //============================================================================= /*! * StdMeshers_StartEndLength_i::GetImpl @@ -261,3 +171,29 @@ std::string StdMeshers_StartEndLength_i::getMethodOfParameter(const int paramInd { return paramIndex == 0 ? "SetStartLength" : "SetEndLength"; } + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_StartEndLength_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + return StdMeshers_Reversible1D_i::getObjectsDependOn( entryArray, subIDArray ); +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_StartEndLength_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + return StdMeshers_Reversible1D_i::setObjectsDependOn( entryArray, subIDArray ); +} diff --git a/src/StdMeshers_I/StdMeshers_StartEndLength_i.hxx b/src/StdMeshers_I/StdMeshers_StartEndLength_i.hxx index 50e989105..24fdb86a7 100644 --- a/src/StdMeshers_I/StdMeshers_StartEndLength_i.hxx +++ b/src/StdMeshers_I/StdMeshers_StartEndLength_i.hxx @@ -34,7 +34,7 @@ #include #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis) -#include "SMESH_Hypothesis_i.hxx" +#include "StdMeshers_Reversible1D_i.hxx" #include "StdMeshers_StartEndLength.hxx" class SMESH_Gen; @@ -44,7 +44,8 @@ class SMESH_Gen; // ====================================================== class STDMESHERS_I_EXPORT StdMeshers_StartEndLength_i: public virtual POA_StdMeshers::StdMeshers_StartEndLength, - public virtual SMESH_Hypothesis_i + public virtual SMESH_Hypothesis_i, + public virtual StdMeshers_Reversible1D_i { public: // Constructor @@ -73,17 +74,16 @@ public: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); - //Set Reversed Edges - void SetReversedEdges( const SMESH::long_array& theIDs); - //Get Reversed Edges - SMESH::long_array* GetReversedEdges(); + // Methods for copying mesh definition to other geometry - //Set Object Entry - void SetObjectEntry( const char* entry); + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; - //Get Object Entry - char* GetObjectEntry(); + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; diff --git a/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.cxx b/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.cxx index 638d03d95..c5877c77f 100644 --- a/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.cxx +++ b/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.cxx @@ -235,13 +235,13 @@ throw ( SALOME::SALOME_Exception ) //================================================================================ /*! - * \brief Verify whether hypothesis supports given entity type - * \param type - dimension (see SMESH::Dimension enumeration) - * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise - * + * \brief Verify whether hypothesis supports given entity type + * \param type - dimension (see SMESH::Dimension enumeration) + * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise + * * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration) */ -//================================================================================ +//================================================================================ CORBA::Boolean StdMeshers_ViscousLayers2D_i::IsDimSupported( SMESH::Dimension type ) { @@ -251,7 +251,7 @@ CORBA::Boolean StdMeshers_ViscousLayers2D_i::IsDimSupported( SMESH::Dimension ty //================================================================================ /*! * \brief Sets sub-mesh event listeners to clear sub-meshes of edges - * shrinked by viscous layers + * shrinked by viscous layers */ //================================================================================ @@ -259,3 +259,43 @@ void StdMeshers_ViscousLayers2D_i::UpdateAsMeshesRestored() { GetImpl()->RestoreListeners(); } + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_ViscousLayers2D_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + const ::StdMeshers_ViscousLayers2D* impl = + static_cast( myBaseImpl ); + + subIDArray = impl->GetBndShapes(); + + return true; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_ViscousLayers2D_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + std::vector< int > newIDs; + newIDs.reserve( subIDArray.size() ); + + for ( size_t i = 0; i < subIDArray.size(); ++i ) + if ( subIDArray[ i ] > 0 ) + newIDs.push_back( subIDArray[ i ]); + + GetImpl()->SetBndShapes( newIDs, GetIsToIgnoreEdges() ); + + return true; +} diff --git a/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.hxx b/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.hxx index 0b28e8597..2ca1310f5 100644 --- a/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.hxx +++ b/src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.hxx @@ -73,6 +73,17 @@ class STDMESHERS_I_EXPORT StdMeshers_ViscousLayers2D_i: // Sets sub-mesh event listeners to clear sub-meshes of edges // shrinked by viscous layers virtual void UpdateAsMeshesRestored(); + + + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); }; #endif diff --git a/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx b/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx index 6ae54c6e8..914d92260 100644 --- a/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx +++ b/src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx @@ -295,3 +295,44 @@ std::string StdMeshers_ViscousLayers_i::getMethodOfParameter(const int paramInde } return ""; } + + +//================================================================================ +/*! + * \brief Return geometry this hypothesis depends on. Return false if there is no geometry parameter + */ +//================================================================================ + +bool +StdMeshers_ViscousLayers_i::getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const +{ + const ::StdMeshers_ViscousLayers* impl = + static_cast( myBaseImpl ); + + subIDArray = impl->GetBndShapes(); + + return true; +} + +//================================================================================ +/*! + * \brief Set new geometry instead of that returned by getObjectsDependOn() + */ +//================================================================================ + +bool +StdMeshers_ViscousLayers_i::setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) +{ + std::vector< int > newIDs; + newIDs.reserve( subIDArray.size() ); + + for ( size_t i = 0; i < subIDArray.size(); ++i ) + if ( subIDArray[ i ] > 0 ) + newIDs.push_back( subIDArray[ i ]); + + GetImpl()->SetBndShapes( newIDs, GetIsToIgnoreFaces() ); + + return true; +} diff --git a/src/StdMeshers_I/StdMeshers_ViscousLayers_i.hxx b/src/StdMeshers_I/StdMeshers_ViscousLayers_i.hxx index 19f5835b0..246a91442 100644 --- a/src/StdMeshers_I/StdMeshers_ViscousLayers_i.hxx +++ b/src/StdMeshers_I/StdMeshers_ViscousLayers_i.hxx @@ -73,6 +73,15 @@ class STDMESHERS_I_EXPORT StdMeshers_ViscousLayers_i: // Verify whether hypothesis supports given entity type CORBA::Boolean IsDimSupported( SMESH::Dimension type ); + // Methods for copying mesh definition to other geometry + + // Return geometry this hypothesis depends on. Return false if there is no geometry parameter + virtual bool getObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ) const; + + // Set new geometry instead of that returned by getObjectsDependOn() + virtual bool setObjectsDependOn( std::vector< std::string > & entryArray, + std::vector< int > & subIDArray ); protected: virtual std::string getMethodOfParameter(const int paramIndex, int nbVars) const; }; -- 2.30.2