Boost logo

Geometry :

Subject: Re: [geometry] breadth first visiting with visitor for R tree's MBRs
From: Adam Wulkiewicz (adam.wulkiewicz_at_[hidden])
Date: 2018-03-02 00:13:26


Hi,

Zhe Li Via Geometry wrote:
> Below is the visitor code I wrote. The struct 'tempnode' is used to be
> stored as a temp result in the priority queue.
>
>
>
> How should I change it to meet the requirement?

In the elements container of internal node there are pairs of MBR and
node pointer. When you call apply_visitor() you're passing node and
visitor into it and inside this function the node is dispatched either
into internal_node or leaf and passed into your visitor. So you should
rather store node pointer or node reference with MBR, not a copy of
internal node. In fact you could simply store pairs that are contained
in elements container. You could define the type of the pair like that:

typedef typename bgid::rtree::elements_type<internal_node>::type
elements_type;
typedef boost::range_value<elements_type>::type mbr_node_ptr_pair_t;

> Actually, my problem is quite similar to visiting the MBRs level by level
> (breadth first), so if there is an example of breadth-first visiting using
> visitor, I think I could figure out my problem according to it.

Here you go, breadth-first and depth-first printing of internal nodes
MBRs and leafs elements numbers. Note that I only store node pointers of
the nodes that are going to be traversed next in m_nodes container and
that you have to keep traversing also when you reach leafs because there
may be nodes left in the container.

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <deque>
#include <iostream>

namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
namespace bgid = bgi::detail;

typedef bg::model::point<float, 2, bg::cs::cartesian> point;
typedef bgi::rtree<point, bgi::linear<3> > rtree;
typedef bg::model::box<point> box;

template
<
 Â Â Â  typename Value,
 Â Â Â  typename Options,
 Â Â Â  typename Translator,
 Â Â Â  typename Box,
 Â Â Â  typename Allocators>
class breadth_first_visitor
 Â Â Â  : public bgid::rtree::visitor
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  Value,
 Â Â Â Â Â Â Â Â Â Â Â  typename Options::parameters_type,
 Â Â Â Â Â Â Â Â Â Â Â  Box,
 Â Â Â Â Â Â Â Â Â Â Â  Allocators,
 Â Â Â Â Â Â Â Â Â Â Â  typename Options::node_tag,
 Â Â Â Â Â Â Â Â Â Â Â  true
 Â Â Â Â Â Â Â  >::type

{
 Â Â Â  typedef typename bgid::rtree::internal_node
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  Value, typename Options::parameters_type, Box, Allocators,
typename Options::node_tag
 Â Â Â Â Â Â Â  >::type internal_node;

 Â Â Â  typedef typename bgid::rtree::leaf
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  Value, typename Options::parameters_type, Box, Allocators,
typename Options::node_tag
 Â Â Â Â Â Â Â  >::type leaf;

 Â Â Â  typedef typename Allocators::node_pointer node_pointer;

public:
 Â Â Â  void operator()(internal_node const& n)
 Â Â Â  {
 Â Â Â Â Â Â Â  typedef typename
bgid::rtree::elements_type<internal_node>::type elements_type;
 Â Â Â Â Â Â Â  elements_type const& elements = bgid::rtree::elements(n);

 Â Â Â Â Â Â Â  for ( typename elements_type::const_iterator it = elements.begin();
 Â Â Â Â Â Â Â Â Â Â Â Â Â  it != elements.end() ; ++it)
 Â Â Â Â Â Â Â  {
 Â Â Â Â Â Â Â Â Â Â Â  // do something with MBR
std::cout << bg::dsv(it->first) << std::endl;

 Â Â Â Â Â Â Â Â Â Â Â  // add child node pointer to the container
 Â Â Â Â Â Â Â Â Â Â Â  m_nodes.push_back(it->second);
 Â Â Â Â Â Â Â  }

 Â Â Â Â Â Â Â  traverse();
 Â Â Â  }

 Â Â Â  void operator()(leaf const& n)
 Â Â Â  {
 Â Â Â Â Â Â Â  std::cout << boost::size(bgid::rtree::elements(n)) << "
elements in leaf" << std::endl;

 Â Â Â Â Â Â Â  traverse();
 Â Â Â  }

private:
 Â Â Â  void traverse()
 Â Â Â  {
 Â Â Â Â Â Â Â  if (! m_nodes.empty())
 Â Â Â Â Â Â Â  {
 Â Â Â Â Â Â Â Â Â Â Â  node_pointer next = m_nodes.front();
 Â Â Â Â Â Â Â Â Â Â Â  m_nodes.pop_front();

 Â Â Â Â Â Â Â Â Â Â Â  bgid::rtree::apply_visitor(*this, *next);
 Â Â Â Â Â Â Â  }
 Â Â Â  }

 Â Â Â  std::deque<node_pointer> m_nodes;
};

template
<
 Â Â Â  typename Value,
 Â Â Â  typename Options,
 Â Â Â  typename Translator,
 Â Â Â  typename Box,
 Â Â Â  typename Allocators>
class depth_first_visitor
 Â Â Â  : public bgid::rtree::visitor
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  Value,
 Â Â Â Â Â Â Â Â Â Â Â  typename Options::parameters_type,
 Â Â Â Â Â Â Â Â Â Â Â  Box,
 Â Â Â Â Â Â Â Â Â Â Â  Allocators,
 Â Â Â Â Â Â Â Â Â Â Â  typename Options::node_tag,
 Â Â Â Â Â Â Â Â Â Â Â  true
 Â Â Â Â Â Â Â  >::type

{
 Â Â Â  typedef typename bgid::rtree::internal_node
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  Value, typename Options::parameters_type, Box, Allocators,
typename Options::node_tag
 Â Â Â Â Â Â Â  >::type internal_node;

 Â Â Â  typedef typename bgid::rtree::leaf
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  Value, typename Options::parameters_type, Box, Allocators,
typename Options::node_tag
 Â Â Â Â Â Â Â  >::type leaf;

 Â Â Â  typedef typename Allocators::node_pointer node_pointer;

public:
 Â Â Â  void operator()(internal_node const& n)
 Â Â Â  {
 Â Â Â Â Â Â Â  typedef typename
bgid::rtree::elements_type<internal_node>::type elements_type;
 Â Â Â Â Â Â Â  elements_type const& elements = bgid::rtree::elements(n);

 Â Â Â Â Â Â Â  for ( typename elements_type::const_iterator it = elements.begin();
 Â Â Â Â Â Â Â Â Â Â Â Â Â  it != elements.end() ; ++it)
 Â Â Â Â Â Â Â  {
 Â Â Â Â Â Â Â Â Â Â Â  // do something with MBR
std::cout << bg::dsv(it->first) << std::endl;

 Â Â Â Â Â Â Â Â Â Â Â  // traverse
 Â Â Â Â Â Â Â Â Â Â Â  node_pointer next = it->second;
 Â Â Â Â Â Â Â Â Â Â Â  bgid::rtree::apply_visitor(*this, *next);
 Â Â Â Â Â Â Â  }
 Â Â Â  }

 Â Â Â  void operator()(leaf const& n)
 Â Â Â  {
 Â Â Â Â Â Â Â  std::cout << boost::size(bgid::rtree::elements(n)) << "
elements in leaf" << std::endl;
 Â Â Â  }
};

template <typename Rtree>
inline void print_breadth_first(Rtree const& tree)
{
 Â Â Â  typedef bgid::rtree::utilities::view<Rtree> RTV;
 Â Â Â  RTV rtv(tree);

 Â Â Â  breadth_first_visitor
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::value_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::options_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::translator_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::box_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::allocators_type
 Â Â Â Â Â Â Â  > v;

 Â Â Â  rtv.apply_visitor(v);
}

template <typename Rtree>
inline void print_depth_first(Rtree const& tree)
{
 Â Â Â  typedef bgid::rtree::utilities::view<Rtree> RTV;
 Â Â Â  RTV rtv(tree);

 Â Â Â  depth_first_visitor
 Â Â Â Â Â Â Â  <
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::value_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::options_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::translator_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::box_type,
 Â Â Â Â Â Â Â Â Â Â Â  typename RTV::allocators_type
 Â Â Â Â Â Â Â  > v;

 Â Â Â  rtv.apply_visitor(v);
}

int main()
{
 Â Â Â  rtree tree;

 Â Â Â  for (int i = 0 ; i < 10 ; i += 1)
 Â Â Â Â Â Â Â  tree.insert(point(i, i));

 Â Â Â  std::cout << "breadth first" << std::endl;
 Â Â Â  print_breadth_first(tree);
 Â Â Â  std::cout << "depth first" << std::endl;
 Â Â Â  print_depth_first(tree);
}

I get the following results:

breadth first
((4, 4), (9, 9))
((0, 0), (3, 3))
((6, 6), (7, 7))
((4, 4), (5, 5))
((8, 8), (9, 9))
((0, 0), (1, 1))
((2, 2), (3, 3))
2 elements in leaf
2 elements in leaf
2 elements in leaf
2 elements in leaf
2 elements in leaf
depth first
((4, 4), (9, 9))
((6, 6), (7, 7))
2 elements in leaf
((4, 4), (5, 5))
2 elements in leaf
((8, 8), (9, 9))
2 elements in leaf
((0, 0), (3, 3))
((0, 0), (1, 1))
2 elements in leaf
((2, 2), (3, 3))
2 elements in leaf

Adam



Geometry list run by mateusz at loskot.net