Salome HOME
Merge branch 'master' into V9_dev
authorrnv <rnv@opencascade.com>
Thu, 20 Jul 2017 09:00:49 +0000 (12:00 +0300)
committerrnv <rnv@opencascade.com>
Thu, 20 Jul 2017 09:00:49 +0000 (12:00 +0300)
19 files changed:
doc/salome/examples/modifying_meshes_ex22.py
doc/salome/gui/SMESH/doxyfile_py.in
src/Controls/SMESH_Controls.cxx
src/SMDS/ObjectPool.hxx
src/SMDS/SMDS_MeshGroup.cxx
src/SMESH/SMESH_MesherHelper.cxx
src/SMESHDS/SMESHDS_GroupBase.cxx
src/SMESHDS/SMESHDS_GroupBase.hxx
src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx
src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHUtils/SMESH_MeshAlgos.cxx
src/SMESH_I/SMESH_Group_i.cxx
src/SMESH_SWIG/smeshBuilder.py
src/StdMeshers/StdMeshers_Cartesian_3D.cxx
src/StdMeshers/StdMeshers_Import_1D2D.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
src/StdMeshers/StdMeshers_ViscousLayers.cxx
src/StdMeshers/StdMeshers_ViscousLayers2D.cxx

index 32466ccf0d6c96a56b050062e55df2569a10548f..d9e1f97d9431a6ca63509bb465fe4d45310abb0a 100644 (file)
@@ -1,34 +1,90 @@
 # Extrusion
 
 
-import salome
+import salome, math
 salome.salome_init()
-import GEOM
 from salome.geom import geomBuilder
 geompy = geomBuilder.New()
 
-import SMESH, SALOMEDS
+import SMESH
 from salome.smesh import smeshBuilder
 smesh =  smeshBuilder.New()
 
-import SMESH_mechanic
+# create an empty mesh
+mesh = smesh.Mesh() 
 
-#smesh = SMESH_mechanic.smesh
-mesh = SMESH_mechanic.mesh 
+# add a node
+mesh.AddNode( 0.,0.,0. )
 
-# select the top face
-faces = geompy.SubShapeAllSorted(SMESH_mechanic.shape_mesh, geompy.ShapeType["FACE"])
-face = faces[7]
-geompy.addToStudyInFather(SMESH_mechanic.shape_mesh, face, "face circular top")
+# extrude a node into a line of 10 segments along the X axis
+ids = mesh.GetNodesId()
+stepVector = [1.,0.,0.]
+nbSteps = 10
+mesh.ExtrusionSweep( ids, stepVector, nbSteps, IsNodes=True )
 
-# create a vector for extrusion
-point = SMESH.PointStruct(0., 0., 5.)
-vector = SMESH.DirStruct(point)
+# create some groups
+lastNode      = mesh.GetNodesId()[-1]
+lastNodeGroup = mesh.MakeGroupByIds( "node %s"% lastNode, SMESH.NODE, [lastNode])
+lineGroup     = mesh.MakeGroupByIds( "line", SMESH.EDGE, mesh.GetElementsId() )
 
-# create a group to be extruded
-GroupTri = mesh.GroupOnGeom(face, "Group of faces (extrusion)", SMESH.FACE)
+# rotate the segments around the first node to get a mesh of a disk quarter
+axisZ  = [0.,0.,0., 0.,0.,1.]
+groups = mesh.RotationSweepObject( lineGroup, axisZ, math.pi/2., 10, 1e-3, MakeGroups=True, TotalAngle=True )
 
-# perform extrusion of the group
-mesh.ExtrusionSweepObject(GroupTri, vector, 5)
+# extrude all faces into volumes
+obj        = mesh
+stepVector = [0.,0.,-1.]
+nbSteps    = 5
+groups = mesh.ExtrusionSweepObject2D( obj, stepVector, nbSteps, MakeGroups=True )
+
+# remove all segments created by the last command
+for g in groups:
+    if g.GetType() == SMESH.EDGE:
+        mesh.RemoveGroupWithContents( g )
+
+# extrude all segments into faces along Z
+obj = mesh
+stepVector = [0.,0.,1.]
+mesh.ExtrusionSweepObject1D( obj, stepVector, nbSteps )
+
+# extrude a group
+lineExtruded = None
+for g in mesh.GetGroups( SMESH.FACE ):
+    if g.GetName() == "line_extruded":
+        lineExtruded = g
+        break
+obj        = lineExtruded
+stepVector = [0,-5.,0.]
+nbSteps    = 1
+mesh.ExtrusionSweepObject( obj, stepVector, nbSteps )
+
+# extrude all nodes and triangle faces of the disk quarter, applying a scale factor
+diskGroup = None
+for g in mesh.GetGroups( SMESH.FACE ):
+    if g.GetName() == "line_rotated":
+        diskGroup = g
+        break
+crit = [ smesh.GetCriterion( SMESH.FACE, SMESH.FT_ElemGeomType,'=',SMESH.Geom_TRIANGLE ),
+         smesh.GetCriterion( SMESH.FACE, SMESH.FT_BelongToMeshGroup,'=', diskGroup )]
+trianglesFilter = smesh.GetFilterFromCriteria( crit )
+
+nodes      = [ diskGroup ]
+edges      = []
+faces      = [ trianglesFilter ]
+stepVector = [0,0,1]
+nbSteps    = 10
+mesh.ExtrusionSweepObjects( nodes, edges, faces, stepVector, nbSteps, scaleFactors=[0.5], linearVariation=True )
+
+# extrude a cylindrical group of faces by normal
+cylGroup = None
+for g in mesh.GetGroups( SMESH.FACE ):
+    if g.GetName().startswith("node "):
+        cylGroup = g
+        break
+
+elements = cylGroup
+stepSize = 5.
+nbSteps  = 2
+mesh.ExtrusionByNormal( elements, stepSize, nbSteps )
 
 salome.sg.updateObjBrowser()
index d48007ab2988b9beab705ed9ebfcf09f62ca18d6..50b8dbe3e5ef7c9f9c38fcd024846a74892c3108 100755 (executable)
@@ -103,11 +103,12 @@ INPUT             = tmp2/smeshBuilder.py \
                     tmp2/smesh_algorithm.py \
                     tmp2/StdMeshersBuilder.py \
                     tmp2/smeshstudytools.py \
-                    tmp1/smeshBuilder.py
-FILE_PATTERNS     = 
+                    tmp1/smeshBuilder.py \
+                    @CMAKE_CURRENT_SOURCE_DIR@/input
+FILE_PATTERNS     = tui_*.doc
 IMAGE_PATH        = @CMAKE_CURRENT_SOURCE_DIR@/images
 RECURSIVE         = NO
-EXAMPLE_PATH      = @CMAKE_SOURCE_DIR@/src/SMESH_SWIG
+EXAMPLE_PATH      = @CMAKE_SOURCE_DIR@/src/SMESH_SWIG @CMAKE_SOURCE_DIR@/doc/salome/examples
 
 #---------------------------------------------------------------------------
 #HTML related options
@@ -165,3 +166,8 @@ DOT_CLEANUP            = YES
 #---------------------------------------------------------------------------
 GENERATE_TAGFILE  = smeshpy_doc.tag
 SEARCHENGINE           = YES
