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
+
+
+ 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,57 +3952,18 @@ 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 );
-
- 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 = " << this << ".FindCoincidentNodes( "
- << Tolerance << " )";
-
- SMESH_CATCH( SMESH::throwCorbaException );
-}
-
-//=======================================================================
-//function : FindCoincidentNodesOnPart
-//purpose :
-//=======================================================================
-
-void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr theObject,
- CORBA::Double Tolerance,
- SMESH::array_of_long_array_out GroupsOfNodes)
- throw (SALOME::SALOME_Exception)
-{
- SMESH_TRY;
- initData();
-
- TIDSortedNodeSet nodes;
- idSourceToNodeSet( theObject, getMeshDS(), nodes );
-
- ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
- if(!nodes.empty())
- getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
+ getEditor().FindCoincidentNodes( Nodes, Tolerance, aListOfListOfNodes, SeparateCornersAndMedium );
GroupsOfNodes = new SMESH::array_of_long_array;
GroupsOfNodes->length( aListOfListOfNodes.size() );
@@ -4016,9 +3977,56 @@ void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr
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 << ", "
+ << SeparateCornersAndMedium << " )";
+
+ SMESH_CATCH( SMESH::throwCorbaException );
+}
+
+//=======================================================================
+//function : FindCoincidentNodesOnPart
+//purpose :
+//=======================================================================
+
+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;
+ initData();
+
+ TIDSortedNodeSet nodes;
+ idSourceToNodeSet( theObject, getMeshDS(), nodes );
+
+ findCoincidentNodes( nodes, Tolerance, GroupsOfNodes, SeparateCornersAndMedium );
+
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 );
- // 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 )
+ 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, pnt.size());
+ for ( size_t i = 0; i < pnt.size(); ++i )
+ {
+ 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;