Salome HOME
0021543: EDF 1978 SMESH: Viscous layer for 2D meshes
authoreap <eap@opencascade.com>
Mon, 15 Oct 2012 14:30:14 +0000 (14:30 +0000)
committereap <eap@opencascade.com>
Mon, 15 Oct 2012 14:30:14 +0000 (14:30 +0000)
Derive SMESH_Octree from a template SMESH_Tree

src/SMESHUtils/SMESH_Octree.cxx
src/SMESHUtils/SMESH_Octree.hxx
src/SMESHUtils/SMESH_OctreeNode.cxx
src/SMESHUtils/SMESH_OctreeNode.hxx

index 00778a729a6af359750e34b05ff09bf86426c6ad..cfaccbde2f400012ddc771146d0f0ed086bfeded 100644 (file)
@@ -20,7 +20,7 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-//  SMESH  SMESH_Octree : global Octree implementation
+//  SMESH  SMESH_Octree : Octree implementation
 //  File      : SMESH_Octree.cxx
 //  Created   : Tue Jan 16 16:00:00 2007
 //  Author    : Nicolas Geimer & AurĂ©lien Motteux(OCC)
  */
 //===========================================================================
 
-SMESH_Octree::SMESH_Octree (SMESH_Octree::Limit* limit):
-  myChildren(NULL),
-  myFather(NULL),
-  myIsLeaf( false ),
-  myLimit( limit ),
-  myLevel(0),
-  myBox(NULL)
+SMESH_Octree::SMESH_Octree (SMESH_TreeLimit* limit): TBaseTree( limit )
 {
 }
 
-//================================================================================
-/*!
- * \brief Compute the Octree
- */
-//================================================================================
-
-void SMESH_Octree::compute()
-{
-  if ( myLevel==0 )
-  {
-    myBox = buildRootBox();
-    if ( myLimit->myMinBoxSize > 0. && maxSize() <= myLimit->myMinBoxSize )
-      myIsLeaf = true;
-    else
-      buildChildren();
-  }
-}
-
-//======================================
-/*!
- * \brief SMESH_Octree Destructor
- */
-//======================================
-
-SMESH_Octree::~SMESH_Octree ()
-{
-  if(myChildren != NULL)
-  {
-    if(!isLeaf())
-    {
-      for(int i = 0; i<8; i++)
-        delete myChildren[i];
-      delete[] myChildren;
-      myChildren = 0;
-    }
-  }
-  if ( myBox )
-    delete myBox;
-  myBox = 0;
-  if ( level() == 0 )
-    delete myLimit;
-  myLimit = 0;
-}
-
 //=================================================================
 /*!
- * \brief Build the 8 children boxes and call buildChildrenData()
+ * \brief Allocate a bndbox according to childIndex. childIndex is zero based
  */
 //=================================================================
 
-void SMESH_Octree::buildChildren()
+Bnd_B3d* SMESH_Octree::newChildBox(int childIndex) const
 {
-  if ( isLeaf() ) return;
-
-  myChildren = new SMESH_Octree*[8];
-
-  gp_XYZ min = myBox->CornerMin();
-  gp_XYZ max = myBox->CornerMax();
+  gp_XYZ min = getBox()->CornerMin();
+  gp_XYZ max = getBox()->CornerMax();
   gp_XYZ HSize = (max - min)/2.;
-  gp_XYZ mid = min + HSize;
   gp_XYZ childHsize = HSize/2.;
 
-  // get the whole model size
-  double rootSize = 0;
-  {
-    SMESH_Octree* root = this;
-    while ( root->myLevel > 0 )
-      root = root->myFather;
-    rootSize = root->maxSize();
-  }
-  Standard_Real XminChild, YminChild, ZminChild;
-  gp_XYZ minChild;
-  for (int i = 0; i < 8; i++)
-  {
-    // We build the eight boxes, we need 2 points to do that:
-    // Min and Mid
-    // In binary, we can write i from 0 to 7
-    // For instance :
-    // 5 is 101, it corresponds here in coordinates to ZYX
-    // If coordinate is 0 in Y-> box from Ymin to Ymid
-    // If coordinate is 1 in Y-> box from Ymid to Ymax
-    // Same scheme for X and Z
-    // I need the minChild to build the Bnd_B3d box.
+  gp_XYZ minChild( min.X() + childIndex%2     * HSize.X(),
+                   min.Y() + (childIndex%4)/2 * HSize.Y(),
+                   min.Z() + ( childIndex>=4 ) * HSize.Z());
 
-    XminChild = (i%2==0)?min.X():mid.X();
-    YminChild = ((i%4)/2==0)?min.Y():mid.Y();
-    ZminChild = (i<4)?min.Z():mid.Z();
-    minChild.SetCoord(XminChild, YminChild, ZminChild);
-
-    // 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]->myFather = this;
-    myChildren[i]->myLimit = myLimit;
-    myChildren[i]->myLevel = myLevel + 1;
-    myChildren[i]->myBox = new Bnd_B3d(minChild+childHsize,childHsize);
-    myChildren[i]->myBox->Enlarge( rootSize * 1e-10 );
-    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.
-  buildChildrenData();
-
-  //After we pass to the next level of the Octree
-  for (int i = 0; i<8; i++)
-    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 );
+  return new Bnd_B3d(minChild+childHsize,childHsize);
 }
 
 //===========================================================================
