23173: EDF 11552 - Problem using Add 0D element function

IPAL52875: Extrusion along a path: the buttons are not active if the path is closed
IPAL52882: Hexahedron (i,j,k) makes a wrong mesh on a block with composite sides
This commit is contained in:
eap 2015-09-29 19:25:32 +03:00
parent 8682ebb1eb
commit 674c0d8b9d
17 changed files with 338 additions and 182 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
doc/salome/gui/SMESH/images/image88.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -108,11 +108,17 @@ In this dialog
0D elements on in the VTK viewer or typing their IDs in the dialog.</li> 0D elements on in the VTK viewer or typing their IDs in the dialog.</li>
</ul></li> </ul></li>
<li><b> Set Filter </b> button allows selecting elements or nodes <li><b> Set Filter </b> button allows selecting elements or nodes
by filtering mesh elements or nodes with different criteria by filtering mesh elements or nodes with different criteria
(see \ref filtering_elements "Filter usage").</li> (see \ref filtering_elements "Filter usage").</li>
<li> Switching on <b>Add to group</b> check-box allows specifying the <li> Switching on <b>Add to group</b> check-box allows specifying the
name of the group to which all created or found 0D elements will be added. You can either select an existing group from name of the group to which all created or found (existing) 0D elements will
a drop-down list, or enter the name of the group to be created.</li> be added. You can either select an existing group from a drop-down
list, or enter the name of the group to be created. If a selected
existing \ref grouping_elements_page "group" is not Standalone
(Group On Geometry or Group On Filter) it will be converted to
Standalone.
\warning If <b>Add to group</b> is activated it has to be filled in.
</li>
</ul> </ul>
@ -124,7 +130,7 @@ by filtering mesh elements or nodes with different criteria
In this dialog box specify the nodes, which will form your ball elements, In this dialog box specify the nodes, which will form your ball elements,
either by selecting them in the 3D viewer or by manually entering their IDs, either by selecting them in the 3D viewer or by manually entering their IDs,
specify the ball diameter and click the \b Apply or <b>Apply and specify the ball diameter and click the \b Apply or <b>Apply and
Close</b> button. Close</b> button.
\image html add_ball.png \image html add_ball.png

View File

@ -39,8 +39,15 @@ number of mesh segments following an 1D hypothesis.
<li>For meshing of 3D entities (<b>solid objects</b>):</li> <li>For meshing of 3D entities (<b>solid objects</b>):</li>
<ul> <ul>
<li><em>Hexahedron (i,j,k)</em>meshing algorithm - 6-sided solids are <li><em>Hexahedron (i,j,k)</em> meshing algorithm - solids are
split into hexahedral (cuboid) elements.</li> split into hexahedral elements thus forming a structured 3D
mesh. The algorithm requires that 2D mesh generated on a solid could
be considered as a mesh of a box, i.e. there should be six nodes shared
by three quadrangles and the rest nodes should be shared by four
quadrangles.
\image html hexa_ijk_mesh.png "Structured mesh generated by Hexahedron (i,j,k) on a solid bound by 16 faces"
</li>
<li>\subpage cartesian_algo_page "Body Fitting" meshing <li>\subpage cartesian_algo_page "Body Fitting" meshing
algorithm - solids are split into hexahedral elements forming algorithm - solids are split into hexahedral elements forming
a Cartesian grid; polyhedra and other types of elements are generated a Cartesian grid; polyhedra and other types of elements are generated
@ -66,7 +73,7 @@ There is also a number of more specific algorithms:
<li>\subpage projection_algos_page "for meshing by projection of another mesh"</li> <li>\subpage projection_algos_page "for meshing by projection of another mesh"</li>
<li>\subpage import_algos_page "for meshing by importing elements from another mesh"</li> <li>\subpage import_algos_page "for meshing by importing elements from another mesh"</li>
<li>\subpage radial_prism_algo_page "for meshing geometrical objects with cavities"</li> <li>\subpage radial_prism_algo_page "for meshing geometrical objects with cavities"</li>
<li>\subpage radial_quadrangle_1D2D_algo_page "for meshing special 2d faces (circles and part of circles)"</li> <li>\subpage radial_quadrangle_1D2D_algo_page "for meshing special faces (circles and parts of circles)"</li>
<li>\subpage use_existing_page "Use Edges to be Created Manually" and <li>\subpage use_existing_page "Use Edges to be Created Manually" and
\ref use_existing_page "Use Faces to be Created Manually" algorithms can be \ref use_existing_page "Use Faces to be Created Manually" algorithms can be
used to create a 1D or a 2D mesh in a python script.</li> used to create a 1D or a 2D mesh in a python script.</li>

