Debug 23078: [CEA 1498] Sewing of meshes without having to set the nodes ids

This commit is contained in:
eap 2015-09-23 17:47:26 +03:00
parent 0463dee592
commit fd96feab4b
16 changed files with 455 additions and 183 deletions

BIN
doc/salome/gui/SMESH/images/sewing1.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

View File

@ -41,11 +41,9 @@ To apply this algorithm when you define your mesh, select <b>Body
This dialog allows to define This dialog allows to define
<ul> <ul>
<li>\b Name of the algorithm. </li> <li>\b Name of the algorithm. </li>
<li> Minimal size of a cell truncated by the geometry boundary. If the <li> Minimal size of a cell truncated by the geometry boundary. If the
size of a truncated grid cell is \b Threshold times less than a size of a truncated grid cell is \b Threshold times less than a
initial cell size, then a mesh element is not created. </li> initial cell size, then a mesh element is not created. </li>
<li> <b> Implement Edges </b> check-box activates incorporation of <li> <b> Implement Edges </b> check-box activates incorporation of
geometrical edges in the mesh. geometrical edges in the mesh.
@ -64,9 +62,10 @@ This dialog allows to define
System.</li> System.</li>
<li> You can define the \b Spacing of a grid as an algebraic formula <li> You can define the \b Spacing of a grid as an algebraic formula
<em>f(t)</em> where \a t is a position along a grid axis <em>f(t)</em> where \a t is a position along a grid axis
normalized at [0.0,1.0]. The whole range of geometry can be normalized at [0.0,1.0]. <em>f(t)</em> must be non-negative
divided into sub-ranges with their own spacing formulas to apply; at 0. <= \a t <= 1. The whole extent of geometry can be
\a t varies between 0.0 and 1.0 within each sub-range. \b Insert button divided into ranges with their own spacing formulas to apply;
\a t varies between 0.0 and 1.0 within each \b Range. \b Insert button
divides a selected range into two. \b Delete button adds the divides a selected range into two. \b Delete button adds the
selected sub-range to the previous one. Double click on a range in selected sub-range to the previous one. Double click on a range in
the list enables edition of its right boundary. Double click on a the list enables edition of its right boundary. Double click on a

View File

@ -16,8 +16,8 @@ and hypotheses.
Mesh generation on the geometry is performed in the bottom-up Mesh generation on the geometry is performed in the bottom-up
flow: nodes on vertices are created first, then edges are divided into flow: nodes on vertices are created first, then edges are divided into
segments using nodes on vertices; the segments of edges are then segments using nodes on vertices; the node of segments are then
used to mesh faces; then the mesh of faces is used to mesh used to mesh faces; then the nodes of faces are used to mesh
solids. This automatically assures the conformity of the mesh. solids. This automatically assures the conformity of the mesh.
It is required to choose a meshing algorithm for every dimension of It is required to choose a meshing algorithm for every dimension of

View File

@ -20,9 +20,11 @@ and from its sub-menu select the \b Sewing item.</li>
<li>Check in the dialog box one of the radio buttons corresponding to <li>Check in the dialog box one of the radio buttons corresponding to
the type of sewing operation you would like to perform.</li> the type of sewing operation you would like to perform.</li>
<li>Fill the other fields available in the dialog box.</li> <li>Fill the other fields available in the dialog box.</li>
<li>Click the \b Apply or <b>Apply and Close</b> button to perform the operation of sewing.</li> <li>Click the \b Apply or <b>Apply and Close</b> button to perform the
operation of sewing.</li>
</ol> </ol>
<br> <br>
\anchor free_borders_anchor \anchor free_borders_anchor
<h2>Sew free borders</h2> <h2>Sew free borders</h2>
@ -31,14 +33,69 @@ This functionality allows you to unite free borders of a 2D mesh.
There are two working modes: \a Automatic and \a Manual. In the \b There are two working modes: \a Automatic and \a Manual. In the \b
Automatic mode, the program finds free borders coincident within a Automatic mode, the program finds free borders coincident within a
certain tolerance and sew them. Optionally it is possible to adjust specified tolerance and sews them. Optionally it is possible to
the found free borders before sewing. In the \b Manual mode you are to visually check and correct is necessary the found free borders before
define borders to sew by picking three nodes of each border. sewing. <br>
In the \b Manual mode you are to define borders to sew by picking
three nodes of each of two borders.
\image html sewing1.png \image html sewing1.png
<center>Default mode is \a Automatic</center>
For sewing free borders you should define three points on each border: To use \b Automatic sewing:
first, second and the last node: <ul>
<li>Specify a mesh you want to sew by selecting it or any its part
(group or sub-mesh) in the Object Browser or in the VTK Viewer.</li>
<li>Specify the \b Tolerance within which free borders are considered
coincident. At the default zero \b Tolerance, the tolerance used by
the search algorithm is defined as one tenth of an average size of
elements adjacent to free borders being compared.</li>
<li>To visually check the coincident free borders found by the
algorithm, switch off <b>Auto Sewing</b> check-box. Then controls
to adjust groups of coincident free borders will become available in
the dialog.</li>
\image html sewing_auto.png
<center>Controls to adjust groups of coincident free borders</center>
<li>\b Detect button launches the algorithm of search of coincident
free borders.</li>
<li>The found groups of <b>Coincident Free Borders</b> are shown in a
list, a group per a line. Each group has its own color which is used
to display the borders of the group in the VTK Viewer. A free border
within a group is designated by IDs of its first and last nodes within
parenthesis. All borders present in the list will be sewn upon \b
Apply.</li>
<li>\b Remove button removes selected groups from the list.</li>
<li><b>Select All</b> check-box selects all groups in the list.</li>
<li>When a group is selected, its borders appear in <b>Edit Selected
Group</b> list that allows you to change this group.</li>
<li>
\image html sort.png
<em>Set First</em> button moves the selected border to the
first position in the group, as a result other borders will be moved
to this border during sewing.
</li><li>
\image html remove.png
<em>Remove Border</em> button removes selected borders from the
group. It is active if there are more than two borders in the group.
</li>
<li>Selection of a border in the list allows to change its first and
last nodes whose IDs appear in two fields below the list. \a Arrow
buttons near each field move the corresponding end node by
number of nodes defined by \b Step field.</li>
<li>
\image html swap.png
<em>Swap</em> button swaps the first and last nodes of a
selected border.
</li>
</ul>
For sewing free borders manually you should switch the \b Mode to \b
Manual and define three points on each border: first, second and the
last node:
\image html sewing_manual.png
<ul> <ul>
<li>the first node specifies beginning of the border;</li> <li>the first node specifies beginning of the border;</li>
<li>the second node specifies the part of the border which should be <li>the second node specifies the part of the border which should be