@@ -175,37 +67,13 @@ bool SMESH_Octree::isLeaf() const
 
 double SMESH_Octree::maxSize() const
 {
-  if ( myBox && !myBox->IsVoid() )
+  if ( getBox() && !getBox()->IsVoid() )
   {
-    gp_XYZ min = myBox->CornerMin();
-    gp_XYZ max = myBox->CornerMax();
+    gp_XYZ min = getBox()->CornerMin();
+    gp_XYZ max = getBox()->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.;
 }
-
-//================================================================================
-/*!
- * \brief Return height of the tree, full or from this level to topest leaf
- */
-//================================================================================
-
-int SMESH_Octree::getHeight(const bool full) const
-{
-  if ( full && myFather )
-    return myFather->getHeight( true );
-
-  if ( isLeaf() )
-    return 1;
-
-  int heigth = 0;
-  for (int i = 0; i<8; i++)
-  {
-    int h = myChildren[i]->getHeight( false );
-    if ( h > heigth )
-      heigth = h;
-  }
-  return heigth + 1;
-}
index 97d767a60cffb0d7bab10d123c625dd616c89273..9cc5eb4e37852aa36090889ed1a8521da21cddac 100644 (file)
@@ -20,7 +20,7 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-//  SMESH SMESH_Octree : global Octree implementation
+//  SMESH SMESH_Octree : Octree implementation
 //  File      : SMESH_Octree.hxx
 //  Created   : Tue Jan 16 16:00:00 2007
 //  Author    : Nicolas Geimer & AurĂ©lien Motteux (OCC)
 #define _SMESH_OCTREE_HXX_
 
 #include "SMESH_Utils.hxx"
+#include "SMESH_Tree.hxx"
 #include <Bnd_B3d.hxx>
 
-class SMESHUtils_EXPORT SMESH_Octree {
-
+//================================================================================
+/*!
+ * \brief 3D tree of anything.
+ * Methods to implement in a descendant are:
+ * - Bnd_B3d*       buildRootBox(); // box of the whole tree
+ * - descendant*    newChild() const; // a new child instance
+ * - void           buildChildrenData(); // Fill in data of the children
+ */
+class SMESHUtils_EXPORT SMESH_Octree : public SMESH_Tree< Bnd_B3d, 8 >
+{
 public:
-
-  // Data limiting the tree height
-  struct Limit {
-    // MaxLevel of the Octree
-    int    myMaxLevel;
-    // Minimal size of the Box
-    double myMinBoxSize;
-
-    // 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
-  };
+  typedef SMESH_Tree< Bnd_B3d, 8> TBaseTree;
 
   // Constructor. limit must be provided at tree root construction.
   // limit will be deleted by SMESH_Octree
-  SMESH_Octree (Limit* limit=0);
-
-  // Destructor
-  virtual ~SMESH_Octree ();
-
-  // Compute the Octree. Must be called by constructor of inheriting class
-  void                   compute();
-
-  // 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; }
+  SMESH_Octree (SMESH_TreeLimit* limit=0);
 
   // Compute the bigger dimension of my box
   double                 maxSize() const;
@@ -76,49 +56,16 @@ public:
   // Return index of a child the given point is in
   inline int             getChildIndex(double x, double y, double z, const gp_XYZ& boxMiddle)const;
 
-  // Return height of the tree, full or from this level to topest leaf
-  int                    getHeight(const bool full=true) const;
+ protected:
 
-protected:
-  // Return box of the whole tree
-  virtual Bnd_B3d*       buildRootBox() = 0;
-
-  // Constructor for children
-  virtual SMESH_Octree*  allocateOctreeChild() const = 0;
-
-  // Build the data in the 8 children
-  virtual void           buildChildrenData() = 0;
-
-  // members
-
-  // 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;
-
-  Bnd_B3d*       myBox;
+  // Allocate a bndbox according to childIndex. childIndex is zero based
+  virtual Bnd_B3d*       newChildBox(int childIndex) const;
 };
 
 //================================================================================
 /*!
  * \brief Return index of a child the given point is in
  */
-//================================================================================
-
 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;
index d14a50a2465106b190ee8ad57afc373a14ab16b5..821812340bb57920f4a870b80b1ede124a241022 100644 (file)
@@ -21,7 +21,7 @@
 //
 
 //  SMESH SMESH_OctreeNode : Octree with Nodes set
-//  inherites global class SMESH_Octree
+//  inherites class SMESH_Octree
 //  File      : SMESH_OctreeNode.cxx
 //  Created   : Tue Jan 16 16:00:00 2007
 //  Author    : Nicolas Geimer & Aurelien Motteux (OCC)
@@ -43,11 +43,11 @@ using namespace std;
  * \param minBoxSize - Minimal size of the Octree Box
  */
 //================================================================
+
 SMESH_OctreeNode::SMESH_OctreeNode (const TIDSortedNodeSet & theNodes, const int maxLevel,
                                     const int maxNbNodes , const double minBoxSize )
-  :SMESH_Octree( new SMESH_Octree::Limit( maxLevel,minBoxSize)),
-  myMaxNbNodes(maxNbNodes),
-  myNodes(theNodes)
+  :SMESH_Octree( new Limit( maxLevel,minBoxSize,maxNbNodes)),
+   myNodes(theNodes)
 {
   compute();
 }
@@ -58,9 +58,19 @@ SMESH_OctreeNode::SMESH_OctreeNode (const TIDSortedNodeSet & theNodes, const int
  */
 //================================================================================
 
-SMESH_OctreeNode::SMESH_OctreeNode (int maxNbNodes):
-  SMESH_Octree(), myMaxNbNodes(maxNbNodes)
+SMESH_OctreeNode::SMESH_OctreeNode ():SMESH_Octree()
+{
+}
+
+//================================================================================
+/*!
+ * \brief Return max number of nodes in a tree leaf
+ */
+//================================================================================
+
+int SMESH_OctreeNode::getMaxNbNodes() const
 {
+  return ((Limit*)myLimit)->myMaxNbNodes;
 }
 
 //==================================================================================
@@ -69,9 +79,9 @@ SMESH_OctreeNode::SMESH_OctreeNode (int maxNbNodes):
  */
 //==================================================================================
 
-SMESH_Octree* SMESH_OctreeNode::allocateOctreeChild() const
+SMESH_Octree* SMESH_OctreeNode::newChild() const
 {
-  return new SMESH_OctreeNode(myMaxNbNodes);
+  return new SMESH_OctreeNode();
 }
 
 //======================================
@@ -91,7 +101,7 @@ Bnd_B3d* SMESH_OctreeNode::buildRootBox()
     gp_XYZ p1( n1->X(), n1->Y(), n1->Z() );
     box->Add(p1);
   }
-  if ( myNodes.size() <= myMaxNbNodes )
+  if ( myNodes.size() <= getMaxNbNodes() )
     myIsLeaf = true;
 
   return box;
@@ -109,8 +119,8 @@ Bnd_B3d* SMESH_OctreeNode::buildRootBox()
 const bool SMESH_OctreeNode::isInside (const gp_XYZ& p, const double precision)
 {
   if (precision <= 0.)
-    return !(getBox().IsOut(p));
-  Bnd_B3d BoxWithPrecision = getBox();
+    return !(getBox()->IsOut(p));
+  Bnd_B3d BoxWithPrecision = *getBox();
   BoxWithPrecision.Enlarge(precision);
   return ! BoxWithPrecision.IsOut(p);
 }
@@ -123,8 +133,8 @@ const bool SMESH_OctreeNode::isInside (const gp_XYZ& p, const double precision)
 //================================================
 void SMESH_OctreeNode::buildChildrenData()
 {
-  gp_XYZ min = getBox().CornerMin();
-  gp_XYZ max = getBox().CornerMax();
+  gp_XYZ min = getBox()->CornerMin();
+  gp_XYZ max = getBox()->CornerMax();
   gp_XYZ mid = (min + max)/2.;
 
   TIDSortedNodeSet::iterator it = myNodes.begin();
@@ -140,7 +150,7 @@ void SMESH_OctreeNode::buildChildrenData()
   for (int i = 0; i < 8; i++)
   {
     SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
-    if ( myChild->myNodes.size() <= myMaxNbNodes )
+    if ( myChild->myNodes.size() <= getMaxNbNodes() )
       myChild->myIsLeaf = true;
   }
 }
@@ -200,7 +210,7 @@ bool SMESH_OctreeNode::NodesAround(const gp_XYZ &node,
     if (!isLeaf())
     {
       // first check a child containing node
-      gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
+      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;
@@ -401,7 +411,7 @@ void SMESH_OctreeNode::UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt
   }
   else if ( myChildren )
   {
-    gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
+    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 )
@@ -420,7 +430,7 @@ void SMESH_OctreeNode::UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt
 SMESH_OctreeNodeIteratorPtr SMESH_OctreeNode::GetChildrenIterator()
 {
   return SMESH_OctreeNodeIteratorPtr
-    ( new SMDS_SetIterator< SMESH_OctreeNode*, SMESH_Octree** >
+    ( new SMDS_SetIterator< SMESH_OctreeNode*, TBaseTree** >
       ( myChildren, (( isLeaf() || !myChildren ) ? myChildren : &myChildren[ 8 ] )));
 }
 
index cc66a275b12fa8a7f85ec97a1d7d45ceff5dd559..eea34d11f8ea462f40d521c6150013066d978f16 100644 (file)
@@ -109,7 +109,16 @@ public:
 
 protected:
 
-  SMESH_OctreeNode (int maxNbNodes );
+  struct Limit : public SMESH_TreeLimit
+  {
+    int myMaxNbNodes;
+    Limit(int maxLevel, double minSize, int maxNbNodes)
+      :SMESH_TreeLimit(maxLevel, minSize), myMaxNbNodes(maxNbNodes) {}
+  };
+
+  int                   getMaxNbNodes() const;
+
+  SMESH_OctreeNode();
 
   // Compute the bounding box of the whole set of nodes myNodes
   virtual Bnd_B3d*      buildRootBox();
@@ -118,7 +127,7 @@ protected:
   virtual void          buildChildrenData();
 
   // Construct an empty SMESH_OctreeNode used by SMESH_Octree::buildChildren()
-  virtual SMESH_Octree* allocateOctreeChild() const;
+  virtual SMESH_Octree* newChild() const;
 
   // Return in result a list of nodes closed to Node and remove it from SetOfNodes
   void                  FindCoincidentNodes( const SMDS_MeshNode *            Node,
@@ -126,9 +135,6 @@ protected:
                                              std::list<const SMDS_MeshNode*>* Result,
                                              const double                     precision);
 
-  // The max number of nodes a leaf box can contain
-  int                myMaxNbNodes;
-
   // The set of nodes inside the box of the Octree (Empty if Octree is not a leaf)
   TIDSortedNodeSet   myNodes;