View File

@ -187,13 +187,9 @@ creation and computing) of the following steps:
which is a 2D object, you do not need to define a 3D Algorithm and which is a 2D object, you do not need to define a 3D Algorithm and
Hypotheses. Hypotheses.
In the <b>Object Browser</b> the structure of the new mesh will be In the <b>Object Browser</b> the structure of the new mesh is
displayed as follows: displayed as follows:
<center>
\image html image88.jpg \image html image88.jpg
</center>
It contains: It contains:
<ul> <ul>
<li>a mesh name (<em>Mesh_mechanic</em>); <li>a mesh name (<em>Mesh_mechanic</em>);
@ -203,6 +199,13 @@ creation and computing) of the following steps:
to the hypotheses chosen at the construction of the mesh;</li> to the hypotheses chosen at the construction of the mesh;</li>
<li><b>Applied algorithms</b> folder containing the references <li><b>Applied algorithms</b> folder containing the references
to the algorithms chosen at the construction of the mesh.</li> to the algorithms chosen at the construction of the mesh.</li>
<li><b>SubMeshes on Face</b> folder containing the sub-meshes
defined on geometrical faces. There also can be folders for
sub-meshes on vertices, edges, wires, shells, solids and
compounds.</li>
<li><b>Groups of Faces</b> folder containing the groups of mesh
faces. There also can be folders for groups of nodes, edges,
volumes 0D elements and balls.</li>
</ul> </ul>
There is an alternative way to assign Algorithms and Hypotheses by There is an alternative way to assign Algorithms and Hypotheses by
@ -212,15 +215,25 @@ creation and computing) of the following steps:
CustomMeshers.xml file located in the home directory. CustomMeshers.xml CustomMeshers.xml file located in the home directory. CustomMeshers.xml
file must describe sets of hypotheses in the file must describe sets of hypotheses in the
same way as ${SMESH_ROOT_DIR}/share/salome/resources/smesh/StdMeshers.xml same way as ${SMESH_ROOT_DIR}/share/salome/resources/smesh/StdMeshers.xml
file does (sets of hypotheses are enclosed between <hypotheses-set-group> file does (sets of hypotheses are enclosed between \<hypotheses-set-group\>
tags). tags). For example:
~~~~~~{.xml}
<center> <?xml version='1.0' encoding='us-ascii'?>
<!DOCTYPE meshers PUBLIC "" "desktop.dtd">
<meshers>
<hypotheses-set-group>
<hypotheses-set name="My favorite hypotheses"
hypos="AutomaticLength"
algos="CompositeSegment_1D, Quadrangle_2D, GHS3D_3D"/>
</hypotheses-set-group>
</meshers>
~~~~~~
<br>
<center>
\image html hypo_sets.png \image html hypo_sets.png
List of sets of hypotheses. Tag <em>[custom]</em> is List of sets of hypotheses. Tag <em>[custom]</em> is
automatically added to the sets defined by the user. automatically added to the sets defined by the user.
</center> </center>
\note \note
- \a "Automatic" in the names of predefined sets of hypotheses - \a "Automatic" in the names of predefined sets of hypotheses
does not actually mean that they are suitable for meshing any does not actually mean that they are suitable for meshing any

View File

@ -3,7 +3,7 @@
\page selection_filter_library_page Selection filter library \page selection_filter_library_page Selection filter library
\n Selection filter library allows creating and storing in files \n Selection filter library allows creating and storing in files
filters that can be later reused for operations on meshes. You can filters that can be later loaded and used for operations on meshes. You can
access to it from the Main Menu via <b>Tools / Selection filter library</b>. access to it from the Main Menu via <b>Tools / Selection filter library</b>.
It is also possible to save any filter by invoking the filter library It is also possible to save any filter by invoking the filter library
from \a Filter dialog launched from any mesh operation. from \a Filter dialog launched from any mesh operation.

View File

@ -63,9 +63,9 @@ To use \b Automatic sewing:
<li>The found groups of <b>Coincident Free Borders</b> are shown in a <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 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 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 within a group is designated by IDs of its first, second and last
parenthesis. All borders present in the list will be sewn upon \b nodes within parenthesis. All borders present in the list will be
Apply.</li> sewn upon \b Apply.</li>
<li>\b Remove button removes selected groups from the list.</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><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 <li>When a group is selected, its borders appear in <b>Edit Selected

View File

@ -7963,10 +7963,6 @@ public:
const SMDS_MeshElement* Get() const const SMDS_MeshElement* Get() const
{ return myElem; } { return myElem; }
void Set(const SMDS_MeshElement* e) const
{ myElem = e; }
private: private:
mutable const SMDS_MeshElement* myElem; mutable const SMDS_MeshElement* myElem;
}; };

