mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
[index][example] Improve the rtree visualization.
Add support for rtrees storing Points and Segments. Add the support for Segments in print_indexable() and gl_draw_indexable() index utilities.
This commit is contained in:
parent
82304fdeef
commit
ba8d1b471d
@ -11,6 +11,8 @@
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
namespace utilities {
|
||||
@ -26,8 +28,16 @@ struct gl_draw_point<Point, 2>
|
||||
{
|
||||
static inline void apply(Point const& p, typename coordinate_type<Point>::type z)
|
||||
{
|
||||
glBegin(GL_POINT);
|
||||
glVertex3f(geometry::get<0>(p), geometry::get<1>(p), z);
|
||||
typename coordinate_type<Point>::type const& x = geometry::get<0>(p);
|
||||
typename coordinate_type<Point>::type const& y = geometry::get<1>(p);
|
||||
/*glBegin(GL_POINT);
|
||||
glVertex3f(x, y, z);
|
||||
glEnd();*/
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(x+1, y, z);
|
||||
glVertex3f(x, y+1, z);
|
||||
glVertex3f(x-1, y, z);
|
||||
glVertex3f(x, y-1, z);
|
||||
glEnd();
|
||||
}
|
||||
};
|
||||
@ -50,32 +60,42 @@ struct gl_draw_box<Box, 2>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Segment, size_t Dimension>
|
||||
struct gl_draw_segment
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct gl_draw_segment<Segment, 2>
|
||||
{
|
||||
static inline void apply(Segment const& s, typename coordinate_type<Segment>::type z)
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(geometry::get<0, 0>(s), geometry::get<0, 1>(s), z);
|
||||
glVertex3f(geometry::get<1, 0>(s), geometry::get<1, 1>(s), z);
|
||||
glEnd();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable, typename Tag>
|
||||
struct gl_draw_indexable
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
|
||||
};
|
||||
|
||||
template <typename Indexable>
|
||||
struct gl_draw_indexable<Indexable, box_tag>
|
||||
{
|
||||
static const size_t dimension = geometry::dimension<Indexable>::value;
|
||||
template <typename Box>
|
||||
struct gl_draw_indexable<Box, box_tag>
|
||||
: gl_draw_box<Box, geometry::dimension<Box>::value>
|
||||
{};
|
||||
|
||||
static inline void apply(Indexable const& i, typename coordinate_type<Indexable>::type z)
|
||||
{
|
||||
gl_draw_box<Indexable, dimension>::apply(i, z);
|
||||
}
|
||||
};
|
||||
template <typename Point>
|
||||
struct gl_draw_indexable<Point, point_tag>
|
||||
: gl_draw_point<Point, geometry::dimension<Point>::value>
|
||||
{};
|
||||
|
||||
template <typename Indexable>
|
||||
struct gl_draw_indexable<Indexable, point_tag>
|
||||
{
|
||||
static const size_t dimension = geometry::dimension<Indexable>::value;
|
||||
|
||||
static inline void apply(Indexable const& i, typename coordinate_type<Indexable>::type z)
|
||||
{
|
||||
gl_draw_point<Indexable, dimension>::apply(i, z);
|
||||
}
|
||||
};
|
||||
template <typename Segment>
|
||||
struct gl_draw_indexable<Segment, segment_tag>
|
||||
: gl_draw_segment<Segment, geometry::dimension<Segment>::value>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
|
@ -66,6 +66,7 @@ struct print_corner<Box, Corner, 1>
|
||||
template <typename Indexable, typename Tag>
|
||||
struct print_indexable
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
|
||||
};
|
||||
|
||||
template <typename Indexable>
|
||||
@ -96,6 +97,21 @@ struct print_indexable<Indexable, point_tag>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indexable>
|
||||
struct print_indexable<Indexable, segment_tag>
|
||||
{
|
||||
static const size_t dimension = geometry::dimension<Indexable>::value;
|
||||
|
||||
static inline void apply(std::ostream &os, Indexable const& i)
|
||||
{
|
||||
os << '(';
|
||||
print_corner<Indexable, 0, dimension>::apply(os, i);
|
||||
os << ")-(";
|
||||
print_corner<Indexable, 1, dimension>::apply(os, i);
|
||||
os << ')';
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
template <typename Indexable> inline
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Boost.Geometry Index
|
||||
// Additional tests
|
||||
// OpenGL visualization
|
||||
|
||||
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -26,29 +26,164 @@
|
||||
#include <boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/utilities/statistics.hpp>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#define ENABLE_POINTS_AND_SEGMENTS
|
||||
|
||||
namespace bg = boost::geometry;
|
||||
namespace bgi = bg::index;
|
||||
|
||||
// used types
|
||||
|
||||
typedef bg::model::point<float, 2, boost::geometry::cs::cartesian> P;
|
||||
typedef bg::model::box<P> B;
|
||||
//bgi::rtree<B> t(2, 1);
|
||||
typedef bg::model::linestring<P> LS;
|
||||
typedef bg::model::segment<P> S;
|
||||
typedef bg::model::ring<P> R;
|
||||
typedef bg::model::polygon<P> Poly;
|
||||
typedef bg::model::multi_polygon<Poly> MPoly;
|
||||
|
||||
typedef bgi::rtree<
|
||||
B,
|
||||
bgi::rstar<4, 2>
|
||||
> RTree;
|
||||
RTree t;
|
||||
std::vector<B> vect;
|
||||
// containers variant
|
||||
|
||||
template <typename V>
|
||||
struct containers
|
||||
{
|
||||
bgi::rtree< V, bgi::rstar<4, 2> > tree;
|
||||
std::vector<V> values;
|
||||
std::vector<V> result;
|
||||
};
|
||||
|
||||
boost::variant<
|
||||
containers<B>
|
||||
#ifdef ENABLE_POINTS_AND_SEGMENTS
|
||||
, containers<P>
|
||||
, containers<S>
|
||||
#endif
|
||||
> cont;
|
||||
|
||||
// visitors
|
||||
|
||||
template <typename Pred>
|
||||
struct query_v : boost::static_visitor<size_t>
|
||||
{
|
||||
Pred m_pred;
|
||||
query_v(Pred const& pred) : m_pred(pred) {}
|
||||
|
||||
template <typename C>
|
||||
size_t operator()(C & c) const
|
||||
{
|
||||
c.result.clear();
|
||||
return c.tree.query(m_pred, std::back_inserter(c.result));
|
||||
}
|
||||
};
|
||||
template <typename Cont, typename Pred>
|
||||
inline size_t query(Cont & cont, Pred const& pred)
|
||||
{
|
||||
return boost::apply_visitor(query_v<Pred>(pred), cont);
|
||||
}
|
||||
|
||||
struct print_result_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename C>
|
||||
void operator()(C & c) const
|
||||
{
|
||||
for ( size_t i = 0 ; i < c.result.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, c.result[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void print_result(Cont const& cont)
|
||||
{
|
||||
boost::apply_visitor(print_result_v(), cont);
|
||||
}
|
||||
|
||||
struct bounds_v : boost::static_visitor<B>
|
||||
{
|
||||
template <typename C>
|
||||
B operator()(C & c) const
|
||||
{
|
||||
return c.tree.bounds();
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline B bounds(Cont const& cont)
|
||||
{
|
||||
return boost::apply_visitor(bounds_v(), cont);
|
||||
}
|
||||
|
||||
struct depth_v : boost::static_visitor<size_t>
|
||||
{
|
||||
template <typename C>
|
||||
size_t operator()(C & c) const
|
||||
{
|
||||
return get(c.tree);
|
||||
}
|
||||
template <typename RTree>
|
||||
static size_t get(RTree const& t)
|
||||
{
|
||||
return bgi::detail::rtree::utilities::view<RTree>(t).depth();
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline size_t depth(Cont const& cont)
|
||||
{
|
||||
return boost::apply_visitor(depth_v(), cont);
|
||||
}
|
||||
|
||||
struct draw_tree_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename C>
|
||||
void operator()(C & c) const
|
||||
{
|
||||
bgi::detail::rtree::utilities::gl_draw(c.tree);
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void draw_tree(Cont const& cont)
|
||||
{
|
||||
return boost::apply_visitor(draw_tree_v(), cont);
|
||||
}
|
||||
|
||||
struct draw_result_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename C>
|
||||
void operator()(C & c) const
|
||||
{
|
||||
for ( size_t i = 0 ; i < c.result.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::gl_draw_indexable(c.result[i], depth_v::get(c.tree));
|
||||
}
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void draw_result(Cont const& cont)
|
||||
{
|
||||
return boost::apply_visitor(draw_result_v(), cont);
|
||||
}
|
||||
|
||||
struct print_tree_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename C>
|
||||
void operator()(C & c) const
|
||||
{
|
||||
bgi::detail::rtree::utilities::print(std::cout, c.tree);
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void print_tree(Cont const& cont)
|
||||
{
|
||||
return boost::apply_visitor(print_tree_v(), cont);
|
||||
}
|
||||
|
||||
// globals used in querying
|
||||
|
||||
size_t found_count = 0;
|
||||
P search_point;
|
||||
size_t count = 5;
|
||||
std::vector<B> nearest_boxes;
|
||||
|
||||
P search_point;
|
||||
B search_box;
|
||||
R search_ring;
|
||||
Poly search_poly;
|
||||
@ -63,30 +198,24 @@ enum query_mode_type {
|
||||
|
||||
bool search_valid = false;
|
||||
|
||||
// various queries
|
||||
|
||||
void query_knn()
|
||||
{
|
||||
float x = ( rand() % 1000 ) / 10.0f;
|
||||
float y = ( rand() % 1000 ) / 10.0f;
|
||||
|
||||
nearest_boxes.clear();
|
||||
|
||||
if ( query_mode == qm_knn )
|
||||
{
|
||||
search_point = P(x, y);
|
||||
found_count = t.query(
|
||||
bgi::nearest(search_point, count),
|
||||
std::back_inserter(nearest_boxes)
|
||||
);
|
||||
found_count = query(cont, bgi::nearest(search_point, count));
|
||||
}
|
||||
else if ( query_mode == qm_knnb )
|
||||
{
|
||||
float w = 2 + ( rand() % 1000 ) / 500.0f;
|
||||
float h = 2 + ( rand() % 1000 ) / 500.0f;
|
||||
search_box = B(P(x - w, y - h), P(x + w, y + h));
|
||||
found_count = t.query(
|
||||
bgi::nearest(search_box, count),
|
||||
std::back_inserter(nearest_boxes)
|
||||
);
|
||||
found_count = query(cont, bgi::nearest(search_box, count));
|
||||
}
|
||||
else if ( query_mode == qm_knns )
|
||||
{
|
||||
@ -95,10 +224,7 @@ void query_knn()
|
||||
float w = (10 + ( rand() % 1000 ) / 100.0f) * signx;
|
||||
float h = (10 + ( rand() % 1000 ) / 100.0f) * signy;
|
||||
search_segment = S(P(x - w, y - h), P(x + w, y + h));
|
||||
found_count = t.query(
|
||||
bgi::nearest(search_segment, count),
|
||||
std::back_inserter(nearest_boxes)
|
||||
);
|
||||
found_count = query(cont, bgi::nearest(search_segment, count));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -107,20 +233,33 @@ void query_knn()
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
// TODO: print the correct indexable!
|
||||
std::cout << "search point: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, search_point);
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
if ( query_mode == qm_knn )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
std::cout << "search point: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, search_point);
|
||||
}
|
||||
else if ( query_mode == qm_knnb )
|
||||
{
|
||||
std::cout << "search box: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, search_box);
|
||||
}
|
||||
else if ( query_mode == qm_knns )
|
||||
{
|
||||
std::cout << "search segment: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, search_segment);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
std::cout << "\nfound: ";
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "nearest not found\n";
|
||||
}
|
||||
|
||||
#ifndef ENABLE_POINTS_AND_SEGMENTS
|
||||
void query_path()
|
||||
{
|
||||
float x = ( rand() % 1000 ) / 10.0f;
|
||||
@ -136,11 +275,7 @@ void query_path()
|
||||
search_path[2 * i + 1] = P(x+w, yy);
|
||||
}
|
||||
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(
|
||||
bgi::detail::path<LS>(search_path, count),
|
||||
std::back_inserter(nearest_boxes)
|
||||
);
|
||||
found_count = query(cont, bgi::detail::path<LS>(search_path, count));
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
@ -148,15 +283,12 @@ void query_path()
|
||||
BOOST_FOREACH(P const& p, search_path)
|
||||
bgi::detail::utilities::print_indexable(std::cout, p);
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "values on path not found\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Predicate>
|
||||
void query()
|
||||
@ -169,26 +301,20 @@ void query()
|
||||
float h = 10 + ( rand() % 1000 ) / 100.0f;
|
||||
|
||||
search_box = B(P(x - w, y - h), P(x + w, y + h));
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(Predicate(search_box), std::back_inserter(nearest_boxes) );
|
||||
}
|
||||
else
|
||||
{
|
||||
search_box = t.bounds();
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(Predicate(search_box), std::back_inserter(nearest_boxes) );
|
||||
search_box = bounds(cont);
|
||||
}
|
||||
|
||||
found_count = query(cont, Predicate(search_box));
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
std::cout << "search box: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, search_box);
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "boxes not found\n";
|
||||
@ -221,8 +347,7 @@ void query_ring()
|
||||
search_ring.push_back(P(x - w, y - h/2));
|
||||
search_ring.push_back(P(x - w, y - h));
|
||||
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(Predicate(search_ring), std::back_inserter(nearest_boxes) );
|
||||
found_count = query(cont, Predicate(search_ring));
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
@ -233,11 +358,7 @@ void query_ring()
|
||||
std::cout << ' ';
|
||||
}
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "boxes not found\n";
|
||||
@ -277,8 +398,7 @@ void query_poly()
|
||||
search_poly.inners()[0].push_back(P(x - w/2, y + h/2));
|
||||
search_poly.inners()[0].push_back(P(x - w/2, y - h/2));
|
||||
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(Predicate(search_poly), std::back_inserter(nearest_boxes) );
|
||||
found_count = query(cont, Predicate(search_poly));
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
@ -289,11 +409,7 @@ void query_poly()
|
||||
std::cout << ' ';
|
||||
}
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "boxes not found\n";
|
||||
@ -349,9 +465,8 @@ void query_multi_poly()
|
||||
search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 2*h));
|
||||
search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 6*h/5));
|
||||
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(Predicate(search_multi_poly), std::back_inserter(nearest_boxes) );
|
||||
|
||||
found_count = query(cont, Predicate(search_multi_poly));
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
std::cout << "search multi_poly[0] outer: ";
|
||||
@ -361,11 +476,7 @@ void query_multi_poly()
|
||||
std::cout << ' ';
|
||||
}
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "boxes not found\n";
|
||||
@ -386,9 +497,8 @@ void query_segment()
|
||||
boost::geometry::set<1, 0>(search_segment, x + w);
|
||||
boost::geometry::set<1, 1>(search_segment, y + h);
|
||||
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(Predicate(search_segment), std::back_inserter(nearest_boxes) );
|
||||
|
||||
found_count = query(cont, Predicate(search_segment));
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
std::cout << "search segment: ";
|
||||
@ -396,11 +506,7 @@ void query_segment()
|
||||
bgi::detail::utilities::print_indexable(std::cout, P(x+w, y+h));
|
||||
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "boxes not found\n";
|
||||
@ -424,9 +530,8 @@ void query_linestring()
|
||||
search_linestring.push_back(P(xx, yy));
|
||||
}
|
||||
|
||||
nearest_boxes.clear();
|
||||
found_count = t.query(Predicate(search_linestring), std::back_inserter(nearest_boxes) );
|
||||
|
||||
found_count = query(cont, Predicate(search_linestring));
|
||||
|
||||
if ( found_count > 0 )
|
||||
{
|
||||
std::cout << "search linestring: ";
|
||||
@ -436,44 +541,46 @@ void query_linestring()
|
||||
std::cout << ' ';
|
||||
}
|
||||
std::cout << "\nfound: ";
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
{
|
||||
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
print_result(cont);
|
||||
}
|
||||
else
|
||||
std::cout << "boxes not found\n";
|
||||
}
|
||||
|
||||
// the function running the correct query based on the query_mode
|
||||
|
||||
void search()
|
||||
{
|
||||
namespace d = bgi::detail;
|
||||
|
||||
if ( query_mode == qm_knn || query_mode == qm_knnb || query_mode == qm_knns )
|
||||
query_knn();
|
||||
else if ( query_mode == qm_c )
|
||||
query< d::spatial_predicate<B, d::covered_by_tag, false> >();
|
||||
else if ( query_mode == qm_d )
|
||||
query< d::spatial_predicate<B, d::disjoint_tag, false> >();
|
||||
else if ( query_mode == qm_i )
|
||||
query< d::spatial_predicate<B, d::intersects_tag, false> >();
|
||||
else if ( query_mode == qm_nd )
|
||||
query< d::spatial_predicate<B, d::disjoint_tag, true> >();
|
||||
else if ( query_mode == qm_ni )
|
||||
query< d::spatial_predicate<B, d::intersects_tag, true> >();
|
||||
else if ( query_mode == qm_all )
|
||||
query< d::spatial_predicate<B, d::intersects_tag, false> >();
|
||||
#ifdef ENABLE_POINTS_AND_SEGMENTS
|
||||
else
|
||||
std::cout << "query disabled\n";
|
||||
#else
|
||||
else if ( query_mode == qm_c )
|
||||
query< d::spatial_predicate<B, d::covered_by_tag, false> >();
|
||||
else if ( query_mode == qm_o )
|
||||
query< d::spatial_predicate<B, d::overlaps_tag, false> >();
|
||||
else if ( query_mode == qm_w )
|
||||
query< d::spatial_predicate<B, d::within_tag, false> >();
|
||||
else if ( query_mode == qm_nc )
|
||||
query< d::spatial_predicate<B, d::covered_by_tag, true> >();
|
||||
else if ( query_mode == qm_nd )
|
||||
query< d::spatial_predicate<B, d::disjoint_tag, true> >();
|
||||
else if ( query_mode == qm_ni )
|
||||
query< d::spatial_predicate<B, d::intersects_tag, true> >();
|
||||
else if ( query_mode == qm_no )
|
||||
query< d::spatial_predicate<B, d::overlaps_tag, true> >();
|
||||
else if ( query_mode == qm_nw )
|
||||
query< d::spatial_predicate<B, d::within_tag, true> >();
|
||||
else if ( query_mode == qm_all )
|
||||
query< d::spatial_predicate<B, d::intersects_tag, false> >();
|
||||
else if ( query_mode == qm_ri )
|
||||
query_ring< d::spatial_predicate<R, d::intersects_tag, false> >();
|
||||
else if ( query_mode == qm_pi )
|
||||
@ -486,15 +593,18 @@ void search()
|
||||
query_linestring< d::spatial_predicate<LS, d::intersects_tag, false> >();
|
||||
else if ( query_mode == qm_path )
|
||||
query_path();
|
||||
#endif
|
||||
|
||||
search_valid = true;
|
||||
}
|
||||
|
||||
// various drawing functions
|
||||
|
||||
void draw_point(P const& p)
|
||||
{
|
||||
float x = boost::geometry::get<0>(p);
|
||||
float y = boost::geometry::get<1>(p);
|
||||
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
|
||||
float z = depth(cont);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(x+1, y, z);
|
||||
@ -508,7 +618,7 @@ void draw_knn_area(float min_distance, float max_distance)
|
||||
{
|
||||
float x = boost::geometry::get<0>(search_point);
|
||||
float y = boost::geometry::get<1>(search_point);
|
||||
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
|
||||
float z = depth(cont);
|
||||
|
||||
draw_point(search_point);
|
||||
|
||||
@ -535,7 +645,7 @@ void draw_linestring(LS const& ls)
|
||||
{
|
||||
float x = boost::geometry::get<0>(p);
|
||||
float y = boost::geometry::get<1>(p);
|
||||
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
|
||||
float z = depth(cont);
|
||||
glVertex3f(x, y, z);
|
||||
}
|
||||
|
||||
@ -548,7 +658,7 @@ void draw_segment(S const& s)
|
||||
float y1 = boost::geometry::get<0, 1>(s);
|
||||
float x2 = boost::geometry::get<1, 0>(s);
|
||||
float y2 = boost::geometry::get<1, 1>(s);
|
||||
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
|
||||
float z = depth(cont);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(x1, y1, z);
|
||||
@ -563,7 +673,7 @@ void draw_box(Box const& box)
|
||||
float y1 = boost::geometry::get<bg::min_corner, 1>(box);
|
||||
float x2 = boost::geometry::get<bg::max_corner, 0>(box);
|
||||
float y2 = boost::geometry::get<bg::max_corner, 1>(box);
|
||||
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
|
||||
float z = depth(cont);
|
||||
|
||||
// search box
|
||||
glBegin(GL_LINE_LOOP);
|
||||
@ -577,7 +687,7 @@ void draw_box(Box const& box)
|
||||
template <typename Range>
|
||||
void draw_ring(Range const& range)
|
||||
{
|
||||
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
|
||||
float z = depth(cont);
|
||||
|
||||
// search box
|
||||
glBegin(GL_LINE_LOOP);
|
||||
@ -607,11 +717,13 @@ void draw_multi_polygon(MultiPolygon const& multi_polygon)
|
||||
draw_polygon(p);
|
||||
}
|
||||
|
||||
// render the scene -> tree, if searching data available also the query geometry and result
|
||||
|
||||
void render_scene(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
bgi::detail::rtree::utilities::gl_draw(t);
|
||||
draw_tree(cont);
|
||||
|
||||
if ( search_valid )
|
||||
{
|
||||
@ -640,10 +752,7 @@ void render_scene(void)
|
||||
|
||||
glColor3f(1.0f, 0.5f, 0.0f);
|
||||
|
||||
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
|
||||
bgi::detail::utilities::gl_draw_indexable(
|
||||
nearest_boxes[i],
|
||||
bgi::detail::rtree::utilities::view<RTree>(t).depth());
|
||||
draw_result(cont);
|
||||
}
|
||||
|
||||
glFlush();
|
||||
@ -680,49 +789,100 @@ void resize(int w, int h)
|
||||
srand(1);
|
||||
}
|
||||
|
||||
// randomize various indexables
|
||||
|
||||
inline void rand_val(B & b)
|
||||
{
|
||||
float x = ( rand() % 100 );
|
||||
float y = ( rand() % 100 );
|
||||
float w = ( rand() % 2 ) + 1;
|
||||
float h = ( rand() % 2 ) + 1;
|
||||
b = B(P(x - w, y - h),P(x + w, y + h));
|
||||
}
|
||||
inline void rand_val(P & p)
|
||||
{
|
||||
float x = ( rand() % 100 );
|
||||
float y = ( rand() % 100 );
|
||||
p = P(x, y);
|
||||
}
|
||||
inline void rand_val(S & s)
|
||||
{
|
||||
float x = ( rand() % 100 );
|
||||
float y = ( rand() % 100 );
|
||||
float w = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
|
||||
float h = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
|
||||
s = S(P(x - w, y - h),P(x + w, y + h));
|
||||
}
|
||||
|
||||
// more higher-level visitors
|
||||
|
||||
struct insert_random_value_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename V>
|
||||
void operator()(containers<V> & c) const
|
||||
{
|
||||
V v;
|
||||
rand_val(v);
|
||||
|
||||
boost::geometry::index::insert(c.tree, v);
|
||||
c.values.push_back(v);
|
||||
|
||||
std::cout << "inserted: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, v);
|
||||
std::cout << '\n';
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void insert_random_value(Cont & cont)
|
||||
{
|
||||
return boost::apply_visitor(insert_random_value_v(), cont);
|
||||
}
|
||||
|
||||
struct remove_random_value_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename V>
|
||||
void operator()(containers<V> & c) const
|
||||
{
|
||||
if ( c.values.empty() )
|
||||
return;
|
||||
|
||||
size_t i = rand() % c.values.size();
|
||||
V v = c.values[i];
|
||||
|
||||
c.tree.remove(v);
|
||||
c.values.erase(c.values.begin() + i);
|
||||
|
||||
std::cout << "removed: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, v);
|
||||
std::cout << '\n';
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void remove_random_value(Cont & cont)
|
||||
{
|
||||
return boost::apply_visitor(remove_random_value_v(), cont);
|
||||
}
|
||||
|
||||
// handle mouse input
|
||||
|
||||
void mouse(int button, int state, int /*x*/, int /*y*/)
|
||||
{
|
||||
if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
|
||||
{
|
||||
float x = ( rand() % 100 );
|
||||
float y = ( rand() % 100 );
|
||||
float w = ( rand() % 2 ) + 1;
|
||||
float h = ( rand() % 2 ) + 1;
|
||||
|
||||
B b(P(x - w, y - h),P(x + w, y + h));
|
||||
|
||||
boost::geometry::index::insert(t, b);
|
||||
vect.push_back(b);
|
||||
|
||||
std::cout << "inserted: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, b);
|
||||
std::cout << '\n';
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
|
||||
insert_random_value(cont);
|
||||
search_valid = false;
|
||||
}
|
||||
else if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
|
||||
{
|
||||
if ( vect.empty() )
|
||||
return;
|
||||
|
||||
size_t i = rand() % vect.size();
|
||||
B b = vect[i];
|
||||
|
||||
bgi::remove(t, b);
|
||||
vect.erase(vect.begin() + i);
|
||||
|
||||
std::cout << "removed: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, b);
|
||||
std::cout << '\n';
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
|
||||
remove_random_value(cont);
|
||||
search_valid = false;
|
||||
}
|
||||
else if ( button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN )
|
||||
@ -733,71 +893,117 @@ void mouse(int button, int state, int /*x*/, int /*y*/)
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
// more higher-level visitors
|
||||
|
||||
struct insert_random_values_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename V>
|
||||
void operator()(containers<V> & c) const
|
||||
{
|
||||
for ( size_t i = 0 ; i < 35 ; ++i )
|
||||
{
|
||||
V v;
|
||||
rand_val(v);
|
||||
|
||||
c.tree.insert(v);
|
||||
c.values.push_back(v);
|
||||
|
||||
std::cout << "inserted: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, v);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void insert_random_values(Cont & cont)
|
||||
{
|
||||
return boost::apply_visitor(insert_random_values_v(), cont);
|
||||
}
|
||||
|
||||
struct bulk_insert_random_values_v : boost::static_visitor<>
|
||||
{
|
||||
template <typename V>
|
||||
void operator()(containers<V> & c) const
|
||||
{
|
||||
c.values.clear();
|
||||
|
||||
for ( size_t i = 0 ; i < 35 ; ++i )
|
||||
{
|
||||
V v;
|
||||
rand_val(v);
|
||||
|
||||
c.values.push_back(v);
|
||||
|
||||
std::cout << "inserted: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, v);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
create(c.tree, c.values);
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
template <typename Tree, typename Values>
|
||||
void create(Tree & tree, Values const& values) const
|
||||
{
|
||||
Tree t(values);
|
||||
tree = boost::move(t);
|
||||
}
|
||||
};
|
||||
template <typename Cont>
|
||||
inline void bulk_insert_random_values(Cont & cont)
|
||||
{
|
||||
return boost::apply_visitor(bulk_insert_random_values_v(), cont);
|
||||
}
|
||||
|
||||
// handle keyboard input
|
||||
|
||||
std::string current_line;
|
||||
|
||||
void keyboard(unsigned char key, int /*x*/, int /*y*/)
|
||||
{
|
||||
if ( key == '\r' || key == '\n' )
|
||||
{
|
||||
if ( current_line == "t" )
|
||||
if ( current_line == "storeb" )
|
||||
{
|
||||
cont = containers<B>();
|
||||
glutPostRedisplay();
|
||||
}
|
||||
#ifdef ENABLE_POINTS_AND_SEGMENTS
|
||||
else if ( current_line == "storep" )
|
||||
{
|
||||
cont = containers<P>();
|
||||
glutPostRedisplay();
|
||||
}
|
||||
else if ( current_line == "stores" )
|
||||
{
|
||||
cont = containers<S>();
|
||||
glutPostRedisplay();
|
||||
}
|
||||
#endif
|
||||
else if ( current_line == "t" )
|
||||
{
|
||||
std::cout << "\n";
|
||||
bgi::detail::rtree::utilities::print(std::cout, t);
|
||||
print_tree(cont);
|
||||
std::cout << "\n";
|
||||
}
|
||||
else if ( current_line == "rand" )
|
||||
{
|
||||
for ( size_t i = 0 ; i < 35 ; ++i )
|
||||
{
|
||||
float x = ( rand() % 100 );
|
||||
float y = ( rand() % 100 );
|
||||
float w = ( rand() % 2 ) + 1;
|
||||
float h = ( rand() % 2 ) + 1;
|
||||
|
||||
B b(P(x - w, y - h),P(x + w, y + h));
|
||||
|
||||
boost::geometry::index::insert(t, b);
|
||||
vect.push_back(b);
|
||||
|
||||
std::cout << "inserted: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, b);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
|
||||
insert_random_values(cont);
|
||||
search_valid = false;
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
else if ( current_line == "bulk" )
|
||||
{
|
||||
vect.clear();
|
||||
|
||||
for ( size_t i = 0 ; i < 35 ; ++i )
|
||||
{
|
||||
float x = ( rand() % 100 );
|
||||
float y = ( rand() % 100 );
|
||||
float w = ( rand() % 2 ) + 1;
|
||||
float h = ( rand() % 2 ) + 1;
|
||||
|
||||
B b(P(x - w, y - h),P(x + w, y + h));
|
||||
vect.push_back(b);
|
||||
|
||||
std::cout << "inserted: ";
|
||||
bgi::detail::utilities::print_indexable(std::cout, b);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
RTree t2(vect);
|
||||
t = boost::move(t2);
|
||||
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
|
||||
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
|
||||
std::cout << "\n";
|
||||
|
||||
bulk_insert_random_values(cont);
|
||||
search_valid = false;
|
||||
|
||||
glutPostRedisplay();
|
||||
@ -859,6 +1065,8 @@ void keyboard(unsigned char key, int /*x*/, int /*y*/)
|
||||
}
|
||||
}
|
||||
|
||||
// main function
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
glutInit(&argc, argv);
|
||||
|
Loading…
x
Reference in New Issue
Block a user