Salome HOME
#19926 [CEA 19782] renumbering meshes
authoreap <eap@opencascade.com>
Fri, 9 Oct 2020 08:44:21 +0000 (11:44 +0300)
committereap <eap@opencascade.com>
Thu, 15 Oct 2020 13:57:54 +0000 (16:57 +0300)
34 files changed:
doc/salome/examples/filters_ex39.py
doc/salome/gui/SMESH/images/block_renumber_hyp.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/3d_meshing_hypo.rst [new file with mode: 0644]
doc/salome/gui/SMESH/input/about_hypo.rst
doc/salome/gui/SMESH/input/max_element_volume_hypo.rst [deleted file]
doc/salome/gui/SMESH/input/tui_defining_hypotheses.rst
idl/SMESH_BasicHypothesis.idl
resources/CMakeLists.txt
resources/StdMeshers.xml.in
resources/mesh_tree_hypo_renumber.png [new file with mode: 0644]
src/SMESH/SMESH_Mesh.cxx
src/SMESH/SMESH_Mesh.hxx
src/SMESH_I/SMESH_Gen_i.hxx
src/SMESH_I/SMESH_Gen_i_1.cxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_SWIG/StdMeshersBuilder.py
src/SMESH_SWIG/smeshBuilder.py
src/StdMeshers/CMakeLists.txt
src/StdMeshers/StdMeshers_BlockRenumber.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_BlockRenumber.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_CompositeHexa_3D.cxx
src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx
src/StdMeshers/StdMeshers_Hexa_3D.cxx
src/StdMeshers/StdMeshers_Hexa_3D.hxx
src/StdMeshersGUI/CMakeLists.txt
src/StdMeshersGUI/StdMeshersGUI.cxx
src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.cxx [new file with mode: 0644]
src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.h [new file with mode: 0644]
src/StdMeshersGUI/StdMeshers_images.ts
src/StdMeshersGUI/StdMeshers_msg_en.ts
src/StdMeshers_I/CMakeLists.txt
src/StdMeshers_I/StdMeshers_BlockRenumber_i.cxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_BlockRenumber_i.hxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_i.cxx

index 2d3c907d680ea0ded5c26b849be95fc55ad3d6ca..6a2ddd5077618c33daeec7572df1b237191d01ae 100644 (file)
@@ -1,4 +1,4 @@
-# Elements of a domain
+# "Elements of a domain" filter and "Renumber" hypothesis
 
 import salome, SMESH
 salome.salome_init()
@@ -22,7 +22,15 @@ mesh = smesh.Mesh( boxes )
 mesh.Segment(box1).NumberOfSegments( 5 )  # to have different nb of elements on the boxes
 mesh.Segment(box2).NumberOfSegments( 10 )
 mesh.Quadrangle()
-mesh.Hexahedron()
+ijkAlgo = mesh.Hexahedron()
+
+# Use Renumber hypothesis to get hexahedra and nodes numbered like in a structured mesh.
+# k axis of box1 will be ( 100,100,0 ) - ( 100,100,100 )
+# k axis of box2 will be ( 0,0,0 ) - (0,0,100), by default
+v000 = geompy.MakeVertex( 100,100,0, theName='v000' ) # can use box sub-vertex or standalone one
+v001 = geompy.GetVertexNearPoint( box1, geompy.MakeVertex(100,100,100), theName='v001')
+ijkAlgo.Renumber([ smeshBuilder.BlockCS( box1, v000, v001 ) ])
+
 mesh.Compute()
 
 # Create filters with FT_ConnectedElements criterion by pointing a domain in different ways:
diff --git a/doc/salome/gui/SMESH/images/block_renumber_hyp.png b/doc/salome/gui/SMESH/images/block_renumber_hyp.png
new file mode 100644 (file)
index 0000000..4c610f7
Binary files /dev/null and b/doc/salome/gui/SMESH/images/block_renumber_hyp.png differ
diff --git a/doc/salome/gui/SMESH/input/3d_meshing_hypo.rst b/doc/salome/gui/SMESH/input/3d_meshing_hypo.rst
new file mode 100644 (file)
index 0000000..bef317c
--- /dev/null
@@ -0,0 +1,42 @@
+.. _a3d_meshing_hypo_page:
+
+*********************
+3D Meshing Hypotheses
+*********************
+
+.. _max_element_volume_hypo:
+
+Max Element Volume hypothesis
+#############################
+
+**Max Element Volume** hypothesis is applied for meshing of 3D objects composing your geometrical object. Definition of this hypothesis consists of setting the **maximum volume** of 3D meshing elements (depending on the chosen meshing algorithm it can be **hexahedrons** or **tetrahedrons**), which will compose the mesh of these 3D objects.
+
+.. image:: ../images/a-maxelvolume.png
+       :align: center
+
+**See Also** a sample TUI Script of a :ref:`tui_max_element_volume` operation.  
+
+.. _block_renumber_hypo:
+
+Renumber hypothesis
+###################
+
+**Renumber** hypothesis is applied for meshing of 3D objects along with **Hexahedron (i,j,k)** algorithm.
+
+Order and hence numbering of hexahedral elements in the structured mesh generated by **Hexahedron (ijk)** algorithm depends on the order of faces in a block geometry. Nodes are not in a structured order, since geometrical edges and faces are discretized before construction of hexahedra. **Renumber** hypothesis allows for getting hexahedra and nodes ordered like in a structured grid.
+
+.. image:: ../images/block_renumber_hyp.png
+       :align: center
+
+**Renumber** hypothesis allows to define direction of **i, j** and **k** axes of a block. For that you specify two vertices of the block
+
+* **Vertex (0,0,0)** located at the origin of the block local coordinate system.
+* **Vertex (0,0,1)** located at the end of **k** axis of the block.
+
+Axes **i** and **j** are found automatically using the right-hand rule.
+
+For blocks with edges parallel to the axes of global coordinate system, their local coordinate system by default is defined as having axes parallel to the global ones. So, for such blocks specification of vertices is optional, it is enough just to assign **Renumber** hypothesis.
+
+**See Also** a sample TUI Script of a :ref:`tui_block_renumber` operation.  
+
+
index df935f3d7cd7c54623e343c48937a708ad82eff4..a4609d905e847548760ca927ce0bee446e6b3768 100644 (file)
@@ -16,7 +16,7 @@ In **MESH** there are:
 
 * :ref:`a1d_meshing_hypo_page` for meshing of **edges**
 * :ref:`a2d_meshing_hypo_page` for meshing of **faces**
-* :ref:`3D Hypothesis <max_element_volume_hypo_page>` for meshing of **volumes**
+* :ref:`a3d_meshing_hypo_page` for meshing of **volumes**
 * :ref:`additional_hypo_page`
 
 **Table of Contents**
@@ -26,6 +26,6 @@ In **MESH** there are:
 
    1d_meshing_hypo.rst
    2d_meshing_hypo.rst
-   3D: Max Element Volume hypothesis <max_element_volume_hypo>
+   3d_meshing_hypo.rst
    additional_hypo.rst 
 
diff --git a/doc/salome/gui/SMESH/input/max_element_volume_hypo.rst b/doc/salome/gui/SMESH/input/max_element_volume_hypo.rst
deleted file mode 100644 (file)
index 5f835fc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-.. _max_element_volume_hypo_page:
-
-*****************************
-Max Element Volume hypothesis
-*****************************
-
-**Max Element Volume** hypothesis is applied for meshing of 3D objects composing your geometrical object. Definition of this hypothesis consists of setting the **maximum volume** of 3D meshing elements (depending on the chosen meshing algorithm it can be **hexahedrons** or **tetrahedrons**), which will compose the mesh of these 3D objects.
-
-.. image:: ../images/a-maxelvolume.png
-       :align: center
-
-**See Also** a sample TUI Script of a :ref:`tui_max_element_volume` operation.  
-
-
index facc0fdc13cc2c1bdde740ba7299a4cecb589f3b..fd676a358e6d740c04f833dd9fb1e454e744a1d9 100644 (file)
@@ -34,6 +34,10 @@ and hypotheses.
     *  :ref:`tui_max_element_volume` hypothesis 
     *  :ref:`Viscous layers <tui_viscous_layers>` hypotheses
 
+* Hexahedron (i,j,k) 3D algorithm
+
+   *   :ref:`tui_block_renumber`
+
 * :ref:`tui_projection`
 * :ref:`Extrusion 3D <tui_prism_3d_algo>` algorithm
 * :ref:`Radial Prism <tui_radial_prism>` algorithm
@@ -136,6 +140,16 @@ Length from Edges
 
 :download:`Download this script <../../../examples/defining_hypotheses_ex07.py>`
 
+.. _tui_block_renumber:
+
+Renumber 3D hypothesis
+======================
+
+.. literalinclude:: ../../../examples/filters_ex39.py
+    :language: python
+
+:download:`Download this script <../../../examples/filters_ex39.py>`
+
 Defining Additional Hypotheses
 ##############################
 
index 0f7edc5f698d0765abb4e4fc553ea55fc312a281..a6b6882ccc99a9fbd7802f857b1fd105ca3cfd4d 100644 (file)
@@ -1089,6 +1089,25 @@ module StdMeshers
       raises (SALOME::SALOME_Exception);
   };
 
+
+  /*!
+   * interface of "Renumber" hypothesis used by Hexahedron(ijk) algorithm
+   * to renumber mesh of a block to be structured-like
+   */
+  struct BlockCS // Local coordinate system of a block
+  {
+    GEOM::GEOM_Object solid;
+    GEOM::GEOM_Object vertex000;
+    GEOM::GEOM_Object vertex001;
+  };
+  typedef sequence<BlockCS> blockcs_array;
+
+  interface StdMeshers_BlockRenumber : SMESH::SMESH_Hypothesis
+  {
+    void SetBlocksOrientation( in blockcs_array blockCS );
+    blockcs_array GetBlocksOrientation();
+  };
+
   /*!
    * StdMeshers_SegmentAroundVertex_0D: interface of "SegmentAroundVertex" algorithm
    */
index fe0d107fb5e685da12fc84f2624e8c2b0b2bcea5..1a5619a10d4baf262bff2e3f5fec2e8b53d7d632 100644 (file)
@@ -203,6 +203,7 @@ SET(SMESH_RESOURCES_FILES
   mesh_tree_hypo_projection_2d.png
   mesh_tree_hypo_projection_3d.png
   mesh_tree_hypo_quadratic.png
+  mesh_tree_hypo_renumber.png
   mesh_tree_hypo_segment.png
   mesh_tree_hypo_source_3d_shape.png
   mesh_tree_hypo_source_edge.png
index d70cdd45e452b58ccbbfebcb10353bba9e7672f4..8baf92e0af5eff02e15c683882642a7663bd2f9a 100644 (file)
                 icon-id  ="mesh_hypo_length.png"
                 dim      ="3"/>
 
+    <hypothesis type     ="BlockRenumber"
+                label-id ="Renumber"
+                icon-id  ="mesh_hypo_renumber.png"
+                dim      ="3"/>
+
   </hypotheses>
 
   <algorithms>
                input    ="QUAD"
                output   ="HEXA,PENTA"
               need-geom="false"
+               hypos    ="BlockRenumber"
                opt-hypos="ViscousLayers"
                dim      ="3">
       <python-wrap>
         <algo>Hexa_3D=Hexahedron(algo=smeshBuilder.Hexa)</algo>
         <hypo>ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetFaces(1),SetFaces(2),SetMethod(),SetGroupName())</hypo>
+        <hypo>BlockRenumber=Renumber(GetBlocksOrientation())</hypo>
       </python-wrap>
     </algorithm>
 
diff --git a/resources/mesh_tree_hypo_renumber.png b/resources/mesh_tree_hypo_renumber.png
new file mode 100644 (file)
index 0000000..0d2714f
Binary files /dev/null and b/resources/mesh_tree_hypo_renumber.png differ
index 2f8846f96bee608ee8f6e071b83a3c27204db8ff..e71853f0f646711e99def985c04d1b5fcde15f82 100644 (file)
@@ -2024,6 +2024,16 @@ bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
 }
 