+
+#---------------------------------------------------------------------------
+#Custom commands
+#---------------------------------------------------------------------------
+ALIASES += tui_script{1}="\include \1 <a href=\"../../examples/SMESH/\1\">Download this script</a>"
index 6e80cc77ad1a53324ea380b885c3cc6eb78c1a8b..ee372e22239ca26fdeede963c30de29d18e2beaf 100644 (file)
@@ -4493,7 +4493,7 @@ bool ElementsOnShape::Classifier::isOutOfFace  (const gp_Pnt& p)
   if ( myProjFace.IsDone() && myProjFace.LowerDistance() <= myTol )
   {
     // check relatively to the face
-    Quantity_Parameter u, v;
+    Standard_Real u, v;
     myProjFace.LowerDistanceParameters(u, v);
     gp_Pnt2d aProjPnt (u, v);
     BRepClass_FaceClassifier aClsf ( TopoDS::Face( myShape ), aProjPnt, myTol );
index 5e5f0d289d275eff3d2c3d10a6b99d80b88d400d..ef514b353b0388fdcf4b61eb0cb8924a1742327e 100644 (file)
 #define _OBJECTPOOL_HXX_
 
 #include <vector>
-//#include <stack>
 #include <iostream>
 
+#include "SMDS_Iterator.hxx"
+
 namespace
 {
   // assure deallocation of memory of a vector
@@ -33,18 +34,22 @@ namespace
   }
 }
 
+template<class X> class ObjectPoolIterator;
+
 template<class X> class ObjectPool
 {
 
 private:
-  std::vector<X*> _chunkList;
+  std::vector<X*>   _chunkList;
   std::vector<bool> _freeList;
-  int _nextFree;
-  int _maxAvail;
-  int _chunkSize;
-  int _maxOccupied;
-  int _nbHoles;
-  int _lastDelChunk;
+  int               _nextFree;    // either the 1st hole or last added
+  int               _maxAvail;    // nb allocated elements
+  int               _chunkSize;
+  int               _maxOccupied; // max used ID
+  int               _nbHoles;
+  int               _lastDelChunk;
+
+  friend class ObjectPoolIterator<X>;
 
   int getNextFree()
   {
@@ -76,16 +81,16 @@ private:
   }
 
 public:
-  ObjectPool(int nblk)
+  ObjectPool(int nblk = 1024)
   {
-    _chunkSize = nblk;
-    _nextFree = 0;
-    _maxAvail = 0;
-    _maxOccupied = 0;
-    _nbHoles = 0;
+    _chunkSize    = nblk;
+    _nextFree     = 0;
+    _maxAvail     = 0;
+    _maxOccupied  = -1;
+    _nbHoles      = 0;
+    _lastDelChunk = 0;
     _chunkList.clear();
     _freeList.clear();
-    _lastDelChunk = 0;
   }
 
   virtual ~ObjectPool()
@@ -105,16 +110,16 @@ public:
         _freeList.insert(_freeList.end(), _chunkSize, true);
         _maxAvail += _chunkSize;
         _freeList[_nextFree] = false;
-        obj = newChunk; // &newChunk[0];
+        obj = newChunk;
       }
     else
       {
         int chunkId = _nextFree / _chunkSize;
         int rank = _nextFree - chunkId * _chunkSize;
         _freeList[_nextFree] = false;
-        obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
+        obj = _chunkList[chunkId] + rank;
       }
-    if (_nextFree < _maxOccupied)
+    if (_nextFree <= _maxOccupied)
       {
         _nbHoles-=1;
       }
@@ -122,7 +127,6 @@ public:
       {
         _maxOccupied = _nextFree;
       }
-    //obj->init();
     return obj;
   }
 
@@ -148,10 +152,10 @@ public:
     if (toFree < _nextFree)
       _nextFree = toFree;
     if (toFree < _maxOccupied)
-      _nbHoles += 1;
+      ++_nbHoles;
+    else
+      --_maxOccupied;
     _lastDelChunk = i;
-    //obj->clean();
-    //checkDelete(i); compactage non fait
   }
 
   void clear()
@@ -167,6 +171,37 @@ public:
     clearVector( _freeList );
   }
 
+  // nb allocated elements
+  size_t size() const
+  {
+    return _freeList.size();
+  }
+
+  // nb used elements
+  size_t nbElements() const
+  {
+    return _maxOccupied + 1 - _nbHoles;
+  }
+
+  // return an element w/o any check
+  const X* operator[]( size_t i ) const // i < size()
+  {
+    int chunkId = i / _chunkSize;
+    int    rank = i - chunkId * _chunkSize;
+    return _chunkList[ chunkId ] + rank;
+  }
+
+  // return only being used element
+  const X* at( size_t i ) const // i < size()
+  {
+    if ( i >= size() || _freeList[ i ] )
+      return 0;
+
+    int chunkId = i / _chunkSize;
+    int    rank = i - chunkId * _chunkSize;
+    return _chunkList[ chunkId ] + rank;
+  }
+
   //  void destroy(int toFree)
   //  {
   //    // no control 0<= toFree < _freeList.size()
@@ -177,4 +212,41 @@ public:
 
 };
 
+template<class X> class ObjectPoolIterator : public SMDS_Iterator<const X*>
+{
+  const ObjectPool<X>& _pool;
+  int                  _i, _nbFound;
+public:
+
+  ObjectPoolIterator( const ObjectPool<X>& pool ) : _pool( pool ), _i( 0 ), _nbFound( 0 )
+  {
+    if ( more() && _pool._freeList[ _i ] == true )
+    {
+      next();
+      --_nbFound;
+    }
+  }
+
+  virtual bool more()
+  {
+    return ( _i <= _pool._maxOccupied && _nbFound < (int)_pool.nbElements() );
+  }
+
+  virtual const X* next()
+  {
+    const X* x = 0;
+    if ( more() )
+    {
+      x = _pool[ _i ];
+
+      ++_nbFound;
+
+      for ( ++_i; _i <= _pool._maxOccupied; ++_i )
+        if ( _pool._freeList[ _i ] == false )
+          break;
+    }
+    return x;
+  }
+};
+
 #endif
index eb2331f989e42b7c6b311800cd53700300658e23..f61079353f7a78bbd240f86eae85c1e02d572f1a 100644 (file)
@@ -163,7 +163,7 @@ bool SMDS_MeshGroup::Remove(const SMDS_MeshElement * theElem)
 
 bool SMDS_MeshGroup::Contains(const SMDS_MeshElement * theElem) const
 {
-        return myElements.find(theElem)!=myElements.end();
+  return myElements.find(theElem) != myElements.end();
 }
 
 //=======================================================================
index 004c856f1bae102ebbdc2e7a4bd6b56966ccaef4..4d8f9952a0749638ba138ce458ae7f1c2825630c 100644 (file)
@@ -824,7 +824,7 @@ bool SMESH_MesherHelper::CheckNodeUV(const TopoDS_Face&   F,
         MESSAGE( "SMESH_MesherHelper::CheckNodeUV() failed to project" );
         return false;
       }
-      Quantity_Parameter U,V;
+      Standard_Real U,V;
       projector.LowerDistanceParameters(U,V);
       uv.SetCoord( U,V );
       surfPnt = surface->Value( U, V );
@@ -1130,7 +1130,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge&   E,
           MESSAGE( "SMESH_MesherHelper::CheckNodeU() failed to project" );
           return false;
         }
-        Quantity_Parameter U = projector->LowerDistanceParameter();
+        Standard_Real U = projector->LowerDistanceParameter();
         u = double( U );
         curvPnt = curve->Value( u );
         dist = nodePnt.Distance( curvPnt );
