1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // HYDRO HYDROData_QuadtreeNode : Quadtree with Nodes set (from SMESH module)
24 // inherites class HYDROData_Quadtree
25 // File : HYDROData_QuadtreeNode.cxx
26 // Created : Tue Jan 16 16:00:00 2007
27 // Author : Nicolas Geimer & Aurelien Motteux (OCC)
30 #include "HYDROData_QuadtreeNode.hxx"
35 #include "HYDRO_trace.hxx"
40 * \brief Constructor : Build all the Quadtree using Compute()
41 * \param theNodes - Set of nodes, the Quadtree is built from this nodes
42 * \param maxLevel - Maximum level for the leaves
43 * \param maxNbNodes - Maximum number of nodes, a leaf can contain
44 * \param minBoxSize - Minimal size of the Quadtree Box
46 HYDROData_QuadtreeNode::HYDROData_QuadtreeNode(Nodes_3D* theNodes,
49 const double minBoxSize) :
50 HYDROData_Quadtree(new Limit(maxLevel, minBoxSize, maxNbNodes)), myNodes(theNodes), myPrecision(0.25)
52 //DEBTRACE("---------------------------- HYDROData_QuadtreeNode root constructor");
55 //DEBTRACE(" --- start compute");
57 //DEBTRACE(" --- end compute");
62 * \brief Constructor used to allocate a child
64 HYDROData_QuadtreeNode::HYDROData_QuadtreeNode() :
65 HYDROData_Quadtree(), myNodes(0), myPrecision(0.25)
67 myNodes = new Nodes_3D();
71 * \brief virtual destructor: deletes myNodes
73 HYDROData_QuadtreeNode::~HYDROData_QuadtreeNode()
83 * \brief Set the nodes and compute the quadtree,
84 * when the nodes are not given to the public constructor (delayed compute)
86 void HYDROData_QuadtreeNode::setNodesAndCompute(Nodes_3D* theNodes)
91 DEBTRACE(" --- start compute");
93 DEBTRACE(" --- end compute : children & height " << this->nbChildren() << " " << this->getHeight());
94 DEBTRACE("Bounding box min: " << this->myBox->CornerMin().X() << " " << this->myBox->CornerMin().Y());
95 DEBTRACE("Bounding box max: " << this->myBox->CornerMax().X() << " " << this->myBox->CornerMax().Y());
100 * \brief Return max number of nodes in a tree leaf
102 int HYDROData_QuadtreeNode::getMaxNbNodes() const
104 return ((Limit*) myLimit)->myMaxNbNodes;
108 * \brief Construct an empty HYDROData_QuadtreeNode used by HYDROData_Quadtree::buildChildren()
110 HYDROData_Quadtree* HYDROData_QuadtreeNode::newChild() const
112 return new HYDROData_QuadtreeNode();
116 * \brief Compute the first bounding box
118 * We take the max/min coord of the nodes
120 Bnd_B2d* HYDROData_QuadtreeNode::buildRootBox()
122 Bnd_B2d* box = new Bnd_B2d;
123 Nodes_3D::iterator it = myNodes->begin();
124 for (; it != myNodes->end(); it++)
126 const gpi_XYZ* n1 = *it;
127 gp_XY p1(n1->X(), n1->Y());
130 if (myNodes->size() <= getMaxNbNodes())
137 * \brief Tells us if Node is inside the current box with the precision "precision"
139 * \param precision - The box is enlarged with this precision
140 * \retval bool - True if Node is in the box within precision
142 const bool HYDROData_QuadtreeNode::isInside(const gp_XY& p, const double precision)
145 return !(getBox()->IsOut(p));
146 Bnd_B2d BoxWithPrecision = *getBox();
147 BoxWithPrecision.Enlarge(precision);
148 return !BoxWithPrecision.IsOut(p);
152 * \brief Set the data of the children
153 * Shares the father's data with each of his child
155 void HYDROData_QuadtreeNode::buildChildrenData()
157 gp_XY min = getBox()->CornerMin();
158 gp_XY max = getBox()->CornerMax();
159 gp_XY mid = (min + max) / 2.;
161 //DEBTRACE("buildChildrenData level, min, max, nbNodes "<<level()<< " ("<< min.X()<<","<< min.Y()<<") ("<< max.X()<<","<< max.Y()<<") "<< myNodes->size());
162 Nodes_3D::iterator it = myNodes->begin();
163 while (it != myNodes->end())
166 int ChildBoxNum = getChildIndex(n1->X(), n1->Y(), mid);
167 HYDROData_QuadtreeNode* myChild = dynamic_cast<HYDROData_QuadtreeNode*>(myChildren[ChildBoxNum]);
168 myChild->myNodes->push_back(n1);
170 it = myNodes->begin();
172 for (int i = 0; i < 4; i++)
174 HYDROData_QuadtreeNode* myChild = dynamic_cast<HYDROData_QuadtreeNode*>(myChildren[i]);
175 if (myChild->myNodes->size() <= getMaxNbNodes())
177 myChild->myIsLeaf = true;
178 //DEBTRACE("buildChildrenData leaf nbNodes "<< myChild->myNodes->size());
184 * \brief Return in Result a list of Nodes potentials to be near Node
186 * \param precision - precision used
187 * \param Result - list of Nodes potentials to be near Node
189 void HYDROData_QuadtreeNode::NodesAround(const gp_XY& Node,
190 list<const gpi_XYZ*>* Result,
191 const double precision)
194 if (isInside(p, precision))
198 Result->insert(Result->end(), myNodes->begin(), myNodes->end());
199 //DEBTRACE("Leaf result "<< Result->size());
203 for (int i = 0; i < 4; i++)
205 HYDROData_QuadtreeNode* myChild = dynamic_cast<HYDROData_QuadtreeNode*>(myChildren[i]);
206 myChild->NodesAround(p, Result, precision);
213 * \brief Return in dist2Nodes nodes mapped to their square distance from Node
214 * \param node - node to find nodes closest to
215 * \param dist2Nodes - map of found nodes and their distances
216 * \param precision - radius of a sphere to check nodes inside
217 * \retval bool - true if an exact overlapping found !!!
219 bool HYDROData_QuadtreeNode::NodesAround(const gp_XY& node,
220 map<double, const gpi_XYZ*>& dist2Nodes,
223 if (!dist2Nodes.empty())
224 precision = min(precision, sqrt(dist2Nodes.begin()->first));
225 else if (precision == 0.)
226 precision = maxSize() / 2;
228 if (isInside(node, precision))
232 // first check a child containing node
233 gp_XY mid = (getBox()->CornerMin() + getBox()->CornerMax()) / 2.;
234 int nodeChild = getChildIndex(node.X(), node.Y(), mid);
235 if (((HYDROData_QuadtreeNode*) myChildren[nodeChild])->NodesAround(node, dist2Nodes, precision))
238 for (int i = 0; i < 4; i++)
240 if (((HYDROData_QuadtreeNode*) myChildren[i])->NodesAround(node, dist2Nodes, precision))
243 else if (NbNodes() > 0)
245 double minDist = precision * precision;
246 Nodes_3D::iterator nIt = myNodes->begin();
247 for (; nIt != myNodes->end(); ++nIt)
249 const gpi_XYZ* p = *nIt;
250 gp_XY p2(p->X(), p->Y());
251 double dist2 = (node - p2).SquareModulus();
253 dist2Nodes.insert(make_pair(minDist = dist2, p));
255 // if ( dist2Nodes.size() > 1 ) // leave only closest node in dist2Nodes
256 // dist2Nodes.erase( ++dist2Nodes.begin(), dist2Nodes.end());
258 // true if an exact overlapping found
259 return (sqrt(minDist) <= precision * 1e-12);