26   struct rtree_node : 
public rtree_elt_base {
 
   27     std::unique_ptr<rtree_elt_base> left, right;
 
   28     rtree_node(
const base_node& bmin, 
const base_node& bmax,
 
   29                std::unique_ptr<rtree_elt_base> &&left_,
 
   30                std::unique_ptr<rtree_elt_base> &&right_)
 
   31       : rtree_elt_base(false, bmin, bmax), left(std::move(left_)),
 
   32         right( std::move(right_)) { }
 
   35   struct rtree_leaf : 
public rtree_elt_base {
 
   37     rtree_leaf(
const base_node& bmin, 
const base_node& bmax,
 
   38                rtree::pbox_cont& lst_)
 
   39       : rtree_elt_base(true, bmin, bmax) { lst.swap(lst_); }
 
   43   static void update_box(base_node& bmin, base_node& bmax,
 
   44                          const base_node& a, 
const base_node& b) {
 
   45     base_node::iterator itmin=bmin.begin(), itmax=bmax.begin();
 
   47       itmin[i] = std::min(itmin[i], a.at(i));
 
   48       itmax[i] = std::max(itmax[i], b.at(i));
 
   52   inline static bool r1_ge_r2(
const base_node& min1, 
const base_node& max1,
 
   53                        const base_node& min2, 
const base_node& max2,
 
   56       if ((min1[i] > min2[i]+EPS) || (max1[i] < max2[i]-EPS)) 
return false;
 
   60   inline static bool r1_inter_r2(
const base_node& min1, 
const base_node& max1,
 
   61                           const base_node& min2, 
const base_node& max2,
 
   64       if ((max1[i] < min2[i]-EPS) || (min1[i] > max2[i]+EPS)) 
return false;
 
   69   struct intersection_p {
 
   70     const base_node &min, &max;
 
   71     const scalar_type EPS;
 
   72     intersection_p(
const base_node& min_, 
const base_node& max_, scalar_type EPS_)
 
   73       : min(min_), max(max_), EPS(EPS_) {}
 
   74     bool operator()(
const base_node& min2, 
const base_node& max2)
 const 
   75     { 
return r1_inter_r2(min,max,min2,max2,EPS); }
 
   76     bool accept(
const base_node& min2, 
const base_node& max2)
 const 
   77     { 
return operator()(min2,max2); }
 
   82     const base_node &min, &max;
 
   83     const scalar_type EPS;
 
   84     contains_p(
const base_node& min_, 
const base_node& max_, scalar_type EPS_)
 
   85       : min(min_), max(max_), EPS(EPS_) {}
 
   86     bool operator()(
const base_node& min2, 
const base_node& max2)
 const 
   87     { 
return r1_ge_r2(min2,max2,min,max,EPS); }
 
   88     bool accept(
const base_node& min2, 
const base_node& max2)
 const 
   89     { 
return r1_inter_r2(min,max,min2,max2,EPS); }
 
   94     const base_node &min, &max;
 
   95     const scalar_type EPS;
 
   96     contained_p(
const base_node& min_, 
const base_node& max_, scalar_type EPS_)
 
   97       : min(min_), max(max_), EPS(EPS_) {}
 
   98     bool accept(
const base_node& min2, 
const base_node& max2)
 const 
   99     { 
return r1_inter_r2(min,max,min2,max2,EPS); }
 
  100     bool operator()(
const base_node& min2, 
const base_node& max2)
 const 
  101     { 
return r1_ge_r2(min,max,min2,max2,EPS); }
 
  107     const scalar_type EPS;
 
  108     has_point_p(
const base_node& P_, scalar_type EPS_) : P(P_), EPS(EPS_) {}
 
  109     bool operator()(
const base_node& min2, 
const base_node& max2)
 const {
 
  110       for (
size_type i = 0; i < P.size(); ++i) {
 
  111         if (P[i] < min2[i]-EPS) 
return false;
 
  112         if (P[i] > max2[i]+EPS) 
return false;
 
  116     bool accept(
const base_node& min2, 
const base_node& max2)
 const 
  117     { 
return operator()(min2,max2); }
 
  122   struct intersect_line {
 
  124     const base_small_vector dirv;
 
  125     intersect_line(
const base_node& org_, 
const base_small_vector &dirv_)
 
  126       : org(org_), dirv(dirv_) {}
 
  127     bool operator()(
const base_node& min2, 
const base_node& max2)
 const {
 
  129       GMM_ASSERT1(N == min2.size(), 
"Dimensions mismatch");
 
  131         if (dirv[i] != scalar_type(0)) {
 
  132           scalar_type a1=(min2[i]-org[i])/dirv[i], a2=(max2[i]-org[i])/dirv[i];
 
  133           bool interf1 = 
true, interf2 = 
true;
 
  136               scalar_type y1 = org[j] + a1*dirv[j], y2 = org[j] + a2*dirv[j];
 
  137               if (y1 < min2[j] || y1 > max2[j]) interf1 = 
false;
 
  138               if (y2 < min2[j] || y2 > max2[j]) interf2 = 
false;
 
  140           if (interf1 || interf2) 
return true;
 
  144     bool accept(
const base_node& min2, 
const base_node& max2)
 const 
  145     { 
return operator()(min2,max2); }
 
  150   struct intersect_line_and_box {
 
  152     const base_small_vector dirv;
 
  153     const base_node min,max;
 
  154     const scalar_type EPS;
 
  155     intersect_line_and_box(
const base_node& org_,
 
  156                            const base_small_vector &dirv_,
 
  157                            const base_node& min_, 
const base_node& max_,
 
  159       : org(org_), dirv(dirv_), min(min_), max(max_), EPS(EPS_) {}
 
  160     bool operator()(
const base_node& min2, 
const base_node& max2)
 const {
 
  162       GMM_ASSERT1(N == min2.size(), 
"Dimensions mismatch");
 
  163       if (!(r1_inter_r2(min,max,min2,max2,EPS))) 
return false;
 
  165         if (dirv[i] != scalar_type(0)) {
 
  166           scalar_type a1=(min2[i]-org[i])/dirv[i], a2=(max2[i]-org[i])/dirv[i];
 
  167           bool interf1 = 
true, interf2 = 
true;
 
  170               scalar_type y1 = org[j] + a1*dirv[j], y2 = org[j] + a2*dirv[j];
 
  171               if (y1 < min2[j] || y1 > max2[j]) interf1 = 
false;
 
  172               if (y2 < min2[j] || y2 > max2[j]) interf2 = 
false;
 
  174           if (interf1 || interf2) 
return true;
 
  178     bool accept(
const base_node& min2, 
const base_node& max2)
 const 
  179     { 
return operator()(min2,max2); }
 
  182   size_type rtree::add_box(
const base_node &min, 
const base_node &max,
 
  186       GMM_WARNING3(
"Add a box when the tree is already built cancel the tree. " 
  187                    "Unefficient operation.");
 
  188       tree_built = 
false; root = std::unique_ptr<rtree_elt_base>();
 
  190     bi.min = &nodes[nodes.
add_node(min, EPS)];
 
  191     bi.max = &nodes[nodes.
add_node(max, EPS)];
 
  192     bi.id = (
id + 1) ? 
id : boxes.size();
 
  193     return boxes.emplace(std::move(bi)).first->id;
 
  196   rtree::rtree(scalar_type EPS_)
 
  197     : EPS(EPS_), boxes(box_index_topology_compare(EPS_)), tree_built(false)
 
  200   void rtree::clear() {
 
  201     root = std::unique_ptr<rtree_elt_base>();
 
  207   template <
typename Predicate>
 
  208   static void find_matching_boxes_(rtree_elt_base *n, rtree::pbox_set& boxlst,
 
  209                                    const Predicate &p) {
 
  211       const rtree_leaf *rl = 
static_cast<rtree_leaf*
>(n);
 
  212       for (rtree::pbox_cont::const_iterator it = rl->lst.begin();
 
  213            it != rl->lst.end(); ++it) {
 
  214         if (p(*(*it)->min, *(*it)->max)) { boxlst.insert(*it); }
 
  217       const rtree_node *rn = 
static_cast<rtree_node*
>(n);
 
  218       if (p.accept(rn->left->rmin,rn->left->rmax))
 
  219         bgeot::find_matching_boxes_(rn->left.get(), boxlst, p);
 
  220       if (p.accept(rn->right->rmin,rn->right->rmax))
 
  221         bgeot::find_matching_boxes_(rn->right.get(), boxlst, p);
 
  225   void rtree::find_intersecting_boxes(
const base_node& bmin,
 
  226                                       const base_node& bmax,
 
  227                                       pbox_set& boxlst)
 const {
 
  230     GMM_ASSERT2(tree_built, 
"Boxtree not initialised.");
 
  232       find_matching_boxes_(root.get(),boxlst,intersection_p(bmin,bmax, EPS));
 
  235   void rtree::find_containing_boxes(
const base_node& bmin,
 
  236                                     const base_node& bmax,
 
  237                                     pbox_set& boxlst)
 const {
 
  239     GMM_ASSERT2( tree_built, 
"Boxtree not initialised.");
 
  241       find_matching_boxes_(root.get(), boxlst, contains_p(bmin,bmax, EPS));
 
  244   void rtree::find_contained_boxes(
const base_node& bmin,
 
  245                                    const base_node& bmax,
 
  246                                    pbox_set& boxlst)
 const {
 
  248     GMM_ASSERT2(tree_built, 
"Boxtree not initialised.");
 
  250       find_matching_boxes_(root.get(), boxlst, contained_p(bmin,bmax, EPS));
 
  253   void rtree::find_boxes_at_point(
const base_node& P, pbox_set& boxlst)
 const {
 
  255     GMM_ASSERT2(tree_built, 
"Boxtree not initialised.");
 
  257       find_matching_boxes_(root.get(), boxlst, has_point_p(P, EPS));
 
  260   void rtree::find_line_intersecting_boxes(
const base_node& org,
 
  261                                            const base_small_vector& dirv,
 
  262                                            pbox_set& boxlst)
 const {
 
  264     GMM_ASSERT2(tree_built, 
"Boxtree not initialised.");
 
  266       find_matching_boxes_(root.get(),boxlst,intersect_line(org, dirv));
 
  269   void rtree::find_line_intersecting_boxes(
const base_node& org,
 
  270                                            const base_small_vector& dirv,
 
  271                                            const base_node& bmin,
 
  272                                            const base_node& bmax,
 
  273                                            pbox_set& boxlst)
 const {
 
  275     GMM_ASSERT2(tree_built, 
"Boxtree not initialised.");
 
  277       find_matching_boxes_(root.get(), boxlst,
 
  278                            intersect_line_and_box(org, dirv, bmin, bmax, EPS));
 
  285   static bool split_test(
const rtree::pbox_cont& b,
 
  286                          const base_node& bmin, 
const base_node& bmax,
 
  287                          unsigned dir, scalar_type& split_v) {
 
  288     scalar_type v = bmin[dir] + (bmax[dir] - bmin[dir])/2; split_v = v;
 
  290     for (rtree::pbox_cont::const_iterator it = b.begin(); it!=b.end(); ++it) {
 
  291       if ((*it)->max->at(dir) < v) {
 
  292         if (cnt == 0) split_v = (*it)->max->at(dir);
 
  293         else split_v = std::max((*it)->max->at(dir),split_v);
 
  297     return (cnt > 0 && cnt < b.size());
 
  306   static std::unique_ptr<rtree_elt_base> build_tree_(rtree::pbox_cont b,
 
  307                                                      const base_node& bmin,
 
  308                                                      const base_node& bmax,
 
  311     scalar_type split_v(0);
 
  312     unsigned split_dir = unsigned((last_dir+1)%N);
 
  313     bool split_ok = 
false;
 
  314     if (b.size() > rtree_elt_base::RECTS_PER_LEAF) {
 
  315       for (
size_type itry=0; itry < N; ++itry) {
 
  316         if (split_test(b, bmin, bmax, split_dir, split_v))
 
  317           { split_ok = 
true; 
break; }
 
  318         split_dir = unsigned((split_dir+1)%N);
 
  323       for (rtree::pbox_cont::const_iterator it = b.begin();
 
  324            it != b.end(); ++it) {
 
  325         if ((*it)->min->at(split_dir) < split_v) cnt1++;
 
  326         if ((*it)->max->at(split_dir) > split_v) cnt2++;
 
  328       assert(cnt1); assert(cnt2);
 
  329       GMM_ASSERT1(cnt1+cnt2 >= b.size(), 
"internal error");
 
  330       rtree::pbox_cont v1(cnt1), v2(cnt2);
 
  331       base_node bmin1(bmax), bmax1(bmin);
 
  332       base_node bmin2(bmax), bmax2(bmin);
 
  334       for (rtree::pbox_cont::const_iterator it = b.begin();
 
  335            it != b.end(); ++it) {
 
  336         if ((*it)->min->at(split_dir) < split_v) {
 
  338           update_box(bmin1,bmax1,*(*it)->min,*(*it)->max);
 
  340         if ((*it)->max->at(split_dir) > split_v) {
 
  342           update_box(bmin2,bmax2,*(*it)->min,*(*it)->max);
 
  346         bmin1[k] = std::max(bmin1[k],bmin[k]);
 
  347         bmax1[k] = std::min(bmax1[k],bmax[k]);
 
  348         bmin2[k] = std::max(bmin2[k],bmin[k]);
 
  349         bmax2[k] = std::min(bmax2[k],bmax[k]);
 
  351       bmax1[split_dir] = std::min(bmax1[split_dir], split_v);
 
  352       bmin2[split_dir] = std::max(bmin2[split_dir], split_v);
 
  353       assert(cnt1 == v1.size()); assert(cnt2 == v2.size());
 
  354       return std::make_unique<rtree_node>
 
  356          build_tree_(v1, bmin1, bmax1, split_dir),
 
  357          build_tree_(v2, bmin2, bmax2, split_dir));
 
  359       return std::make_unique<rtree_leaf>(bmin, bmax, b);
 
  363   void rtree::build_tree() {
 
  365       if (boxes.size() == 0) { tree_built = 
true; 
return; }
 
  366       getfem::local_guard lock = locks_.get_lock();
 
  368       pbox_cont b(boxes.size());
 
  369       pbox_cont::iterator b_it = b.begin();
 
  370       base_node bmin(*boxes.begin()->min), bmax(*boxes.begin()->max);
 
  371       for (box_cont::const_iterator it=boxes.begin(); it != boxes.end(); ++it) {
 
  372         update_box(bmin,bmax,*(*it).min,*(*it).max);
 
  375       root = build_tree_(b, bmin, bmax, 0);
 
  380   static void dump_tree_(rtree_elt_base *p, 
int level, 
size_type& count) {
 
  382     for (
int i=0; i < level; ++i) cout << 
"  ";
 
  383     cout << 
"span=" << p->rmin << 
".." << p->rmax << 
" ";
 
  385       rtree_leaf *rl = 
static_cast<rtree_leaf*
>(p);
 
  386       cout << 
"Leaf [" << rl->lst.size() << 
" elts] = ";
 
  387       for (
size_type i=0; i < rl->lst.size(); ++i)
 
  388         cout << 
" " << rl->lst[i]->id;
 
  390       count += rl->lst.size();
 
  393       const rtree_node *rn = 
static_cast<rtree_node*
>(p);
 
  394       if (rn->left) { dump_tree_(rn->left.get(), level+1, count); }
 
  395       if (rn->right) { dump_tree_(rn->right.get(), level+1, count); }
 
  400     cout << 
"tree dump follows\n";
 
  401     if (!root) build_tree();
 
  403     dump_tree_(root.get(), 0, count);
 
  404     cout << 
" --- end of tree dump, nb of rectangles: " << boxes.size()
 
  405          << 
", rectangle ref in tree: " << count << 
"\n";
 
region-tree for window/point search on a set of rectangles.
 
size_type add_node(const base_node &pt, const scalar_type radius=0, bool remove_duplicated_nodes=true)
Add a point to the array or use an existing point, located within a distance smaller than radius.
 
size_t size_type
used as the common size type in the library