View File

@ -38,7 +38,6 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
Status aResult = DRS_OK; Status aResult = DRS_OK;
int nbNodes, nbCells; int nbNodes, nbCells;
//int i;
char *file2Read = (char *)myFile.c_str(); char *file2Read = (char *)myFile.c_str();
FILE* aFileId = fopen(file2Read, "w+"); FILE* aFileId = fopen(file2Read, "w+");
@ -55,7 +54,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
nbNodes = myMesh->NbNodes(); nbNodes = myMesh->NbNodes();
/* Combien de mailles, faces ou aretes ? */ /* Combien de mailles, faces ou aretes ? */
int /*nb_of_nodes,*/ nb_of_edges, nb_of_faces, nb_of_volumes; int nb_of_edges, nb_of_faces, nb_of_volumes;
nb_of_edges = myMesh->NbEdges(); nb_of_edges = myMesh->NbEdges();
nb_of_faces = myMesh->NbFaces(); nb_of_faces = myMesh->NbFaces();
nb_of_volumes = myMesh->NbVolumes(); nb_of_volumes = myMesh->NbVolumes();
@ -64,7 +63,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
SCRUTE(nb_of_faces); SCRUTE(nb_of_faces);
SCRUTE(nb_of_volumes); SCRUTE(nb_of_volumes);
fprintf(stdout, "%d %d\n", nbNodes, nbCells); //fprintf(stdout, "%d %d\n", nbNodes, nbCells);
fprintf(aFileId, "%d %d\n", nbNodes, nbCells); fprintf(aFileId, "%d %d\n", nbNodes, nbCells);
/**************************************************************************** /****************************************************************************
@ -74,7 +73,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
SMDS_NodeIteratorPtr itNodes=myMesh->nodesIterator(); SMDS_NodeIteratorPtr itNodes=myMesh->nodesIterator();
while(itNodes->more()){ while(itNodes->more()){
const SMDS_MeshNode * node = itNodes->next(); const SMDS_MeshNode * node = itNodes->next();
fprintf(aFileId, "%d %e %e %e\n", node->GetID(), node->X(), node->Y(), node->Z()); fprintf(aFileId, "%d %.14e %.14e %.14e\n", node->GetID(), node->X(), node->Y(), node->Z());
} }
/**************************************************************************** /****************************************************************************

View File

@ -56,7 +56,8 @@ DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh():
myDoGroupOfVolumes (false), myDoGroupOfVolumes (false),
myDoGroupOf0DElems(false), myDoGroupOf0DElems(false),
myDoGroupOfBalls(false), myDoGroupOfBalls(false),
myAutoDimension(true) myAutoDimension(true),
myAddODOnVertices(false)
{} {}
void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName, void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName,

View File

@ -139,8 +139,12 @@ const SMDS_MeshNode* SMDS_Mesh0DElement::GetNode(const int ind) const
//function : ChangeNode //function : ChangeNode
//purpose : //purpose :
//======================================================================= //=======================================================================
bool SMDS_Mesh0DElement::ChangeNode (const SMDS_MeshNode * node) bool SMDS_Mesh0DElement::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
{ {
myNode = node; if ( nbNodes == 1 )
{
myNode = nodes[0];
return true; return true;
} }
return false;
}

View File

@ -34,8 +34,7 @@ class SMDS_EXPORT SMDS_Mesh0DElement: public SMDS_MeshCell
{ {
public: public:
SMDS_Mesh0DElement (const SMDS_MeshNode * node); SMDS_Mesh0DElement (const SMDS_MeshNode * node);
bool ChangeNode (const SMDS_MeshNode * node); virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes);
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
virtual void Print (std::ostream & OS) const; virtual void Print (std::ostream & OS) const;
virtual SMDSAbs_ElementType GetType() const; virtual SMDSAbs_ElementType GetType() const;

View File

@ -7371,8 +7371,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
for ( ; eIt != elems.end(); eIt++ ) for ( ; eIt != elems.end(); eIt++ )
{ {
const SMDS_MeshElement* elem = *eIt; const SMDS_MeshElement* elem = *eIt;
int nbNodes = elem->NbNodes(); const int nbNodes = elem->NbNodes();
int aShapeId = FindShape( elem ); const int aShapeId = FindShape( elem );
nodeSet.clear(); nodeSet.clear();
curNodes.resize( nbNodes ); curNodes.resize( nbNodes );
@ -7911,6 +7911,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
} // if ( nbNodes != nbUniqueNodes ) // some nodes stick } // if ( nbNodes != nbUniqueNodes ) // some nodes stick
if ( isOk ) // the non-poly elem remains valid after sticking nodes if ( isOk ) // the non-poly elem remains valid after sticking nodes
{
if ( nbNodes != nbUniqueNodes )
{ {
elemType.Init( elem ).SetID( elem->GetID() ); elemType.Init( elem ).SetID( elem->GetID() );
@ -7924,6 +7926,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
if ( elem != newElem ) if ( elem != newElem )
ReplaceElemInGroups( elem, newElem, aMesh ); ReplaceElemInGroups( elem, newElem, aMesh );
} }
else
{
aMesh->ChangeElementNodes( elem, & curNodes[0], nbNodes );
}
}
else { else {
// Remove invalid regular element or invalid polygon // Remove invalid regular element or invalid polygon
rmElemIds.push_back( elem->GetID() ); rmElemIds.push_back( elem->GetID() );
@ -8749,6 +8756,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
} }
// find coincident // find coincident
TListOfListOfElementsID equalGroups; TListOfListOfElementsID equalGroups;
if ( !segments.empty() )
FindEqualElements( segments, equalGroups ); FindEqualElements( segments, equalGroups );
if ( !equalGroups.empty() ) if ( !equalGroups.empty() )
{ {

View File

@ -329,14 +329,13 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
SelectAllCheck = new QCheckBox(tr("SELECT_ALL"), GroupCoincident); SelectAllCheck = new QCheckBox(tr("SELECT_ALL"), GroupCoincident);
aCoincidentLayout->addWidget(ListCoincident, 0, 0, 4, 2); aCoincidentLayout->addWidget(ListCoincident, 0, 0, 5, 2);
aCoincidentLayout->addWidget(DetectButton, 1, 2); aCoincidentLayout->addWidget(DetectButton, 1, 2);
aCoincidentLayout->addWidget(RemoveGroupButton, 3, 2); aCoincidentLayout->addWidget(RemoveGroupButton, 3, 2);
aCoincidentLayout->addWidget(SelectAllCheck, 4, 0); aCoincidentLayout->addWidget(SelectAllCheck, 5, 0);
aCoincidentLayout->setRowMinimumHeight(1, 10); aCoincidentLayout->setRowMinimumHeight(1, 10);
aCoincidentLayout->setRowStretch (1, 5); aCoincidentLayout->setRowStretch (4, 5);
aCoincidentLayout->setRowStretch (5, 0);
GroupCoincidentLayout->addWidget( GroupCoincident );
/*****************************************/ /*****************************************/
// Controls for editing the selected group // Controls for editing the selected group
@ -391,8 +390,13 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
GroupEditLayout->addWidget(SwapBut, 1, 7); GroupEditLayout->addWidget(SwapBut, 1, 7);
GroupEditLayout->addWidget(StepLabel, 1, 8); GroupEditLayout->addWidget(StepLabel, 1, 8);
GroupEditLayout->addWidget(StepSpin, 1, 9); GroupEditLayout->addWidget(StepSpin, 1, 9);
GroupEditLayout->setRowStretch( 0, 1 );
GroupCoincidentLayout->addWidget( GroupCoincident );
GroupCoincidentLayout->addWidget( GroupEdit ); GroupCoincidentLayout->addWidget( GroupEdit );
GroupCoincidentLayout->setRowStretch( 0, 10 );
GroupCoincidentLayout->setRowStretch( 1, 1 );
aSewFreeBordersLayout->addWidget( GroupCoincidentWidget ); aSewFreeBordersLayout->addWidget( GroupCoincidentWidget );
// layout // layout
@ -579,6 +583,7 @@ void SMESHGUI_SewingDlg::ConstructorsClicked (int constructorId)
{ {
ModeGroup->hide(); ModeGroup->hide();
SewFreeBordersWidget->hide(); SewFreeBordersWidget->hide();
restoreDisplayMode();
} }
bool isNodeSelection = true; bool isNodeSelection = true;
@ -673,12 +678,11 @@ void SMESHGUI_SewingDlg::ConstructorsClicked (int constructorId)
LineEdit4->setValidator(new SMESHGUI_IdValidator(this, 1)); LineEdit4->setValidator(new SMESHGUI_IdValidator(this, 1));
} }
if ( isNodeSelection ) if ( myActor )
{ myActor->SetPointRepresentation( isNodeSelection );
SMESH::SetPointRepresentation(true);
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
aViewWindow->SetSelectionMode(NodeSelection); aViewWindow->SetSelectionMode( isNodeSelection ? NodeSelection : ActorSelection );
}
UpdateButtons(); UpdateButtons();
@ -700,7 +704,8 @@ void SMESHGUI_SewingDlg::setDisplayMode()
{ {
myStoredEntityMode = 0; myStoredEntityMode = 0;
myStoredRepresentation = -1; myStoredRepresentation = -1;
if ( myActor )
if ( myActor && AutoSewCheck->isVisible() && !AutoSewCheck->isChecked() )
{ {
myStoredEntityMode = myActor->GetEntityMode(); myStoredEntityMode = myActor->GetEntityMode();
myStoredRepresentation = myActor->GetRepresentation(); myStoredRepresentation = myActor->GetRepresentation();
@ -728,6 +733,9 @@ void SMESHGUI_SewingDlg::restoreDisplayMode()
myStoredEntityMode = 0; myStoredEntityMode = 0;
myStoredRepresentation = -1; myStoredRepresentation = -1;
} }
for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
if ( myBorderDisplayers[ i ])
myBorderDisplayers[ i ]->Hide();
} }
//======================================================================= //=======================================================================
@ -751,6 +759,12 @@ void SMESHGUI_SewingDlg::onModeChange( int mode )
if ( !SewFreeBordersWidget->isVisible() ) if ( !SewFreeBordersWidget->isVisible() )
SewFreeBordersWidget->show(); SewFreeBordersWidget->show();
} }
if ( myActor )
myActor->SetPointRepresentation( mode == MODE_MANUAL );
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetCurrentVtkView() )
aViewWindow->SetSelectionMode( mode == MODE_MANUAL ? NodeSelection : ActorSelection );
onAutoSew( AutoSewCheck->isChecked() ); onAutoSew( AutoSewCheck->isChecked() );
QApplication::instance()->processEvents(); QApplication::instance()->processEvents();
@ -774,6 +788,12 @@ void SMESHGUI_SewingDlg::onAutoSew( int isAuto )
if ( ModeButGrp->checkedId() == MODE_AUTO ) if ( ModeButGrp->checkedId() == MODE_AUTO )
SewFreeBordersWidget->show(); SewFreeBordersWidget->show();
if ( isAuto )
restoreDisplayMode();
else
setDisplayMode();
SMESH::RepaintCurrentView();
UpdateButtons(); UpdateButtons();
updateGeometry(); updateGeometry();
@ -847,6 +867,7 @@ QString SMESHGUI_SewingDlg::getGroupText(int groupIndex)
void SMESHGUI_SewingDlg::onDetectClicked() void SMESHGUI_SewingDlg::onDetectClicked()
{ {
myBusy = true;
ListCoincident->clear(); ListCoincident->clear();
if ( myMesh->_is_nil() ) if ( myMesh->_is_nil() )
@ -881,6 +902,7 @@ void SMESHGUI_SewingDlg::onDetectClicked()
item->setData( GROUP_COLOR, groupColor ); item->setData( GROUP_COLOR, groupColor );
item->setData( GROUP_INDEX, i ); item->setData( GROUP_INDEX, i );
} }
myBusy = false;
onSelectGroup(); onSelectGroup();
@ -894,6 +916,7 @@ void SMESHGUI_SewingDlg::onDetectClicked()
void SMESHGUI_SewingDlg::onRemoveGroupClicked() void SMESHGUI_SewingDlg::onRemoveGroupClicked()
{ {
myBusy = true;
QList<QListWidgetItem*> selItems = ListCoincident->selectedItems(); QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
for ( int i = 0; i < selItems.count(); ++i ) for ( int i = 0; i < selItems.count(); ++i )
{ {
@ -901,10 +924,14 @@ void SMESHGUI_SewingDlg::onRemoveGroupClicked()
item->setSelected( false ); item->setSelected( false );
int groupIndex = item->data( GROUP_INDEX ).toInt(); int groupIndex = item->data( GROUP_INDEX ).toInt();
delete item; delete item;
if ( myBorderDisplayers[ groupIndex ])
myBorderDisplayers[ groupIndex ]->Hide(); myBorderDisplayers[ groupIndex ]->Hide();
SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ]; SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
aGRP.length( 0 ); aGRP.length( 0 );
} }
myBusy = false;
onSelectGroup();
UpdateButtons(); UpdateButtons();
} }
@ -925,9 +952,10 @@ void SMESHGUI_SewingDlg::showGroup( QListWidgetItem* item )
if ( groupIndex >= 0 && if ( groupIndex >= 0 &&
groupIndex < myBorders->coincidentGroups.length() ) groupIndex < myBorders->coincidentGroups.length() )
{ {
if ( !myBorderDisplayers[ groupIndex ]) if ( !myBorderDisplayers[ groupIndex ] && SMESH::GetCurrentVtkView())
myBorderDisplayers[ groupIndex ] = new BorderGroupDisplayer( myBorders, groupIndex, groupColor, myMesh ); myBorderDisplayers[ groupIndex ] = new BorderGroupDisplayer( myBorders, groupIndex, groupColor, myMesh );
bool wholeBorders = setCurrentGroup(); bool wholeBorders = setCurrentGroup();
if ( myBorderDisplayers[ groupIndex ])
myBorderDisplayers[ groupIndex ]->ShowGroup( wholeBorders ); myBorderDisplayers[ groupIndex ]->ShowGroup( wholeBorders );
} }
} }
@ -1111,6 +1139,7 @@ void SMESHGUI_SewingDlg::onGroupChange( bool partChange )
for ( int i = 0; i < ListEdit->count(); ++i ) for ( int i = 0; i < ListEdit->count(); ++i )
ListEdit->item( i )->setText( getPartText( aGRP[ i ])); ListEdit->item( i )->setText( getPartText( aGRP[ i ]));
if ( myBorderDisplayers[ myCurGroupIndex ])
myBorderDisplayers[ myCurGroupIndex ]->Update(); myBorderDisplayers[ myCurGroupIndex ]->Update();
if ( partChange ) if ( partChange )
@ -1410,6 +1439,7 @@ void SMESHGUI_SewingDlg::onCloseView()
{ {
DeactivateActiveDialog(); DeactivateActiveDialog();
mySelector = 0; mySelector = 0;
myActor = 0;
for ( size_t i = 0; i < myBorderDisplayers.size(); ++i ) for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
{ {
@ -1969,11 +1999,11 @@ void SMESHGUI_SewingDlg::BorderGroupDisplayer::Update()
myPartActors[ i ] = SMESH_Actor::New( obj, "", "", 1 ); myPartActors[ i ] = SMESH_Actor::New( obj, "", "", 1 );
myPartActors[ i ]->SetEdgeColor( myColor.redF(), myColor.greenF(), myColor.blueF() ); myPartActors[ i ]->SetEdgeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
myPartActors[ i ]->SetLineWidth( 3 * SMESH::GetFloat("SMESH:element_width",1)); myPartActors[ i ]->SetLineWidth( 3 * SMESH::GetFloat("SMESH:element_width",1));
myPartActors[ i ]->SetPickable( false );
myPartActors[ i ]->SetNodeColor( myColor.redF(), myColor.greenF(), myColor.blueF() ); myPartActors[ i ]->SetNodeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
myPartActors[ i ]->SetMarkerStd( VTK::MT_POINT, 13 ); myPartActors[ i ]->SetMarkerStd( VTK::MT_POINT, 13 );
myPartActors[ i ]->SetPickable ( false );
myViewWindow->AddActor( myPartActors[ i ]); myViewWindow->AddActor( myPartActors[ i ]);
myViewWindow->Repaint(); //myViewWindow->Repaint();
} }
} }
} }

