022484: EDF 2304 SMESH: Reorient a group of faces regarding to a volume

This commit is contained in:
eap 2014-08-11 17:30:26 +04:00
parent b178951ce4
commit 811a7a4c17
18 changed files with 420 additions and 71 deletions

View File

@ -1,4 +1,4 @@
# Reorient faces by vector # Reorient faces
import salome import salome
@ -52,3 +52,20 @@ mesh.Reorient2D( group, smesh.MakeDirStruct( -10, 1, 10 ), [0,0,0])
# #
# FaceOrPoint - a SMESH.PointStruct structure # FaceOrPoint - a SMESH.PointStruct structure
mesh.Reorient2D( localAlgo.GetSubMesh().GetIDs(), [10,1,0], SMESH.PointStruct(0,0,0)) mesh.Reorient2D( localAlgo.GetSubMesh().GetIDs(), [10,1,0], SMESH.PointStruct(0,0,0))
# Use Reorient2DBy3D() to orient faces of 2 geom faces to have their normal pointing inside volumes
mesh3D = smesh.Mesh( box, '3D mesh')
mesh3D.AutomaticHexahedralization(0.5)
group0 = mesh3D.Group( faces[0] )
group1 = mesh3D.Group( faces[1] )
# pass group0 and ids of faces of group1 to inverse
nbRev = mesh3D.Reorient2DBy3D([ group0, group1.GetIDs() ], mesh3D, theOutsideNormal=False)
print "Nb reoriented faces:", nbRev
# orient the reversed faces back
nbRev = mesh3D.Reorient2DBy3D( mesh3D, mesh3D, theOutsideNormal=True)
print "Nb re-reoriented faces:", nbRev

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,49 +1,66 @@
/*! /*!
\page reorient_faces_page Reorient faces by vector \page reorient_faces_page Reorient faces
\n This operation allows changing orientation of a set of neighboring \n This operation allows changing orientation of faces two ways.
faces. The desired orientation is defined by a vector. Since the direction <ol>
of face normals in the set can be even opposite, it is necessary to <li> To reorient a set of neighboring faces by defining the desired
specify a control face whose normal will be compared with the vector. This orientation by a vector. <br> Since the direction of face normals in
face can be either specified explicitly or found by proximity to the set can be even opposite, it is necessary to specify a control
a given point. face whose normal will be compared with the vector. This face can be
either <ul>
<li> found by proximity to a given point or </li>
<li> specified explicitly. </li>
</ul> </li>
<li> To reorient faces with relation to adjacent volumes. </li>
</ol>
Orientation of a face is changed by reverting the order of its nodes. Orientation of a face is changed by reverting the order of its nodes.
<em>To change orientation of faces:</em> <em>To change orientation of faces:</em>
<ol> <ol>
<li>In the \b Modification menu select <b>Reorient faces by <li>In the \b Modification menu select <b>Reorient faces</b>
vector</b> item or click <em>Reorient faces by item or click <em>Reorient faces</em> button in the toolbar.
vector</em> button in the toolbar.
<center> <center>
\image html reorient_faces_face.png \image html reorient_faces_face.png
<em>"Reorient faces by vector" button</em> <em>"Reorient faces" button</em>
</center> </center>
The following dialog box will appear: The following dialog box will appear:
<center> <center>
\image html reorient_2d_point.png \image html reorient_2d_point.png "First mode: to reorient adjacent faces according to a vector. The control face is found by point."
\image html reorient_2d_face.png <br>
\image html reorient_2d_face.png "Second mode: to reorient adjacent faces according to a vector. The control face is explicitly given."
<br>
\image html reorient_2d_volume.png "Third mode: to reorient faces with relation to adjacent volumes."
</center> </center>
<li>In this dialog <li>In this dialog
<ul> <ul>
<li>Specify the way of selection of the control face: by point or <li>Specify either of the tree operation modes.</li>
explicitly.</li> <li>Select the \b Object (mesh, sub-mesh or group)
<li>Select the \b Object (mesh, sub-mesh or a group of faces) containing faces to reorient in the Object Browser or in the 3D Viewer.</li> containing faces to reorient, in the Object Browser or in the 3D
<li>Specify the coordinates of the \b Point by which the control face Viewer.</li>
will be found or of the control \b Face itself. You can easy specify the \b <li>To reorient according to vector: <ul>
Point by either picking a node in the 3D Viewer or selecting a vertex <li>Specify the coordinates of the \b Point by which the control face
in the Object Browser. It is possible to pick the \b Face by mouse in will be found or the control \b Face itself. You can easy specify the \b
the 3D Viewer or enter its ID.</li> Point by either picking a node in the 3D Viewer or selecting a vertex
<li>Set up the \b Direction vector to be compared with the normal of the in the Object Browser. It is possible to pick the \b Face by mouse in
control face. If you pick a node in the 3D Viewer then the \b Direction the 3D Viewer or enter its ID.</li>
vector will go from the coordinate system origin to the selected node. <li>Set up the \b Direction vector to be compared with the normal of the
If you pick two nodes (holding Shift button) then the \b Direction vector control face. If you pick a node in the 3D Viewer then the \b Direction
will go from the first to the second node.</li> vector will go from the coordinate system origin to the selected node.
If you pick two nodes (holding Shift button) then the \b Direction vector
will go from the first to the second node.</li> </ul> </li>
<li>To reorient according to volumes: <ul>
<li>Select an object (mesh, sub-mesh or group) containing
reference \b Volumes, in the Object Browser or in the 3D
Viewer.</li>
<li>Specify whether face normals should point outside or inside
the reference volumes using <b>Face normal outside volume</b>
check-box.</li></ul> </li>
</ul> </ul>
</li> </li>
@ -51,6 +68,6 @@ The following dialog box will appear:
</ol> </ol>
<br><b>See Also</b> a sample TUI Script of a <br><b>See Also</b> a sample TUI Script of a
\ref tui_reorient_faces "Reorient faces by vector" operation. \ref tui_reorient_faces "Reorient faces" operation.
*/ */