index 7d4d10fdfc9f41f8fff17b1f3db466370501b952..95a91cd0c7f5e40f09de0e75b18e9cfb528b67b2 100644 (file)
@@ -51,7 +51,7 @@ SMESHDS_GroupBase::SMESHDS_GroupBase (const int                 theID,
 
 //=============================================================================
 /*!
- *  
+ *  Don't use it!
  */
 //=============================================================================
 
index bb0bf250f413682ecf642e61fc4fd9a75bca8ce8..625e64a51f4fe4a7674b315534c7f6f16f2269dd 100644 (file)
@@ -69,7 +69,7 @@ class SMESHDS_EXPORT SMESHDS_GroupBase
   virtual SMDS_ElemIteratorPtr GetElements() const = 0;
 
   virtual int GetID (const int theIndex);
-  // use it for iterations 1..Extent()
+  // DON'T use it for iterations 1..Extent()
 
   virtual int GetTic() const = 0;
 
index aaf5f6801e7816bc65f882f23fd720d2da8bf6dc..3c32b743eea5fa8d1accec0b353cc8044b23e2a5 100644 (file)
@@ -77,7 +77,8 @@ SMESHGUI_GroupOnShapeDlg::SMESHGUI_GroupOnShapeDlg()
 
   // Elem geom
 
-  QGroupBox* elemsGrp = new QGroupBox( tr( "SMESH_ELEMENTS" ), mainFrame() );
+  QGroupBox* elemsGrp = new QGroupBox( tr( "ELEMENTS" ), mainFrame() );
+  elemsGrp->setToolTip( tr("ELEMENTS_TOOLTIP") );
   QLabel* label = new QLabel( tr( "SMESH_GEOM" ), elemsGrp );
   myElemGeomBtn = new QPushButton( elemsGrp );
   myElemGeomBtn->setCheckable(true);
index 1f1ee9efc667d21d729e144ac52cc706f7da0087..6820457e5d6a8b1779cfadfa47d770fc1dcf938b 100755 (executable)
@@ -974,18 +974,18 @@ void SMESHGUI_MultiEditDlg::setSelectionMode()
   }
 
   if (entityType()) {
-    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
-      aViewWindow->SetSelectionMode(VolumeSelection);
     SMESH::SetFilter(new SMESHGUI_VolumesFilter());
-  } else {
     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
-      aViewWindow->SetSelectionMode(FaceSelection);
+      aViewWindow->SetSelectionMode(VolumeSelection); // here myActor set to a filter
+  } else {
     if (myFilterType == SMESH::TriaFilter)
       SMESH::SetFilter(new SMESHGUI_TriangleFilter());
     else if (myFilterType == SMESH::QuadFilter)
       SMESH::SetFilter(new SMESHGUI_QuadrangleFilter());
     else
       SMESH::SetFilter(new SMESHGUI_FacesFilter());
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode(FaceSelection); // here myActor set to a filter
   }
 }
 
index 2a0601830e89c7583f3eff093d7cb9f815b95811..a5e80c6594129f1b5e6b9f370e5f2a5c779e4f0f 100644 (file)
@@ -6996,6 +6996,14 @@ It is impossible to read point coordinates from file</translation>
         <source>SMESH_CREATE_GROUP_FROM_GEOM</source>
         <translation>Create Groups from Geometry</translation>
     </message>
+    <message>
+        <source>ELEMENTS</source>
+        <translation>Elements</translation>
+    </message>
+    <message>
+        <source>ELEMENTS_TOOLTIP</source>
+        <translation>No 0D elements</translation>
+    </message>
 </context>
 <context>
     <name>SMESHGUI_MeshOrderDlg</name>
index 1eae5f7818e23d205812d4330a7e8437c34349cb..8464e245fe197e6765f100a08498d730211522bb 100644 (file)
@@ -228,15 +228,15 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
                       SMDSAbs_ElementType  elemType,
                       SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(),
                       double               tolerance = NodeRadius );
-    void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems );
-    void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems);
-    void getElementsInSphere ( const gp_XYZ& center,
-                               const double  radius, TIDSortedElemSet& foundElems);
-    size_t getSize() { return std::max( _size, _elements.size() ); }
-    virtual ~ElementBndBoxTree();
+    void prepare(); // !!!call it before calling the following methods!!!
+    void getElementsNearPoint( const gp_Pnt& point, vector<const SMDS_MeshElement*>& foundElems );
+    void getElementsNearLine ( const gp_Ax1& line,  vector<const SMDS_MeshElement*>& foundElems);
+    void getElementsInSphere ( const gp_XYZ&                    center,
+                               const double                     radius,
+                               vector<const SMDS_MeshElement*>& foundElems);
 
   protected:
-    ElementBndBoxTree():_size(0) {}
+    ElementBndBoxTree() {}
     SMESH_Octree* newChild() const { return new ElementBndBoxTree; }
     void          buildChildrenData();
     Bnd_B3d*      buildRootBox();
@@ -245,11 +245,25 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
     struct ElementBox : public Bnd_B3d
     {
       const SMDS_MeshElement* _element;
-      int                     _refCount; // an ElementBox can be included in several tree branches
-      ElementBox(const SMDS_MeshElement* elem, double tolerance);
+      bool                    _isMarked;
+      void init(const SMDS_MeshElement* elem, double tolerance);
     };
     vector< ElementBox* > _elements;
-    size_t                _size;
+
+    typedef ObjectPool< ElementBox > TElementBoxPool;
+
+    //!< allocator of ElementBox's and SMESH_TreeLimit
+    struct LimitAndPool : public SMESH_TreeLimit
+    {
+      TElementBoxPool            _elBoPool;
+      std::vector< ElementBox* > _markedElems;
+      LimitAndPool():SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ) {}
+    };
+    LimitAndPool* getLimitAndPool() const
+    {
+      SMESH_TreeLimit* limitAndPool = const_cast< SMESH_TreeLimit* >( myLimit );
+      return static_cast< LimitAndPool* >( limitAndPool );
+    }
   };
 
   //================================================================================
@@ -258,32 +272,27 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance)
-    :SMESH_Octree( new SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ))
+  ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh&     mesh,
+                                       SMDSAbs_ElementType  elemType,
+                                       SMDS_ElemIteratorPtr theElemIt,
+                                       double               tolerance)
+    :SMESH_Octree( new LimitAndPool() )
   {
     int nbElems = mesh.GetMeshInfo().NbElements( elemType );
     _elements.reserve( nbElems );
 
+    TElementBoxPool& elBoPool = getLimitAndPool()->_elBoPool;
+
     SMDS_ElemIteratorPtr elemIt = theElemIt ? theElemIt : mesh.elementsIterator( elemType );
     while ( elemIt->more() )
-      _elements.push_back( new ElementBox( elemIt->next(),tolerance  ));
-
+    {
+      ElementBox* eb = elBoPool.getNew();
+      eb->init( elemIt->next(), tolerance );
+      _elements.push_back( eb );
+    }
     compute();
   }
 
-  //================================================================================
-  /*!
-   * \brief Destructor
-   */
-  //================================================================================
-
-  ElementBndBoxTree::~ElementBndBoxTree()
-  {
-    for ( size_t i = 0; i < _elements.size(); ++i )
-      if ( --_elements[i]->_refCount <= 0 )
-        delete _elements[i];
-  }
-
   //================================================================================
   /*!
    * \brief Return the maximal box
@@ -311,14 +320,10 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
       for (int j = 0; j < 8; j++)
       {
         if ( !_elements[i]->IsOut( *myChildren[j]->getBox() ))
-        {
-          _elements[i]->_refCount++;
           ((ElementBndBoxTree*)myChildren[j])->_elements.push_back( _elements[i]);
-        }
       }
-      _elements[i]->_refCount--;
     }
-    _size = _elements.size();
+    //_size = _elements.size();
     SMESHUtils::FreeVector( _elements ); // = _elements.clear() + free memory
 
     for (int j = 0; j < 8; j++)
@@ -327,33 +332,61 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
       if ((int) child->_elements.size() <= MaxNbElemsInLeaf )
         child->myIsLeaf = true;
 
-      if ( child->_elements.capacity() - child->_elements.size() > 1000 )
+      if ( child->isLeaf() && child->_elements.capacity() > child->_elements.size() )
         SMESHUtils::CompactVector( child->_elements );
     }
   }
 
+  //================================================================================
+  /*!
+   * \brief Un-mark all elements
+   */
+  //================================================================================
+
+  void ElementBndBoxTree::prepare()
+  {
+    // TElementBoxPool& elBoPool = getElementBoxPool();
+    // for ( size_t i = 0; i < elBoPool.nbElements(); ++i )
+    //   const_cast< ElementBox* >( elBoPool[ i ])->_isMarked = false;
+  }
+
   //================================================================================
   /*!
    * \brief Return elements which can include the point
    */
   //================================================================================
 
-  void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt&     point,
-                                                TIDSortedElemSet& foundElems)
+  void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt&                    point,
+                                                vector<const SMDS_MeshElement*>& foundElems)
   {
     if ( getBox()->IsOut( point.XYZ() ))
       return;
 
     if ( isLeaf() )
     {
+      LimitAndPool* pool = getLimitAndPool();
+
       for ( size_t i = 0; i < _elements.size(); ++i )
-        if ( !_elements[i]->IsOut( point.XYZ() ))
-          foundElems.insert( _elements[i]->_element );
+        if ( !_elements[i]->IsOut( point.XYZ() ) &&
+             !_elements[i]->_isMarked )
+        {
+          foundElems.push_back( _elements[i]->_element );
+          _elements[i]->_isMarked = true;
+          pool->_markedElems.push_back( _elements[i] );
+        }
     }
     else
     {
       for (int i = 0; i < 8; i++)
         ((ElementBndBoxTree*) myChildren[i])->getElementsNearPoint( point, foundElems );
+
+      if ( level() == 0 )
+      {
+        LimitAndPool* pool = getLimitAndPool();
+        for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
+          pool->_markedElems[i]->_isMarked = false;
+        pool->_markedElems.clear();
+      }
     }
   }
 
@@ -363,22 +396,37 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  void ElementBndBoxTree::getElementsNearLine( const gp_Ax1&     line,
-                                               TIDSortedElemSet& foundElems)
+  void ElementBndBoxTree::getElementsNearLine( const gp_Ax1&                    line,
+                                               vector<const SMDS_MeshElement*>& foundElems)
   {
     if ( getBox()->IsOut( line ))
       return;
 
     if ( isLeaf() )
     {
+      LimitAndPool* pool = getLimitAndPool();
+
       for ( size_t i = 0; i < _elements.size(); ++i )
-        if ( !_elements[i]->IsOut( line ))
-          foundElems.insert( _elements[i]->_element );
+        if ( !_elements[i]->IsOut( line ) &&
+             !_elements[i]->_isMarked )
+        {
+          foundElems.push_back( _elements[i]->_element );
+          _elements[i]->_isMarked = true;
+          pool->_markedElems.push_back( _elements[i] );
+        }
     }
     else
     {
       for (int i = 0; i < 8; i++)
         ((ElementBndBoxTree*) myChildren[i])->getElementsNearLine( line, foundElems );
+
+      if ( level() == 0 )
+      {
+        LimitAndPool* pool = getLimitAndPool();
+        for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
+          pool->_markedElems[i]->_isMarked = false;
+        pool->_markedElems.clear();
+      }
     }
   }
 
@@ -388,23 +436,38 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ&     center,
-                                                const double      radius,
-                                                TIDSortedElemSet& foundElems)
+  void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ&                    center,
+                                                const double                     radius,
+                                                vector<const SMDS_MeshElement*>& foundElems)
   {
     if ( getBox()->IsOut( center, radius ))
       return;
 
     if ( isLeaf() )
     {
+      LimitAndPool* pool = getLimitAndPool();
+
       for ( size_t i = 0; i < _elements.size(); ++i )
-        if ( !_elements[i]->IsOut( center, radius ))
-          foundElems.insert( _elements[i]->_element );
+        if ( !_elements[i]->IsOut( center, radius ) &&
+             !_elements[i]->_isMarked )
+        {
+          foundElems.push_back( _elements[i]->_element );
+          _elements[i]->_isMarked = true;
+          pool->_markedElems.push_back( _elements[i] );
+        }
     }
     else
     {
       for (int i = 0; i < 8; i++)
         ((ElementBndBoxTree*) myChildren[i])->getElementsInSphere( center, radius, foundElems );
+
+      if ( level() == 0 )
+      {
+        LimitAndPool* pool = getLimitAndPool();
+        for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
+          pool->_markedElems[i]->_isMarked = false;
+        pool->_markedElems.clear();
+      }
     }
   }
 
@@ -414,13 +477,13 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem, double tolerance)
+  void ElementBndBoxTree::ElementBox::init(const SMDS_MeshElement* elem, double tolerance)
   {
     _element  = elem;
-    _refCount = 1;
+    _isMarked = false;
     SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
     while ( nIt->more() )
-      Add( SMESH_TNodeXYZ( nIt->next() ));
+      Add( SMESH_NodeXYZ( nIt->next() ));
     Enlarge( tolerance );
   }
 