View File

@ -47,17 +47,20 @@ namespace
/*! /*!
* \brief Node on a free border * \brief Node on a free border
*/ */
struct BNode struct BNode : public SMESH_TNodeXYZ
{ {
const SMDS_MeshNode * myNode;
mutable std::vector< BEdge* > myLinkedEdges; mutable std::vector< BEdge* > myLinkedEdges;
mutable std::vector< BEdge* > myCloseEdges; mutable std::vector< std::pair < BEdge*, double > > myCloseEdges; // edge & U
BNode(const SMDS_MeshNode * node): myNode( node ) {} BNode(const SMDS_MeshNode * node): SMESH_TNodeXYZ( node ) {}
const SMDS_MeshNode * Node() const { return _node; }
void AddLinked( BEdge* e ) const; void AddLinked( BEdge* e ) const;
void AddClose ( const BEdge* e ) const; void AddClose ( const BEdge* e, double u ) const;
BEdge* FindCloseEdgeOfBorder( int borderID ) const; BEdge* GetCloseEdge( size_t i ) const { return myCloseEdges[i].first; }
bool operator<(const BNode& other) const { return myNode->GetID() < other.myNode->GetID(); } double GetCloseU( size_t i ) const { return myCloseEdges[i].second; }
BEdge* GetCloseEdgeOfBorder( int borderID, double * u = 0 ) const;
bool IsCloseEdge( const BEdge* ) const;
bool operator<(const BNode& other) const { return Node()->GetID() < other.Node()->GetID(); }
}; };
/*! /*!
* \brief Edge of a free border * \brief Edge of a free border
@ -72,9 +75,9 @@ namespace
BEdge* myNext; BEdge* myNext;
const SMDS_MeshElement* myFace; const SMDS_MeshElement* myFace;
std::set< int > myCloseBorders; std::set< int > myCloseBorders;
bool myInGroup; int myInGroup;
BEdge():SMDS_LinearEdge( 0, 0 ), myBorderID(-1), myID(-1), myPrev(0), myNext(0), myInGroup(0) {} BEdge():SMDS_LinearEdge( 0, 0 ), myBorderID(-1), myID(-1), myPrev(0), myNext(0), myInGroup(-1) {}
void Set( const BNode * node1, void Set( const BNode * node1,
const BNode * node2, const BNode * node2,
@ -83,11 +86,15 @@ namespace
{ {
myBNode1 = node1; myBNode1 = node1;
myBNode2 = node2; myBNode2 = node2;
myNodes[0] = node1->myNode; myNodes[0] = node1->Node();
myNodes[1] = node2->myNode; myNodes[1] = node2->Node();
myFace = face; myFace = face;
setId( ID ); // mesh element ID setId( ID ); // mesh element ID
} }
bool IsInGroup() const
{
return myInGroup >= 0;
}
bool Contains( const BNode* n ) const bool Contains( const BNode* n ) const
{ {
return ( n == myBNode1 || n == myBNode2 ); return ( n == myBNode1 || n == myBNode2 );
@ -105,8 +112,8 @@ namespace
void Reverse() void Reverse()
{ {
std::swap( myBNode1, myBNode2 ); std::swap( myBNode1, myBNode2 );
myNodes[0] = myBNode1->myNode; myNodes[0] = myBNode1->Node();
myNodes[1] = myBNode2->myNode; myNodes[1] = myBNode2->Node();
} }
void Orient() void Orient()
{ {
@ -125,25 +132,95 @@ namespace
myNext->SetID( id + 1 ); myNext->SetID( id + 1 );
} }
} }
void FindRangeOfSameCloseBorders(BEdge* eRange[2]) bool IsOut( const gp_XYZ& point, const double tol, double& u ) const
{ {
gp_XYZ me = *myBNode2 - *myBNode1;
gp_XYZ n1p = point - *myBNode1;
u = ( me * n1p ) / me.SquareModulus(); // param [0,1] on this
if ( u < 0. ) return ( n1p.SquareModulus() > tol * tol );
if ( u > 1. ) return ( ( point - *myBNode2 ).SquareModulus() > tol * tol );
gp_XYZ proj = ( 1. - u ) * *myBNode1 + u * *myBNode2; // projection of the point on this
double dist2 = ( point - proj ).SquareModulus();
return ( dist2 > tol * tol );
}
bool IsOverlappingProjection( const BEdge* toE, const double u, bool is1st ) const
{
// is1st shows which end of toE is projected on this at u
double u2;
const double eps = 0.1;
if ( toE == myBNode1->GetCloseEdgeOfBorder( toE->myBorderID, &u2 ) ||
toE == myBNode2->GetCloseEdgeOfBorder( toE->myBorderID, &u2 ))
return (( 0 < u2 && u2 < 1 ) && // u2 is proj param of myBNode's on toE
( Abs( u2 - int( !is1st )) > eps ));
const BNode* n = is1st ? toE->myBNode2 : toE->myBNode1;
if ( this == n->GetCloseEdgeOfBorder( this->myBorderID, &u2 ))
return Abs( u - u2 ) > eps;
return false;
}
bool GetRangeOfSameCloseBorders(BEdge* eRange[2], const std::set< int >& bordIDs)
{
if ( this->myCloseBorders != bordIDs )
return false;
eRange[0] = this; eRange[0] = this;
while ( eRange[0]->myPrev && eRange[0]->myPrev->myCloseBorders == this->myCloseBorders ) while ( eRange[0]->myPrev && eRange[0]->myPrev->myCloseBorders == bordIDs )
{ {
if ( eRange[0]->myPrev == this /*|| eRange[0]->myPrev->myInGroup*/ ) if ( eRange[0]->myPrev == this /*|| eRange[0]->myPrev->myInGroup*/ )
break; break;
eRange[0] = eRange[0]->myPrev; eRange[0] = eRange[0]->myPrev;
} }
eRange[1] = this; eRange[1] = this;
if ( eRange[0]->myPrev != this ) // not closed range if ( eRange[0]->myPrev != this ) // not closed range
while ( eRange[1]->myNext && eRange[1]->myNext->myCloseBorders == this->myCloseBorders ) while ( eRange[1]->myNext && eRange[1]->myNext->myCloseBorders == bordIDs )
{ {
if ( eRange[1]->myNext == this /*|| eRange[1]->myNext->myInGroup*/ ) if ( eRange[1]->myNext == this /*|| eRange[1]->myNext->myInGroup*/ )
break; break;
eRange[1] = eRange[1]->myNext; eRange[1] = eRange[1]->myNext;
} }
return ( eRange[0] != eRange[1] );
}
}; // class BEdge
void extendPart( BEdge* & e1, BEdge* & e2, const std::set< int >& bordIDs, int groupID )
{
if (( e1->myPrev == e2 ) ||
( e1 == e2 && e1->myPrev && e1->myPrev->myInGroup == groupID ))
return; // full free border already
double u;
BEdge* be;
std::set<int>::const_iterator bord;
if ( e1->myPrev )
{
for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord )
if (( *bord != e1->myBorderID ) &&
(( be = e1->myBNode1->GetCloseEdgeOfBorder( *bord, &u ))) &&
( be->myInGroup == groupID ) &&
( 0 < u && u < 1 ) &&
( be->IsOverlappingProjection( e1->myPrev, u, false )))
{
e1 = e1->myPrev;
break;
}
}
if ( e2->myNext )
{
for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord )
if (( *bord != e2->myBorderID ) &&
(( be = e2->myBNode2->GetCloseEdgeOfBorder( *bord, &u ))) &&
( be->myInGroup == groupID ) &&
( 0 < u && u < 1 ) &&
( be->IsOverlappingProjection( e2->myNext, u, true )))
{
e2 = e2->myNext;
break;
}
}
} }
};
void BNode::AddLinked( BEdge* e ) const void BNode::AddLinked( BEdge* e ) const
{ {
@ -164,17 +241,32 @@ namespace
myLinkedEdges[i]->RemoveLinked( myLinkedEdges[j] ); myLinkedEdges[i]->RemoveLinked( myLinkedEdges[j] );
} }
} }
void BNode::AddClose ( const BEdge* e ) const void BNode::AddClose ( const BEdge* e, double u ) const
{ {
if ( ! e->Contains( this )) if ( ! e->Contains( this ))
myCloseEdges.push_back( const_cast< BEdge* >( e )); myCloseEdges.push_back( make_pair( const_cast< BEdge* >( e ), u ));
} }
BEdge* BNode::FindCloseEdgeOfBorder( int borderID ) const BEdge* BNode::GetCloseEdgeOfBorder( int borderID, double * uPtr ) const
{
BEdge* e = 0;
double u = 0;
for ( size_t i = 0; i < myCloseEdges.size(); ++i )
if ( borderID == GetCloseEdge( i )->myBorderID )
{
if ( e && Abs( u - 0.5 ) < Abs( GetCloseU( i ) - 0.5 ))
continue;
u = GetCloseU( i );
e = GetCloseEdge ( i );
}
if ( uPtr ) *uPtr = u;
return e;
}
bool BNode::IsCloseEdge( const BEdge* e ) const
{ {
for ( size_t i = 0; i < myCloseEdges.size(); ++i ) for ( size_t i = 0; i < myCloseEdges.size(); ++i )
if ( borderID == myCloseEdges[ i ]->myBorderID ) if ( e == GetCloseEdge( i ) )
return myCloseEdges[ i ]; return true;
return 0; return false;
} }
/// Accessor to SMDS_MeshElement* inherited by BEdge /// Accessor to SMDS_MeshElement* inherited by BEdge
@ -333,12 +425,11 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
std::vector< const SMDS_MeshElement* > candidateEdges; std::vector< const SMDS_MeshElement* > candidateEdges;
for ( bn = bNodes.begin(); bn != bNodes.end(); ++bn ) for ( bn = bNodes.begin(); bn != bNodes.end(); ++bn )
{ {
gp_Pnt point = SMESH_TNodeXYZ( bn->myNode ); searcher->FindElementsByPoint( *bn, SMDSAbs_Edge, candidateEdges );
searcher->FindElementsByPoint( point, SMDSAbs_Edge, candidateEdges );
if ( candidateEdges.size() <= bn->myLinkedEdges.size() ) if ( candidateEdges.size() <= bn->myLinkedEdges.size() )
continue; continue;
double nodeTol = 0; double nodeTol = 0, u;
for ( size_t i = 0; i < bn->myLinkedEdges.size(); ++i ) for ( size_t i = 0; i < bn->myLinkedEdges.size(); ++i )
nodeTol = Max( nodeTol, bordToler[ bn->myLinkedEdges[ i ]->myBorderID ]); nodeTol = Max( nodeTol, bordToler[ bn->myLinkedEdges[ i ]->myBorderID ]);
@ -346,9 +437,8 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
{ {
const BEdge* be = static_cast< const BEdge* >( candidateEdges[ i ]); const BEdge* be = static_cast< const BEdge* >( candidateEdges[ i ]);
double tol = Max( nodeTol, bordToler[ be->myBorderID ]); double tol = Max( nodeTol, bordToler[ be->myBorderID ]);
if ( maxTolerance - tol < 1e-12 || if ( !be->IsOut( *bn, tol, u ))
!SMESH_MeshAlgos::IsOut( be, point, tol )) bn->AddClose( be, u );
bn->AddClose( be );
} }
} }
@ -366,8 +456,8 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
for ( size_t iE1 = 0; iE1 < be.myBNode1->myCloseEdges.size(); ++iE1 ) for ( size_t iE1 = 0; iE1 < be.myBNode1->myCloseEdges.size(); ++iE1 )
{ {
// find edges of the same border close to both nodes of the edge // find edges of the same border close to both nodes of the edge
BEdge* closeE1 = be.myBNode1->myCloseEdges[ iE1 ]; BEdge* closeE1 = be.myBNode1->GetCloseEdge( iE1 );
BEdge* closeE2 = be.myBNode2->FindCloseEdgeOfBorder( closeE1->myBorderID ); BEdge* closeE2 = be.myBNode2->GetCloseEdgeOfBorder( closeE1->myBorderID );
if ( !closeE2 ) if ( !closeE2 )
continue; continue;
// check that edges connecting closeE1 and closeE2 (if any) are also close to 'be' // check that edges connecting closeE1 and closeE2 (if any) are also close to 'be'
@ -378,7 +468,7 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
{ {
BEdge* ce = closeE1; BEdge* ce = closeE1;
do { do {
coincide = ( ce->myBNode2->FindCloseEdgeOfBorder( be.myBorderID )); coincide = ( ce->myBNode2->GetCloseEdgeOfBorder( be.myBorderID ));
ce = ce->myNext; ce = ce->myNext;
} while ( coincide && ce && ce != closeE2 ); } while ( coincide && ce && ce != closeE2 );
@ -415,9 +505,9 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
for ( size_t i = 0; i < borders.size(); ++i ) for ( size_t i = 0; i < borders.size(); ++i )
{ {
BEdge* be = borders[i]; BEdge* be = borders[i];
foundFreeBordes._borders[i].push_back( be->myBNode1->myNode ); foundFreeBordes._borders[i].push_back( be->myBNode1->Node() );
do { do {
foundFreeBordes._borders[i].push_back( be->myBNode2->myNode ); foundFreeBordes._borders[i].push_back( be->myBNode2->Node() );
be = be->myNext; be = be->myNext;
} }
while ( be && be != borders[i] ); while ( be && be != borders[i] );
@ -427,55 +517,121 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
TFreeBorderPart part; TFreeBorderPart part;
TCoincidentGroup group; TCoincidentGroup group;
for ( size_t i = 0; i < borders.size(); ++i ) vector< BEdge* > ranges; // couples of edges delimiting parts
BEdge* be = 0; // a current edge
int skipGroup = bEdges.size(); // a group ID used to avoid repeating treatment of edges
for ( int i = 0, nbBords = borders.size(); i < nbBords; i += bool(!be) )
{ {
BEdge* be = borders[i]; if ( !be )
be = borders[i];
// look for an edge close to other borders // look for an edge close to other borders
do { do {
if ( !be->myInGroup && !be->myCloseBorders.empty() ) if ( !be->IsInGroup() && !be->myCloseBorders.empty() )
break; break;
be = be->myNext; be = be->myNext;
} while ( be && be != borders[i] ); } while ( be && be != borders[i] );
if ( !be || be->myInGroup || be->myCloseBorders.empty() ) if ( !be || be->IsInGroup() || be->myCloseBorders.empty() )
continue; // all edges of a border treated or are non-coincident {
be = 0;
continue; // all edges of a border are treated or non-coincident
}
group.clear(); group.clear();
ranges.clear();
// look for the 1st and last edge of a coincident group // look for the 1st and last edge of a coincident group
BEdge* beRange[2]; BEdge* beRange[2];
be->FindRangeOfSameCloseBorders( beRange ); if ( !be->GetRangeOfSameCloseBorders( beRange, be->myCloseBorders ))
{
be->myInGroup = skipGroup;
be = be->myNext;
continue;
}
ranges.push_back( beRange[0] );
ranges.push_back( beRange[1] );
int groupID = foundFreeBordes._coincidentGroups.size();
be = beRange[0];
be->myInGroup = groupID;
while ( be != beRange[1] )
{
be->myInGroup = groupID;
be = be->myNext;
}
beRange[1]->myInGroup = groupID;
// add parts of other borders
BEdge* be1st = beRange[0]; BEdge* be1st = beRange[0];
closeEdges.clear();
std::set<int>::iterator closeBord = be1st->myCloseBorders.begin();
for ( ; closeBord != be1st->myCloseBorders.end(); ++closeBord )
closeEdges.push_back( be1st->myBNode2->GetCloseEdgeOfBorder( *closeBord ));
for ( size_t iE = 0; iE < closeEdges.size(); ++iE )
{
be = closeEdges[ iE ];
if ( !be ) continue;
bool ok = be->GetRangeOfSameCloseBorders( beRange, be->myCloseBorders );
if ( !ok && be->myPrev )
ok = be->myPrev->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders );
if ( !ok && be->myNext )
ok = be->myNext->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders );
if ( !ok )
continue;
be = beRange[0];
if ( be->myCloseBorders != be1st->myCloseBorders )
{
//add missing edges to closeEdges
closeBord = be->myCloseBorders.begin();
for ( ; closeBord != be->myCloseBorders.end(); ++closeBord )
if ( !be1st->myCloseBorders.count( *closeBord ))
closeEdges.push_back( be->myBNode2->GetCloseEdgeOfBorder( *closeBord ));
}
ranges.push_back( beRange[0] );
ranges.push_back( beRange[1] );
be->myInGroup = groupID;
while ( be != beRange[1] )
{
be->myInGroup = groupID;
be = be->myNext;
}
beRange[1]->myInGroup = groupID;
}
if ( ranges.size() > 2 )
{
for ( size_t iR = 1; iR < ranges.size(); iR += 2 )
extendPart( ranges[ iR-1 ], ranges[ iR ], be1st->myCloseBorders, groupID );
// fill in a group // fill in a group
beRange[0] = ranges[0];
beRange[1] = ranges[1];
part._border = i; part._border = i;
part._node1 = beRange[0]->myID; part._node1 = beRange[0]->myID;
part._node2 = beRange[0]->myID + 1; part._node2 = beRange[0]->myID + 1;
part._nodeLast = beRange[1]->myID + 1; part._nodeLast = beRange[1]->myID + 1;
group.push_back( part ); group.push_back( part );
be = beRange[0]; be1st = beRange[0];
be->myInGroup = true; for ( size_t iR = 3; iR < ranges.size(); iR += 2 )
while ( be != beRange[1] )
{ {
be->myInGroup = true; beRange[0] = ranges[iR-1];
be = be->myNext; beRange[1] = ranges[iR-0];
}
beRange[1]->myInGroup = true;
// add parts of other borders
std::set<int>::iterator closeBord = be1st->myCloseBorders.begin();
for ( ; closeBord != be1st->myCloseBorders.end(); ++closeBord )
{
be = be1st->myBNode2->FindCloseEdgeOfBorder( *closeBord );
if ( !be ) continue;
be->FindRangeOfSameCloseBorders( beRange );
// find out mutual orientation of borders // find out mutual orientation of borders
bool reverse = ( beRange[0]->myBNode1->FindCloseEdgeOfBorder( i ) != be1st && double u1, u2;
beRange[0]->myBNode2->FindCloseEdgeOfBorder( i ) != be1st ); be1st ->IsOut( *beRange[ 0 ]->myBNode1, maxTolerance, u1 );
beRange[ 0 ]->IsOut( *be1st->myBNode1, maxTolerance, u2 );
bool reverse = (( u1 < 0 || u1 > 1 ) && ( u2 < 0 || u2 > 1 ));
// fill in a group // fill in a group
part._border = beRange[0]->myBorderID; part._border = beRange[0]->myBorderID;
@ -490,18 +646,29 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
part._nodeLast = beRange[1]->myID + 1; part._nodeLast = beRange[1]->myID + 1;
} }
group.push_back( part ); group.push_back( part );
}
foundFreeBordes._coincidentGroups.push_back( group );
}
else
{
beRange[0] = ranges[0];
beRange[1] = ranges[1];
be = beRange[0]; be = beRange[0];
be->myInGroup = true; be->myInGroup = skipGroup;
while ( be != beRange[1] ) while ( be != beRange[1] )
{ {
be->myInGroup = true; be->myInGroup = skipGroup;
be = be->myNext; be = be->myNext;
} }
beRange[1]->myInGroup = true; beRange[1]->myInGroup = skipGroup;
} }
foundFreeBordes._coincidentGroups.push_back( group ); be = ranges[1];
} // loop on free borders } // loop on free borders
}
return;
} // SMESH_MeshAlgos::FindCoincidentFreeBorders()

View File

@ -1210,19 +1210,13 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
{ {
gp_Vec edge( xyz[i-1], xyz[i] ); gp_Vec edge( xyz[i-1], xyz[i] );
gp_Vec n1p ( xyz[i-1], point ); gp_Vec n1p ( xyz[i-1], point );
// double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude();
// if ( dist > tol )
// continue;
// gp_Vec n2p( xyz[i], point );
// if ( fabs( edge.Magnitude() - n1p.Magnitude() - n2p.Magnitude()) > tol )
// continue;
double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
if ( u < 0. ) { if ( u <= 0. ) {
if ( n1p.SquareMagnitude() < tol * tol ) if ( n1p.SquareMagnitude() < tol * tol )
return false; return false;
continue; continue;
} }
if ( u > 1. ) { if ( u >= 1. ) {
if ( point.SquareDistance( xyz[i] ) < tol * tol ) if ( point.SquareDistance( xyz[i] ) < tol * tol )
return false; return false;
continue; continue;

View File

@ -4641,11 +4641,12 @@ SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
CORBA::Short nbSewed = 0; CORBA::Short nbSewed = 0;
SMESH_MeshAlgos::TFreeBorderVec groups; SMESH_MeshAlgos::TFreeBorderVec groups;
SMESH_MeshAlgos::TFreeBorder borderNodes; // triples on nodes for every FreeBorderPart SMESH_MeshAlgos::TFreeBorder borderNodes; // triples of nodes for every FreeBorderPart
// check the input // check the input and collect nodes
for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i ) for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i )
{ {
borderNodes.clear();
const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ]; const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP ) for ( CORBA::ULong iP = 0; iP < aGRP.length(); ++iP )
{ {
@ -4672,71 +4673,70 @@ SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::node2", SALOME::BAD_PARAM);
if ( !n3 ) if ( !n3 )
THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM); THROW_SALOME_CORBA_EXCEPTION("Nonexistent FreeBorderPart::nodeLast", SALOME::BAD_PARAM);
borderNodes.push_back( n1 );
borderNodes.push_back( n2 );
borderNodes.push_back( n3 );
}
groups.push_back( borderNodes );
}
// SewFreeBorder() can merge nodes, thus nodes stored in 'groups' can become dead;
// to get nodes that replace other nodes during merge we create 0D elements
// on each node and MergeNodes() will replace underlying nodes of 0D elements by
// new ones.
vector< const SMDS_MeshElement* > tmp0Delems;
for ( size_t i = 0; i < groups.size(); ++i )
{
SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
for ( size_t iN = 0; iN < nodes.size(); ++iN )
{
SMDS_ElemIteratorPtr it0D = nodes[iN]->GetInverseElementIterator(SMDSAbs_0DElement);
if ( it0D->more() )
tmp0Delems.push_back( it0D->next() );
else
tmp0Delems.push_back( getMeshDS()->Add0DElement( nodes[iN] ));
} }
} }
//TIDSortedElemSet dummy; SMESH_TRY;
::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK; ::SMESH_MeshEditor::Sew_Error res, ok = ::SMESH_MeshEditor::SEW_OK;
for ( CORBA::ULong i = 0; i < freeBorders.coincidentGroups.length(); ++i ) int i0D = 0;
for ( size_t i = 0; i < groups.size(); ++i )
{ {
const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ]; bool isBordToBord = true;
if ( aGRP.length() < 2 )
continue;
//int n1bord2, n2bord2;
bool groupSewed = false; bool groupSewed = false;
for ( CORBA::ULong iP = 1; iP < aGRP.length(); ++iP ) SMESH_MeshAlgos::TFreeBorder& nodes = groups[i];
for ( size_t iN = 3; iN+2 < nodes.size(); iN += 3 )
{ {
const SMESH::FreeBorderPart& aPART_0 = aGRP[ 0 ]; const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
const SMESH::FreeBorder& aBRD_0 = freeBorders.borders[ aPART_0.border ]; const SMDS_MeshNode* n1 = tmp0Delems[ i0D + 1 ]->GetNode( 0 );
const SMDS_MeshNode* n2 = tmp0Delems[ i0D + 2 ]->GetNode( 0 );
const SMDS_MeshNode* n0 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.node1 ]); const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
const SMDS_MeshNode* n1 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.node2 ]); const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.nodeLast ]); const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
const SMESH::FreeBorderPart& aPART = aGRP[ iP ];
const SMESH::FreeBorder& aBRD = freeBorders.borders[ aPART.border ];
const SMDS_MeshNode* n3 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node1 ]);
const SMDS_MeshNode* n4 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.node2 ]);
const SMDS_MeshNode* n5 = getMeshDS()->FindNode( aBRD.nodeIDs[ aPART.nodeLast ]);
if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 ) if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
continue; continue;
// if ( iP == 1 ) if ( !isBordToBord )
// {
// n1bord2 = aBRD.nodeIDs[ aPART.node1 ];
// n2bord2 = aBRD.nodeIDs[ aPART.node2 ];
// }
// else if ( !SMESH_MeshAlgos::FindFaceInSet( n0, n1, dummy, dummy ))
// {
// // a face including n0 and n1 was split;
// // find a new face starting at n0 in order to get a new n1
// const SMDS_MeshNode* n1test = getMeshDS()->FindNode( n1bord2 );
// const SMDS_MeshNode* n2test = getMeshDS()->FindNode( n2bord2 );
// if ( n1test && SMESH_MeshAlgos::FindFaceInSet( n0, n1test, dummy, dummy ))
// n1 = n1test;
// else if ( n2test && SMESH_MeshAlgos::FindFaceInSet( n0, n2test, dummy, dummy ))
// n1 = n2test;
// // else continue; ??????
// }
if ( iP > 1 )
{ {
n1 = n2; // at border-to-side sewing only last side node (n1) is needed n1 = n2; // at border-to-side sewing only last side node (n1) is needed
n2 = 0; // and n2 is not used n2 = 0; // and n2 is not used
} }
// 1st border moves to 2nd // 1st border moves to 2nd
res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
n0 ,n1 ,n2 ,// 2nd n0 ,n1 ,n2 ,// 2nd
/*2ndIsFreeBorder=*/ iP == 1, /*2ndIsFreeBorder=*/ isBordToBord,
createPolygons, createPolyhedra); createPolygons, createPolyhedra);
groupSewed = ( res == ok ); groupSewed = ( res == ok );
isBordToBord = false;
} }
i0D += nodes.size();
nbSewed += groupSewed; nbSewed += groupSewed;
} }
@ -4745,6 +4745,20 @@ SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
<< createPolygons << ", " << createPolygons << ", "
<< createPolyhedra << " )"; << createPolyhedra << " )";
SMESH_CATCH( SMESH::doNothing );
declareMeshModified( /*isReComputeSafe=*/false );
// remove tmp 0D elements
SMESH_TRY;
set< const SMDS_MeshElement* > removed0D;
for ( size_t i = 0; i < tmp0Delems.size(); ++i )
{
if ( removed0D.insert( tmp0Delems[i] ).second )
getMeshDS()->RemoveFreeElement( tmp0Delems[i], /*sm=*/0, /*fromGroups=*/false );
}
SMESH_CATCH( SMESH::throwCorbaException );
return nbSewed; return nbSewed;
} }