From cf56ad7e8d88ee8500aaab001dfcee5924b48304 Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 15 Oct 2012 14:30:14 +0000 Subject: [PATCH] 0021543: EDF 1978 SMESH: Viscous layer for 2D meshes Derive SMESH_Octree from a template SMESH_Tree --- src/SMESHUtils/SMESH_Octree.cxx | 158 +++------------------------- src/SMESHUtils/SMESH_Octree.hxx | 87 +++------------ src/SMESHUtils/SMESH_OctreeNode.cxx | 44 +++++--- src/SMESHUtils/SMESH_OctreeNode.hxx | 16 ++- 4 files changed, 68 insertions(+), 237 deletions(-) diff --git a/src/SMESHUtils/SMESH_Octree.cxx b/src/SMESHUtils/SMESH_Octree.cxx index 00778a729..cfaccbde2 100644 --- a/src/SMESHUtils/SMESH_Octree.cxx +++ b/src/SMESHUtils/SMESH_Octree.cxx @@ -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) @@ -35,136 +35,28 @@ */ //=========================================================================== -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; -} diff --git a/src/SMESHUtils/SMESH_Octree.hxx b/src/SMESHUtils/SMESH_Octree.hxx index 97d767a60..9cc5eb4e3 100644 --- a/src/SMESHUtils/SMESH_Octree.hxx +++ b/src/SMESHUtils/SMESH_Octree.hxx @@ -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) @@ -30,45 +30,25 @@ #define _SMESH_OCTREE_HXX_ #include "SMESH_Utils.hxx" +#include "SMESH_Tree.hxx" #include -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; diff --git a/src/SMESHUtils/SMESH_OctreeNode.cxx b/src/SMESHUtils/SMESH_OctreeNode.cxx index d14a50a24..821812340 100644 --- a/src/SMESHUtils/SMESH_OctreeNode.cxx +++ b/src/SMESHUtils/SMESH_OctreeNode.cxx @@ -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 (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 ] ))); } diff --git a/src/SMESHUtils/SMESH_OctreeNode.hxx b/src/SMESHUtils/SMESH_OctreeNode.hxx index cc66a275b..eea34d11f 100644 --- a/src/SMESHUtils/SMESH_OctreeNode.hxx +++ b/src/SMESHUtils/SMESH_OctreeNode.hxx @@ -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* 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; -- 2.30.2