@@ -604,7 +667,7 @@ bool SMESH_ElementSearcherImpl::getIntersParamOnLine(const gp_Lin&           lin
     anExtCC.Init( lineCurve, edge.Value() );
     if ( anExtCC.NbExtrema() > 0 && anExtCC.LowerDistance() <= tol)
     {
-      Quantity_Parameter pl, pe;
+      Standard_Real pl, pe;
       anExtCC.LowerDistanceParameters( pl, pe );
       param += pl;
       if ( ++nbInts == 2 )
@@ -771,9 +834,13 @@ FindElementsByPoint(const gp_Pnt&                      point,
     {
       _ebbTree[_elementType] = new ElementBndBoxTree( *_mesh, type, _meshPartIt, tolerance );
     }
-    TIDSortedElemSet suspectElems;
+    else
+    {
+      _ebbTree[ type ]->prepare();
+    }
+    vector< const SMDS_MeshElement* > suspectElems;
     _ebbTree[ type ]->getElementsNearPoint( point, suspectElems );
-    TIDSortedElemSet::iterator elem = suspectElems.begin();
+    vector< const SMDS_MeshElement* >::iterator elem = suspectElems.begin();
     for ( ; elem != suspectElems.end(); ++elem )
       if ( !SMESH_MeshAlgos::IsOut( *elem, point, tolerance ))
         foundElements.push_back( *elem );
@@ -801,8 +868,10 @@ SMESH_ElementSearcherImpl::FindClosestTo( const gp_Pnt&       point,
     ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
     if ( !ebbTree )
       ebbTree = new ElementBndBoxTree( *_mesh, type, _meshPartIt );
+    else
+      ebbTree->prepare();
 
-    TIDSortedElemSet suspectElems;
+    vector<const SMDS_MeshElement*> suspectElems;
     ebbTree->getElementsNearPoint( point, suspectElems );
 
     if ( suspectElems.empty() && ebbTree->maxSize() > 0 )
@@ -816,13 +885,14 @@ SMESH_ElementSearcherImpl::FindClosestTo( const gp_Pnt&       point,
         radius = ebbTree->maxSize() / pow( 2., getTreeHeight()) / 2;
       while ( suspectElems.empty() )
       {
+        ebbTree->prepare();
         ebbTree->getElementsInSphere( point.XYZ(), radius, suspectElems );
         radius *= 1.1;
       }
     }
     double minDist = std::numeric_limits<double>::max();
     multimap< double, const SMDS_MeshElement* > dist2face;
-    TIDSortedElemSet::iterator elem = suspectElems.begin();
+    vector<const SMDS_MeshElement*>::iterator elem = suspectElems.begin();
     for ( ; elem != suspectElems.end(); ++elem )
     {
       double dist = SMESH_MeshAlgos::GetDistance( *elem, point );
@@ -886,6 +956,8 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
   ElementBndBoxTree*& ebbTree = _ebbTree[ SMDSAbs_Face ];
   if ( !ebbTree )
     ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
+  else
+    ebbTree->prepare();
 
   // Algo: analyse transition of a line starting at the point through mesh boundary;
   // try three lines parallel to axis of the coordinate system and perform rough
@@ -901,13 +973,14 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
     gp_Ax1 lineAxis( point, axisDir[axis]);
     gp_Lin line    ( lineAxis );
 
-    TIDSortedElemSet suspectFaces; // faces possibly intersecting the line
+    vector<const SMDS_MeshElement*> suspectFaces; // faces possibly intersecting the line
+    if ( axis > 0 ) ebbTree->prepare();
     ebbTree->getElementsNearLine( lineAxis, suspectFaces );
 
     // Intersect faces with the line
 
     map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
-    TIDSortedElemSet::iterator face = suspectFaces.begin();
+    vector<const SMDS_MeshElement*>::iterator face = suspectFaces.begin();
     for ( ; face != suspectFaces.end(); ++face )
     {
       // get face plane
@@ -1114,10 +1187,10 @@ void SMESH_ElementSearcherImpl::GetElementsNearLine( const gp_Ax1&
   ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
   if ( !ebbTree )
     ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
+  else
+    ebbTree->prepare();
 
-  TIDSortedElemSet suspectFaces; // elements possibly intersecting the line
-  ebbTree->getElementsNearLine( line, suspectFaces );
-  foundElems.assign( suspectFaces.begin(), suspectFaces.end());
+  ebbTree->getElementsNearLine( line, foundElems );
 }
 
 //=======================================================================
@@ -1135,10 +1208,10 @@ void SMESH_ElementSearcherImpl::GetElementsInSphere( const gp_XYZ&
   ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
   if ( !ebbTree )
     ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
+  else
+    ebbTree->prepare();
 
-  TIDSortedElemSet suspectFaces; // elements possibly intersecting the line
-  ebbTree->getElementsInSphere( center, radius, suspectFaces );
-  foundElems.assign( suspectFaces.begin(), suspectFaces.end() );
+  ebbTree->getElementsInSphere( center, radius, foundElems );
 }
 
 //=======================================================================
index ef9ad77608468615d646e17fb2de594c76c5fb55..354a1daf0fbba3a0bbd680fbe2e5d60dddde8cdd 100644 (file)
@@ -473,8 +473,9 @@ SMESH::long_array* SMESH_GroupBase_i::GetListOfID()
   {
     int aSize = aGroupDS->Extent();
     aRes->length(aSize);
-    for (int i = 0; i < aSize; i++)
-      aRes[i] = aGroupDS->GetID(i+1);
+    SMDS_ElemIteratorPtr it = aGroupDS->GetElements();
+    for (int i = 0; it->more(); i++)
+      aRes[i] = it->next()->GetID();
 
     if ( 0 < aSize && aSize < 100 ) // for comfortable testing ;)
       std::sort( &aRes[0], &aRes[0]+aSize );
index 6da2aaf29ba637d254f751255cb7afb9f1fd2a2c..bace171b6cf7ddccb9d3e9ae49dc75ca8a57b62d 100644 (file)
@@ -3930,6 +3930,7 @@ class Mesh(metaclass=MeshMeta):
     #         - a GEOM point
     #  @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
                               scaleFactors=[], linearVariation=False, basePoint=[] ):
         unRegister = genObjUnRegister()
@@ -3970,6 +3971,7 @@ class Mesh(metaclass=MeshMeta):
     #  @param IsNodes is True if elements with given ids are nodes
     #  @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
         n,e,f = [],[],[]
         if IsNodes: n = IDsOfElements
@@ -3996,6 +3998,7 @@ class Mesh(metaclass=MeshMeta):
     #  @return the list of created groups (SMESH_GroupBase) if \a MakeGroups=True,
     #          empty list otherwise.
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
                           ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
         unRegister = genObjUnRegister()
@@ -4025,6 +4028,7 @@ class Mesh(metaclass=MeshMeta):
     #  @param IsNodes is True if elements to extrude are nodes
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObject(self, theObject, StepVector, NbOfSteps, MakeGroups=False, IsNodes=False):
         n,e,f = [],[],[]
         if IsNodes: n    = theObject
@@ -4041,6 +4045,7 @@ class Mesh(metaclass=MeshMeta):
     #  @param MakeGroups to generate new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObject1D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
         return self.ExtrusionSweepObjects([],theObject,[], StepVector, NbOfSteps, MakeGroups)
 
@@ -4054,6 +4059,7 @@ class Mesh(metaclass=MeshMeta):
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObject2D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
         return self.ExtrusionSweepObjects([],[],theObject, StepVector, NbOfSteps, MakeGroups)
 
@@ -4098,6 +4104,7 @@ class Mesh(metaclass=MeshMeta):
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathMesh, PathShape=None,
                                   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
                                   HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False):
@@ -4141,6 +4148,7 @@ class Mesh(metaclass=MeshMeta):
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
                             HasAngles=False, Angles=[], LinearVariation=False,
                             HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
@@ -4173,6 +4181,7 @@ class Mesh(metaclass=MeshMeta):
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPath(self, IDsOfElements, PathMesh, PathShape, NodeStart,
                            HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                            MakeGroups=False, LinearVariation=False):
@@ -4203,6 +4212,7 @@ class Mesh(metaclass=MeshMeta):
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObject(self, theObject, PathMesh, PathShape, NodeStart,
                                  HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                  MakeGroups=False, LinearVariation=False):
@@ -4232,6 +4242,7 @@ class Mesh(metaclass=MeshMeta):
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObject1D(self, theObject, PathMesh, PathShape, NodeStart,
                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                    MakeGroups=False, LinearVariation=False):
@@ -4261,6 +4272,7 @@ class Mesh(metaclass=MeshMeta):
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObject2D(self, theObject, PathMesh, PathShape, NodeStart,
                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                    MakeGroups=False, LinearVariation=False):
index 4220d7d18211ae7f39086b4c9a860b2e8d4a681b..cf33157bf24edc68d5d4ed9a8e70bba011941dd8 100644 (file)
@@ -2924,7 +2924,7 @@ namespace
       proj.Perform( testPnt );
       if ( proj.IsDone() && proj.NbPoints() > 0 )       
       {
-        Quantity_Parameter u,v;
+        Standard_Real u,v;
         proj.LowerDistanceParameters( u,v );
 
         if ( proj.LowerDistance() <= 0.1 * _grid->_tol )
index e0e2df6664e4181ebdf98d7e3cc4fc5f1133c272..5fe88234795100292df4b272078a686225c1754c 100644 (file)
@@ -411,7 +411,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape &
           proj.Perform( gc );
           if ( !proj.IsDone() || proj.NbPoints() < 1 )
             continue;
-          Quantity_Parameter U,V;
+          Standard_Real U,V;
           proj.LowerDistanceParameters(U,V);
           gp_XY uv( U,V );
           classifier.Perform( geomFace, uv, clsfTol );
index 9a51d8a6d1c06002532fcc520a3ff6eea840cb18..300df900e2250cd025318a071fe56a40b768b60a 100644 (file)
@@ -51,7 +51,6 @@
 #include <Geom_Surface.hxx>
 #include <NCollection_DefineArray2.hxx>
 #include <Precision.hxx>
-#include <Quantity_Parameter.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
 #include <TColStd_SequenceOfReal.hxx>
 #include <TColgp_SequenceOfXY.hxx>
index eafdf22ef132433b1160be9fc79ffb6e3c07ce12..de79cbc6228602101028bf0f41c60f358c45f5ac 100644 (file)
@@ -500,6 +500,7 @@ namespace VISCOUS_3D
     gp_Ax1 LastSegment(double& segLen, _EdgesOnShape& eos) const;
     gp_XY  LastUV( const TopoDS_Face& F, _EdgesOnShape& eos, int which=-1 ) const;
     bool   IsOnEdge() const { return _2neibors; }
+    bool   IsOnFace() const { return ( _nodes[0]->GetPosition()->GetDim() == 2 ); }
     gp_XYZ Copy( _LayerEdge& other, _EdgesOnShape& eos, SMESH_MesherHelper& helper );
     void   SetCosin( double cosin );
     void   SetNormal( const gp_XYZ& n ) { _normal = n; }
@@ -2926,15 +2927,6 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data )
   // define allowed thickness
   computeGeomSize( data ); // compute data._geomSize and _LayerEdge::_maxLen
 
-  data._maxThickness = 0;
-  data._minThickness = 1e100;
-  list< const StdMeshers_ViscousLayers* >::iterator hyp = data._hyps.begin();
-  for ( ; hyp != data._hyps.end(); ++hyp )
-  {
-    data._maxThickness = Max( data._maxThickness, (*hyp)->GetTotalThickness() );
-    data._minThickness = Min( data._minThickness, (*hyp)->GetTotalThickness() );
-  }
-  //const double tgtThick = /*Min( 0.5 * data._geomSize, */data._maxThickness;
 
   // Find shapes needing smoothing; such a shape has _LayerEdge._normal on it's
   // boundary inclined to the shape at a sharp angle
@@ -3699,7 +3691,7 @@ gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
       isOK = false;
       return p.XYZ();
     }
-    Quantity_Parameter U,V;
+    Standard_Real U,V;
     projector.LowerDistanceParameters(U,V);
     uv.SetCoord( U,V );
   }
@@ -4363,7 +4355,7 @@ void _ViscousBuilder::computeGeomSize( _SolidData& data )
     _EdgesOnShape& eos = data._edgesOnShape[ iS ];
     if ( eos._edges.empty() )
       continue;
-    // get neighbor faces intersection with which should not be considered since
+    // get neighbor faces, intersection with which should not be considered since
     // collisions are avoided by means of smoothing
     set< TGeomID > neighborFaces;
     if ( eos._hyp.ToSmooth() )
@@ -4393,6 +4385,78 @@ void _ViscousBuilder::computeGeomSize( _SolidData& data )
       }
     }
   }
