From: eap Date: Wed, 1 Jul 2015 11:59:24 +0000 (+0300) Subject: 23080: [CEA 1497] Do not merge a middle node in quadratic with the extreme nodes... X-Git-Tag: V7_7_0a1~29 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=b22e182dd1a2c30be324b21074158390d00714b3;hp=fe7d1d57677486d8c546226dc2bf573fbfb6679d 23080: [CEA 1497] Do not merge a middle node in quadratic with the extreme nodes of a segment --- diff --git a/doc/salome/gui/SMESH/images/mergenodes.png b/doc/salome/gui/SMESH/images/mergenodes.png old mode 100755 new mode 100644 index 05286a56e..499453d45 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 6a2a92830..625083f4d 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/input/merging_nodes.doc b/doc/salome/gui/SMESH/input/merging_nodes.doc index 3f713efda..8e2aa4fad 100644 --- a/doc/salome/gui/SMESH/input/merging_nodes.doc +++ b/doc/salome/gui/SMESH/input/merging_nodes.doc @@ -21,6 +21,10 @@ then converted to the single node. processed.
  • \b Tolerance is a maximum distance between nodes sufficient for merging.
  • +
  • Activation of No merge of corner and medium nodes check-box + prevents merging medium nodes of quadratic elements with corner + 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. diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 3cdbea8bf..0b4321172 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -609,41 +609,44 @@ module SMESH in AxisStruct Axis, in double AngleInRadians, in boolean CopyGroups, - in string MeshName) + in string MeshName) raises (SALOME::SALOME_Exception); void RotateObject (in SMESH_IDSource theObject, in AxisStruct Axis, in double AngleInRadians, - in boolean Copy) + in boolean Copy) raises (SALOME::SALOME_Exception); ListOfGroups RotateObjectMakeGroups (in SMESH_IDSource theObject, in AxisStruct Axis, - in double AngleInRadians) + in double AngleInRadians) raises (SALOME::SALOME_Exception); SMESH_Mesh RotateObjectMakeMesh (in SMESH_IDSource theObject, in AxisStruct Axis, in double AngleInRadians, in boolean CopyGroups, - in string MeshName) + in string MeshName) raises (SALOME::SALOME_Exception); void FindCoincidentNodes (in double Tolerance, - out array_of_long_array GroupsOfNodes) + out array_of_long_array GroupsOfNodes, + in boolean SeparateCornersAndMedium) raises (SALOME::SALOME_Exception); void FindCoincidentNodesOnPart (in SMESH_IDSource SubMeshOrGroup, in double Tolerance, - out array_of_long_array GroupsOfNodes) + out array_of_long_array GroupsOfNodes, + in boolean SeparateCornersAndMedium) raises (SALOME::SALOME_Exception); void FindCoincidentNodesOnPartBut (in SMESH_IDSource SubMeshOrGroup, in double Tolerance, out array_of_long_array GroupsOfNodes, - in ListOfIDSources ExceptSubMeshOrGroups) + in ListOfIDSources ExceptSubMeshOrGroups, + in boolean SeparateCornersAndMedium) raises (SALOME::SALOME_Exception); - void MergeNodes (in array_of_long_array GroupsOfNodes) + void MergeNodes (in array_of_long_array GroupsOfNodes) raises (SALOME::SALOME_Exception); /*! diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 18666319f..fc945c44e 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -6983,27 +6983,67 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, //================================================================================ /*! - * \brief Return list of group of nodes close to each other within theTolerance - * Search among theNodes or in the whole mesh if theNodes is empty using - * an Octree algorithm + * * \brief Return list of group of nodes close to each other within theTolerance + * * Search among theNodes or in the whole mesh if theNodes is empty using + * * an Octree algorithm + * \param [in,out] theNodes - the nodes to treat + * \param [in] theTolerance - the tolerance + * \param [out] theGroupsOfNodes - the result groups of coincident nodes + * \param [in] theSeparateCornersAndMedium - if \c true, in quadratic mesh puts + * corner and medium nodes in separate groups */ //================================================================================ void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet & theNodes, const double theTolerance, - TListOfListOfNodes & theGroupsOfNodes) + TListOfListOfNodes & theGroupsOfNodes, + bool theSeparateCornersAndMedium) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - if ( theNodes.empty() ) - { // get all nodes in the mesh + if ( myMesh->NbEdges ( ORDER_QUADRATIC ) + + myMesh->NbFaces ( ORDER_QUADRATIC ) + + myMesh->NbVolumes( ORDER_QUADRATIC ) == 0 ) + theSeparateCornersAndMedium = false; + + TIDSortedNodeSet& corners = theNodes; + TIDSortedNodeSet medium; + + if ( theNodes.empty() ) // get all nodes in the mesh + { + TIDSortedNodeSet* nodes[2] = { &corners, &medium }; SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(/*idInceasingOrder=*/true); - while ( nIt->more() ) - theNodes.insert( theNodes.end(),nIt->next()); + if ( theSeparateCornersAndMedium ) + while ( nIt->more() ) + { + const SMDS_MeshNode* n = nIt->next(); + TIDSortedNodeSet* & nodeSet = nodes[ SMESH_MesherHelper::IsMedium( n )]; + nodeSet->insert( nodeSet->end(), n ); + } + else + while ( nIt->more() ) + theNodes.insert( theNodes.end(),nIt->next() ); + } + else if ( theSeparateCornersAndMedium ) // separate corners from medium nodes + { + TIDSortedNodeSet::iterator nIt = corners.begin(); + while ( nIt != corners.end() ) + if ( SMESH_MesherHelper::IsMedium( *nIt )) + { + medium.insert( medium.end(), *nIt ); + corners.erase( nIt++ ); + } + else + { + ++nIt; + } } - SMESH_OctreeNode::FindCoincidentNodes ( theNodes, &theGroupsOfNodes, theTolerance); + if ( !corners.empty() ) + SMESH_OctreeNode::FindCoincidentNodes ( corners, &theGroupsOfNodes, theTolerance ); + if ( !medium.empty() ) + SMESH_OctreeNode::FindCoincidentNodes ( medium, &theGroupsOfNodes, theTolerance ); } //======================================================================= @@ -7763,7 +7803,7 @@ void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet & theElements, { // get all elements in the mesh SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator(); while ( eIt->more() ) - theElements.insert( theElements.end(), eIt->next()); + theElements.insert( theElements.end(), eIt->next() ); } vector< TGroupOfElems > arrayOfGroups; @@ -7771,31 +7811,32 @@ void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet & theElements, TMapOfNodeSet mapOfNodeSet; TIDSortedElemSet::iterator elemIt = theElements.begin(); - for ( int i = 0, j=0; elemIt != theElements.end(); ++elemIt, ++j ) { + for ( int i = 0; elemIt != theElements.end(); ++elemIt ) + { const SMDS_MeshElement* curElem = *elemIt; SortableElement SE(curElem); - int ind = -1; // check uniqueness pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i)); - if( !(pp.second) ) { + if ( !pp.second ) { // one more coincident elem TMapOfNodeSet::iterator& itSE = pp.first; - ind = (*itSE).second; - arrayOfGroups[ind].push_back(curElem->GetID()); + int ind = (*itSE).second; + arrayOfGroups[ind].push_back( curElem->GetID() ); } else { - groupOfElems.clear(); - groupOfElems.push_back(curElem->GetID()); - arrayOfGroups.push_back(groupOfElems); + arrayOfGroups.push_back( groupOfElems ); + arrayOfGroups.back().push_back( curElem->GetID() ); i++; } } + groupOfElems.clear(); vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin(); - for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) { - groupOfElems = *groupIt; - if ( groupOfElems.size() > 1 ) { - groupOfElems.sort(); - theGroupsOfElementsID.push_back(groupOfElems); + for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) + { + if ( groupIt->size() > 1 ) { + //groupOfElems.sort(); -- theElements is sorted already + theGroupsOfElementsID.push_back( groupOfElems ); + theGroupsOfElementsID.back().splice( theGroupsOfElementsID.back().end(), *groupIt ); } } } diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index cbe9466de..1dbed7d99 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -440,7 +440,8 @@ public: void FindCoincidentNodes (TIDSortedNodeSet & theNodes, const double theTolerance, - TListOfListOfNodes & theGroupsOfNodes); + TListOfListOfNodes & theGroupsOfNodes, + bool theSeparateCornersAndMedium); // Return list of group of nodes close to each other within theTolerance. // Search among theNodes or in the whole mesh if theNodes is empty. diff --git a/src/SMESHGUI/SMESHGUI_MergeDlg.cxx b/src/SMESHGUI/SMESHGUI_MergeDlg.cxx index 1a37b7760..5c62beb67 100644 --- a/src/SMESHGUI/SMESHGUI_MergeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_MergeDlg.cxx @@ -93,6 +93,10 @@ #define SPACING 6 #define MARGIN 11 +namespace +{ + enum ActionType { MERGE_NODES, MERGE_ELEMENTS }; +} namespace SMESH { class TIdPreview @@ -307,7 +311,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) { setModal(false); setAttribute(Qt::WA_DeleteOnClose, true); - setWindowTitle(myAction == 1 ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES")); + setWindowTitle(myAction == MERGE_ELEMENTS ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES")); myIdPreview = new SMESH::TIdPreview(SMESH::GetViewWindow( mySMESHGUI )); @@ -325,7 +329,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) DlgLayout->setMargin(MARGIN); /***************************************************************/ - GroupConstructors = new QGroupBox(myAction == 1 ? + GroupConstructors = new QGroupBox(myAction == MERGE_ELEMENTS ? tr("SMESH_MERGE_ELEMENTS") : tr("SMESH_MERGE_NODES"), this); @@ -336,7 +340,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) GroupConstructorsLayout->setMargin(MARGIN); RadioButton = new QRadioButton(GroupConstructors); - RadioButton->setIcon(myAction == 1 ? IconMergeElems : IconMergeNodes); + RadioButton->setIcon(myAction == MERGE_ELEMENTS ? IconMergeElems : IconMergeNodes); RadioButton->setChecked(true); GroupConstructorsLayout->addWidget(RadioButton); ButtonGroup->addButton(RadioButton, 0); @@ -378,7 +382,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) /***************************************************************/ // Controls for coincident elements detecting - GroupCoincident = new QGroupBox(myAction == 1 ? + GroupCoincident = new QGroupBox(myAction == MERGE_ELEMENTS ? tr("COINCIDENT_ELEMENTS") : tr("COINCIDENT_NODES"), this); @@ -387,12 +391,16 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) aCoincidentLayout->setSpacing(SPACING); aCoincidentLayout->setMargin(MARGIN); - if (myAction == 0) { // case merge nodes + if (myAction == MERGE_NODES) // case merge nodes + { QWidget* foo = new QWidget(GroupCoincident); TextLabelTolerance = new QLabel(tr("SMESH_TOLERANCE"), foo); SpinBoxTolerance = new SMESHGUI_SpinBox(foo); SpinBoxTolerance->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); + SeparateCornersAndMedium = new QCheckBox(tr("SEPARATE_CORNERS_AND_MEDIUM"), foo); + SeparateCornersAndMedium->setEnabled( false ); + GroupExclude = new QGroupBox(tr("EXCLUDE_GROUPS"), foo); GroupExclude->setCheckable( true ); GroupExclude->setChecked( false ); @@ -405,9 +413,10 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) QGridLayout* fooLayout = new QGridLayout( foo ); fooLayout->setSpacing(SPACING); fooLayout->setMargin(0); - fooLayout->addWidget(TextLabelTolerance, 0, 0 ); - fooLayout->addWidget(SpinBoxTolerance, 0, 1 ); - fooLayout->addWidget(GroupExclude, 1, 0, 1, 2 ); + fooLayout->addWidget(TextLabelTolerance, 0, 0 ); + fooLayout->addWidget(SpinBoxTolerance, 0, 1 ); + fooLayout->addWidget(SeparateCornersAndMedium, 1, 0 ); + fooLayout->addWidget(GroupExclude, 2, 0, 1, 2 ); aCoincidentLayout->addWidget(foo); } else { @@ -430,7 +439,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) RemoveGroupButton = new QPushButton(tr("SMESH_BUT_REMOVE"), GroupCoincidentWidget); SelectAllCB = new QCheckBox(tr("SELECT_ALL"), GroupCoincidentWidget); - ShowIDs = new QCheckBox(myAction == 1 ? tr("SHOW_ELEMS_IDS") : tr("SHOW_NODES_IDS"), GroupCoincidentWidget); + ShowIDs = new QCheckBox(myAction == MERGE_ELEMENTS ? tr("SHOW_ELEMS_IDS") : tr("SHOW_NODES_IDS"), GroupCoincidentWidget); GroupCoincidentLayout->addWidget(ListCoincident, 0, 0, 4, 2); GroupCoincidentLayout->addWidget(DetectButton, 0, 2); @@ -501,9 +510,9 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction) DlgLayout->addWidget(GroupEdit); DlgLayout->addWidget(GroupButtons); - GroupCoincidentWidget->setVisible( myAction != 0 ); - GroupCoincident->setVisible( myAction == 0 ); - //if GroupExclude->setVisible( myAction == 0 ); + GroupCoincidentWidget->setVisible( myAction != MERGE_NODES ); + GroupCoincident ->setVisible( myAction == MERGE_NODES ); + //if GroupExclude->setVisible( myAction == MERGE_NODES ); GroupEdit->hide(); this->resize(10,10); @@ -528,7 +537,7 @@ SMESHGUI_MergeDlg::~SMESHGUI_MergeDlg() //================================================================================= void SMESHGUI_MergeDlg::Init() { - if (myAction == 0) { + if ( myAction == MERGE_NODES ) { SpinBoxTolerance->RangeStepAndValidator(0.0, COORD_MAX, 0.00001, "len_tol_precision"); SpinBoxTolerance->SetValue(1e-05); } @@ -578,7 +587,7 @@ void SMESHGUI_MergeDlg::Init() // Update Buttons updateControls(); - if (myAction == 0) + if ( myAction == MERGE_NODES ) myHelpFileName = "merging_nodes_page.html"; else myHelpFileName = "merging_elements_page.html"; @@ -639,7 +648,7 @@ bool SMESHGUI_MergeDlg::ClickOnApply() SMESH::array_of_long_array_var aGroupsOfElements = new SMESH::array_of_long_array; if ( ListCoincident->count() == 0) { - if (myAction == 0) + if ( myAction == MERGE_NODES ) SUIT_MessageBox::warning(this, tr("SMESH_WARNING"), tr("SMESH_NO_NODES_DETECTED")); @@ -663,13 +672,13 @@ bool SMESHGUI_MergeDlg::ClickOnApply() aGroupsOfElements[anArrayNum++] = anIds.inout(); } - if( myAction == 0 ) + if( myAction == MERGE_NODES ) aMeshEditor->MergeNodes (aGroupsOfElements.inout()); else aMeshEditor->MergeElements (aGroupsOfElements.inout()); if ( myTypeId == 0 ) { - if (myAction == 0 ) + if (myAction == MERGE_NODES ) SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"), tr("SMESH_MERGED_NODES").arg(QString::number(ListCoincident->count()).toLatin1().data())); else @@ -805,6 +814,16 @@ void SMESHGUI_MergeDlg::updateControls() buttonOk->setEnabled(enable); buttonApply->setEnabled(enable); DetectButton->setEnabled( !myMesh->_is_nil() ); + + if ( myAction == MERGE_NODES ) + { + bool has2ndOrder = (( !myMesh->_is_nil() ) && + ( myMesh->NbEdgesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 || + myMesh->NbFacesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 || + myMesh->NbVolumesOfOrder( SMESH::ORDER_QUADRATIC ) > 0 )); + + SeparateCornersAndMedium->setEnabled( has2ndOrder ); + } } //================================================================================= @@ -831,7 +850,7 @@ void SMESHGUI_MergeDlg::onDetect() else src = SMESH::SMESH_IDSource::_duplicate( mySubMeshOrGroup ); switch (myAction) { - case 0 : + case MERGE_NODES : for ( int i = 0; GroupExclude->isChecked() && i < ListExclude->count(); i++ ) { if ( ListExclude->item( i )->checkState() == Qt::Checked ) { aExcludeGroups->length( aExcludeGroups->length()+1 ); @@ -841,9 +860,11 @@ void SMESHGUI_MergeDlg::onDetect() aMeshEditor->FindCoincidentNodesOnPartBut(src.in(), SpinBoxTolerance->GetValue(), aGroupsArray.out(), - aExcludeGroups.in()); + aExcludeGroups.in(), + SeparateCornersAndMedium->isEnabled() && + SeparateCornersAndMedium->isChecked()); break; - case 1 : + case MERGE_ELEMENTS : aMeshEditor->FindEqualElements(src.in(), aGroupsArray.out()); break; } @@ -906,7 +927,7 @@ void SMESHGUI_MergeDlg::onSelectGroup() mySelectionMgr->setSelectedObjects(aList,false); if (ShowIDs->isChecked()) - if (myAction == 0) { + if ( myAction == MERGE_NODES ) { myIdPreview->SetPointsData(myActor->GetObject()->GetMesh(), anIndices); myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility()); } @@ -959,7 +980,7 @@ void SMESHGUI_MergeDlg::onSelectElementFromGroup() mySelectionMgr->setSelectedObjects(aList); if (ShowIDs->isChecked()) - if (myAction == 0) { + if (myAction == MERGE_NODES) { myIdPreview->SetPointsData(myActor->GetObject()->GetMesh(), anIndices); myIdPreview->SetPointsLabeled(!anIndices.IsEmpty(), myActor->GetVisibility()); } @@ -1187,13 +1208,13 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument() if ( myActor && myTypeId == 1 && mySelector->IsSelectionEnabled() ) { mySubMeshOrGroup = SMESH::SMESH_IDSource::_nil(); mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter); - + if ((!SMESH::IObjectToInterface(IO)->_is_nil() || //SUBMESH OR GROUP !SMESH::IObjectToInterface(IO)->_is_nil()) && !SMESH::IObjectToInterface(IO)->_is_nil()) mySubMeshOrGroup = SMESH::IObjectToInterface(IO); - - if (myAction == 0) { + + if (myAction == MERGE_NODES) { SMESH::SetPointRepresentation(true); if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) aViewWindow->SetSelectionMode(NodeSelection); @@ -1204,7 +1225,7 @@ void SMESHGUI_MergeDlg::SelectionIntoArgument() } // process groups - if ( myAction == 0 && !myMesh->_is_nil() && myEntry != aCurrentEntry ) { + if ( myAction == MERGE_NODES && !myMesh->_is_nil() && myEntry != aCurrentEntry ) { myGroups.clear(); ListExclude->clear(); SMESH::ListOfGroups_var aListOfGroups = myMesh->GetGroups(); @@ -1317,7 +1338,7 @@ void SMESHGUI_MergeDlg::onTypeChanged (int id) if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) aViewWindow->SetSelectionMode(ActorSelection); mySelectionMgr->clearFilters(); - if (myAction == 0) + if (myAction == MERGE_NODES) GroupCoincidentWidget->hide(); else GroupCoincident->hide(); @@ -1338,7 +1359,7 @@ void SMESHGUI_MergeDlg::onTypeChanged (int id) myMeshOrSubMeshOrGroupFilter = new SMESH_LogicalFilter (aListOfFilters, SMESH_LogicalFilter::LO_OR); - if (myAction == 0) { + if (myAction == MERGE_NODES) { GroupCoincidentWidget->show(); SMESH::SetPointRepresentation(true); if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) diff --git a/src/SMESHGUI/SMESHGUI_MergeDlg.h b/src/SMESHGUI/SMESHGUI_MergeDlg.h index b003b3842..7e777ea43 100644 --- a/src/SMESHGUI/SMESHGUI_MergeDlg.h +++ b/src/SMESHGUI/SMESHGUI_MergeDlg.h @@ -125,6 +125,7 @@ private: QWidget* GroupCoincidentWidget; QLabel* TextLabelTolerance; SMESHGUI_SpinBox* SpinBoxTolerance; + QCheckBox* SeparateCornersAndMedium; QPushButton* DetectButton; QListWidget* ListCoincident; QPushButton* AddGroupButton; diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 45b444feb..45fef3733 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -5100,6 +5100,10 @@ Please select a group and try again EXCLUDE_GROUPS Exclude Groups + + SEPARATE_CORNERS_AND_MEDIUM + No merge of corner and medium nodes + SMESHGUI_ExtrusionAlongPathDlg diff --git a/src/SMESHUtils/SMESH_OctreeNode.cxx b/src/SMESHUtils/SMESH_OctreeNode.cxx index 6225108bd..772a50f99 100644 --- a/src/SMESHUtils/SMESH_OctreeNode.cxx +++ b/src/SMESHUtils/SMESH_OctreeNode.cxx @@ -275,42 +275,33 @@ void SMESH_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes, * \param theGroupsOfNodes - list of nodes closed to each other returned */ //============================= -void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes, - const double theTolerance, +void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes, + const double theTolerance, list< list< const SMDS_MeshNode*> >* theGroupsOfNodes) { TIDSortedNodeSet::iterator it1 = theSetOfNodes->begin(); list::iterator it2; + list ListOfCoincidentNodes; + TIDCompare idLess; + while (it1 != theSetOfNodes->end()) { const SMDS_MeshNode * n1 = *it1; - list ListOfCoincidentNodes;// Initialize the lists via a declaration, it's enough - - list * groupPtr = 0; - // Searching for Nodes around n1 and put them in ListofCoincidentNodes. // Found nodes are also erased from theSetOfNodes FindCoincidentNodes(n1, theSetOfNodes, &ListOfCoincidentNodes, theTolerance); - // We build a list {n1 + his neigbours} and add this list in theGroupsOfNodes - for (it2 = ListOfCoincidentNodes.begin(); it2 != ListOfCoincidentNodes.end(); it2++) + if ( !ListOfCoincidentNodes.empty() ) { - const SMDS_MeshNode* n2 = *it2; - if ( !groupPtr ) - { - theGroupsOfNodes->push_back( list() ); - groupPtr = & theGroupsOfNodes->back(); - groupPtr->push_back( n1 ); - } - if (groupPtr->front() > n2) - groupPtr->push_front( n2 ); - else - groupPtr->push_back( n2 ); + // We build a list {n1 + his neigbours} and add this list in theGroupsOfNodes + if ( idLess( n1, ListOfCoincidentNodes.front() )) ListOfCoincidentNodes.push_front( n1 ); + else ListOfCoincidentNodes.push_back ( n1 ); + ListOfCoincidentNodes.sort( idLess ); + theGroupsOfNodes->push_back( list() ); + theGroupsOfNodes->back().splice( theGroupsOfNodes->back().end(), ListOfCoincidentNodes ); } - if (groupPtr != 0) - groupPtr->sort(); theSetOfNodes->erase(it1); it1 = theSetOfNodes->begin(); diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 81d0e15c1..3afdb9f1f 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -2632,11 +2632,12 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray, } // if an IDSource is a mesh } //meshes loop - if (theMergeNodesAndElements) { - // merge nodes + if (theMergeNodesAndElements) // merge nodes + { TIDSortedNodeSet aMeshNodes; // no input nodes SMESH_MeshEditor::TListOfListOfNodes aGroupsOfNodes; - aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes ); + aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes, + /*SeparateCornersAndMedium=*/ false ); aNewEditor.MergeNodes( aGroupsOfNodes ); // merge elements aNewEditor.MergeEqualElements(); diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 06481f54b..157983e3c 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -3952,25 +3952,24 @@ SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr theObject, //======================================================================= -//function : FindCoincidentNodes +//function : findCoincidentNodes //purpose : //======================================================================= -void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tolerance, - SMESH::array_of_long_array_out GroupsOfNodes) - throw (SALOME::SALOME_Exception) +void SMESH_MeshEditor_i:: +findCoincidentNodes (TIDSortedNodeSet & Nodes, + CORBA::Double Tolerance, + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) { - SMESH_TRY; - initData(); - ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; - TIDSortedNodeSet nodes; // no input nodes - getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes ); + getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium ); GroupsOfNodes = new SMESH::array_of_long_array; GroupsOfNodes->length( aListOfListOfNodes.size() ); ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin(); - for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) { + for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) + { list< const SMDS_MeshNode* >& aListOfNodes = *llIt; list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();; SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ]; @@ -3978,8 +3977,28 @@ void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tol for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ ) aGroup[ j ] = (*lIt)->GetID(); } +} + +//======================================================================= +//function : FindCoincidentNodes +//purpose : +//======================================================================= + +void SMESH_MeshEditor_i:: +FindCoincidentNodes (CORBA::Double Tolerance, + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) + throw (SALOME::SALOME_Exception) +{ + SMESH_TRY; + initData(); + + TIDSortedNodeSet nodes; // no input nodes + findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium ); + TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( " - << Tolerance << " )"; + << Tolerance << ", " + << SeparateCornersAndMedium << " )"; SMESH_CATCH( SMESH::throwCorbaException ); } @@ -3989,9 +4008,11 @@ void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double Tol //purpose : //======================================================================= -void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject, - CORBA::Double Tolerance, - SMESH::array_of_long_array_out GroupsOfNodes) +void SMESH_MeshEditor_i:: +FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject, + CORBA::Double Tolerance, + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) throw (SALOME::SALOME_Exception) { SMESH_TRY; @@ -4000,25 +4021,12 @@ void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr TIDSortedNodeSet nodes; idSourceToNodeSet( theObject, getMeshDS(), nodes ); - ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; - if(!nodes.empty()) - getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes ); + findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium ); - GroupsOfNodes = new SMESH::array_of_long_array; - GroupsOfNodes->length( aListOfListOfNodes.size() ); - ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin(); - for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) - { - list< const SMDS_MeshNode* >& aListOfNodes = *llIt; - list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();; - SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ]; - aGroup.length( aListOfNodes.size() ); - for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ ) - aGroup[ j ] = (*lIt)->GetID(); - } TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( " - <GetElements( theExceptSubMeshOrGroups[i], + SMESH::NODE ); + while ( nodeIt->more() ) + nodes.erase( cast2Node( nodeIt->next() )); } - ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes; - if(!nodes.empty()) - getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes ); + findCoincidentNodes( nodes, theTolerance, theGroupsOfNodes, theSeparateCornersAndMedium ); - theGroupsOfNodes = new SMESH::array_of_long_array; - theGroupsOfNodes->length( aListOfListOfNodes.size() ); - ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin(); - for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) - { - list< const SMDS_MeshNode* >& aListOfNodes = *llIt; - list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();; - SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ]; - aGroup.length( aListOfNodes.size() ); - for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ ) - aGroup[ j ] = (*lIt)->GetID(); - } TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( " << theObject<<", " << theTolerance << ", " - << theExceptSubMeshOrGroups << " )"; + << theExceptSubMeshOrGroups << ", " + << theSeparateCornersAndMedium << " )"; SMESH_CATCH( SMESH::throwCorbaException ); } diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index 2cdf9fa61..6d25784d5 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -472,16 +472,19 @@ public: throw (SALOME::SALOME_Exception); void FindCoincidentNodes (CORBA::Double Tolerance, - SMESH::array_of_long_array_out GroupsOfNodes) + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) throw (SALOME::SALOME_Exception); void FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr Object, CORBA::Double Tolerance, - SMESH::array_of_long_array_out GroupsOfNodes) + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium) throw (SALOME::SALOME_Exception); void FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr Object, CORBA::Double Tolerance, SMESH::array_of_long_array_out GroupsOfNodes, - const SMESH::ListOfIDSources& ExceptSubMeshOrGroups) + const SMESH::ListOfIDSources& ExceptSubMeshOrGroups, + CORBA::Boolean SeparateCornersAndMedium) throw (SALOME::SALOME_Exception); void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes) throw (SALOME::SALOME_Exception); @@ -903,6 +906,12 @@ private: //!< private methods const bool emptyIfIsMesh = false, IDSource_Error* error = 0); + void findCoincidentNodes( TIDSortedNodeSet & Nodes, + CORBA::Double Tolerance, + SMESH::array_of_long_array_out GroupsOfNodes, + CORBA::Boolean SeparateCornersAndMedium); + + private: //!< fields diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 22e31b4ee..c6e1eabb4 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -4299,31 +4299,39 @@ class Mesh: ## Finds groups of adjacent nodes within Tolerance. # @param Tolerance the value of tolerance - # @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]]) + # @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts + # corner and medium nodes in separate groups thus preventing + # their further merge. + # @return the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]]) # @ingroup l2_modif_trsf - def FindCoincidentNodes (self, Tolerance): - return self.editor.FindCoincidentNodes(Tolerance) + def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False): + return self.editor.FindCoincidentNodes( Tolerance, SeparateCornerAndMediumNodes ) ## Finds groups of ajacent nodes within Tolerance. # @param Tolerance the value of tolerance # @param SubMeshOrGroup SubMesh or Group # @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search - # @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]]) + # @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts + # corner and medium nodes in separate groups thus preventing + # their further merge. + # @return the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]]) # @ingroup l2_modif_trsf - def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]): + def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, + exceptNodes=[], SeparateCornerAndMediumNodes=False): unRegister = genObjUnRegister() if (isinstance( SubMeshOrGroup, Mesh )): SubMeshOrGroup = SubMeshOrGroup.GetMesh() - if not isinstance( exceptNodes, list): + if not isinstance( exceptNodes, list ): exceptNodes = [ exceptNodes ] - if exceptNodes and isinstance( exceptNodes[0], int): - exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE)] + if exceptNodes and isinstance( exceptNodes[0], int ): + exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE )] unRegister.set( exceptNodes ) - return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes) + return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance, + exceptNodes, SeparateCornerAndMediumNodes) ## Merges nodes - # @param GroupsOfNodes a list of pairs of nodes IDs for merging - # (e.g. [[1,12],[25,4]], then nodes 12 and 4 will be removed and replaced + # @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 # @ingroup l2_modif_trsf def MergeNodes (self, GroupsOfNodes): @@ -4331,7 +4339,7 @@ class Mesh: ## Finds the elements built on the same nodes. # @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching - # @return the list of pairs of equal elements IDs (e.g. [[1,12],[25,4]]) + # @return the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]]) # @ingroup l2_modif_trsf def FindEqualElements (self, MeshOrSubMeshOrGroup=None): if not MeshOrSubMeshOrGroup: @@ -4341,8 +4349,8 @@ class Mesh: return self.editor.FindEqualElements( MeshOrSubMeshOrGroup ) ## Merges elements in each given group. - # @param GroupsOfElementsID a list of pairs of elements IDs for merging - # (e.g. [[1,12],[25,4]], then elements 12 and 4 will be removed and + # @param GroupsOfElementsID a list of groups of elements IDs for merging + # (e.g. [[1,12,13],[25,4]], then elements 12, 13 and 4 will be removed and # replaced by elements 1 and 25 in all groups) # @ingroup l2_modif_trsf def MergeElements(self, GroupsOfElementsID): diff --git a/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx b/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx index 8740859d0..ea8fdc936 100644 --- a/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx @@ -592,7 +592,8 @@ namespace //================================================================================ TopoDS_Edge makeEdgeFromMA( SMESH_MesherHelper& theHelper, - const SMESH_MAT2d::MedialAxis& theMA ) + const SMESH_MAT2d::MedialAxis& theMA, + const double theMinSegLen) { if ( theMA.nbBranches() != 1 ) return TopoDS_Edge(); @@ -605,14 +606,31 @@ namespace TopoDS_Face face = TopoDS::Face( theHelper.GetSubShape() ); Handle(Geom_Surface) surface = BRep_Tool::Surface( face ); + vector< gp_Pnt > pnt; + pnt.reserve( uv.size() * 2 ); + pnt.push_back( surface->Value( uv[0].X(), uv[0].Y() )); + for ( size_t i = 1; i < uv.size(); ++i ) + { + gp_Pnt p = surface->Value( uv[i].X(), uv[i].Y() ); + int nbDiv = int( p.Distance( pnt.back() ) / theMinSegLen ); + for ( int iD = 1; iD < nbDiv; ++iD ) + { + double R = iD / double( nbDiv ); + gp_XY uvR = uv[i-1] * (1 - R) + uv[i] * R; + pnt.push_back( surface->Value( uvR.X(), uvR.Y() )); + } + pnt.push_back( p ); + } + // cout << "from salome.geom import geomBuilder" << endl; // cout << "geompy = geomBuilder.New(salome.myStudy)" << endl; - Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1, uv.size()); - for ( size_t i = 0; i < uv.size(); ++i ) + Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1, pnt.size()); + for ( size_t i = 0; i < pnt.size(); ++i ) { - gp_Pnt p = surface->Value( uv[i].X(), uv[i].Y() ); + gp_Pnt& p = pnt[i]; points->SetValue( i+1, p ); - //cout << "geompy.MakeVertex( "<< p.X()<<", " << p.Y()<<", " << p.Z()<<" )" << endl; + // cout << "geompy.MakeVertex( "<< p.X()<<", " << p.Y()<<", " << p.Z() + // <<" theName = 'p_" << i << "')" << endl; } GeomAPI_Interpolate interpol( points, /*isClosed=*/false, gp::Resolution()); @@ -658,6 +676,7 @@ namespace const SMESH_MAT2d::MedialAxis& theMA, const SinuousFace& theSinuFace, SMESH_Algo* the1dAlgo, + const double theMinSegLen, vector& theMAParams ) { // check if all EDGEs of one size are meshed, then MA discretization is not needed @@ -674,7 +693,7 @@ namespace return true; // discretization is not needed - TopoDS_Edge branchEdge = makeEdgeFromMA( theHelper, theMA ); + TopoDS_Edge branchEdge = makeEdgeFromMA( theHelper, theMA, theMinSegLen ); if ( branchEdge.IsNull() ) return false; @@ -1446,7 +1465,7 @@ bool StdMeshers_QuadFromMedialAxis_1D2D::Compute(SMESH_Mesh& theMesh, _regular1D->SetSegmentLength( minSegLen ); vector maParams; - if ( ! divideMA( helper, ma, sinuFace, _regular1D, maParams )) + if ( ! divideMA( helper, ma, sinuFace, _regular1D, minSegLen, maParams )) return error(COMPERR_BAD_SHAPE); _progress = 0.4;