+//=======================================================================
+//function : GetShapeByEntry
+//purpose  : return TopoDS_Shape by its study entry
+//=======================================================================
+
+TopoDS_Shape SMESH_Mesh::GetShapeByEntry(const std::string& entry) const
+{
+  return _callUp ? _callUp->GetShapeByEntry( entry ) : TopoDS_Shape();
+}
+
 //=============================================================================
 /*!
  *  
index 27b54ed47ba6b36841c32ba5fde5b75011aab5cb..18c11c894a6b61c1b43fade9ef5f96f87a3d620e 100644 (file)
@@ -214,6 +214,9 @@ class SMESH_EXPORT SMESH_Mesh
   bool IsNotConformAllowed() const;
   
   bool IsMainShape(const TopoDS_Shape& theShape) const;
+
+  TopoDS_Shape GetShapeByEntry(const std::string& entry) const;
+
   /*!
    * \brief Return list of ancestors of theSubShape in the order
    *        that lower dimension shapes come first
@@ -342,6 +345,7 @@ class SMESH_EXPORT SMESH_Mesh
     virtual void HypothesisModified( int hypID, bool updateIcons )=0;
     virtual void Load()=0;
     virtual bool IsLoaded()=0;
+    virtual TopoDS_Shape GetShapeByEntry(const std::string& entry)=0;
     virtual ~TCallUp() {}
   };
   void SetCallUp( TCallUp * upCaller );
index d6cb5b130647cc5b9a84acfd0fc200f398520757..3c2e62f5d6ed41c91c174cae2f94defa42a87996 100644 (file)
@@ -116,13 +116,15 @@ public:
   // Get CORBA object corresponding to the SALOMEDS::SObject
   static CORBA::Object_var SObjectToObject( SALOMEDS::SObject_ptr theSObject );
   // Get the SALOMEDS::SObject corresponding to a CORBA object
-  static SALOMEDS::SObject_ptr ObjectToSObject(CORBA::Object_ptr theObject);
+  static SALOMEDS::SObject_ptr ObjectToSObject( CORBA::Object_ptr theObject );
   // Get the SALOMEDS::Study from naming service
   static SALOMEDS::Study_var getStudyServant();
   // Get GEOM Object corresponding to TopoDS_Shape
-  GEOM::GEOM_Object_ptr ShapeToGeomObject (const TopoDS_Shape& theShape );
+  static GEOM::GEOM_Object_ptr ShapeToGeomObject( const TopoDS_Shape& theShape );
   // Get TopoDS_Shape corresponding to GEOM_Object
-  TopoDS_Shape GeomObjectToShape(GEOM::GEOM_Object_ptr theGeomObject);
+  static TopoDS_Shape GeomObjectToShape( GEOM::GEOM_Object_ptr theGeomObject );
+  // Get GEOM Object by its study entry
+  static GEOM::GEOM_Object_ptr GetGeomObjectByEntry( const std::string& entry );
 
   // Default constructor
   SMESH_Gen_i();
index 4c78e23167b83c632d3dcaf13a2b4473ef68c776..d7d61bcafd70381b50a07fb5ca2d8194e28289cd 100644 (file)
@@ -236,8 +236,8 @@ template<typename T> static inline T* objectToServant( CORBA::Object_ptr theIOR
 GEOM::GEOM_Object_ptr SMESH_Gen_i::ShapeToGeomObject (const TopoDS_Shape& theShape )
 {
   GEOM::GEOM_Object_var aShapeObj;
-  if ( !theShape.IsNull() ) {
-    GEOM_Client* aClient = GetShapeReader();
+  if ( !theShape.IsNull() && mySMESHGen ) {
+    GEOM_Client* aClient = mySMESHGen->GetShapeReader();
     TCollection_AsciiString IOR;
     if ( aClient && aClient->Find( theShape, IOR ))
     {
@@ -257,9 +257,9 @@ GEOM::GEOM_Object_ptr SMESH_Gen_i::ShapeToGeomObject (const TopoDS_Shape& theSha
 TopoDS_Shape SMESH_Gen_i::GeomObjectToShape(GEOM::GEOM_Object_ptr theGeomObject)
 {
   TopoDS_Shape S;
-  if ( !theGeomObject->_is_nil() && !theGeomObject->_non_existent() )
+  if ( mySMESHGen && !theGeomObject->_is_nil() && !theGeomObject->_non_existent() )
   {
-    GEOM_Client*           aClient = GetShapeReader();
+    GEOM_Client*           aClient = mySMESHGen->GetShapeReader();
     GEOM::GEOM_Gen_var aGeomEngine = GetGeomEngine( theGeomObject );
     if ( aClient && !aGeomEngine->_is_nil () )
       S = aClient->GetShape( aGeomEngine, theGeomObject );
@@ -267,6 +267,25 @@ TopoDS_Shape SMESH_Gen_i::GeomObjectToShape(GEOM::GEOM_Object_ptr theGeomObject)
   return S;
 }
 
+//================================================================================
+/*!
+ * \brief Get GEOM Object by its study entry
+ */
+//================================================================================
+
+GEOM::GEOM_Object_ptr SMESH_Gen_i::GetGeomObjectByEntry( const std::string& entry )
+{
+  GEOM::GEOM_Object_var go;
+  if ( !entry.empty() && mySMESHGen )
+  {
+    SALOMEDS::SObject_wrap so = mySMESHGen->getStudyServant()->FindObjectID( entry.c_str() );
+    CORBA::Object_var     obj = SObjectToObject( so );
+    go = GEOM::GEOM_Object::_narrow( obj );
+  }
+  return go._retn();
+}
+
+
 //=======================================================================
 //function : publish
 //purpose  :
index 2e9130d676a3405e236846906bc912004d1efb7f..8a4313de59b324bccd92a775f058d82c58e3fcad 100644 (file)
@@ -3435,12 +3435,17 @@ namespace
   {
     SMESH_Mesh_i* _mesh;
     TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
-    virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
-    virtual void HypothesisModified( int hypID,
-                                     bool updIcons) { _mesh->onHypothesisModified( hypID,
-                                                                                   updIcons ); }
-    virtual void Load ()                            { _mesh->Load(); }
-    virtual bool IsLoaded()                         { return _mesh->IsLoaded(); }
+    void RemoveGroup (const int theGroupID) override { _mesh->removeGroup( theGroupID ); }
+    void HypothesisModified( int hypID,
+                             bool updIcons) override { _mesh->onHypothesisModified( hypID,
+                                                                                    updIcons ); }
+    void Load ()                            override { _mesh->Load(); }
+    bool IsLoaded()                         override { return _mesh->IsLoaded(); }
+    TopoDS_Shape GetShapeByEntry(const std::string& entry) override
+    {
+      GEOM::GEOM_Object_var go = SMESH_Gen_i::GetGeomObjectByEntry( entry );
+      return SMESH_Gen_i::GeomObjectToShape( go );
+    }
   };
 }
 