+
+  data._maxThickness = 0;
+  data._minThickness = 1e100;
+  list< const StdMeshers_ViscousLayers* >::iterator hyp = data._hyps.begin();
+  for ( ; hyp != data._hyps.end(); ++hyp )
+  {
+    data._maxThickness = Max( data._maxThickness, (*hyp)->GetTotalThickness() );
+    data._minThickness = Min( data._minThickness, (*hyp)->GetTotalThickness() );
+  }
+
+  // Limit inflation step size by geometry size found by intersecting
+  // normals of _LayerEdge's with mesh faces
+  if ( data._stepSize > 0.3 * data._geomSize )
+    limitStepSize( data, 0.3 * data._geomSize );
+
+  if ( data._stepSize > data._minThickness )
+    limitStepSize( data, data._minThickness );
+
+
+  // -------------------------------------------------------------------------
+  // Detect _LayerEdge which can't intersect with opposite or neighbor layer,
+  // so no need in detecting intersection at each inflation step
+  // -------------------------------------------------------------------------
+
+  int nbSteps = data._maxThickness / data._stepSize;
+  if ( nbSteps < 3 || nbSteps * data._n2eMap.size() < 100000 )
+    return;
+
+  vector< const SMDS_MeshElement* > closeFaces;
+  int nbDetected = 0;
+
+  for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS )
+  {
+    _EdgesOnShape& eos = data._edgesOnShape[ iS ];
+    if ( eos._edges.empty() || eos.ShapeType() != TopAbs_FACE )
+      continue;
+
+    for ( size_t i = 0; i < eos.size(); ++i )
+    {
+      SMESH_NodeXYZ p( eos[i]->_nodes[0] );
+      double radius = data._maxThickness + 2 * eos[i]->_maxLen;
+      closeFaces.clear();
+      searcher->GetElementsInSphere( p, radius, SMDSAbs_Face, closeFaces );
+
+      bool toIgnore = true;
+      for ( size_t iF = 0; iF < closeFaces.size()  && toIgnore; ++iF )
+        if ( !( toIgnore = ( closeFaces[ iF ]->getshapeId() == eos._shapeID ||
+                             data._ignoreFaceIds.count( closeFaces[ iF ]->getshapeId() ))))
+        {
+          // check if a _LayerEdge will inflate in a direction opposite to a direction
+          // toward a close face
+          bool allBehind = true;
+          for ( int iN = 0; iN < closeFaces[ iF ]->NbCornerNodes()  && allBehind; ++iN )
+          {
+            SMESH_NodeXYZ pi( closeFaces[ iF ]->GetNode( iN ));
+            allBehind = (( pi - p ) * eos[i]->_normal < 0.1 * data._stepSize );
+          }
+          toIgnore = allBehind;
+        }
+
+
+      if ( toIgnore ) // no need to detect intersection
+      {
+        eos[i]->Set( _LayerEdge::INTERSECTED );
+        ++nbDetected;
+      }
+    }
+  }
+
+  debugMsg( "Nb LE to intersect " << data._n2eMap.size()-nbDetected << ", ignore " << nbDetected );
+
+  return;
 }
 
 //================================================================================
@@ -4405,14 +4469,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
 {
   SMESH_MesherHelper helper( *_mesh );
 
-  // Limit inflation step size by geometry size found by itersecting
-  // normals of _LayerEdge's with mesh faces
-  if ( data._stepSize > 0.3 * data._geomSize )
-    limitStepSize( data, 0.3 * data._geomSize );
-
   const double tgtThick = data._maxThickness;
-  if ( data._stepSize > data._minThickness )
-    limitStepSize( data, data._minThickness );
 
   if ( data._stepSize < 1. )
     data._epsilon = data._stepSize * 1e-7;
@@ -4530,6 +4587,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
       break;
     }
 #endif
+
     // new step size
     limitStepSize( data, 0.25 * distToIntersection );
     if ( data._stepSizeNodes[0] )
@@ -4851,6 +4909,7 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
       _LayerEdge*      edge = eos._edges[i];
       if ( edge->_nodes.size() < 2 ) continue;
       SMESH_TNodeXYZ tgtXYZ = edge->_nodes.back();
+      //SMESH_TNodeXYZ prevXYZ = edge->_nodes[0];
       gp_XYZ        prevXYZ = edge->PrevCheckPos( &eos );
       //const gp_XYZ& prevXYZ = edge->PrevPos();
       for ( size_t j = 0; j < edge->_simplices.size(); ++j )
@@ -5654,17 +5713,16 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData&                    data,
         if ( iFrom >= iTo ) continue;
         _LayerEdge* e0 = _eos[iFrom]->_2neibors->_edges[0];
         _LayerEdge* e1 = _eos[iTo-1]->_2neibors->_edges[1];
