Salome HOME
[bos #32739][CEA] 3D warp 35/head
authorasozinov <alexey.sozinov@opencascade.com>
Mon, 15 May 2023 15:14:50 +0000 (16:14 +0100)
committermbs <martin.bernhard@opencascade.com>
Fri, 1 Mar 2024 20:10:57 +0000 (20:10 +0000)
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

30 files changed:
doc/examples/filters_ex41.py [new file with mode: 0644]
doc/examples/quality_controls_ex23.py [new file with mode: 0644]
doc/gui/images/image_warping3D.jpg [new file with mode: 0644]
doc/gui/input/about_quality_controls.rst
doc/gui/input/tui_filters.rst
doc/gui/input/tui_quality_controls.rst
doc/gui/input/warping_3d.rst [new file with mode: 0644]
idl/SMESH_Filter.idl
src/Controls/SMESH_Controls.cxx
src/Controls/SMESH_ControlsDef.hxx
src/OBJECT/SMESH_Actor.cxx
src/OBJECT/SMESH_Actor.h
src/OBJECT/SMESH_ActorDef.h
src/OBJECT/SMESH_DeviceActor.cxx
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_FilterDlg.cxx
src/SMESHGUI/SMESHGUI_MeshInfo.cxx
src/SMESHGUI/SMESHGUI_Operations.h
src/SMESHGUI/SMESHGUI_Selection.cxx
src/SMESHGUI/SMESHGUI_SelectionProxy.cxx
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHGUI/SMESH_msg_fr.ts
src/SMESHGUI/SMESH_msg_ja.ts
src/SMESH_I/SMESH_2smeshpy.cxx
src/SMESH_I/SMESH_Filter_i.cxx
src/SMESH_I/SMESH_Filter_i.hxx
src/SMESH_I/SMESH_PythonDump.cxx
src/SMESH_SWIG/smeshBuilder.py
test/SMESH_controls_3D_warping.py [new file with mode: 0644]
test/tests.set

diff --git a/doc/examples/filters_ex41.py b/doc/examples/filters_ex41.py
new file mode 100644 (file)
index 0000000..30fec54
--- /dev/null
@@ -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))
diff --git a/doc/examples/quality_controls_ex23.py b/doc/examples/quality_controls_ex23.py
new file mode 100644 (file)
index 0000000..f34704a
--- /dev/null
@@ -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)
diff --git a/doc/gui/images/image_warping3D.jpg b/doc/gui/images/image_warping3D.jpg
new file mode 100644 (file)
index 0000000..1795d1b
Binary files /dev/null and b/doc/gui/images/image_warping3D.jpg differ
index 7c7250b48a2a5b6de4d3af7a17ec845589629426..1c48d1657b1983108732bc07dcef52e97511f64e 100644 (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
index 314defd3104569855aa3d199b00c3042e6975dc6..db22d5ecf621baee283e777d969ab82189039d9b 100644 (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
index 69d77049390f01fc9517e7b3801f27691707ffed..478b8073ea20e81f60cbc33c05c4a446f2164c25 100644 (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>`
diff --git a/doc/gui/input/warping_3d.rst b/doc/gui/input/warping_3d.rst
new file mode 100644 (file)
index 0000000..6050357
--- /dev/null
@@ -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.
index 4876d8d00ab3440b1cbdb91b29192edfbea97018..05cfa6dc43a1c3e7f6d193944f233abdff67f5d1 100644 (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();
index 92c6166064e24d0e0df7f13620ee8b94784e7e5c..57855777584e688899d0d94b68d9c5e5086ef901 100644 (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
index d6456eab461ebd6ef8186ee9753b45a55150c5e5..456f4b30a8237473853594b5fff070764367d0e6 100644 (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;
   
   
     /*
index 8e21c3d5a25bcfab6350271fa9b65b05d18fc90f..2799e4494d5292f79b638af2bc02776369c57507 100644 (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()
 
 }
 
+// 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
@@ -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();
   }
 }
 
index 9dc3e579c74484edbbfab4c913e8227daf642b77..15519a24cd4e1234a151c6d882d823df1170650b 100644 (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;
index bb53280c1f89f5c37d59e6489252e86dc0cb79bb..49a326b69486e75c7968cd27f80f7e6d64140b2a 100644 (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);
index 313f73801d9a7e93f018c3cfaabfd1441df3b4aa..be17fe3c30317da05193bf43c17d083e1e28f2d5 100644 (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();
     }
index aa02081d9db7cb5b47bde706ab6392e9527588eb..69cbc7390bcfaa078d777a057ee03f7710147467 100644 (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 );
index a01f2a9a1327ca1e65d6c7b3f9996cc558d82a10..98439f06eb8ec44f0db59006c5218bd8fda6d8c7 100644 (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");
index 2aef4b2d274bff64aa99702c04f0ced8a644daa1..24c610d783233a1976abede0dbb3a83fbff5d3af 100644 (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:
index 6ae97b6e426f1b2c8d18b259c8caafff71e52821..bdf6e7382f98a3b7e514e4c86da706fba4f2316b 100644 (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
index dad61903249c9c7fb3d5879f853c070f9e1f0a3f..5669e9eadec03e0b298b6f7d1e487d18b00ea402 100644 (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;
index a555136fdfe9c7f1fd4eb6eb8991cb4832a4b491..6d7afa4e3cc2ca98bc384b177aa35eb236105ea1 100644 (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;
index 48c73b054a70788b004922d6bb29d646e00d703e..8c6f0359b72e5b87e5881e075b76c175bddd5914 100644 (file)
         <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>
@@ -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>
index 96818910a04de0586074711d967aa35f206645db..9d00671aea312585b76d9d77c7b71165ba880031 100644 (file)
         <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>
index 07b8fcef0b7370679e06b1edd188ce9f73205d8d..a2704dba5e187ed04baa9b81ad972d603ea1db71 100644 (file)
       <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>
index 06d536b85f22d18082425acdb930d06583d11a80..5d6fbc10f571c72a28ff4ee9bc7cbe2136d22729 100644 (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 );
     }
index a38f03943d5d726b9339b1e0c781acadd136d393..5448c6699586ad36f3b6069ef7095aaaafeffca7 100644 (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",
index 54f0f9c09692f473400fe73dbf385865e2c82790..94162013477eda9d3536e1ab94c0d86e44728515 100644 (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();
index f388424ed9c9ca23581108b6aa41a96e58700f36..a07d95377541553de0a6f8d8a0ab397c24008872 100644 (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;
index 9d32e76fa0e25e18e9f345725f6a16e54c747428..1bb9a251bb4d0fa662a8fc079ed3dad6e83b453b 100644 (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.
diff --git a/test/SMESH_controls_3D_warping.py b/test/SMESH_controls_3D_warping.py
new file mode 100644 (file)
index 0000000..ce792d4
--- /dev/null
@@ -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()
index 66a2564f745fcdd96a9ad630e1f86b8c1a68850a..fb8380f908f00b792b9d269fd415d5b3238dfc62 100644 (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