index 14bf304146377a5f6e19c798a964f5ec679f7236..0759332e9b0ea599ba10749532a8027d4aae8240 100644 (file)
@@ -916,8 +916,17 @@ class StdMeshersBuilder_Hexahedron(Mesh_Algorithm):
         """
         Mesh_Algorithm.__init__(self)
         self.Create(mesh, geom, Hexa)
+        self.renumHypothesis = 0
         pass
 
+    def Renumber(self, blockCSList=[] ):
+        if isinstance( blockCSList, StdMeshers.BlockCS ):
+            blockCSList = [blockCSList]
+        if not self.renumHypothesis:
+            self.renumHypothesis = self.Hypothesis("BlockRenumber", blockCSList, UseExisting=0)
+        self.renumHypothesis.SetBlocksOrientation( blockCSList )
+        return self.renumHypothesis
+
     pass # end of StdMeshersBuilder_Hexahedron class
 
 class StdMeshersBuilder_Projection1D(Mesh_Algorithm):
index 21456eed4fa3dfa94caf9f422c7606214f39f0e6..b40bc6d1eea57f812cdb8ec5e10a3d48313cd31e 100644 (file)
@@ -38,8 +38,9 @@ SMESH.MED_MINOR_7 = 27 # back compatibility
 SMESH.MED_MINOR_8 = 28 # back compatibility
 SMESH.MED_MINOR_9 = 29 # back compatibility
 
-from   SMESH import *
-from   salome.smesh.smesh_algorithm import Mesh_Algorithm
+from SMESH import *
+from salome.smesh.smesh_algorithm import Mesh_Algorithm
+from StdMeshers import BlockCS
 
 import SALOME
 import SALOMEDS
index 87e4db8ebcc8929e4e19d5af901ca0f23e1bdcd6..3f7dc1af79af37fc0fc7621c81d4527bdc48e2b7 100644 (file)
@@ -64,6 +64,7 @@ SET(_link_LIBRARIES
   SMESHDS
   SMESHUtils
   ${TBB_LIBS}
+  ${Boost_LIBRARIES}
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
@@ -131,6 +132,7 @@ SET(StdMeshers_HEADERS
   StdMeshers_QuadFromMedialAxis_1D2D.hxx
   StdMeshers_PolygonPerFace_2D.hxx
   StdMeshers_PolyhedronPerSolid_3D.hxx
+  StdMeshers_BlockRenumber.hxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
@@ -197,6 +199,7 @@ SET(StdMeshers_SOURCES
   StdMeshers_QuadFromMedialAxis_1D2D.cxx
   StdMeshers_PolygonPerFace_2D.cxx
   StdMeshers_PolyhedronPerSolid_3D.cxx
+  StdMeshers_BlockRenumber.cxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
diff --git a/src/StdMeshers/StdMeshers_BlockRenumber.cxx b/src/StdMeshers/StdMeshers_BlockRenumber.cxx
new file mode 100644 (file)
index 0000000..bc2e63a
--- /dev/null
@@ -0,0 +1,324 @@
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : StdMeshers_BlockRenumber.cxx
+//  Author : Edward AGAPOV, OCC
+//  Module : SMESH
+
+#include "StdMeshers_BlockRenumber.hxx"
+
+#include "SMDS_EdgePosition.hxx"
+#include "SMDS_FacePosition.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESHDS_SubMesh.hxx"
+#include "SMESH_Algo.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_TryCatch.hxx"
+
+#include <BRep_Tool.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopoDS.hxx>
+
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+
+//=============================================================================
+/*!
+ * Constructor 
+ */
+//=============================================================================
+
+StdMeshers_BlockRenumber::StdMeshers_BlockRenumber(int hypId, SMESH_Gen * gen)
+  :SMESH_Hypothesis(hypId, gen)
+{
+  _name = "BlockRenumber";
+  _param_algo_dim = 3; // is used by StdMeshers_Hexa_3D and StdMeshers_CompositeHexa_3D
+}
+
+//================================================================================
+/*!
+ * \brief Set local CS of blocks
+ */
+//================================================================================
+
+void StdMeshers_BlockRenumber::SetBlocksOrientation( std::vector< StdMeshers_BlockCS > & blockCS )
+{
+  if ( _blockCS != blockCS )
+  {
+    NotifySubMeshesHypothesisModification();
+    _blockCS.swap( blockCS );
+    _solids2vertices.Clear();
+  }
+}
+
+//================================================================================
+/*
+ * Return true and vertices if block orientation is defined for a given solid
+ */
+//================================================================================
+
+bool StdMeshers_BlockRenumber::IsSolidIncluded( SMESH_Mesh&         mesh,
+                                                const TopoDS_Shape& solid,
+                                                TopoDS_Vertex&      vertex000,
+                                                TopoDS_Vertex&      vertex001 ) const
+{
+  bool result = false;
+  vertex000.Nullify();
+  vertex001.Nullify();
+
+  if ( _solids2vertices.IsEmpty() )
+  {
+    StdMeshers_BlockRenumber* me = const_cast<StdMeshers_BlockRenumber*>(this);
+    for ( StdMeshers_BlockCS& bcs : me->_blockCS )
+    {
+      TopoDS_Shape so   = mesh.GetShapeByEntry( bcs._solid );
+      TopoDS_Shape s000 = mesh.GetShapeByEntry( bcs._vertex000 );
+      TopoDS_Shape s001 = mesh.GetShapeByEntry( bcs._vertex001 );
+      TopoDS_Vertex v000 = StdMeshers_RenumberHelper::GetVertexAtPoint( so, s000 );
+      TopoDS_Vertex v001 = StdMeshers_RenumberHelper::GetVertexAtPoint( so, s001 );
+      if ( !v000.IsNull() && !v001.IsNull() )
+      {
+        me->_solids2vertices.Bind( so, std::make_pair( v000, v001 ));
+        if ( so.IsSame( solid ))
+        {
+          result = true;
+          vertex000 = v000;
+          vertex001 = v001;
+        }
+      }
+    }
+  }
+  else if ( !solid.IsNull() )
+  {
+    if (( result = _solids2vertices.IsBound( solid )))
+    {
+      auto vvPairPtr = _solids2vertices.Seek( solid );
+      vertex000 = vvPairPtr->first;
+      vertex001 = vvPairPtr->second;
+    }
+  }
+  return result;
+}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose  : 
+//=======================================================================
+
+SMESH_ComputeErrorPtr StdMeshers_BlockRenumber::CheckHypothesis(SMESH_Mesh&         aMesh,
+                                                                const TopoDS_Shape& aShape) const
+{
+  SMESH_Comment errorTxt;
+  for ( size_t i = 0; i < _blockCS.size() &&  errorTxt.empty(); ++i )
+  {
+    TopoDS_Shape solid = aMesh.GetShapeByEntry( _blockCS[i]._solid );
+    TopoDS_Shape  v000 = aMesh.GetShapeByEntry( _blockCS[i]._vertex000 );
+    TopoDS_Shape  v001 = aMesh.GetShapeByEntry( _blockCS[i]._vertex001 );
+    v000 = StdMeshers_RenumberHelper::GetVertexAtPoint( solid, v000 );
+    v001 = StdMeshers_RenumberHelper::GetVertexAtPoint( solid, v001 );
+
+    if ( solid.IsNull() || solid.ShapeType() != TopAbs_SOLID )
+      errorTxt << "Can't find a SOLID by entry '" << _blockCS[i]._solid << "'";
+    else if ( v000.IsNull() || v000.ShapeType() != TopAbs_VERTEX )
+      errorTxt << "Can't find a VERTEX by entry '" << _blockCS[i]._vertex000 << "'";
+    else if ( v001.IsNull() || v001.ShapeType() != TopAbs_VERTEX )
+      errorTxt << "Can't find a VERTEX by entry '" << _blockCS[i]._vertex001 << "'";
+    else if ( !SMESH_MesherHelper::IsSubShape( v000, solid ))
+      errorTxt << "VERTEX '" << _blockCS[i]._vertex001 << "' does not belong to SOLID '"
+               << _blockCS[i]._solid << "'";
+    else if ( !SMESH_MesherHelper::IsSubShape( v001, solid ))
+      errorTxt << "VERTEX '" << _blockCS[i]._vertex001 << "' does not belong to SOLID '"
+               << _blockCS[i]._solid << "'";
+    else if ( SMESH_MesherHelper::Count( solid, TopAbs_VERTEX, true ) == 8 &&
+              SMESH_MesherHelper::GetCommonAncestor( v000, v001, aMesh, TopAbs_EDGE ).IsNull() )
+      errorTxt << "Vertices '" << _blockCS[i]._vertex000 << "' and '" << _blockCS[i]._vertex001
+               << "' are not connected by an edge";
+  }
+
+  SMESH_ComputeErrorPtr error;
+  if ( !errorTxt.empty() )
+  {
+    error = SMESH_ComputeError::New( COMPERR_BAD_PARMETERS,
+                                     SMESH_Comment("Renumber hypothesis: ") << errorTxt );
+  }
+  return error;
+}
+
+//=======================================================================
+//function : StdMeshers_RenumberHelper
+//purpose  : constructor
+//=======================================================================
+
+StdMeshers_RenumberHelper::StdMeshers_RenumberHelper( SMESH_Mesh&                     mesh,
+                                                      const StdMeshers_BlockRenumber* hyp)
+  : _mesh( &mesh ), _hyp( hyp ), _newOldNodes( 2, nullptr )
+{
+}
+
+//=======================================================================
+//function : GetVertex000
+//purpose  : Find default vertex at (0,0,0) local position
+//=======================================================================
+
+TopoDS_Vertex StdMeshers_RenumberHelper::GetVertex000( const TopTools_MapOfShape& cornerVertices )
+{
+  TopoDS_Vertex v000;
+  if ( cornerVertices.Extent() < 8 )
+    return TopoDS_Vertex();
+
+  double minVal = DBL_MAX, minX = DBL_MAX, val;
+  for ( auto it = cornerVertices.cbegin(); it != cornerVertices.cend(); ++it )
+  {
+    gp_Pnt P = BRep_Tool::Pnt( TopoDS::Vertex( *it ));
+    val = P.X() + P.Y() + P.Z();
+    if ( val < minVal || ( val == minVal && P.X() < minX ))
+    {
+      v000 = TopoDS::Vertex( *it );
+      minVal = val;
+      minX = P.X();
+    }
+  }
+  return v000;
+}
+
+//=======================================================================
+//function : GetVertex000
+//purpose  : Find default vertex at (0,0,0) local position
+//=======================================================================
+
+TopoDS_Vertex StdMeshers_RenumberHelper::GetVertexAtPoint( const TopoDS_Shape&  solid,
+                                                           const TopoDS_Shape& point )
+{
+  if ( !solid.IsNull() && !point.IsNull() && point.ShapeType() == TopAbs_VERTEX )
+  {
+    gp_Pnt   p = BRep_Tool::Pnt( TopoDS::Vertex( point ));
+    double tol = Precision::Confusion();
+    for ( TopExp_Explorer exp( solid, TopAbs_VERTEX ); exp.More(); exp.Next() )
+    {
+      const TopoDS_Vertex& v = TopoDS::Vertex( exp.Current() );
+      if ( v.IsSame( point ) || p.IsEqual( BRep_Tool::Pnt( v ), tol ))
+        return v;
+    }
+  }
+  return TopoDS_Vertex();
+}
+
+//================================================================================
+/*
+ * Create a copy of an old node and remember this couple of nodes for replacement
+ */
+//================================================================================
+
+void StdMeshers_RenumberHelper::AddReplacingNode( const SMDS_MeshNode* & oldNode )
+{
+  SMESHDS_Mesh*     mesh = _mesh->GetMeshDS();
+  SMESH_NodeXYZ   oldXYZ = oldNode;
+  SMDS_MeshNode* newNode = mesh->AddNode( oldXYZ.X(), oldXYZ.Y(), oldXYZ.Z() );
+  _newOldNodes.front() = newNode;
+  _newOldNodes.back()  = oldNode;
+  _nodesToMerge.push_back( _newOldNodes );
+  oldNode = newNode;
+
+  int               shapeID = oldXYZ->GetShapeID();
+  const TopoDS_Shape& shape = mesh->IndexToShape( shapeID );
+  if ( !shape.IsNull() )
+    switch ( shape.ShapeType() )
+    {
+    case TopAbs_FACE:
+      if ( SMDS_FacePositionPtr pos = oldXYZ->GetPosition() )
+        mesh->SetNodeOnFace( newNode, shapeID, pos->GetUParameter(), pos->GetVParameter() );
+      break;
+    case TopAbs_EDGE:
+      if ( SMDS_EdgePositionPtr pos = oldXYZ->GetPosition() )
+        mesh->SetNodeOnEdge( newNode, shapeID, pos->GetUParameter() );
+      break;
+    case TopAbs_VERTEX:
+      mesh->SetNodeOnVertex( newNode, shapeID );
+      break;
+    default:
+      mesh->SetNodeInVolume( newNode, shapeID );
+    }
+}
+
+//================================================================================
+/*
+ * Replace old nodes by new ones
+ */
+//================================================================================
+
+void StdMeshers_RenumberHelper::DoReplaceNodes()
+{
+  SMESH_MeshEditor( _mesh ).MergeNodes( _nodesToMerge );
+}
+
+//=============================================================================
+/*!
+ * Persistence
+ */
+//=============================================================================
+
+ostream & StdMeshers_BlockRenumber::SaveTo(ostream & save)
+{
+  boost::archive::text_oarchive archive( save );
+  archive << *this;
+
+  return save;
+}
+
+//=============================================================================
+/*!
+ * Persistence
+ */
+//=============================================================================
+
+istream & StdMeshers_BlockRenumber::LoadFrom(istream & load)
+{
+  SMESH_TRY;
+
+  boost::archive::text_iarchive archive( load );
+  archive >> *this;
+
+  SMESH_CATCH( SMESH::doNothing );
+
+  return load;
+}
+
+namespace boost {
+  namespace serialization {
+
+    //=======================================================================
+    //function : serialize
+    //purpose  : serialize StdMeshers_BlockCS
+    //=======================================================================
+
+    template<class Archive>
+    void serialize(Archive & ar, StdMeshers_BlockCS & blockCS, const unsigned int version)
+    {
+      ar & blockCS._solid;
+      ar & blockCS._vertex000;
+      ar & blockCS._vertex001;
+    }
+
+  } // namespace serialization
+} // namespace boost
diff --git a/src/StdMeshers/StdMeshers_BlockRenumber.hxx b/src/StdMeshers/StdMeshers_BlockRenumber.hxx
new file mode 100644 (file)
index 0000000..f68b17e
--- /dev/null
@@ -0,0 +1,170 @@
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementation of SMESH idl descriptions
+//  File   : StdMeshers_BlockRenumber.hxx
+//  Author : Edward AGAPOV, OCC
+//  Module : SMESH
+//
+#ifndef _SMESH_BlockRenumber_HXX_
+#define _SMESH_BlockRenumber_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+
+#include "SMESH_ComputeError.hxx"
+#include "SMESH_Hypothesis.hxx"
+#include "SMESH_MeshEditor.hxx"
+
+#include <NCollection_DataMap.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopoDS_Vertex.hxx>
+
+#include <boost/serialization/vector.hpp>
+#include <map>
+
+class SMESH_Mesh;
+class TopoDS_Shape;
+class TopoDS_TShape;
+class TopoDS_Vertex;
+
+// =========================================================
+struct StdMeshers_BlockCS // Local coordinate system of a block
+{
+  std::string _solid;
+  std::string _vertex000;
+  std::string _vertex001;
+
+  bool operator==( const StdMeshers_BlockCS& other ) const
+  {
+    return ( _solid     == other._solid &&
+             _vertex000 == other._vertex000 &&
+             _vertex001 == other._vertex001 );
+  }
+};
+
+// =========================================================
+/*!
+ * \class 3D Hypothesis used by Hexahedron(ijk) algorithm
+ *        to renumber mesh of a block to be structured-like 
+ */
+// =========================================================
+
+class STDMESHERS_EXPORT StdMeshers_BlockRenumber : public SMESH_Hypothesis
+{
+public:
+  StdMeshers_BlockRenumber(int hypId, SMESH_Gen * gen);
+
+  void SetBlocksOrientation( std::vector< StdMeshers_BlockCS > & blockCS );
+
+  const std::vector< StdMeshers_BlockCS > &  GetBlocksOrientation() const { return _blockCS; }
+
+  virtual std::ostream & SaveTo(std::ostream & save) override;
+  virtual std::istream & LoadFrom(std::istream & load) override;
+
+  /*!
+   * \brief Initialize Fineness by the mesh built on the geometry
+   *  \param theMesh - the built mesh
+   *  \param theShape - the geometry of interest
+   *  \retval bool - true if parameter values have been successfully defined
+   */
+  bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape) override
+  { return false; }
+
+  /*!
+   * \brief Initialize my parameter values by default parameters.
+   *  \retval bool - true if parameter values have been successfully defined
+   */
+  bool SetParametersByDefaults(const TDefaults&  dflts, const SMESH_Mesh* theMesh=0) override
+  { return false; }
+
+ public:
+
+  /*!
+   * \brief Check validity of parameter
+   */
+  SMESH_ComputeErrorPtr CheckHypothesis(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape) const;
+
+  /*!
+   * \brief Return true and vertices if block orientation is defined for a given solid
+   */
+  bool IsSolidIncluded( SMESH_Mesh&         mesh,
+                        const TopoDS_Shape& solid,
+                        TopoDS_Vertex&      vertex000,
+                        TopoDS_Vertex&      vertex001 ) const;
+
+ private:
+
+  // Persistence: define both input and output at once
+  friend class boost::serialization::access;
+  template<class Archive> void serialize( Archive & ar, const unsigned int version )
+  {
+    ar & _blockCS;
+  }
+
+ protected:
+
+  std::vector< StdMeshers_BlockCS > _blockCS;
+
+  typedef NCollection_DataMap< TopoDS_Shape, std::pair< TopoDS_Vertex, TopoDS_Vertex > > TSolid2VV;
+  TSolid2VV                         _solids2vertices; // shapes defined by _blockCS, non-persistent
+};
+
+// =========================================================
+/*!
+ * \brief Help in using StdMeshers_BlockRenumber
+ */
+class StdMeshers_RenumberHelper
+{
+public:
+
+  StdMeshers_RenumberHelper( SMESH_Mesh&                     mesh,
+                             const StdMeshers_BlockRenumber* hyp);
+  /*!
+   * \brief Find default vertex at (0,0,0) local position
+   */
+  static TopoDS_Vertex GetVertex000( const TopTools_MapOfShape& cornerVertices );
+
+  /*!
+   * \brief Find a vertex of a solid located at the given point
+   */
+  static TopoDS_Vertex GetVertexAtPoint( const TopoDS_Shape& solid, const TopoDS_Shape& point );
+
+  /*!
+   * \brief Create a copy of an old node and remember this couple of nodes for replacement
+   */
+  void AddReplacingNode( const SMDS_MeshNode* & oldNode );
+
+  /*!
+   * \brief Replace old nodes by new ones
+   */
+  void DoReplaceNodes();
+
+private:
+
+  SMESH_Mesh*                     _mesh;
+  const StdMeshers_BlockRenumber* _hyp;
+
+  SMESH_MeshEditor::TListOfListOfNodes _nodesToMerge;
+  std::list< const SMDS_MeshNode* >    _newOldNodes;
+};
+
+#endif
index 8f624c777867ebb71336b405cee6cccad5f88337..2e697303ae3e697a070a332c5f08cbec85c1c142 100644 (file)
@@ -38,6 +38,8 @@
 #include "SMESH_MeshAlgos.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
+#include "StdMeshers_BlockRenumber.hxx"
+#include "StdMeshers_FaceSide.hxx"
 #include "StdMeshers_ViscousLayers.hxx"
 
 #include <BRepAdaptor_Surface.hxx>
@@ -61,6 +63,7 @@
 #include <list>
 #include <set>
 #include <vector>
+#include <Bnd_B3d.hxx>
 
 using namespace std;
 
@@ -180,6 +183,8 @@ public: //** Methods to find and orient faces of 6 sides of the box **//
   TChildIterator GetChildren() const
   { return TChildIterator( myChildren.begin(), myChildren.end()); }
 
+  bool Contain( const TopoDS_Vertex& vertex ) const { return mySides.Contain( vertex ); }
+
 public: //** Loading and access to mesh **//
 
   //!< Load nodes of a mesh
@@ -271,7 +276,7 @@ private:
 //================================================================================
 
 StdMeshers_CompositeHexa_3D::StdMeshers_CompositeHexa_3D(int hypId, SMESH_Gen* gen)
-  :SMESH_3D_Algo(hypId, gen)
+  :SMESH_3D_Algo(hypId, gen), _blockRenumberHyp( nullptr )
 {
   _name = "CompositeHexa_3D";
   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);       // 1 bit /shape type
@@ -287,6 +292,7 @@ bool StdMeshers_CompositeHexa_3D::CheckHypothesis(SMESH_Mesh&         aMesh,
                                                   const TopoDS_Shape& aShape,
                                                   Hypothesis_Status&  aStatus)
 {
+  _blockRenumberHyp = nullptr;
   aStatus = HYP_OK;
   return true;
 }
@@ -545,6 +551,163 @@ namespace
     return faceFound;
   }
 
+    //================================================================================
+  /*!
+   * \brief Rearrange block sides according to StdMeshers_BlockRenumber hypothesis
+   */
+  //================================================================================
+
+  bool arrangeForRenumber( list< _QuadFaceGrid >&     blockSides,
+                           const TopTools_MapOfShape& cornerVertices,
+                           SMESH_Mesh*                mesh,
+                           TopoDS_Vertex&             v000,
+                           TopoDS_Vertex&             v001 )
+  {
+    if ( v000.IsNull() )
+    {
+      // block CS is not defined;
+      // renumber only if the block has an edge parallel to an axis of global CS
+
+      v000 = StdMeshers_RenumberHelper::GetVertex000( cornerVertices );
+    }
+
+    Bnd_B3d bbox;
+    for ( auto it = cornerVertices.cbegin(); it != cornerVertices.cend(); ++it )
+      bbox.Add( BRep_Tool::Pnt( TopoDS::Vertex( *it )));
+    double tol = 1e-5 * Sqrt( bbox.SquareExtent() );
+
+    // get block edges starting at v000
+
+    std::vector< const _FaceSide* > edgesAtV000;
+    std::vector< gp_Vec >           edgeDir;
+    std::vector< int >              iParallel; // 0 - none, 1 - X, 2 - Y, 3 - Z
+    TopTools_MapOfShape             lastVertices;
+    for ( _QuadFaceGrid & quad: blockSides )
+    {
+      for ( int iS = 0; iS < 4 &&  edgesAtV000.size() < 3; ++iS )
+      {
+        const _FaceSide* side = & quad.GetSide( iS );
+        TopoDS_Vertex v1 = side->FirstVertex(), v2 = side->LastVertex();
+        if (( v1.IsSame( v000 ) && !lastVertices.Contains( v2 )) ||
+            ( v2.IsSame( v000 ) && !lastVertices.Contains( v1 )))
+        {
+          bool reverse = v2.IsSame( v000 );
+          if ( reverse )
+            std::swap( v1, v2 );
+          lastVertices.Add( v2 );
+
+          edgesAtV000.push_back( side );
+
+          gp_Pnt pf = BRep_Tool::Pnt( v1 );
+          gp_Pnt pl = BRep_Tool::Pnt( v2 );
+          gp_Vec vec( pf, pl );
+          edgeDir.push_back( vec );
+
+          iParallel.push_back( 0 );
+          if ( !v001.IsNull() )
+          {
+            if ( quad.IsComplex() )
+              for ( _QuadFaceGrid::TChildIterator chIt = quad.GetChildren(); chIt.more(); )
+              {
+                const _QuadFaceGrid& child = chIt.next();
+                if ( child.GetSide( iS ).Contain( v001 ))
+                {
+                  iParallel.back() = 3;
+                  break;
+                }
+              }
+            else if ( side->Contain( v001 ))
+              iParallel.back() = 3;
+          }
+          else
+          {
+            bool isStraight = true;
+            std::list< TopoDS_Edge > edges;
+            for ( int iE = 0; true; ++iE )
+            {
+              TopoDS_Edge edge = side->Edge( iE );
+              if ( edge.IsNull() )
+                break;
+              edges.push_back( edge );
+              if ( isStraight )
+                isStraight = SMESH_Algo::IsStraight( edge );
+            }
+            // is parallel to a GCS axis?
+            if ( isStraight )
+            {
+              int nbDiff = (( Abs( vec.X() ) > tol ) +
+                            ( Abs( vec.Y() ) > tol ) +
+                            ( Abs( vec.Z() ) > tol ) );
+              if ( nbDiff == 1 )
+                iParallel.back() = ( Abs( vec.X() ) > tol ) ? 1 : ( Abs( vec.Y() ) > tol ) ? 2 : 3;
+            }
+            else
+            {
+              TopoDS_Face nullFace;
+              StdMeshers_FaceSide fSide( nullFace, edges, mesh, true, true );
+              edgeDir.back() = gp_Vec( pf, fSide.Value3d( reverse ? 0.99 : 0.01 ));
+            }
+          }
+        }
+      }
+    }
+    if ( std::accumulate( iParallel.begin(), iParallel.end(), 0 ) == 0 )
+      return false;
+
+    // find edge OZ and edge OX
+    const _FaceSide* edgeOZ = nullptr, *edgeOY = nullptr, *edgeOX = nullptr;
+    auto iZIt = std::find( iParallel.begin(), iParallel.end(), 3 );
+    if ( iZIt != iParallel.end() )
+    {
+      int i = std::distance( iParallel.begin(), iZIt );
+      edgeOZ = edgesAtV000[ i ];
+      int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() );
+      int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() );
+      if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 )
+        std::swap( iE1, iE2 );
+      edgeOX = edgesAtV000[ iE1 ];
+      edgeOY = edgesAtV000[ iE2 ];
+    }
+    else
+    {
+      for ( size_t i = 0; i < edgesAtV000.size(); ++i )
+      {
+        if ( !iParallel[ i ] )
+          continue;
+        int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() );
+        int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() );
+        if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 )
+          std::swap( iE1, iE2 );
+        edgeOZ = edgesAtV000[ iParallel[i] == 1 ? iE2 : iE1 ];
+        edgeOX = edgesAtV000[ iParallel[i] == 1 ? i : iE1 ];
+        edgeOY = edgesAtV000[ iParallel[i] == 1 ? iE1 : i ];
+        break;
+      }
+    }
+
+    if ( !edgeOZ || !edgeOX || !edgeOY )
+      return false;
+
+    TopoDS_Vertex v100 = edgeOX->LastVertex();
+    if ( v100.IsSame( v000 ))
+      v100 = edgeOX->FirstVertex();
+
+    // Find the left quad, one including v000 but not v100
+
+    for ( auto quad = blockSides.begin(); quad != blockSides.end(); ++quad )
+    {
+      if ( quad->Contain( v000 ) && !quad->Contain( v100 )) // it's a left quad
+      {
+        if ( quad != blockSides.begin() )
+          blockSides.splice( blockSides.begin(), blockSides, quad );
+        blockSides.front().SetBottomSide( *edgeOZ ); // edgeOY
+
+        return true;
+      }
+    }
+    return false;
+  }
+
 } // namespace
 
 //================================================================================
@@ -557,6 +720,7 @@ bool StdMeshers_CompositeHexa_3D::findBoxFaces( const TopoDS_Shape&    shape,
                                                 list< _QuadFaceGrid >& boxFaces,
                                                 SMESH_Mesh&            mesh,
                                                 SMESH_ProxyMesh&       proxyMesh,
+                                                bool&                  toRenumber,
                                                 _QuadFaceGrid * &      fBottom,
                                                 _QuadFaceGrid * &      fTop,
                                                 _QuadFaceGrid * &      fFront,
@@ -609,6 +773,22 @@ bool StdMeshers_CompositeHexa_3D::findBoxFaces( const TopoDS_Shape&    shape,
     for ( exp.Init( shape, TopAbs_FACE); exp.More(); exp.Next(), ++boxFace )
       boxFace->Init( TopoDS::Face( exp.Current() ), proxyMesh );
   }
+
+  toRenumber = _blockRenumberHyp;
+  if ( toRenumber )
+  {
+    TopoDS_Vertex v000, v001;
+    _blockRenumberHyp->IsSolidIncluded( mesh, shape, v000, v001 );
+
+    toRenumber = arrangeForRenumber( boxFaces, cornerVertices, &mesh, v000, v001 );
+
+    if ( toRenumber )
+    {
+      mesh.GetMeshDS()->Modified();
+      mesh.GetMeshDS()->CompactMesh(); // remove numbering holes
+    }
+  }
+  
   // ----------------------------------------
   // Find out position of faces within a box
   // ----------------------------------------
@@ -686,8 +866,9 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
   // Try to find 6 side faces
   // -------------------------
   list< _QuadFaceGrid > boxFaceContainer;
+  bool toRenumber = false;
   _QuadFaceGrid *fBottom, *fTop, *fFront, *fBack, *fLeft, *fRight;
-  if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh,
+  if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh, toRenumber,
                        fBottom, fTop, fFront, fBack, fLeft, fRight))
     return false;
 
@@ -711,6 +892,8 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
   fRight ->ComputeIJK( COO_Y, COO_Z, /*x=*/1. );
   fTop   ->ComputeIJK( COO_X, COO_Y, /*z=*/1. );
 
+  StdMeshers_RenumberHelper renumHelper( theMesh, _blockRenumberHyp );
+
   int x, xSize = fBottom->GetNbHoriSegments(*proxyMesh) + 1, X = xSize - 1;
   int y, ySize = fBottom->GetNbVertSegments(*proxyMesh) + 1, Y = ySize - 1;
   int z, zSize = fFront ->GetNbVertSegments(*proxyMesh) + 1, Z = zSize - 1;
@@ -768,8 +951,23 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
 
   gp_XYZ params; // normalized parameters of an internal node within the unit box
 
-  for ( x = 1; x < xSize-1; ++x )
+  if ( toRenumber )
+    for ( y = 0; y < ySize; ++y )
+    {
+      vector< const SMDS_MeshNode* >& columnXy = columns[ colIndex( X, y )];
+      for ( z = 0; z < zSize; ++z )
+        renumHelper.AddReplacingNode( columnXy[ z ] );
+    }
+
+  for ( x = X-1; x > 0; --x )
   {
+    if ( toRenumber )
+    {
+      vector< const SMDS_MeshNode* >& columnX0 = columns[ colIndex( x, 0 )];
+      for ( z = 0; z < zSize; ++z )
+        renumHelper.AddReplacingNode( columnX0[ z ] );
+    }
+
     const double rX = x / double(X);
     for ( y = 1; y < ySize-1; ++y )
     {
@@ -788,6 +986,10 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
       // points projections on horizontal faces
       pointsOnShapes[ SMESH_Block::ID_Fxy0 ] = fBottom->GetXYZ( x, y );
       pointsOnShapes[ SMESH_Block::ID_Fxy1 ] = fTop   ->GetXYZ( x, y );
+
+      if ( toRenumber )
+        renumHelper.AddReplacingNode( column[ 0 ] );
+
       for ( z = 1; z < zSize-1; ++z ) // z loop
       {
         // compute normalized parameters of an internal node within the unit box
@@ -832,16 +1034,35 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
         //cout << "Params: ( "<< params.X()<<", "<<params.Y()<<", "<<params.Z()<<" )"<<endl;
         //cout << "coords: ( "<< coords.X()<<", "<<coords.Y()<<", "<<coords.Z()<<" )"<<endl;
 #endif
-      }
+      } // z loop
+      if ( toRenumber )
+        renumHelper.AddReplacingNode( column[ Z ] );
+
+    } // y loop
+    if ( toRenumber )
+    {
+      vector< const SMDS_MeshNode* >& columnXY = columns[ colIndex( x, Y )];
+      for ( z = 0; z < zSize; ++z )
+        renumHelper.AddReplacingNode( columnXY[ z ] );
     }
-  }
+  } // for ( x = X-1; x > 0; --x )
+
+  if ( toRenumber )
+    for ( y = 0; y < ySize; ++y )
+    {
+      vector< const SMDS_MeshNode* >& column0Y = columns[ colIndex( 0, y )];
+      for ( z = 0; z < zSize; ++z )
+        renumHelper.AddReplacingNode( column0Y[ z ] );
+    }
+
+
   // faces no more needed, free memory
   boxFaceContainer.clear();
 
   // ----------------
   // Add hexahedrons
   // ----------------
-  for ( x = 0; x < xSize-1; ++x ) {
+  for ( x = xSize-2; true; --x ) {
     for ( y = 0; y < ySize-1; ++y ) {
       vector< const SMDS_MeshNode* >& col00 = columns[ colIndex( x, y )];
       vector< const SMDS_MeshNode* >& col10 = columns[ colIndex( x+1, y )];
@@ -850,11 +1071,22 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh&         theMesh,
       for ( z = 0; z < zSize-1; ++z )
       {
         // bottom face normal of a hexa mush point outside the volume
-        helper.AddVolume(col00[z],   col01[z],   col11[z],   col10[z],
-                         col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
+        helper.AddVolume(col10[z], col11[z], col11[z+1], col10[z+1],
+                         col00[z], col01[z], col01[z+1], col00[z+1]);
       }
     }
+    if ( x == 0)
+      break;
+
   }
+  if ( toRenumber )
+    renumHelper.DoReplaceNodes();
+
+  if ( _blockRenumberHyp )
+  {
+    return error( _blockRenumberHyp->CheckHypothesis( theMesh, theShape ));
+  }
+
   return true;
 }
 
@@ -875,7 +1107,8 @@ bool StdMeshers_CompositeHexa_3D::Evaluate(SMESH_Mesh&         theMesh,
   // -------------------------
   list< _QuadFaceGrid > boxFaceContainer;
   _QuadFaceGrid *fBottom, *fTop, *fFront, *fBack, *fLeft, *fRight;
-  if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh,
+  bool toRenumber = false;
+  if ( ! findBoxFaces( theShape, boxFaceContainer, theMesh, *proxyMesh, toRenumber,
                        fBottom, fTop, fFront, fBack, fLeft, fRight))
     return false;
 
index 695624fe5bda1fdc0b9dfcc898bcd975d106bb2c..9a17e2b81ce30b06c02643f5bbe1448c907cbed2 100644 (file)
@@ -29,6 +29,7 @@
 
 class SMESH_Mesh;
 class SMESH_ProxyMesh;
+class StdMeshers_BlockRenumber;
 class StdMeshers_FaceSide;
 class TopoDS_Edge;
 class TopoDS_Face;
@@ -44,7 +45,8 @@ class STDMESHERS_EXPORT StdMeshers_CompositeHexa_3D: public SMESH_3D_Algo
 {
 public:
   StdMeshers_CompositeHexa_3D(int hypId, SMESH_Gen* gen);
-  //virtual ~StdMeshers_CompositeHexa_3D();
+
+  void SetHypothesis( const StdMeshers_BlockRenumber* hyp ) { _blockRenumberHyp = hyp; }
 
   virtual bool Compute(SMESH_Mesh&         aMesh,
                        const TopoDS_Shape& aShape);
@@ -56,18 +58,21 @@ public:
                                const TopoDS_Shape& aShape,
                                Hypothesis_Status&  aStatus);
 
-private:
+ private:
 
   bool findBoxFaces( const TopoDS_Shape&         shape,
                      std::list< _QuadFaceGrid >& boxFaceContainer,
                      SMESH_Mesh&                 mesh,
                      SMESH_ProxyMesh&            proxyMesh,
+                     bool&                       toRenumber,
                      _QuadFaceGrid * &           fBottom,
                      _QuadFaceGrid * &           fTop,
                      _QuadFaceGrid * &           fFront,
                      _QuadFaceGrid * &           fBack,
                      _QuadFaceGrid * &           fLeft,
                      _QuadFaceGrid * &           fRight);
+
+  const StdMeshers_BlockRenumber* _blockRenumberHyp;
 };
 
 #endif
index 53877e2abdbd5399bc727f0abeefa31171c454e7..26b22cae1347584cda6e05236a05bfb0ad78f474 100644 (file)
 //
 #include "StdMeshers_Hexa_3D.hxx"
 
+#include "SMDS_MeshNode.hxx"
+#include "SMESH_Comment.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_subMesh.hxx"
+#include "StdMeshers_BlockRenumber.hxx"
 #include "StdMeshers_CompositeHexa_3D.hxx"
 #include "StdMeshers_FaceSide.hxx"
 #include "StdMeshers_HexaFromSkin_3D.hxx"
 #include "StdMeshers_Quadrangle_2D.hxx"
 #include "StdMeshers_ViscousLayers.hxx"
 
-#include "SMESH_Comment.hxx"
-#include "SMESH_Gen.hxx"
-#include "SMESH_Mesh.hxx"
-#include "SMESH_MesherHelper.hxx"
-#include "SMESH_subMesh.hxx"
-
-#include "SMDS_MeshNode.hxx"
-
+#include <BRep_Tool.hxx>
+#include <Bnd_B3d.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
-#include <TopTools_SequenceOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <TopTools_SequenceOfShape.hxx>
 #include <TopoDS.hxx>
 
 #include "utilities.h"
 #include "Utils_ExceptHandlers.hxx"
 
+#include <cstddef>
+
 typedef SMESH_Comment TComm;
 
 using namespace std;
@@ -77,6 +80,7 @@ StdMeshers_Hexa_3D::StdMeshers_Hexa_3D(int hypId, SMESH_Gen * gen)
   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);       // 1 bit /shape type
   _requireShape = false;
   _compatibleHypothesis.push_back("ViscousLayers");
+  _compatibleHypothesis.push_back("BlockRenumber");
   _quadAlgo = new StdMeshers_Quadrangle_2D( gen->GetANewId(), _gen );
 }
 
@@ -114,7 +118,8 @@ bool StdMeshers_Hexa_3D::CheckHypothesis
     return false;
 */
 
-  _viscousLayersHyp = NULL;
+  _viscousLayersHyp = nullptr;
+  _blockRenumberHyp = nullptr;
 
   const list<const SMESHDS_Hypothesis*>& hyps =
     GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliary=*/false);
@@ -129,13 +134,25 @@ bool StdMeshers_Hexa_3D::CheckHypothesis
   aStatus = HYP_OK;
   for ( ; h != hyps.end(); ++h )
   {
-    if ( !(_viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h )))
-      break;
+    if ( !_viscousLayersHyp &&
+         (_viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h )))
+      continue;
+    if ( !_blockRenumberHyp &&
+         (_blockRenumberHyp = dynamic_cast< const StdMeshers_BlockRenumber*> ( *h )))
+      continue;
+    break;
   }
-  if ( !_viscousLayersHyp )
+  if ((int) hyps.size() != (bool)_viscousLayersHyp + (bool)_blockRenumberHyp )
     aStatus = HYP_INCOMPATIBLE;
   else
-    error( _viscousLayersHyp->CheckHypothesis( aMesh, aShape, aStatus ));
+  {
+    if ( _viscousLayersHyp )
+      if ( !error( _viscousLayersHyp->CheckHypothesis( aMesh, aShape, aStatus )))
+        aStatus = HYP_BAD_PARAMETER;
+
+    if ( _blockRenumberHyp && aStatus == HYP_OK )
+      error( _blockRenumberHyp->CheckHypothesis( aMesh, aShape ));
+  }
 
   return aStatus == HYP_OK;
 }
@@ -202,26 +219,6 @@ namespace
     int operator()(const int x, const int y) const { return y * _xSize + x; }
   };
 
-  //================================================================================
-  /*!
-   * \brief Appends a range of node columns from a map to another map
-   */
-  template< class TMapIterator >
-  void append( TParam2ColumnMap& toMap, TMapIterator from, TMapIterator to )
-  {
-    const SMDS_MeshNode* lastNode = toMap.rbegin()->second[0];
-    const SMDS_MeshNode* firstNode = from->second[0];
-    if ( lastNode == firstNode )
-      from++;
-    double u = toMap.rbegin()->first;
-    for (; from != to; ++from )
-    {
-      u += 1;
-      TParam2ColumnMap::iterator u2nn = toMap.insert( toMap.end(), make_pair ( u, TNodeColumn()));
-      u2nn->second.swap( from->second );
-    }
-  }
-
   //================================================================================
   /*!
    * \brief Finds FaceQuadStruct having a side equal to a given one and rearranges
@@ -260,6 +257,204 @@ namespace
     }
     return foundQuad;
   }
+
+  //================================================================================
+  /*!
+   * \brief Put quads to aCubeSide in the order of enum EBoxSides
+   */
+  //================================================================================
+
+  bool arrangeQuads( FaceQuadStructPtr quad[ 6 ], _FaceGrid aCubeSide[ 6 ], bool reverseBottom )
+  {
+    swap( aCubeSide[B_BOTTOM]._quad, quad[0] );
+    if ( reverseBottom )
+      swap( aCubeSide[B_BOTTOM]._quad->side[ Q_RIGHT],// direct the bottom normal inside cube
+            aCubeSide[B_BOTTOM]._quad->side[ Q_LEFT ] );
+
+    aCubeSide[B_FRONT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_BOTTOM], quad );
+    aCubeSide[B_RIGHT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_RIGHT ], quad );
+    aCubeSide[B_BACK ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_TOP   ], quad );
+    aCubeSide[B_LEFT ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_LEFT  ], quad );
+    if ( aCubeSide[B_FRONT ]._quad )
+      aCubeSide[B_TOP]._quad = getQuadWithBottom( aCubeSide[B_FRONT ]._quad->side[Q_TOP ], quad );
+
+    for ( int i = 1; i < 6; ++i )
+      if ( !aCubeSide[i]._quad )
+        return false;
+    return true;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Rearrange block sides according to StdMeshers_BlockRenumber hypothesis
+   */
+  //================================================================================
+
+  bool arrangeForRenumber( _FaceGrid      blockSide[ 6 ],
+                           TopoDS_Vertex& v000,
+                           TopoDS_Vertex& v001 )
+  {
+    std::swap( blockSide[B_BOTTOM]._quad->side[ Q_RIGHT],// restore after arrangeQuads()
+               blockSide[B_BOTTOM]._quad->side[ Q_LEFT ] );
+
+    // find v000
+    TopTools_MapOfShape cornerVertices;
+    cornerVertices.Add(  blockSide[B_BOTTOM]._quad->side[Q_BOTTOM].grid->LastVertex()  );
+    cornerVertices.Add(  blockSide[B_BOTTOM]._quad->side[Q_BOTTOM].grid->FirstVertex() );
+    cornerVertices.Add(  blockSide[B_BOTTOM]._quad->side[Q_TOP   ].grid->LastVertex()  );
+    cornerVertices.Add(  blockSide[B_BOTTOM]._quad->side[Q_TOP   ].grid->FirstVertex() );
+    cornerVertices.Add(  blockSide[B_TOP   ]._quad->side[Q_BOTTOM].grid->FirstVertex() );
+    cornerVertices.Add(  blockSide[B_TOP   ]._quad->side[Q_BOTTOM].grid->LastVertex()  );
+    cornerVertices.Add(  blockSide[B_TOP   ]._quad->side[Q_TOP   ].grid->FirstVertex() );
+    cornerVertices.Add(  blockSide[B_TOP   ]._quad->side[Q_TOP   ].grid->LastVertex()  );
+
+    if ( v000.IsNull() )
+    {
+      // block CS is not defined;
+      // renumber only if the block has an edge parallel to an axis of global CS
+
+      v000 = StdMeshers_RenumberHelper::GetVertex000( cornerVertices );
+    }
+
+    Bnd_B3d bbox;
+    for ( auto it = cornerVertices.cbegin(); it != cornerVertices.cend(); ++it )
+      bbox.Add( BRep_Tool::Pnt( TopoDS::Vertex( *it )));
+    double tol = 1e-5 * Sqrt( bbox.SquareExtent() );
+
+    // get block edges starting at v000
+
+    std::vector< StdMeshers_FaceSidePtr > edgesAtV000;
+    std::vector< gp_Vec >                 edgeDir;
+    std::vector< int >                    iParallel; // 0 - none, 1 - X, 2 - Y, 3 - Z
+    TopTools_MapOfShape                   lastVertices;
+    for ( int iQ = 0; iQ < 6; ++iQ )
+    {
+      FaceQuadStructPtr quad = blockSide[iQ]._quad;
+      for ( size_t iS = 0; iS < quad->side.size() &&  edgesAtV000.size() < 3; ++iS )
+      {
+        StdMeshers_FaceSidePtr edge = quad->side[iS];
+        TopoDS_Vertex v1 = edge->FirstVertex(), v2 = edge->LastVertex();
+        if (( v1.IsSame( v000 ) && !lastVertices.Contains( v2 )) ||
+            ( v2.IsSame( v000 ) && !lastVertices.Contains( v1 )))
+        {
+          bool reverse = v2.IsSame( v000 );
+          if ( reverse )
+            std::swap( v1, v2 );
+          lastVertices.Add( v2 );
+
+          edgesAtV000.push_back( edge );
+
+          gp_Pnt pf = BRep_Tool::Pnt( v1 );
+          gp_Pnt pl = BRep_Tool::Pnt( v2 );
+          gp_Vec vec( pf, pl );
+          edgeDir.push_back( vec );
+
+          iParallel.push_back( 0 );
+          if ( !v001.IsNull() )
+          {
+            if ( v001.IsSame( v2 ))
+              iParallel.back() = 3;
+          }
+          else
+          {
+            bool isStraight = true;
+            for ( int iE = 0; iE < edge->NbEdges() &&  isStraight; ++iE )
+              isStraight = SMESH_Algo::IsStraight( edge->Edge( iE ));
+
+            // is parallel to a GCS axis?
+            if ( isStraight )
+            {
+              int nbDiff = (( Abs( vec.X() ) > tol ) +
+                            ( Abs( vec.Y() ) > tol ) +
+                            ( Abs( vec.Z() ) > tol ) );
+              if ( nbDiff == 1 )
+                iParallel.back() = ( Abs( vec.X() ) > tol ) ? 1 : ( Abs( vec.Y() ) > tol ) ? 2 : 3;
+            }
+            else
+            {
+              edgeDir.back() = gp_Vec( pf, edge->Value3d( reverse ? 0.99 : 0.01 ));
+            }
+          }
+        }
+      }
+    }
+    if ( std::accumulate( iParallel.begin(), iParallel.end(), 0 ) == 0 )
+      return false;
+
+    // find edge OZ and edge OX
+    StdMeshers_FaceSidePtr edgeOZ, edgeOX;
+    auto iZIt = std::find( iParallel.begin(), iParallel.end(), 3 );
+    if ( iZIt != iParallel.end() )
+    {
+      int i = std::distance( iParallel.begin(), iZIt );
+      edgeOZ = edgesAtV000[ i ];
+      int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() );
+      int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() );
+      if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 )
+        std::swap( iE1, iE2 );
+      edgeOX = edgesAtV000[ iE1 ];
+    }
+    else
+    {
+      for ( size_t i = 0; i < edgesAtV000.size(); ++i )
+      {
+        if ( !iParallel[ i ] )
+          continue;
+        int iE1 = SMESH_MesherHelper::WrapIndex( i + 1, edgesAtV000.size() );
+        int iE2 = SMESH_MesherHelper::WrapIndex( i + 2, edgesAtV000.size() );
+        if (( edgeDir[ iE1 ] ^ edgeDir[ iE2 ] ) * edgeDir[ i ] < 0 )
+          std::swap( iE1, iE2 );
+        edgeOZ = edgesAtV000[ iParallel[i] == 1 ? iE2 : iE1 ];
+        edgeOX = edgesAtV000[ iParallel[i] == 1 ? i : iE1 ];
+        break;
+      }
+    }
+
+    if ( !edgeOZ || !edgeOX )
+      return false;
+
+    TopoDS_Vertex v100 = edgeOX->LastVertex();
+    if ( v100.IsSame( v000 ))
+      v100 = edgeOX->FirstVertex();
+
+    // Find the left quad, one including v000 but not v100
+
+    for ( int iQ = 0; iQ < 6; ++iQ )
+    {
+      FaceQuadStructPtr quad = blockSide[iQ]._quad;
+      bool hasV000 = false, hasV100 = false;
+      for ( size_t iS = 0; iS < quad->side.size(); ++iS )
+      {
+        StdMeshers_FaceSidePtr edge = quad->side[iS];
+        if ( edge->FirstVertex().IsSame( v000 ) || edge->LastVertex().IsSame( v000 ))
+          hasV000 = true;
+        if ( edge->FirstVertex().IsSame( v100 ) || edge->LastVertex().IsSame( v100 ))
+          hasV100 = true;
+      }
+      if ( hasV000 && !hasV100 )
+      {
+        // orient the left quad
+        for ( int i = 0; i < 4; ++i )
+        {
+          if ( quad->side[Q_BOTTOM].grid->Edge(0).IsSame( edgeOZ->Edge(0) ))
+            break;
+          quad->shift( 1, true );
+        }
+
+        FaceQuadStructPtr quads[ 6 ];
+        quads[0].swap( blockSide[iQ]._quad );
+        for ( int i = 1, j = 0; i < 6; ++i, ++j )
+          if ( blockSide[ j ]._quad )
+            quads[ i ].swap( blockSide[ j ]._quad );
+          else
+            --i;
+
+        return arrangeQuads( quads, blockSide, false/* true*/ );
+      }
+    }
+    return false;
+  }
+
   //================================================================================
   /*!
    * \brief Returns true if the 1st base node of sideGrid1 belongs to sideGrid2
@@ -371,9 +566,11 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
   if ( FF.Extent() != 6)
   {
     static StdMeshers_CompositeHexa_3D compositeHexa(_gen->GetANewId(), _gen);
+    compositeHexa.SetHypothesis( _blockRenumberHyp );
     if ( !compositeHexa.Compute( aMesh, aShape ))
       return error( compositeHexa.GetComputeError() );
-    return true;
+
+    return _blockRenumberHyp ? error( _blockRenumberHyp->CheckHypothesis( aMesh, aShape )) : true;
   }
 
   // Find sides of a cube
@@ -399,22 +596,11 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
       return error( COMPERR_BAD_SHAPE, "Not a quadrangular box side" );
   }
 
+  // put quads in a proper order
   _FaceGrid aCubeSide[ 6 ];
+  if ( !arrangeQuads( quad, aCubeSide, true ))
+    return error( COMPERR_BAD_SHAPE );
 
-  swap( aCubeSide[B_BOTTOM]._quad, quad[0] );
-  swap( aCubeSide[B_BOTTOM]._quad->side[ Q_RIGHT],// direct the normal of bottom quad inside cube
-        aCubeSide[B_BOTTOM]._quad->side[ Q_LEFT ] );
-
-  aCubeSide[B_FRONT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_BOTTOM], quad );
-  aCubeSide[B_RIGHT]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_RIGHT ], quad );
-  aCubeSide[B_BACK ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_TOP   ], quad );
-  aCubeSide[B_LEFT ]._quad = getQuadWithBottom( aCubeSide[B_BOTTOM]._quad->side[Q_LEFT  ], quad );
-  if ( aCubeSide[B_FRONT ]._quad )
-    aCubeSide[B_TOP]._quad = getQuadWithBottom( aCubeSide[B_FRONT ]._quad->side[Q_TOP ], quad );
-
-  for ( int i = 1; i < 6; ++i )
-    if ( !aCubeSide[i]._quad )
-      return error( COMPERR_BAD_SHAPE );
 
   // Make viscous layers
   // --------------------
@@ -446,6 +632,22 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
     }
   }
 
+  // Arrange sides according to _blockRenumberHyp
+  bool toRenumber = _blockRenumberHyp;
+  if ( toRenumber )
+  {
+    TopoDS_Vertex v000, v001;
+    _blockRenumberHyp->IsSolidIncluded( aMesh, aShape, v000, v001 );
+
+    toRenumber = arrangeForRenumber( aCubeSide, v000, v001 );
+
+    if ( toRenumber )
+    {
+      meshDS->Modified();
+      meshDS->CompactMesh(); // remove numbering holes
+    }
+  }
+
   // Check presence of regular grid mesh on FACEs of the cube
   // ------------------------------------------------------------
 
@@ -605,6 +807,8 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
   computeIJK( *fFront,  COO_X, COO_Z, /*y=*/0. );
   computeIJK( *fBack,   COO_X, COO_Z, /*y=*/1. );
 
+  StdMeshers_RenumberHelper renumHelper( aMesh, _blockRenumberHyp );
+
   // projection points of the internal node on cube sub-shapes by which
   // coordinates of the internal node are computed
   vector<gp_XYZ> pointsOnShapes( SMESH_Block::ID_Shell );
@@ -620,8 +824,25 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
   pointsOnShapes[ SMESH_Block::ID_V111 ] = fTop->GetXYZ( X, Y );
 
   gp_XYZ params; // normalized parameters of an internal node within the unit box
-  for ( x = 1; x < xSize-1; ++x )
+  for ( x = 0; x < xSize; ++x )
   {
+    if ( toRenumber )
+    {
+      vector< const SMDS_MeshNode* >& columnX0 = columns[ colIndex( x, 0 )];
+      for ( z = 0; z < zSize; ++z )
+        renumHelper.AddReplacingNode( columnX0[ z ] );
+      if ( x == 0 || x == X )
+      {
+        for ( y = 1; y < ySize; ++y )
+        {
+          vector< const SMDS_MeshNode* >& column0Y = columns[ colIndex( x, y )];
+          for ( z = 0; z < zSize; ++z )
+            renumHelper.AddReplacingNode( column0Y[ z ] );
+        }
+        continue;
+      }
+    }
+
     const double rX = x / double(X);
     for ( y = 1; y < ySize-1; ++y )
     {
@@ -641,6 +862,10 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
       // projection points on horizontal faces
       pointsOnShapes[ SMESH_Block::ID_Fxy0 ] = fBottom->GetXYZ( x, y );
       pointsOnShapes[ SMESH_Block::ID_Fxy1 ] = fTop   ->GetXYZ( x, y );
+
+      if ( toRenumber )
+        renumHelper.AddReplacingNode( column[ 0 ] );
+
       for ( z = 1; z < zSize-1; ++z ) // z loop
       {
         const double rZ = z / double(Z);
@@ -673,13 +898,23 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
         gp_XYZ coords;
         SMESH_Block::ShellPoint( params, pointsOnShapes, coords );
         column[ z ] = helper.AddNode( coords.X(), coords.Y(), coords.Z() );
-      }
+
+      } // z loop
+      if ( toRenumber )
+        renumHelper.AddReplacingNode( column[ Z ] );
+
+    } // y loop
+    if ( toRenumber )
+    {
+      vector< const SMDS_MeshNode* >& columnX0 = columns[ colIndex( x, Y )];
+      for ( z = 0; z < zSize; ++z )
+        renumHelper.AddReplacingNode( columnX0[ z ] );
     }
-  }
+  } // x loop
 
   // side data no more needed, free memory
   for ( int i = 0; i < 6; ++i )
-    aCubeSide[i]._columns.clear();
+    SMESHUtils::FreeVector( aCubeSide[i]._columns );
 
   // 5) Create hexahedrons
   // ---------------------
@@ -693,11 +928,25 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh &         aMesh,
       for ( z = 0; z < zSize-1; ++z )
       {
         // bottom face normal of a hexa mush point outside the volume
-        helper.AddVolume(col00[z],   col01[z],   col11[z],   col10[z],
-                         col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
+        if ( toRenumber )
+          helper.AddVolume(col00[z], col01[z], col01[z+1], col00[z+1],
+                           col10[z], col11[z], col11[z+1], col10[z+1]);
+        else
+          helper.AddVolume(col00[z],   col01[z],   col11[z],   col10[z],
+                           col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
       }
     }
   }
+
+  if ( toRenumber )
+    renumHelper.DoReplaceNodes();
+
+
+  if ( _blockRenumberHyp )
+  {
+    return error( _blockRenumberHyp->CheckHypothesis( aMesh, aShape ));
+  }
+
   return true;
 }
 
index a743d47540205fd6addfd2f087c20e7d1c577905..16315e0d745e47f667016af46da2ab5997f81a3c 100644 (file)
@@ -37,6 +37,7 @@
 class SMESH_MesherHelper;
 class StdMeshers_Quadrangle_2D;
 class StdMeshers_ViscousLayers;
+class StdMeshers_BlockRenumber;
 
 class STDMESHERS_EXPORT StdMeshers_Hexa_3D : public SMESH_3D_Algo
 {
@@ -64,6 +65,7 @@ public:
  protected:
 
   const StdMeshers_ViscousLayers* _viscousLayersHyp;
+  const StdMeshers_BlockRenumber* _blockRenumberHyp;
   StdMeshers_Quadrangle_2D*       _quadAlgo;
 };
 
index c0f1c390f9bc013f81ebaf9459072e84d60d95cd..d423dd2a3be8a15137fcac80978b2bb1728dd3c6 100644 (file)
@@ -81,6 +81,7 @@ SET(_moc_HEADERS
   StdMeshersGUI_RadioButtonsGrpWdg.h
   StdMeshersGUI_PropagationHelperWdg.h
   StdMeshersGUI_NameCheckableGrpWdg.h
+  StdMeshersGUI_BlockRenumberCreator.h
 )
 
 IF(SALOME_USE_PLOT2DVIEWER)
@@ -117,6 +118,7 @@ SET(_other_SOURCES
   StdMeshersGUI_RadioButtonsGrpWdg.cxx
   StdMeshersGUI_PropagationHelperWdg.cxx
   StdMeshersGUI_NameCheckableGrpWdg.cxx
+  StdMeshersGUI_BlockRenumberCreator.cxx
 )
 
 IF(SALOME_USE_PLOT2DVIEWER)
index 5118745839f8fd36f9b9b991dd82c210b7729479..406c14de972335ba5e848ba8f8217c1a4245ebe2 100644 (file)
 // Author : Alexander SOLOVYOV, Open CASCADE S.A.S.
 // SMESH includes
 //
-#include "StdMeshersGUI_StdHypothesisCreator.h"
-#include "StdMeshersGUI_NbSegmentsCreator.h"
+#include "StdMeshersGUI_BlockRenumberCreator.h"
 #include "StdMeshersGUI_CartesianParamCreator.h"
+#include "StdMeshersGUI_NbSegmentsCreator.h"
 #include "StdMeshersGUI_QuadrangleParamWdg.h"
+#include "StdMeshersGUI_StdHypothesisCreator.h"
 
 //=============================================================================
 /*! GetHypothesisCreator
@@ -45,6 +46,8 @@ extern "C"
       return new StdMeshersGUI_CartesianParamCreator( aHypType );
     else if ( aHypType=="QuadrangleParams" )
       return new StdMeshersGUI_QuadrangleParamCreator( aHypType );
+    else if ( aHypType=="BlockRenumber")
+      return new StdMeshersGUI_BlockRenumberCreator( aHypType );
     else
       return new StdMeshersGUI_StdHypothesisCreator( aHypType );
   }
diff --git a/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.cxx
new file mode 100644 (file)
index 0000000..9aacd16
--- /dev/null
@@ -0,0 +1,515 @@
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : StdMeshersGUI_BlockRenumberCreator.cxx
+// Author : Open CASCADE S.A.S.
+
+#include "StdMeshersGUI_BlockRenumberCreator.h"
+
+#include "SMESHGUI.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_VTKUtils.h"
+#include "SMESHGUI_HypothesesUtils.h"
+
+#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
+
+#include <GEOMBase.h>
+#include <LightApp_SelectionMgr.h>
+#include <SALOMEDSClient_SObject.hxx>
+#include <SALOMEDSClient_Study.hxx>
+#include <SALOME_InteractiveObject.hxx>
+#include <SALOME_ListIO.hxx>
+#include <SUIT_ResourceMgr.h>
+#include <SalomeApp_Tools.h>
+
+#include <QApplication>
+#include <QButtonGroup>
+#include <QGridLayout>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHeaderView>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QString>
+#include <QTreeWidget>
+#include <QTreeWidgetItem>
+
+#define SPACING 6
+#define MARGIN  11
+
+namespace {
+
+  //================================================================================
+  /*!
+   * \brief Textual representation of GEOM_Object in QTreeWidget
+   */
+  //================================================================================
+
+  QString toText( const GEOM::GEOM_Object_var& theGO,
+                  const QString &              /*theLabel*/,
+                  QString&                     theEntry )
+  {
+    QString txt;
+    if ( !theGO->_is_nil() )
+    {
+      CORBA::String_var  name = theGO->GetName();
+      CORBA::String_var entry = theGO->GetStudyEntry();
+      theEntry = entry.in();
+
+      txt = name.in();
+      //txt = theLabel + name.in() + " [" + theEntry + "]";
+      //txt += " ";//" (";
+      //txt += entry.in();
+      //txt += ")";
+    }
+    return txt;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Find GEOM_Object by study entry
+   */
+  //================================================================================
+
+  GEOM::GEOM_Object_var toGeom( const QString& entry )
+  {
+    return SMESH::EntryToInterface<GEOM::GEOM_Object>( entry );
+  }
+
+
+  //================================================================================
+  /*!
+   * \brief Find GEOM_Object in the tree
+   */
+  //================================================================================
+
+  QTreeWidgetItem* findSolidInTree( const GEOM::GEOM_Object_var& go, QTreeWidget* tree )
+  {
+    if ( go->_is_nil() || !tree )
+      return nullptr;
+
+    for ( int i = 0; i < tree->topLevelItemCount(); ++i )
+    {
+      QTreeWidgetItem* item = tree->topLevelItem( i );
+      if ( item->data( 1, Qt::UserRole ).toString() == SMESH::toQStr( go->GetStudyEntry() ))
+        return item;
+    }
+    return nullptr;
+  }
+}
+
+//================================================================================
+/*!
+ * \brief StdMeshersGUI_BlockRenumberCreator constructor
+ */
+//================================================================================
+
+StdMeshersGUI_BlockRenumberCreator::StdMeshersGUI_BlockRenumberCreator(const QString& aHypType)
+  : StdMeshersGUI_StdHypothesisCreator( aHypType ),
+    mySolidFilter( "", TopAbs_SOLID, 1, TopAbs_SOLID ),
+    myVertexFilter( "", TopAbs_VERTEX, 1, TopAbs_VERTEX )
+{
+}
+
+//================================================================================
+/*!
+ * \brief StdMeshersGUI_BlockRenumberCreator destructor
+ */
+//================================================================================
+
+StdMeshersGUI_BlockRenumberCreator::~StdMeshersGUI_BlockRenumberCreator()
+{
+  SMESHGUI::selectionMgr()->clearFilters();
+}
+
+//================================================================================
+/*!
+ * \brief Create widgets
+ */
+//================================================================================
+
+QFrame* StdMeshersGUI_BlockRenumberCreator::buildFrame()
+{
+  QFrame* fr = new QFrame();
+  //fr->setMinimumWidth(460);
+
+  QGridLayout* frLayout = new QGridLayout( fr );
+  frLayout->setSpacing( SPACING );
+  frLayout->setMargin( MARGIN );
+
+  // name
+  myName = 0;
+  int row = 0;
+  if( isCreation() )
+  {
+    myName = new QLineEdit( fr );
+    frLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), fr ), row, 0 );
+    frLayout->addWidget( myName,                               row, 1 );
+    row++;
+  }
+
+  QGroupBox* groupBox = new QGroupBox( tr( "BLOCK_CS_GROUPBOX" ), fr );
+  frLayout->addWidget( groupBox, row, 0, 1, 2 );
+
+  QGridLayout* layout = new QGridLayout( groupBox );
+  layout->setSpacing( SPACING );
+  layout->setMargin( MARGIN );
+  layout->setColumnStretch( 0, 1 );
+
+  // tree
+  row = 0;
+  myBlockTree = new QTreeWidget( groupBox );
+  myBlockTree->setColumnCount( 2 );
+  myBlockTree->header()->hide();
+  // myBlockTree->setHeaderLabels( QStringList()
+  //                               << tr("COLUMN_BLOCK") << tr("COLUMN_V000") << tr("COLUMN_V001"));
+  layout->addWidget( myBlockTree, row, 0, row + 7, 1 );
+
+  // selection widgets
+  myButGroup = new QButtonGroup( groupBox );
+  myButGroup->setExclusive( true );
+  QLabel* label[3] = { new QLabel( tr( "SOLID" ), groupBox ),
+                       new QLabel( tr( "V000" ),  groupBox ),
+                       new QLabel( tr( "V001" ),  groupBox ) };
+  QIcon icon( SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT")));
+  for ( int i = 0; i < 3; ++i )
+  {
+    myShapeSelectBut[i] = new QPushButton( icon, "", groupBox );
+    myLineEdit      [i] = new QLineEdit( groupBox );
+    layout->addWidget( label[i],            row, 1 );
+    layout->addWidget( myShapeSelectBut[i], row, 2 );
+    layout->addWidget( myLineEdit[i],       row, 3 );
+    myShapeSelectBut[i]->setCheckable( true );
+    myButGroup->addButton( myShapeSelectBut[i], i );
+    row++;
+  }
+
+  // buttons
+  myAddBut    = new QPushButton( tr("ADD"),    groupBox );
+  myModifBut  = new QPushButton( tr("MODIFY"),       groupBox );
+  myRemoveBut = new QPushButton( tr("SMESH_REMOVE"), groupBox );
+  layout->addWidget( myAddBut, row, 1, 1, 3 );
+  row++;
+  layout->addWidget( myModifBut, row, 1, 1, 3 );
+  row++;
+  layout->addWidget( myRemoveBut, row, 1, 1, 3 );
+  row++;
+  layout->setRowStretch( row, 1 );
+
+  LightApp_SelectionMgr* selMgr = SMESH::GetSelectionMgr( SMESHGUI::GetSMESHGUI() );
+
+  connect( selMgr,              SIGNAL( currentSelectionChanged()), SLOT( onSelectionChange()));
+  connect( myBlockTree,         SIGNAL( itemSelectionChanged() ),   SLOT( onTreeSelectionChange()));
+  connect( myShapeSelectBut[0], SIGNAL( clicked(bool)),             SLOT( onSelectBtnClick() ));
+  connect( myShapeSelectBut[1], SIGNAL( clicked(bool)),             SLOT( onSelectBtnClick() ));
+  connect( myShapeSelectBut[2], SIGNAL( clicked(bool)),             SLOT( onSelectBtnClick() ));
+  connect( myAddBut,            SIGNAL( clicked() ),                SLOT( onAddBtnClick() ));
+  connect( myModifBut,          SIGNAL( clicked() ),                SLOT( onModifBtnClick() ));
+  connect( myRemoveBut,         SIGNAL( clicked() ),                SLOT( onRemoveBtnClick() ));
+
+  return fr;
+}
+
+//================================================================================
+/*!
+ * \brief Set myGO's to the tree
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::setBlockToTree(QTreeWidgetItem* solidItem)
+{
+  if ( !myGO[0]->_is_nil() && !myGO[1]->_is_nil() && !myGO[2]->_is_nil() )
+  {
+    if ( !solidItem ) solidItem = new QTreeWidgetItem( myBlockTree );
+    solidItem->setExpanded( true );
+    QTreeWidgetItem* item = solidItem;
+
+    QFont boldFont = item->font( 0 );
+    boldFont.setBold( true );
+
+    QString entry, label[3] = { tr("BLOCK_LABEL"), tr("V000_LABEL"), tr("V001_LABEL") };
+    for ( int i = 0; i < 3; ++i )
+    {
+      if ( i > 0 && ! (item = solidItem->child( i - 1 )))
+        item = new QTreeWidgetItem( solidItem );
+
+      item->setText( 0, label[i] );
+      item->setText( 1, toText( myGO[i], label[i], entry ));
+      item->setData( 1, Qt::UserRole, entry );
+      item->setFont( 1, boldFont );
+      item->setToolTip( 1, entry );
+    }
+    myBlockTree->resizeColumnToContents( 0 );
+    myBlockTree->resizeColumnToContents( 1 );
+  }
+  for ( int i = 0; i < 3; ++i )
+  {
+    myGO[i] = GEOM::GEOM_Object::_nil();
+    myLineEdit[i]->setText("");
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Transfer parameters from hypothesis to widgets
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::retrieveParams() const
+{
+  StdMeshersGUI_BlockRenumberCreator* me = const_cast<StdMeshersGUI_BlockRenumberCreator*>( this );
+
+  StdMeshers::StdMeshers_BlockRenumber_var h =
+    StdMeshers::StdMeshers_BlockRenumber::_narrow( initParamsHypothesis() );
+
+  if( myName )
+    me->myName->setText( hypName() );
+
+  me->myBlockTree->clear();
+
+  StdMeshers::blockcs_array_var blkArray = h->GetBlocksOrientation();
+  for ( CORBA::ULong i = 0; i < blkArray->length(); ++i )
+  {
+    me->myGO[0] = GEOM::GEOM_Object::_duplicate( blkArray[i].solid.in()     );
+    me->myGO[1] = GEOM::GEOM_Object::_duplicate( blkArray[i].vertex000.in() );
+    me->myGO[2] = GEOM::GEOM_Object::_duplicate( blkArray[i].vertex001.in() );
+    me->setBlockToTree();
+  }
+
+  me->myShapeSelectBut[0]->click();
+
+  me->updateButtons();
+}
+
+//================================================================================
+/*!
+ * \brief Transfer parameters from widgets to hypothesis
+ */
+//================================================================================
+
+QString StdMeshersGUI_BlockRenumberCreator::storeParams() const
+{
+  StdMeshers::StdMeshers_BlockRenumber_var h =
+    StdMeshers::StdMeshers_BlockRenumber::_narrow( hypothesis() );
+
+  try
+  {
+    if( isCreation() )
+      SMESH::SetName( SMESH::FindSObject( h ), myName->text().toUtf8().constData() );
+
+    StdMeshers::blockcs_array_var array = new StdMeshers::blockcs_array();
+    array->length( myBlockTree->topLevelItemCount() );
+
+    for ( int i = 0; i < myBlockTree->topLevelItemCount(); ++i )
+    {
+      StdMeshers::BlockCS& bcs = array[i];
+      QTreeWidgetItem*   item0 = myBlockTree->topLevelItem( i );
+      QTreeWidgetItem*   item1 = item0->child( 0 );
+      QTreeWidgetItem*   item2 = item0->child( 1 );
+
+      bcs.solid     = toGeom( item0->data( 1, Qt::UserRole ).toString() )._retn();
+      bcs.vertex000 = toGeom( item1->data( 1, Qt::UserRole ).toString() )._retn();
+      bcs.vertex001 = toGeom( item2->data( 1, Qt::UserRole ).toString() )._retn();
+    }
+    h->SetBlocksOrientation( array );
+
+  }
+  catch(const SALOME::SALOME_Exception& ex)
+  {
+    SalomeApp_Tools::QtCatchCorbaException(ex);
+  }
+  return "";
+}
+
+//================================================================================
+/*!
+ * \brief Take selected object
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::onSelectionChange()
+{
+  SALOME_ListIO list;
+  SMESHGUI::GetSMESHGUI()->selectionMgr()->selectedObjects( list );
+
+  int shapeID = myButGroup->checkedId();
+  if ( shapeID < 0 || shapeID > 2 )
+    shapeID = 0;
+
+  myGO[ shapeID ] = GEOM::GEOM_Object::_nil();
+  myLineEdit[ shapeID ]->clear();
+
+  if ( list.IsEmpty() )
+    return;
+
+  Handle(SALOME_InteractiveObject) io = list.First();
+  if ( !io->hasEntry() )
+    return;
+
+  myGO[ shapeID ] = SMESH::IObjectToInterface<GEOM::GEOM_Object>( io );
+
+  if ( !myGO[ shapeID ]->_is_nil() )
+    myLineEdit[ shapeID ]->setText( SMESH::toQStr( myGO[ shapeID ]->GetName() ));
+
+  updateButtons();
+}
+
+//================================================================================
+/*!
+ * \brief Display selected block CS in myLineEdit's
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::onTreeSelectionChange()
+{
+  QList<QTreeWidgetItem *> items = myBlockTree->selectedItems();
+  for ( QTreeWidgetItem* item : items )
+  {
+    if ( item->parent() )
+      item = item->parent();
+
+    QTreeWidgetItem* items[3] = { item, item->child( 0 ), item->child( 1 ) };
+    if ( items[1] && items[2] )
+      for ( int i = 0; i < 3; ++i )
+      {
+        myGO[i] = toGeom( items[i]->data( 1, Qt::UserRole ).toString() );
+        myLineEdit[i]->setText( items[i]->text( 1 ));
+      }
+
+    break;
+  }
+
+  updateButtons();
+}
+
+//================================================================================
+/*!
+ * \brief Activate/deactivate buttons
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::updateButtons()
+{
+  bool isSolidInTree = findSolidInTree( myGO[0], myBlockTree );
+  myAddBut   ->setEnabled( !isSolidInTree &&
+                           !myGO[0]->_is_nil() && !myGO[1]->_is_nil() && !myGO[2]->_is_nil() );
+  myModifBut ->setEnabled( isSolidInTree );
+  myRemoveBut->setEnabled( !myBlockTree->selectedItems().isEmpty() ||
+                           myBlockTree->topLevelItemCount() == 1 );
+}
+
+//================================================================================
+/*!
+ * \brief Install filter upon activation of another object selection
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::onSelectBtnClick()
+{
+  int shapeID = myButGroup->checkedId();
+  LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
+  selMgr->clearFilters();
+  selMgr->installFilter( shapeID > 0 ? &myVertexFilter : &mySolidFilter );
+}
+
+//================================================================================
+/*!
+ * \brief Add shapes to the tree
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::onAddBtnClick()
+{
+  setBlockToTree();
+  updateButtons();
+}
+
+//================================================================================
+/*!
+ * \brief Modify a current block
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::onModifBtnClick()
+{
+  if ( QTreeWidgetItem* item = findSolidInTree( myGO[0], myBlockTree ))
+  {
+    setBlockToTree( item );
+  }
+  updateButtons();
+}
+
+//================================================================================
+/*!
+ * \brief Remove selected block from the tree
+ */
+//================================================================================
+
+void StdMeshersGUI_BlockRenumberCreator::onRemoveBtnClick()
+{
+  QList<QTreeWidgetItem *> items = myBlockTree->selectedItems();
+  if ( items.isEmpty() && myBlockTree->topLevelItemCount() == 1 )
+    items.push_back( myBlockTree->topLevelItem( 0 ));
+
+  for ( QTreeWidgetItem* item : items )
+  {
+    if ( item->parent() )
+      item = item->parent();
+    delete item;
+  }
+
+  updateButtons();
+}
+
+
+//================================================================================
+/*!
+ * \brief Validate parameters
+ */
+//================================================================================
+
+bool StdMeshersGUI_BlockRenumberCreator::checkParams( QString& msg ) const
+{
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Returns a name of help page
+ */
+//================================================================================
+
+QString StdMeshersGUI_BlockRenumberCreator::helpPage() const
+{
+  return "block_renumber.html";
+}
+
+//================================================================================
+/*!
+ * \brief Type name
+ */
+//================================================================================
+
+QString  StdMeshersGUI_BlockRenumberCreator::hypTypeName( const QString& ) const
+{
+  return "BLOCK_RENUMBER";
+}
diff --git a/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.h b/src/StdMeshersGUI/StdMeshersGUI_BlockRenumberCreator.h
new file mode 100644 (file)
index 0000000..f3fe31d
--- /dev/null
@@ -0,0 +1,89 @@
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File   : StdMeshersGUI_BlockRenumberCreator.h
+// Author : Open CASCADE S.A.S.
+//
+#ifndef STDMESHERSGUI_BlockRenumberCreator_H
+#define STDMESHERSGUI_BlockRenumberCreator_H
+
+#include "SMESH_NumberFilter.hxx"
+#include "SMESH_StdMeshersGUI.hxx"
+#include "StdMeshersGUI_StdHypothesisCreator.h"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(GEOM_Gen)
+//#include CORBA_SERVER_HEADER(SMESH_Hypothesis)
+
+class QButtonGroup;
+class QLineEdit;
+class QString;
+class QTreeWidget;
+class QTreeWidgetItem;
+
+class STDMESHERSGUI_EXPORT StdMeshersGUI_BlockRenumberCreator : public StdMeshersGUI_StdHypothesisCreator
+{
+  Q_OBJECT
+
+public:
+  StdMeshersGUI_BlockRenumberCreator( const QString& aHypType );
+  ~StdMeshersGUI_BlockRenumberCreator();
+
+  virtual bool     checkParams( QString& ) const override;
+  virtual QString  helpPage() const override;
+  virtual QString  hypTypeName( const QString& ) const override;
+
+protected:
+  virtual QFrame*  buildFrame() override;
+  virtual void     retrieveParams() const override;
+  virtual QString  storeParams() const override;
+
+private slots:
+  void             onSelectionChange();
+  void             onTreeSelectionChange();
+  void             updateButtons();
+  void             onSelectBtnClick();
+  void             onAddBtnClick();
+  void             onModifBtnClick();
+  void             onRemoveBtnClick();
+
+private:
+  
+  void             setBlockToTree( QTreeWidgetItem* item = 0 );
+
+  QLineEdit*       myName;
+  QTreeWidget*     myBlockTree;
+
+  QPushButton*     myShapeSelectBut[3];
+  QButtonGroup*    myButGroup;
+  QLineEdit*       myLineEdit[3];
+
+  QPushButton*     myAddBut;
+  QPushButton*     myModifBut;
+  QPushButton*     myRemoveBut;
+
+  GEOM::GEOM_Object_var myGO[3];
+
+  SMESH_NumberFilter mySolidFilter, myVertexFilter;
+};
+
+#endif // STDMESHERSGUI_BlockRenumberCreator_H
index 681bf7bed80000aadedbc890d174e1040688ddf9..3b41151ac3e9007a479c355a8dcb94709d02f92a 100644 (file)
             <source>ICON_DLG_START_END_LENGTH</source>
             <translation>mesh_hypo_length.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_BLOCK_RENUMBER</source>
+            <translation>mesh_tree_hypo_renumber.png</translation>
+        </message>
         <message>
             <source>ICON_SELECT</source>
             <translation>select1.png</translation>
             <source>ICON_SMESH_TREE_HYPO_QuadraticMesh</source>
             <translation>mesh_tree_hypo_quadratic.png</translation>
         </message>
+        <message>
+            <source>ICON_SMESH_TREE_HYPO_BlockRenumber</source>
+            <translation>mesh_tree_hypo_renumber.png</translation>
+        </message>
         <message>
             <source>ICON_SMESH_TREE_HYPO_SegmentLengthAroundVertex</source>
             <translation>mesh_tree_hypo_length.png</translation>
index 0c0509f1996954e988f6f0a0e7697b1925d59f16..1af404162c1bf992337b10914b48423e7b72b230 100644 (file)
@@ -508,6 +508,14 @@ this one for this mesh/sub-mesh.</translation>
         <source>SMESH_QUAD_TYPE</source>
         <translation>Type</translation>
     </message>
+    <message>
+        <source>SMESH_BLOCK_RENUMBER_TITLE</source>
+        <translation>Hypothesis Construction</translation>
+    </message>
+    <message>
+        <source>SMESH_BLOCK_RENUMBER_HYPOTHESIS</source>
+        <translation>Renumber</translation>
+    </message>
 </context>
 <context>
     <name>StdMeshersGUI_QuadrangleParamWdg</name>
@@ -679,4 +687,55 @@ this one for this mesh/sub-mesh.</translation>
         <translation>Chain %1 (%2 edges)</translation>
     </message>
 </context>
+<context>
+    <name>StdMeshersGUI_BlockRenumberCreator</name>
+    <message>
+        <source>BLOCK_CS_GROUPBOX</source>
+        <translation>Block coordinate system</translation>
+    </message>
+    <message>
+        <source>SOLID</source>
+        <translation>Solid</translation>
+    </message>
+    <message>
+        <source>V000</source>
+        <translation>Vertex (0,0,0)</translation>
+    </message>
+    <message>
+        <source>V001</source>
+        <translation>Vertex (0,0,1)</translation>
+    </message>
+    <message>
+        <source>ADD</source>
+        <translation>Add</translation>
+    </message>
+    <message>
+        <source>MODIFY</source>
+        <translation>Modify</translation>
+    </message>
+    <message>
+        <source>COLUMN_BLOCK</source>
+        <translation>Block</translation>
+    </message>
+    <message>
+        <source>COLUMN_V000</source>
+        <translation>Vertex (0,0,0)</translation>
+    </message>
+    <message>
+        <source>COLUMN_V001</source>
+        <translation>Vertex (0,0,1)</translation>
+    </message>
+    <message>
+        <source>BLOCK_LABEL</source>
+        <translation>Block: </translation>
+    </message>
+    <message>
+        <source>V000_LABEL</source>
+        <translation>Vertex (0,0,0): </translation>
+    </message>
+    <message>
+        <source>V001_LABEL</source>
+        <translation>Vertex (0,0,1): </translation>
+    </message>
+</context>
 </TS>
index e4e0f27f46148f86b77846704d6ac895e97fd7a1..8dbfc245d102d70e10b42685768b8963958a8d58 100644 (file)
@@ -119,6 +119,7 @@ SET(StdMeshersEngine_HEADERS
   StdMeshers_Cartesian_3D_i.hxx
   StdMeshers_PolygonPerFace_2D_i.hxx
   StdMeshers_PolyhedronPerSolid_3D_i.hxx
+  StdMeshers_BlockRenumber_i.hxx
 )
 IF(SALOME_SMESH_ENABLE_MEFISTO)
   SET(StdMeshersEngine_HEADERS ${StdMeshersEngine_HEADERS} StdMeshers_MEFISTO_2D_i.hxx)
@@ -175,6 +176,7 @@ SET(StdMeshersEngine_SOURCES
   StdMeshers_Adaptive1D_i.cxx 
   StdMeshers_PolygonPerFace_2D_i.cxx
   StdMeshers_PolyhedronPerSolid_3D_i.cxx
+  StdMeshers_BlockRenumber_i.cxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
diff --git a/src/StdMeshers_I/StdMeshers_BlockRenumber_i.cxx b/src/StdMeshers_I/StdMeshers_BlockRenumber_i.cxx
new file mode 100644 (file)
index 0000000..7c517ca
--- /dev/null
@@ -0,0 +1,189 @@
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes
+//  File   : StdMeshers_BlockRenumber_i.cxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+//
+#include "StdMeshers_ObjRefUlils.hxx"
+#include "StdMeshers_BlockRenumber_i.hxx"
+#include "SMESH_Gen_i.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_PythonDump.hxx"
+
+#include "Utils_CorbaException.hxx"
+
+//=============================================================================
+/*!
+ *  StdMeshers_BlockRenumber_i::StdMeshers_BlockRenumber_i
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_BlockRenumber_i::StdMeshers_BlockRenumber_i( PortableServer::POA_ptr thePOA,
+                                                        ::SMESH_Gen*            theGenImpl )
+  : SALOME::GenericObj_i( thePOA ),
+    SMESH_Hypothesis_i( thePOA )
+{
+  myBaseImpl = new ::StdMeshers_BlockRenumber( theGenImpl->GetANewId(),
+                                               theGenImpl );
+}
+
+//================================================================================
+/*!
+ * \brief Set orientation of blocks
+ */
+//================================================================================
+
+void StdMeshers_BlockRenumber_i::SetBlocksOrientation( const StdMeshers::blockcs_array& blockCS )
+{
+  try {
+    SMESH_Comment dump;
+    CORBA::String_var entry;
+    std::vector< StdMeshers_BlockCS > bcsVec( blockCS.length() );
+    for ( size_t i = 0; i < bcsVec.size(); i++ )
+    {
+      StdMeshers_BlockCS& bcs = bcsVec[i];
+      if ( !CORBA::is_nil( blockCS[i].solid )    &&
+           !CORBA::is_nil( blockCS[i].vertex000 )&&
+           !CORBA::is_nil( blockCS[i].vertex001 ))
+      {
+        entry          = blockCS[i].solid->GetStudyEntry();
+        bcs._solid     = entry.in();
+        entry          = blockCS[i].vertex000->GetStudyEntry();
+        bcs._vertex000 = entry.in();
+        entry          = blockCS[i].vertex001->GetStudyEntry();
+        bcs._vertex001 = entry.in();
+
+        if ( !dump.empty() ) dump << ",\n    ";
+        dump << "StdMeshers.BlockCS( "
+             << bcs._solid << ", " << bcs._vertex000 << ", " << bcs._vertex001
+             << " )";
+      }
+    }
+    this->GetImpl()->SetBlocksOrientation( bcsVec );
+
+    // Update Python script
+    SMESH::TPythonDump() << _this() << ".SetBlocksOrientation([ " << dump << " ])";
+  }
+  catch ( SALOME_Exception& S_ex ) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Return orientation of blocks
+ */
+//================================================================================
+
+StdMeshers::blockcs_array*  StdMeshers_BlockRenumber_i::GetBlocksOrientation()
+{
+  const std::vector< StdMeshers_BlockCS >& bcsVec =  this->GetImpl()->GetBlocksOrientation();
+  StdMeshers::blockcs_array_var          bcsArray = new StdMeshers::blockcs_array();
+  bcsArray->length( bcsVec.size() );
+  TopoDS_Shape nullShape;
+  for ( size_t i = 0; i < bcsVec.size(); ++i )
+  {
+    bcsArray[i].solid =
+      StdMeshers_ObjRefUlils::EntryOrShapeToGeomObject( bcsVec[i]._solid, nullShape );
+    bcsArray[i].vertex000 =
+      StdMeshers_ObjRefUlils::EntryOrShapeToGeomObject( bcsVec[i]._vertex000, nullShape );
+    bcsArray[i].vertex001 =
+      StdMeshers_ObjRefUlils::EntryOrShapeToGeomObject( bcsVec[i]._vertex001, nullShape );
+  }
+  return bcsArray._retn();
+}
+
+//================================================================================
+/*!
+ * \brief Return geom entries
+ */
+//================================================================================
+
+bool StdMeshers_BlockRenumber_i::getObjectsDependOn( std::vector< std::string > & entryArray,
+                                                     std::vector< int >         & subIDArray ) const
+{
+  const std::vector< StdMeshers_BlockCS >& bcsVec =
+    const_cast<StdMeshers_BlockRenumber_i*>(this)->GetImpl()->GetBlocksOrientation();
+  entryArray.reserve( entryArray.capacity() + 3 * bcsVec.size());
+  for ( size_t i = 0; i < bcsVec.size(); ++i )
+  {
+    entryArray.push_back( bcsVec[i]._solid     );
+    entryArray.push_back( bcsVec[i]._vertex000 );
+    entryArray.push_back( bcsVec[i]._vertex001 );
+  }
+  return !bcsVec.empty();
+}
+
+//================================================================================
+/*!
+ * \brief Update geom entries for a new geometry
+ */
+//================================================================================
+
+bool StdMeshers_BlockRenumber_i::setObjectsDependOn( std::vector< std::string > & entryArray,
+                                                     std::vector< int >         & subIDArray )
+{
+  std::vector< StdMeshers_BlockCS > bcsVec( entryArray.size() / 3 );
+  for ( size_t i = 0; i + 2 < entryArray.size(); i += 3 )
+  {
+    StdMeshers_BlockCS& bcs = bcsVec[i];
+    bcs._solid     = entryArray[ i ];
+    bcs._vertex000 = entryArray[ i + 1 ];
+    bcs._vertex001 = entryArray[ i + 2 ];
+  }
+  this->GetImpl()->SetBlocksOrientation( bcsVec );
+  return true;
+}
+
+
+//=============================================================================
+/*!
+ *  StdMeshers_BlockRenumber_i::GetImpl
+ *
+ *  Get implementation
+ */
+//=============================================================================
+
+::StdMeshers_BlockRenumber* StdMeshers_BlockRenumber_i::GetImpl()
+{
+  return ( ::StdMeshers_BlockRenumber* )myBaseImpl;
+}
+
+//================================================================================
+/*!
+ * \brief Verify whether hypothesis supports given entity type
+ * \param type - dimension (see SMESH::Dimension enumeration)
+ * \retval CORBA::Boolean - TRUE if dimension is supported, FALSE otherwise
+ *
+ * Verify whether hypothesis supports given entity type (see SMESH::Dimension enumeration)
+ */
+//================================================================================
+CORBA::Boolean StdMeshers_BlockRenumber_i::IsDimSupported( SMESH::Dimension type )
+{
+  return type == SMESH::DIM_3D;
+}
+
diff --git a/src/StdMeshers_I/StdMeshers_BlockRenumber_i.hxx b/src/StdMeshers_I/StdMeshers_BlockRenumber_i.hxx
new file mode 100644 (file)
index 0000000..42291fd
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : StdMeshers_BlockRenumber_i.hxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//
+#ifndef _SMESH_BlockRenumber_I_HXX_
+#define _SMESH_BlockRenumber_I_HXX_
+
+#include "SMESH_StdMeshers_I.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
+
+#include "SMESH_Hypothesis_i.hxx"
+#include "StdMeshers_BlockRenumber.hxx"
+
+class SMESH_Gen;
+
+// =========================================================
+/*!
+ * \class 3D Hypothesis used by Hexahedron(ijk) algorithm
+ *        to renumber mesh of a block to be structured-like
+ */
+// =========================================================
+
+class STDMESHERS_I_EXPORT StdMeshers_BlockRenumber_i:
+  public virtual POA_StdMeshers::StdMeshers_BlockRenumber,
+  public virtual SMESH_Hypothesis_i
+{
+public:
+
+  StdMeshers_BlockRenumber_i( PortableServer::POA_ptr thePOA,
+                              ::SMESH_Gen*            theGenImpl );
+
+  // Set orientation of blocks
+  void SetBlocksOrientation( const StdMeshers::blockcs_array& blockCS ) override;
+
+  // Return orientation of blocks
+  StdMeshers::blockcs_array* GetBlocksOrientation() override;
+
+
+  // Get implementation
+  ::StdMeshers_BlockRenumber* GetImpl();
+
+  // Verify whether hypothesis supports given entity type
+  CORBA::Boolean IsDimSupported( SMESH::Dimension type ) override;
+
+  // Methods for copying mesh definition to other geometry
+  bool getObjectsDependOn( std::vector< std::string > & entryArray,
+                           std::vector< int >         & subIDArray ) const override;
+  bool setObjectsDependOn( std::vector< std::string > & entryArray,
+                           std::vector< int >         & subIDArray ) override;
+};
+
+#endif
index 2bd9e4eda848788b145ecae6b9a7ff2750eb6aa9..9038d2f58ce77ada94a66f53608e47a1803345b0 100644 (file)
@@ -34,6 +34,7 @@
 #include "StdMeshers_Adaptive1D_i.hxx"
 #include "StdMeshers_Arithmetic1D_i.hxx"
 #include "StdMeshers_AutomaticLength_i.hxx"
+#include "StdMeshers_BlockRenumber_i.hxx"
 #include "StdMeshers_CartesianParameters3D_i.hxx"
 #include "StdMeshers_Cartesian_3D_i.hxx"
 #include "StdMeshers_CompositeSegment_1D_i.hxx"
@@ -207,6 +208,8 @@ STDMESHERS_I_EXPORT
       aCreator = new StdHypothesisCreator_i<StdMeshers_ViscousLayers2D_i>;
     else if (strcmp(aHypName, "CartesianParameters3D") == 0)
       aCreator = new StdHypothesisCreator_i<StdMeshers_CartesianParameters3D_i>;
+    else if (strcmp(aHypName, "BlockRenumber") == 0)
+      aCreator = new StdHypothesisCreator_i<StdMeshers_BlockRenumber_i>;
 
     // Algorithms
     else if (strcmp(aHypName, "Regular_1D") == 0)