Salome HOME
0020464: EDF 1100 SMESH: Performance issue of the function MoveNode
authoreap <eap@opencascade.com>
Thu, 10 Sep 2009 05:50:18 +0000 (05:50 +0000)
committereap <eap@opencascade.com>
Thu, 10 Sep 2009 05:50:18 +0000 (05:50 +0000)
0020139: EDF 944 SMESH : Get 2D/3D element with X, Y, Z coordinates

optimize for performance

src/SMESH/SMESH_Octree.cxx
src/SMESH/SMESH_Octree.hxx
src/SMESH/SMESH_OctreeNode.cxx
src/SMESH/SMESH_OctreeNode.hxx

index 280f31bd9d153d7c1ca2a3662df815c3f48df948..00bdb26698cb480a6c7404cf29b5b1c84460a2a6 100644 (file)
 
 //===========================================================================
 /*!
- * \brief SMESH_Octree Constructor
- * \param maxLevel     - The level max the octree can reach (If <0 unlimited)
+ * Constructor. limit must be provided at tree root construction.
+ * limit will be deleted by SMESH_Octree.
  */
 //===========================================================================
-SMESH_Octree::SMESH_Octree (const int maxLevel, const double minBoxSize):
-    myChildren(NULL),
-    myFather(NULL),
-    myLevel(0),
-    myMaxLevel(maxLevel),
-    myMinBoxSize(minBoxSize),
-    myIsLeaf(-1)
+
+SMESH_Octree::SMESH_Octree (SMESH_Octree::Limit* limit):
+  myChildren(NULL),
+  myFather(NULL),
+  myIsLeaf( false ),
+  myLimit( limit ),
+  myLevel(0),
+  myBox(NULL)
+{
+}
+
+//================================================================================
+/*!
+ * \brief Compute the Octree
+ */
+//================================================================================
+
+void SMESH_Octree::compute()
 {
-  myBox = new Bnd_B3d();
+  if ( myLevel==0 )
+  {
+    myBox = buildRootBox();
+    if ( myLimit->myMinBoxSize > 0. && maxSize() <= myLimit->myMinBoxSize )
+      myIsLeaf = true;
+    else
+      buildChildren();
+  }
 }
 
 //======================================
@@ -50,85 +68,25 @@ SMESH_Octree::SMESH_Octree (const int maxLevel, const double minBoxSize):
  * \brief SMESH_Octree Destructor
  */
 //======================================
+
 SMESH_Octree::~SMESH_Octree ()
 {
   if(myChildren != NULL)
   {
-    if(!myIsLeaf)
+    if(!isLeaf())
     {
       for(int i = 0; i<8; i++)
         delete myChildren[i];
       delete[] myChildren;
+      myChildren = 0;
     }
   }
-  delete myBox;
-}
-
-//===========================================================================
-/*!
- * \brief Set the bounding box of the Octree
- * \param box          - 3d Bounding Box of the Octree
- */
-//===========================================================================
-void SMESH_Octree::setBox(const Bnd_B3d* box)
-{
-//   delete myBox;
-//   myBox=new Bnd_B3d(*box);
-  *myBox = *box;
-}
-
-//===========================================================================
-/*!
- * \brief Set box to the 3d Bounding Box of the Octree
- * \param box          - Set box to the 3d Bounding Box of the Octree
- */
-//===========================================================================
-void SMESH_Octree::getBox(Bnd_B3d& box)
-{
-//   if(box != NULL)
-//     delete box;
-//   box = new Bnd_B3d (*myBox);
-  box = *myBox;
-}
-
-//===========================================================================
-/*!
- * \brief Set the max level of the Octree
- * \param maxLevel     - The level max the octree can reach (If <0 unlimited)
- */
-//===========================================================================
-void SMESH_Octree::setMaxLevel(const int maxLevel)
-{myMaxLevel = maxLevel;}
-
-
-//===========================================================================
-/*!
- * \brief Compute the bigger dimension of the box
- * \param box          - 3d Box
- * \retval double - bigger dimension of the box
- */
-//===========================================================================
-double SMESH_Octree::maxSize(const Bnd_B3d* box)
-{
-  if(box ==NULL)
-    return 0;
-  gp_XYZ min = box->CornerMin();
-  gp_XYZ max = box->CornerMax();
-  gp_XYZ Size = (max - min);
-  double returnVal = (Size.X()>Size.Y())?Size.X():Size.Y();
-  return (returnVal>Size.Z())?returnVal:Size.Z();
-}
-
-//=============================
-/*!
- * \brief Compute the Octree
- */
-//=============================
-void SMESH_Octree::Compute()
-{
-  // As soon as the Octree is a Leaf, I stop building his children
-  if(!isLeaf())
-    buildChildren();
+  if ( myBox )
+    delete myBox;
+  myBox = 0;
+  if ( level() == 0 )
+    delete myLimit;
+  myLimit = 0;
 }
 
 //=================================================================
@@ -136,8 +94,11 @@ void SMESH_Octree::Compute()
  * \brief Build the 8 children boxes and call buildChildrenData()
  */
 //=================================================================
+
 void SMESH_Octree::buildChildren()
 {
+  if ( isLeaf() ) return;
+
   myChildren = new SMESH_Octree*[8];
 
   gp_XYZ min = myBox->CornerMin();
@@ -147,7 +108,6 @@ void SMESH_Octree::buildChildren()
   gp_XYZ childHsize = HSize/2.;
 
   Standard_Real XminChild, YminChild, ZminChild;
-  Bnd_B3d* box;
   gp_XYZ minChild;
   for (int i = 0; i < 8; i++)
   {
@@ -166,19 +126,53 @@ void SMESH_Octree::buildChildren()
     ZminChild = (i<4)?min.Z():mid.Z();
     minChild.SetCoord(XminChild, YminChild, ZminChild);
 
-    box = new Bnd_B3d(minChild+childHsize,childHsize);
     // The child is of the same type than its father (For instance, a SMESH_OctreeNode)
     // We allocate the memory we need for the child
     myChildren[i] = allocateOctreeChild();
     // and we assign to him its box.
-    myChildren[i]->setBox(box);
-    delete box;
+    myChildren[i]->myFather = this;
+    myChildren[i]->myLimit = myLimit;
+    myChildren[i]->myLevel = myLevel + 1;
+    myChildren[i]->myBox = new Bnd_B3d(minChild+childHsize,childHsize);
+    if ( myLimit->myMinBoxSize > 0. && myChildren[i]->maxSize() <= myLimit->myMinBoxSize )
+      myChildren[i]->myIsLeaf = true;
   }
 
-  // After building the 8 boxes, we put the data into the children..
+  // After building the 8 boxes, we put the data into the children.
   buildChildrenData();
 
   //After we pass to the next level of the Octree
   for (int i = 0; i<8; i++)
-    myChildren[i]->Compute();
+    myChildren[i]->buildChildren();
+}
+
+//================================================================================
+/*!
+ * \brief Tell if Octree is a leaf or not
+ *        An inheriting class can influence it via myIsLeaf protected field
+ */
+//================================================================================
+
+bool SMESH_Octree::isLeaf() const
+{
+  return myIsLeaf || ((myLimit->myMaxLevel > 0) ? (level() >= myLimit->myMaxLevel) : false );
+}
+
+//===========================================================================
+/*!
+ * \brief Compute the bigger dimension of my box
+ */
+//===========================================================================
+
+double SMESH_Octree::maxSize() const
+{
+  if ( myBox )
+  {
+    gp_XYZ min = myBox->CornerMin();
+    gp_XYZ max = myBox->CornerMax();
+    gp_XYZ Size = (max - min);
+    double returnVal = (Size.X()>Size.Y())?Size.X():Size.Y();
+    return (returnVal>Size.Z())?returnVal:Size.Z();
+  }
+  return 0.;
 }