View File

@ -223,6 +223,7 @@ SMESHGUI_Add0DElemsOnAllNodesOp::SMESHGUI_Add0DElemsOnAllNodesOp()
connect( myDlg, SIGNAL( selTypeChanged(int) ), SLOT( onSelTypeChange(int))); connect( myDlg, SIGNAL( selTypeChanged(int) ), SLOT( onSelTypeChange(int)));
connect( myDlg->myFilterBtn, SIGNAL( clicked()), SLOT( onSetFilter() )); connect( myDlg->myFilterBtn, SIGNAL( clicked()), SLOT( onSetFilter() ));
connect( myDlg->myGroupBox, SIGNAL( clicked(bool)), SLOT( updateButtons() ));
} }
//================================================================================ //================================================================================
@ -270,6 +271,7 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
myIO.Nullify(); myIO.Nullify();
myDlg->setObjectText( 0, ""); myDlg->setObjectText( 0, "");
updateButtons();
SALOME_ListIO aList; SALOME_ListIO aList;
selectionMgr()->selectedObjects( aList ); selectionMgr()->selectedObjects( aList );
@ -297,7 +299,8 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
// fill the list of existing groups // fill the list of existing groups
myDlg->myGroupListCmBox->clear(); myDlg->myGroupListCmBox->clear();
myDlg->myGroupListCmBox->addItem( QString() ); myDlg->myGroupListCmBox->addItem( QString() );
if ( !myIO.IsNull() && myIO->hasEntry()) { if ( !myIO.IsNull() && myIO->hasEntry())
{
SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO ); SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
_PTR(SObject) meshSO = SMESH::ObjectToSObject( mesh ); _PTR(SObject) meshSO = SMESH::ObjectToSObject( mesh );
_PTR(SObject) group0DRoot; _PTR(SObject) group0DRoot;
@ -313,9 +316,44 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::selectionDone()
myDlg->myGroupListCmBox->addItem( groupName.c_str() ); myDlg->myGroupListCmBox->addItem( groupName.c_str() );
} }
} }
// enable buttons
updateButtons();
} }
} }
//=======================================================================
//function : updateButtons
//purpose : enable [Apply]
//=======================================================================
void SMESHGUI_Add0DElemsOnAllNodesOp::updateButtons()
{
bool ok = false;
if (( !myIO.IsNull() && myIO->hasEntry() && !myDlg->objectText( 0 ).isEmpty() ) &&
( !myDlg->myGroupBox->isChecked() || !myDlg->myGroupListCmBox->currentText().isEmpty() ))
{
SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO( myIO );
if ( !mesh->_is_nil() )
{
if ( myDlg->getSelectionType() == SEL_OBJECT )
ok = true;
else
{
QString ids = myDlg->objectText( 0 );
QStringList idList = ids.split( " ", QString::SkipEmptyParts );
const bool isElem = ( myDlg->getSelectionType() == SEL_ELEMENTS );
QStringList::iterator idIt = idList.begin();
for ( ; idIt != idList.end() && !ok; ++idIt )
ok = ( mesh->GetElementType( idIt->toLong(), isElem ) != SMESH::ALL );
}
}
}
myDlg->button( QtxDialog::Apply )->setEnabled( ok );
myDlg->button( QtxDialog::OK )->setEnabled( ok );
}
//================================================================================ //================================================================================
/*! /*!
* \brief Return a filter of objects * \brief Return a filter of objects
@ -496,3 +534,14 @@ void SMESHGUI_Add0DElemsOnAllNodesOp::onSetFilter()
myFilterDlg->show(); myFilterDlg->show();
} }
//=======================================================================
//function : onTextChanged
//purpose : SLOT called when the user types IDs
//=======================================================================
void SMESHGUI_Add0DElemsOnAllNodesOp::onTextChanged( int obj, const QStringList& text )
{
SMESHGUI_SelectionOp::onTextChanged( obj, text );
updateButtons();
}

View File

@ -99,6 +99,8 @@ class SMESHGUI_EXPORT SMESHGUI_Add0DElemsOnAllNodesOp : public SMESHGUI_Selectio
virtual bool onApply(); virtual bool onApply();
void onSelTypeChange(int); void onSelTypeChange(int);
void onSetFilter(); void onSetFilter();
virtual void onTextChanged( int, const QStringList& );
void updateButtons();
private: private:
SMESHGUI_Add0DElemsOnAllNodesDlg* myDlg; SMESHGUI_Add0DElemsOnAllNodesDlg* myDlg;

View File

@ -1048,11 +1048,19 @@ bool SMESHGUI_ExtrusionAlongPathDlg::isValuesValid()
if ( type != SMESH::NODE ) if ( type != SMESH::NODE )
return false; return false;
if ( mesh->HasShapeToMesh() )
{
SMESH::NodePosition_var pos = mesh->GetNodePosition( aNodeStart );
if ( pos->shapeType != GEOM::VERTEX )
return false;
}
else
{
SMESH::long_array_var elems = mesh->GetNodeInverseElements( aNodeStart ); SMESH::long_array_var elems = mesh->GetNodeInverseElements( aNodeStart );
if ( elems->length() != 1 || if ( elems->length() != 1 ||
mesh->GetElementType( elems[0], true ) != SMESH::EDGE ) mesh->GetElementType( elems[0], true ) != SMESH::EDGE )
return false; return false;
}
return true; return true;
} }

View File

@ -1583,7 +1583,8 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
// remember current algo // remember current algo
prevAlgo = algoByDim[ dim ] = hypData( dim, Algo, algoIndex ); prevAlgo = algoByDim[ dim ] = hypData( dim, Algo, algoIndex );
} }
if ( myMaxShapeDim == SMESH::DIM_3D && forward && algoDim == SMESH::DIM_1D ) { if ( myMaxShapeDim == SMESH::DIM_3D && forward && algoDim == SMESH::DIM_1D )
{
algoDim = SMESH::DIM_3D; algoDim = SMESH::DIM_3D;
forward = -1; forward = -1;
a3DAlgo = prevAlgo; a3DAlgo = prevAlgo;

View File

@ -54,6 +54,7 @@
#include <SVTK_ViewModel.h> #include <SVTK_ViewModel.h>
#include <SVTK_ViewWindow.h> #include <SVTK_ViewWindow.h>
#include <SalomeApp_IntSpinBox.h> #include <SalomeApp_IntSpinBox.h>
#include <SalomeApp_Tools.h>
// OCCT includes // OCCT includes
#include <TColStd_MapOfInteger.hxx> #include <TColStd_MapOfInteger.hxx>
@ -832,8 +833,9 @@ QString SMESHGUI_SewingDlg::getPartText(const SMESH::FreeBorderPart& aPART)
if ( 0 <= aPART.node1 && aPART.node1 < aBRD.nodeIDs.length() && if ( 0 <= aPART.node1 && aPART.node1 < aBRD.nodeIDs.length() &&
0 <= aPART.nodeLast && aPART.nodeLast < aBRD.nodeIDs.length() ) 0 <= aPART.nodeLast && aPART.nodeLast < aBRD.nodeIDs.length() )
{ {
text += QString("( %1 %2 ) ") text += QString("( %1 %2 %3 ) ")
.arg( aBRD.nodeIDs[ aPART.node1 ] ) .arg( aBRD.nodeIDs[ aPART.node1 ] )
.arg( aBRD.nodeIDs[ aPART.node2 ] )
.arg( aBRD.nodeIDs[ aPART.nodeLast ] ); .arg( aBRD.nodeIDs[ aPART.nodeLast ] );
} }
} }
@ -883,9 +885,8 @@ void SMESHGUI_SewingDlg::onDetectClicked()
SMESH::SMESH_MeshEditor_var editor = myMesh->GetMeshEditor(); SMESH::SMESH_MeshEditor_var editor = myMesh->GetMeshEditor();
myBorders = editor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() ); myBorders = editor->FindCoincidentFreeBorders( SpinBoxTolerance->GetValue() );
if ( !haveBorders() ) if ( haveBorders() )
return; {
for ( size_t i = 0; i < myBorderDisplayers.size(); ++i ) for ( size_t i = 0; i < myBorderDisplayers.size(); ++i )
{ {
delete myBorderDisplayers[ i ]; delete myBorderDisplayers[ i ];
@ -908,6 +909,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; myBusy = false;
onSelectGroup(); onSelectGroup();
@ -1389,7 +1391,11 @@ bool SMESHGUI_SewingDlg::ClickOnApply()
QString msg = tr(QString("ERROR_%1").arg(anError).toLatin1().data()); QString msg = tr(QString("ERROR_%1").arg(anError).toLatin1().data());
SUIT_MessageBox::warning(this, tr("SMESH_WRN_WARNING"), msg); SUIT_MessageBox::warning(this, tr("SMESH_WRN_WARNING"), msg);
} }
} catch (...) { }
catch ( const SALOME::SALOME_Exception& S_ex )
{
SalomeApp_Tools::QtCatchCorbaException( S_ex );
return false;
} }
if (aResult) { if (aResult) {
@ -1887,7 +1893,6 @@ SMESHGUI_SewingDlg::BorderGroupDisplayer::~BorderGroupDisplayer()
} }
} }
myIdPreview.SetPointsLabeled(false); myIdPreview.SetPointsLabeled(false);
//myViewWindow->Repaint();
} }
void SMESHGUI_SewingDlg::BorderGroupDisplayer::Hide() void SMESHGUI_SewingDlg::BorderGroupDisplayer::Hide()
@ -2010,7 +2015,6 @@ void SMESHGUI_SewingDlg::BorderGroupDisplayer::Update()
myPartActors[ i ]->SetMarkerStd( VTK::MT_POINT, 13 ); myPartActors[ i ]->SetMarkerStd( VTK::MT_POINT, 13 );
myPartActors[ i ]->SetPickable ( false ); myPartActors[ i ]->SetPickable ( false );
myViewWindow->AddActor( myPartActors[ i ]); myViewWindow->AddActor( myPartActors[ i ]);
//myViewWindow->Repaint();
} }
} }
} }

View File

@ -59,7 +59,8 @@ namespace
BEdge* GetCloseEdge( size_t i ) const { return myCloseEdges[i].first; } BEdge* GetCloseEdge( size_t i ) const { return myCloseEdges[i].first; }
double GetCloseU( size_t i ) const { return myCloseEdges[i].second; } double GetCloseU( size_t i ) const { return myCloseEdges[i].second; }
BEdge* GetCloseEdgeOfBorder( int borderID, double * u = 0 ) const; BEdge* GetCloseEdgeOfBorder( int borderID, double * u = 0 ) const;
bool IsCloseEdge( const BEdge* ) const; bool HasCloseEdgeWithNode( const BNode* n ) const;
bool IsCloseEdge( const BEdge*, double * u = 0 ) const;
bool operator<(const BNode& other) const { return Node()->GetID() < other.Node()->GetID(); } bool operator<(const BNode& other) const { return Node()->GetID() < other.Node()->GetID(); }
}; };
/*! /*!
@ -149,8 +150,8 @@ namespace
// is1st shows which end of toE is projected on this at u // is1st shows which end of toE is projected on this at u
double u2; double u2;
const double eps = 0.1; const double eps = 0.1;
if ( toE == myBNode1->GetCloseEdgeOfBorder( toE->myBorderID, &u2 ) || if ( myBNode1->IsCloseEdge( toE, &u2 ) ||
toE == myBNode2->GetCloseEdgeOfBorder( toE->myBorderID, &u2 )) myBNode2->IsCloseEdge( toE, &u2 ))
return (( 0 < u2 && u2 < 1 ) && // u2 is proj param of myBNode's on toE return (( 0 < u2 && u2 < 1 ) && // u2 is proj param of myBNode's on toE
( Abs( u2 - int( !is1st )) > eps )); ( Abs( u2 - int( !is1st )) > eps ));
@ -164,24 +165,59 @@ namespace
if ( this->myCloseBorders != bordIDs ) if ( this->myCloseBorders != bordIDs )
return false; return false;
if ( bordIDs.size() == 1 && bordIDs.count( myBorderID )) // border close to self
{
double u;
eRange[0] = this;
while ( eRange[0]->myBNode1->GetCloseEdgeOfBorder( myBorderID, &u ))
{
if ( eRange[0]->myPrev == this || u < 0 || u > 1 )
break;
eRange[0] = eRange[0]->myPrev;
}
eRange[1] = this;
while ( eRange[1]->myBNode2->GetCloseEdgeOfBorder( myBorderID, &u ))
{
if ( eRange[1]->myNext == this || u < 0 || u > 1 )
break;
eRange[1] = eRange[1]->myNext;
}
}
else
{
eRange[0] = this; eRange[0] = this;
while ( eRange[0]->myPrev && eRange[0]->myPrev->myCloseBorders == bordIDs ) while ( eRange[0]->myPrev && eRange[0]->myPrev->myCloseBorders == bordIDs )
{ {
if ( eRange[0]->myPrev == this /*|| eRange[0]->myPrev->myInGroup*/ ) if ( eRange[0]->myPrev == this )
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 border
while ( eRange[1]->myNext && eRange[1]->myNext->myCloseBorders == bordIDs ) while ( eRange[1]->myNext && eRange[1]->myNext->myCloseBorders == bordIDs )
{ {
if ( eRange[1]->myNext == this /*|| eRange[1]->myNext->myInGroup*/ ) if ( eRange[1]->myNext == this )
break; break;
eRange[1] = eRange[1]->myNext; eRange[1] = eRange[1]->myNext;
} }
}
return ( eRange[0] != eRange[1] ); if ( eRange[0] == eRange[1] )
{
std::set<int>::iterator closeBord = eRange[0]->myCloseBorders.begin();
for ( ; closeBord != eRange[0]->myCloseBorders.end(); ++closeBord )
{
if ( BEdge* be = eRange[0]->myBNode1->GetCloseEdgeOfBorder( *closeBord ))
if ( be->myCloseBorders == eRange[0]->myCloseBorders )
return true;
if ( BEdge* be = eRange[0]->myBNode2->GetCloseEdgeOfBorder( *closeBord ))
if ( be->myCloseBorders == eRange[0]->myCloseBorders )
return true;
}
return false;
}
return true;
} }
}; // class BEdge }; // class BEdge
@ -197,8 +233,7 @@ namespace
if ( e1->myPrev ) if ( e1->myPrev )
{ {
for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord ) for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord )
if (( *bord != e1->myBorderID ) && if ((( be = e1->myBNode1->GetCloseEdgeOfBorder( *bord, &u ))) &&
(( be = e1->myBNode1->GetCloseEdgeOfBorder( *bord, &u ))) &&
( be->myInGroup == groupID ) && ( be->myInGroup == groupID ) &&
( 0 < u && u < 1 ) && ( 0 < u && u < 1 ) &&
( be->IsOverlappingProjection( e1->myPrev, u, false ))) ( be->IsOverlappingProjection( e1->myPrev, u, false )))
@ -206,12 +241,17 @@ namespace
e1 = e1->myPrev; e1 = e1->myPrev;
break; break;
} }
if ( bord == bordIDs.end() && // not extended
e1->myBNode1->HasCloseEdgeWithNode( e1->myPrev->myBNode1 ))
{
e1 = e1->myPrev;
}
e1->myInGroup = groupID;
} }
if ( e2->myNext ) if ( e2->myNext )
{ {
for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord ) for ( bord = bordIDs.begin(); bord != bordIDs.end(); ++bord )
if (( *bord != e2->myBorderID ) && if ((( be = e2->myBNode2->GetCloseEdgeOfBorder( *bord, &u ))) &&
(( be = e2->myBNode2->GetCloseEdgeOfBorder( *bord, &u ))) &&
( be->myInGroup == groupID ) && ( be->myInGroup == groupID ) &&
( 0 < u && u < 1 ) && ( 0 < u && u < 1 ) &&
( be->IsOverlappingProjection( e2->myNext, u, true ))) ( be->IsOverlappingProjection( e2->myNext, u, true )))
@ -219,6 +259,12 @@ namespace
e2 = e2->myNext; e2 = e2->myNext;
break; break;
} }
if ( bord == bordIDs.end() && // not extended
e2->myBNode2->HasCloseEdgeWithNode( e2->myNext->myBNode2 ))
{
e2 = e2->myNext;
}
e2->myInGroup = groupID;
} }
} }
@ -261,11 +307,22 @@ namespace
if ( uPtr ) *uPtr = u; if ( uPtr ) *uPtr = u;
return e; return e;
} }
bool BNode::IsCloseEdge( const BEdge* e ) const bool BNode::HasCloseEdgeWithNode( const BNode* n ) const
{
for ( size_t i = 0; i < myCloseEdges.size(); ++i )
if ( GetCloseEdge( i )->Contains( n ) &&
0 < GetCloseU( i ) && GetCloseU( i ) < 1 )
return true;
return false;
}
bool BNode::IsCloseEdge( const BEdge* e, double * uPtr ) const
{ {
for ( size_t i = 0; i < myCloseEdges.size(); ++i ) for ( size_t i = 0; i < myCloseEdges.size(); ++i )
if ( e == GetCloseEdge( i ) ) if ( e == GetCloseEdge( i ) )
{
if ( uPtr ) *uPtr = GetCloseU( i );
return true; return true;
}
return false; return false;
} }
@ -315,6 +372,7 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
// find free links // find free links
typedef NCollection_DataMap<SMESH_TLink, const SMDS_MeshElement*, TLinkHasher > TLink2FaceMap; typedef NCollection_DataMap<SMESH_TLink, const SMDS_MeshElement*, TLinkHasher > TLink2FaceMap;
TLink2FaceMap linkMap; TLink2FaceMap linkMap;
int nbSharedLinks = 0;
SMDS_FaceIteratorPtr faceIt = mesh.facesIterator(); SMDS_FaceIteratorPtr faceIt = mesh.facesIterator();
while ( faceIt->more() ) while ( faceIt->more() )
{ {
@ -327,27 +385,36 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
{ {
const SMDS_MeshNode* n1 = nodeIt->next(); const SMDS_MeshNode* n1 = nodeIt->next();
SMESH_TLink link( n0, n1 ); SMESH_TLink link( n0, n1 );
if ( !linkMap.Bind( link, face )) if ( const SMDS_MeshElement** faceInMap = linkMap.ChangeSeek( link ))
linkMap.UnBind( link ); {
nbSharedLinks += bool( *faceInMap );
*faceInMap = 0;
}
else
{
linkMap.Bind( link, face );
}
n0 = n1; n0 = n1;
} }
} }
if ( linkMap.IsEmpty() ) if ( linkMap.Extent() == nbSharedLinks )
return; return;
// form free borders // form free borders
std::set < BNode > bNodes; std::set < BNode > bNodes;
std::vector< BEdge > bEdges( linkMap.Extent() ); std::vector< BEdge > bEdges( linkMap.Extent() - nbSharedLinks );
TLink2FaceMap::Iterator linkIt( linkMap ); TLink2FaceMap::Iterator linkIt( linkMap );
for ( int iEdge = 0; linkIt.More(); linkIt.Next(), ++iEdge ) for ( int iEdge = 0; linkIt.More(); linkIt.Next() )
{ {
if ( !linkIt.Value() ) continue;
const SMESH_TLink & link = linkIt.Key(); const SMESH_TLink & link = linkIt.Key();
std::set< BNode >::iterator n1 = bNodes.insert( BNode( link.node1() )).first; std::set< BNode >::iterator n1 = bNodes.insert( BNode( link.node1() )).first;
std::set< BNode >::iterator n2 = bNodes.insert( BNode( link.node2() )).first; std::set< BNode >::iterator n2 = bNodes.insert( BNode( link.node2() )).first;
bEdges[ iEdge ].Set( &*n1, &*n2, linkIt.Value(), iEdge+1 ); bEdges[ iEdge ].Set( &*n1, &*n2, linkIt.Value(), iEdge+1 );
n1->AddLinked( & bEdges[ iEdge ] ); n1->AddLinked( & bEdges[ iEdge ] );
n2->AddLinked( & bEdges[ iEdge ] ); n2->AddLinked( & bEdges[ iEdge ] );
++iEdge;
} }
linkMap.Clear(); linkMap.Clear();
@ -563,36 +630,44 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
} }
beRange[1]->myInGroup = groupID; beRange[1]->myInGroup = groupID;
// get starting edge of each close border
closeEdges.clear();
be = beRange[0];
if ( be->myCloseBorders.empty() )
be = beRange[0]->myNext;
std::set<int>::iterator closeBord = be->myCloseBorders.begin();
for ( ; closeBord != be->myCloseBorders.end(); ++closeBord )
if ( BEdge* e = be->myBNode2->GetCloseEdgeOfBorder( *closeBord ))
closeEdges.push_back( e );
for ( size_t iE = 0; iE < closeEdges.size(); ++iE )
if ( be->myCloseBorders != closeEdges[iE]->myCloseBorders )
{
closeBord = closeEdges[iE]->myCloseBorders.begin();
for ( ; closeBord != closeEdges[iE]->myCloseBorders.end(); ++closeBord )
if ( !be->myCloseBorders.count( *closeBord ))
if ( BEdge* e = closeEdges[iE]->myBNode2->GetCloseEdgeOfBorder( *closeBord ))
if ( std::find( closeEdges.begin(), closeEdges.end(), e ) == closeEdges.end() )
closeEdges.push_back( e );
}
// add parts of other borders // 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 ) for ( size_t iE = 0; iE < closeEdges.size(); ++iE )
{ {
be = closeEdges[ iE ]; be = closeEdges[ iE ];
if ( !be ) continue; if ( !be ) continue;
bool ok = be->GetRangeOfSameCloseBorders( beRange, be->myCloseBorders ); bool ok = be->GetRangeOfSameCloseBorders( beRange, be->myCloseBorders );
if ( !ok && be->myPrev ) // if ( !ok && be->myPrev )
ok = be->myPrev->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders ); // ok = be->myPrev->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders );
if ( !ok && be->myNext ) // if ( !ok && be->myNext )
ok = be->myNext->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders ); // ok = be->myNext->GetRangeOfSameCloseBorders( beRange, be1st->myCloseBorders );
if ( !ok ) if ( !ok )
continue; continue;
be = beRange[0]; 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[0] );
ranges.push_back( beRange[1] ); ranges.push_back( beRange[1] );
@ -645,8 +720,10 @@ void SMESH_MeshAlgos::FindCoincidentFreeBorders(SMDS_Mesh& mesh,
part._node2 = beRange[0]->myID + 1; part._node2 = beRange[0]->myID + 1;
part._nodeLast = beRange[1]->myID + 1; part._nodeLast = beRange[1]->myID + 1;
} }
// if ( group[0]._node2 != part._node2 )
group.push_back( part ); group.push_back( part );
} }
//if ( group.size() > 1 )
foundFreeBordes._coincidentGroups.push_back( group ); foundFreeBordes._coincidentGroups.push_back( group );
} }
else else

View File

@ -1541,10 +1541,8 @@ SMESH_MeshAlgos::FindFaceInSet(const SMDS_MeshNode* n1,
const SMDS_MeshElement* face = 0; const SMDS_MeshElement* face = 0;
SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face); SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face);
//MESSAGE("n1->GetInverseElementIterator(SMDSAbs_Face) " << invElemIt);
while ( invElemIt->more() && !face ) // loop on inverse faces of n1 while ( invElemIt->more() && !face ) // loop on inverse faces of n1
{ {
//MESSAGE("in while ( invElemIt->more() && !face )");
const SMDS_MeshElement* elem = invElemIt->next(); const SMDS_MeshElement* elem = invElemIt->next();
if (avoidSet.count( elem )) if (avoidSet.count( elem ))
continue; continue;
@ -1563,9 +1561,6 @@ SMESH_MeshAlgos::FindFaceInSet(const SMDS_MeshNode* n1,
if ( !face && elem->IsQuadratic()) if ( !face && elem->IsQuadratic())
{ {
// analysis for quadratic elements using all nodes // analysis for quadratic elements using all nodes
// const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>(elem);
// if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
// use special nodes iterator
SMDS_ElemIteratorPtr anIter = elem->interlacedNodesElemIterator(); SMDS_ElemIteratorPtr anIter = elem->interlacedNodesElemIterator();
const SMDS_MeshNode* prevN = static_cast<const SMDS_MeshNode*>( anIter->next() ); const SMDS_MeshNode* prevN = static_cast<const SMDS_MeshNode*>( anIter->next() );
for ( i1 = -1, i2 = 0; anIter->more() && !face; i1++, i2++ ) for ( i1 = -1, i2 = 0; anIter->more() && !face; i1++, i2++ )

View File

@ -1115,8 +1115,8 @@ bool _QuadFaceGrid::LoadGrid( SMESH_Mesh& mesh )
// store the rest nodes row by row // store the rest nodes row by row
const SMDS_MeshNode* dummy = mesh.GetMeshDS()->AddNode(0,0,0); TIDSortedElemSet emptySet, avoidSet;
const SMDS_MeshElement* firstQuad = dummy; // most left face above the last row of found nodes const SMDS_MeshElement* firstQuad = 0; // most left face above the last row of found nodes
int nbFoundNodes = myIndexer._xSize; int nbFoundNodes = myIndexer._xSize;
while ( nbFoundNodes != myGrid.size() ) while ( nbFoundNodes != myGrid.size() )
@ -1134,8 +1134,6 @@ bool _QuadFaceGrid::LoadGrid( SMESH_Mesh& mesh )
// o---o o o o o // o---o o o o o
//n1down n2down //n1down n2down
// //
TIDSortedElemSet emptySet, avoidSet;
avoidSet.insert( firstQuad );
firstQuad = SMESH_MeshAlgos::FindFaceInSet( n1down, n2down, emptySet, avoidSet); firstQuad = SMESH_MeshAlgos::FindFaceInSet( n1down, n2down, emptySet, avoidSet);
while ( firstQuad && !faceSubMesh->Contains( firstQuad )) { while ( firstQuad && !faceSubMesh->Contains( firstQuad )) {
avoidSet.insert( firstQuad ); avoidSet.insert( firstQuad );
@ -1182,8 +1180,8 @@ bool _QuadFaceGrid::LoadGrid( SMESH_Mesh& mesh )
n1down = myGrid[ nbFoundNodes - myIndexer._xSize - 1 ]; n1down = myGrid[ nbFoundNodes - myIndexer._xSize - 1 ];
n1up = n2up; n1up = n2up;
} }
avoidSet.clear(); avoidSet.insert( firstQuad );
} }
mesh.GetMeshDS()->RemoveNode(dummy);
DumpGrid(); // debug DumpGrid(); // debug
return true; return true;