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
@ -52,3 +52,20 @@ mesh.Reorient2D( group, smesh.MakeDirStruct( -10, 1, 10 ), [0,0,0])
#
# FaceOrPoint - a SMESH.PointStruct structure
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
faces. The desired orientation is defined by a vector. Since the direction
of face normals in the set can be even opposite, it is necessary to
specify a control face whose normal will be compared with the vector. This
face can be either specified explicitly or found by proximity to
a given point.
\n This operation allows changing orientation of faces two ways.
<ol>
<li> To reorient a set of neighboring faces by defining the desired
orientation by a vector. <br> Since the direction of face normals in
the set can be even opposite, it is necessary to specify a control
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.
<em>To change orientation of faces:</em>
<ol>
<li>In the \b Modification menu select <b>Reorient faces by
vector</b> item or click <em>Reorient faces by
vector</em> button in the toolbar.
<li>In the \b Modification menu select <b>Reorient faces</b>
item or click <em>Reorient faces</em> button in the toolbar.
<center>
\image html reorient_faces_face.png
<em>"Reorient faces by vector" button</em>
<em>"Reorient faces" button</em>
</center>
The following dialog box will appear:
<center>
\image html reorient_2d_point.png
\image html reorient_2d_face.png
\image html reorient_2d_point.png "First mode: to reorient adjacent faces according to a vector. The control face is found by point."
<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>
<li>In this dialog
<ul>
<li>Specify the way of selection of the control face: by point or
explicitly.</li>
<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>
<li>Specify the coordinates of the \b Point by which the control face
will be found or of the control \b Face itself. You can easy specify the \b
<li>Specify either of the tree operation modes.</li>
<li>Select the \b Object (mesh, sub-mesh or group)
containing faces to reorient, in the Object Browser or in the 3D
Viewer.</li>
<li>To reorient according to vector: <ul>
<li>Specify the coordinates of the \b Point by which the control face
will be found or the control \b Face itself. You can easy specify the \b
Point by either picking a node in the 3D Viewer or selecting a vertex
in the Object Browser. It is possible to pick the \b Face by mouse in
the 3D Viewer or enter its ID.</li>
<li>Set up the \b Direction vector to be compared with the normal of the
<li>Set up the \b Direction vector to be compared with the normal of the
control face. If you pick a node in the 3D Viewer then the \b Direction
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>
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>
</li>
@ -51,6 +68,6 @@ The following dialog box will appear:
</ol>
<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.
* 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.
* \return number of reoriented elements.
* \return number of reoriented faces.
*/
long Reorient2D(in SMESH_IDSource the2Dgroup,
in DirStruct theDirection,
in long theFace,
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.

View File

@ -205,6 +205,7 @@ SET(SMESH_RESOURCES_FILES
mesh_min_dist.png
reorient_faces_point.png
reorient_faces_face.png
reorient_faces_volume.png
mesh_ball.png
mesh_measure_basic_props.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;
}
//================================================================================
/*!
* \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
//purpose :

View File

@ -126,6 +126,12 @@ public:
// Reverse theFaces whose orientation to be same as that of theFace
// 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.
* \param theElems - The triangles to be fused.

View File

@ -92,8 +92,8 @@
#define SPACING 6
#define MARGIN 11
enum { CONSTRUCTOR_POINT=0, CONSTRUCTOR_FACE,
EObject, EPoint, EFace, EDirection };
enum { CONSTRUCTOR_POINT=0, CONSTRUCTOR_FACE, CONSTRUCTOR_VOLUME,
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 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);
myConstructorGrp = new QButtonGroup(aConstructorBox);
@ -149,6 +150,11 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
aConstructorGrpLayout->addWidget(aFaceBut);
myConstructorGrp->addButton(aFaceBut, CONSTRUCTOR_FACE);
QRadioButton* aVolBut= new QRadioButton(aConstructorBox);
aVolBut->setIcon(iconReoriVolum);
aConstructorGrpLayout->addWidget(aVolBut);
myConstructorGrp->addButton(aVolBut, CONSTRUCTOR_VOLUME);
// Create other controls
setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
@ -157,17 +163,22 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
createObject( tr("POINT") , aFrame, EPoint );
createObject( tr("FACE") , aFrame, EFace );
createObject( tr("DIRECTION"), aFrame, EDirection );
createObject( tr("VOLUMES"), aFrame, EVolumes );
setNameIndication( EObject, OneName );
setNameIndication( EFace, OneName );
setReadOnly( EFace, false );
if ( QLineEdit* le = qobject_cast<QLineEdit*>( objectWg( EFace, Control ) ))
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( EObject , Label )->setFixedWidth( width );
objectWg( EPoint , 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);
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");
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
QGroupBox* anObjectGrp = new QGroupBox(tr("FACES"), aFrame);
@ -213,12 +233,12 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
objectWg( EPoint, Control )->hide();
aPointGrpLayout->addWidget( objectWg( EPoint, Label ) );
aPointGrpLayout->addWidget( objectWg( EPoint, Btn ) );
aPointGrpLayout->addWidget( aXLabel );
aPointGrpLayout->addWidget( myX );
aPointGrpLayout->addWidget( aYLabel );
aPointGrpLayout->addWidget( myY );
aPointGrpLayout->addWidget( aZLabel );
aPointGrpLayout->addWidget( myZ );
aPointGrpLayout->addWidget( aXLabel, 0 );
aPointGrpLayout->addWidget( myX, 1 );
aPointGrpLayout->addWidget( aYLabel, 0 );
aPointGrpLayout->addWidget( myY, 1 );
aPointGrpLayout->addWidget( aZLabel, 0 );
aPointGrpLayout->addWidget( myZ, 1 );
myFaceFrm = new QFrame(aFrame);
QHBoxLayout* aFaceGrpLayout = new QHBoxLayout(myFaceFrm);
@ -227,25 +247,35 @@ QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
aFaceGrpLayout->addWidget( objectWg( EFace, Btn ) );
aFaceGrpLayout->addWidget( objectWg( EFace, Control ) );
QFrame* aDirectFrm = new QFrame(aFrame);
QHBoxLayout* aDirectGrpLayout = new QHBoxLayout(aDirectFrm);
myVolumFrm = new QFrame(aFrame);
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);
objectWg( EDirection, Control )->hide();
aDirectGrpLayout->addWidget( objectWg( EDirection, Label ) );
aDirectGrpLayout->addWidget( objectWg( EDirection, Btn ) );
aDirectGrpLayout->addWidget(aDXLabel );
aDirectGrpLayout->addWidget(myDX );
aDirectGrpLayout->addWidget(aDYLabel );
aDirectGrpLayout->addWidget(myDY );
aDirectGrpLayout->addWidget(aDZLabel );
aDirectGrpLayout->addWidget(myDZ );
aDirectGrpLayout->addWidget( aDXLabel, 0 );
aDirectGrpLayout->addWidget( myDX, 1 );
aDirectGrpLayout->addWidget( aDYLabel, 0 );
aDirectGrpLayout->addWidget( myDY, 1 );
aDirectGrpLayout->addWidget( aDZLabel, 0 );
aDirectGrpLayout->addWidget( myDZ, 1 );
QGroupBox* anOrientGrp = new QGroupBox(tr("ORIENTATION"), aFrame);
QVBoxLayout* anOrientGrpLayout = new QVBoxLayout ( anOrientGrp );
anOrientGrpLayout->addWidget(myPointFrm);
anOrientGrpLayout->addWidget(myFaceFrm);
anOrientGrpLayout->addWidget(aDirectFrm);
anOrientGrpLayout->addWidget(myVolumFrm);
anOrientGrpLayout->addWidget(myDirFrm);
QVBoxLayout* aLay = new QVBoxLayout(aFrame);
@ -269,15 +299,27 @@ void SMESHGUI_ReorientFacesDlg::constructorChange(int id)
if ( id == CONSTRUCTOR_FACE )
{
myPointFrm->hide();
myVolumFrm->hide();
myFaceFrm->show();
myDirFrm->show();
activateObject( EFace );
}
else
else if ( id == CONSTRUCTOR_POINT )
{
myFaceFrm->hide();
myVolumFrm->hide();
myPointFrm->show();
myDirFrm->show();
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();
break;
case EObject:
case EVolumes:
SMESH::SetPointRepresentation(false);
setSelectionMode( ActorSelection );
break;
@ -406,6 +449,14 @@ SUIT_SelectionFilter* SMESHGUI_ReorientFacesOp::createFilter( const int what ) c
filters.append( new SMESH_TypeFilter( SMESH::GROUP_FACE ));
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:
{
QList<SUIT_SelectionFilter*> filters;
@ -433,6 +484,12 @@ void SMESHGUI_ReorientFacesOp::selectionDone()
if ( !myDlg->isVisible() || !myDlg->isEnabled() )
return;
if ( mySelectionMode == EVolumes )
{
SMESHGUI_SelectionOp::selectionDone();
return;
}
myDlg->clearSelection( mySelectionMode );
SALOME_ListIO aList;
@ -603,9 +660,26 @@ bool SMESHGUI_ReorientFacesOp::onApply()
try {
SUIT_OverrideCursor wc;
SMESH::SMESH_Mesh_var aMesh = myObject->GetMesh();
if ( aMesh->_is_nil() ) return false;
SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
if (aMeshEditor->_is_nil()) return false;
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();
@ -620,12 +694,11 @@ bool SMESHGUI_ReorientFacesOp::onApply()
point.y = myDlg->myY->GetValue();
point.z = myDlg->myZ->GetValue();
SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
if (aMeshEditor->_is_nil()) return false;
aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
int aResult = aMeshEditor->Reorient2D( myObject, direction, face, point );
aResult = aMeshEditor->Reorient2D( myObject, direction, face, point );
}
if (aResult)
{
SALOME_ListIO aList;
@ -673,6 +746,27 @@ bool SMESHGUI_ReorientFacesOp::isValid( QString& msg )
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
gp_Vec vec( myDlg->myDX->GetValue(),
myDlg->myDY->GetValue(),

View File

@ -33,12 +33,13 @@
#include "SMESHGUI_SelectionOp.h"
class QButtonGroup;
class QCheckBox;
class QLineEdit;
class SMESHGUI_SpinBox;
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
{
@ -76,6 +77,7 @@ private:
int mySelectionMode;
SMESH::SMESH_IDSource_var myObject;
SMESH::SMESH_IDSource_var myVolumeObj;
};
/*!
@ -98,6 +100,9 @@ private:
QButtonGroup* myConstructorGrp;
QFrame* myFaceFrm;
QFrame* myPointFrm;
QFrame* myDirFrm;
QFrame* myVolumFrm;
QCheckBox* myOutsideChk;
SMESHGUI_SpinBox* myX;
SMESHGUI_SpinBox* myY;
SMESHGUI_SpinBox* myZ;

View File

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

View File

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

View File

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

View File

@ -1645,7 +1645,7 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
TIDSortedElemSet elements;
prepareIdSource( the2Dgroup );
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;
@ -1710,6 +1710,55 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
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.

View File

@ -203,6 +203,18 @@ public:
const SMESH::DirStruct& theDirection,
CORBA::Long theFace,
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
CORBA::Boolean TriToQuad (const SMESH::long_array & IDsOfElements,

View File

@ -2964,6 +2964,37 @@ class Mesh:
theFace = -1
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.
# @param IDsOfElements The triangles to be fused,
# @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to