View File

@ -238,12 +238,23 @@ module SMESH
* \param theFace - ID of face whose orientation is checked. * \param theFace - ID of face whose orientation is checked.
* It can be < 1 then \a thePoint is used to find a face. * It can be < 1 then \a thePoint is used to find a face.
* \param thePoint - is used to find a face if \a theFace < 1. * \param thePoint - is used to find a face if \a theFace < 1.
* \return number of reoriented elements. * \return number of reoriented faces.
*/ */
long Reorient2D(in SMESH_IDSource the2Dgroup, long Reorient2D(in SMESH_IDSource the2Dgroup,
in DirStruct theDirection, in DirStruct theDirection,
in long theFace, in long theFace,
in PointStruct thePoint) raises (SALOME::SALOME_Exception); in PointStruct thePoint) raises (SALOME::SALOME_Exception);
/*!
* \brief Reorient faces basing on orientation of adjacent volumes.
* \param faces - a list of objects containing face to reorient
* \param volumes - an object containing volumes.
* \param outsideNormal - to orient faces to have their normal
* pointing either \a outside or \a inside the adjacent volumes.
* \return number of reoriented faces.
*/
long Reorient2DBy3D(in ListOfIDSources faces,
in SMESH_IDSource volumes,
in boolean outsideNormal) raises (SALOME::SALOME_Exception);
/*! /*!
* \brief Fuse neighbour triangles into quadrangles. * \brief Fuse neighbour triangles into quadrangles.

View File

@ -205,6 +205,7 @@ SET(SMESH_RESOURCES_FILES
mesh_min_dist.png mesh_min_dist.png
reorient_faces_point.png reorient_faces_point.png
reorient_faces_face.png reorient_faces_face.png
reorient_faces_volume.png
mesh_ball.png mesh_ball.png
mesh_measure_basic_props.png mesh_measure_basic_props.png
mesh_measure_length.png mesh_measure_length.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

View File

@ -1243,6 +1243,92 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces,
return nbReori; return nbReori;
} }
//================================================================================
/*!
* \brief Reorient faces basing on orientation of adjacent volumes.
* \param theFaces - faces to reorient. If empty, all mesh faces are treated.
* \param theVolumes - reference volumes.
* \param theOutsideNormal - to orient faces to have their normal
* pointing either \a outside or \a inside the adjacent volumes.
* \return number of reoriented faces.
*/
//================================================================================
int SMESH_MeshEditor::Reorient2DBy3D (TIDSortedElemSet & theFaces,
TIDSortedElemSet & theVolumes,
const bool theOutsideNormal)
{
int nbReori = 0;
SMDS_ElemIteratorPtr faceIt;
if ( theFaces.empty() )
faceIt = GetMeshDS()->elementsIterator( SMDSAbs_Face );
else
faceIt = elemSetIterator( theFaces );
vector< const SMDS_MeshNode* > faceNodes;
TIDSortedElemSet checkedVolumes;
set< const SMDS_MeshNode* > faceNodesSet;
SMDS_VolumeTool volumeTool;
while ( faceIt->more() ) // loop on given faces
{
const SMDS_MeshElement* face = faceIt->next();
if ( face->GetType() != SMDSAbs_Face )
continue;
const int nbCornersNodes = face->NbCornerNodes();
faceNodes.assign( face->begin_nodes(), face->end_nodes() );
checkedVolumes.clear();
SMDS_ElemIteratorPtr vIt = faceNodes[ 0 ]->GetInverseElementIterator( SMDSAbs_Volume );
while ( vIt->more() )
{
const SMDS_MeshElement* volume = vIt->next();
if ( !checkedVolumes.insert( volume ).second )
continue;
if ( !theVolumes.empty() && !theVolumes.count( volume ))
continue;
// is volume adjacent?
bool allNodesCommon = true;
for ( int iN = 1; iN < nbCornersNodes && allNodesCommon; ++iN )
allNodesCommon = ( volume->GetNodeIndex( faceNodes[ iN ]) > -1 );
if ( !allNodesCommon )
continue;
// get nodes of a corresponding volume facet
faceNodesSet.clear();
faceNodesSet.insert( faceNodes.begin(), faceNodes.end() );
volumeTool.Set( volume );
int facetID = volumeTool.GetFaceIndex( faceNodesSet );
if ( facetID < 0 ) continue;
volumeTool.SetExternalNormal();
const SMDS_MeshNode** facetNodes = volumeTool.GetFaceNodes( facetID );
// compare order of faceNodes and facetNodes
const int iQ = 1 + ( nbCornersNodes < faceNodes.size() );
int iNN[2];
for ( int i = 0; i < 2; ++i )
{
const SMDS_MeshNode* n = facetNodes[ i*iQ ];
for ( int iN = 0; iN < nbCornersNodes; ++iN )
if ( faceNodes[ iN ] == n )
{
iNN[ i ] = iN;
break;
}
}
bool isOutside = Abs( iNN[0]-iNN[1] ) == 1 ? iNN[0] < iNN[1] : iNN[0] > iNN[1];
if ( isOutside != theOutsideNormal )
nbReori += Reorient( face );
}
} // loop on given faces
return nbReori;
}
//======================================================================= //=======================================================================
//function : getBadRate //function : getBadRate
//purpose : //purpose :

