mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2024-11-11 16:19:16 +05:00
22316: EDF 2719 SMESH: Split hexas into prisms
This commit is contained in:
parent
a406fd6793
commit
f500e5a8b6
BIN
doc/salome/gui/SMESH/images/split_into_prisms.png
Normal file
BIN
doc/salome/gui/SMESH/images/split_into_prisms.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 26 KiB |
@ -39,7 +39,7 @@ with consequent transformation of all adjacent elements and edges.</li>
|
||||
of the selected elements.</li>
|
||||
<li>\subpage reorient_faces_page "Reorient faces by vector".</li>
|
||||
<li>\subpage cutting_quadrangles_page "Cut a quadrangle" into two triangles.</li>
|
||||
<li>\subpage split_to_tetra_page "Split" volumic elements into tetrahedra.</li>
|
||||
<li>\subpage split_to_tetra_page "Split" volumic elements into tetrahedra or prisms.</li>
|
||||
<li>\subpage smoothing_page "Smooth" elements, reducung distortions in
|
||||
them by adjusting the locations of element corners.</li>
|
||||
<li>Create an \subpage extrusion_page "extrusion" along a vector.</li>
|
||||
|
@ -1,53 +1,86 @@
|
||||
/*!
|
||||
|
||||
\page split_to_tetra_page Splitting volumes into tetrahedra
|
||||
\page split_to_tetra_page Splitting volumes
|
||||
|
||||
\n This operation allows to split volumic elements into tetrahedra.
|
||||
2D mesh is modified accordingly.
|
||||
\n This operation allows to split either any volumic elements into
|
||||
tetrahedra or hexahedra into prisms. 2D mesh is modified accordingly.
|
||||
|
||||
<em>To split volumes:</em>
|
||||
<ol>
|
||||
<li>Display a mesh or a submesh in the 3D viewer.</li>
|
||||
<li>In the \b Modification menu select the <b>Split into Tetrahedra</b> item or
|
||||
click <em>"Split into Tetrahedra"</em> button in the toolbar.
|
||||
<li>Display a mesh, a sub-mesh or a group in the 3D viewer.</li>
|
||||
<li>In the \b Modification menu select the <b>Split Volumes</b> item or
|
||||
click <em>"Split Volumes"</em> button in the toolbar.
|
||||
|
||||
\image html split_into_tetra_icon.png
|
||||
<center><em>"Split into Tetrahedra" button</em></center>
|
||||
<center><em>"Split Volumes" button</em></center>
|
||||
|
||||
The following dialog box will appear:
|
||||
|
||||
\image html split_into_tetra.png
|
||||
|
||||
\par
|
||||
<br>
|
||||
<b>Target element type</b> group of radio-buttons allows to select
|
||||
a type of operation. If \b Tetrahedron button is checked, then the
|
||||
operation will split volumes of any type into tetrahedra.
|
||||
If \b Prism button is checked, then the operation will split hexahedra
|
||||
into prisms, and the dialog will look as follows:
|
||||
|
||||
\image html split_into_prisms.png
|
||||
|
||||
<ul>
|
||||
<li>The main list contains the list of volumes. You can click on
|
||||
a volume in the 3D viewer and it will be highlighted (lock Shift
|
||||
keyboard button to select several volumes). Click \b Add button and
|
||||
the ID of this volume will be added to the list. To remove the
|
||||
selected element or elements from the list click \b Remove button. <b>Sort
|
||||
list</b> button allows to sort the list of IDs. \b Filter button allows to
|
||||
apply a definite filter to the selection of volumes.
|
||||
<br><b>Note:</b> If you split not all adjacent non-tetrahedral volumes, your mesh becomes
|
||||
non-conform.</li>
|
||||
<li>The main list contains list of volumes to split. You can click on
|
||||
a volume in the 3D viewer and it will be highlighted (lock Shift
|
||||
keyboard button to select several volumes). Click \b Add button and
|
||||
the ID of this volume will be added to the list. To remove the
|
||||
selected element or elements from the list click \b Remove button. <b>Sort
|
||||
list</b> button allows to sort the list of IDs. \b Filter button allows to
|
||||
apply a definite filter to the selection of volumes.
|
||||
<br><b>Note:</b> If you split not all adjacent non-tetrahedral
|
||||
volumes, your mesh becomes non-conform.</li>
|
||||
<li><b>Apply to all</b> radio button allows to split all
|
||||
volumes of the currently displayed mesh or submesh.</li>
|
||||
volumes of the currently selected mesh.</li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li>\b Split hexahedron
|
||||
<li><b> Split hexahedron </b> group allows to specify a method of
|
||||
splitting hexahedra.
|
||||
|
||||
<ul>
|
||||
<li><b>Into 5 tetrahedra</b>, <b>Into 6 tetrahedra</b> and <b>Into 24 tetrahedra</b> allows to
|
||||
specify the number of tetrahedra a hexahedron will be split into. If the specified method does
|
||||
not allow to get a conform mesh, a generic solution is applied: an additional node
|
||||
is created at the gravity center of a hexahedron, serving an apex of tetrahedra, all quadrangle sides of the hexahedron are split into two triangles each serving a base of a new tetrahedron.</li>
|
||||
</ul>
|
||||
|
||||
<li><b>Into N tetrahedra/prisms</b> allows to specify the number of
|
||||
tetrahedra or prisms a hexahedron will be split into. If the
|
||||
specified method does not allow to get a conform mesh, a generic
|
||||
solution is applied: an additional node is created at the gravity
|
||||
center of a hexahedron, serving an apex of tetrahedra, all
|
||||
quadrangle sides of the hexahedron are split into two triangles each
|
||||
serving a base of a new tetrahedron.</li>
|
||||
<li> <b> Facet to split </b> group allows to specify a side (facet) of a
|
||||
hexahedron to split into triangles when splitting into prisms.
|
||||
The facet to split is defined by specifying a point and a direction
|
||||
close to normal of the facet. The operation finds a hexahedron most
|
||||
close to the specified point and splits a facet whose normal is most
|
||||
close to the specified direction. Then the splitting is propagated
|
||||
from that hexahedron to all adjacent hexahedra.
|
||||
<ul>
|
||||
<li> <b> Hexa location </b> allows to specify a <em> start
|
||||
point </em> by which a first split hexahedron is found. <em>
|
||||
Selection button</em> switches to selection of the element whose
|
||||
barycenter will be used the start point and whose direction will be
|
||||
used as a normal to facet to split into triangles. To return to
|
||||
selection of volumes to split it is necessary to switch this button
|
||||
off. </li>
|
||||
<li> <b> Facet normal </b> allows to specify a direction of the
|
||||
normal to hexahedron facet to split into triangles.</li>
|
||||
</ul>
|
||||
<li><b> All domains </b> - if it is off the operation stops as all
|
||||
hehexedra adjacent to the start hexahedron are split into
|
||||
prisms. Else the operation tries to continue splitting starting from
|
||||
another hexahedron closest to the <b> Hexa location</b>. </li>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<li><b>Select from</b> a set of fields allows to choose a submesh or an
|
||||
existing group whose elements will be automatically added to the
|
||||
list.</li>
|
||||
<li><b>Select from</b> a set of fields allows to choose a sub-mesh or an
|
||||
existing group whose elements will be added to the list as you ckick
|
||||
\b Add button.</li>
|
||||
</ul>
|
||||
|
||||
<li>Click the \b Apply or <b>Apply and Close</b> button to confirm the operation.</li>
|
||||
|
@ -323,6 +323,25 @@ module SMESH
|
||||
void SplitVolumesIntoTetra(in SMESH_IDSource elems, in short methodFlags)
|
||||
raises (SALOME::SALOME_Exception);
|
||||
|
||||
/*!
|
||||
* \brief Split hexahedra into triangular prisms
|
||||
* \param elems - elements to split
|
||||
* \param facetToSplitNormal - normal used to find a facet of hexahedron
|
||||
* to split into triangles. Location of this vector is used to
|
||||
* find a hexahedron whose facets are tested using direction of this vector.
|
||||
* \param methodFlags - flags passing splitting method:
|
||||
* 1 - split the hexahedron into 2 prisms
|
||||
* 2 - split the hexahedron into 4 prisms
|
||||
* \param allDomains - if \c False, only hexahedra adjacent to one closest
|
||||
* to \a facetToSplitNormal location are split, else \a facetToSplitNormal
|
||||
* is used to find the facet to split in all domains present in \a elems.
|
||||
*/
|
||||
void SplitHexahedraIntoPrisms(in SMESH_IDSource elems,
|
||||
in short methodFlags,
|
||||
in SMESH::AxisStruct facetToSplitNormal,
|
||||
in boolean allDomains)
|
||||
raises (SALOME::SALOME_Exception);
|
||||
|
||||
|
||||
enum Smooth_Method { LAPLACIAN_SMOOTH, CENTROIDAL_SMOOTH };
|
||||
|
||||
|
@ -557,7 +557,6 @@ bool SMDS_VtkVolume::IsMediumNode(const SMDS_MeshNode* node) const
|
||||
int SMDS_VtkVolume::NbCornerNodes() const
|
||||
{
|
||||
vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myMeshId]->getGrid();
|
||||
int nbN = grid->GetCell(myVtkID)->GetNumberOfPoints();
|
||||
vtkIdType aVtkType = grid->GetCellType(myVtkID);
|
||||
switch (aVtkType)
|
||||
{
|
||||
@ -568,7 +567,7 @@ int SMDS_VtkVolume::NbCornerNodes() const
|
||||
case VTK_TRIQUADRATIC_HEXAHEDRON: return 8;
|
||||
default:;
|
||||
}
|
||||
return nbN;
|
||||
return grid->GetCell(myVtkID)->GetNumberOfPoints();
|
||||
}
|
||||
|
||||
SMDSAbs_EntityType SMDS_VtkVolume::GetEntityType() const
|
||||
|
@ -1603,44 +1603,110 @@ namespace
|
||||
const int* thePentaTo3[6] = { thePentaTo3_1, thePentaTo3_2, thePentaTo3_3,
|
||||
thePentaTo3_4, thePentaTo3_5, thePentaTo3_6 };
|
||||
|
||||
// Methods of splitting hexahedron into prisms
|
||||
|
||||
const int theHexTo4Prisms_BT[6*4+1] = // bottom-top
|
||||
{
|
||||
0, 1, 8, 4, 5, 9, 1, 2, 8, 5, 6, 9, 2, 3, 8, 6, 7, 9, 3, 0, 8, 7, 4, 9, -1
|
||||
};
|
||||
const int theHexTo4Prisms_LR[6*4+1] = // left-right
|
||||
{
|
||||
1, 0, 8, 2, 3, 9, 0, 4, 8, 3, 7, 9, 4, 5, 8, 7, 6, 9, 5, 1, 8, 6, 2, 9, -1
|
||||
};
|
||||
const int theHexTo4Prisms_FB[6*4+1] = // front-back
|
||||
{
|
||||
0, 3, 8, 1, 2, 9, 3, 7, 8, 2, 6, 9, 7, 4, 8, 6, 5, 9, 4, 0, 8, 5, 1, 9, -1
|
||||
};
|
||||
|
||||
const int theHexTo2Prisms_BT_1[6*2+1] =
|
||||
{
|
||||
0, 1, 3, 4, 5, 7, 1, 2, 3, 5, 6, 7, -1
|
||||
};
|
||||
const int theHexTo2Prisms_BT_2[6*2+1] =
|
||||
{
|
||||
0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 6, 7, -1
|
||||
};
|
||||
const int* theHexTo2Prisms_BT[2] = { theHexTo2Prisms_BT_1, theHexTo2Prisms_BT_2 };
|
||||
|
||||
const int theHexTo2Prisms_LR_1[6*2+1] =
|
||||
{
|
||||
1, 0, 4, 2, 3, 7, 1, 4, 5, 2, 7, 6, -1
|
||||
};
|
||||
const int theHexTo2Prisms_LR_2[6*2+1] =
|
||||
{
|
||||
1, 0, 4, 2, 3, 7, 1, 4, 5, 2, 7, 6, -1
|
||||
};
|
||||
const int* theHexTo2Prisms_LR[2] = { theHexTo2Prisms_LR_1, theHexTo2Prisms_LR_2 };
|
||||
|
||||
const int theHexTo2Prisms_FB_1[6*2+1] =
|
||||
{
|
||||
0, 3, 4, 1, 2, 5, 3, 7, 4, 2, 6, 5, -1
|
||||
};
|
||||
const int theHexTo2Prisms_FB_2[6*2+1] =
|
||||
{
|
||||
0, 3, 7, 1, 2, 7, 0, 7, 4, 1, 6, 5, -1
|
||||
};
|
||||
const int* theHexTo2Prisms_FB[2] = { theHexTo2Prisms_FB_1, theHexTo2Prisms_FB_2 };
|
||||
|
||||
|
||||
struct TTriangleFacet //!< stores indices of three nodes of tetra facet
|
||||
{
|
||||
int _n1, _n2, _n3;
|
||||
TTriangleFacet(int n1, int n2, int n3): _n1(n1), _n2(n2), _n3(n3) {}
|
||||
bool contains(int n) const { return ( n == _n1 || n == _n2 || n == _n3 ); }
|
||||
bool hasAdjacentTetra( const SMDS_MeshElement* elem ) const;
|
||||
bool hasAdjacentVol( const SMDS_MeshElement* elem,
|
||||
const SMDSAbs_GeometryType geom = SMDSGeom_TETRA) const;
|
||||
};
|
||||
struct TSplitMethod
|
||||
{
|
||||
int _nbTetra;
|
||||
int _nbSplits;
|
||||
int _nbCorners;
|
||||
const int* _connectivity; //!< foursomes of tetra connectivy finished by -1
|
||||
bool _baryNode; //!< additional node is to be created at cell barycenter
|
||||
bool _ownConn; //!< to delete _connectivity in destructor
|
||||
map<int, const SMDS_MeshNode*> _faceBaryNode; //!< map face index to node at BC of face
|
||||
|
||||
TSplitMethod( int nbTet=0, const int* conn=0, bool addNode=false)
|
||||
: _nbTetra(nbTet), _connectivity(conn), _baryNode(addNode), _ownConn(false) {}
|
||||
: _nbSplits(nbTet), _nbCorners(4), _connectivity(conn), _baryNode(addNode), _ownConn(false) {}
|
||||
~TSplitMethod() { if ( _ownConn ) delete [] _connectivity; _connectivity = 0; }
|
||||
bool hasFacet( const TTriangleFacet& facet ) const
|
||||
{
|
||||
const int* tetConn = _connectivity;
|
||||
for ( ; tetConn[0] >= 0; tetConn += 4 )
|
||||
if (( facet.contains( tetConn[0] ) +
|
||||
facet.contains( tetConn[1] ) +
|
||||
facet.contains( tetConn[2] ) +
|
||||
facet.contains( tetConn[3] )) == 3 )
|
||||
return true;
|
||||
if ( _nbCorners == 4 )
|
||||
{
|
||||
const int* tetConn = _connectivity;
|
||||
for ( ; tetConn[0] >= 0; tetConn += 4 )
|
||||
if (( facet.contains( tetConn[0] ) +
|
||||
facet.contains( tetConn[1] ) +
|
||||
facet.contains( tetConn[2] ) +
|
||||
facet.contains( tetConn[3] )) == 3 )
|
||||
return true;
|
||||
}
|
||||
else // prism, _nbCorners == 6
|
||||
{
|
||||
const int* prismConn = _connectivity;
|
||||
for ( ; prismConn[0] >= 0; prismConn += 6 )
|
||||
{
|
||||
if (( facet.contains( prismConn[0] ) &&
|
||||
facet.contains( prismConn[1] ) &&
|
||||
facet.contains( prismConn[2] ))
|
||||
||
|
||||
( facet.contains( prismConn[3] ) &&
|
||||
facet.contains( prismConn[4] ) &&
|
||||
facet.contains( prismConn[5] )))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//=======================================================================
|
||||
/*!
|
||||
* \brief return TSplitMethod for the given element
|
||||
* \brief return TSplitMethod for the given element to split into tetrahedra
|
||||
*/
|
||||
//=======================================================================
|
||||
|
||||
TSplitMethod getSplitMethod( SMDS_VolumeTool& vol, const int theMethodFlags)
|
||||
TSplitMethod getTetraSplitMethod( SMDS_VolumeTool& vol, const int theMethodFlags)
|
||||
{
|
||||
const int iQ = vol.Element()->IsQuadratic() ? 2 : 1;
|
||||
|
||||
@ -1665,8 +1731,8 @@ namespace
|
||||
{
|
||||
TTriangleFacet t012( nInd[0*iQ], nInd[1*iQ], nInd[2*iQ] );
|
||||
TTriangleFacet t123( nInd[1*iQ], nInd[2*iQ], nInd[3*iQ] );
|
||||
if ( t012.hasAdjacentTetra( vol.Element() )) triaSplits.push_back( t012 );
|
||||
else if ( t123.hasAdjacentTetra( vol.Element() )) triaSplits.push_back( t123 );
|
||||
if ( t012.hasAdjacentVol( vol.Element() )) triaSplits.push_back( t012 );
|
||||
else if ( t123.hasAdjacentVol( vol.Element() )) triaSplits.push_back( t123 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1679,7 +1745,7 @@ namespace
|
||||
TTriangleFacet t023( nInd[ iQ * ( iCom )],
|
||||
nInd[ iQ * ( (iCom+2)%nbNodes )],
|
||||
nInd[ iQ * ( (iCom+3)%nbNodes )]);
|
||||
if ( t012.hasAdjacentTetra( vol.Element() ) && t023.hasAdjacentTetra( vol.Element() ))
|
||||
if ( t012.hasAdjacentVol( vol.Element() ) && t023.hasAdjacentVol( vol.Element() ))
|
||||
{
|
||||
triaSplits.push_back( t012 );
|
||||
triaSplits.push_back( t023 );
|
||||
@ -1719,12 +1785,12 @@ namespace
|
||||
default:
|
||||
nbVariants = 0;
|
||||
}
|
||||
for ( int variant = 0; variant < nbVariants && method._nbTetra == 0; ++variant )
|
||||
for ( int variant = 0; variant < nbVariants && method._nbSplits == 0; ++variant )
|
||||
{
|
||||
// check method compliancy with adjacent tetras,
|
||||
// all found splits must be among facets of tetras described by this method
|
||||
method = TSplitMethod( nbTet, connVariants[variant] );
|
||||
if ( hasAdjacentSplits && method._nbTetra > 0 )
|
||||
if ( hasAdjacentSplits && method._nbSplits > 0 )
|
||||
{
|
||||
bool facetCreated = true;
|
||||
for ( int iF = 0; facetCreated && iF < triaSplitsByFace.size(); ++iF )
|
||||
@ -1738,7 +1804,7 @@ namespace
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( method._nbTetra < 1 )
|
||||
if ( method._nbSplits < 1 )
|
||||
{
|
||||
// No standard method is applicable, use a generic solution:
|
||||
// each facet of a volume is split into triangles and
|
||||
@ -1832,7 +1898,7 @@ namespace
|
||||
connectivity[ connSize++ ] = baryCenInd;
|
||||
}
|
||||
}
|
||||
method._nbTetra += nbTet;
|
||||
method._nbSplits += nbTet;
|
||||
|
||||
} // loop on volume faces
|
||||
|
||||
@ -1842,13 +1908,132 @@ namespace
|
||||
|
||||
return method;
|
||||
}
|
||||
//=======================================================================
|
||||
/*!
|
||||
* \brief return TSplitMethod to split haxhedron into prisms
|
||||
*/
|
||||
//=======================================================================
|
||||
|
||||
TSplitMethod getPrismSplitMethod( SMDS_VolumeTool& vol,
|
||||
const int methodFlags,
|
||||
const int facetToSplit)
|
||||
{
|
||||
// order of facets in HEX according to SMDS_VolumeTool::Hexa_F :
|
||||
// B, T, L, B, R, F
|
||||
const int iF = ( facetToSplit < 2 ) ? 0 : 1 + ( facetToSplit-2 ) % 2; // [0,1,2]
|
||||
|
||||
if ( methodFlags == SMESH_MeshEditor::HEXA_TO_4_PRISMS )
|
||||
{
|
||||
static TSplitMethod to4methods[4]; // order BT, LR, FB
|
||||
if ( to4methods[iF]._nbSplits == 0 )
|
||||
{
|
||||
switch ( iF ) {
|
||||
case 0:
|
||||
to4methods[iF]._connectivity = theHexTo4Prisms_BT;
|
||||
to4methods[iF]._faceBaryNode[ 0 ] = 0;
|
||||
to4methods[iF]._faceBaryNode[ 1 ] = 0;
|
||||
break;
|
||||
case 1:
|
||||
to4methods[iF]._connectivity = theHexTo4Prisms_LR;
|
||||
to4methods[iF]._faceBaryNode[ 2 ] = 0;
|
||||
to4methods[iF]._faceBaryNode[ 4 ] = 0;
|
||||
break;
|
||||
case 2:
|
||||
to4methods[iF]._connectivity = theHexTo4Prisms_FB;
|
||||
to4methods[iF]._faceBaryNode[ 3 ] = 0;
|
||||
to4methods[iF]._faceBaryNode[ 5 ] = 0;
|
||||
break;
|
||||
default: return to4methods[3];
|
||||
}
|
||||
to4methods[iF]._nbSplits = 4;
|
||||
to4methods[iF]._nbCorners = 6;
|
||||
}
|
||||
return to4methods[iF];
|
||||
}
|
||||
// else if ( methodFlags == HEXA_TO_2_PRISMS )
|
||||
|
||||
TSplitMethod method;
|
||||
|
||||
const int iQ = vol.Element()->IsQuadratic() ? 2 : 1;
|
||||
|
||||
const int nbVariants = 2, nbSplits = 2;
|
||||
const int** connVariants = 0;
|
||||
switch ( iF ) {
|
||||
case 0: connVariants = theHexTo2Prisms_BT; break;
|
||||
case 1: connVariants = theHexTo2Prisms_LR; break;
|
||||
case 2: connVariants = theHexTo2Prisms_FB; break;
|
||||
default: return method;
|
||||
}
|
||||
|
||||
// look for prisms adjacent via facetToSplit and an opposite one
|
||||
for ( int is2nd = 0; is2nd < 2; ++is2nd )
|
||||
{
|
||||
int iFacet = is2nd ? vol.GetOppFaceIndexOfHex( facetToSplit ) : facetToSplit;
|
||||
int nbNodes = vol.NbFaceNodes( iFacet ) / iQ;
|
||||
if ( nbNodes != 4 ) return method;
|
||||
|
||||
const int* nInd = vol.GetFaceNodesIndices( iFacet );
|
||||
TTriangleFacet t012( nInd[0*iQ], nInd[1*iQ], nInd[2*iQ] );
|
||||
TTriangleFacet t123( nInd[1*iQ], nInd[2*iQ], nInd[3*iQ] );
|
||||
TTriangleFacet* t;
|
||||
if ( t012.hasAdjacentVol( vol.Element(), SMDSGeom_PENTA ))
|
||||
t = &t012;
|
||||
else if ( t123.hasAdjacentVol( vol.Element(), SMDSGeom_PENTA ))
|
||||
t = &t123;
|
||||
else
|
||||
continue;
|
||||
|
||||
// there are adjacent prism
|
||||
for ( int variant = 0; variant < nbVariants; ++variant )
|
||||
{
|
||||
// check method compliancy with adjacent prisms,
|
||||
// the found prism facets must be among facets of prisms described by current method
|
||||
method._nbSplits = nbSplits;
|
||||
method._nbCorners = 6;
|
||||
method._connectivity = connVariants[ variant ];
|
||||
if ( method.hasFacet( *t ))
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
// No adjacent prisms. Select a variant with a best aspect ratio.
|
||||
|
||||
double badness[2] = { 0, 0 };
|
||||
static SMESH::Controls::NumericalFunctorPtr aspectRatio( new SMESH::Controls::AspectRatio);
|
||||
const SMDS_MeshNode** nodes = vol.GetNodes();
|
||||
for ( int variant = 0; variant < nbVariants; ++variant )
|
||||
for ( int is2nd = 0; is2nd < 2; ++is2nd )
|
||||
{
|
||||
int iFacet = is2nd ? vol.GetOppFaceIndexOfHex( facetToSplit ) : facetToSplit;
|
||||
const int* nInd = vol.GetFaceNodesIndices( iFacet );
|
||||
|
||||
method._connectivity = connVariants[ variant ];
|
||||
TTriangleFacet t012( nInd[0*iQ], nInd[1*iQ], nInd[2*iQ] );
|
||||
TTriangleFacet t123( nInd[1*iQ], nInd[2*iQ], nInd[3*iQ] );
|
||||
TTriangleFacet* t = ( method.hasFacet( t012 )) ? & t012 : & t123;
|
||||
|
||||
SMDS_FaceOfNodes tria ( nodes[ t->_n1 ],
|
||||
nodes[ t->_n2 ],
|
||||
nodes[ t->_n3 ] );
|
||||
badness[ variant ] += getBadRate( &tria, aspectRatio );
|
||||
}
|
||||
const int iBetter = ( badness[1] < badness[0] && badness[0]-badness[1] > 0.1 * badness[0] );
|
||||
|
||||
method._nbSplits = nbSplits;
|
||||
method._nbCorners = 6;
|
||||
method._connectivity = connVariants[ iBetter ];
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Check if there is a tetraherdon adjacent to the given element via this facet
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
bool TTriangleFacet::hasAdjacentTetra( const SMDS_MeshElement* elem ) const
|
||||
bool TTriangleFacet::hasAdjacentVol( const SMDS_MeshElement* elem,
|
||||
const SMDSAbs_GeometryType geom ) const
|
||||
{
|
||||
// find the tetrahedron including the three nodes of facet
|
||||
const SMDS_MeshNode* n1 = elem->GetNode(_n1);
|
||||
@ -1858,16 +2043,16 @@ namespace
|
||||
while ( volIt1->more() )
|
||||
{
|
||||
const SMDS_MeshElement* v = volIt1->next();
|
||||
SMDSAbs_EntityType type = v->GetEntityType();
|
||||
if ( type != SMDSEntity_Tetra && type != SMDSEntity_Quad_Tetra )
|
||||
if ( v->GetGeomType() != geom )
|
||||
continue;
|
||||
if ( type == SMDSEntity_Quad_Tetra && v->GetNodeIndex( n1 ) > 3 )
|
||||
const int lastCornerInd = v->NbCornerNodes() - 1;
|
||||
if ( v->IsQuadratic() && v->GetNodeIndex( n1 ) > lastCornerInd )
|
||||
continue; // medium node not allowed
|
||||
const int ind2 = v->GetNodeIndex( n2 );
|
||||
if ( ind2 < 0 || 3 < ind2 )
|
||||
if ( ind2 < 0 || lastCornerInd < ind2 )
|
||||
continue;
|
||||
const int ind3 = v->GetNodeIndex( n3 );
|
||||
if ( ind3 < 0 || 3 < ind3 )
|
||||
if ( ind3 < 0 || lastCornerInd < ind3 )
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
@ -1900,19 +2085,23 @@ namespace
|
||||
} // namespace
|
||||
|
||||
//=======================================================================
|
||||
//function : SplitVolumesIntoTetra
|
||||
//purpose : Split volume elements into tetrahedra.
|
||||
//function : SplitVolumes
|
||||
//purpose : Split volume elements into tetrahedra or prisms.
|
||||
// If facet ID < 0, element is split into tetrahedra,
|
||||
// else a hexahedron is split into prisms so that the given facet is
|
||||
// split into triangles
|
||||
//=======================================================================
|
||||
|
||||
void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
const int theMethodFlags)
|
||||
void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
|
||||
const int theMethodFlags)
|
||||
{
|
||||
// std-like iterator on coordinates of nodes of mesh element
|
||||
typedef SMDS_StdIterator< SMESH_TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator;
|
||||
NXyzIterator xyzEnd;
|
||||
|
||||
SMDS_VolumeTool volTool;
|
||||
SMESH_MesherHelper helper( *GetMesh());
|
||||
SMESH_MesherHelper helper( *GetMesh()), fHelper(*GetMesh());
|
||||
fHelper.ToFixNodeParameters( true );
|
||||
|
||||
SMESHDS_SubMesh* subMesh = 0;//GetMeshDS()->MeshElements(1);
|
||||
SMESHDS_SubMesh* fSubMesh = 0;//subMesh;
|
||||
@ -1923,29 +2112,33 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
map< TVolumeFaceKey, const SMDS_MeshNode* > volFace2BaryNode;
|
||||
double bc[3];
|
||||
|
||||
TIDSortedElemSet::const_iterator elem = theElems.begin();
|
||||
for ( ; elem != theElems.end(); ++elem )
|
||||
TFacetOfElem::const_iterator elem2facet = theElems.begin();
|
||||
for ( ; elem2facet != theElems.end(); ++elem2facet )
|
||||
{
|
||||
if ( (*elem)->GetType() != SMDSAbs_Volume )
|
||||
const SMDS_MeshElement* elem = elem2facet->first;
|
||||
const int facetToSplit = elem2facet->second;
|
||||
if ( elem->GetType() != SMDSAbs_Volume )
|
||||
continue;
|
||||
SMDSAbs_EntityType geomType = (*elem)->GetEntityType();
|
||||
const SMDSAbs_EntityType geomType = elem->GetEntityType();
|
||||
if ( geomType == SMDSEntity_Tetra || geomType == SMDSEntity_Quad_Tetra )
|
||||
continue;
|
||||
|
||||
if ( !volTool.Set( *elem, /*ignoreCentralNodes=*/false )) continue; // strange...
|
||||
if ( !volTool.Set( elem, /*ignoreCentralNodes=*/false )) continue; // strange...
|
||||
|
||||
TSplitMethod splitMethod = getSplitMethod( volTool, theMethodFlags );
|
||||
if ( splitMethod._nbTetra < 1 ) continue;
|
||||
TSplitMethod splitMethod = ( facetToSplit < 0 ?
|
||||
getTetraSplitMethod( volTool, theMethodFlags ) :
|
||||
getPrismSplitMethod( volTool, theMethodFlags, facetToSplit ));
|
||||
if ( splitMethod._nbSplits < 1 ) continue;
|
||||
|
||||
// find submesh to add new tetras to
|
||||
if ( !subMesh || !subMesh->Contains( *elem ))
|
||||
if ( !subMesh || !subMesh->Contains( elem ))
|
||||
{
|
||||
int shapeID = FindShape( *elem );
|
||||
int shapeID = FindShape( elem );
|
||||
helper.SetSubShape( shapeID ); // helper will add tetras to the found submesh
|
||||
subMesh = GetMeshDS()->MeshElements( shapeID );
|
||||
}
|
||||
int iQ;
|
||||
if ( (*elem)->IsQuadratic() )
|
||||
if ( elem->IsQuadratic() )
|
||||
{
|
||||
iQ = 2;
|
||||
// add quadratic links to the helper
|
||||
@ -1963,7 +2156,8 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
iQ = 1;
|
||||
helper.SetIsQuadratic( false );
|
||||
}
|
||||
vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() );
|
||||
vector<const SMDS_MeshNode*> nodes( volTool.GetNodes(),
|
||||
volTool.GetNodes() + elem->NbCornerNodes() );
|
||||
helper.SetElementsOnShape( true );
|
||||
if ( splitMethod._baryNode )
|
||||
{
|
||||
@ -1991,16 +2185,25 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
}
|
||||
}
|
||||
|
||||
// make tetras
|
||||
vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra ); // splits of a volume
|
||||
const int* tetConn = splitMethod._connectivity;
|
||||
for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 )
|
||||
newElems.Append( tetras[ i ] = helper.AddVolume( nodes[ tetConn[0] ],
|
||||
nodes[ tetConn[1] ],
|
||||
nodes[ tetConn[2] ],
|
||||
nodes[ tetConn[3] ]));
|
||||
// make new volumes
|
||||
vector<const SMDS_MeshElement* > splitVols( splitMethod._nbSplits ); // splits of a volume
|
||||
const int* volConn = splitMethod._connectivity;
|
||||
if ( splitMethod._nbCorners == 4 ) // tetra
|
||||
for ( int i = 0; i < splitMethod._nbSplits; ++i, volConn += splitMethod._nbCorners )
|
||||
newElems.Append( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
|
||||
nodes[ volConn[1] ],
|
||||
nodes[ volConn[2] ],
|
||||
nodes[ volConn[3] ]));
|
||||
else // prisms
|
||||
for ( int i = 0; i < splitMethod._nbSplits; ++i, volConn += splitMethod._nbCorners )
|
||||
newElems.Append( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
|
||||
nodes[ volConn[1] ],
|
||||
nodes[ volConn[2] ],
|
||||
nodes[ volConn[3] ],
|
||||
nodes[ volConn[4] ],
|
||||
nodes[ volConn[5] ]));
|
||||
|
||||
ReplaceElemInGroups( *elem, tetras, GetMeshDS() );
|
||||
ReplaceElemInGroups( elem, splitVols, GetMeshDS() );
|
||||
|
||||
// Split faces on sides of the split volume
|
||||
|
||||
@ -2029,17 +2232,37 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.find(iF);
|
||||
if ( iF_n != splitMethod._faceBaryNode.end() )
|
||||
{
|
||||
const SMDS_MeshNode *baryNode = iF_n->second;
|
||||
for ( int iN = 0; iN < nbNodes*iQ; iN += iQ )
|
||||
{
|
||||
const SMDS_MeshNode* n1 = fNodes[iN];
|
||||
const SMDS_MeshNode *n2 = fNodes[(iN+iQ)%(nbNodes*iQ)];
|
||||
const SMDS_MeshNode *n3 = iF_n->second;
|
||||
const SMDS_MeshNode *n3 = baryNode;
|
||||
if ( !volTool.IsFaceExternal( iF ))
|
||||
swap( n2, n3 );
|
||||
triangles.push_back( helper.AddFace( n1,n2,n3 ));
|
||||
|
||||
if ( fSubMesh && n3->getshapeId() < 1 )
|
||||
fSubMesh->AddNode( n3 );
|
||||
}
|
||||
if ( fSubMesh ) // update position of the bary node on geometry
|
||||
{
|
||||
if ( subMesh )
|
||||
subMesh->RemoveNode( baryNode, false );
|
||||
GetMeshDS()->SetNodeOnFace( baryNode, fSubMesh->GetID() );
|
||||
const TopoDS_Shape& s = GetMeshDS()->IndexToShape( fSubMesh->GetID() );
|
||||
if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
|
||||
{
|
||||
fHelper.SetSubShape( s );
|
||||
gp_XY uv( 1e100, 1e100 );
|
||||
double distXYZ[4];
|
||||
if ( !fHelper.CheckNodeUV( TopoDS::Face( s ), baryNode,
|
||||
uv, /*tol=*/1e-7, /*force=*/true, distXYZ ) &&
|
||||
uv.X() < 1e100 )
|
||||
{
|
||||
// node is too far from the surface
|
||||
GetMeshDS()->MoveNode( baryNode, distXYZ[1], distXYZ[2], distXYZ[3] );
|
||||
const_cast<SMDS_MeshNode*>( baryNode )->SetPosition
|
||||
( SMDS_PositionPtr( new SMDS_FacePosition( uv.X(), uv.Y() )));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2069,6 +2292,8 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
}
|
||||
}
|
||||
list< TTriangleFacet >::iterator facet = facets.begin();
|
||||
if ( facet == facets.end() )
|
||||
break;
|
||||
for ( ; facet != facets.end(); ++facet )
|
||||
{
|
||||
if ( !volTool.IsFaceExternal( iF ))
|
||||
@ -2087,11 +2312,11 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
}
|
||||
ReplaceElemInGroups( face, triangles, GetMeshDS() );
|
||||
GetMeshDS()->RemoveFreeElement( face, fSubMesh, /*fromGroups=*/false );
|
||||
}
|
||||
|
||||
} // while a face based on facet nodes exists
|
||||
} // loop on volume faces to split them into triangles
|
||||
|
||||
GetMeshDS()->RemoveFreeElement( *elem, subMesh, /*fromGroups=*/false );
|
||||
GetMeshDS()->RemoveFreeElement( elem, subMesh, /*fromGroups=*/false );
|
||||
|
||||
if ( geomType == SMDSEntity_TriQuad_Hexa )
|
||||
{
|
||||
@ -2106,6 +2331,198 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
|
||||
myLastCreatedElems = newElems;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : GetHexaFacetsToSplit
|
||||
//purpose : For hexahedra that will be split into prisms, finds facets to
|
||||
// split into triangles. Only hexahedra adjacent to the one closest
|
||||
// to theFacetNormal.Location() are returned.
|
||||
//param [in,out] theHexas - the hexahedra
|
||||
//param [in] theFacetNormal - facet normal
|
||||
//param [out] theFacets - the hexahedra and found facet IDs
|
||||
//=======================================================================
|
||||
|
||||
void SMESH_MeshEditor::GetHexaFacetsToSplit( TIDSortedElemSet& theHexas,
|
||||
const gp_Ax1& theFacetNormal,
|
||||
TFacetOfElem & theFacets)
|
||||
{
|
||||
#define THIS_METHOD "SMESH_MeshEditor::GetHexaFacetsToSplit(): "
|
||||
|
||||
// Find a hexa closest to the location of theFacetNormal
|
||||
|
||||
const SMDS_MeshElement* startHex;
|
||||
{
|
||||
// get SMDS_ElemIteratorPtr on theHexas
|
||||
typedef const SMDS_MeshElement* TValue;
|
||||
typedef TIDSortedElemSet::iterator TSetIterator;
|
||||
typedef SMDS::SimpleAccessor<TValue,TSetIterator> TAccesor;
|
||||
typedef SMDS_MeshElement::GeomFilter TFilter;
|
||||
typedef SMDS_SetIterator < TValue, TSetIterator, TAccesor, TFilter > TElemSetIter;
|
||||
SMDS_ElemIteratorPtr elemIt = SMDS_ElemIteratorPtr
|
||||
( new TElemSetIter( theHexas.begin(),
|
||||
theHexas.end(),
|
||||
SMDS_MeshElement::GeomFilter( SMDSGeom_HEXA )));
|
||||
|
||||
SMESH_ElementSearcher* searcher =
|
||||
SMESH_MeshAlgos::GetElementSearcher( *myMesh->GetMeshDS(), elemIt );
|
||||
|
||||
startHex = searcher->FindClosestTo( theFacetNormal.Location(), SMDSAbs_Volume );
|
||||
|
||||
delete searcher;
|
||||
|
||||
if ( !startHex )
|
||||
throw SALOME_Exception( THIS_METHOD "startHex not found");
|
||||
}
|
||||
|
||||
// Select a facet of startHex by theFacetNormal
|
||||
|
||||
SMDS_VolumeTool vTool( startHex );
|
||||
double norm[3], dot, maxDot = 0;
|
||||
int facetID = -1;
|
||||
for ( int iF = 0; iF < vTool.NbFaces(); ++iF )
|
||||
if ( vTool.GetFaceNormal( iF, norm[0], norm[1], norm[2] ))
|
||||
{
|
||||
dot = Abs( theFacetNormal.Direction().Dot( gp_Dir( norm[0], norm[1], norm[2] )));
|
||||
if ( dot > maxDot )
|
||||
{
|
||||
facetID = iF;
|
||||
maxDot = dot;
|
||||
}
|
||||
}
|
||||
if ( facetID < 0 )
|
||||
throw SALOME_Exception( THIS_METHOD "facet of startHex not found");
|
||||
|
||||
// Fill theFacets starting from facetID of startHex
|
||||
|
||||
// facets used for seach of volumes adjacent to already treated ones
|
||||
typedef pair< TFacetOfElem::iterator, int > TElemFacets;
|
||||
typedef map< TVolumeFaceKey, TElemFacets > TFacetMap;
|
||||
TFacetMap facetsToCheck;
|
||||
|
||||
set<const SMDS_MeshNode*> facetNodes;
|
||||
const SMDS_MeshElement* curHex;
|
||||
|
||||
const bool allHex = ( theHexas.size() == myMesh->NbHexas() );
|
||||
|
||||
while ( startHex )
|
||||
{
|
||||
// move in two directions from startHex via facetID
|
||||
for ( int is2nd = 0; is2nd < 2; ++is2nd )
|
||||
{
|
||||
curHex = startHex;
|
||||
int curFacet = facetID;
|
||||
if ( is2nd ) // do not treat startHex twice
|
||||
{
|
||||
vTool.Set( curHex );
|
||||
if ( vTool.IsFreeFace( curFacet, &curHex ))
|
||||
{
|
||||
curHex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vTool.GetFaceNodes( curFacet, facetNodes );
|
||||
vTool.Set( curHex );
|
||||
curFacet = vTool.GetFaceIndex( facetNodes );
|
||||
}
|
||||
}
|
||||
while ( curHex )
|
||||
{
|
||||
// store a facet to split
|
||||
if ( curHex->GetGeomType() != SMDSGeom_HEXA )
|
||||
{
|
||||
theFacets.insert( make_pair( curHex, -1 ));
|
||||
break;
|
||||
}
|
||||
if ( !allHex && !theHexas.count( curHex ))
|
||||
break;
|
||||
|
||||
pair< TFacetOfElem::iterator, bool > facetIt2isNew =
|
||||
theFacets.insert( make_pair( curHex, curFacet ));
|
||||
if ( !facetIt2isNew.second )
|
||||
break;
|
||||
|
||||
// remember not-to-split facets in facetsToCheck
|
||||
int oppFacet = vTool.GetOppFaceIndexOfHex( curFacet );
|
||||
for ( int iF = 0; iF < vTool.NbFaces(); ++iF )
|
||||
{
|
||||
if ( iF == curFacet && iF == oppFacet )
|
||||
continue;
|
||||
TVolumeFaceKey facetKey ( vTool, iF );
|
||||
TElemFacets elemFacet( facetIt2isNew.first, iF );
|
||||
pair< TFacetMap::iterator, bool > it2isnew =
|
||||
facetsToCheck.insert( make_pair( facetKey, elemFacet ));
|
||||
if ( !it2isnew.second )
|
||||
facetsToCheck.erase( it2isnew.first ); // adjacent hex already checked
|
||||
}
|
||||
// pass to a volume adjacent via oppFacet
|
||||
if ( vTool.IsFreeFace( oppFacet, &curHex ))
|
||||
{
|
||||
curHex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get a new curFacet
|
||||
vTool.GetFaceNodes( oppFacet, facetNodes );
|
||||
vTool.Set( curHex );
|
||||
curFacet = vTool.GetFaceIndex( facetNodes, /*hint=*/curFacet );
|
||||
}
|
||||
}
|
||||
} // move in two directions from startHex via facetID
|
||||
|
||||
// Find a new startHex by facetsToCheck
|
||||
|
||||
startHex = 0;
|
||||
facetID = -1;
|
||||
TFacetMap::iterator fIt = facetsToCheck.begin();
|
||||
while ( !startHex && fIt != facetsToCheck.end() )
|
||||
{
|
||||
const TElemFacets& elemFacets = fIt->second;
|
||||
const SMDS_MeshElement* hex = elemFacets.first->first;
|
||||
int splitFacet = elemFacets.first->second;
|
||||
int lateralFacet = elemFacets.second;
|
||||
facetsToCheck.erase( fIt );
|
||||
fIt = facetsToCheck.begin();
|
||||
|
||||
vTool.Set( hex );
|
||||
if ( vTool.IsFreeFace( lateralFacet, &curHex ) ||
|
||||
curHex->GetGeomType() != SMDSGeom_HEXA )
|
||||
continue;
|
||||
if ( !allHex && !theHexas.count( curHex ))
|
||||
continue;
|
||||
|
||||
startHex = curHex;
|
||||
|
||||
// find a facet of startHex to split
|
||||
|
||||
set<const SMDS_MeshNode*> lateralNodes;
|
||||
vTool.GetFaceNodes( lateralFacet, lateralNodes );
|
||||
vTool.GetFaceNodes( splitFacet, facetNodes );
|
||||
int oppLateralFacet = vTool.GetOppFaceIndexOfHex( lateralFacet );
|
||||
vTool.Set( startHex );
|
||||
lateralFacet = vTool.GetFaceIndex( lateralNodes, oppLateralFacet );
|
||||
|
||||
// look for a facet of startHex having common nodes with facetNodes
|
||||
// but not lateralFacet
|
||||
for ( int iF = 0; iF < vTool.NbFaces(); ++iF )
|
||||
{
|
||||
if ( iF == lateralFacet )
|
||||
continue;
|
||||
int nbCommonNodes = 0;
|
||||
const SMDS_MeshNode** nn = vTool.GetFaceNodes( iF );
|
||||
for ( int iN = 0, nbN = vTool.NbFaceNodes( iF ); iN < nbN; ++iN )
|
||||
nbCommonNodes += facetNodes.count( nn[ iN ]);
|
||||
|
||||
if ( nbCommonNodes >= 2 )
|
||||
{
|
||||
facetID = iF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( facetID < 0 )
|
||||
throw SALOME_Exception( THIS_METHOD "facet of a new startHex not found");
|
||||
}
|
||||
} // while ( startHex )
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AddToSameGroups
|
||||
//purpose : add elemToAdd to the groups the elemInGroups belongs to
|
||||
|
@ -169,11 +169,32 @@ public:
|
||||
SMESH::Controls::NumericalFunctorPtr theCriterion);
|
||||
|
||||
|
||||
enum SplitVolumToTetraFlags { HEXA_TO_5 = 1, HEXA_TO_6 = 2, HEXA_TO_24 = 3 };//!<arg of SplitVolumesIntoTetra()
|
||||
typedef std::map < const SMDS_MeshElement*, int, TIDCompare > TFacetOfElem;
|
||||
|
||||
//!<2nd arg of SplitVolumes()
|
||||
enum SplitVolumToTetraFlags { HEXA_TO_5 = 1, // split into tetrahedra
|
||||
HEXA_TO_6,
|
||||
HEXA_TO_24,
|
||||
HEXA_TO_2_PRISMS, // split into prisms
|
||||
HEXA_TO_4_PRISMS };
|
||||
/*!
|
||||
* \brief Split volumic elements into tetrahedra.
|
||||
* \brief Split volumic elements into tetrahedra or prisms.
|
||||
* If facet ID < 0, element is split into tetrahedra,
|
||||
* else a hexahedron is split into prisms so that the given facet is
|
||||
* split into triangles
|
||||
*/
|
||||
void SplitVolumesIntoTetra (const TIDSortedElemSet & theElems, const int theMethodFlags);
|
||||
void SplitVolumes (const TFacetOfElem & theElems, const int theMethodFlags);
|
||||
|
||||
/*!
|
||||
* \brief For hexahedra that will be split into prisms, finds facets to
|
||||
* split into triangles
|
||||
* \param [in,out] theHexas - the hexahedra
|
||||
* \param [in] theFacetNormal - facet normal
|
||||
* \param [out] theFacets - the hexahedra and found facet IDs
|
||||
*/
|
||||
void GetHexaFacetsToSplit( TIDSortedElemSet& theHexas,
|
||||
const gp_Ax1& theFacetNormal,
|
||||
TFacetOfElem & theFacets);
|
||||
|
||||
|
||||
enum SmoothMethod { LAPLACIAN = 0, CENTROIDAL };
|
||||
|
@ -2668,7 +2668,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
|
||||
else if ( theCommandID == 410 )
|
||||
aDlg = new SMESHGUI_UnionOfTrianglesDlg(this);
|
||||
else if ( theCommandID == 419 )
|
||||
aDlg = new SMESHGUI_CuttingIntoTetraDlg(this);
|
||||
aDlg = new SMESHGUI_SplitVolumesDlg(this);
|
||||
else
|
||||
aDlg = new SMESHGUI_CuttingOfQuadsDlg(this);
|
||||
|
||||
|
@ -36,9 +36,12 @@
|
||||
#include "SMESHGUI_SpinBox.h"
|
||||
#include "SMESHGUI_MeshEditPreview.h"
|
||||
|
||||
#include <SMESH_Actor.h>
|
||||
#include <SMESH_TypeFilter.hxx>
|
||||
#include <SMDS_Mesh.hxx>
|
||||
#include "SMDS_Mesh.hxx"
|
||||
#include "SMDS_MeshNode.hxx"
|
||||
#include "SMDS_VolumeTool.hxx"
|
||||
#include "SMESH_Actor.h"
|
||||
#include "SMESH_MeshAlgos.hxx"
|
||||
#include "SMESH_TypeFilter.hxx"
|
||||
|
||||
// SALOME GUI includes
|
||||
#include <SUIT_Desktop.h>
|
||||
@ -58,9 +61,11 @@
|
||||
#include <VTKViewer_CellLocationsArray.h>
|
||||
|
||||
// OCCT includes
|
||||
#include <TColStd_IndexedMapOfInteger.hxx>
|
||||
#include <Bnd_B3d.hxx>
|
||||
#include <TColStd_DataMapOfIntegerInteger.hxx>
|
||||
#include <TColStd_IndexedMapOfInteger.hxx>
|
||||
#include <TColStd_MapIteratorOfMapOfInteger.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
|
||||
// VTK includes
|
||||
#include <vtkIdList.h>
|
||||
@ -103,9 +108,10 @@
|
||||
// Purpose : Constructor
|
||||
//=======================================================================
|
||||
SMESHGUI_MultiEditDlg
|
||||
::SMESHGUI_MultiEditDlg(SMESHGUI* theModule,
|
||||
const int theMode,
|
||||
const bool the3d2d):
|
||||
::SMESHGUI_MultiEditDlg(SMESHGUI* theModule,
|
||||
const int theMode,
|
||||
const bool the3d2d,
|
||||
bool theDoInit):
|
||||
SMESHGUI_PreviewDlg(theModule),
|
||||
mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
|
||||
mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
|
||||
@ -128,7 +134,8 @@ SMESHGUI_MultiEditDlg
|
||||
aDlgLay->addWidget(aMainFrame);
|
||||
aDlgLay->addWidget(aBtnFrame);
|
||||
|
||||
Init();
|
||||
if ( theDoInit )
|
||||
Init();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -162,6 +169,7 @@ QWidget* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool
|
||||
QRadioButton* aFaceRb = new QRadioButton(tr("SMESH_FACE"), aEntityTypeGrp);
|
||||
QRadioButton* aVolumeRb = new QRadioButton(tr("SMESH_VOLUME"), aEntityTypeGrp);
|
||||
|
||||
|
||||
aEntityLayout->addWidget(aFaceRb);
|
||||
aEntityLayout->addWidget(aVolumeRb);
|
||||
|
||||
@ -226,9 +234,6 @@ QWidget* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool
|
||||
myComboBoxFunctor->addItem(tr("ASPECTRATIO_ELEMENTS"));
|
||||
myComboBoxFunctor->addItem(tr("MINIMUMANGLE_ELEMENTS"));
|
||||
myComboBoxFunctor->addItem(tr("SKEW_ELEMENTS"));
|
||||
//myComboBoxFunctor->addItem(tr("AREA_ELEMENTS"));
|
||||
//myComboBoxFunctor->addItem(tr("LENGTH2D_EDGES")); // for existing elements only
|
||||
//myComboBoxFunctor->addItem(tr("MULTI2D_BORDERS")); // for existing elements only
|
||||
myComboBoxFunctor->setCurrentIndex(0);
|
||||
|
||||
aCriterionLayout->addWidget(myChoiceWidget);
|
||||
@ -305,7 +310,7 @@ QWidget* SMESHGUI_MultiEditDlg::createButtonFrame (QWidget* theParent)
|
||||
bool SMESHGUI_MultiEditDlg::isValid (const bool /*theMess*/)
|
||||
{
|
||||
return (!myMesh->_is_nil() &&
|
||||
(myListBox->count() > 0 || (myToAllChk->isChecked()/* && myActor*/)));
|
||||
(myListBox->count() > 0 || (myToAllChk->isChecked() && nbElemsInMesh() > 0)));
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -1071,6 +1076,11 @@ bool SMESHGUI_ChangeOrientationDlg::process (SMESH::SMESH_MeshEditor_ptr theEdit
|
||||
return theEditor->ReorientObject( obj );
|
||||
}
|
||||
|
||||
int SMESHGUI_ChangeOrientationDlg::nbElemsInMesh()
|
||||
{
|
||||
return ( myFilterType = SMESH::FaceFilter ) ? myMesh->NbFaces() : myMesh->NbVolumes();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Class : SMESHGUI_UnionOfTrianglesDlg
|
||||
* Description : Construction of quadrangles by automatic association of triangles
|
||||
@ -1163,39 +1173,44 @@ bool SMESHGUI_UnionOfTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theEdito
|
||||
ok = theEditor->TriToQuadObject(obj, aCriterion, aMaxAngle);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int SMESHGUI_UnionOfTrianglesDlg::nbElemsInMesh()
|
||||
{
|
||||
return myMesh->NbTriangles();
|
||||
}
|
||||
|
||||
void SMESHGUI_UnionOfTrianglesDlg::onDisplaySimulation( bool toDisplayPreview )
|
||||
{
|
||||
if ( myPreviewCheckBox->isChecked() && toDisplayPreview ) {
|
||||
if ( isValid( true ) ) {
|
||||
try{
|
||||
SUIT_OverrideCursor aWaitCursor;
|
||||
// get Ids of elements
|
||||
SMESH::SMESH_IDSource_var obj;
|
||||
SMESH::long_array_var anElemIds = getIds( obj );
|
||||
SUIT_OverrideCursor aWaitCursor;
|
||||
// get Ids of elements
|
||||
SMESH::SMESH_IDSource_var obj;
|
||||
SMESH::long_array_var anElemIds = getIds( obj );
|
||||
|
||||
SMESH::NumericalFunctor_var aCriterion = getNumericalFunctor();
|
||||
SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditPreviewer();
|
||||
SMESH::NumericalFunctor_var aCriterion = getNumericalFunctor();
|
||||
SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditPreviewer();
|
||||
|
||||
double aMaxAngle = myMaxAngleSpin->GetValue() * M_PI / 180.0;
|
||||
double aMaxAngle = myMaxAngleSpin->GetValue() * M_PI / 180.0;
|
||||
|
||||
if ( CORBA::is_nil( obj ) )
|
||||
aMeshEditor->TriToQuad( anElemIds.inout(), aCriterion, aMaxAngle );
|
||||
else
|
||||
aMeshEditor->TriToQuadObject( obj, aCriterion, aMaxAngle );
|
||||
if ( CORBA::is_nil( obj ) )
|
||||
aMeshEditor->TriToQuad( anElemIds.inout(), aCriterion, aMaxAngle );
|
||||
else
|
||||
aMeshEditor->TriToQuadObject( obj, aCriterion, aMaxAngle );
|
||||
|
||||
SMESH::MeshPreviewStruct_var aMeshPreviewStruct = aMeshEditor->GetPreviewData();
|
||||
SMESH::MeshPreviewStruct_var aMeshPreviewStruct = aMeshEditor->GetPreviewData();
|
||||
|
||||
vtkProperty* aProp = vtkProperty::New();
|
||||
aProp->SetRepresentationToWireframe();
|
||||
aProp->SetColor( 250, 0, 250 );
|
||||
aProp->SetLineWidth( SMESH::GetFloat( "SMESH:element_width", 1 ) + 3 );
|
||||
mySimulation->GetActor()->SetProperty( aProp );
|
||||
aProp->Delete();
|
||||
vtkProperty* aProp = vtkProperty::New();
|
||||
aProp->SetRepresentationToWireframe();
|
||||
aProp->SetColor( 250, 0, 250 );
|
||||
aProp->SetLineWidth( SMESH::GetFloat( "SMESH:element_width", 1 ) + 3 );
|
||||
mySimulation->GetActor()->SetProperty( aProp );
|
||||
aProp->Delete();
|
||||
|
||||
mySimulation->SetData( aMeshPreviewStruct._retn() );
|
||||
mySimulation->SetData( aMeshPreviewStruct._retn() );
|
||||
} catch ( ... ) {
|
||||
hidePreview();
|
||||
hidePreview();
|
||||
}
|
||||
} else {
|
||||
hidePreview();
|
||||
@ -1279,6 +1294,12 @@ bool SMESHGUI_CuttingOfQuadsDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
|
||||
return hasObj ? theEditor->QuadToTriObject(obj, aCrit) : theEditor->QuadToTri(theIds, aCrit);
|
||||
}
|
||||
|
||||
int SMESHGUI_CuttingOfQuadsDlg::nbElemsInMesh()
|
||||
{
|
||||
return myMesh->NbQuadrangles();
|
||||
}
|
||||
|
||||
|
||||
void SMESHGUI_CuttingOfQuadsDlg::onCriterionRB()
|
||||
{
|
||||
if (myGroupChoice->checkedId() == 2) // Use numeric functor
|
||||
@ -1488,51 +1509,147 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
|
||||
}
|
||||
|
||||
/*!
|
||||
* Class : SMESHGUI_CuttingIntoTetraDlg
|
||||
* Description : Modification of orientation of faces
|
||||
* Class : SMESHGUI_SplitVolumesDlg
|
||||
* Description : Spliter of volumes into tetrahedra or prisms
|
||||
*/
|
||||
|
||||
SMESHGUI_CuttingIntoTetraDlg::SMESHGUI_CuttingIntoTetraDlg(SMESHGUI* theModule)
|
||||
: SMESHGUI_MultiEditDlg(theModule, SMESH::VolumeFilter, false)
|
||||
SMESHGUI_SplitVolumesDlg::SMESHGUI_SplitVolumesDlg(SMESHGUI* theModule)
|
||||
: SMESHGUI_MultiEditDlg(theModule, SMESH::VolumeFilter, /*the3d2d=*/true, /*doInit=*/false)
|
||||
{
|
||||
setWindowTitle(tr("CAPTION"));
|
||||
myHelpFileName = "split_to_tetra_page.html";
|
||||
myEntityType = 1;
|
||||
myCellSize = -1.;
|
||||
|
||||
// Facet selection group
|
||||
|
||||
myFacetSelGrp = new QGroupBox(tr("FACET_TO_SPLIT"), myCriterionGrp->parentWidget());
|
||||
QGridLayout* facetSelLayout = new QGridLayout( myFacetSelGrp );
|
||||
facetSelLayout->setMargin(MARGIN);
|
||||
facetSelLayout->setSpacing(SPACING);
|
||||
|
||||
QLabel* pointLbl = new QLabel( tr("START_POINT"), myFacetSelGrp);
|
||||
QLabel* normalLbl = new QLabel( tr("FACET_NORMAL"), myFacetSelGrp);
|
||||
myFacetSelBtn = new QPushButton( mySubmeshBtn->icon(), "", myFacetSelGrp );
|
||||
myFacetSelBtn->setCheckable( true );
|
||||
QLabel* XLbl = new QLabel( tr("SMESH_X"), myFacetSelGrp);
|
||||
QLabel* YLbl = new QLabel( tr("SMESH_Y"), myFacetSelGrp);
|
||||
QLabel* ZLbl = new QLabel( tr("SMESH_Z"), myFacetSelGrp);
|
||||
QLabel* dXLbl = new QLabel( tr("SMESH_DX"), myFacetSelGrp);
|
||||
QLabel* dYLbl = new QLabel( tr("SMESH_DY"), myFacetSelGrp);
|
||||
QLabel* dZLbl = new QLabel( tr("SMESH_DZ"), myFacetSelGrp);
|
||||
QPushButton* axisBtn[3];
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
myPointSpin[i] = new SMESHGUI_SpinBox( myFacetSelGrp );
|
||||
myDirSpin [i] = new SMESHGUI_SpinBox( myFacetSelGrp );
|
||||
myPointSpin[i]->RangeStepAndValidator( -1e10, 1e10, 10 );
|
||||
myDirSpin [i]->RangeStepAndValidator( -1., 1., 0.1 );
|
||||
myPointSpin[i]->SetValue(0.);
|
||||
myDirSpin [i]->SetValue(0.);
|
||||
myAxisBtn [i] = new QPushButton( QString("|| O") + char('X'+i ), myFacetSelGrp);
|
||||
}
|
||||
myDirSpin[2]->SetValue(1.);
|
||||
|
||||
myAllDomainsChk = new QCheckBox( tr("ALL_DOMAINS"), mySelGrp );
|
||||
|
||||
facetSelLayout->addWidget( pointLbl, 0, 0 );
|
||||
facetSelLayout->addWidget( myFacetSelBtn, 0, 1 );
|
||||
facetSelLayout->addWidget( XLbl, 0, 2 );
|
||||
facetSelLayout->addWidget( myPointSpin[0],0, 3 );
|
||||
facetSelLayout->addWidget( YLbl, 0, 4 );
|
||||
facetSelLayout->addWidget( myPointSpin[1],0, 5 );
|
||||
facetSelLayout->addWidget( ZLbl, 0, 6 );
|
||||
facetSelLayout->addWidget( myPointSpin[2],0, 7 );
|
||||
|
||||
facetSelLayout->addWidget( normalLbl, 1, 0 );
|
||||
facetSelLayout->addWidget( dXLbl, 1, 2 );
|
||||
facetSelLayout->addWidget( myDirSpin[0], 1, 3 );
|
||||
facetSelLayout->addWidget( dYLbl, 1, 4 );
|
||||
facetSelLayout->addWidget( myDirSpin[1], 1, 5 );
|
||||
facetSelLayout->addWidget( dZLbl, 1, 6 );
|
||||
facetSelLayout->addWidget( myDirSpin[2], 1, 7 );
|
||||
|
||||
facetSelLayout->addWidget( myAxisBtn[0], 2, 2, 1, 2 );
|
||||
facetSelLayout->addWidget( myAxisBtn[1], 2, 4, 1, 2 );
|
||||
facetSelLayout->addWidget( myAxisBtn[2], 2, 6, 1, 2 );
|
||||
|
||||
myCriterionGrp->layout()->addWidget( myFacetSelGrp );
|
||||
myCriterionGrp->layout()->addWidget( myAllDomainsChk );
|
||||
//myChoiceWidget->layout()->addWidget( myAllDomainsChk );
|
||||
|
||||
connect( myFacetSelBtn, SIGNAL(clicked(bool)), SLOT(onFacetSelection(bool)) );
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
connect( myAxisBtn [i], SIGNAL(clicked()), SLOT(onSetDir()) );
|
||||
connect( myPointSpin[i], SIGNAL(valueChanged (const QString&)),
|
||||
this, SLOT (updateNormalPreview(const QString&)) );
|
||||
connect( myDirSpin [i], SIGNAL(valueChanged (const QString&)),
|
||||
this, SLOT (updateNormalPreview(const QString&)) );
|
||||
}
|
||||
if ( myEntityTypeGrp )
|
||||
{
|
||||
myEntityTypeGrp->button(0)->setText( tr("SMESH_TETRAS"));
|
||||
myEntityTypeGrp->button(1)->setText( tr("SMESH_PRISM"));
|
||||
if ( QGroupBox* gb = qobject_cast< QGroupBox* >( myEntityTypeGrp->button(0)->parent() ))
|
||||
gb->setTitle( tr("TARGET_ELEM_TYPE"));
|
||||
}
|
||||
|
||||
myToAllChk->setChecked( true ); //aplly to the whole mesh by default
|
||||
|
||||
bool hasHexa = true;//myMesh->_is_nil() ? false : myMesh->NbHexas();
|
||||
|
||||
if ( hasHexa )
|
||||
{
|
||||
myGroupChoice->button(0)->setText( tr("SPLIT_HEX_TO_5_TETRA"));
|
||||
myGroupChoice->button(1)->setText( tr("SPLIT_HEX_TO_6_TETRA"));
|
||||
myGroupChoice->button(2)->setText( tr("SPLIT_HEX_TO_24_TETRA"));
|
||||
|
||||
myCriterionGrp->setTitle( tr("SPLIT_METHOD"));
|
||||
myCriterionGrp->show();
|
||||
myComboBoxFunctor->hide();
|
||||
myChoiceWidget->show();
|
||||
}
|
||||
setSelectionMode();
|
||||
updateButtons();
|
||||
|
||||
on3d2dChanged( 0 );
|
||||
Init();
|
||||
}
|
||||
|
||||
SMESHGUI_CuttingIntoTetraDlg::~SMESHGUI_CuttingIntoTetraDlg()
|
||||
SMESHGUI_SplitVolumesDlg::~SMESHGUI_SplitVolumesDlg()
|
||||
{
|
||||
}
|
||||
|
||||
bool SMESHGUI_CuttingIntoTetraDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
|
||||
const SMESH::long_array& theIds,
|
||||
SMESH::SMESH_IDSource_ptr theObj)
|
||||
bool SMESHGUI_SplitVolumesDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
|
||||
const SMESH::long_array& theIds,
|
||||
SMESH::SMESH_IDSource_ptr theObj)
|
||||
{
|
||||
SMESH::SMESH_IDSource_wrap obj = theObj;
|
||||
if ( CORBA::is_nil( obj ))
|
||||
obj = theEditor->MakeIDSource( theIds, myEntityType ? SMESH::VOLUME : SMESH::FACE );
|
||||
obj = theEditor->MakeIDSource( theIds, SMESH::VOLUME );
|
||||
else
|
||||
obj->Register();
|
||||
try {
|
||||
theEditor->SplitVolumesIntoTetra( obj, myGroupChoice->checkedId()+1 );
|
||||
if ( isIntoPrisms() )
|
||||
{
|
||||
QStringList aParameters;
|
||||
aParameters << myPointSpin[0]->text();
|
||||
aParameters << myPointSpin[1]->text();
|
||||
aParameters << myPointSpin[2]->text();
|
||||
aParameters << myDirSpin[0]->text();
|
||||
aParameters << myDirSpin[1]->text();
|
||||
aParameters << myDirSpin[2]->text();
|
||||
myMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
|
||||
|
||||
SMESH::AxisStruct_var axis = new SMESH::AxisStruct;
|
||||
axis->x = myPointSpin[0]->GetValue();
|
||||
axis->y = myPointSpin[1]->GetValue();
|
||||
axis->z = myPointSpin[2]->GetValue();
|
||||
axis->vx = myDirSpin[0]->GetValue();
|
||||
axis->vy = myDirSpin[1]->GetValue();
|
||||
axis->vz = myDirSpin[2]->GetValue();
|
||||
|
||||
theEditor->SplitHexahedraIntoPrisms( obj, myGroupChoice->checkedId()+1,
|
||||
axis, myAllDomainsChk->isChecked() );
|
||||
}
|
||||
else
|
||||
{
|
||||
theEditor->SplitVolumesIntoTetra( obj, myGroupChoice->checkedId()+1 );
|
||||
}
|
||||
}
|
||||
catch ( const SALOME::SALOME_Exception& S_ex ) {
|
||||
SalomeApp_Tools::QtCatchCorbaException( S_ex );
|
||||
@ -1543,3 +1660,308 @@ bool SMESHGUI_CuttingIntoTetraDlg::process (SMESH::SMESH_MeshEditor_ptr theEdito
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int SMESHGUI_SplitVolumesDlg::nbElemsInMesh()
|
||||
{
|
||||
return isIntoPrisms() ? myMesh->NbHexas() : myMesh->NbVolumes() - myMesh->NbTetras();
|
||||
}
|
||||
|
||||
bool SMESHGUI_SplitVolumesDlg::isIntoPrisms()
|
||||
{
|
||||
return ( myEntityTypeGrp->checkedId() == 1 );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Slot called when a target element type changes
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESHGUI_SplitVolumesDlg::on3d2dChanged(int isPrism)
|
||||
{
|
||||
if ( isPrism )
|
||||
{
|
||||
myFacetSelGrp->show();
|
||||
myAllDomainsChk->show();
|
||||
myGroupChoice->button(2)->hide();
|
||||
myGroupChoice->button(0)->setText( tr("SPLIT_HEX_TO_2_PRISMS"));
|
||||
myGroupChoice->button(1)->setText( tr("SPLIT_HEX_TO_4_PRISMS"));
|
||||
}
|
||||
else
|
||||
{
|
||||
myFacetSelGrp->hide();
|
||||
myAllDomainsChk->hide();
|
||||
myGroupChoice->button(2)->show();
|
||||
myGroupChoice->button(0)->setText( tr("SPLIT_HEX_TO_5_TETRA"));
|
||||
myGroupChoice->button(1)->setText( tr("SPLIT_HEX_TO_6_TETRA"));
|
||||
myGroupChoice->button(2)->setText( tr("SPLIT_HEX_TO_24_TETRA"));
|
||||
}
|
||||
SMESHGUI_MultiEditDlg::on3d2dChanged( !myEntityType );
|
||||
myEntityType = 1; // == VOLUME
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Set selection mode
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESHGUI_SplitVolumesDlg::setSelectionMode()
|
||||
{
|
||||
if ( myBusy || !isEnabled() ) return;
|
||||
|
||||
SMESH::RemoveFilters();
|
||||
|
||||
mySelectionMgr->clearFilters();
|
||||
|
||||
if (mySubmeshChk->isChecked()) {
|
||||
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
|
||||
aViewWindow->SetSelectionMode(ActorSelection);
|
||||
mySelectionMgr->installFilter(new SMESH_TypeFilter(SMESH::SUBMESH));
|
||||
myFacetSelBtn->setChecked( false );
|
||||
}
|
||||
else if (myGroupChk->isChecked()) {
|
||||
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
|
||||
aViewWindow->SetSelectionMode(ActorSelection);
|
||||
mySelectionMgr->installFilter(new SMESH_TypeFilter(SMESH::GROUP));
|
||||
myFacetSelBtn->setChecked( false );
|
||||
}
|
||||
|
||||
if ( myFacetSelBtn->isChecked() )
|
||||
{
|
||||
// facet selection - select any element
|
||||
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
|
||||
aViewWindow->SetSelectionMode( CellSelection );
|
||||
myFilterType = SMESH::AllElementsFilter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
|
||||
aViewWindow->SetSelectionMode( VolumeSelection );
|
||||
if ( isIntoPrisms() )
|
||||
{
|
||||
SMESH::SetFilter(new SMESHGUI_VolumeShapeFilter( SMDSGeom_HEXA ));
|
||||
myFilterType = SMESHGUI_VolumeShapeFilter::GetId( SMDSGeom_HEXA );
|
||||
}
|
||||
else // to tetrahedra
|
||||
{
|
||||
SMESH::SetFilter(new SMESHGUI_VolumesFilter());
|
||||
myFilterType = SMESH::VolumeFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief SLOT called when selection changed
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESHGUI_SplitVolumesDlg::onSelectionDone()
|
||||
{
|
||||
if (myBusy || !isEnabled()) return;
|
||||
|
||||
if ( !myFacetSelBtn->isChecked() )
|
||||
{
|
||||
SMESHGUI_MultiEditDlg::onSelectionDone();
|
||||
}
|
||||
else // set point and normal by a selected element
|
||||
{
|
||||
const SALOME_ListIO& aList = mySelector->StoredIObjects();
|
||||
int nbSel = aList.Extent();
|
||||
if (nbSel > 0)
|
||||
{
|
||||
Handle(SALOME_InteractiveObject) anIO = aList.First();
|
||||
|
||||
myActor = SMESH::FindActorByEntry( anIO->getEntry() );
|
||||
|
||||
SMESH::SMESH_Mesh_var aSelMesh = SMESH::GetMeshByIO(anIO);
|
||||
if (!aSelMesh->_is_nil())
|
||||
myMesh = aSelMesh;
|
||||
|
||||
TColStd_IndexedMapOfInteger aMapIndex;
|
||||
mySelector->GetIndex( anIO, aMapIndex );
|
||||
if ( !aMapIndex.IsEmpty() )
|
||||
showFacetByElement( aMapIndex(1) );
|
||||
else if ( myCellSize < 0 )
|
||||
showFacetByElement( 1 );
|
||||
}
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Show facet normal by a selected element
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESHGUI_SplitVolumesDlg::showFacetByElement( int elemID )
|
||||
{
|
||||
if ( !isIntoPrisms() || !myActor )
|
||||
{
|
||||
mySimulation->SetVisibility( false );
|
||||
return;
|
||||
}
|
||||
SMDS_Mesh* mesh = myActor->GetObject()->GetMesh();
|
||||
const SMDS_MeshElement* elem = mesh->FindElement( elemID );
|
||||
if ( !elem ) return;
|
||||
|
||||
// set point XYZ by the element barycenter
|
||||
gp_XYZ bc( 0,0,0 );
|
||||
Bnd_B3d bbox;
|
||||
SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
|
||||
vector< const SMDS_MeshNode* > nodes;
|
||||
nodes.reserve( elem->NbNodes() );
|
||||
while ( nIt->more() )
|
||||
{
|
||||
nodes.push_back( nIt->next() );
|
||||
gp_XYZ p = SMESH_TNodeXYZ( nodes.back() );
|
||||
bc += p;
|
||||
bbox.Add( p );
|
||||
}
|
||||
bc /= nodes.size();
|
||||
|
||||
myPointSpin[0]->SetValue( bc.X() );
|
||||
myPointSpin[1]->SetValue( bc.Y() );
|
||||
myPointSpin[2]->SetValue( bc.Z() );
|
||||
|
||||
// set size
|
||||
myCellSize = sqrt( bbox.SquareExtent() );
|
||||
|
||||
// set normal and size
|
||||
gp_XYZ norm;
|
||||
switch ( elem->GetType())
|
||||
{
|
||||
case SMDSAbs_Edge:
|
||||
{
|
||||
norm = SMESH_TNodeXYZ( nodes[1] ) - SMESH_TNodeXYZ( nodes[0] );
|
||||
break;
|
||||
}
|
||||
case SMDSAbs_Face:
|
||||
{
|
||||
if ( !SMESH_MeshAlgos::FaceNormal( elem, norm, /*normalized=*/false ))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
case SMDSAbs_Volume:
|
||||
{
|
||||
SMDS_VolumeTool vTool( elem );
|
||||
vTool.SetExternalNormal();
|
||||
bool freeFacetFound = false;
|
||||
double n[3];
|
||||
for ( int i = 0; i < vTool.NbFaces() && !freeFacetFound; ++i )
|
||||
if (( freeFacetFound = vTool.IsFreeFace( i )))
|
||||
vTool.GetFaceNormal( i, n[0], n[1], n[2] );
|
||||
if ( !freeFacetFound )
|
||||
vTool.GetFaceNormal( 0, n[0], n[1], n[2] );
|
||||
norm.SetCoord( n[0], n[1], n[2] );
|
||||
break;
|
||||
}
|
||||
default: return;
|
||||
}
|
||||
|
||||
double size = norm.Modulus();
|
||||
if ( size < 1e-20 )
|
||||
return;
|
||||
norm /= size;
|
||||
|
||||
myDirSpin[0]->SetValue( norm.X() );
|
||||
myDirSpin[1]->SetValue( norm.Y() );
|
||||
myDirSpin[2]->SetValue( norm.Z() );
|
||||
|
||||
if ( myCellSize > 0. )
|
||||
updateNormalPreview();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief SLOT called when a point or a normal changes
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESHGUI_SplitVolumesDlg::updateNormalPreview(const QString&)
|
||||
{
|
||||
if ( myCellSize < 0. )
|
||||
{
|
||||
showFacetByElement( 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
gp_Pnt point ( myPointSpin[0]->GetValue(),
|
||||
myPointSpin[1]->GetValue(),
|
||||
myPointSpin[2]->GetValue() );
|
||||
gp_XYZ norm ( myDirSpin[0]->GetValue(),
|
||||
myDirSpin[1]->GetValue(),
|
||||
myDirSpin[2]->GetValue() );
|
||||
if ( norm.Modulus() < 1e-20 )
|
||||
return;
|
||||
|
||||
vtkUnstructuredGrid* grid = mySimulation->GetGrid();
|
||||
|
||||
// Initialize the preview mesh of an arrow
|
||||
if ( grid->GetNumberOfPoints() == 0 )
|
||||
{
|
||||
mySimulation->SetArrowShapeAndNb( /*nb=*/1, /*hLen=*/0.3, /*R=*/0.1, /*start=*/0 );
|
||||
}
|
||||
|
||||
// Compute new coordinates of the grid according to the dialog controls
|
||||
|
||||
gp_Ax1 axis( point, norm );
|
||||
mySimulation->SetArrows( &axis, 4 * myCellSize );
|
||||
mySimulation->SetVisibility(true);
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Slot called when facet selection button is clicked
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESHGUI_SplitVolumesDlg::onFacetSelection(bool isFacetSelection)
|
||||
{
|
||||
setSelectionMode();
|
||||
onSelectionDone();
|
||||
mySelGrp->setEnabled( !isFacetSelection );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Slot called when an || axis button is clicked
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESHGUI_SplitVolumesDlg::onSetDir()
|
||||
{
|
||||
myDirSpin[0]->SetValue(0.);
|
||||
myDirSpin[1]->SetValue(0.);
|
||||
myDirSpin[2]->SetValue(0.);
|
||||
int i = 0;
|
||||
for ( ; i < 3; ++i )
|
||||
if ( sender() == myAxisBtn[i] )
|
||||
break;
|
||||
if ( i == 3 )
|
||||
i == 0;
|
||||
myDirSpin[i]->SetValue(1.);
|
||||
|
||||
if ( myActor && !myMesh->_is_nil() && myMesh->NbNodes() > 0 )
|
||||
{
|
||||
double b[6];
|
||||
myActor->GetUnstructuredGrid()->GetBounds(b);
|
||||
gp_XYZ center( 0.5 * ( b[0] + b[1] ),
|
||||
0.5 * ( b[2] + b[3] ),
|
||||
0.5 * ( b[4] + b[5] ));
|
||||
gp_XYZ point ( myPointSpin[0]->GetValue(),
|
||||
myPointSpin[1]->GetValue(),
|
||||
myPointSpin[2]->GetValue() );
|
||||
gp_XYZ norm ( myDirSpin[0]->GetValue(),
|
||||
myDirSpin[1]->GetValue(),
|
||||
myDirSpin[2]->GetValue() );
|
||||
|
||||
gp_Vec cp( center, point );
|
||||
if ( cp.Dot( norm ) < 0. )
|
||||
myDirSpin[i]->SetValue(-1.);
|
||||
}
|
||||
|
||||
updateNormalPreview();
|
||||
}
|
||||
|
@ -70,7 +70,10 @@ class SMESHGUI_EXPORT SMESHGUI_MultiEditDlg : public SMESHGUI_PreviewDlg
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SMESHGUI_MultiEditDlg( SMESHGUI*, const int, const bool = false );
|
||||
SMESHGUI_MultiEditDlg( SMESHGUI* theModule,
|
||||
const int theMode,
|
||||
const bool the3d2d = false,
|
||||
bool theDoInit = true );
|
||||
virtual ~SMESHGUI_MultiEditDlg();
|
||||
|
||||
void Init();
|
||||
@ -87,7 +90,7 @@ protected slots:
|
||||
void onHelp();
|
||||
|
||||
void onDeactivate();
|
||||
void onSelectionDone();
|
||||
virtual void onSelectionDone();
|
||||
|
||||
void onFilterBtn();
|
||||
void onAddBtn();
|
||||
@ -98,7 +101,7 @@ protected slots:
|
||||
void onGroupChk();
|
||||
virtual void onToAllChk();
|
||||
void onFilterAccepted();
|
||||
void on3d2dChanged(int);
|
||||
virtual void on3d2dChanged(int);
|
||||
|
||||
SMESH::NumericalFunctor_ptr getNumericalFunctor();
|
||||
|
||||
@ -110,11 +113,12 @@ protected:
|
||||
virtual bool isValid( const bool );
|
||||
SMESH::long_array_var getIds(SMESH::SMESH_IDSource_var& obj);
|
||||
void updateButtons();
|
||||
void setSelectionMode();
|
||||
virtual void setSelectionMode();
|
||||
virtual bool isIdValid( const int ) const;
|
||||
virtual bool process( SMESH::SMESH_MeshEditor_ptr,
|
||||
const SMESH::long_array& ,
|
||||
SMESH::SMESH_IDSource_ptr obj) = 0;
|
||||
virtual int nbElemsInMesh() = 0;
|
||||
int entityType();
|
||||
|
||||
protected:
|
||||
@ -178,6 +182,7 @@ protected:
|
||||
virtual bool process( SMESH::SMESH_MeshEditor_ptr,
|
||||
const SMESH::long_array& ,
|
||||
SMESH::SMESH_IDSource_ptr obj);
|
||||
virtual int nbElemsInMesh();
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -197,6 +202,7 @@ protected:
|
||||
virtual bool process( SMESH::SMESH_MeshEditor_ptr,
|
||||
const SMESH::long_array&,
|
||||
SMESH::SMESH_IDSource_ptr obj );
|
||||
virtual int nbElemsInMesh();
|
||||
|
||||
protected slots:
|
||||
virtual void onDisplaySimulation( bool );
|
||||
@ -221,6 +227,7 @@ protected:
|
||||
virtual bool process( SMESH::SMESH_MeshEditor_ptr,
|
||||
const SMESH::long_array& ,
|
||||
SMESH::SMESH_IDSource_ptr obj);
|
||||
virtual int nbElemsInMesh();
|
||||
|
||||
protected slots:
|
||||
virtual void reject();
|
||||
@ -237,21 +244,45 @@ private:
|
||||
};
|
||||
|
||||
/*!
|
||||
* Class : SMESHGUI_CuttingIntoTetraDlg
|
||||
* Class : SMESHGUI_SplitVolumesDlg
|
||||
* Description : Split all volumes into tetrahedrons
|
||||
*/
|
||||
class SMESHGUI_CuttingIntoTetraDlg : public SMESHGUI_MultiEditDlg
|
||||
class SMESHGUI_SplitVolumesDlg : public SMESHGUI_MultiEditDlg
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SMESHGUI_CuttingIntoTetraDlg( SMESHGUI* );
|
||||
virtual ~SMESHGUI_CuttingIntoTetraDlg();
|
||||
SMESHGUI_SplitVolumesDlg( SMESHGUI* );
|
||||
virtual ~SMESHGUI_SplitVolumesDlg();
|
||||
|
||||
protected slots:
|
||||
|
||||
virtual void on3d2dChanged(int);
|
||||
virtual void onSelectionDone();
|
||||
|
||||
void onFacetSelection(bool);
|
||||
void onSetDir();
|
||||
void updateNormalPreview(const QString& s="");
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool process( SMESH::SMESH_MeshEditor_ptr,
|
||||
const SMESH::long_array&,
|
||||
SMESH::SMESH_IDSource_ptr obj );
|
||||
virtual int nbElemsInMesh();
|
||||
|
||||
virtual void setSelectionMode();
|
||||
void showFacetByElement( int id );
|
||||
bool isIntoPrisms();
|
||||
|
||||
QGroupBox* myFacetSelGrp;
|
||||
SMESHGUI_SpinBox* myPointSpin[3];
|
||||
SMESHGUI_SpinBox* myDirSpin [3];
|
||||
QPushButton* myFacetSelBtn;
|
||||
QPushButton* myAxisBtn[3];
|
||||
QCheckBox* myAllDomainsChk;
|
||||
|
||||
double myCellSize;
|
||||
};
|
||||
|
||||
#endif // SMESHGUI_MULTIEDITDLG_H
|
||||
|
@ -1066,15 +1066,15 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>MEN_SPLIT_TO_TETRA</source>
|
||||
<translation>Split into Tetrahedra</translation>
|
||||
<translation>Split Volumes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>TOP_SPLIT_TO_TETRA</source>
|
||||
<translation>Split into Tetrahedra</translation>
|
||||
<translation>Split Volumes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>STB_SPLIT_TO_TETRA</source>
|
||||
<translation>Split into Tetrahedra</translation>
|
||||
<translation>Split Volumes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>MESHERS_FILE_CANT_OPEN</source>
|
||||
@ -6278,10 +6278,10 @@ It is impossible to read point coordinates from file</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SMESHGUI_CuttingIntoTetraDlg</name>
|
||||
<name>SMESHGUI_SplitVolumesDlg</name>
|
||||
<message>
|
||||
<source>CAPTION</source>
|
||||
<translation>Splitting volumes into tetrahedra</translation>
|
||||
<translation>Splitting volumes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SPLIT_METHOD</source>
|
||||
@ -6299,6 +6299,34 @@ It is impossible to read point coordinates from file</translation>
|
||||
<source>SPLIT_HEX_TO_24_TETRA</source>
|
||||
<translation>Into 24 tetrahedra</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SPLIT_HEX_TO_2_PRISMS</source>
|
||||
<translation>Into 2 prisms</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SPLIT_HEX_TO_4_PRISMS</source>
|
||||
<translation>Into 4 Prisms</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>TARGET_ELEM_TYPE</source>
|
||||
<translation>Target element type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FACET_TO_SPLIT</source>
|
||||
<translation>Facet to split</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>START_POINT</source>
|
||||
<translation>Hexa location</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FACET_NORMAL</source>
|
||||
<translation>Facet normal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ALL_DOMAINS</source>
|
||||
<translation>All domains</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SMESHGUI_PrecisionDlg</name>
|
||||
|
@ -1999,13 +1999,15 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
|
||||
{
|
||||
SMESH_TRY;
|
||||
initData();
|
||||
|
||||
prepareIdSource( elems );
|
||||
SMESH::long_array_var anElementsId = elems->GetIDs();
|
||||
TIDSortedElemSet elemSet;
|
||||
arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume );
|
||||
|
||||
getEditor().SplitVolumesIntoTetra( elemSet, int( methodFlags ));
|
||||
::SMESH_MeshEditor::TFacetOfElem elemSet;
|
||||
const int noneFacet = -1;
|
||||
SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
|
||||
while( volIt->more() )
|
||||
elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
|
||||
|
||||
getEditor().SplitVolumes( elemSet, int( methodFlags ));
|
||||
declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
|
||||
|
||||
TPythonDump() << this << ".SplitVolumesIntoTetra( "
|
||||
@ -2014,6 +2016,66 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
|
||||
SMESH_CATCH( SMESH::throwCorbaException );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Split hexahedra into triangular prisms
|
||||
* \param elems - elements to split
|
||||
* \param facetToSplitNormal - normal used to find a facet of hexahedron
|
||||
* to split into triangles
|
||||
* \param methodFlags - flags passing splitting method:
|
||||
* 1 - split the hexahedron into 2 prisms
|
||||
* 2 - split the hexahedron into 4 prisms
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr elems,
|
||||
CORBA::Short methodFlags,
|
||||
const SMESH::AxisStruct & facetToSplitNormal,
|
||||
CORBA::Boolean allDomains)
|
||||
throw (SALOME::SALOME_Exception)
|
||||
{
|
||||
SMESH_TRY;
|
||||
initData();
|
||||
prepareIdSource( elems );
|
||||
|
||||
gp_Ax1 facetNorm( gp_Pnt( facetToSplitNormal.x,
|
||||
facetToSplitNormal.y,
|
||||
facetToSplitNormal.z ),
|
||||
gp_Dir( facetToSplitNormal.vx,
|
||||
facetToSplitNormal.vy,
|
||||
facetToSplitNormal.vz ));
|
||||
TIDSortedElemSet elemSet;
|
||||
SMESH::long_array_var anElementsId = elems->GetIDs();
|
||||
SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
|
||||
arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
|
||||
|
||||
::SMESH_MeshEditor::TFacetOfElem elemFacets;
|
||||
while ( !elemSet.empty() )
|
||||
{
|
||||
getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
|
||||
if ( !allDomains )
|
||||
break;
|
||||
|
||||
::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
|
||||
for ( ; ef != elemFacets.end(); ++ef )
|
||||
elemSet.erase( ef->first );
|
||||
}
|
||||
|
||||
if ( methodFlags == 2 )
|
||||
methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
|
||||
else
|
||||
methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
|
||||
|
||||
getEditor().SplitVolumes( elemFacets, int( methodFlags ));
|
||||
declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
|
||||
|
||||
TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
|
||||
<< elems << ", " << methodFlags<< ", "
|
||||
<< facetToSplitNormal<< ", " << allDomains << " )";
|
||||
|
||||
SMESH_CATCH( SMESH::throwCorbaException );
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Smooth
|
||||
//purpose :
|
||||
|
@ -233,6 +233,11 @@ public:
|
||||
void SplitVolumesIntoTetra(SMESH::SMESH_IDSource_ptr elems,
|
||||
CORBA::Short methodFlags)
|
||||
throw (SALOME::SALOME_Exception);
|
||||
void SplitHexahedraIntoPrisms(SMESH::SMESH_IDSource_ptr elems,
|
||||
CORBA::Short methodFlags,
|
||||
const SMESH::AxisStruct & facetToSplitNormal,
|
||||
CORBA::Boolean allDomains)
|
||||
throw (SALOME::SALOME_Exception);
|
||||
|
||||
CORBA::Boolean Smooth(const SMESH::long_array & IDsOfElements,
|
||||
const SMESH::long_array & IDsOfFixedNodes,
|
||||
|
@ -73,7 +73,7 @@
|
||||
## @defgroup l2_modif_invdiag Diagonal inversion of elements
|
||||
## @defgroup l2_modif_unitetri Uniting triangles
|
||||
## @defgroup l2_modif_changori Changing orientation of elements
|
||||
## @defgroup l2_modif_cutquadr Cutting quadrangles
|
||||
## @defgroup l2_modif_cutquadr Cutting elements
|
||||
## @defgroup l2_modif_smooth Smoothing
|
||||
## @defgroup l2_modif_extrurev Extrusion and Revolution
|
||||
## @defgroup l2_modif_patterns Pattern mapping
|
||||
@ -307,7 +307,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
|
||||
[TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = range(4)
|
||||
|
||||
# Methods of splitting a hexahedron into tetrahedra
|
||||
Hex_5Tet, Hex_6Tet, Hex_24Tet = 1, 2, 3
|
||||
Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
|
||||
|
||||
def __new__(cls):
|
||||
global engine
|
||||
@ -851,11 +851,15 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
|
||||
|
||||
## Creates a filter from criteria
|
||||
# @param criteria a list of criteria
|
||||
# @param binOp binary operator used when binary operator of criteria is undefined
|
||||
# @return SMESH_Filter
|
||||
#
|
||||
# <a href="../tui_filters_page.html#tui_filters">Example of Filters usage</a>
|
||||
# @ingroup l1_controls
|
||||
def GetFilterFromCriteria(self,criteria):
|
||||
def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
|
||||
for i in range( len( criteria ) - 1 ):
|
||||
if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
|
||||
criteria[i].BinaryOp = self.EnumToLong( binOp )
|
||||
aFilterMgr = self.CreateFilterManager()
|
||||
aFilter = aFilterMgr.CreateFilter()
|
||||
aFilter.SetCriteria(criteria)
|
||||
@ -2284,6 +2288,12 @@ class Mesh:
|
||||
def GetElementGeomType(self, id):
|
||||
return self.mesh.GetElementGeomType(id)
|
||||
|
||||
## Returns the shape type of mesh element
|
||||
# @return the value from SMESH::GeometryType enumeration
|
||||
# @ingroup l1_meshinfo
|
||||
def GetElementShape(self, id):
|
||||
return self.mesh.GetElementShape(id)
|
||||
|
||||
## Returns the list of submesh elements IDs
|
||||
# @param Shape a geom object(sub-shape) IOR
|
||||
# Shape must be the sub-shape of a ShapeToMesh()
|
||||
@ -3026,18 +3036,54 @@ class Mesh:
|
||||
return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
|
||||
|
||||
## Splits volumic elements into tetrahedrons
|
||||
# @param elemIDs either list of elements or mesh or group or submesh
|
||||
# @param method flags passing splitting method: Hex_5Tet, Hex_6Tet, Hex_24Tet
|
||||
# Hex_5Tet - split the hexahedron into 5 tetrahedrons, etc
|
||||
# @param elems either a list of elements or a mesh or a group or a submesh or a filter
|
||||
# @param method flags passing splitting method:
|
||||
# smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
|
||||
# smesh.Hex_5Tet - to split the hexahedron into 5 tetrahedrons, etc.
|
||||
# @ingroup l2_modif_cutquadr
|
||||
def SplitVolumesIntoTetra(self, elemIDs, method=smeshBuilder.Hex_5Tet ):
|
||||
def SplitVolumesIntoTetra(self, elems, method=smeshBuilder.Hex_5Tet ):
|
||||
unRegister = genObjUnRegister()
|
||||
if isinstance( elemIDs, Mesh ):
|
||||
elemIDs = elemIDs.GetMesh()
|
||||
if ( isinstance( elemIDs, list )):
|
||||
elemIDs = self.editor.MakeIDSource(elemIDs, SMESH.VOLUME)
|
||||
unRegister.set( elemIDs )
|
||||
self.editor.SplitVolumesIntoTetra(elemIDs, method)
|
||||
if isinstance( elems, Mesh ):
|
||||
elems = elems.GetMesh()
|
||||
if ( isinstance( elems, list )):
|
||||
elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
|
||||
unRegister.set( elems )
|
||||
self.editor.SplitVolumesIntoTetra(elems, method)
|
||||
|
||||
## Splits hexahedra into prisms
|
||||
# @param elems either a list of elements or a mesh or a group or a submesh or a filter
|
||||
# @param startHexPoint a point used to find a hexahedron for which @a facetNormal
|
||||
# gives a normal vector defining facets to split into triangles.
|
||||
# @a startHexPoint can be either a triple of coordinates or a vertex.
|
||||
# @param facetNormal a normal to a facet to split into triangles of a
|
||||
# hexahedron found by @a startHexPoint.
|
||||
# @a facetNormal can be either a triple of coordinates or an edge.
|
||||
# @param method flags passing splitting method: smesh.Hex_2Prisms, smesh.Hex_4Prisms.
|
||||
# smesh.Hex_2Prisms - to split the hexahedron into 2 prisms, etc.
|
||||
# @param allDomains if @c False, only hexahedra adjacent to one closest
|
||||
# to @a startHexPoint are split, else @a startHexPoint
|
||||
# is used to find the facet to split in all domains present in @a elems.
|
||||
# @ingroup l2_modif_cutquadr
|
||||
def SplitHexahedraIntoPrisms(self, elems, startHexPoint, facetNormal,
|
||||
method=smeshBuilder.Hex_2Prisms, allDomains=False ):
|
||||
# IDSource
|
||||
unRegister = genObjUnRegister()
|
||||
if isinstance( elems, Mesh ):
|
||||
elems = elems.GetMesh()
|
||||
if ( isinstance( elems, list )):
|
||||
elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
|
||||
unRegister.set( elems )
|
||||
pass
|
||||
# axis
|
||||
if isinstance( startHexPoint, geomBuilder.GEOM._objref_GEOM_Object):
|
||||
startHexPoint = self.geompyD.PointCoordinates( startHexPoint )
|
||||
if isinstance( facetNormal, geomBuilder.GEOM._objref_GEOM_Object):
|
||||
facetNormal = self.geompyD.VectorCoordinates( facetNormal )
|
||||
axis = SMESH.AxisStruct( startHexPoint[0], startHexPoint[1], startHexPoint[2],
|
||||
facetNormal[0], facetNormal[1], facetNormal[2])
|
||||
self.mesh.SetParameters( axis.parameters )
|
||||
|
||||
self.editor.SplitHexahedraIntoPrisms(elems, method, axis, allDomains)
|
||||
|
||||
## Splits quadrangle faces near triangular facets of volumes
|
||||
#
|
||||
@ -3187,8 +3233,8 @@ class Mesh:
|
||||
# Note that nodes built on edges and boundary nodes are always fixed.
|
||||
# @param MaxNbOfIterations the maximum number of iterations
|
||||
# @param MaxAspectRatio varies in range [1.0, inf]
|
||||
# @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
|
||||
# @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (smesh.CENTROIDAL_SMOOTH)
|
||||
# @return TRUE in case of success, FALSE otherwise.
|
||||
# @ingroup l2_modif_smooth
|
||||
def Smooth(self, IDsOfElements, IDsOfFixedNodes,
|
||||
@ -3206,8 +3252,8 @@ class Mesh:
|
||||
# Note that nodes built on edges and boundary nodes are always fixed.
|
||||
# @param MaxNbOfIterations the maximum number of iterations
|
||||
# @param MaxAspectRatio varies in range [1.0, inf]
|
||||
# @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
|
||||
# @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (smesh.CENTROIDAL_SMOOTH)
|
||||
# @return TRUE in case of success, FALSE otherwise.
|
||||
# @ingroup l2_modif_smooth
|
||||
def SmoothObject(self, theObject, IDsOfFixedNodes,
|
||||
@ -3223,8 +3269,8 @@ class Mesh:
|
||||
# Note that nodes built on edges and boundary nodes are always fixed.
|
||||
# @param MaxNbOfIterations the maximum number of iterations
|
||||
# @param MaxAspectRatio varies in range [1.0, inf]
|
||||
# @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
|
||||
# @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (smesh.CENTROIDAL_SMOOTH)
|
||||
# @return TRUE in case of success, FALSE otherwise.
|
||||
# @ingroup l2_modif_smooth
|
||||
def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
|
||||
@ -3242,8 +3288,8 @@ class Mesh:
|
||||
# Note that nodes built on edges and boundary nodes are always fixed.
|
||||
# @param MaxNbOfIterations the maximum number of iterations
|
||||
# @param MaxAspectRatio varies in range [1.0, inf]
|
||||
# @param Method is either Laplacian (SMESH.SMESH_MeshEditor.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (SMESH.SMESH_MeshEditor.CENTROIDAL_SMOOTH)
|
||||
# @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
|
||||
# or Centroidal (smesh.CENTROIDAL_SMOOTH)
|
||||
# @return TRUE in case of success, FALSE otherwise.
|
||||
# @ingroup l2_modif_smooth
|
||||
def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
|
||||
|
Loading…
Reference in New Issue
Block a user