Version: 6.3.1

src/SMESH/SMESH_OctreeNode.cxx

Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH SMESH_OctreeNode : Octree with Nodes set
00024 //  inherites global class SMESH_Octree
00025 //  File      : SMESH_OctreeNode.cxx
00026 //  Created   : Tue Jan 16 16:00:00 2007
00027 //  Author    : Nicolas Geimer & Aurelien Motteux (OCC)
00028 //  Module    : SMESH
00029 //
00030 #include "SMESH_OctreeNode.hxx"
00031 
00032 #include "SMDS_SetIterator.hxx"
00033 #include <gp_Pnt.hxx>
00034 
00035 using namespace std;
00036 
00037 //===============================================================
00045 //================================================================
00046 SMESH_OctreeNode::SMESH_OctreeNode (const TIDSortedNodeSet & theNodes, const int maxLevel,
00047                                     const int maxNbNodes , const double minBoxSize )
00048   :SMESH_Octree( new SMESH_Octree::Limit( maxLevel,minBoxSize)),
00049   myMaxNbNodes(maxNbNodes),
00050   myNodes(theNodes)
00051 {
00052   compute();
00053 }
00054 
00055 //================================================================================
00059 //================================================================================
00060 
00061 SMESH_OctreeNode::SMESH_OctreeNode (int maxNbNodes):
00062   SMESH_Octree(), myMaxNbNodes(maxNbNodes)
00063 {
00064 }
00065 
00066 //==================================================================================
00070 //==================================================================================
00071 
00072 SMESH_Octree* SMESH_OctreeNode::allocateOctreeChild() const
00073 {
00074   return new SMESH_OctreeNode(myMaxNbNodes);
00075 }
00076 
00077 //======================================
00083 //======================================
00084 
00085 Bnd_B3d* SMESH_OctreeNode::buildRootBox()
00086 {
00087   Bnd_B3d* box = new Bnd_B3d;
00088   TIDSortedNodeSet::iterator it = myNodes.begin();
00089   for (; it != myNodes.end(); it++) {
00090     const SMDS_MeshNode* n1 = *it;
00091     gp_XYZ p1( n1->X(), n1->Y(), n1->Z() );
00092     box->Add(p1);
00093   }
00094   if ( myNodes.size() <= myMaxNbNodes )
00095     myIsLeaf = true;
00096 
00097   return box;
00098 }
00099 
00100 //====================================================================================
00107 //====================================================================================
00108 
00109 const bool SMESH_OctreeNode::isInside (const gp_XYZ& p, const double precision)
00110 {
00111   if (precision <= 0.)
00112     return !(getBox().IsOut(p));
00113   Bnd_B3d BoxWithPrecision = getBox();
00114   BoxWithPrecision.Enlarge(precision);
00115   return ! BoxWithPrecision.IsOut(p);
00116 }
00117 
00118 //================================================
00123 //================================================
00124 void SMESH_OctreeNode::buildChildrenData()
00125 {
00126   gp_XYZ min = getBox().CornerMin();
00127   gp_XYZ max = getBox().CornerMax();
00128   gp_XYZ mid = (min + max)/2.;
00129 
00130   TIDSortedNodeSet::iterator it = myNodes.begin();
00131   while (it != myNodes.end())
00132   {
00133     const SMDS_MeshNode* n1 = *it;
00134     int ChildBoxNum = getChildIndex( n1->X(), n1->Y(), n1->Z(), mid );
00135     SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[ChildBoxNum]);
00136     myChild->myNodes.insert(myChild->myNodes.end(),n1);
00137     myNodes.erase( it );
00138     it = myNodes.begin();
00139   }
00140   for (int i = 0; i < 8; i++)
00141   {
00142     SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
00143     if ( myChild->myNodes.size() <= myMaxNbNodes )
00144       myChild->myIsLeaf = true;
00145   }
00146 }
00147 
00148 //===================================================================
00155 //====================================================================
00156 void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
00157                                     list<const SMDS_MeshNode*>* Result,
00158                                     const double precision)
00159 {
00160   gp_XYZ p(Node->X(), Node->Y(), Node->Z());
00161   if (isInside(p, precision))
00162   {
00163     if (isLeaf())
00164     {
00165       Result->insert(Result->end(), myNodes.begin(), myNodes.end());
00166     }
00167     else
00168     {
00169       for (int i = 0; i < 8; i++)
00170       {
00171         SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
00172         myChild->NodesAround(Node, Result, precision);
00173       }
00174     }
00175   }
00176 }
00177 
00178 //================================================================================
00186 //================================================================================
00187 
00188 bool SMESH_OctreeNode::NodesAround(const gp_XYZ &node,
00189                                    map<double, const SMDS_MeshNode*>& dist2Nodes,
00190                                    double                             precision)
00191 {
00192   if ( !dist2Nodes.empty() )
00193     precision = min ( precision, sqrt( dist2Nodes.begin()->first ));
00194   else if ( precision == 0. )
00195     precision = maxSize() / 2;
00196 
00197   //gp_XYZ p(node->X(), node->Y(), node->Z());
00198   if (isInside(node, precision))
00199   {
00200     if (!isLeaf())
00201     {
00202       // first check a child containing node
00203       gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
00204       int nodeChild  = getChildIndex( node.X(), node.Y(), node.Z(), mid );
00205       if ( ((SMESH_OctreeNode*) myChildren[nodeChild])->NodesAround(node, dist2Nodes, precision))
00206         return true;
00207       
00208       for (int i = 0; i < 8; i++)
00209         if ( i != nodeChild )
00210           if (((SMESH_OctreeNode*) myChildren[i])->NodesAround(node, dist2Nodes, precision))
00211             return true;
00212     }
00213     else if ( NbNodes() > 0 )
00214     {
00215       double minDist = precision * precision;
00216       gp_Pnt p1 ( node.X(), node.Y(), node.Z() );
00217       set<const SMDS_MeshNode*>::iterator nIt = myNodes.begin();
00218       for ( ; nIt != myNodes.end(); ++nIt )
00219       {
00220         gp_Pnt p2 ( (*nIt)->X(), (*nIt)->Y(), (*nIt)->Z() );
00221         double dist2 = p1.SquareDistance( p2 );
00222         if ( dist2 < minDist )
00223           dist2Nodes.insert( make_pair( minDist = dist2, *nIt ));
00224       }
00225 //       if ( dist2Nodes.size() > 1 ) // leave only closest node in dist2Nodes
00226 //         dist2Nodes.erase( ++dist2Nodes.begin(), dist2Nodes.end());
00227 
00228       return ( sqrt( minDist) <= precision * 1e-12 );
00229     }
00230   }
00231   return false;
00232 }
00233 
00234 //=============================
00245 //=============================
00246 void SMESH_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes,
00247                                             list< list< const SMDS_MeshNode*> >* theGroupsOfNodes,
00248                                             const double theTolerance,
00249                                             const int maxLevel,
00250                                             const int maxNbNodes)
00251 {
00252   SMESH_OctreeNode theOctreeNode(theSetOfNodes, maxLevel, maxNbNodes, theTolerance);
00253   theOctreeNode.FindCoincidentNodes (&theSetOfNodes, theTolerance, theGroupsOfNodes);
00254 }
00255 
00256 //=============================
00265 //=============================
00266 void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes,
00267                                              const double               theTolerance,
00268                                              list< list< const SMDS_MeshNode*> >* theGroupsOfNodes)
00269 {
00270   TIDSortedNodeSet::iterator it1 = theSetOfNodes->begin();
00271   list<const SMDS_MeshNode*>::iterator it2;
00272 
00273   while (it1 != theSetOfNodes->end())
00274   {
00275     const SMDS_MeshNode * n1 = *it1;
00276 
00277     list<const SMDS_MeshNode*> ListOfCoincidentNodes;// Initialize the lists via a declaration, it's enough
00278 
00279     list<const SMDS_MeshNode*> * groupPtr = 0;
00280 
00281     // Searching for Nodes around n1 and put them in ListofCoincidentNodes.
00282     // Found nodes are also erased from theSetOfNodes
00283     FindCoincidentNodes(n1, theSetOfNodes, &ListOfCoincidentNodes, theTolerance);
00284 
00285     // We build a list {n1 + his neigbours} and add this list in theGroupsOfNodes
00286     for (it2 = ListOfCoincidentNodes.begin(); it2 != ListOfCoincidentNodes.end(); it2++)
00287     {
00288       const SMDS_MeshNode* n2 = *it2;
00289       if ( !groupPtr )
00290       {
00291         theGroupsOfNodes->push_back( list<const SMDS_MeshNode*>() );
00292         groupPtr = & theGroupsOfNodes->back();
00293         groupPtr->push_back( n1 );
00294       }
00295       if (groupPtr->front() > n2)
00296         groupPtr->push_front( n2 );
00297       else
00298         groupPtr->push_back( n2 );
00299     }
00300     if (groupPtr != 0)
00301       groupPtr->sort();
00302 
00303     theSetOfNodes->erase(it1);
00304     it1 = theSetOfNodes->begin();
00305   }
00306 }
00307 
00308 //======================================================================================
00317 //======================================================================================
00318 void SMESH_OctreeNode::FindCoincidentNodes (const SMDS_MeshNode * Node,
00319                                             TIDSortedNodeSet* SetOfNodes,
00320                                             list<const SMDS_MeshNode*>* Result,
00321                                             const double precision)
00322 {
00323   gp_XYZ p(Node->X(), Node->Y(), Node->Z());
00324   bool isInsideBool = isInside(p, precision);
00325 
00326   if (isInsideBool)
00327   {
00328     // I'm only looking in the leaves, since all the nodes are stored there.
00329     if (isLeaf())
00330     {
00331       gp_Pnt p1 (Node->X(), Node->Y(), Node->Z());
00332 
00333       TIDSortedNodeSet myNodesCopy = myNodes;
00334       TIDSortedNodeSet::iterator it = myNodesCopy.begin();
00335       double tol2 = precision * precision;
00336       bool squareBool;
00337 
00338       while (it != myNodesCopy.end())
00339       {
00340         const SMDS_MeshNode* n2 = *it;
00341         // We're only looking at nodes with a superior Id.
00342         // JFA: Why?
00343         //if (Node->GetID() < n2->GetID())
00344         if (Node->GetID() != n2->GetID()) // JFA: for bug 0020185
00345         {
00346           gp_Pnt p2 (n2->X(), n2->Y(), n2->Z());
00347           // Distance optimized computation
00348           squareBool = (p1.SquareDistance( p2 ) <= tol2);
00349 
00350           // If n2 inside the SquareDistance, we add it in Result and remove it from SetOfNodes and myNodes
00351           if (squareBool)
00352           {
00353             Result->insert(Result->begin(), n2);
00354             SetOfNodes->erase( n2 );
00355             myNodes.erase( n2 );
00356           }
00357         }
00358         //myNodesCopy.erase( it );
00359         //it = myNodesCopy.begin();
00360         it++;
00361       }
00362       if (Result->size() > 0)
00363         myNodes.erase(Node); // JFA: for bug 0020185
00364     }
00365     else
00366     {
00367       // If I'm not a leaf, I'm going to see my children !
00368       for (int i = 0; i < 8; i++)
00369       {
00370         SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
00371         myChild->FindCoincidentNodes(Node, SetOfNodes, Result, precision);
00372       }
00373     }
00374   }
00375 }
00376 
00377 //================================================================================
00381 //================================================================================
00382 
00383 void SMESH_OctreeNode::UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt& toPnt )
00384 {
00385   if ( isLeaf() )
00386   {
00387     TIDSortedNodeSet::iterator pNode = myNodes.find( node );
00388     bool nodeInMe = ( pNode != myNodes.end() );
00389 
00390     bool pointInMe = isInside( toPnt.Coord(), 1e-10 );
00391 
00392     if ( pointInMe != nodeInMe )
00393     {
00394       if ( pointInMe )
00395         myNodes.insert( node );
00396       else
00397         myNodes.erase( node );
00398     }
00399   }
00400   else if ( myChildren )
00401   {
00402     gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
00403     int nodeChild  = getChildIndex( node->X(), node->Y(), node->Z(), mid );
00404     int pointChild = getChildIndex( toPnt.X(), toPnt.Y(), toPnt.Z(), mid );
00405     if ( nodeChild != pointChild )
00406     {
00407       ((SMESH_OctreeNode*) myChildren[ nodeChild  ])->UpdateByMoveNode( node, toPnt );
00408       ((SMESH_OctreeNode*) myChildren[ pointChild ])->UpdateByMoveNode( node, toPnt );
00409     }
00410   }
00411 }
00412 
00413 //================================================================================
00417 //================================================================================
00418 SMESH_OctreeNodeIteratorPtr SMESH_OctreeNode::GetChildrenIterator()
00419 {
00420   return SMESH_OctreeNodeIteratorPtr
00421     ( new SMDS_SetIterator< SMESH_OctreeNode*, SMESH_Octree** >
00422       ( myChildren, (( isLeaf() || !myChildren ) ? myChildren : &myChildren[ 8 ] )));
00423 }
00424 
00425 //================================================================================
00429 //================================================================================
00430 SMDS_NodeIteratorPtr SMESH_OctreeNode::GetNodeIterator()
00431 {
00432   return SMDS_NodeIteratorPtr
00433     ( new SMDS_SetIterator< SMDS_pNode, TIDSortedNodeSet::const_iterator >
00434       ( myNodes.begin(), myNodes.size() ? myNodes.end() : myNodes.begin()));
00435 }
Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS