[bos #32739][CEA] 3D warp

added new eControl
added new case for 3DWarp
Added new class for 3D Warp
Added 3D warp for use as filter

Threshold of criteria

Fix problem when the Threshold checkbox on Scalar Bar Properties does not remove elements outside of the range
This commit is contained in:
asozinov 2023-05-15 16:14:50 +01:00 committed by mbs
parent 2de9636a4f
commit 5b323f6344
30 changed files with 669 additions and 26 deletions

View File

@ -0,0 +1,9 @@
# Warping 3D
# create mesh
from mechanic import *
# get faces with warping angle = 2.0e-13 with tolerance 5.0e-14
filter = smesh_builder.GetFilter(SMESH.VOLUME, SMESH.FT_Warping3D, "=", 2.0e-13, Tolerance=5.0e-14)
ids = mesh.GetIdsFromFilter(filter)
print("Number of volumes with warping = 2.0e-13 (tolerance 5.0e-14):", len(ids))

View File

@ -0,0 +1,25 @@
# Warping
from mechanic import *
# Criterion : WARP ANGLE > 1e-15
wa_margin = 1e-15
aFilter = smesh_builder.GetFilter(SMESH.VOLUME, SMESH.FT_Warping3D, SMESH.FT_MoreThan, wa_margin)
anIds = mesh.GetIdsFromFilter(aFilter)
# print the result
print("Criterion: Warp > ", wa_margin, " Nb = ", len(anIds))
j = 1
for i in range(len(anIds)):
if j > 20: j = 1; print("")
print(anIds[i], end=' ')
j = j + 1
pass
print("")
# create a group
aGroup = mesh.CreateEmptyGroup(SMESH.VOLUME, "Warp > " + repr(wa_margin))
aGroup.Add(anIds)

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

View File

@ -47,6 +47,7 @@ Volume quality controls:
* :ref:`aspect_ratio_3d_page`
* :ref:`volume_page`
* :ref:`warping_3d_page`
* :ref:`max_element_length_3d_page`
* :ref:`scaled_jacobian_page`
* :ref:`bare_border_volumes_page`
@ -98,6 +99,7 @@ To manage the quality controls call pop-up in the VTK viewer and select "Control
aspect_ratio_3d.rst
volume.rst
max_element_length_3d.rst
warping_3d.rst
bare_border_volumes.rst
over_constrained_volumes.rst
scalar_bar.rst

View File

@ -97,6 +97,24 @@ filters 2D mesh elements (faces) according to the warping angle value:
**See also:** :ref:`tui_warping`
.. _filter_warping_3d:
Warping 3D
=============
filters 3D mesh elements (volumes) according to the maximum warping angle value of the faces of volumes:
* element type is *SMESH.VOLUME*
* functor type is *SMESH.FT_Warping3D*
* threshold is floating point value (warping angle)
.. literalinclude:: ../../examples/filters_ex41.py
:language: python
:download:`Download this script <../../examples/filters_ex41.py>`
**See also:** :ref:`tui_warping_3d`
.. _filter_minimum_angle:
Minimum angle

View File

@ -250,3 +250,13 @@ Scaled Jacobian
:language: python
:download:`Download this script <../../examples/quality_controls_ex24.py>`
.. _tui_warping_3d:
Warping 3D
=======
.. literalinclude:: ../../examples/quality_controls_ex23.py
:language: python
:download:`Download this script <../../examples/quality_controls_ex23.py>`

View File

@ -0,0 +1,24 @@
.. _warping_3d_page:
*******
Warping 3D
*******
3D Warping control compute warping angle on each faces of volume elements.
The page :ref:`warping_page` provide information about computing warping angle for 2D element
*To apply the Warping quality criterion to your mesh:*
.. |img| image:: ../images/image39.png
#. Display your mesh in the viewer.
#. Choose **Controls > Volume Controls > Warping 3D** or click *"Warping 3D"* button |img| of the toolbar.
Your mesh will be displayed in the viewer with its elements colored according to the applied mesh quality control criterion:
.. image:: ../images/image_warping3D.jpg
:align: center
**See Also** a sample TUI Script of a :ref:`tui_warping_3d` filter.

View File

@ -42,7 +42,8 @@ module SMESH
{
FT_AspectRatio,
FT_AspectRatio3D,
FT_Warping,
FT_Warping,
FT_Warping3D,
FT_MinimumAngle,
FT_Taper,
FT_Skew,
@ -138,6 +139,7 @@ module SMESH
interface AspectRatio : NumericalFunctor{};
interface AspectRatio3D : NumericalFunctor{};
interface Warping : NumericalFunctor{};
interface Warping3D : NumericalFunctor {};
interface Taper : NumericalFunctor{};
interface Skew : NumericalFunctor{};
interface Area : NumericalFunctor{};
@ -586,6 +588,7 @@ module SMESH
AspectRatio CreateAspectRatio();
AspectRatio3D CreateAspectRatio3D();
Warping CreateWarping();
Warping3D CreateWarping3D();
Taper CreateTaper();
Skew CreateSkew();
Area CreateArea();

View File

@ -1423,21 +1423,7 @@ bool Warping::IsApplicable( const SMDS_MeshElement* element ) const
double Warping::GetValue( const TSequenceOfXYZ& P )
{
if ( P.size() != 4 )
return 0;
gp_XYZ G = ( P( 1 ) + P( 2 ) + P( 3 ) + P( 4 ) ) / 4.;
double A1 = ComputeA( P( 1 ), P( 2 ), P( 3 ), G );
double A2 = ComputeA( P( 2 ), P( 3 ), P( 4 ), G );
double A3 = ComputeA( P( 3 ), P( 4 ), P( 1 ), G );
double A4 = ComputeA( P( 4 ), P( 1 ), P( 2 ), G );
double val = Max( Max( A1, A2 ), Max( A3, A4 ) );
const double eps = 0.1; // val is in degrees
return val < eps ? 0. : val;
return ComputeValue(P);
}
double Warping::ComputeA( const gp_XYZ& thePnt1,
@ -1464,6 +1450,25 @@ double Warping::ComputeA( const gp_XYZ& thePnt1,
return asin( fabs( H / L ) ) * 180. / M_PI;
}
double Warping::ComputeValue(const TSequenceOfXYZ& thePoints) const
{
if (thePoints.size() != 4)
return 0;
gp_XYZ G = (thePoints(1) + thePoints(2) + thePoints(3) + thePoints(4)) / 4.;
double A1 = ComputeA(thePoints(1), thePoints(2), thePoints(3), G);
double A2 = ComputeA(thePoints(2), thePoints(3), thePoints(4), G);
double A3 = ComputeA(thePoints(3), thePoints(4), thePoints(1), G);
double A4 = ComputeA(thePoints(4), thePoints(1), thePoints(2), G);
double val = Max(Max(A1, A2), Max(A3, A4));
const double eps = 0.1; // val is in degrees
return val < eps ? 0. : val;
}
double Warping::GetBadRate( double Value, int /*nbNodes*/ ) const
{
// the warp is in the range [0.0,PI/2]
@ -1478,6 +1483,93 @@ SMDSAbs_ElementType Warping::GetType() const
}
//================================================================================
/*
Class : Warping3D
Description : Functor for calculating warping
*/
//================================================================================
bool Warping3D::IsApplicable(const SMDS_MeshElement* element) const
{
return NumericalFunctor::IsApplicable(element);//&& element->NbNodes() == 4;
}
double Warping3D::GetValue(long theId)
{
double aVal = 0;
myCurrElement = myMesh->FindElement(theId);
if (myCurrElement)
{
WValues aValues;
ProcessVolumeELement(aValues);
for (const auto& aValue: aValues)
{
aVal = Max(aVal, aValue.myWarp);
}
}
return aVal;
}
double Warping3D::GetValue(const TSequenceOfXYZ& P)
{
return ComputeValue(P);
}
SMDSAbs_ElementType Warping3D::GetType() const
{
return SMDSAbs_Volume;
}
bool Warping3D::Value::operator<(const Warping3D::Value& x) const
{
if (myPntIds.size() != x.myPntIds.size())
return myPntIds.size() < x.myPntIds.size();
for (int anInd = 0; anInd < myPntIds.size(); ++anInd)
if (myPntIds[anInd] != x.myPntIds[anInd])
return myPntIds[anInd] != x.myPntIds[anInd];
return false;
}
// Compute value on each face of volume
void Warping3D::ProcessVolumeELement(WValues& theValues)
{
SMDS_VolumeTool aVTool(myCurrElement);
double aCoord[3];
for (int aFaceID = 0; aFaceID < aVTool.NbFaces(); ++aFaceID)
{
TSequenceOfXYZ aPoints;
std::set<const SMDS_MeshNode*> aNodes;
std::vector<long> aNodeIds;
const SMDS_MeshNode** aNodesPtr = aVTool.GetFaceNodes(aFaceID);
if (aNodesPtr)
{
for (int i = 0; i < aVTool.NbFaceNodes(aFaceID); ++i)
{
aNodesPtr[i]->GetXYZ(aCoord);
aPoints.push_back(gp_XYZ{ aCoord[0], aCoord[1], aCoord[2] });
aNodeIds.push_back(aNodesPtr[i]->GetID());
}
double aWarp = GetValue(aPoints);
Value aVal{ aWarp, aNodeIds };
theValues.push_back(aVal);
}
}
}
void Warping3D::GetValues(WValues& theValues)
{
for (SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator(); anIter->more(); )
{
myCurrElement = anIter->next();
ProcessVolumeELement(theValues);
}
}
//================================================================================
/*
Class : Taper

View File

@ -246,9 +246,35 @@ namespace SMESH{
virtual SMDSAbs_ElementType GetType() const;
virtual bool IsApplicable( const SMDS_MeshElement* element ) const;
private:
protected:
double ComputeA( const gp_XYZ&, const gp_XYZ&, const gp_XYZ&, const gp_XYZ& ) const;
double ComputeValue( const TSequenceOfXYZ& thePoints ) const;
};
/*
Class : Warping3D
Description : Functor for calculating warping
*/
class SMESHCONTROLS_EXPORT Warping3D: public virtual Warping {
public:
virtual bool IsApplicable(const SMDS_MeshElement* element) const;
virtual double GetValue(const TSequenceOfXYZ& thePoints);
virtual double GetValue(long theId);
virtual SMDSAbs_ElementType GetType() const;
struct Value {
double myWarp;
std::vector<long> myPntIds;
bool operator<(const Value& x) const;
};
typedef std::vector<Value> WValues;
void GetValues(WValues& theValues);
private:
void ProcessVolumeELement(WValues& theValues);
};
typedef boost::shared_ptr<Warping3D> Warping3DPtr;
/*

View File

@ -1013,6 +1013,14 @@ void SMESH_ActorDef::SetControlMode( eControl theMode, bool theCheckEntityMode )
myControlActor = my2DActor;
break;
}
case eWarping3D:
{
SMESH::Controls::Warping3D* aControl = new SMESH::Controls::Warping3D();
aControl->SetPrecision(myControlsPrecision);
myFunctor.reset(aControl);
myControlActor = my3DActor;
break;
}
case eSkew:
{
SMESH::Controls::Skew* aControl = new SMESH::Controls::Skew();
@ -1078,6 +1086,10 @@ void SMESH_ActorDef::SetControlMode( eControl theMode, bool theCheckEntityMode )
my1DExtActor->SetExtControlMode(myFunctor,myScalarBarActor,myLookupTable);
UpdateDistribution();
break;
case eWarping3D:
my2DExtActor->SetExtControlMode(myFunctor, myScalarBarActor, myLookupTable);
UpdateDistribution();
break;
default:
myControlActor->SetControlMode(myFunctor,myScalarBarActor,myLookupTable);
UpdateDistribution();
@ -1543,6 +1555,7 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation)
case eBareBorderFace:
case eOverConstrainedFace:
case eCoincidentElems2D:
case eWarping3D:
my2DExtActor->VisibilityOn();
break;
case eBareBorderVolume:
@ -1558,7 +1571,8 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation)
if ( GetPickable( ))
myPickableActor->VisibilityOn();
if ( GetRepresentation() != ePoint )
if ( GetRepresentation() != ePoint &&
!(IsClipThresholdOn() && GetActorForThreshold() != myControlActor)) // Avoid calling VisibilityOn if for display result of Threshold Criteria need only ExtActor
{
if(myEntityMode & e0DElements ){
my0DActor->VisibilityOn();
@ -2502,11 +2516,27 @@ void SMESH_ActorDef::UpdateScalarBar()
}
// Hides the cells beyond threshold if isThresholdOn == true.
void SMESH_ActorDef::ClipThreshold(bool isThresholdOn, double min /*= 0.0*/, double max /*= 0.0*/)
// Get Actor for Threshold criteria compute
SMESH_DeviceActor* SMESH_ActorDef::GetActorForThreshold()
{
switch (myControlMode) {
case eLength2D:
return my1DExtActor;
case eWarping3D:
return my2DExtActor;
default:;
return myControlActor;
}
}
// Hides the cells beyond threshold if isThresholdOn == true.
void SMESH_ActorDef::ClipThreshold(bool isThresholdOn,double min /*= 0.0*/, double max /*= 0.0*/)
{
SMESH_DeviceActor* anActor = GetActorForThreshold();
if (anActor != myControlActor)
myControlActor->VisibilityOff();
myIsClipThresholdOn = isThresholdOn;
if (isThresholdOn)
{
// Initialize the filter
@ -2514,7 +2544,7 @@ void SMESH_ActorDef::ClipThreshold(bool isThresholdOn, double min /*= 0.0*/, dou
// We have set scalar data with SMESH_DeviceActor::SetControlMode() call as vtkDataSetAttributes::SCALARS.
// So, we don't need to pass an array name in SetInputArrayToProcess().
threshold->SetInputConnection(myControlActor->myMergeFilter->GetOutputPort());
threshold->SetInputConnection(anActor->myMergeFilter->GetOutputPort());
threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, vtkDataSetAttributes::SCALARS);
// Set range
@ -2528,12 +2558,18 @@ void SMESH_ActorDef::ClipThreshold(bool isThresholdOn, double min /*= 0.0*/, dou
// Add to the filters' chain
vtkAlgorithmOutput* port = threshold->GetOutputPort();
myControlActor->myPassFilter[0]->SetInputConnection(port);
anActor->myPassFilter[0]->SetInputConnection(port);
}
else
{
// Restore the filters' chain
myControlActor->SetImplicitFunctionUsed(myControlActor->myIsImplicitFunctionUsed);
anActor->SetImplicitFunctionUsed(anActor->myIsImplicitFunctionUsed);
// Restore Actor filters when after Controls, which not use ExtACtor was called Controls, which use ExtActor
// For avoid artifact's
if (anActor != myControlActor)
myControlActor->SetImplicitFunctionUsed(myControlActor->myIsImplicitFunctionUsed);
myControlActor->VisibilityOn();
}
}

View File

@ -38,6 +38,7 @@
class vtkUnstructuredGrid;
class SMESH_ScalarBarActor;
class SMESH_DeviceActor;
class vtkPlane;
class vtkImplicitBoolean;
@ -139,7 +140,7 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor
enum eControl{eNone, eLength, eLength2D, eDeflection2D, eFreeBorders, eFreeEdges, eFreeNodes,
eFreeFaces, eMultiConnection, eArea, eTaper, eAspectRatio,
eMinimumAngle, eWarping, eSkew, eAspectRatio3D, eMultiConnection2D, eVolume3D, eScaledJacobian,
eMinimumAngle, eWarping, eSkew, eAspectRatio3D, eWarping3D, eMultiConnection2D, eVolume3D, eScaledJacobian,
eMaxElementLength2D, eMaxElementLength3D, eBareBorderFace, eBareBorderVolume,
eOverConstrainedFace, eOverConstrainedVolume, eCoincidentNodes,
eCoincidentElems1D, eCoincidentElems2D, eCoincidentElems3D, eNodeConnectivityNb,
@ -167,6 +168,7 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor
virtual void UpdateScalarBar() = 0;
virtual void UpdateDistribution() = 0;
virtual void ClipThreshold(bool isThresholdOn, double min = 0.0, double max = 0.0) = 0;
virtual SMESH_DeviceActor* GetActorForThreshold() = 0;
virtual bool IsClipThresholdOn() const = 0;
virtual void SetWireframeOff(bool isWireframeOff) = 0;
virtual bool IsWireframeOff() const = 0;

View File

@ -226,6 +226,7 @@ class SMESH_ActorDef : public SMESH_Actor
virtual void UpdateScalarBar();
virtual void UpdateDistribution();
virtual SMESH_DeviceActor* GetActorForThreshold();
virtual void ClipThreshold(bool isThresholdOn, double min = 0.0, double max = 0.0);
virtual bool IsClipThresholdOn() const { return myIsClipThresholdOn; }
virtual void SetWireframeOff(bool isWireframeOff);

View File

@ -504,6 +504,80 @@ SMESH_DeviceActor
theLookupTable->SetRange(aScalars->GetRange());
theLookupTable->Build();
myMergeFilter->SetScalarsData(aDataSet);
aDataSet->Delete();
}
else if (Warping3D* aWarping3D = dynamic_cast<Warping3D*>(theFunctor.get())){
SMESH::Controls::Warping3D::WValues aValues;
aWarping3D->GetValues(aValues);
vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
aDataSet->SetPoints(aGrid->GetPoints());
vtkIdType aNbCells = aValues.size();
vtkDoubleArray* aScalars = vtkDoubleArray::New();
aScalars->SetNumberOfComponents(1);
aScalars->SetNumberOfTuples(aNbCells);
vtkIdType aCellsSize = 3 * aNbCells;
vtkCellArray* aConnectivity = vtkCellArray::New();
aConnectivity->Allocate(aCellsSize, 0);
vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
aCellTypesArray->SetNumberOfComponents(1);
aCellTypesArray->Allocate(aNbCells* aCellTypesArray->GetNumberOfComponents());
Warping3D::WValues::const_iterator anIter = aValues.begin();
aNbCells = 0;
for (; anIter != aValues.end(); anIter++) {
const Warping3D::Value& aValue = *anIter;
vtkIdList* anIdList = vtkIdList::New();
anIdList->SetNumberOfIds(aValue.myPntIds.size());
bool isExist = true;
for (int i = 0; i < aValue.myPntIds.size(); ++i)
{
int aVTKId = myVisualObj->GetNodeVTKId(aValue.myPntIds[i]);
if (aVTKId < 0)
{
isExist = false;
break;
}
anIdList->SetId(i, aVTKId);
}
if (isExist)
{
aConnectivity->InsertNextCell(anIdList);
aCellTypesArray->InsertNextValue(VTK_POLYGON);
aScalars->SetValue(aNbCells, aValue.myWarp);
aNbCells++;
}
}
aCellTypesArray->SetNumberOfTuples(aNbCells);
aScalars->SetNumberOfTuples(aNbCells);
vtkIdTypeArray* aCellLocationsArray = vtkIdTypeArray::New();
aCellLocationsArray->SetNumberOfComponents(1);
aCellLocationsArray->SetNumberOfTuples(aNbCells);
aConnectivity->InitTraversal();
vtkIdType const* pts(nullptr);
for (vtkIdType idType = 0, npts; aConnectivity->GetNextCell(npts, pts); idType++)
aCellLocationsArray->SetValue(idType, aConnectivity->GetTraversalLocation(npts));
aDataSet->SetCells(aCellTypesArray, aCellLocationsArray, aConnectivity);
SetUnstructuredGrid(aDataSet);
aDataSet->GetCellData()->SetScalars(aScalars);
aScalars->Delete();
theLookupTable->SetRange(aScalars->GetRange());
theLookupTable->Build();
myMergeFilter->SetScalarsData(aDataSet);
aDataSet->Delete();
}

View File

@ -1121,6 +1121,8 @@ namespace
type = QObject::tr( "ASPECTRATIO_3D_ELEMENTS" );
else if ( dynamic_cast< SMESH::Controls::Warping* >( f.get() ) )
type = QObject::tr( "WARP_ELEMENTS" );
else if (dynamic_cast<SMESH::Controls::Warping3D*>(f.get()))
type = QObject::tr("WARP_3D_ELEMENTS");
else if ( dynamic_cast< SMESH::Controls::Taper* >( f.get() ) )
type = QObject::tr( "TAPER_ELEMENTS" );
else if ( dynamic_cast< SMESH::Controls::Skew* >( f.get() ) )
@ -1780,6 +1782,7 @@ namespace
ActionControl.Bind( SMESHOp::OpMaxElementLength2D, SMESH_Actor::eMaxElementLength2D );
ActionControl.Bind( SMESHOp::OpEqualFace, SMESH_Actor::eCoincidentElems2D );
ActionControl.Bind( SMESHOp::OpAspectRatio3D, SMESH_Actor::eAspectRatio3D );
ActionControl.Bind( SMESHOp::OpWarping3D, SMESH_Actor::eWarping3D );
ActionControl.Bind( SMESHOp::OpVolume, SMESH_Actor::eVolume3D );
ActionControl.Bind( SMESHOp::OpScaledJacobian, SMESH_Actor::eScaledJacobian );
ActionControl.Bind( SMESHOp::OpMaxElementLength3D, SMESH_Actor::eMaxElementLength3D );
@ -3906,6 +3909,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
case SMESHOp::OpMaxElementLength2D:
case SMESHOp::OpEqualFace:
case SMESHOp::OpAspectRatio3D:
case SMESHOp::OpWarping3D:
case SMESHOp::OpVolume:
case SMESHOp::OpScaledJacobian:
case SMESHOp::OpMaxElementLength3D:
@ -4214,6 +4218,7 @@ void SMESHGUI::initialize( CAM_Application* app )
createSMESHAction( SMESHOp::OpMaxElementLength2D, "MAX_ELEMENT_LENGTH_2D", "ICON_MAX_ELEMENT_LENGTH_2D", 0, true );
createSMESHAction( SMESHOp::OpEqualFace, "EQUAL_FACE", "ICON_EQUAL_FACE", 0, true );
createSMESHAction( SMESHOp::OpAspectRatio3D, "ASPECT_3D", "ICON_ASPECT_3D", 0, true );
createSMESHAction( SMESHOp::OpWarping3D, "WARP_3D", "ICON_WARP", 0, true);
createSMESHAction( SMESHOp::OpVolume, "VOLUME_3D", "ICON_VOLUME_3D", 0, true );
createSMESHAction( SMESHOp::OpMaxElementLength3D, "MAX_ELEMENT_LENGTH_3D", "ICON_MAX_ELEMENT_LENGTH_3D", 0, true );
createSMESHAction( SMESHOp::OpBareBorderVolume, "BARE_BORDER_VOLUME", "ICON_BARE_BORDER_VOLUME", 0, true );
@ -4359,7 +4364,7 @@ void SMESHGUI::initialize( CAM_Application* app )
<< SMESHOp::OpMinimumAngle << SMESHOp::OpWarpingAngle << SMESHOp::OpSkew
<< SMESHOp::OpMaxElementLength2D << SMESHOp::OpBareBorderFace
<< SMESHOp::OpOverConstrainedFace << SMESHOp::OpEqualFace // face controls
<< SMESHOp::OpAspectRatio3D << SMESHOp::OpVolume
<< SMESHOp::OpAspectRatio3D << SMESHOp::OpVolume << SMESHOp::OpWarping3D
<< SMESHOp::OpMaxElementLength3D << SMESHOp::OpBareBorderVolume
<< SMESHOp::OpOverConstrainedVolume << SMESHOp::OpEqualVolume << SMESHOp::OpScaledJacobian; // volume controls
QActionGroup* aCtrlGroup = new QActionGroup( application()->desktop() );
@ -4472,6 +4477,7 @@ void SMESHGUI::initialize( CAM_Application* app )
createMenu( SMESHOp::OpEqualFace, faceId, -1 );
createMenu( SMESHOp::OpDeflection2D, faceId, -1 );
createMenu( SMESHOp::OpAspectRatio3D, volumeId, -1 );
createMenu( SMESHOp::OpWarping3D, volumeId, -1 );
createMenu( SMESHOp::OpVolume, volumeId, -1 );
createMenu( SMESHOp::OpMaxElementLength3D, volumeId, -1 );
createMenu( SMESHOp::OpBareBorderVolume, volumeId, -1 );
@ -4631,6 +4637,7 @@ void SMESHGUI::initialize( CAM_Application* app )
int ctrl3dTb = createTool( tr( "TB_CTRL3D" ), QString( "SMESHVolumeControlsToolbar" ) ) ;
createTool( SMESHOp::OpAspectRatio3D, ctrl3dTb );
createTool( SMESHOp::OpWarping3D, ctrl3dTb );
createTool( SMESHOp::OpVolume, ctrl3dTb );
createTool( SMESHOp::OpMaxElementLength3D, ctrl3dTb );
createTool( SMESHOp::OpBareBorderVolume, ctrl3dTb );
@ -5095,6 +5102,10 @@ void SMESHGUI::initialize( CAM_Application* app )
popupMgr()->setRule( action( SMESHOp::OpAspectRatio3D ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
popupMgr()->setRule( action( SMESHOp::OpAspectRatio3D ), "controlMode = 'eAspectRatio3D'", QtxPopupMgr::ToggleRule );
popupMgr()->insert ( action( SMESHOp::OpWarping3D ), aSubId, -1 );
popupMgr()->setRule( action( SMESHOp::OpWarping3D ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
popupMgr()->setRule( action( SMESHOp::OpWarping3D), "controlMode = 'eWarping3D'", QtxPopupMgr::ToggleRule );
popupMgr()->insert ( action( SMESHOp::OpVolume ), aSubId, -1 );
popupMgr()->setRule( action( SMESHOp::OpVolume ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule );
popupMgr()->setRule( action( SMESHOp::OpVolume ), "controlMode = 'eVolume3D'", QtxPopupMgr::ToggleRule );

View File

@ -1563,6 +1563,7 @@ void SMESHGUI_FilterTable::updateAdditionalWidget()
bool isDbl = ( aCriterion == SMESH::FT_AspectRatio ||
aCriterion == SMESH::FT_AspectRatio3D ||
aCriterion == SMESH::FT_Warping ||
aCriterion == SMESH::FT_Warping3D ||
aCriterion == SMESH::FT_MinimumAngle ||
aCriterion == SMESH::FT_Taper ||
aCriterion == SMESH::FT_Skew ||
@ -1606,6 +1607,7 @@ const char* SMESHGUI_FilterTable::getPrecision( const int aType )
case SMESH::FT_Taper:
retval = "parametric_precision"; break;
case SMESH::FT_Warping:
case SMESH::FT_Warping3D:
case SMESH::FT_MinimumAngle:
case SMESH::FT_Skew:
case SMESH::FT_CoplanarFaces:
@ -1812,6 +1814,7 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int /*col*/,
case SMESH::FT_AspectRatio:
case SMESH::FT_AspectRatio3D:
case SMESH::FT_Warping:
case SMESH::FT_Warping3D:
case SMESH::FT_MinimumAngle:
case SMESH::FT_Taper:
case SMESH::FT_Skew:
@ -2270,6 +2273,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
if (aCriteria.isEmpty())
{
aCriteria[ SMESH::FT_AspectRatio3D ] = tr("ASPECT_RATIO_3D");
aCriteria[ SMESH::FT_Warping3D ] = tr("WARPING_3D");
aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS");
aCriteria[ SMESH::FT_BelongToMeshGroup ] = tr("BELONG_TO_MESH_GROUP");
aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM");

View File

@ -1674,6 +1674,8 @@ QString SMESHGUI_ElemInfo::ctrl2str( int control )
title = tr( "ASPECTRATIO_3D_ELEMENTS" ); break;
case SMESH::FT_Warping:
title = tr( "WARP_ELEMENTS" ); break;
case SMESH::FT_Warping3D:
title = tr( "WARP_3D_ELEMENTS" ); break;
case SMESH::FT_MinimumAngle:
title = tr( "MINIMUMANGLE_ELEMENTS" ); break;
case SMESH::FT_Taper:

View File

@ -123,6 +123,7 @@ namespace SMESHOp {
OpOverConstrainedVolume = 3304, // MENU CONTROLS - OVERCONSTRAINED VOLUMES
OpEqualVolume = 3305, // MENU CONTROLS - DOUBLE VOLUMES
OpScaledJacobian = 3306, // MENU CONTROLS - SCALED JACOBIAN
OpWarping3D = 3307, // MENU CONTROLS - Warping 3D
OpOverallMeshQuality = 3400, // MENU CONTROLS - OVERALL MESH QUALITY
// Modification -------------------//--------------------------------
OpNode = 4000, // MENU MODIFICATION - ADD - NODE

View File

@ -377,6 +377,7 @@ QString SMESHGUI_Selection::controlMode( int ind ) const
case SMESH_Actor::eTaper: mode = "eTaper"; break;
case SMESH_Actor::eAspectRatio: mode = "eAspectRatio"; break;
case SMESH_Actor::eAspectRatio3D: mode = "eAspectRatio3D"; break;
case SMESH_Actor::eWarping3D: mode = "eWarping3D"; break;
case SMESH_Actor::eMinimumAngle: mode = "eMinimumAngle"; break;
case SMESH_Actor::eWarping: mode = "eWarping"; break;
case SMESH_Actor::eSkew: mode = "eSkew"; break;
@ -438,6 +439,7 @@ bool SMESHGUI_Selection::isNumFunctor( int ind ) const
case SMESH_Actor::eAspectRatio3D:
case SMESH_Actor::eMinimumAngle:
case SMESH_Actor::eWarping:
case SMESH_Actor::eWarping3D:
case SMESH_Actor::eSkew:
result = true;
break;

View File

@ -908,6 +908,9 @@ bool SMESH::SelectionProxy::elementControl( int id, int control, double precisio
case SMESH::FT_Warping:
functor.reset( new SMESH::Controls::Warping() );
break;
case SMESH::FT_Warping3D:
functor.reset(new SMESH::Controls::Warping3D());
break;
case SMESH::FT_MinimumAngle:
functor.reset( new SMESH::Controls::MinimumAngle() );
break;
@ -979,6 +982,9 @@ bool SMESH::SelectionProxy::elementControl( int id, int control, double precisio
case SMESH::FT_Warping:
functor = manager->CreateWarping();
break;
case SMESH::FT_Warping3D:
functor = manager->CreateWarping3D();
break;
case SMESH::FT_MinimumAngle:
functor = manager->CreateMinimumAngle();
break;

View File

@ -115,6 +115,10 @@
<source>ASPECTRATIO_3D_ELEMENTS</source>
<translation>Aspect Ratio 3D</translation>
</message>
<message>
<source>WARPING_3D_ELEMENTS</source>
<translation>Warping 3D</translation>
</message>
<message>
<source>ASPECTRATIO_ELEMENTS</source>
<translation>Aspect Ratio</translation>
@ -1332,6 +1336,10 @@
<source>MEN_WARP</source>
<translation>Warping Angle</translation>
</message>
<message>
<source>MEN_WARP_3D</source>
<translation>Warping 3D</translation>
</message>
<message>
<source>MEN_WHAT_IS</source>
<translation>Mesh Element Information</translation>
@ -3936,6 +3944,10 @@ Use Display Entity menu command to show them.
<source>STB_WARP</source>
<translation>Warping angle</translation>
</message>
<message>
<source>STB_WARP_3D</source>
<translation>Warping angle</translation>
</message>
<message>
<source>STB_WHAT_IS</source>
<translation>Show information about the mesh node or element</translation>
@ -4656,6 +4668,10 @@ Use Display Entity menu command to show them.
<source>TOP_WARP</source>
<translation>Warping angle</translation>
</message>
<message>
<source>TOP_WARP_3D</source>
<translation>Warping 3D</translation>
</message>
<message>
<source>TOP_WHAT_IS</source>
<translation>Mesh Element Information</translation>
@ -4680,6 +4696,10 @@ Use Display Entity menu command to show them.
<source>WARP_ELEMENTS</source>
<translation>Warping</translation>
</message>
<message>
<source>WARP_3D_ELEMENTS</source>
<translation>Warping 3D</translation>
</message>
<message>
<source>MEN_FILE_INFO</source>
<translation>File Information</translation>
@ -6297,6 +6317,10 @@ Please check input data and try again</translation>
<source>ASPECT_RATIO_3D</source>
<translation>Aspect ratio 3D</translation>
</message>
<message>
<source>WARPING_3D</source>
<translation>Warping 3D</translation>
</message>
<message>
<source>BAD_ORIENTED_VOLUME</source>
<translation>Bad oriented volume</translation>

View File

@ -1332,6 +1332,10 @@
<source>MEN_WARP</source>
<translation>Angle de déformation</translation>
</message>
<message>
<source>MEN_WARP_3D</source>
<translation>Déformation 3D</translation>
</message>
<message>
<source>MEN_WHAT_IS</source>
<translation>Information sur un élément de maillage</translation>
@ -3935,6 +3939,10 @@ Utilisez le menu &quot;Visualiser une entité&quot; pour les afficher.
<source>STB_WARP</source>
<translation>Angle de déformation</translation>
</message>
<message>
<source>STB_WARP_3D</source>
<translation>Déformation 3D</translation>
</message>
<message>
<source>STB_WHAT_IS</source>
<translation>Information sur un élément ou un nœud de maillage</translation>
@ -4655,6 +4663,10 @@ Utilisez le menu &quot;Visualiser une entité&quot; pour les afficher.
<source>TOP_WARP</source>
<translation>Angle de déformation</translation>
</message>
<message>
<source>TOP_WARP_3D</source>
<translation>Déformation 3D</translation>
</message>
<message>
<source>TOP_WHAT_IS</source>
<translation>Information sur l'élément de maillage</translation>
@ -4679,6 +4691,10 @@ Utilisez le menu &quot;Visualiser une entité&quot; pour les afficher.
<source>WARP_ELEMENTS</source>
<translation>Déformation</translation>
</message>
<message>
<source>WARP_3D_ELEMENTS</source>
<translation>Déformation 3D</translation>
</message>
<message>
<source>MEN_FILE_INFO</source>
<translation>Information sur le fichier du maillage</translation>

View File

@ -1131,6 +1131,10 @@
<source>MEN_WARP</source>
<translation></translation>
</message>
<message>
<source>MEN_WARP_3D</source>
<translation>3Dワープ</translation>
</message>
<message>
<source>MEN_WHAT_IS</source>
<translation></translation>
@ -3539,6 +3543,10 @@
<source>STB_WARP</source>
<translation></translation>
</message>
<message>
<source>STB_WARP_3D</source>
<translation>3Dワープ</translation>
</message>
<message>
<source>STB_WHAT_IS</source>
<translation> </translation>
@ -4207,6 +4215,10 @@
<source>TOP_WARP</source>
<translation></translation>
</message>
<message>
<source>TOP_WARP_3D</source>
<translation>3Dワープ</translation>
</message>
<message>
<source>TOP_WHAT_IS</source>
<translation></translation>
@ -4231,6 +4243,10 @@
<source>WARP_ELEMENTS</source>
<translation></translation>
</message>
<message>
<source>WARP_3D_ELEMENTS</source>
<translation>3D </translation>
</message>
<message>
<source>MEN_FILE_INFO</source>
<translation>MEDファイルの情報</translation>

View File

@ -303,6 +303,8 @@ namespace {
// - FT_Length3D = 22
// v 9.12.0: FT_Undefined == 51, new items:
// - FT_ScaledJacobian = 8
// v 9.12.0: FT_Undefined == 52, new items:
// - FT_Warping3D = 4
//
// It's necessary to continue recording this history and to fill
// undef2newItems (see below) accordingly.
@ -328,6 +330,7 @@ namespace {
undef2newItems[ 49 ].push_back( 22 );
undef2newItems[ 50 ].push_back( 22 );
undef2newItems[ 51 ].push_back( 8 );
undef2newItems[ 52 ].push_back( 4 );
ASSERT( undef2newItems.rbegin()->first == SMESH::FT_Undefined );
}

View File

@ -399,6 +399,20 @@ namespace SMESH {
return SMESH::FT_Warping;
}
/*
Class : Warping3D_i
Description : Functor for calculating warping
*/
Warping3D_i::Warping3D_i()
{
myNumericalFunctorPtr.reset(new Controls::Warping3D());
myFunctorPtr = myNumericalFunctorPtr;
}
FunctorType Warping3D_i::GetFunctorType()
{
return SMESH::FT_Warping3D;
}
/*
Class : Taper_i
@ -2106,6 +2120,14 @@ namespace SMESH {
}
Warping3D_ptr FilterManager_i::CreateWarping3D()
{
SMESH::Warping3D_i* aServant = new SMESH::Warping3D_i();
SMESH::Warping3D_var anObj = aServant->_this();
TPythonDump() << aServant << " = " << this << ".CreateWarping3D()";
return anObj._retn();
}
Taper_ptr FilterManager_i::CreateTaper()
{
SMESH::Taper_i* aServant = new SMESH::Taper_i();
@ -3071,6 +3093,9 @@ namespace SMESH {
case SMESH::FT_Warping:
aFunctor = aFilterMgr->CreateWarping();
break;
case SMESH::FT_Warping3D:
aFunctor = aFilterMgr->CreateWarping3D();
break;
case SMESH::FT_MinimumAngle:
aFunctor = aFilterMgr->CreateMinimumAngle();
break;
@ -3532,6 +3557,7 @@ namespace SMESH {
{
case FT_AspectRatio : return "Aspect ratio";
case FT_Warping : return "Warping";
case FT_Warping3D : return "Warping 3D";
case FT_MinimumAngle : return "Minimum angle";
case FT_Taper : return "Taper";
case FT_Skew : return "Skew";
@ -3589,6 +3615,7 @@ namespace SMESH {
{
if ( theStr.equals( "Aspect ratio" ) ) return FT_AspectRatio;
else if ( theStr.equals( "Warping" ) ) return FT_Warping;
else if ( theStr.equals( "Warping 3D" ) ) return FT_Warping3D;
else if ( theStr.equals( "Minimum angle" ) ) return FT_MinimumAngle;
else if ( theStr.equals( "Taper" ) ) return FT_Taper;
else if ( theStr.equals( "Skew" ) ) return FT_Skew;
@ -4163,6 +4190,7 @@ namespace SMESH {
"FT_AspectRatio",
"FT_AspectRatio3D",
"FT_Warping",
"FT_Warping3D",
"FT_MinimumAngle",
"FT_Taper",
"FT_Skew",

View File

@ -164,6 +164,19 @@ namespace SMESH
Warping_i();
FunctorType GetFunctorType();
};
/*
Class : Warping3D_i
Description : Functor for calculating 3D warping
*/
class SMESH_I_EXPORT Warping3D_i : public virtual POA_SMESH::Warping3D,
public virtual NumericalFunctor_i
{
public:
Warping3D_i();
FunctorType GetFunctorType();
};
/*
@ -1121,6 +1134,7 @@ namespace SMESH
AspectRatio_ptr CreateAspectRatio();
AspectRatio3D_ptr CreateAspectRatio3D();
Warping_ptr CreateWarping();
Warping3D_ptr CreateWarping3D();
Taper_ptr CreateTaper();
Skew_ptr CreateSkew();
Area_ptr CreateArea();

View File

@ -409,6 +409,7 @@ namespace SMESH
case FT_AspectRatio: myStream<< "aAspectRatio"; break;
case FT_AspectRatio3D: myStream<< "aAspectRatio3D"; break;
case FT_Warping: myStream<< "aWarping"; break;
case FT_Warping3D: myStream<< "aWarping3D"; break;
case FT_MinimumAngle: myStream<< "aMinimumAngle"; break;
case FT_Taper: myStream<< "aTaper"; break;
case FT_Skew: myStream<< "aSkew"; break;

View File

@ -1203,6 +1203,8 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
functor = aFilterMgr.CreateAspectRatio3D()
elif theCriterion == FT_Warping:
functor = aFilterMgr.CreateWarping()
elif theCriterion == FT_Warping3D:
functor = aFilterMgr.CreateWarping3D()
elif theCriterion == FT_MinimumAngle:
functor = aFilterMgr.CreateMinimumAngle()
elif theCriterion == FT_Taper:
@ -7460,6 +7462,19 @@ class Mesh(metaclass = MeshMeta):
return self.FunctorValue(SMESH.FT_Warping, elemId)
def GetWarping3D(self, elemId):
"""
Get warping angle of faces element of 3D elements.
Parameters:
elemId: mesh element ID
Returns:
element's warping angle value
"""
return self.FunctorValue(SMESH.FT_Warping3D, elemId)
def GetMinimumAngle(self, elemId):
"""
Get minimum angle of 2D element.

View File

@ -0,0 +1,177 @@
#!/usr/bin/env python
import os
import sys
import salome
import tempfile
salome.salome_init()
def getTmpFileName(ext):
"""
get a tmp file name
"""
tempdir = tempfile.gettempdir()
tmp_file = tempfile.NamedTemporaryFile(suffix=".%s"%ext , dir=tempdir, delete=False)
tmp_filename = tmp_file.name
return tmp_filename
###
### SHAPER component
###
from salome.shaper import model
model.begin()
partSet = model.moduleDocument()
Part_1 = model.addPart(partSet)
Part_1_doc = Part_1.document()
Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 1, 7)
Point_2 = model.addPoint(Part_1_doc, 1, 0, 1.5)
Point_3 = model.addPoint(Part_1_doc, 0.5, 0, 3.5)
Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "Point_1"), 0.75)
Cylinder_2 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "Point_2"), model.selection("EDGE", "PartSet/OX"), 0.6, 3)
Fuse_1_objects_1 = [model.selection("SOLID", "Cylinder_2_1"),
model.selection("SOLID", "Cylinder_1_1"),
model.selection("SOLID", "Sphere_1_1")]
Fuse_1 = model.addFuse(Part_1_doc, Fuse_1_objects_1, keepSubResults = True)
model.end()
expected_volume = 25.881416712512
model.testResultsVolumes(Fuse_1, [expected_volume])
###
### SHAPERSTUDY component
###
model.publishToShaperStudy()
import SHAPERSTUDY
Fuse_1_1, = SHAPERSTUDY.shape(model.featureStringId(Fuse_1))
###
### SMESH component
###
import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New()
# Surface Mesh
# ============
Mesh_1 = smesh.Mesh(Fuse_1_1, "Mesh_1")
NETGEN_1D_2D = Mesh_1.Triangle(algo=smeshBuilder.NETGEN_1D2D)
NETGEN_2D_Parameters_1 = NETGEN_1D_2D.Parameters()
NETGEN_2D_Parameters_1.SetMaxSize( 0.75 )
NETGEN_2D_Parameters_1.SetMinSize( 0 )
NETGEN_2D_Parameters_1.SetSecondOrder( 0 )
NETGEN_2D_Parameters_1.SetOptimize( 1 )
NETGEN_2D_Parameters_1.SetFineness( 5 )
NETGEN_2D_Parameters_1.SetGrowthRate( 0.1 )
NETGEN_2D_Parameters_1.SetNbSegPerEdge( 2 )
NETGEN_2D_Parameters_1.SetNbSegPerRadius( 4 )
isDone = Mesh_1.Compute()
if not isDone:
raise Exception("Error when computing the surface mesh")
# MG-Hexa mesh
# ============
MG_Hexa = Mesh_1.Hexahedron(algo=smeshBuilder.MG_Hexa)
isDone = Mesh_1.Compute()
if not isDone:
raise Exception("Error when computing volumes with MG-Hexa")
volume = smesh.GetVolume(Mesh_1)
#print("volume: ", volume)
assert abs(volume-expected_volume)/expected_volume < 0.03
assert Mesh_1.NbTriangles() == 0
nb_hexa = Mesh_1.NbHexas()
assert Mesh_1.NbVolumes() == nb_hexa
# MG-Hexa mesh with layers
# ========================
MG_Hexa_Parameters = MG_Hexa.Parameters()
MG_Hexa_Parameters.SetNbLayers( 3 )
MG_Hexa_Parameters.SetFirstLayerSize( 0.01 )
MG_Hexa_Parameters.SetGrowth( 1.1 )
MG_Hexa_Parameters.SetFacesWithLayers( [ 10, 3 ] )
MG_Hexa_Parameters.SetImprintedFaces( [ 18, 20, 22 ] )
isDone = Mesh_1.Compute()
if not isDone:
raise Exception("Error when computing volumes with MG-Hexa and layers")
nb_hexa_with_layers = Mesh_1.NbHexas()
assert Mesh_1.NbVolumes() == nb_hexa_with_layers
assert nb_hexa < nb_hexa_with_layers
volume_with_layers = smesh.GetVolume(Mesh_1)
#print("volume_with_layers: ", volume_with_layers)
assert abs(volume_with_layers-expected_volume)/expected_volume < 0.05
gr_small_volume = Mesh_1.MakeGroup("small_volumes_layers",
SMESH.VOLUME,
CritType=SMESH.FT_Volume3D,
Compare=SMESH.FT_LessThan,
Threshold=8e-5,
Tolerance=1e-07)
layers_volume = smesh.GetVolume(gr_small_volume)
#print("layers_volume: ", layers_volume)
assert layers_volume < 0.9
# check max Warp3D
max_warp3D = Mesh_1.GetMinMax(SMESH.FT_Warping3D)[1]
print("max_warp3D: ", max_warp3D)
# Check that some elements are warped
assert max_warp3D > 1
gr_warp3D = Mesh_1.MakeGroup("warp3D",
SMESH.VOLUME,
CritType=SMESH.FT_Warping3D,
Compare=SMESH.FT_MoreThan,
Threshold=1,
Tolerance=1e-07)
# Check the group has some elements
assert gr_warp3D.Size() > 0
# create a mesh with the faces of the hexaedra thanks to medcoupling
umesh_3D = Mesh_1.ExportMEDCoupling()[0]
# create faces
umesh_2D,d0,d1,d2,d3=umesh_3D.buildDescendingConnectivity()
# export the 2D mesh in a tmp file
tmp_filename = getTmpFileName("med")
umesh_2D.write(tmp_filename)
# import it in SMESH
([Mesh_faces], status) = smesh.CreateMeshesFromMED( tmp_filename )
gr_warp2D = Mesh_faces.MakeGroup("warp2D",
SMESH.FACE,
CritType=SMESH.FT_Warping,
Compare=SMESH.FT_MoreThan,
Threshold=1,
Tolerance=1e-07)
# check max Warp3D
max_warp2D = Mesh_faces.GetMinMax(SMESH.FT_Warping)[1]
print("max_warp2D: ", max_warp2D)
assert max_warp2D > 1
assert abs(max_warp2D-max_warp3D)/max_warp2D < 1e-5
os.remove(tmp_filename)
if salome.sg.hasDesktop():
salome.sg.updateObjBrowser()

View File

@ -47,6 +47,7 @@ SET(BAD_TESTS
SMESH_box_tetra.py
SMESH_controls.py
SMESH_controls_scaled_jacobian.py
SMESH_controls_3D_warping.py
SMESH_fixation_netgen.py
SMESH_fixation_tetra.py
SMESH_flight_skin.py