index f906c2a08c03a58920448f1ecbabce7f18f90e5b..79a641dd4c262b003d8063cf961b20dd924e2afd 100644 (file)
 class SMESH_Octree {
 
 public:
-  // Constructor
-  SMESH_Octree (const int maxLevel = -1, const double minBoxSize = 0.);
 
-  // Destructor
-  virtual ~SMESH_Octree ();
-
-  // Tell if Octree is a leaf or not (has to be implemented in inherited classes)
-  virtual const bool     isLeaf() = 0;
+  // Data limiting the tree height
+  struct Limit {
+    // MaxLevel of the Octree
+    int    myMaxLevel;
+    // Minimal size of the Box
+    double myMinBoxSize;
 
-  // Compute the Octree
-  void                   Compute();
+    // Default:
+    // maxLevel-> 8^8 = 16777216 terminal trees
+    // minSize -> box size not checked
+    Limit(int maxLevel=8, double minSize=0.):myMaxLevel(maxLevel),myMinBoxSize(minSize) {}
+    virtual ~Limit() {} // it can be inherited
+  };
 
-  // Set the maximal level of the Octree
-  void                   setMaxLevel(const int maxLevel);
+  // Constructor. limit must be provided at tree root construction.
+  // limit will be deleted by SMESH_Octree
+  SMESH_Octree (Limit* limit=0);
 
-  // Set the minimal size of the Box
-  void                   setMinBoxSize(const double minBoxSize){myMinBoxSize = minBoxSize;};
-
-  // Set the bounding box of the Octree
-  void                   setBox(const Bnd_B3d* box);
+  // Destructor
+  virtual ~SMESH_Octree ();
 
-  // Set box to the 3d Bounding Box of the Octree
-  void                   getBox(Bnd_B3d & box);
+  // Compute the Octree. Must be called by constructor of inheriting class
+  void                   compute();
 
-  // Compute the bigger dimension of the box
-  static double          maxSize(const Bnd_B3d* box);
+  // Tell if Octree is a leaf or not.
+  // An inheriting class can influence it via myIsLeaf protected field
+  bool                   isLeaf() const;
 
   // Return its level
   int                    level() const { return myLevel; }
 
+  // Get box to the 3d Bounding Box of the Octree
+  const Bnd_B3d&         getBox() const { return *myBox; }
+
+  // Compute the bigger dimension of my box
+  double                 maxSize() const;
+
+  // Return index of a child the given point is in
+  inline int             getChildIndex(double x, double y, double z, const gp_XYZ& boxMiddle)const;
+
 protected:
-  // Constructor for children (has to be implemented in inherited classes)
-  virtual SMESH_Octree* allocateOctreeChild() = 0;
+  // Return box of the whole tree
+  virtual Bnd_B3d*       buildRootBox() = 0;
 
-  // Build the 8 children boxes
-  void buildChildren();
+  // Constructor for children
+  virtual SMESH_Octree*  allocateOctreeChild() const = 0;
 
-  // Build the data in the 8 children (has to be implemented in inherited classes)
-  virtual void buildChildrenData() = 0;
+  // Build the data in the 8 children
+  virtual void           buildChildrenData() = 0;
 
   // members
 
-  // Box of the Octree
-  Bnd_B3d*       myBox;
-
   // Array of 8 Octree children
   SMESH_Octree** myChildren;
 
   // Point the father, set to NULL for the level 0
   SMESH_Octree*  myFather;
 
+  // Tell us if the Octree is a leaf or not
+  bool           myIsLeaf;
+
+  // Tree limit
+  const Limit*   myLimit;
+
+private:
+  // Build the 8 children boxes recursively
+  void                   buildChildren();
+
   // Level of the Octree
   int            myLevel;
 
-  // MaxLevel of the Octree
-  int            myMaxLevel;
+  Bnd_B3d*       myBox;
+};
 
-  // Minimal size of the Box
-  double         myMinBoxSize;
+//================================================================================
+/*!
+ * \brief Return index of a child the given point is in
+ */
+//================================================================================
 
-  // Tell us if the Octree is a leaf or not (-1 if not initialized)
-  int            myIsLeaf;
-};
+inline int SMESH_Octree::getChildIndex(double x, double y, double z, const gp_XYZ& mid) const
+{
+  return (x > mid.X()) + ( y > mid.Y())*2 + (z > mid.Z())*4;
+}
 
 #endif
index 9a74d71bd7048db96817b792dad1b6ae5b703d54..8a230d72e5046c32dfc8009ecbcaaf05a5dab2f4 100644 (file)
@@ -46,18 +46,22 @@ using namespace std;
 //================================================================
 SMESH_OctreeNode::SMESH_OctreeNode (const set<const SMDS_MeshNode*> & theNodes, const int maxLevel,
                                     const int maxNbNodes , const double minBoxSize )