-        gp_XY uv0 = ( e0 == eV0 ) ? uvV0 : e0->LastUV( F, _eos );
-        gp_XY uv1 = ( e1 == eV1 ) ? uvV1 : e1->LastUV( F, _eos );
-        double param0 = ( iFrom == 0 ) ? 0. : _leParams[ iFrom-1 ];
-        double param1 = _leParams[ iTo ];
-        const gp_XY rangeUV = uv1 - uv0;
+        gp_XY      uv0 = ( e0 == eV0 ) ? uvV0 : e0->LastUV( F, _eos );
+        gp_XY      uv1 = ( e1 == eV1 ) ? uvV1 : e1->LastUV( F, _eos );
+        double  param0 = ( iFrom == 0 ) ? 0. : _leParams[ iFrom-1 ];
+        double  param1 = _leParams[ iTo ];
+        gp_XY  rangeUV = uv1 - uv0;
         for ( size_t i = iFrom; i < iTo; ++i )
         {
           if ( _eos[i]->Is( _LayerEdge::BLOCKED )) continue;
           double param = ( _leParams[i] - param0 ) / ( param1 - param0 );
           gp_XY newUV = uv0 + param * rangeUV;
-          _eos[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
 
           gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
           SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( _eos[i]->_nodes.back() );
@@ -5674,6 +5732,28 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData&                    data,
           SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
           pos->SetUParameter( newUV.X() );
           pos->SetVParameter( newUV.Y() );
+
+          gp_XYZ newUV0( newUV.X(), newUV.Y(), 0 );
+
+          if ( !_eos[i]->Is( _LayerEdge::SMOOTHED ))
+          {
+            _eos[i]->Set( _LayerEdge::SMOOTHED ); // to check in refine() (IPAL54237)
+            if ( _eos[i]->_pos.size() > 2 )
+            {
+              // modify previous positions to make _LayerEdge less sharply bent
+              vector<gp_XYZ>& uvVec = _eos[i]->_pos;
+              const gp_XYZ  uvShift = newUV0 - uvVec.back();
+              const double     len2 = ( uvVec.back() - uvVec[ 0 ] ).SquareModulus();
+              int iPrev = uvVec.size() - 2;
+              while ( iPrev > 0 )
+              {
+                double r = ( uvVec[ iPrev ] - uvVec[0] ).SquareModulus() / len2;
+                uvVec[ iPrev ] += uvShift * r;
+                --iPrev;
+              }
+            }
+          }
+          _eos[i]->_pos.back() = newUV0;
         }
       }
     }
@@ -5764,6 +5844,8 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData&                    data,
         SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
         pos->SetUParameter( newUV.X() );
         pos->SetVParameter( newUV.Y() );
+
+        _eos[i]->Set( _LayerEdge::SMOOTHED ); // to check in refine() (IPAL54237)
       }
     }
     return true;
@@ -5836,8 +5918,9 @@ bool _Smoother1D::smoothComplexEdge( _SolidData&                    data,
   // project tgt nodes of extreme _LayerEdge's to the offset segments
   // -----------------------------------------------------------------
 
-  if ( e[0]->Is( _LayerEdge::NORMAL_UPDATED )) _iSeg[0] = 0;
-  if ( e[1]->Is( _LayerEdge::NORMAL_UPDATED )) _iSeg[1] = _offPoints.size()-2;
+  const int updatedOrBlocked = _LayerEdge::NORMAL_UPDATED | _LayerEdge::BLOCKED;
+  if ( e[0]->Is( updatedOrBlocked )) _iSeg[0] = 0;
+  if ( e[1]->Is( updatedOrBlocked )) _iSeg[1] = _offPoints.size()-2;
 
   gp_Pnt pExtreme[2], pProj[2];
   for ( int is2nd = 0; is2nd < 2; ++is2nd )
@@ -5893,10 +5976,14 @@ bool _Smoother1D::smoothComplexEdge( _SolidData&                    data,
   gp_Vec vDiv1( pExtreme[1], pProj[1] );
   double d0 = vDiv0.Magnitude();
   double d1 = vDiv1.Magnitude();
-  if ( e[0]->_normal * vDiv0.XYZ() < 0 ) e[0]->_len += d0;
-  else                                   e[0]->_len -= d0;
-  if ( e[1]->_normal * vDiv1.XYZ() < 0 ) e[1]->_len += d1;
-  else                                   e[1]->_len -= d1;
+  if ( e[0]->Is( _LayerEdge::BLOCKED )) {
+    if ( e[0]->_normal * vDiv0.XYZ() < 0 ) e[0]->_len += d0;
+    else                                   e[0]->_len -= d0;
+  }
+  if ( e[1]->Is( _LayerEdge::BLOCKED )) {
+    if ( e[1]->_normal * vDiv1.XYZ() < 0 ) e[1]->_len += d1;
+    else                                   e[1]->_len -= d1;
+  }
 
   // ---------------------------------------------------------------------------------
   // compute normalized length of the offset segments located between the projections
@@ -6011,8 +6098,8 @@ void _Smoother1D::prepare(_SolidData& data)
 
   // divide E to have offset segments with low deflection
   BRepAdaptor_Curve c3dAdaptor( E );
-  const double curDeflect = 0.1; //0.3; // 0.01; // Curvature deflection
-  const double angDeflect = 0.1; //0.2; // 0.09; // Angular deflection
+  const double curDeflect = 0.1; //0.01; // Curvature deflection == |p1p2]*sin(p1p2,p1pM)
+  const double angDeflect = 0.1; //0.09; // Angular deflection == sin(p1pM,pMp2)
   GCPnts_TangentialDeflection discret(c3dAdaptor, angDeflect, curDeflect);
   if ( discret.NbPoints() <= 2 )
   {
@@ -6022,14 +6109,39 @@ void _Smoother1D::prepare(_SolidData& data)
 
   const double u0 = c3dAdaptor.FirstParameter();
   gp_Pnt p; gp_Vec tangent;
-  _offPoints.resize( discret.NbPoints() );
-  for ( size_t i = 0; i < _offPoints.size(); i++ )
+  if ( discret.NbPoints() >= (int) _eos.size() + 2 )
+  {
+    _offPoints.resize( discret.NbPoints() );
+    for ( size_t i = 0; i < _offPoints.size(); i++ )
+    {
+      double u = discret.Parameter( i+1 );
+      c3dAdaptor.D1( u, p, tangent );
+      _offPoints[i]._xyz     = p.XYZ();
+      _offPoints[i]._edgeDir = tangent.XYZ();
+      _offPoints[i]._param = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / _curveLen;
+    }
+  }
+  else
   {
-    double u = discret.Parameter( i+1 );
-    c3dAdaptor.D1( u, p, tangent );
-    _offPoints[i]._xyz     = p.XYZ();
-    _offPoints[i]._edgeDir = tangent.XYZ();
-    _offPoints[i]._param = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / _curveLen;
+    std::vector< double > params( _eos.size() + 2 );
+
+    params[0]     = data.GetHelper().GetNodeU( E, leOnV[0]->_nodes[0] );
+    params.back() = data.GetHelper().GetNodeU( E, leOnV[1]->_nodes[0] );
+    for ( size_t i = 0; i < _eos.size(); i++ )
+      params[i+1] = data.GetHelper().GetNodeU( E, _eos[i]->_nodes[0] );
+
+    if ( params[1] > params[ _eos.size() ] )
+      std::reverse( params.begin() + 1, params.end() - 1 );
+
+    _offPoints.resize( _eos.size() + 2 );
+    for ( size_t i = 0; i < _offPoints.size(); i++ )
+    {
+      const double u = params[i];
+      c3dAdaptor.D1( u, p, tangent );
+      _offPoints[i]._xyz     = p.XYZ();
+      _offPoints[i]._edgeDir = tangent.XYZ();
+      _offPoints[i]._param = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / _curveLen;
+    }
   }
 
   // set _2edges
@@ -6069,8 +6181,14 @@ void _Smoother1D::prepare(_SolidData& data)
 
   int iLBO = _offPoints.size() - 2; // last but one
 
-  _leOnV[ 0 ]._normal = getNormalNormal( leOnV[0]->_normal, _edgeDir[0] );
-  _leOnV[ 1 ]._normal = getNormalNormal( leOnV[1]->_normal, _edgeDir[1] );
+  if ( leOnV[ 0 ]->Is( _LayerEdge::MULTI_NORMAL ))
+    _leOnV[ 0 ]._normal = getNormalNormal( _eos._edges[1]->_normal, _edgeDir[0] );
+  else
+    _leOnV[ 0 ]._normal = getNormalNormal( leOnV[0]->_normal,       _edgeDir[0] );
+  if ( leOnV[ 1 ]->Is( _LayerEdge::MULTI_NORMAL ))
+    _leOnV[ 1 ]._normal = getNormalNormal( _eos._edges.back()->_normal, _edgeDir[1] );
+  else
+    _leOnV[ 1 ]._normal = getNormalNormal( leOnV[1]->_normal,           _edgeDir[1] );
   _leOnV[ 0 ]._len = 0;
   _leOnV[ 1 ]._len = 0;
   _leOnV[ 0 ]._lenFactor = _offPoints[1   ]._2edges._edges[1]->_lenFactor;
@@ -6104,7 +6222,7 @@ void _Smoother1D::prepare(_SolidData& data)
 
 //================================================================================
 /*!
- * \brief set _normal of _leOnV[is2nd] to be normal to the EDGE
+ * \brief return _normal of _leOnV[is2nd] normal to the EDGE
  */
 //================================================================================
 
@@ -6115,6 +6233,9 @@ gp_XYZ _Smoother1D::getNormalNormal( const gp_XYZ & normal,
   gp_XYZ  norm = edgeDir ^ cross;
   double  size = norm.Modulus();
 
+  // if ( size == 0 ) // MULTI_NORMAL _LayerEdge
+  //   return gp_XYZ( 1e-100, 1e-100, 1e-100 );
+
   return norm / size;
 }
 
@@ -6834,8 +6955,8 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
       // compute new _normals
       for ( size_t i = 0; i < intEdgesDist.size(); ++i )
       {
-        _LayerEdge* edge2    = intEdgesDist[i].first;
-        double       distWgt = edge1->_len / intEdgesDist[i].second;
+        _LayerEdge* edge2   = intEdgesDist[i].first;
+        double      distWgt = edge1->_len / intEdgesDist[i].second;
         // if ( edge1->Is( _LayerEdge::BLOCKED ) &&
         //      edge2->Is( _LayerEdge::BLOCKED )) continue;        
         if ( edge2->Is( _LayerEdge::MARKED )) continue;
@@ -6876,9 +6997,14 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
         e2neIt->second._maxLen  = 0.7 * minIntDist / edge1->_lenFactor;
         if ( iter > 0 && sgn1 * sgn2 < 0 && edge1->_cosin < 0 )
           e2neIt->second._normal += dir2;
+
         e2neIt = edge2newEdge.insert( make_pair( edge2, zeroEdge )).first;
         e2neIt->second._normal += distWgt * newNormal;
-        e2neIt->second._cosin   = edge2->_cosin;
+        if ( Precision::IsInfinite( zeroEdge._maxLen ))
+        {
+          e2neIt->second._cosin  = edge2->_cosin;
+          e2neIt->second._maxLen = 1.3 * minIntDist / edge1->_lenFactor;
+        }
         if ( iter > 0 && sgn1 * sgn2 < 0 && edge2->_cosin < 0 )
           e2neIt->second._normal += dir1;
       }
@@ -6895,9 +7021,10 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
     for ( e2neIt = edge2newEdge.begin(); e2neIt != edge2newEdge.end(); ++e2neIt )
     {
       _LayerEdge*    edge = e2neIt->first;
-      if ( edge->Is( _LayerEdge::BLOCKED )) continue;
       _LayerEdge& newEdge = e2neIt->second;
       _EdgesOnShape*  eos = data.GetShapeEdges( edge );
+      if ( edge->Is( _LayerEdge::BLOCKED && newEdge._maxLen > edge->_len ))
+        continue;
 
       // Check if a new _normal is OK:
       newEdge._normal.Normalize();
@@ -7804,7 +7931,7 @@ bool _LayerEdge::FindIntersection( SMESH_ElementSearcher&   searcher,
 
 gp_XYZ _LayerEdge::PrevCheckPos( _EdgesOnShape* eos ) const
 {
-  size_t i = Is( NORMAL_UPDATED ) ? _pos.size()-2 : 0;
+  size_t i = Is( NORMAL_UPDATED ) && IsOnFace() ? _pos.size()-2 : 0;
 
   if ( !eos || eos->_sWOL.IsNull() )
     return _pos[ i ];
@@ -9364,7 +9491,7 @@ void _LayerEdge::Block( _SolidData& data )
         {
           _EdgesOnShape* eos = data.GetShapeEdges( neibor );
           while ( neibor->_len > neibor->_maxLen &&
-                  neibor->NbSteps() > 1 )
+                  neibor->NbSteps() > 0 )
             neibor->InvalidateStep( neibor->NbSteps(), *eos, /*restoreLength=*/true );
           neibor->SetNewLength( neibor->_maxLen, *eos, data.GetHelper() );
           //neibor->Block( data );
@@ -9416,7 +9543,10 @@ void _LayerEdge::InvalidateStep( size_t curStep, const _EdgesOnShape& eos, bool
 
     if ( restoreLength )
     {
-      _len -= ( nXYZ.XYZ() - curXYZ ).Modulus() / _lenFactor;
+      if ( NbSteps() == 0 )
+        _len = 0.;
+      else
+        _len -= ( nXYZ.XYZ() - curXYZ ).Modulus() / _lenFactor;
     }
   }
 }
@@ -9710,8 +9840,20 @@ bool _ViscousBuilder::refine(_SolidData& data)
       }
       else if ( eos._isRegularSWOL ) // usual SWOL
       {
-        for ( size_t j = 1; j < edge._pos.size(); ++j )
-          segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus();
+        if ( edge.Is( _LayerEdge::SMOOTHED ))
+        {
+          SMESH_NodeXYZ p0( edge._nodes[0] );
+          for ( size_t j = 1; j < edge._pos.size(); ++j )
+          {
+            gp_XYZ pj = surface->Value( edge._pos[j].X(), edge._pos[j].Y() ).XYZ();
+            segLen[j] = ( pj - p0 ) * edge._normal;
+          }
+        }
+        else
+        {
+          for ( size_t j = 1; j < edge._pos.size(); ++j )
+            segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus();
+        }
       }
       else if ( !surface.IsNull() ) // SWOL surface with singularities
       {
index 6586e120fb3ddb09e208c94e5febbdfeec9c349a..23d18d35db0c9aa2d06edecc8ce57e039d828552 100644 (file)
@@ -1318,7 +1318,7 @@ void _ViscousBuilder2D::setLayerEdgeData( _LayerEdge&                 lEdge,
     faceProj->Perform( p );
     if ( !faceProj->IsDone() || faceProj->NbPoints() < 1 )
       return setLayerEdgeData( lEdge, u, pcurve, curve, p, reverse, NULL );
-    Quantity_Parameter U,V;
+    Standard_Real U,V;
     faceProj->LowerDistanceParameters(U,V);
     lEdge._normal2D.SetCoord( U - uv.X(), V - uv.Y() );
     lEdge._normal2D.Normalize();