mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2024-12-26 09:20:34 +05:00
Debug 23078: [CEA 1498] Sewing of meshes without having to set the nodes ids
This commit is contained in:
parent
0463dee592
commit
fd96feab4b
BIN
doc/salome/gui/SMESH/images/sewing1.png
Executable file → Normal file
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 |
BIN
doc/salome/gui/SMESH/images/sewing_auto.png
Normal file
BIN
doc/salome/gui/SMESH/images/sewing_auto.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
doc/salome/gui/SMESH/images/sewing_manual.png
Normal file
BIN
doc/salome/gui/SMESH/images/sewing_manual.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
BIN
doc/salome/gui/SMESH/images/swap.png
Normal file
BIN
doc/salome/gui/SMESH/images/swap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 527 B |
@ -41,11 +41,9 @@ To apply this algorithm when you define your mesh, select <b>Body
|
||||
This dialog allows to define
|
||||
<ul>
|
||||
<li>\b Name of the algorithm. </li>
|
||||
|
||||
<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
|
||||
initial cell size, then a mesh element is not created. </li>
|
||||
|
||||
<li> <b> Implement Edges </b> check-box activates incorporation of
|
||||
geometrical edges in the mesh.
|
||||
|
||||
@ -64,9 +62,10 @@ This dialog allows to define
|
||||
System.</li>
|
||||
<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
|
||||
normalized at [0.0,1.0]. The whole range of geometry can be
|
||||
divided into sub-ranges with their own spacing formulas to apply;
|
||||
\a t varies between 0.0 and 1.0 within each sub-range. \b Insert button
|
||||
normalized at [0.0,1.0]. <em>f(t)</em> must be non-negative
|
||||
at 0. <= \a t <= 1. The whole extent of geometry can be
|
||||
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
|
||||
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
|
||||
|
@ -16,8 +16,8 @@ and hypotheses.
|
||||
|
||||
Mesh generation on the geometry is performed in the bottom-up
|
||||
flow: nodes on vertices are created first, then edges are divided into
|
||||
segments using nodes on vertices; the segments of edges are then
|
||||
used to mesh faces; then the mesh of faces is used to mesh
|
||||
segments using nodes on vertices; the node of segments are then
|
||||
used to mesh faces; then the nodes of faces are used to mesh
|
||||
solids. This automatically assures the conformity of the mesh.
|
||||
|
||||
It is required to choose a meshing algorithm for every dimension of
|
||||
|
@ -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
|
||||
the type of sewing operation you would like to perform.</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>
|
||||
|
||||
|
||||
<br>
|
||||
\anchor free_borders_anchor
|
||||
<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
|
||||
Automatic mode, the program finds free borders coincident within a
|
||||
certain tolerance and sew them. Optionally it is possible to adjust
|
||||
the found free borders before sewing. In the \b Manual mode you are to
|
||||
define borders to sew by picking three nodes of each border.
|
||||
specified tolerance and sews them. Optionally it is possible to
|
||||
visually check and correct is necessary the found free borders before
|
||||
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
|
||||
<center>Default mode is \a Automatic</center>
|
||||
|
||||
For sewing free borders you should define three points on each border:
|
||||
first, second and the last node:
|
||||
To use \b Automatic sewing:
|
||||
<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>
|
||||
<li>the first node specifies beginning of the border;</li>
|
||||
<li>the second node specifies the part of the border which should be
|
||||
|
@ -38,7 +38,6 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
|
||||
Status aResult = DRS_OK;
|
||||
|
||||
int nbNodes, nbCells;
|
||||
//int i;
|
||||
|
||||
char *file2Read = (char *)myFile.c_str();
|
||||
FILE* aFileId = fopen(file2Read, "w+");
|
||||
@ -55,7 +54,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
|
||||
nbNodes = myMesh->NbNodes();
|
||||
|
||||
/* 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_faces = myMesh->NbFaces();
|
||||
nb_of_volumes = myMesh->NbVolumes();
|
||||
@ -64,7 +63,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
|
||||
SCRUTE(nb_of_faces);
|
||||
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);
|
||||
|
||||
/****************************************************************************
|
||||
@ -74,7 +73,7 @@ Driver_Mesh::Status DriverDAT_W_SMDS_Mesh::Perform()
|
||||
SMDS_NodeIteratorPtr itNodes=myMesh->nodesIterator();
|
||||
while(itNodes->more()){
|
||||
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());
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -56,7 +56,8 @@ DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh():
|
||||
myDoGroupOfVolumes (false),
|
||||
myDoGroupOf0DElems(false),
|
||||
myDoGroupOfBalls(false),
|
||||
myAutoDimension(true)
|
||||
myAutoDimension(true),
|
||||
myAddODOnVertices(false)
|
||||
{}
|
||||
|
||||
void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName,
|
||||
|
@ -139,8 +139,12 @@ const SMDS_MeshNode* SMDS_Mesh0DElement::GetNode(const int ind) const
|
||||
//function : ChangeNode
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
bool SMDS_Mesh0DElement::ChangeNode (const SMDS_MeshNode * node)
|
||||
bool SMDS_Mesh0DElement::ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes)
|
||||
{
|
||||
myNode = node;
|
||||
return true;
|
||||
if ( nbNodes == 1 )
|
||||
{
|
||||
myNode = nodes[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -34,8 +34,7 @@ class SMDS_EXPORT SMDS_Mesh0DElement: public SMDS_MeshCell
|
||||
{
|
||||
public:
|
||||
SMDS_Mesh0DElement (const SMDS_MeshNode * node);
|
||||
bool ChangeNode (const SMDS_MeshNode * node);
|
||||
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes) {return false;};
|
||||
virtual bool ChangeNodes(const SMDS_MeshNode* nodes[], const int nbNodes);
|
||||
virtual void Print (std::ostream & OS) const;
|
||||
|
||||
virtual SMDSAbs_ElementType GetType() const;
|
||||
|
@ -7371,8 +7371,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
|
||||
for ( ; eIt != elems.end(); eIt++ )
|
||||
{
|
||||
const SMDS_MeshElement* elem = *eIt;
|
||||
int nbNodes = elem->NbNodes();
|
||||
int aShapeId = FindShape( elem );
|
||||
const int nbNodes = elem->NbNodes();
|
||||
const int aShapeId = FindShape( elem );
|
||||
|
||||
nodeSet.clear();
|
||||
curNodes.resize( nbNodes );
|
||||
@ -7912,17 +7912,24 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
|
||||
|
||||
if ( isOk ) // the non-poly elem remains valid after sticking nodes
|
||||
{
|
||||
elemType.Init( elem ).SetID( elem->GetID() );
|
||||
if ( nbNodes != nbUniqueNodes )
|
||||
{
|
||||
elemType.Init( elem ).SetID( elem->GetID() );
|
||||
|
||||
SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;
|
||||
aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
|
||||
SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;
|
||||
aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
|
||||
|
||||
uniqueNodes.resize(nbUniqueNodes);
|
||||
SMDS_MeshElement* newElem = this->AddElement( uniqueNodes, elemType );
|
||||
if ( sm && newElem )
|
||||
sm->AddElement( newElem );
|
||||
if ( elem != newElem )
|
||||
ReplaceElemInGroups( elem, newElem, aMesh );
|
||||
uniqueNodes.resize(nbUniqueNodes);
|
||||
SMDS_MeshElement* newElem = this->AddElement( uniqueNodes, elemType );
|
||||
if ( sm && newElem )
|
||||
sm->AddElement( newElem );
|
||||
if ( elem != newElem )
|
||||
ReplaceElemInGroups( elem, newElem, aMesh );
|
||||
}
|
||||
else
|
||||
{
|
||||
aMesh->ChangeElementNodes( elem, & curNodes[0], nbNodes );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Remove invalid regular element or invalid polygon
|
||||
@ -8749,7 +8756,8 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
|
||||
}
|
||||
// find coincident
|
||||
TListOfListOfElementsID equalGroups;
|
||||
FindEqualElements( segments, equalGroups );
|
||||
if ( !segments.empty() )
|
||||
FindEqualElements( segments, equalGroups );
|
||||
if ( !equalGroups.empty() )
|
||||
{
|
||||
// remove from segments those that will be removed
|
||||
|
@ -329,14 +329,13 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
|
||||
|
||||
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(RemoveGroupButton, 3, 2);
|
||||
aCoincidentLayout->addWidget(SelectAllCheck, 4, 0);
|
||||
aCoincidentLayout->addWidget(SelectAllCheck, 5, 0);
|
||||
aCoincidentLayout->setRowMinimumHeight(1, 10);
|
||||
aCoincidentLayout->setRowStretch (1, 5);
|
||||
|
||||
GroupCoincidentLayout->addWidget( GroupCoincident );
|
||||
aCoincidentLayout->setRowStretch (4, 5);
|
||||
aCoincidentLayout->setRowStretch (5, 0);
|
||||
|
||||
/*****************************************/
|
||||
// Controls for editing the selected group
|
||||
@ -391,8 +390,13 @@ SMESHGUI_SewingDlg::SMESHGUI_SewingDlg( SMESHGUI* theModule )
|
||||
GroupEditLayout->addWidget(SwapBut, 1, 7);
|
||||
GroupEditLayout->addWidget(StepLabel, 1, 8);
|
||||
GroupEditLayout->addWidget(StepSpin, 1, 9);
|
||||
GroupEditLayout->setRowStretch( 0, 1 );
|
||||
|
||||
GroupCoincidentLayout->addWidget( GroupCoincident );
|
||||
GroupCoincidentLayout->addWidget( GroupEdit );
|
||||
GroupCoincidentLayout->setRowStretch( 0, 10 );
|
||||
GroupCoincidentLayout->setRowStretch( 1, 1 );
|
||||
|
||||
aSewFreeBordersLayout->addWidget( GroupCoincidentWidget );
|
||||
|
||||
// layout
|
||||
@ -579,6 +583,7 @@ void SMESHGUI_SewingDlg::ConstructorsClicked (int constructorId)
|
||||
{
|
||||
ModeGroup->hide();
|
||||
SewFreeBordersWidget->hide();
|
||||
restoreDisplayMode();
|
||||
}
|
||||
|
||||
bool isNodeSelection = true;
|
||||
@ -673,12 +678,11 @@ void SMESHGUI_SewingDlg::ConstructorsClicked (int constructorId)
|
||||
LineEdit4->setValidator(new SMESHGUI_IdValidator(this, 1));
|
||||
}
|
||||
|
||||
if ( isNodeSelection )
|
||||
{
|
||||
SMESH::SetPointRepresentation(true);
|
||||
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
|
||||
aViewWindow->SetSelectionMode(NodeSelection);
|
||||
}
|
||||
if ( myActor )
|
||||
myActor->SetPointRepresentation( isNodeSelection );
|
||||
|
||||
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
|
||||
aViewWindow->SetSelectionMode( isNodeSelection ? NodeSelection : ActorSelection );
|
||||
|
||||
UpdateButtons();
|
||||
|
||||
@ -700,7 +704,8 @@ void SMESHGUI_SewingDlg::setDisplayMode()
|
||||
{
|
||||
myStoredEntityMode = 0;
|
||||
myStoredRepresentation = -1;
|
||||
if ( myActor )
|
||||
|
||||
if ( myActor && AutoSewCheck->isVisible() && !AutoSewCheck->isChecked() )
|
||||
{
|
||||
myStoredEntityMode = myActor->GetEntityMode();
|
||||
myStoredRepresentation = myActor->GetRepresentation();
|
||||
@ -728,6 +733,9 @@ void SMESHGUI_SewingDlg::restoreDisplayMode()
|
||||
myStoredEntityMode = 0;
|
||||
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() )
|
||||
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() );
|
||||
|
||||
QApplication::instance()->processEvents();
|
||||
@ -774,6 +788,12 @@ void SMESHGUI_SewingDlg::onAutoSew( int isAuto )
|
||||
if ( ModeButGrp->checkedId() == MODE_AUTO )
|
||||
SewFreeBordersWidget->show();
|
||||
|
||||
if ( isAuto )
|
||||
restoreDisplayMode();
|
||||
else
|
||||
setDisplayMode();
|
||||
SMESH::RepaintCurrentView();
|
||||
|
||||
UpdateButtons();
|
||||
|
||||
updateGeometry();
|
||||
@ -847,6 +867,7 @@ QString SMESHGUI_SewingDlg::getGroupText(int groupIndex)
|
||||
|
||||
void SMESHGUI_SewingDlg::onDetectClicked()
|
||||
{
|
||||
myBusy = true;
|
||||
ListCoincident->clear();
|
||||
|
||||
if ( myMesh->_is_nil() )
|
||||
@ -881,6 +902,7 @@ void SMESHGUI_SewingDlg::onDetectClicked()
|
||||
item->setData( GROUP_COLOR, groupColor );
|
||||
item->setData( GROUP_INDEX, i );
|
||||
}
|
||||
myBusy = false;
|
||||
|
||||
onSelectGroup();
|
||||
|
||||
@ -894,6 +916,7 @@ void SMESHGUI_SewingDlg::onDetectClicked()
|
||||
|
||||
void SMESHGUI_SewingDlg::onRemoveGroupClicked()
|
||||
{
|
||||
myBusy = true;
|
||||
QList<QListWidgetItem*> selItems = ListCoincident->selectedItems();
|
||||
for ( int i = 0; i < selItems.count(); ++i )
|
||||
{
|
||||
@ -901,10 +924,14 @@ void SMESHGUI_SewingDlg::onRemoveGroupClicked()
|
||||
item->setSelected( false );
|
||||
int groupIndex = item->data( GROUP_INDEX ).toInt();
|
||||
delete item;
|
||||
myBorderDisplayers[ groupIndex ]->Hide();
|
||||
if ( myBorderDisplayers[ groupIndex ])
|
||||
myBorderDisplayers[ groupIndex ]->Hide();
|
||||
SMESH::FreeBordersGroup& aGRP = myBorders->coincidentGroups[ myCurGroupIndex ];
|
||||
aGRP.length( 0 );
|
||||
}
|
||||
myBusy = false;
|
||||
|
||||
onSelectGroup();
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
@ -917,7 +944,7 @@ void SMESHGUI_SewingDlg::showGroup( QListWidgetItem* item )
|
||||
{
|
||||
if ( !item ||
|
||||
item->listWidget() != ListCoincident ||
|
||||
!haveBorders() )
|
||||
!haveBorders())
|
||||
return;
|
||||
|
||||
int groupIndex = item->data( GROUP_INDEX ).toInt();
|
||||
@ -925,10 +952,11 @@ void SMESHGUI_SewingDlg::showGroup( QListWidgetItem* item )
|
||||
if ( groupIndex >= 0 &&
|
||||
groupIndex < myBorders->coincidentGroups.length() )
|
||||
{
|
||||
if ( !myBorderDisplayers[ groupIndex ])
|
||||
if ( !myBorderDisplayers[ groupIndex ] && SMESH::GetCurrentVtkView())
|
||||
myBorderDisplayers[ groupIndex ] = new BorderGroupDisplayer( myBorders, groupIndex, groupColor, myMesh );
|
||||
bool wholeBorders = setCurrentGroup();
|
||||
myBorderDisplayers[ groupIndex ]->ShowGroup( wholeBorders );
|
||||
if ( myBorderDisplayers[ groupIndex ])
|
||||
myBorderDisplayers[ groupIndex ]->ShowGroup( wholeBorders );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1111,7 +1139,8 @@ void SMESHGUI_SewingDlg::onGroupChange( bool partChange )
|
||||
for ( int i = 0; i < ListEdit->count(); ++i )
|
||||
ListEdit->item( i )->setText( getPartText( aGRP[ i ]));
|
||||
|
||||
myBorderDisplayers[ myCurGroupIndex ]->Update();
|
||||
if ( myBorderDisplayers[ myCurGroupIndex ])
|
||||
myBorderDisplayers[ myCurGroupIndex ]->Update();
|
||||
|
||||
if ( partChange )
|
||||
onSelectBorderPartFromGroup();
|
||||
@ -1410,6 +1439,7 @@ void SMESHGUI_SewingDlg::onCloseView()
|
||||
{
|
||||
DeactivateActiveDialog();
|
||||
mySelector = 0;
|
||||
myActor = 0;
|
||||
|
||||
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 ]->SetEdgeColor( myColor.redF(), myColor.greenF(), myColor.blueF() );
|
||||
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 ]->SetMarkerStd( VTK::MT_POINT, 13 );
|
||||
myPartActors[ i ]->SetPickable ( false );
|
||||
myViewWindow->AddActor( myPartActors[ i ]);
|
||||
myViewWindow->Repaint();
|
||||
//myViewWindow->Repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,17 +47,20 @@ namespace
|
||||
/*!
|
||||
* \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* > 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 AddClose ( const BEdge* e ) const;
|
||||
BEdge* FindCloseEdgeOfBorder( int borderID ) const;
|
||||
bool operator<(const BNode& other) const { return myNode->GetID() < other.myNode->GetID(); }
|
||||
void AddClose ( const BEdge* e, double u ) const;
|
||||
BEdge* GetCloseEdge( size_t i ) const { return myCloseEdges[i].first; }
|
||||
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
|
||||
@ -72,9 +75,9 @@ namespace
|
||||
BEdge* myNext;
|
||||
const SMDS_MeshElement* myFace;
|
||||
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,
|
||||
const BNode * node2,
|
||||
@ -83,11 +86,15 @@ namespace
|
||||
{
|
||||
myBNode1 = node1;
|
||||
myBNode2 = node2;
|
||||
myNodes[0] = node1->myNode;
|
||||
myNodes[1] = node2->myNode;
|
||||
myNodes[0] = node1->Node();
|
||||
myNodes[1] = node2->Node();
|
||||
myFace = face;
|
||||
setId( ID ); // mesh element ID
|
||||
}
|
||||
bool IsInGroup() const
|
||||
{
|
||||
return myInGroup >= 0;
|
||||
}
|
||||
bool Contains( const BNode* n ) const
|
||||
{
|
||||
return ( n == myBNode1 || n == myBNode2 );
|
||||
@ -105,8 +112,8 @@ namespace
|
||||
void Reverse()
|
||||
{
|
||||
std::swap( myBNode1, myBNode2 );
|
||||
myNodes[0] = myBNode1->myNode;
|
||||
myNodes[1] = myBNode2->myNode;
|
||||
myNodes[0] = myBNode1->Node();
|
||||
myNodes[1] = myBNode2->Node();
|
||||
}
|
||||
void Orient()
|
||||
{
|
||||
@ -125,25 +132,95 @@ namespace
|
||||
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;
|
||||
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*/ )
|
||||
break;
|
||||
eRange[0] = eRange[0]->myPrev;
|
||||
}
|
||||
|
||||
eRange[1] = this;
|
||||
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*/ )
|
||||
break;
|
||||
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
|
||||
{
|
||||
@ -164,17 +241,32 @@ namespace
|
||||
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 ))
|
||||
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 )
|
||||
if ( borderID == myCloseEdges[ i ]->myBorderID )
|
||||
return myCloseEdges[ i ];
|
||||
return 0;
|
||||
if ( e == GetCloseEdge( i ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Accessor to SMDS_MeshElement* inherited by BEdge
|
||||
@ -333,12 +425,11 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
|
||||
std::vector< const SMDS_MeshElement* > candidateEdges;
|
||||
for ( bn = bNodes.begin(); bn != bNodes.end(); ++bn )
|
||||
{
|
||||
gp_Pnt point = SMESH_TNodeXYZ( bn->myNode );
|
||||
searcher->FindElementsByPoint( point, SMDSAbs_Edge, candidateEdges );
|
||||
searcher->FindElementsByPoint( *bn, SMDSAbs_Edge, candidateEdges );
|
||||
if ( candidateEdges.size() <= bn->myLinkedEdges.size() )
|
||||
continue;
|
||||
|
||||
double nodeTol = 0;
|
||||
double nodeTol = 0, u;
|
||||
for ( size_t i = 0; i < bn->myLinkedEdges.size(); ++i )
|
||||
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 ]);
|
||||
double tol = Max( nodeTol, bordToler[ be->myBorderID ]);
|
||||
if ( maxTolerance - tol < 1e-12 ||
|
||||
!SMESH_MeshAlgos::IsOut( be, point, tol ))
|
||||
bn->AddClose( be );
|
||||
if ( !be->IsOut( *bn, tol, u ))
|
||||
bn->AddClose( be, u );
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,8 +456,8 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
|
||||
for ( size_t iE1 = 0; iE1 < be.myBNode1->myCloseEdges.size(); ++iE1 )
|
||||
{
|
||||
// find edges of the same border close to both nodes of the edge
|
||||
BEdge* closeE1 = be.myBNode1->myCloseEdges[ iE1 ];
|
||||
BEdge* closeE2 = be.myBNode2->FindCloseEdgeOfBorder( closeE1->myBorderID );
|
||||
BEdge* closeE1 = be.myBNode1->GetCloseEdge( iE1 );
|
||||
BEdge* closeE2 = be.myBNode2->GetCloseEdgeOfBorder( closeE1->myBorderID );
|
||||
if ( !closeE2 )
|
||||
continue;
|
||||
// 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;
|
||||
do {
|
||||
coincide = ( ce->myBNode2->FindCloseEdgeOfBorder( be.myBorderID ));
|
||||
coincide = ( ce->myBNode2->GetCloseEdgeOfBorder( be.myBorderID ));
|
||||
ce = ce->myNext;
|
||||
} 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 )
|
||||
{
|
||||
BEdge* be = borders[i];
|
||||
foundFreeBordes._borders[i].push_back( be->myBNode1->myNode );
|
||||
foundFreeBordes._borders[i].push_back( be->myBNode1->Node() );
|
||||
do {
|
||||
foundFreeBordes._borders[i].push_back( be->myBNode2->myNode );
|
||||
foundFreeBordes._borders[i].push_back( be->myBNode2->Node() );
|
||||
be = be->myNext;
|
||||
}
|
||||
while ( be && be != borders[i] );
|
||||
@ -427,81 +517,158 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
|
||||
|
||||
TFreeBorderPart part;
|
||||
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
|
||||
do {
|
||||
if ( !be->myInGroup && !be->myCloseBorders.empty() )
|
||||
if ( !be->IsInGroup() && !be->myCloseBorders.empty() )
|
||||
break;
|
||||
be = be->myNext;
|
||||
} while ( be && be != borders[i] );
|
||||
|
||||
if ( !be || be->myInGroup || be->myCloseBorders.empty() )
|
||||
continue; // all edges of a border treated or are non-coincident
|
||||
|
||||
if ( !be || be->IsInGroup() || be->myCloseBorders.empty() )
|
||||
{
|
||||
be = 0;
|
||||
continue; // all edges of a border are treated or non-coincident
|
||||
}
|
||||
group.clear();
|
||||
ranges.clear();
|
||||
|
||||
// look for the 1st and last edge of a coincident group
|
||||
BEdge* beRange[2];
|
||||
be->FindRangeOfSameCloseBorders( beRange );
|
||||
BEdge* be1st = beRange[0];
|
||||
if ( !be->GetRangeOfSameCloseBorders( beRange, be->myCloseBorders ))
|
||||
{
|
||||
be->myInGroup = skipGroup;
|
||||
be = be->myNext;
|
||||
continue;
|
||||
}
|
||||
|
||||
// fill in a group
|
||||
part._border = i;
|
||||
part._node1 = beRange[0]->myID;
|
||||
part._node2 = beRange[0]->myID + 1;
|
||||
part._nodeLast = beRange[1]->myID + 1;
|
||||
group.push_back( part );
|
||||
ranges.push_back( beRange[0] );
|
||||
ranges.push_back( beRange[1] );
|
||||
|
||||
int groupID = foundFreeBordes._coincidentGroups.size();
|
||||
be = beRange[0];
|
||||
be->myInGroup = true;
|
||||
be->myInGroup = groupID;
|
||||
while ( be != beRange[1] )
|
||||
{
|
||||
be->myInGroup = true;
|
||||
be->myInGroup = groupID;
|
||||
be = be->myNext;
|
||||
}
|
||||
beRange[1]->myInGroup = true;
|
||||
beRange[1]->myInGroup = groupID;
|
||||
|
||||
// add parts of other borders
|
||||
|
||||
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 = be1st->myBNode2->FindCloseEdgeOfBorder( *closeBord );
|
||||
be = closeEdges[ iE ];
|
||||
if ( !be ) continue;
|
||||
|
||||
be->FindRangeOfSameCloseBorders( beRange );
|
||||
|
||||
// find out mutual orientation of borders
|
||||
bool reverse = ( beRange[0]->myBNode1->FindCloseEdgeOfBorder( i ) != be1st &&
|
||||
beRange[0]->myBNode2->FindCloseEdgeOfBorder( i ) != be1st );
|
||||
|
||||
// fill in a group
|
||||
part._border = beRange[0]->myBorderID;
|
||||
if ( reverse ) {
|
||||
part._node1 = beRange[1]->myID + 1;
|
||||
part._node2 = beRange[1]->myID;
|
||||
part._nodeLast = beRange[0]->myID;
|
||||
}
|
||||
else {
|
||||
part._node1 = beRange[0]->myID;
|
||||
part._node2 = beRange[0]->myID + 1;
|
||||
part._nodeLast = beRange[1]->myID + 1;
|
||||
}
|
||||
group.push_back( part );
|
||||
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];
|
||||
be->myInGroup = true;
|
||||
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 = true;
|
||||
be->myInGroup = groupID;
|
||||
be = be->myNext;
|
||||
}
|
||||
beRange[1]->myInGroup = true;
|
||||
beRange[1]->myInGroup = groupID;
|
||||
}
|
||||
|
||||
foundFreeBordes._coincidentGroups.push_back( group );
|
||||
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
|
||||
beRange[0] = ranges[0];
|
||||
beRange[1] = ranges[1];
|
||||
|
||||
part._border = i;
|
||||
part._node1 = beRange[0]->myID;
|
||||
part._node2 = beRange[0]->myID + 1;
|
||||
part._nodeLast = beRange[1]->myID + 1;
|
||||
group.push_back( part );
|
||||
|
||||
be1st = beRange[0];
|
||||
for ( size_t iR = 3; iR < ranges.size(); iR += 2 )
|
||||
{
|
||||
beRange[0] = ranges[iR-1];
|
||||
beRange[1] = ranges[iR-0];
|
||||
|
||||
// find out mutual orientation of borders
|
||||
double u1, u2;
|
||||
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
|
||||
part._border = beRange[0]->myBorderID;
|
||||
if ( reverse ) {
|
||||
part._node1 = beRange[1]->myID + 1;
|
||||
part._node2 = beRange[1]->myID;
|
||||
part._nodeLast = beRange[0]->myID;
|
||||
}
|
||||
else {
|
||||
part._node1 = beRange[0]->myID;
|
||||
part._node2 = beRange[0]->myID + 1;
|
||||
part._nodeLast = beRange[1]->myID + 1;
|
||||
}
|
||||
group.push_back( part );
|
||||
}
|
||||
foundFreeBordes._coincidentGroups.push_back( group );
|
||||
}
|
||||
else
|
||||
{
|
||||
beRange[0] = ranges[0];
|
||||
beRange[1] = ranges[1];
|
||||
|
||||
be = beRange[0];
|
||||
be->myInGroup = skipGroup;
|
||||
while ( be != beRange[1] )
|
||||
{
|
||||
be->myInGroup = skipGroup;
|
||||
be = be->myNext;
|
||||
}
|
||||
beRange[1]->myInGroup = skipGroup;
|
||||
}
|
||||
|
||||
be = ranges[1];
|
||||
|
||||
} // loop on free borders
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} // SMESH_MeshAlgos::FindCoincidentFreeBorders()
|
||||
|
||||
|
@ -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 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
|
||||
if ( u < 0. ) {
|
||||
if ( u <= 0. ) {
|
||||
if ( n1p.SquareMagnitude() < tol * tol )
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
if ( u > 1. ) {
|
||||
if ( u >= 1. ) {
|
||||
if ( point.SquareDistance( xyz[i] ) < tol * tol )
|
||||
return false;
|
||||
continue;
|
||||
|
@ -4641,11 +4641,12 @@ SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
|
||||
CORBA::Short nbSewed = 0;
|
||||
|
||||
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 )
|
||||
{
|
||||
borderNodes.clear();
|
||||
const SMESH::FreeBordersGroup& aGRP = freeBorders.coincidentGroups[ i ];
|
||||
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);
|
||||
if ( !n3 )
|
||||
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;
|
||||
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 ];
|
||||
if ( aGRP.length() < 2 )
|
||||
continue;
|
||||
|
||||
//int n1bord2, n2bord2;
|
||||
|
||||
bool groupSewed = false;
|
||||
for ( CORBA::ULong iP = 1; iP < aGRP.length(); ++iP )
|
||||
bool isBordToBord = true;
|
||||
bool groupSewed = false;
|
||||
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 SMESH::FreeBorder& aBRD_0 = freeBorders.borders[ aPART_0.border ];
|
||||
const SMDS_MeshNode* n0 = tmp0Delems[ i0D + 0 ]->GetNode( 0 );
|
||||
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* n1 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.node2 ]);
|
||||
const SMDS_MeshNode* n2 = getMeshDS()->FindNode( aBRD_0.nodeIDs[ aPART_0.nodeLast ]);
|
||||
|
||||
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 ]);
|
||||
const SMDS_MeshNode* n3 = tmp0Delems[ i0D + 0 + iN ]->GetNode( 0 );
|
||||
const SMDS_MeshNode* n4 = tmp0Delems[ i0D + 1 + iN ]->GetNode( 0 );
|
||||
const SMDS_MeshNode* n5 = tmp0Delems[ i0D + 2 + iN ]->GetNode( 0 );
|
||||
|
||||
if ( !n0 || !n1 || !n2 || !n3 || !n4 || !n5 )
|
||||
continue;
|
||||
|
||||
// if ( iP == 1 )
|
||||
// {
|
||||
// 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 )
|
||||
if ( !isBordToBord )
|
||||
{
|
||||
n1 = n2; // at border-to-side sewing only last side node (n1) is needed
|
||||
n2 = 0; // and n2 is not used
|
||||
}
|
||||
|
||||
// 1st border moves to 2nd
|
||||
res = getEditor().SewFreeBorder( n3, n4, n5 ,// 1st
|
||||
n0 ,n1 ,n2 ,// 2nd
|
||||
/*2ndIsFreeBorder=*/ iP == 1,
|
||||
/*2ndIsFreeBorder=*/ isBordToBord,
|
||||
createPolygons, createPolyhedra);
|
||||
groupSewed = ( res == ok );
|
||||
|
||||
isBordToBord = false;
|
||||
}
|
||||
i0D += nodes.size();
|
||||
nbSewed += groupSewed;
|
||||
}
|
||||
|
||||
@ -4745,6 +4745,20 @@ SewCoincidentFreeBorders(const SMESH::CoincidentFreeBorders& freeBorders,
|
||||
<< createPolygons << ", "
|
||||
<< 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user