-  :SMESH_Octree(maxLevel,minBoxSize),
+  :SMESH_Octree( new SMESH_Octree::Limit( maxLevel,minBoxSize)),
   myMaxNbNodes(maxNbNodes),
   myNodes(theNodes)
 {
-  // We need to compute the first bounding box via a special method
-  computeBoxForFather();
-  myNbNodes = myNodes.size();
-  myIsLeaf = ((myLevel == myMaxLevel) ||
-              (myNbNodes <= myMaxNbNodes) ||
-              (maxSize(myBox) <= myMinBoxSize));
-  // All the children (Boxes and Data) are computed in Compute()
-  Compute();
+  compute();
+}
+
+//================================================================================
+/*!
+ * \brief Constructor used to allocate a child
+ */
+//================================================================================
+
+SMESH_OctreeNode::SMESH_OctreeNode (int maxNbNodes):
+  SMESH_Octree(), myMaxNbNodes(maxNbNodes)
+{
 }
 
 //==================================================================================
@@ -65,16 +69,10 @@ SMESH_OctreeNode::SMESH_OctreeNode (const set<const SMDS_MeshNode*> & theNodes,
  * \brief Construct an empty SMESH_OctreeNode used by SMESH_Octree::buildChildren()
  */
 //==================================================================================
-SMESH_Octree* SMESH_OctreeNode::allocateOctreeChild()
+
+SMESH_Octree* SMESH_OctreeNode::allocateOctreeChild() const
 {
-  SMESH_OctreeNode * theOctree = new SMESH_OctreeNode();
-  theOctree->myFather = this;
-  theOctree->myLevel = myLevel + 1;
-  theOctree->myMaxLevel = myMaxLevel;
-  theOctree->myMaxNbNodes = myMaxNbNodes;
-  theOctree->myMinBoxSize = myMinBoxSize;
-  theOctree->myNbNodes = 0;
-  return theOctree;
+  return new SMESH_OctreeNode(myMaxNbNodes);
 }
 
 //======================================
@@ -84,25 +82,20 @@ SMESH_Octree* SMESH_OctreeNode::allocateOctreeChild()
  * We take the max/min coord of the nodes
  */
 //======================================
-void SMESH_OctreeNode::computeBoxForFather()
+
+Bnd_B3d* SMESH_OctreeNode::buildRootBox()
 {
+  Bnd_B3d* box = new Bnd_B3d;
   set<const SMDS_MeshNode*>::iterator it = myNodes.begin();
   for (; it != myNodes.end(); it++) {
     const SMDS_MeshNode* n1 = *it;
     gp_XYZ p1( n1->X(), n1->Y(), n1->Z() );
-    myBox->Add(p1);
+    box->Add(p1);
   }
-}
+  if ( myNodes.size() <= myMaxNbNodes )
+    myIsLeaf = true;
 
-//====================================================================================
-/*!
- * \brief Tell if Octree is a leaf or not (has to be implemented in inherited classes)
- * \retval      - True if the Octree is a leaf
- */
-//====================================================================================
-const bool SMESH_OctreeNode::isLeaf()
-{
-  return myIsLeaf;
+  return box;
 }
 
 //====================================================================================
@@ -113,19 +106,15 @@ const bool SMESH_OctreeNode::isLeaf()
  * \retval bool - True if Node is in the box within precision
  */
 //====================================================================================
+
 const bool SMESH_OctreeNode::isInside (const SMDS_MeshNode * Node, const double precision)
 {
-  double X = Node->X();
-  double Y = Node->Y();
-  double Z = Node->Z();
-  bool Out = 1 ;
+  gp_XYZ p (Node->X(),Node->Y(),Node->Z());
   if (precision <= 0.)
-    return !(myBox->IsOut(gp_XYZ(X,Y,Z)));
-  Bnd_B3d BoxWithPrecision;
-  getBox(BoxWithPrecision);
+    return !(getBox().IsOut(p));
+  Bnd_B3d BoxWithPrecision = getBox();
   BoxWithPrecision.Enlarge(precision);
-  Out = BoxWithPrecision.IsOut(gp_XYZ(X,Y,Z));
-  return !(Out);
+  return ! BoxWithPrecision.IsOut(p);
 }
 
 //================================================
@@ -136,16 +125,15 @@ const bool SMESH_OctreeNode::isInside (const SMDS_MeshNode * Node, const double
 //================================================
 void SMESH_OctreeNode::buildChildrenData()
 {
-  gp_XYZ min = myBox->CornerMin();
-  gp_XYZ max = myBox->CornerMax();
+  gp_XYZ min = getBox().CornerMin();
+  gp_XYZ max = getBox().CornerMax();
   gp_XYZ mid = (min + max)/2.;
 
   set<const SMDS_MeshNode*>::iterator it = myNodes.begin();
-  int ChildBoxNum;
   while (it != myNodes.end())
   {
     const SMDS_MeshNode* n1 = *it;
-    ChildBoxNum = (n1->X() > mid.X()) + (n1->Y() > mid.Y())*2 + (n1->Z() > mid.Z())*4;
+    int ChildBoxNum = getChildIndex( n1->X(), n1->Y(), n1->Z(), mid );
     SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[ChildBoxNum]);
     myChild->myNodes.insert(myChild->myNodes.end(),n1);
     myNodes.erase( it );
@@ -154,10 +142,8 @@ void SMESH_OctreeNode::buildChildrenData()
   for (int i = 0; i < 8; i++)
   {
     SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
-    myChild->myNbNodes = (myChild->myNodes).size();
-    myChild->myIsLeaf = ((myChild->myLevel == myMaxLevel) ||
-                         (myChild->myNbNodes <= myMaxNbNodes) ||
-                         (maxSize(myChild->myBox) <= myMinBoxSize));
+    if ( myChild->myNodes.size() <= myMaxNbNodes )
+      myChild->myIsLeaf = true;
   }
 }
 
@@ -175,7 +161,7 @@ void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
 {
   if (isInside(Node,precision))
   {
-    if (myIsLeaf)
+    if (isLeaf())
     {
       Result->insert(Result->end(), myNodes.begin(), myNodes.end());
     }
@@ -190,6 +176,61 @@ void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
   }
 }
 
+//================================================================================
+/*!
+ * \brief Return in dist2Nodes nodes mapped to their square distance from Node
+ *  \param node - node to find nodes closest to
+ *  \param dist2Nodes - map of found nodes and their distances
+ *  \param precision - radius of a sphere to check nodes inside
+ *  \retval bool - true if an exact overlapping found
+ */
+//================================================================================
+
+bool SMESH_OctreeNode::NodesAround(const SMDS_MeshNode *              node,
+                                   map<double, const SMDS_MeshNode*>& dist2Nodes,
+                                   double                             precision)
+{
+  if ( !dist2Nodes.empty() )
+    precision = min ( precision, sqrt( dist2Nodes.begin()->first ));
+  else if ( precision == 0. )
+    precision = maxSize() / 2;
+
+  if (isInside(node,precision))
+  {
+    if (!isLeaf())
+    {
+      // first check a child containing node
+      gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
+      int nodeChild  = getChildIndex( node->X(), node->Y(), node->Z(), mid );
+      if ( ((SMESH_OctreeNode*) myChildren[nodeChild])->NodesAround(node, dist2Nodes, precision))
+        return true;
+      
+      for (int i = 0; i < 8; i++)
+        if ( i != nodeChild )
+          if (((SMESH_OctreeNode*) myChildren[i])->NodesAround(node, dist2Nodes, precision))
+            return true;
+    }
+    else if ( NbNodes() > 0 )
+    {
+      double minDist = precision * precision;
+      gp_Pnt p1 ( node->X(), node->Y(), node->Z() );
+      set<const SMDS_MeshNode*>::iterator nIt = myNodes.begin();
+      for ( ; nIt != myNodes.end(); ++nIt )
+      {
+        gp_Pnt p2 ( (*nIt)->X(), (*nIt)->Y(), (*nIt)->Z() );
+        double dist2 = p1.SquareDistance( p2 );
+        if ( dist2 < minDist )
+          dist2Nodes.insert( make_pair( minDist = dist2, *nIt ));
+      }
+//       if ( dist2Nodes.size() > 1 ) // leave only closest node in dist2Nodes
+//         dist2Nodes.erase( ++dist2Nodes.begin(), dist2Nodes.end());
+
+      return ( sqrt( minDist) <= precision * 1e-12 );
+    }
+  }
+  return false;
+}
+
 //=============================
 /*!
  * \brief  Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
@@ -202,15 +243,14 @@ void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
  * \param maxNbNodes - maximum Nodes in a Leaf of the SMESH_OctreeNode constructed, default value is 5
  */
 //=============================
-void SMESH_OctreeNode::FindCoincidentNodes (set<const SMDS_MeshNode*> theSetOfNodes,
+void SMESH_OctreeNode::FindCoincidentNodes (set<const SMDS_MeshNode*>& theSetOfNodes,
                                             list< list< const SMDS_MeshNode*> >* theGroupsOfNodes,
                                             const double theTolerance,
                                             const int maxLevel,
                                             const int maxNbNodes)
 {
-  SMESH_OctreeNode* theOctreeNode = new SMESH_OctreeNode(theSetOfNodes, maxLevel, maxNbNodes, theTolerance);
-  theOctreeNode->FindCoincidentNodes (&theSetOfNodes, theTolerance, theGroupsOfNodes);
-  delete theOctreeNode;
+  SMESH_OctreeNode theOctreeNode(theSetOfNodes, maxLevel, maxNbNodes, theTolerance);
+  theOctreeNode.FindCoincidentNodes (&theSetOfNodes, theTolerance, theGroupsOfNodes);
 }
 
 //=============================
@@ -285,7 +325,7 @@ void SMESH_OctreeNode::FindCoincidentNodes (const SMDS_MeshNode * Node,
   if (isInsideBool)
   {
     // I'm only looking in the leaves, since all the nodes are stored there.
-    if (myIsLeaf)
+    if (isLeaf())
     {
       gp_Pnt p1 (Node->X(), Node->Y(), Node->Z());
 
@@ -333,6 +373,43 @@ void SMESH_OctreeNode::FindCoincidentNodes (const SMDS_MeshNode * Node,
   }
 }
 
+//================================================================================
+/*!
+ * \brief Update data according to node movement
+ */
+//================================================================================
+
+void SMESH_OctreeNode::UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt& toPnt )
+{
+  if ( isLeaf() )
+  {
+    set<const SMDS_MeshNode*>::iterator pNode = myNodes.find( node );
+    bool nodeInMe = ( pNode != myNodes.end() );
+
+    SMDS_MeshNode pointNode( toPnt.X(), toPnt.Y(), toPnt.Z() );
+    bool pointInMe = isInside( &pointNode, 1e-10 );
+
+    if ( pointInMe != nodeInMe )
+    {
+      if ( pointInMe )
+        myNodes.insert( node );
+      else
+        myNodes.erase( node );
+    }
+  }
+  else if ( myChildren )
+  {
+    gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
+    int nodeChild  = getChildIndex( node->X(), node->Y(), node->Z(), mid );
+    int pointChild = getChildIndex( toPnt.X(), toPnt.Y(), toPnt.Z(), mid );
+    if ( nodeChild != pointChild )
+    {
+      ((SMESH_OctreeNode*) myChildren[ nodeChild  ])->UpdateByMoveNode( node, toPnt );
+      ((SMESH_OctreeNode*) myChildren[ pointChild ])->UpdateByMoveNode( node, toPnt );
+    }
+  }
+}
+
 //================================================================================
 /*!
  * \brief Return iterator over children
@@ -342,7 +419,7 @@ SMESH_OctreeNodeIteratorPtr SMESH_OctreeNode::GetChildrenIterator()
 {
   return SMESH_OctreeNodeIteratorPtr
     ( new SMDS_SetIterator< SMESH_OctreeNode*, SMESH_Octree** >
-      ( myChildren, ( isLeaf() ? myChildren : &myChildren[ 8 ] )));
+      ( myChildren, (( isLeaf() || !myChildren ) ? myChildren : &myChildren[ 8 ] )));
 }
 
 //================================================================================
@@ -354,5 +431,5 @@ SMDS_NodeIteratorPtr SMESH_OctreeNode::GetNodeIterator()
 {
   return SMDS_NodeIteratorPtr
     ( new SMDS_SetIterator< SMDS_pNode, set< SMDS_pNode >::const_iterator >
-      ( myNodes.begin(), myNodes.end() ));
+      ( myNodes.begin(), myNodes.size() ? myNodes.end() : myNodes.begin()));
 }
index 6a3b0cb39a1ec85b2d380995f55ad5f09f26e89e..7799765d0076a03d48cf88953eb02f34e7659df0 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <list>
 #include <set>
+#include <map>
 
 #include "SMDS_ElemIterator.hxx"
 
@@ -44,7 +45,7 @@ class SMESH_OctreeNode;
 typedef SMDS_Iterator<SMESH_OctreeNode*>            SMESH_OctreeNodeIterator;
 typedef boost::shared_ptr<SMESH_OctreeNodeIterator> SMESH_OctreeNodeIteratorPtr;
 
-class SMESH_OctreeNode : public SMESH_Octree{
+class SMESH_OctreeNode : public SMESH_Octree {
 
 public:
 
@@ -59,9 +60,6 @@ public:
 //=============================
   virtual ~SMESH_OctreeNode () {};
 
-  // Tells us if SMESH_OctreeNode is a leaf or not (-1 = not initialiazed)
-  virtual const bool isLeaf();
-
   // Tells us if Node is inside the current box with the precision "precision"
   virtual const bool isInside(const SMDS_MeshNode * Node, const double precision = 0.);
 
@@ -70,6 +68,11 @@ public:
                                  std::list<const SMDS_MeshNode*>* Result,
                                  const double precision = 0.);
 
+  // Return in dist2Nodes nodes mapped to their square distance from Node
+  bool               NodesAround(const SMDS_MeshNode *                   Node,
+                                 std::map<double, const SMDS_MeshNode*>& dist2Nodes,
+                                 double                                  precision);
+
   // Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
   // Search for all the nodes in nodes
   void               FindCoincidentNodes ( std::set<const SMDS_MeshNode*>* nodes,
@@ -78,10 +81,15 @@ public:
 
   // Static method that return in theGroupsOfNodes a list of group of nodes close to each other within
   // theTolerance search for all the nodes in nodes
-  static void        FindCoincidentNodes ( std::set<const SMDS_MeshNode*> nodes,
+  static void        FindCoincidentNodes ( std::set<const SMDS_MeshNode*>& nodes,
                                            std::list< std::list< const SMDS_MeshNode*> >* theGroupsOfNodes,
-                                           const double theTolerance = 0.00001, const int maxLevel = -1,
+                                           const double theTolerance = 0.00001,
+                                           const int maxLevel = -1,
                                            const int maxNbNodes = 5);
+  /*!
+   * \brief Update data according to node movement
+   */
+  void                        UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt& toPnt );
   /*!
    * \brief Return iterator over children
    */
@@ -93,25 +101,20 @@ public:
   /*!
    * \brief Return nb nodes in a tree
    */
-  int                         NbNodes() const { return myNbNodes; }
+  int                         NbNodes() const { return myNodes.size(); }
 
 protected:
 
-//=============================
-/*!
- * \brief Empty constructor
- */
-//=============================
-  SMESH_OctreeNode (){};
+  SMESH_OctreeNode (int maxNbNodes );
+
+  // Compute the bounding box of the whole set of nodes myNodes
+  virtual Bnd_B3d*      buildRootBox();
 
   // Shares the father's data with each of his child
   virtual void          buildChildrenData();
 
-  // Compute the bounding box of the whole set of nodes myNodes (only used for OctreeNode level 0)
-  void                  computeBoxForFather();
-
   // Construct an empty SMESH_OctreeNode used by SMESH_Octree::buildChildren()
-  virtual SMESH_Octree* allocateOctreeChild();
+  virtual SMESH_Octree* allocateOctreeChild() const;
 
   // Return in result a list of nodes closed to Node and remove it from SetOfNodes
   void                  FindCoincidentNodes( const SMDS_MeshNode * Node,
@@ -120,13 +123,11 @@ protected:
                                              const double precision);
 
   // The max number of nodes a leaf box can contain
-  int                         myMaxNbNodes;
+  int                              myMaxNbNodes;
 
   // The set of nodes inside the box of the Octree (Empty if Octree is not a leaf)
   std::set<const SMDS_MeshNode*>   myNodes;
 
-  // The number of nodes I have inside the box
-  int                         myNbNodes;
 };
 
 #endif