--- /dev/null
+# 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))
--- /dev/null
+# 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)
* :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`
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
**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
: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>`
--- /dev/null
+.. _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.
{
FT_AspectRatio,
FT_AspectRatio3D,
- FT_Warping,
+ FT_Warping,
+ FT_Warping3D,
FT_MinimumAngle,
FT_Taper,
FT_Skew,
interface AspectRatio : NumericalFunctor{};
interface AspectRatio3D : NumericalFunctor{};
interface Warping : NumericalFunctor{};
+ interface Warping3D : NumericalFunctor {};
interface Taper : NumericalFunctor{};
interface Skew : NumericalFunctor{};
interface Area : NumericalFunctor{};
AspectRatio CreateAspectRatio();
AspectRatio3D CreateAspectRatio3D();
Warping CreateWarping();
+ Warping3D CreateWarping3D();
Taper CreateTaper();
Skew CreateSkew();
Area CreateArea();
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,
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]
}
+//================================================================================
+/*
+ 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
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;
/*
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();
my1DExtActor->SetExtControlMode(myFunctor,myScalarBarActor,myLookupTable);
UpdateDistribution();
break;
+ case eWarping3D:
+ my2DExtActor->SetExtControlMode(myFunctor, myScalarBarActor, myLookupTable);
+ UpdateDistribution();
+ break;
default:
myControlActor->SetControlMode(myFunctor,myScalarBarActor,myLookupTable);
UpdateDistribution();
case eBareBorderFace:
case eOverConstrainedFace:
case eCoincidentElems2D:
+ case eWarping3D:
my2DExtActor->VisibilityOn();
break;
case eBareBorderVolume:
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();
}
+// 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*/)
+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
// 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
// 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();
}
}
class vtkUnstructuredGrid;
class SMESH_ScalarBarActor;
+class SMESH_DeviceActor;
class vtkPlane;
class vtkImplicitBoolean;
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,
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;
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);
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();
}
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() ) )
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 );
case SMESHOp::OpMaxElementLength2D:
case SMESHOp::OpEqualFace:
case SMESHOp::OpAspectRatio3D:
+ case SMESHOp::OpWarping3D:
case SMESHOp::OpVolume:
case SMESHOp::OpScaledJacobian:
case SMESHOp::OpMaxElementLength3D:
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 );
<< 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() );
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 );
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 );
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 );
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 ||
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:
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:
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");
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:
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
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;
case SMESH_Actor::eAspectRatio3D:
case SMESH_Actor::eMinimumAngle:
case SMESH_Actor::eWarping:
+ case SMESH_Actor::eWarping3D:
case SMESH_Actor::eSkew:
result = true;
break;
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;
case SMESH::FT_Warping:
functor = manager->CreateWarping();
break;
+ case SMESH::FT_Warping3D:
+ functor = manager->CreateWarping3D();
+ break;
case SMESH::FT_MinimumAngle:
functor = manager->CreateMinimumAngle();
break;
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
// - 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.
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 );
}
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
}
+ 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();
case SMESH::FT_Warping:
aFunctor = aFilterMgr->CreateWarping();
break;
+ case SMESH::FT_Warping3D:
+ aFunctor = aFilterMgr->CreateWarping3D();
+ break;
case SMESH::FT_MinimumAngle:
aFunctor = aFilterMgr->CreateMinimumAngle();
break;
{
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";
{
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;
"FT_AspectRatio",
"FT_AspectRatio3D",
"FT_Warping",
+ "FT_Warping3D",
"FT_MinimumAngle",
"FT_Taper",
"FT_Skew",
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();
+ };
+
/*
AspectRatio_ptr CreateAspectRatio();
AspectRatio3D_ptr CreateAspectRatio3D();
Warping_ptr CreateWarping();
+ Warping3D_ptr CreateWarping3D();
Taper_ptr CreateTaper();
Skew_ptr CreateSkew();
Area_ptr CreateArea();
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;
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:
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.
--- /dev/null
+#!/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()
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