// Copyright (C) 2007-2019 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // Author : Anthony Geay (CEA/DEN) #ifndef __BBTREEDST_TXX__ #define __BBTREEDST_TXX__ #include #include #include #include #include template class BBTreeDst { private: BBTreeDst* _left; BBTreeDst* _right; int _level; double _max_left; double _min_right; const double *_bb; std::vector _elems; double *_terminal; mcIdType _nbelems; static const int MIN_NB_ELEMS=15; static const int MAX_LEVEL=20; public: BBTreeDst(const double* bbs, mcIdType* elems, int level, mcIdType nbelems): _left(0),_right(0),_level(level),_bb(bbs),_terminal(0),_nbelems(nbelems) { if((nbelems < MIN_NB_ELEMS || level> MAX_LEVEL)) _terminal=new double[2*dim]; _elems.resize(nbelems); for (mcIdType i=0; i(nodes, nodes+nbelems/2, nodes+nbelems); double median = *(nodes+nbelems/2); delete [] nodes; std::vector new_elems_left; std::vector new_elems_right; new_elems_left.reserve(nbelems/2+1); new_elems_right.reserve(nbelems/2+1); double max_left = -std::numeric_limits::max(); double min_right= std::numeric_limits::max(); for(mcIdType i=0; imedian) { new_elems_right.push_back(elem); if (minmax_left) max_left = max; } } _max_left=max_left; _min_right=min_right; mcIdType *tmp; tmp=0; if(!new_elems_left.empty()) tmp=&(new_elems_left[0]); _left=new BBTreeDst(bbs, tmp, level+1, ToIdType(new_elems_left.size())); tmp=0; if(!new_elems_right.empty()) tmp=&(new_elems_right[0]); _right=new BBTreeDst(bbs, tmp, level+1, ToIdType(new_elems_right.size())); } ~BBTreeDst() { delete _left; delete _right; delete [] _terminal; } void getElemsWhoseMinDistanceToPtSmallerThan(const double *pt, double minOfMaxDstsSq, std::vector& elems) const { if(_terminal) { for(mcIdType i=0; i<_nbelems; i++) { if(GetMinDistanceFromBBoxToPt(_bb+_elems[i]*2*dim,pt)minOfMaxDsts) { _left->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); return ; } if(pt[_level%dim]-_max_left>minOfMaxDsts) { _right->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); return ; } _left->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); _right->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); } } /** Get the minimal (square) distance between a point and all the available bounding boxes in the tree. The (square) distance to a bbox is the true geometric distance between the point and a face (or an edge, or a corner) of the bbox. */ void getMinDistanceOfMax(const double *pt, double& minOfMaxDstsSq) const { if(_terminal) { if(GetMinDistanceFromBBoxToPt(_terminal,pt)>minOfMaxDstsSq)//min it is not a bug return ; for(mcIdType i=0; i<_nbelems; i++) { minOfMaxDstsSq=std::min(minOfMaxDstsSq,GetMaxDistanceFromBBoxToPt(_bb+_elems[i]*2*dim,pt)); } } else { double minOfMaxDsts=sqrt(minOfMaxDstsSq); if(_min_right-pt[_level%dim]>minOfMaxDsts) { _left->getMinDistanceOfMax(pt,minOfMaxDstsSq); return ; } if(pt[_level%dim]-_max_left>minOfMaxDsts) { _right->getMinDistanceOfMax(pt,minOfMaxDstsSq); return ; } _left->getMinDistanceOfMax(pt,minOfMaxDstsSq); _right->getMinDistanceOfMax(pt,minOfMaxDstsSq); } } void fillBBoxTerminal(const double* bbs) { for(int j=0;j::max(); _terminal[2*j+1]=-std::numeric_limits::max(); } for(mcIdType i=0;i<_nbelems;i++) { for(int j=0;jmax -> no cells in this return std::numeric_limits::max(); } static double GetMinDistanceFromBBoxToPt(const double *bbox, const double *pt) { if(bbox[0]<=bbox[1]) { double zeRes=0.; for (int idim=0; idim((( (0.max -> no cells in this return std::numeric_limits::max(); } }; #endif