View File

@ -126,6 +126,12 @@ public:
// Reverse theFaces whose orientation to be same as that of theFace // Reverse theFaces whose orientation to be same as that of theFace
// oriented according to theDirection. Return nb of reoriented faces // oriented according to theDirection. Return nb of reoriented faces
int Reorient2DBy3D (TIDSortedElemSet & theFaces,
TIDSortedElemSet & theVolumes,
const bool theOutsideNormal);
// Reorient faces basing on orientation of adjacent volumes.
// Return nb of reoriented faces
/*! /*!
* \brief Fuse neighbour triangles into quadrangles. * \brief Fuse neighbour triangles into quadrangles.
* \param theElems - The triangles to be fused. * \param theElems - The triangles to be fused.

View File

@ -92,8 +92,8 @@
#define SPACING 6 #define SPACING 6
#define MARGIN 11 #define MARGIN 11
enum { CONSTRUCTOR_POINT=0, CONSTRUCTOR_FACE, enum { CONSTRUCTOR_POINT=0, CONSTRUCTOR_FACE, CONSTRUCTOR_VOLUME,
EObject, EPoint, EFace, EDirection }; EObject, EPoint, EFace, EDirection, EVolumes };
//======================================================================= //=======================================================================
/*! /*!
@ -131,6 +131,7 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
QPixmap iconReoriPoint (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_POINT"))); QPixmap iconReoriPoint (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_POINT")));
QPixmap iconReoriFace (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_FACE"))); QPixmap iconReoriFace (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_FACE")));
QPixmap iconReoriVolum (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_VOLUME")));
QGroupBox* aConstructorBox = new QGroupBox(tr("REORIENT_FACES"), aFrame); QGroupBox* aConstructorBox = new QGroupBox(tr("REORIENT_FACES"), aFrame);
myConstructorGrp = new QButtonGroup(aConstructorBox); myConstructorGrp = new QButtonGroup(aConstructorBox);
@ -149,6 +150,11 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
aConstructorGrpLayout->addWidget(aFaceBut); aConstructorGrpLayout->addWidget(aFaceBut);
myConstructorGrp->addButton(aFaceBut, CONSTRUCTOR_FACE); myConstructorGrp->addButton(aFaceBut, CONSTRUCTOR_FACE);
QRadioButton* aVolBut= new QRadioButton(aConstructorBox);
aVolBut->setIcon(iconReoriVolum);
aConstructorGrpLayout->addWidget(aVolBut);
myConstructorGrp->addButton(aVolBut, CONSTRUCTOR_VOLUME);
// Create other controls // Create other controls
setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) ); setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
@ -157,17 +163,22 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
createObject( tr("POINT") , aFrame, EPoint ); createObject( tr("POINT") , aFrame, EPoint );
createObject( tr("FACE") , aFrame, EFace ); createObject( tr("FACE") , aFrame, EFace );
createObject( tr("DIRECTION"), aFrame, EDirection ); createObject( tr("DIRECTION"), aFrame, EDirection );
createObject( tr("VOLUMES"), aFrame, EVolumes );
setNameIndication( EObject, OneName ); setNameIndication( EObject, OneName );
setNameIndication( EFace, OneName ); setNameIndication( EFace, OneName );
setReadOnly( EFace, false ); setReadOnly( EFace, false );
if ( QLineEdit* le = qobject_cast<QLineEdit*>( objectWg( EFace, Control ) )) if ( QLineEdit* le = qobject_cast<QLineEdit*>( objectWg( EFace, Control ) ))
le->setValidator( new SMESHGUI_IdValidator( this,1 )); le->setValidator( new SMESHGUI_IdValidator( this,1 ));
const int width = aFaceBut->fontMetrics().width( tr("DIRECTION")); int width = aFaceBut->fontMetrics().width( tr("DIRECTION"));
objectWg( EDirection, Label )->setFixedWidth( width ); objectWg( EDirection, Label )->setFixedWidth( width );
objectWg( EObject , Label )->setFixedWidth( width ); objectWg( EObject , Label )->setFixedWidth( width );
objectWg( EPoint , Label )->setFixedWidth( width ); objectWg( EPoint , Label )->setFixedWidth( width );
objectWg( EFace , Label )->setFixedWidth( width ); objectWg( EFace , Label )->setFixedWidth( width );
objectWg( EVolumes , Label )->setFixedWidth( width );
myOutsideChk = new QCheckBox( tr("OUTSIDE_VOLUME_NORMAL"), aFrame);
myOutsideChk->setChecked( true );
QLabel* aXLabel = new QLabel(tr("SMESH_X"), aFrame); QLabel* aXLabel = new QLabel(tr("SMESH_X"), aFrame);
myX = new SMESHGUI_SpinBox(aFrame); myX = new SMESHGUI_SpinBox(aFrame);
@ -197,6 +208,15 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
myDY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); myDY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
myDZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision"); myDZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
width = Max( aFaceBut->fontMetrics().width( tr("SMESH_X")),
aFaceBut->fontMetrics().width( tr("SMESH_DX")));
aXLabel->setFixedWidth( width );
aYLabel->setFixedWidth( width );
aZLabel->setFixedWidth( width );
aDXLabel->setFixedWidth( width );
aDYLabel->setFixedWidth( width );
aDZLabel->setFixedWidth( width );
// Layouting // Layouting
QGroupBox* anObjectGrp = new QGroupBox(tr("FACES"), aFrame); QGroupBox* anObjectGrp = new QGroupBox(tr("FACES"), aFrame);
@ -213,12 +233,12 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
objectWg( EPoint, Control )->hide(); objectWg( EPoint, Control )->hide();
aPointGrpLayout->addWidget( objectWg( EPoint, Label ) ); aPointGrpLayout->addWidget( objectWg( EPoint, Label ) );
aPointGrpLayout->addWidget( objectWg( EPoint, Btn ) ); aPointGrpLayout->addWidget( objectWg( EPoint, Btn ) );
aPointGrpLayout->addWidget( aXLabel ); aPointGrpLayout->addWidget( aXLabel, 0 );
aPointGrpLayout->addWidget( myX ); aPointGrpLayout->addWidget( myX, 1 );
aPointGrpLayout->addWidget( aYLabel ); aPointGrpLayout->addWidget( aYLabel, 0 );
aPointGrpLayout->addWidget( myY ); aPointGrpLayout->addWidget( myY, 1 );
aPointGrpLayout->addWidget( aZLabel ); aPointGrpLayout->addWidget( aZLabel, 0 );
aPointGrpLayout->addWidget( myZ ); aPointGrpLayout->addWidget( myZ, 1 );
myFaceFrm = new QFrame(aFrame); myFaceFrm = new QFrame(aFrame);
QHBoxLayout* aFaceGrpLayout = new QHBoxLayout(myFaceFrm); QHBoxLayout* aFaceGrpLayout = new QHBoxLayout(myFaceFrm);
@ -227,25 +247,35 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
aFaceGrpLayout->addWidget( objectWg( EFace, Btn ) ); aFaceGrpLayout->addWidget( objectWg( EFace, Btn ) );
aFaceGrpLayout->addWidget( objectWg( EFace, Control ) ); aFaceGrpLayout->addWidget( objectWg( EFace, Control ) );
QFrame* aDirectFrm = new QFrame(aFrame); myVolumFrm = new QFrame(aFrame);
QHBoxLayout* aDirectGrpLayout = new QHBoxLayout(aDirectFrm); QGridLayout* aVolumGrpLayout = new QGridLayout(myVolumFrm);
aVolumGrpLayout->setMargin(0);
aVolumGrpLayout->setSpacing(SPACING);
aVolumGrpLayout->addWidget( objectWg( EVolumes, Label ), 0, 0 );
aVolumGrpLayout->addWidget( objectWg( EVolumes, Btn ), 0, 1 );
aVolumGrpLayout->addWidget( objectWg( EVolumes, Control ), 0, 2 );
aVolumGrpLayout->addWidget( myOutsideChk, 1, 0, 1, 3 );
myDirFrm = new QFrame(aFrame);
QHBoxLayout* aDirectGrpLayout = new QHBoxLayout(myDirFrm);
aDirectGrpLayout->setMargin(0); aDirectGrpLayout->setMargin(0);
objectWg( EDirection, Control )->hide(); objectWg( EDirection, Control )->hide();
aDirectGrpLayout->addWidget( objectWg( EDirection, Label ) ); aDirectGrpLayout->addWidget( objectWg( EDirection, Label ) );
aDirectGrpLayout->addWidget( objectWg( EDirection, Btn ) ); aDirectGrpLayout->addWidget( objectWg( EDirection, Btn ) );
aDirectGrpLayout->addWidget(aDXLabel ); aDirectGrpLayout->addWidget( aDXLabel, 0 );
aDirectGrpLayout->addWidget(myDX ); aDirectGrpLayout->addWidget( myDX, 1 );
aDirectGrpLayout->addWidget(aDYLabel ); aDirectGrpLayout->addWidget( aDYLabel, 0 );
aDirectGrpLayout->addWidget(myDY ); aDirectGrpLayout->addWidget( myDY, 1 );
aDirectGrpLayout->addWidget(aDZLabel ); aDirectGrpLayout->addWidget( aDZLabel, 0 );
aDirectGrpLayout->addWidget(myDZ ); aDirectGrpLayout->addWidget( myDZ, 1 );
QGroupBox* anOrientGrp = new QGroupBox(tr("ORIENTATION"), aFrame); QGroupBox* anOrientGrp = new QGroupBox(tr("ORIENTATION"), aFrame);
QVBoxLayout* anOrientGrpLayout = new QVBoxLayout ( anOrientGrp ); QVBoxLayout* anOrientGrpLayout = new QVBoxLayout ( anOrientGrp );
anOrientGrpLayout->addWidget(myPointFrm); anOrientGrpLayout->addWidget(myPointFrm);
anOrientGrpLayout->addWidget(myFaceFrm); anOrientGrpLayout->addWidget(myFaceFrm);
anOrientGrpLayout->addWidget(aDirectFrm); anOrientGrpLayout->addWidget(myVolumFrm);
anOrientGrpLayout->addWidget(myDirFrm);
QVBoxLayout* aLay = new QVBoxLayout(aFrame); QVBoxLayout* aLay = new QVBoxLayout(aFrame);
@ -269,15 +299,27 @@ void SMESHGUI_ReorientFacesDlg::constructorChange(int id)
if ( id == CONSTRUCTOR_FACE ) if ( id == CONSTRUCTOR_FACE )
{ {
myPointFrm->hide(); myPointFrm->hide();
myVolumFrm->hide();
myFaceFrm->show(); myFaceFrm->show();
myDirFrm->show();
activateObject( EFace ); activateObject( EFace );
} }
else else if ( id == CONSTRUCTOR_POINT )
{ {
myFaceFrm->hide(); myFaceFrm->hide();
myVolumFrm->hide();
myPointFrm->show(); myPointFrm->show();
myDirFrm->show();
activateObject( EPoint ); activateObject( EPoint );
} }
else // CONSTRUCTOR_VOLUME
{
myFaceFrm->hide();
myPointFrm->hide();
myDirFrm->hide();
myVolumFrm->show();
activateObject( EVolumes );
}
} }
//================================================================================ //================================================================================
@ -373,6 +415,7 @@ void SMESHGUI_ReorientFacesOp::onActivateObject( int what )
SMESH::SetPickable(); SMESH::SetPickable();
break; break;
case EObject: case EObject:
case EVolumes:
SMESH::SetPointRepresentation(false); SMESH::SetPointRepresentation(false);
setSelectionMode( ActorSelection ); setSelectionMode( ActorSelection );
break; break;
@ -406,6 +449,14 @@ SUIT_SelectionFilter* SMESHGUI_ReorientFacesOp::createFilter( const int what ) c
filters.append( new SMESH_TypeFilter( SMESH::GROUP_FACE )); filters.append( new SMESH_TypeFilter( SMESH::GROUP_FACE ));
return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR ); return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
} }
case EVolumes:
{
QList<SUIT_SelectionFilter*> filters;
filters.append( new SMESH_TypeFilter( SMESH::MESH ));
filters.append( new SMESH_TypeFilter( SMESH::SUBMESH_SOLID ));
filters.append( new SMESH_TypeFilter( SMESH::GROUP_VOLUME ));
return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
}
case EPoint: case EPoint:
{ {
QList<SUIT_SelectionFilter*> filters; QList<SUIT_SelectionFilter*> filters;
@ -433,6 +484,12 @@ void SMESHGUI_ReorientFacesOp::selectionDone()
if ( !myDlg->isVisible() || !myDlg->isEnabled() ) if ( !myDlg->isVisible() || !myDlg->isEnabled() )
return; return;
if ( mySelectionMode == EVolumes )
{
SMESHGUI_SelectionOp::selectionDone();
return;
}
myDlg->clearSelection( mySelectionMode ); myDlg->clearSelection( mySelectionMode );
SALOME_ListIO aList; SALOME_ListIO aList;
@ -603,29 +660,45 @@ bool SMESHGUI_ReorientFacesOp::onApply()
try { try {
SUIT_OverrideCursor wc; SUIT_OverrideCursor wc;
SMESH::SMESH_Mesh_var aMesh = myObject->GetMesh(); SMESH::SMESH_Mesh_var aMesh = myObject->GetMesh();
if ( aMesh->_is_nil() ) return false; if ( aMesh->_is_nil() ) return false;
SMESH::DirStruct direction;
direction.PS.x = myDlg->myDX->GetValue();
direction.PS.y = myDlg->myDY->GetValue();
direction.PS.z = myDlg->myDZ->GetValue();
long face = myDlg->objectText( EFace ).toInt();
if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_POINT )
face = -1;
SMESH::PointStruct point;
point.x = myDlg->myX->GetValue();
point.y = myDlg->myY->GetValue();
point.z = myDlg->myZ->GetValue();
SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor(); SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
if (aMeshEditor->_is_nil()) return false; if (aMeshEditor->_is_nil()) return false;
aMesh->SetParameters( aParameters.join(":").toLatin1().constData() ); int aResult = 0;
if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_VOLUME )
{
SMESH::ListOfIDSources_var faceGroups = new SMESH::ListOfIDSources;
faceGroups->length(1);
faceGroups[0] = myObject;
bool outsideNormal = myDlg->myOutsideChk->isChecked();
aResult = aMeshEditor->Reorient2DBy3D( faceGroups, myVolumeObj, outsideNormal );
}
else
{
SMESH::DirStruct direction;
direction.PS.x = myDlg->myDX->GetValue();
direction.PS.y = myDlg->myDY->GetValue();
direction.PS.z = myDlg->myDZ->GetValue();
long face = myDlg->objectText( EFace ).toInt();
if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_POINT )
face = -1;
SMESH::PointStruct point;
point.x = myDlg->myX->GetValue();
point.y = myDlg->myY->GetValue();
point.z = myDlg->myZ->GetValue();
aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
aResult = aMeshEditor->Reorient2D( myObject, direction, face, point );
}
int aResult = aMeshEditor->Reorient2D( myObject, direction, face, point );
if (aResult) if (aResult)
{ {
SALOME_ListIO aList; SALOME_ListIO aList;
@ -673,6 +746,27 @@ bool SMESHGUI_ReorientFacesOp::isValid( QString& msg )
return false; return false;
} }
// check volume object
if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_VOLUME )
{
objectEntry = myDlg->selectedObject( EVolumes );
_PTR(SObject) pSObject = studyDS()->FindObjectID( objectEntry.toLatin1().data() );
myVolumeObj = SMESH::SObjectToInterface< SMESH::SMESH_IDSource>( pSObject );
if ( myVolumeObj->_is_nil() )
{
msg = tr("NO_VOLUME_OBJECT_SELECTED");
return false;
}
bool hasVolumes = false;
types = myVolumeObj->GetTypes();
for ( size_t i = 0; i < types->length() && !hasVolumes; ++i )
hasVolumes = ( types[i] == SMESH::VOLUME );
if ( !hasVolumes )
{
msg = tr("NO_VOLUMES");
return false;
}
}
// check vector // check vector
gp_Vec vec( myDlg->myDX->GetValue(), gp_Vec vec( myDlg->myDX->GetValue(),
myDlg->myDY->GetValue(), myDlg->myDY->GetValue(),

View File

@ -33,12 +33,13 @@
#include "SMESHGUI_SelectionOp.h" #include "SMESHGUI_SelectionOp.h"
class QButtonGroup; class QButtonGroup;
class QCheckBox;
class QLineEdit; class QLineEdit;
class SMESHGUI_SpinBox; class SMESHGUI_SpinBox;
class SMESHGUI_ReorientFacesDlg; class SMESHGUI_ReorientFacesDlg;
/*! /*!
* \brief Operation to reorient faces acoording to vector * \brief Operation to reorient faces acoording to some criterion
*/ */
class SMESHGUI_EXPORT SMESHGUI_ReorientFacesOp: public SMESHGUI_SelectionOp class SMESHGUI_EXPORT SMESHGUI_ReorientFacesOp: public SMESHGUI_SelectionOp
{ {
@ -76,6 +77,7 @@ private:
int mySelectionMode; int mySelectionMode;
SMESH::SMESH_IDSource_var myObject; SMESH::SMESH_IDSource_var myObject;
SMESH::SMESH_IDSource_var myVolumeObj;
}; };
/*! /*!
@ -98,6 +100,9 @@ private:
QButtonGroup* myConstructorGrp; QButtonGroup* myConstructorGrp;
QFrame* myFaceFrm; QFrame* myFaceFrm;
QFrame* myPointFrm; QFrame* myPointFrm;
QFrame* myDirFrm;
QFrame* myVolumFrm;
QCheckBox* myOutsideChk;
SMESHGUI_SpinBox* myX; SMESHGUI_SpinBox* myX;
SMESHGUI_SpinBox* myY; SMESHGUI_SpinBox* myY;
SMESHGUI_SpinBox* myZ; SMESHGUI_SpinBox* myZ;

View File

@ -427,6 +427,10 @@
<source>ICON_DLG_REORIENT2D_FACE</source> <source>ICON_DLG_REORIENT2D_FACE</source>
<translation>reorient_faces_face.png</translation> <translation>reorient_faces_face.png</translation>
</message> </message>
<message>
<source>ICON_DLG_REORIENT2D_VOLUME</source>
<translation>reorient_faces_volume.png</translation>
</message>
<message> <message>
<source>ICON_REORIENT_2D</source> <source>ICON_REORIENT_2D</source>
<translation>reorient_faces_face.png</translation> <translation>reorient_faces_face.png</translation>

View File

@ -470,15 +470,15 @@
</message> </message>
<message> <message>
<source>TOP_REORIENT_2D</source> <source>TOP_REORIENT_2D</source>
<translation>Reorient faces by vector</translation> <translation>Reorient faces</translation>
</message> </message>
<message> <message>
<source>MEN_REORIENT_2D</source> <source>MEN_REORIENT_2D</source>
<translation>Reorient faces by vector</translation> <translation>Reorient faces</translation>
</message> </message>
<message> <message>
<source>STB_REORIENT_2D</source> <source>STB_REORIENT_2D</source>
<translation>Reorient faces by vector</translation> <translation>Reorient faces</translation>
</message> </message>
<message> <message>
<source>TOP_FIND_ELEM</source> <source>TOP_FIND_ELEM</source>
@ -7656,7 +7656,7 @@ as they are of improper type:
<name>SMESHGUI_ReorientFacesDlg</name> <name>SMESHGUI_ReorientFacesDlg</name>
<message> <message>
<source>CAPTION</source> <source>CAPTION</source>
<translation>Reorient faces by vector</translation> <translation>Reorient faces</translation>
</message> </message>
<message> <message>
<source>REORIENT_FACES</source> <source>REORIENT_FACES</source>
@ -7686,6 +7686,14 @@ as they are of improper type:
<source>ORIENTATION</source> <source>ORIENTATION</source>
<translation>Orientation</translation> <translation>Orientation</translation>
</message> </message>
<message>
<source>VOLUMES</source>
<translation>Volumes</translation>
</message>
<message>
<source>OUTSIDE_VOLUME_NORMAL</source>
<translation>Face normal outside volume</translation>
</message>
</context> </context>
<context> <context>
<name>SMESHGUI_ReorientFacesOp</name> <name>SMESHGUI_ReorientFacesOp</name>
@ -7693,10 +7701,18 @@ as they are of improper type:
<source>NO_OBJECT_SELECTED</source> <source>NO_OBJECT_SELECTED</source>
<translation>No object selected</translation> <translation>No object selected</translation>
</message> </message>
<message>
<source>NO_VOLUME_OBJECT_SELECTED</source>
<translation>No volume object selected</translation>
</message>
<message> <message>
<source>NO_FACES</source> <source>NO_FACES</source>
<translation>Object includes no faces</translation> <translation>Object includes no faces</translation>
</message> </message>
<message>
<source>NO_VOLUMES</source>
<translation>Volume object includes no volumes</translation>
</message>
<message> <message>
<source>ZERO_SIZE_VECTOR</source> <source>ZERO_SIZE_VECTOR</source>
<translation>Zero size vector</translation> <translation>Zero size vector</translation>

View File

@ -2369,7 +2369,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
"AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall", "AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall",
"AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces", "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces",
"MoveNode", "MoveClosestNodeToPoint", "MoveNode", "MoveClosestNodeToPoint",
"InverseDiag","DeleteDiag","Reorient","ReorientObject", "InverseDiag","DeleteDiag","Reorient","ReorientObject","Reorient2DBy3D",
"TriToQuad","TriToQuadObject", "QuadTo4Tri", "SplitQuad","SplitQuadObject", "TriToQuad","TriToQuadObject", "QuadTo4Tri", "SplitQuad","SplitQuadObject",
"BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject", "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject",
"ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements", "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements",

View File

@ -1645,7 +1645,7 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
TIDSortedElemSet elements; TIDSortedElemSet elements;
prepareIdSource( the2Dgroup ); prepareIdSource( the2Dgroup );
if ( !idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1)) if ( !idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1))
THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM); return 0;//THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
const SMDS_MeshElement* face = 0; const SMDS_MeshElement* face = 0;
@ -1710,6 +1710,55 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
return 0; return 0;
} }
//=======================================================================
//function : Reorient2DBy3D
//purpose : Reorient faces basing on orientation of adjacent volumes.
//=======================================================================
CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
SMESH::SMESH_IDSource_ptr volumeGroup,
CORBA::Boolean outsideNormal)
throw (SALOME::SALOME_Exception)
{
SMESH_TRY;
initData();
TIDSortedElemSet volumes;
prepareIdSource( volumeGroup );
if ( !idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfIsMesh=*/1))
THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
int nbReori = 0;
for ( size_t i = 0; i < faceGroups.length(); ++i )
{
SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
prepareIdSource( faceGrp );
TIDSortedElemSet faces;
if ( !idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1) &&
faceGroups.length() == 1 )
; //THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
if ( faces.empty() ) // all faces in the mesh treated
break;
}
if ( nbReori ) {
declareMeshModified( /*isReComputeSafe=*/false );
}
TPythonDump() << this << ".Reorient2DBy3D( "
<< faceGroups << ", "
<< volumeGroup << ", "
<< outsideNormal << " )";
return nbReori;
SMESH_CATCH( SMESH::throwCorbaException );
return 0;
}
//============================================================================= //=============================================================================
/*! /*!
* \brief Fuse neighbour triangles into quadrangles. * \brief Fuse neighbour triangles into quadrangles.

View File

@ -203,6 +203,18 @@ public:
const SMESH::DirStruct& theDirection, const SMESH::DirStruct& theDirection,
CORBA::Long theFace, CORBA::Long theFace,
const SMESH::PointStruct& thePoint) throw (SALOME::SALOME_Exception); const SMESH::PointStruct& thePoint) throw (SALOME::SALOME_Exception);
/*!
* \brief Reorient faces basing on orientation of adjacent volumes.
* \param faces - a list of objects containing face to reorient
* \param volumes - an object containing volumes.
* \param outsideNormal - to orient faces to have their normal
* pointing either \a outside or \a inside the adjacent volumes.
* \return number of reoriented faces.
*/
CORBA::Long Reorient2DBy3D(const SMESH::ListOfIDSources & faces,
SMESH::SMESH_IDSource_ptr volumes,
CORBA::Boolean outsideNormal)
throw (SALOME::SALOME_Exception);
// Split/Join faces // Split/Join faces
CORBA::Boolean TriToQuad (const SMESH::long_array & IDsOfElements, CORBA::Boolean TriToQuad (const SMESH::long_array & IDsOfElements,

View File

@ -2964,6 +2964,37 @@ class Mesh:
theFace = -1 theFace = -1
return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint ) return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
## Reorient faces according to adjacent volumes.
# @param the2DObject is a mesh, sub-mesh, group or list of
# either IDs of faces or face groups.
# @param the3DObject is a mesh, sub-mesh, group or list of IDs of volumes.
# @param theOutsideNormal to orient faces to have their normals
# pointing either \a outside or \a inside the adjacent volumes.
# @return number of reoriented faces.
# @ingroup l2_modif_changori
def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
unRegister = genObjUnRegister()
# check the2DObject
if not isinstance( the2DObject, list ):
the2DObject = [ the2DObject ]
elif the2DObject and isinstance( the2DObject[0], int ):
the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
unRegister.set( the2DObject )
the2DObject = [ the2DObject ]
for i,obj2D in enumerate( the2DObject ):
if isinstance( obj2D, Mesh ):
the2DObject[i] = obj2D.GetMesh()
if isinstance( obj2D, list ):
the2DObject[i] = self.GetIDSource( obj2D, SMESH.FACE )
unRegister.set( the2DObject[i] )
# check the3DObject
if isinstance( the3DObject, Mesh ):
the3DObject = the3DObject.GetMesh()
if isinstance( the3DObject, list ):
the3DObject = self.GetIDSource( the3DObject, SMESH.VOLUME )
unRegister.set( the3DObject )
return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
## Fuses the neighbouring triangles into quadrangles. ## Fuses the neighbouring triangles into quadrangles.
# @param IDsOfElements The triangles to be fused, # @param IDsOfElements The triangles to be fused,
# @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to # @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to