From: eap Date: Fri, 10 Jul 2015 16:39:03 +0000 (+0300) Subject: 23081: [CEA 1496] Control merge nodes behaviour: set fixed nodes X-Git-Tag: V7_7_0a1~25 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=de00066f64e01e9028cc5bfc0390911a590a9428 23081: [CEA 1496] Control merge nodes behaviour: set fixed nodes --- diff --git a/doc/salome/examples/transforming_meshes_ex05.py b/doc/salome/examples/transforming_meshes_ex05.py index f99d50b6a..deba1c407 100644 --- a/doc/salome/examples/transforming_meshes_ex05.py +++ b/doc/salome/examples/transforming_meshes_ex05.py @@ -1,10 +1,14 @@ # Merging Nodes -import SMESH_mechanic +import SMESH_mechanic, SMESH mesh = SMESH_mechanic.mesh # merge nodes -Tolerance = 25.0 +Tolerance = 4.0 + +# prevent nodes located on geom edges from removal during merge: +# create a group including all nodes on edges +allSegs = mesh.MakeGroup( "all segments", SMESH.EDGE, SMESH.FT_ElemGeomType,'=', SMESH.Geom_EDGE ) GroupsOfNodes = mesh.FindCoincidentNodes(Tolerance) -mesh.MergeNodes(GroupsOfNodes) +mesh.MergeNodes(GroupsOfNodes, NodesToKeep=allSegs) diff --git a/doc/salome/gui/SMESH/images/mergenodes.png b/doc/salome/gui/SMESH/images/mergenodes.png index 499453d45..ad11a1225 100644 Binary files a/doc/salome/gui/SMESH/images/mergenodes.png and b/doc/salome/gui/SMESH/images/mergenodes.png differ diff --git a/doc/salome/gui/SMESH/images/mergenodes_auto.png b/doc/salome/gui/SMESH/images/mergenodes_auto.png index 625083f4d..99ff0d298 100644 Binary files a/doc/salome/gui/SMESH/images/mergenodes_auto.png and b/doc/salome/gui/SMESH/images/mergenodes_auto.png differ diff --git a/doc/salome/gui/SMESH/images/merging_nodes1.png b/doc/salome/gui/SMESH/images/merging_nodes1.png old mode 100755 new mode 100644 index f64bdcbe2..7913b5eaa Binary files a/doc/salome/gui/SMESH/images/merging_nodes1.png and b/doc/salome/gui/SMESH/images/merging_nodes1.png differ diff --git a/doc/salome/gui/SMESH/images/merging_nodes2.png b/doc/salome/gui/SMESH/images/merging_nodes2.png old mode 100755 new mode 100644 index 8d7cfdd09..e54b6f099 Binary files a/doc/salome/gui/SMESH/images/merging_nodes2.png and b/doc/salome/gui/SMESH/images/merging_nodes2.png differ diff --git a/doc/salome/gui/SMESH/input/merging_nodes.doc b/doc/salome/gui/SMESH/input/merging_nodes.doc index 8e2aa4fad..439e1fea3 100644 --- a/doc/salome/gui/SMESH/input/merging_nodes.doc +++ b/doc/salome/gui/SMESH/input/merging_nodes.doc @@ -26,7 +26,23 @@ merging. nodes. This check-box is enabled provided that the selected mesh includes quadratic elements.
  • Exclude Groups group box allows to ignore the nodes which -belong to the specified mesh groups. +belong to the specified mesh groups.
  • +
  • Nodes to keep group box allows to specify nodes to keep in + the mesh. (By default a node being the first in a group of + coincident nodes is kept.) It is possible to either select nodes in + the Viewer or select groups of any element type whose nodes will be + kept. +
      +
    1. \a Selection button activates selection of nodes to keep.
    2. +
    3. Node IDs button activates selection of nodes in the + Viewer.
    4. +
    5. Groups and Sub-meshes button activates selection of + groups and sub-meshes.
    6. +
    7. \b Add button adds selected nodes or groups to the list.
    8. +
    9. Nodes or groups selected in the list can be removed using \b + Remove button.
    10. +
    +
  • Automatic mode: @@ -77,9 +93,9 @@ nodes of selected groups in the 3D viewer.
  • To confirm your choice click \b Apply or Apply and Close button.
  • -\image html merging_nodes1.png "The initial object" +\image html merging_nodes1.png "The initial object" -\image html merging_nodes2.png "The object has been merged with a very big tolerance" +\image html merging_nodes2.png "The object has been merged"
    See Also a sample TUI Script of a \ref tui_merging_nodes "Merge Nodes" operation. diff --git a/doc/salome/gui/SMESH/input/split_biquad_to_linear.doc b/doc/salome/gui/SMESH/input/split_biquad_to_linear.doc index 85002f949..ea4ac7228 100644 --- a/doc/salome/gui/SMESH/input/split_biquad_to_linear.doc +++ b/doc/salome/gui/SMESH/input/split_biquad_to_linear.doc @@ -10,7 +10,7 @@ So that - bi-quadratic quadrangle will be split into 4 linear quadrangles; - tri-quadratic hexahedron will be split into 8 linear hexahedra; - quadratic segments adjacent to the split bi-quadratic element will - be split into 2 liner segment. + be split into 2 liner segments. \image html split_biquad_to_linear_mesh.png "Mesh before and after splitting" diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 509e9ed8c..57f50fb50 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -658,7 +658,8 @@ module SMESH in boolean SeparateCornersAndMedium) raises (SALOME::SALOME_Exception); - void MergeNodes (in array_of_long_array GroupsOfNodes) + void MergeNodes (in array_of_long_array GroupsOfNodes, + in SMESH::ListOfIDSources NodesToKeep) raises (SALOME::SALOME_Exception); /*! diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index a6e7eddd2..6905e7584 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -1334,7 +1334,7 @@ bool SMESH_Mesh::HasModificationsToDiscard() const // return true if the next Compute() will be partial and // existing but changed elements may prevent successful re-compute bool hasComputed = false, hasNotComputed = false; -SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() ); + SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() ); while ( smIt->more() ) { const SMESH_subMesh* aSubMesh = smIt->next(); diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 54233ac96..8ca7653e0 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -7334,16 +7334,17 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) // Fill nodeNodeMap and elems TListOfListOfNodes::iterator grIt = theGroupsOfNodes.begin(); - for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) { + for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) + { list& nodes = *grIt; list::iterator nIt = nodes.begin(); const SMDS_MeshNode* nToKeep = *nIt; - //MESSAGE("node to keep " << nToKeep->GetID()); - for ( ++nIt; nIt != nodes.end(); nIt++ ) { + for ( ++nIt; nIt != nodes.end(); nIt++ ) + { const SMDS_MeshNode* nToRemove = *nIt; - nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep )); - if ( nToRemove != nToKeep ) { - //MESSAGE(" node to remove " << nToRemove->GetID()); + nodeNodeMap.insert( make_pair( nToRemove, nToKeep )); + if ( nToRemove != nToKeep ) + { rmNodeIds.push_back( nToRemove->GetID() ); AddToSameGroups( nToKeep, nToRemove, aMesh ); // set _alwaysComputed to a sub-mesh of VERTEX to enable mesh computing @@ -7353,7 +7354,6 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() )) sm->SetIsAlwaysComputed( true ); } - SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator(); while ( invElemIt->more() ) { const SMDS_MeshElement* elem = invElemIt->next(); diff --git a/src/SMESHGUI/SMESHGUI_MergeDlg.cxx b/src/SMESHGUI/SMESHGUI_MergeDlg.cxx index 5c62beb67..d084d32b1 100644 --- a/src/SMESHGUI/SMESHGUI_MergeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MergeDlg.cxx @@ -95,7 +95,7 @@ namespace { - enum ActionType { MERGE_NODES, MERGE_ELEMENTS }; + enum ActionType { MERGE_NODES, MERGE_ELEMENTS, TYPE_AUTO=0, TYPE_MANUAL }; } namespace SMESH { @@ -363,7 +363,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) GroupMeshLayout->addWidget(LineEditMesh); /***************************************************************/ - // Controls for switch dialog behaviour + // Controls for switch dialog behaviour (myTypeId) TypeBox = new QGroupBox( tr( "SMESH_MODE" ), this ); GroupType = new QButtonGroup( this ); @@ -378,7 +378,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) aTypeBoxLayout->addWidget( rb1 ); aTypeBoxLayout->addWidget( rb2 ); - myTypeId = 0; + myTypeId = TYPE_AUTO; /***************************************************************/ // Controls for coincident elements detecting @@ -410,6 +410,32 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) GroupExcludeLayout->setMargin(MARGIN); GroupExcludeLayout->addWidget(ListExclude); + QGroupBox* GroupKeep = new QGroupBox(tr("KEEP_NODES"), foo); + SelectKeepNodesButton = new QPushButton( GroupKeep ); + SelectKeepNodesButton->setIcon( IconSelect ); + QLabel* selectLabel = new QLabel(tr("SELECT")); + QRadioButton* idsButton = new QRadioButton(tr("NODE_IDS"), GroupKeep); + QRadioButton* groupButton = new QRadioButton(tr("GROUP_SUBMESH"), GroupKeep); + KeepFromButGroup = new QButtonGroup( this ); + KeepFromButGroup->addButton( idsButton, 0 ); + KeepFromButGroup->addButton( groupButton, 1 ); + groupButton->setChecked( true ); + KeepList = new QListWidget( GroupKeep ); + KeepList->setSelectionMode(QAbstractItemView::ExtendedSelection); + KeepList->setFlow(QListView::TopToBottom); + AddKeepNodesButton = new QPushButton(tr("SMESH_BUT_ADD"), GroupKeep ); + RemoveKeepNodesButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupKeep ); + QGridLayout* GroupKeepLayout = new QGridLayout(GroupKeep); + GroupKeepLayout->setSpacing( SPACING ); + GroupKeepLayout->setMargin ( MARGIN ); + GroupKeepLayout->addWidget( SelectKeepNodesButton, 0, 0 ); + GroupKeepLayout->addWidget( selectLabel, 0, 1 ); + GroupKeepLayout->addWidget( idsButton, 0, 2 ); + GroupKeepLayout->addWidget( groupButton, 0, 3, 1, 2 ); + GroupKeepLayout->addWidget( KeepList, 1, 0, 2, 4 ); + GroupKeepLayout->addWidget( AddKeepNodesButton, 1, 4, 1, 1 ); + GroupKeepLayout->addWidget( RemoveKeepNodesButton, 2, 4, 1, 1 ); + QGridLayout* fooLayout = new QGridLayout( foo ); fooLayout->setSpacing(SPACING); fooLayout->setMargin(0); @@ -417,13 +443,27 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) fooLayout->addWidget(SpinBoxTolerance, 0, 1 ); fooLayout->addWidget(SeparateCornersAndMedium, 1, 0 ); fooLayout->addWidget(GroupExclude, 2, 0, 1, 2 ); + fooLayout->addWidget(GroupKeep, 3, 0, 1, 2 ); aCoincidentLayout->addWidget(foo); + + // Costruction of the logical filter + QList aListOfFilters; + aListOfFilters << new SMESH_TypeFilter (SMESH::SUBMESH) + << new SMESH_TypeFilter (SMESH::GROUP); + mySubMeshOrGroupFilter = + new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR, /*takeOwnership=*/true); } else { - TextLabelTolerance = 0; - SpinBoxTolerance = 0; - GroupExclude = 0; - ListExclude = 0; + TextLabelTolerance = 0; + SpinBoxTolerance = 0; + GroupExclude = 0; + ListExclude = 0; + KeepFromButGroup = 0; + SelectKeepNodesButton = 0; + AddKeepNodesButton = 0; + RemoveKeepNodesButton = 0; + KeepList = 0; + mySubMeshOrGroupFilter = 0; } GroupCoincidentWidget = new QWidget(GroupCoincident); @@ -546,7 +586,7 @@ void SMESHGUI_MergeDlg::Init() GroupType->button(0)->setChecked(true); - myEditCurrentArgument = (QWidget*)LineEditMesh; + myEditCurrentArgument = (QWidget*)LineEditMesh; myActor = 0; mySubMeshOrGroup = SMESH::SMESH_subMesh::_nil(); @@ -555,13 +595,21 @@ void SMESHGUI_MergeDlg::Init() mySMESHGUI->SetActiveDialogBox((QDialog*)this); myIsBusy = false; - + /* signals and slots connections */ connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk())); connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); connect(buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnApply())); connect(buttonHelp, SIGNAL(clicked()), this, SLOT(ClickOnHelp())); + if ( KeepList ) + { + connect(SelectKeepNodesButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument())); + connect(KeepFromButGroup, SIGNAL (buttonClicked(int)), SLOT(onKeepNodeSourceChanged(int))); + connect(AddKeepNodesButton, SIGNAL (clicked()), this, SLOT(onAddKeepNode())); + connect(RemoveKeepNodesButton, SIGNAL (clicked()), this, SLOT(onRemoveKeepNode())); + connect(KeepList, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectKeepNode())); + } connect(SelectMeshButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument())); connect(DetectButton, SIGNAL (clicked()), this, SLOT(onDetect())); connect(ListCoincident, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectGroup())); @@ -572,7 +620,7 @@ void SMESHGUI_MergeDlg::Init() connect(ListEdit, SIGNAL (itemSelectionChanged()), this, SLOT(onSelectElementFromGroup())); connect(AddElemButton, SIGNAL (clicked()), this, SLOT(onAddElement())); connect(RemoveElemButton, SIGNAL (clicked()), this, SLOT(onRemoveElement())); - connect(SetFirstButton, SIGNAL( clicked() ), this, SLOT( onSetFirst() ) ); + connect(SetFirstButton, SIGNAL( clicked() ), this, SLOT( onSetFirst())); connect(GroupType, SIGNAL(buttonClicked(int)), this, SLOT(onTypeChanged(int))); connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog())); @@ -638,7 +686,7 @@ bool SMESHGUI_MergeDlg::ClickOnApply() return false; try { - if (myTypeId == 0) + if (myTypeId == TYPE_AUTO) onDetect(); SUIT_OverrideCursor aWaitCursor; @@ -672,12 +720,51 @@ bool SMESHGUI_MergeDlg::ClickOnApply() aGroupsOfElements[anArrayNum++] = anIds.inout(); } + SMESH::ListOfIDSources_var nodesToKeep; + SMESH::IDSource_wrap tmpIdSource; + if ( myAction == MERGE_NODES ) + { + nodesToKeep = new SMESH::ListOfIDSources(); + int i, nb = KeepList->count(); + if ( isKeepNodesIDsSelection() ) + { + SMESH::long_array_var anIdList = new SMESH::long_array(); + anIdList->length(nb); + for (i = 0; i < nb; i++) + anIdList[i] = KeepList->item(i)->text().toInt(); + + if ( nb > 0 ) + { + tmpIdSource = aMeshEditor->MakeIDSource( anIdList, SMESH::NODE ); + nodesToKeep->length( 1 ); + nodesToKeep[0] = SMESH::SMESH_IDSource::_duplicate( tmpIdSource.in() ); + } + } + else + { + nodesToKeep->length( nb ); + int nbObj = 0; + for (i = 0; i < nb; i++) + { + QString entry = KeepList->item( i )->data( Qt::UserRole ).toString(); + Handle(SALOME_InteractiveObject) anIO = + new SALOME_InteractiveObject( entry.toStdString().c_str(), "SMESH" ); + SMESH::SMESH_IDSource_var idSrc = + SMESH::IObjectToInterface( anIO ); + if ( !idSrc->_is_nil() ) + nodesToKeep[ nbObj++ ] = SMESH::SMESH_IDSource::_duplicate( idSrc ); + } + nodesToKeep->length( nbObj ); + } + KeepList->clear(); + } + if( myAction == MERGE_NODES ) - aMeshEditor->MergeNodes (aGroupsOfElements.inout()); + aMeshEditor->MergeNodes (aGroupsOfElements.inout(), nodesToKeep); else aMeshEditor->MergeElements (aGroupsOfElements.inout()); - if ( myTypeId == 0 ) { + if ( myTypeId == TYPE_AUTO ) { if (myAction == MERGE_NODES ) SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"), tr("SMESH_MERGED_NODES").arg(QString::number(ListCoincident->count()).toLatin1().data())); @@ -685,18 +772,19 @@ bool SMESHGUI_MergeDlg::ClickOnApply() SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"), tr("SMESH_MERGED_ELEMENTS").arg(QString::number(ListCoincident->count()).toLatin1().data())); } - + nodesToKeep->length(0); // release before tmpIdSource calls UnRegister() - } catch(...) { } - + catch(...) { + } + ListCoincident->clear(); - + myEditCurrentArgument = (QWidget*)LineEditMesh; SMESH::UpdateView(); SMESHGUI::Modified(); - + return true; } @@ -810,7 +898,7 @@ void SMESHGUI_MergeDlg::updateControls() { if (ListEdit->count() == 0) SetFirstButton->setEnabled(false); - bool enable = !(myMesh->_is_nil()) && (ListCoincident->count() || (myTypeId == 0)); + bool enable = !(myMesh->_is_nil()) && (ListCoincident->count() || (myTypeId == TYPE_AUTO)); buttonOk->setEnabled(enable); buttonApply->setEnabled(enable); DetectButton->setEnabled( !myMesh->_is_nil() ); @@ -823,6 +911,13 @@ void SMESHGUI_MergeDlg::updateControls() myMesh->NbVolumesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 )); SeparateCornersAndMedium->setEnabled( has2ndOrder ); + + if ( myEditCurrentArgument != KeepList ) + { + AddKeepNodesButton->setEnabled( false ); + RemoveKeepNodesButton->setEnabled( false ); + KeepList->clearSelection(); + } } } @@ -1149,14 +1244,32 @@ void SMESHGUI_MergeDlg::SetEditCurrentArgument() mySelectionMgr->clearSelected(); mySelectionMgr->clearFilters(); - if (send == SelectMeshButton) { + if (send == SelectMeshButton) + { myEditCurrentArgument = (QWidget*)LineEditMesh; SMESH::SetPointRepresentation(false); if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) aViewWindow->SetSelectionMode(ActorSelection); - if (myTypeId == 1) + if (myTypeId == TYPE_MANUAL) mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter); } + else if ( send == SelectKeepNodesButton && send ) + { + myEditCurrentArgument = (QWidget*)KeepList; + KeepList->setWrapping( isKeepNodesIDsSelection() ); + if ( isKeepNodesIDsSelection() ) + { + SMESH::SetPointRepresentation( true ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( NodeSelection ); + } + else + { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( ActorSelection ); + mySelectionMgr->installFilter( mySubMeshOrGroupFilter ); + } + } myEditCurrentArgument->setFocus(); connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument())); @@ -1165,11 +1278,12 @@ void SMESHGUI_MergeDlg::SetEditCurrentArgument() //================================================================================= // function : SelectionIntoArgument() -// purpose : Called when selection as changed or other case +// purpose : Called when selection has changed or other case //================================================================================= void SMESHGUI_MergeDlg::SelectionIntoArgument() { - if (myEditCurrentArgument == (QWidget*)LineEditMesh) { + if (myEditCurrentArgument == (QWidget*)LineEditMesh) + { QString aString = ""; LineEditMesh->setText(aString); @@ -1196,6 +1310,9 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument() myEntry = IO->getEntry(); myMesh = SMESH::GetMeshByIO(IO); + if ( myEntry != aCurrentEntry && KeepList ) + KeepList->clear(); + if (myMesh->_is_nil()) return; @@ -1205,7 +1322,7 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument() if (!myActor) myActor = SMESH::FindActorByObject(myMesh); - if ( myActor && myTypeId == 1 && mySelector->IsSelectionEnabled() ) { + if ( myActor && myTypeId == TYPE_MANUAL && mySelector->IsSelectionEnabled() ) { mySubMeshOrGroup = SMESH::SMESH_IDSource::_nil(); mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter); @@ -1246,6 +1363,59 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument() updateControls(); } + + else if (myEditCurrentArgument == (QWidget*)KeepList && KeepList) + { + AddKeepNodesButton->setEnabled( false ); + RemoveKeepNodesButton->setEnabled( false ); + if ( isKeepNodesIDsSelection() ) + { + if (!myMesh->_is_nil() && !myActor) + myActor = SMESH::FindActorByObject(myMesh); + + if ( mySelector && myActor ) + { + KeepList->clearSelection(); + QString anIDs = ""; + int aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs); + if (aNbNodes > 0) + { + QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts); + QList listItemsToSel; + QListWidgetItem* anItem; + int nbFound = 0; + for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it) + { + QList found = KeepList->findItems(*it, Qt::MatchExactly); + foreach(anItem, found) + if (!anItem->isSelected()) + listItemsToSel.push_back(anItem); + nbFound += found.count(); + } + bool blocked = KeepList->signalsBlocked(); + KeepList->blockSignals(true); + foreach(anItem, listItemsToSel) anItem->setSelected(true); + KeepList->blockSignals(blocked); + //onSelectKeepNode(); + AddKeepNodesButton->setEnabled( nbFound < aNbNodes ); + RemoveKeepNodesButton->setEnabled( nbFound > 0 ); + } + } + } + else if ( !myMesh->_is_nil() ) + { + SALOME_ListIO aList; + mySelectionMgr->selectedObjects(aList); + bool hasNewSelected = false; + SALOME_ListIteratorOfListIO anIt (aList); + for ( ; anIt.More() && !hasNewSelected; anIt.Next()) + if ( anIt.Value()->hasEntry() ) + hasNewSelected = isNewKeepNodesGroup( anIt.Value()->getEntry() ); + + AddKeepNodesButton->setEnabled( hasNewSelected ); + //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() ); + } + } } //================================================================================= @@ -1332,7 +1502,8 @@ void SMESHGUI_MergeDlg::onTypeChanged (int id) myTypeId = id; switch (id) { - case 0: // automatic + case TYPE_AUTO: // automatic + myIdPreview->SetPointsLabeled(false); SMESH::SetPointRepresentation(false); if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) @@ -1345,7 +1516,8 @@ void SMESHGUI_MergeDlg::onTypeChanged (int id) GroupEdit->hide(); break; - case 1: // manual + case TYPE_MANUAL: // manual + SMESH::UpdateView(); // Costruction of the logical filter @@ -1383,3 +1555,168 @@ void SMESHGUI_MergeDlg::onTypeChanged (int id) SelectionIntoArgument(); } + +//======================================================================= +//function : isKeepNodesIDsSelection +//purpose : Return true of Nodes to keep are selected by IDs +//======================================================================= + +bool SMESHGUI_MergeDlg::isKeepNodesIDsSelection() +{ + return KeepFromButGroup && KeepFromButGroup->checkedId() == 0; +} + +//======================================================================= +//function : isNewKeepNodesGroup +//purpose : Return true if an object with given entry is NOT present in KeepList +//======================================================================= + +bool SMESHGUI_MergeDlg::isNewKeepNodesGroup( const char* entry ) +{ + if ( !entry || isKeepNodesIDsSelection() ) + return false; + + for ( int i = 0; i < KeepList->count(); i++ ) + if ( KeepList->item( i )->data( Qt::UserRole ).toString() == entry ) + return false; + + return true; +} + +//======================================================================= +//function : onAddKeepNode +//purpose : SLOT called when [Add] of Nodes To Keep group is pressed +//======================================================================= + +void SMESHGUI_MergeDlg::onAddKeepNode() +{ + if ( myIsBusy ) + return; + myIsBusy = true; + + if ( isKeepNodesIDsSelection() ) + { + //KeepList->clearSelection(); + QString anIDs = ""; + int aNbNodes = 0; + if ( myActor ) + aNbNodes = SMESH::GetNameOfSelectedNodes(mySelector, myActor->getIO(), anIDs); + if (aNbNodes > 0) + { + QStringList anNodes = anIDs.split( " ", QString::SkipEmptyParts); + QList listItemsToSel; + QListWidgetItem* anItem; + for (QStringList::iterator it = anNodes.begin(); it != anNodes.end(); ++it) + { + QList found = KeepList->findItems(*it, Qt::MatchExactly); + if (found.count() == 0) { + anItem = new QListWidgetItem(*it); + KeepList->addItem(anItem); + if (!anItem->isSelected()) + listItemsToSel.push_back(anItem); + } + else { + foreach(anItem, found) + if (!anItem->isSelected()) + listItemsToSel.push_back(anItem); + } + } + bool blocked = KeepList->signalsBlocked(); + KeepList->blockSignals(true); + foreach(anItem, listItemsToSel) anItem->setSelected(true); + KeepList->blockSignals(blocked); + //onSelectKeepNode(); + } + RemoveKeepNodesButton->setEnabled( aNbNodes > 0 ); + } + else + { + SALOME_ListIO aList; + mySelectionMgr->selectedObjects(aList); + SALOME_ListIteratorOfListIO anIt (aList); + for ( ; anIt.More(); anIt.Next()) { + Handle(SALOME_InteractiveObject) anIO = anIt.Value(); + if ( isNewKeepNodesGroup( anIO->getEntry() )) + { + QListWidgetItem* anItem = new QListWidgetItem( anIO->getName() ); + anItem->setData( Qt::UserRole, QString( anIO->getEntry() )); + KeepList->addItem(anItem); + } + } + //RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() ); + } + + AddKeepNodesButton->setEnabled( false ); + + myIsBusy = false; +} + +//======================================================================= +//function : onRemoveKeepNode +//purpose : SLOT called when [Remove] of Nodes To Keep group is pressed +//======================================================================= + +void SMESHGUI_MergeDlg::onRemoveKeepNode() +{ + // if ( isKeepNodesIDsSelection() ) + // { + // } + // else + { + QList selItems = KeepList->selectedItems(); + QListWidgetItem* item; + foreach(item, selItems) delete item; + } + if ( isKeepNodesIDsSelection() ) + { + AddKeepNodesButton->setEnabled( false ); + } + RemoveKeepNodesButton->setEnabled( false ); +} + +//======================================================================= +//function : onSelectKeepNode +//purpose : SLOT called when selection in KeepList changes +//======================================================================= + +void SMESHGUI_MergeDlg::onSelectKeepNode() +{ + if ( myIsBusy || !isEnabled() ) return; + myIsBusy = true; + + if ( isKeepNodesIDsSelection() ) + { + if ( myActor ) + { + mySelectionMgr->clearSelected(); + TColStd_MapOfInteger aIndexes; + QList selItems = KeepList->selectedItems(); + QListWidgetItem* anItem; + foreach(anItem, selItems) aIndexes.Add(anItem->text().toInt()); + mySelector->AddOrRemoveIndex(myActor->getIO(), aIndexes, false); + SALOME_ListIO aList; + aList.Append(myActor->getIO()); + mySelectionMgr->setSelectedObjects(aList,false); + + AddKeepNodesButton->setEnabled( false ); + RemoveKeepNodesButton->setEnabled( aIndexes.Extent() > 0 ); + } + } + else + { + RemoveKeepNodesButton->setEnabled( KeepList->selectedItems().count() ); + } + myIsBusy = false; +} + +//======================================================================= +//function : onKeepNodeSourceChanged +//purpose : SLOT called when type of source of Nodes To Keep change from +// IDs to groups or vice versa +//======================================================================= + +void SMESHGUI_MergeDlg::onKeepNodeSourceChanged(int isGroup) +{ + KeepList->clear(); + SelectKeepNodesButton->click(); +} diff --git a/src/SMESHGUI/SMESHGUI_MergeDlg.h b/src/SMESHGUI/SMESHGUI_MergeDlg.h index 7e777ea43..754dde0f0 100644 --- a/src/SMESHGUI/SMESHGUI_MergeDlg.h +++ b/src/SMESHGUI/SMESHGUI_MergeDlg.h @@ -81,6 +81,8 @@ private: void enterEvent( QEvent* ); /* mouse enter the QWidget */ void keyPressEvent( QKeyEvent* ); void onEditGroup(); + bool isKeepNodesIDsSelection(); + bool isNewKeepNodesGroup( const char* entry ); void FindGravityCenter( TColStd_MapOfInteger&, std::list& ); @@ -99,12 +101,13 @@ private: SMESH::SMESH_IDSource_var mySubMeshOrGroup; SMESH_Actor* myActor; SUIT_SelectionFilter* myMeshOrSubMeshOrGroupFilter; + SUIT_SelectionFilter* mySubMeshOrGroupFilter; SMESH::TIdPreview* myIdPreview; int myAction; bool myIsBusy; - int myTypeId; + int myTypeId; // manual(1) or automatic(0) // Widgets QGroupBox* GroupConstructors; @@ -142,6 +145,12 @@ private: QGroupBox* GroupExclude; QListWidget* ListExclude; + QButtonGroup* KeepFromButGroup; + QPushButton* SelectKeepNodesButton; + QPushButton* AddKeepNodesButton; + QPushButton* RemoveKeepNodesButton; + QListWidget* KeepList; + QGroupBox* TypeBox; QButtonGroup* GroupType; @@ -159,6 +168,10 @@ protected slots: void ClickOnHelp(); void updateControls(); void onDetect(); + void onAddKeepNode(); + void onRemoveKeepNode(); + void onSelectKeepNode(); + void onKeepNodeSourceChanged(int); void onAddGroup(); void onRemoveGroup(); void onSelectGroup(); diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 3bdd72e93..8eb62658c 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -5143,6 +5143,22 @@ Please select a group and try again SEPARATE_CORNERS_AND_MEDIUM No merge of corner and medium nodes + + KEEP_NODES + Nodes to keep + + + GROUP_SUBMESH + Groups and Sub-meshes + + + SELECT + Select: + + + + + SMESHGUI_ExtrusionAlongPathDlg diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index c0e4963cc..1c6f60200 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -4113,7 +4113,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr theObject, //purpose : //======================================================================= -void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes) +void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes, + const SMESH::ListOfIDSources& NodesToKeep) throw (SALOME::SALOME_Exception) { SMESH_TRY; @@ -4123,6 +4124,16 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN TPythonDump aTPythonDump; aTPythonDump << this << ".MergeNodes(["; + + TIDSortedNodeSet setOfNodesToKeep; + for ( int i = 0; i < NodesToKeep.length(); ++i ) + { + prepareIdSource( NodesToKeep[i] ); + SMDS_ElemIteratorPtr nodeIt = myMesh_i->GetElements( NodesToKeep[i], SMESH::NODE ); + while ( nodeIt->more() ) + setOfNodesToKeep.insert( setOfNodesToKeep.end(), cast2Node( nodeIt->next() )); + } + ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; for (int i = 0; i < GroupsOfNodes.length(); i++) { @@ -4132,9 +4143,13 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN for ( int j = 0; j < aNodeGroup.length(); j++ ) { CORBA::Long index = aNodeGroup[ j ]; - const SMDS_MeshNode * node = aMesh->FindNode(index); - if ( node ) - aListOfNodes.push_back( node ); + if ( const SMDS_MeshNode * node = aMesh->FindNode( index )) + { + if ( setOfNodesToKeep.count( node )) + aListOfNodes.push_front( node ); + else + aListOfNodes.push_back( node ); + } } if ( aListOfNodes.size() < 2 ) aListOfListOfNodes.pop_back(); @@ -4142,9 +4157,10 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN if ( i > 0 ) aTPythonDump << ", "; aTPythonDump << aNodeGroup; } + getEditor().MergeNodes( aListOfListOfNodes ); - aTPythonDump << "])"; + aTPythonDump << "], " << NodesToKeep << ")"; declareMeshModified( /*isReComputeSafe=*/false ); diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index 560afae05..97fe0ba88 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -488,7 +488,8 @@ public: const SMESH::ListOfIDSources& ExceptSubMeshOrGroups, CORBA::Boolean SeparateCornersAndMedium) throw (SALOME::SALOME_Exception); - void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes) + void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes, + const SMESH::ListOfIDSources& NodesToKeep ) throw (SALOME::SALOME_Exception); void FindEqualElements(SMESH::SMESH_IDSource_ptr Object, SMESH::array_of_long_array_out GroupsOfElementsID) diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 3e3b6750d..5610d35ec 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -1609,6 +1609,8 @@ class Mesh: # @return SMESH.Hypothesis_Status # @ingroup l2_hypotheses def AddHypothesis(self, hyp, geom=0): + if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ): + hyp, geom = geom, hyp if isinstance( hyp, Mesh_Algorithm ): hyp = hyp.GetAlgorithm() pass @@ -4428,9 +4430,18 @@ class Mesh: # @param GroupsOfNodes a list of groups of nodes IDs for merging # (e.g. [[1,12,13],[25,4]], then nodes 12, 13 and 4 will be removed and replaced # by nodes 1 and 25 correspondingly in all elements and groups + # @param NodesToKeep nodes to keep in the mesh: a list of groups, sub-meshes or node IDs. + # If @a NodesToKeep does not include a node to keep for some group to merge, + # then the first node in the group is kept. # @ingroup l2_modif_trsf - def MergeNodes (self, GroupsOfNodes): - self.editor.MergeNodes(GroupsOfNodes) + def MergeNodes (self, GroupsOfNodes, NodesToKeep=[]): + unRegister = genObjUnRegister() + if NodesToKeep: + if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ): + NodesToKeep = self.GetIDSource( NodesToKeep, SMESH.NODE ) + if not isinstance( NodesToKeep, list ): + NodesToKeep = [ NodesToKeep ] + self.editor.MergeNodes(GroupsOfNodes,NodesToKeep) ## Finds the elements built on the same nodes. # @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching