diff options
Diffstat (limited to 'src/boost/libs/geometry/index/example')
-rw-r--r-- | src/boost/libs/geometry/index/example/3d_benchmark.cpp | 161 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/Jamfile.v2 | 55 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/benchmark.cpp | 158 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/benchmark2.cpp | 86 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/benchmark3.cpp | 99 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/benchmark_experimental.cpp | 482 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/benchmark_insert.cpp | 196 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/glut_vis.cpp | 1094 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/random_test.cpp | 185 | ||||
-rw-r--r-- | src/boost/libs/geometry/index/example/serialize.cpp | 168 |
10 files changed, 2684 insertions, 0 deletions
diff --git a/src/boost/libs/geometry/index/example/3d_benchmark.cpp b/src/boost/libs/geometry/index/example/3d_benchmark.cpp new file mode 100644 index 00000000..25181768 --- /dev/null +++ b/src/boost/libs/geometry/index/example/3d_benchmark.cpp @@ -0,0 +1,161 @@ +// Boost.Geometry Index +// Additional tests + +// Copyright (c) 2011-2013 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> +#include <boost/geometry/index/rtree.hpp> + +#include <boost/chrono.hpp> +#include <boost/foreach.hpp> +#include <boost/random.hpp> + +int main() +{ + namespace bg = boost::geometry; + namespace bgi = bg::index; + typedef boost::chrono::thread_clock clock_t; + typedef boost::chrono::duration<float> dur_t; + + size_t values_count = 500000; + size_t queries_count = 200000; + + std::vector< boost::tuple<float, float, float> > coords; + + //randomize values + { + boost::mt19937 rng; + //rng.seed(static_cast<unsigned int>(std::time(0))); + float max_val = static_cast<float>(values_count / 2); + boost::uniform_real<float> range(-max_val, max_val); + boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range); + + coords.reserve(values_count); + + std::cout << "randomizing data\n"; + for ( size_t i = 0 ; i < values_count ; ++i ) + { + coords.push_back(boost::make_tuple(rnd(), rnd(), rnd())); + } + std::cout << "randomized\n"; + } + + typedef bg::model::point<float, 3, bg::cs::cartesian> P; + typedef bg::model::box<P> B; + //typedef bgi::rtree<B, bgi::linear<32, 8> > RT; + //typedef bgi::rtree<B, bgi::quadratic<32, 8> > RT; + typedef bgi::rtree<B, bgi::rstar<8, 3> > RT; + + std::cout << "sizeof rtree: " << sizeof(RT) << std::endl; + + for (;;) + { + RT t; + + // inserting test + { + clock_t::time_point start = clock_t::now(); + for (size_t i = 0 ; i < values_count ; ++i ) + { + float x = boost::get<0>(coords[i]); + float y = boost::get<1>(coords[i]); + float z = boost::get<2>(coords[i]); + B b(P(x - 0.5f, y - 0.5f, z - 0.5f), P(x + 0.5f, y + 0.5f, z + 0.5f)); + + t.insert(b); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - insert " << values_count << '\n'; + } + + std::vector<B> result; + result.reserve(100); + B result_one; + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = boost::get<0>(coords[i]); + float y = boost::get<1>(coords[i]); + float z = boost::get<2>(coords[i]); + result.clear(); + t.query(bgi::intersects(B(P(x - 10, y - 10, z - 10), P(x + 10, y + 10, z + 10))), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(B) " << queries_count << " found " << temp << '\n'; + } + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count / 2 ; ++i ) + { + float x1 = boost::get<0>(coords[i]); + float y1 = boost::get<1>(coords[i]); + float z1 = boost::get<2>(coords[i]); + float x2 = boost::get<0>(coords[i+1]); + float y2 = boost::get<1>(coords[i+1]); + float z2 = boost::get<2>(coords[i+1]); + float x3 = boost::get<0>(coords[i+2]); + float y3 = boost::get<1>(coords[i+2]); + float z3 = boost::get<2>(coords[i+2]); + result.clear(); + t.query( + bgi::intersects(B(P(x1 - 10, y1 - 10, z1 - 10), P(x1 + 10, y1 + 10, z1 + 10))) + && + !bgi::within(B(P(x2 - 10, y2 - 10, z2 - 10), P(x2 + 10, y2 + 10, z2 + 10))) + && + !bgi::overlaps(B(P(x3 - 10, y3 - 10, z3 - 10), P(x3 + 10, y3 + 10, z3 + 10))) + , + std::back_inserter(result) + ); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(i && !w && !o) " << queries_count << " found " << temp << '\n'; + } + + result.clear(); + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count / 10 ; ++i ) + { + float x = boost::get<0>(coords[i]) - 100; + float y = boost::get<1>(coords[i]) - 100; + float z = boost::get<2>(coords[i]) - 100; + result.clear(); + temp += t.query(bgi::nearest(P(x, y, z), 5), std::back_inserter(result)); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(nearest(P, 5)) " << (queries_count / 10) << " found " << temp << '\n'; + } + + { + clock_t::time_point start = clock_t::now(); + for (size_t i = 0 ; i < values_count / 10 ; ++i ) + { + float x = boost::get<0>(coords[i]); + float y = boost::get<1>(coords[i]); + float z = boost::get<2>(coords[i]); + B b(P(x - 0.5f, y - 0.5f, z - 0.5f), P(x + 0.5f, y + 0.5f, z + 0.5f)); + + t.remove(b); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - remove " << values_count / 10 << '\n'; + } + + std::cout << "------------------------------------------------\n"; + } + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/Jamfile.v2 b/src/boost/libs/geometry/index/example/Jamfile.v2 new file mode 100644 index 00000000..5cfa81a0 --- /dev/null +++ b/src/boost/libs/geometry/index/example/Jamfile.v2 @@ -0,0 +1,55 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# Copyright (c) 2013 Mateusz Loskot, London, UK. +# +# Use, modification and distribution is subject to the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Usage: +# Build as optimised for proper benchmarking: +# b2 variant=release threading=multi +# b2 variant=release threading=multi link=static runtime-link=static +# +# Set GLUT_ROOT to installation prefix of GLUT or, for Windows, +# it may be all-in-one directory with GLUT header and binaries. + +import os ; + +project boost-geometry-index-example + : requirements + <implicit-dependency>/boost//headers + ; + +local GLUT_ROOT = [ os.environ GLUT_ROOT ] ; +if $(GLUT_ROOT) +{ + local glut_name = glut ; + if [ os.name ] = NT + { + glut_name = glut32 ; + } + + lib glut + : + : + <name>$(glut_name) + <search>$(GLUT_ROOT) + <search>$(GLUT_ROOT)/lib + : + : + <include>$(GLUT_ROOT) + <include>$(GLUT_ROOT)/include + ; +} + +exe random_test : random_test.cpp ; +link serialize.cpp /boost//serialization : ; +link benchmark.cpp /boost//chrono : <threading>multi ; +link benchmark2.cpp /boost//chrono : <threading>multi ; +link benchmark3.cpp /boost//chrono : <threading>multi ; +link benchmark_experimental.cpp /boost//chrono : <threading>multi ; +if $(GLUT_ROOT) +{ + link glut_vis.cpp glut ; +} diff --git a/src/boost/libs/geometry/index/example/benchmark.cpp b/src/boost/libs/geometry/index/example/benchmark.cpp new file mode 100644 index 00000000..ba2a1dec --- /dev/null +++ b/src/boost/libs/geometry/index/example/benchmark.cpp @@ -0,0 +1,158 @@ +// Boost.Geometry Index +// Additional tests + +// Copyright (c) 2011-2013 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> + +#include <boost/chrono.hpp> +#include <boost/foreach.hpp> +#include <boost/random.hpp> + +int main() +{ + namespace bg = boost::geometry; + namespace bgi = bg::index; + typedef boost::chrono::thread_clock clock_t; + typedef boost::chrono::duration<float> dur_t; + + size_t values_count = 1000000; + size_t queries_count = 100000; + size_t nearest_queries_count = 10000; + unsigned neighbours_count = 10; + + std::vector< std::pair<float, float> > coords; + + //randomize values + { + boost::mt19937 rng; + //rng.seed(static_cast<unsigned int>(std::time(0))); + float max_val = static_cast<float>(values_count / 2); + boost::uniform_real<float> range(-max_val, max_val); + boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range); + + coords.reserve(values_count); + + std::cout << "randomizing data\n"; + for ( size_t i = 0 ; i < values_count ; ++i ) + { + coords.push_back(std::make_pair(rnd(), rnd())); + } + std::cout << "randomized\n"; + } + + typedef bg::model::point<double, 2, bg::cs::cartesian> P; + typedef bg::model::box<P> B; + typedef bgi::rtree<B, bgi::linear<16, 4> > RT; + //typedef bgi::rtree<B, bgi::quadratic<8, 3> > RT; + //typedef bgi::rtree<B, bgi::rstar<8, 3> > RT; + + std::cout << "sizeof rtree: " << sizeof(RT) << std::endl; + + for (;;) + { + RT t; + + // inserting test + { + clock_t::time_point start = clock_t::now(); + for (size_t i = 0 ; i < values_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); + + t.insert(b); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - insert " << values_count << '\n'; + } + + std::vector<B> result; + result.reserve(100); + B result_one; + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + t.query(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(B) " << queries_count << " found " << temp << '\n'; + } + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count / 2 ; ++i ) + { + float x1 = coords[i].first; + float y1 = coords[i].second; + float x2 = coords[i+1].first; + float y2 = coords[i+1].second; + float x3 = coords[i+2].first; + float y3 = coords[i+2].second; + result.clear(); + t.query( + bgi::intersects(B(P(x1 - 10, y1 - 10), P(x1 + 10, y1 + 10))) + && + !bgi::within(B(P(x2 - 10, y2 - 10), P(x2 + 10, y2 + 10))) + && + !bgi::overlaps(B(P(x3 - 10, y3 - 10), P(x3 + 10, y3 + 10))) + , + std::back_inserter(result) + ); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(i && !w && !o) " << queries_count << " found " << temp << '\n'; + } + + result.clear(); + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) + { + float x = coords[i].first + 100; + float y = coords[i].second + 100; + result.clear(); + temp += t.query(bgi::nearest(P(x, y), neighbours_count), std::back_inserter(result)); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(nearest(P, " << neighbours_count << ")) " << nearest_queries_count << " found " << temp << '\n'; + } + + { + clock_t::time_point start = clock_t::now(); + for (size_t i = 0 ; i < values_count / 10 ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); + + t.remove(b); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - remove " << values_count / 10 << '\n'; + } + + std::cout << "------------------------------------------------\n"; + } + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/benchmark2.cpp b/src/boost/libs/geometry/index/example/benchmark2.cpp new file mode 100644 index 00000000..48194cbd --- /dev/null +++ b/src/boost/libs/geometry/index/example/benchmark2.cpp @@ -0,0 +1,86 @@ +// Boost.Geometry Index +// Compare performance with std::set using 1-dimensional object +// (i.e. angle, or number line coordiante) + +// Copyright (c) 2011-2013 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> + +#include <boost/chrono.hpp> +#include <boost/foreach.hpp> +#include <boost/random.hpp> +#include <set> + +int main() +{ + namespace bg = boost::geometry; + namespace bgi = bg::index; + typedef boost::chrono::thread_clock clock_t; + typedef boost::chrono::duration<float> dur_t; + + size_t values_count = 1001; + size_t count_start = 10; + size_t count_stop = 1000; + size_t count_step = 10; + size_t insrem_count = 3000000; + + typedef bg::model::point<float, 1, bg::cs::cartesian> P; + //typedef bgi::rtree<P, bgi::linear<8, 3> > RT; + typedef bgi::rtree<P, bgi::quadratic<8, 3> > RT; + //typedef bgi::rtree<P, bgi::rstar<8, 3> > RT; + + RT t; + std::set<float> s; + size_t val_i = 0; + for ( size_t curr_count = count_start ; curr_count < count_stop ; curr_count += count_step ) + { + // inserting test + { + for (; val_i < curr_count ; ++val_i ) + { + float v = val_i / 100.0f; + P p(v); + t.insert(p); + s.insert(v); + } + + float v = (val_i+1) / 100.0f; + P test_p(v); + + std::cout << t.size() << ' '; + + clock_t::time_point start = clock_t::now(); + + for (size_t i = 0 ; i < insrem_count ; ++i ) + { + t.insert(test_p); + t.remove(test_p); + } + + dur_t time = clock_t::now() - start; + std::cout << time.count() << ' '; + + start = clock_t::now(); + + for (size_t i = 0 ; i < insrem_count ; ++i ) + { + s.insert(v); + s.erase(v); + } + + time = clock_t::now() - start; + std::cout << time.count() << ' '; + } + + std::cout << '\n'; + } + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/benchmark3.cpp b/src/boost/libs/geometry/index/example/benchmark3.cpp new file mode 100644 index 00000000..ad1910e4 --- /dev/null +++ b/src/boost/libs/geometry/index/example/benchmark3.cpp @@ -0,0 +1,99 @@ +// Boost.Geometry Index +// Additional tests + +// Copyright (c) 2011-2013 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> + +#include <boost/chrono.hpp> +#include <boost/foreach.hpp> +#include <boost/random.hpp> +#include <set> + +int main() +{ + namespace bg = boost::geometry; + namespace bgi = bg::index; + typedef boost::chrono::thread_clock clock_t; + typedef boost::chrono::duration<float> dur_t; + + size_t stored_count = 100000; + + std::vector< std::pair<float, float> > coords; + + //randomize values + { + boost::mt19937 rng; + //rng.seed(static_cast<unsigned int>(std::time(0))); + float max_val = static_cast<float>(stored_count / 10); + boost::uniform_real<float> range(-max_val, max_val); + boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range); + + coords.reserve(stored_count); + + std::cout << "randomizing data\n"; + for ( size_t i = 0 ; i < stored_count ; ++i ) + { + coords.push_back(std::make_pair(rnd(), rnd())); + } + std::cout << "randomized\n"; + } + + typedef bg::model::point<float, 2, bg::cs::cartesian> P; + typedef bgi::rtree<P, bgi::dynamic_linear > RTL; + typedef bgi::rtree<P, bgi::dynamic_quadratic > RTQ; + typedef bgi::rtree<P, bgi::dynamic_rstar > RTR; + + for ( size_t m = 4 ; m < 33 ; m += 2 ) + { + size_t mm = ::ceil(m / 3.0f); + + RTL rtl(bgi::dynamic_linear(m, mm)); + RTQ rtq(bgi::dynamic_quadratic(m, mm)); + RTR rtr(bgi::dynamic_rstar(m, mm)); + + std::cout << m << ' ' << mm << ' '; + + // inserting test + { + clock_t::time_point start = clock_t::now(); + for (size_t i = 0 ; i < stored_count ; ++i ) + { + P p(coords[i].first, coords[i].second); + rtl.insert(p); + } + dur_t time = clock_t::now() - start; + std::cout << time.count() << ' '; + + start = clock_t::now(); + for (size_t i = 0 ; i < stored_count ; ++i ) + { + P p(coords[i].first, coords[i].second); + rtq.insert(p); + } + time = clock_t::now() - start; + std::cout << time.count() << ' '; + + start = clock_t::now(); + for (size_t i = 0 ; i < stored_count ; ++i ) + { + float v = i / 100.0f; + P p(coords[i].first, coords[i].second); + rtr.insert(p); + } + time = clock_t::now() - start; + std::cout << time.count() << ' '; + } + + std::cout << '\n'; + } + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/benchmark_experimental.cpp b/src/boost/libs/geometry/index/example/benchmark_experimental.cpp new file mode 100644 index 00000000..6556d766 --- /dev/null +++ b/src/boost/libs/geometry/index/example/benchmark_experimental.cpp @@ -0,0 +1,482 @@ +// Boost.Geometry Index +// Additional tests + +// Copyright (c) 2011-2015 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + +#include <iostream> + +#include <boost/chrono.hpp> +#include <boost/foreach.hpp> +#include <boost/random.hpp> +#include <boost/range/algorithm/copy.hpp> + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> +#include <boost/geometry/geometries/linestring.hpp> +#include <boost/geometry/geometries/segment.hpp> + +#include <boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp> +#include <boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp> + +namespace bg = boost::geometry; +namespace bgi = bg::index; + +typedef bg::model::point<double, 2, bg::cs::cartesian> P; +typedef bg::model::box<P> B; +typedef bg::model::linestring<P> LS; +typedef bg::model::segment<P> S; +//typedef P V; +typedef B V; +//typedef S V; +//#define SEGMENT_INDEXABLE + +template <typename V> +struct generate_value {}; + +template <> +struct generate_value<B> +{ + static inline B apply(float x, float y) { return B(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); } +}; + +template <> +struct generate_value<S> +{ + static inline S apply(float x, float y) { return S(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); } +}; + +template <> +struct generate_value<P> +{ + static inline P apply(float x, float y) { return P(x, y); } +}; + +//#include <boost/geometry/extensions/nsphere/nsphere.hpp> +//typedef bg::model::nsphere<P, double> NS; +//typedef NS V; +// +//template <> +//struct generate_value<NS> +//{ +// static inline NS apply(float x, float y) { return NS(P(x, y), 0.5); } +//}; + +template <typename I1, typename I2, typename O> +void mycopy(I1 first, I2 last, O o) +{ + for ( ; first != last ; ++o, ++first ) + *o = *first; +} + +//#define BOOST_GEOMETRY_INDEX_BENCHMARK_DEBUG + +int main() +{ + typedef boost::chrono::thread_clock clock_t; + typedef boost::chrono::duration<float> dur_t; + +#ifndef BOOST_GEOMETRY_INDEX_BENCHMARK_DEBUG + size_t values_count = 1000000; + size_t queries_count = 100000; + size_t nearest_queries_count = 20000; + unsigned neighbours_count = 10; + size_t path_queries_count = 2000; + size_t path_queries_count2 = 20000; + unsigned path_values_count = 10; +#else + size_t values_count = 1000; + size_t queries_count = 1; + size_t nearest_queries_count = 1; + unsigned neighbours_count = 10; + size_t path_queries_count = 1; + size_t path_queries_count2 = 1; + unsigned path_values_count = 10; +#endif + + float max_val = static_cast<float>(values_count / 2); + std::vector< std::pair<float, float> > coords; + std::vector<V> values; + + //randomize values + { + boost::mt19937 rng; + //rng.seed(static_cast<unsigned int>(std::time(0))); + boost::uniform_real<float> range(-max_val, max_val); + boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range); + + coords.reserve(values_count); + + std::cout << "randomizing data\n"; + for ( size_t i = 0 ; i < values_count ; ++i ) + { + float x = rnd(); + float y = rnd(); + coords.push_back(std::make_pair(x, y)); + values.push_back(generate_value<V>::apply(x, y)); + } + std::cout << "randomized\n"; + } + + typedef bgi::rtree<V, bgi::linear<16, 4> > RT; + //typedef bgi::rtree<V, bgi::quadratic<16, 4> > RT; + //typedef bgi::rtree<V, bgi::rstar<16, 4> > RT; + + std::cout << "sizeof rtree: " << sizeof(RT) << std::endl; + + for (;;) + { + std::vector<V> result; + result.reserve(100); + B result_one; + + // packing test + { + clock_t::time_point start = clock_t::now(); + + RT t(values.begin(), values.end()); + + dur_t time = clock_t::now() - start; + std::cout << time << " - pack " << values_count /*<< '\n'*/; + + std::cout << (bgi::detail::rtree::utilities::are_levels_ok(t) ? " ok" : " NOK") + << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " ok\n" : "NOK\n"); + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + t.query(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(B) " << queries_count << " found " << temp << '\n'; + } + } + + RT t; + + // inserting test + { + clock_t::time_point start = clock_t::now(); + t.insert(values); + dur_t time = clock_t::now() - start; + std::cout << time << " - insert " << values_count /*<< '\n'*/; + + std::cout << (bgi::detail::rtree::utilities::are_levels_ok(t) ? " ok" : " NOK") + << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " ok\n" : "NOK\n"); + } + + + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + t.query(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(B) " << queries_count << " found " << temp << '\n'; + } + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + boost::copy(t | bgi::adaptors::queried(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))), + std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - range queried(B) " << queries_count << " found " << temp << '\n'; + } + +#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + std::copy( + t.qbegin_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))), + t.qend_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))), + std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - qbegin(B) qend(B) " << queries_count << " found " << temp << '\n'; + } + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + mycopy( + t.qbegin_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))), + t.qend_(), + std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - qbegin(B) qend() " << queries_count << " found " << temp << '\n'; + } + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + boost::copy( + std::make_pair( + t.qbegin_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))), + t.qend_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))) + ), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - range qbegin(B) qend(B)" << queries_count << " found " << temp << '\n'; + } +#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + RT::const_query_iterator first = t.qbegin(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))); + RT::const_query_iterator last = t.qend(); + std::copy(first, last, std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - type-erased qbegin(B) qend() " << queries_count << " found " << temp << '\n'; + } + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + RT::const_query_iterator first = t.qbegin(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))); + RT::const_query_iterator last = t.qend(); + boost::copy(std::make_pair(first, last), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - range type-erased qbegin(B) qend() " << queries_count << " found " << temp << '\n'; + } + +#ifndef SEGMENT_INDEXABLE + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count / 2 ; ++i ) + { + float x1 = coords[i].first; + float y1 = coords[i].second; + float x2 = coords[i+1].first; + float y2 = coords[i+1].second; + float x3 = coords[i+2].first; + float y3 = coords[i+2].second; + result.clear(); + t.query( + bgi::intersects(B(P(x1 - 10, y1 - 10), P(x1 + 10, y1 + 10))) + && + !bgi::within(B(P(x2 - 10, y2 - 10), P(x2 + 10, y2 + 10))) + && + !bgi::covered_by(B(P(x3 - 10, y3 - 10), P(x3 + 10, y3 + 10))) + , + std::back_inserter(result) + ); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(i && !w && !c) " << queries_count << " found " << temp << '\n'; + } +#endif + + result.clear(); + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) + { + float x = coords[i].first + 100; + float y = coords[i].second + 100; + result.clear(); + temp += t.query(bgi::nearest(P(x, y), neighbours_count), std::back_inserter(result)); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(nearest(P, " << neighbours_count << ")) " << nearest_queries_count << " found " << temp << '\n'; + } + +#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) + { + float x = coords[i].first + 100; + float y = coords[i].second + 100; + result.clear(); + std::copy( + t.qbegin_(bgi::nearest(P(x, y), neighbours_count)), + t.qend_(bgi::nearest(P(x, y), neighbours_count)), + std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - qbegin(nearest(P, " << neighbours_count << ")) qend(n) " << nearest_queries_count << " found " << temp << '\n'; + } + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) + { + float x = coords[i].first + 100; + float y = coords[i].second + 100; + result.clear(); + mycopy( + t.qbegin_(bgi::nearest(P(x, y), neighbours_count)), + t.qend_(), + std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - qbegin(nearest(P, " << neighbours_count << ")) qend() " << nearest_queries_count << " found " << temp << '\n'; + } +#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + RT::const_query_iterator first = t.qbegin(bgi::nearest(P(x, y), neighbours_count)); + RT::const_query_iterator last = t.qend(); + std::copy(first, last, std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - type-erased qbegin(nearest(P, " << neighbours_count << ")) qend() " << nearest_queries_count << " found " << temp << '\n'; + } + +#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL +#ifndef SEGMENT_INDEXABLE + + { + LS ls; + ls.resize(6); + + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < path_queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + for ( int i = 0 ; i < 3 ; ++i ) + { + float foo = i*max_val/300; + ls[2*i] = P(x, y+foo); + ls[2*i+1] = P(x+max_val/100, y+foo); + } + result.clear(); + t.query(bgi::path(ls, path_values_count), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(path(LS6, " << path_values_count << ")) " << path_queries_count << " found " << temp << '\n'; + } + + { + LS ls; + ls.resize(2); + + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < path_queries_count2 ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + ls[0] = P(x, y); + ls[1] = P(x+max_val/100, y+max_val/100); + result.clear(); + t.query(bgi::path(ls, path_values_count), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(path(LS2, " << path_values_count << ")) " << path_queries_count2 << " found " << temp << '\n'; + } + + { + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < path_queries_count2 ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + S seg(P(x, y), P(x+max_val/100, y+max_val/100)); + result.clear(); + t.query(bgi::path(seg, path_values_count), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(path(S, " << path_values_count << ")) " << path_queries_count2 << " found " << temp << '\n'; + } +#endif +#endif + { + clock_t::time_point start = clock_t::now(); + for (size_t i = 0 ; i < values_count / 10 ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + + t.remove(generate_value<V>::apply(x, y)); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - remove " << values_count / 10 << '\n'; + + std::cout << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " boxes ok\n" : "boxes NOT ok\n"); + } + + std::cout << "------------------------------------------------\n"; + } + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/benchmark_insert.cpp b/src/boost/libs/geometry/index/example/benchmark_insert.cpp new file mode 100644 index 00000000..4fe82e91 --- /dev/null +++ b/src/boost/libs/geometry/index/example/benchmark_insert.cpp @@ -0,0 +1,196 @@ +// Boost.Geometry Index +// Additional tests + +// Copyright (c) 2011-2015 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> +#include <vector> +#include <algorithm> + +#include <boost/chrono.hpp> +#include <boost/foreach.hpp> +#include <boost/random.hpp> + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> +#include <boost/geometry/geometries/geometries.hpp> + +#include <boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp> +#include <boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp> +#include <boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp> + +namespace bg = boost::geometry; +namespace bgi = bg::index; + +typedef bg::model::point<double, 2, bg::cs::cartesian> P; +typedef bg::model::box<P> B; +typedef bg::model::segment<P> S; +typedef P V; +//typedef B V; +//typedef S V; + +template <typename V> +struct generate_value {}; + +template <> +struct generate_value<B> +{ + static inline B apply(float x, float y) { return B(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); } +}; + +template <> +struct generate_value<S> +{ + static inline S apply(float x, float y) { return S(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); } +}; + +template <> +struct generate_value<P> +{ + static inline P apply(float x, float y) { return P(x, y); } +}; + +template <typename RT> +void test_queries(RT const& t, std::vector< std::pair<float, float> > const& coords, size_t queries_count) +{ + typedef boost::chrono::thread_clock clock_t; + typedef boost::chrono::duration<float> dur_t; + + std::vector<V> result; + result.reserve(100); + + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + t.query(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time.count() << " " << temp << '\n'; +} + +//#define BOOST_GEOMETRY_INDEX_BENCHMARK_DEBUG + +int main() +{ + //typedef bgi::rtree<V, bgi::linear<4, 2> > RT; + //typedef bgi::rtree<V, bgi::linear<16, 4> > RT; + //typedef bgi::rtree<V, bgi::quadratic<4, 2> > RT; + typedef bgi::rtree<V, bgi::rstar<8, 2> > RT; + + typedef boost::chrono::thread_clock clock_t; + typedef boost::chrono::duration<float> dur_t; + +#ifndef BOOST_GEOMETRY_INDEX_BENCHMARK_DEBUG + size_t values_count = 1000000; + size_t queries_count = 100000; + size_t nearest_queries_count = 20000; + unsigned neighbours_count = 10; + size_t max_range_inserts = 10; +#else + size_t values_count = 10000; + size_t queries_count = 1000; + size_t nearest_queries_count = 100; + unsigned neighbours_count = 10; + size_t max_range_inserts = 10; +#endif + + float max_val = static_cast<float>(values_count / 2); + std::vector< std::pair<float, float> > coords; + std::vector<V> values; + + //randomize values + { + boost::mt19937 rng; + //rng.seed(static_cast<unsigned int>(std::time(0))); + boost::uniform_real<float> range(-max_val, max_val); + boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range); + + coords.reserve(values_count); + + std::cout << "randomizing data\n"; + for ( size_t i = 0 ; i < values_count ; ++i ) + { + float x = rnd(); + float y = rnd(); + coords.push_back(std::make_pair(x, y)); + values.push_back(generate_value<V>::apply(x, y)); + } + std::cout << "randomized\n"; + } + + for (;;) + { + // packing test + { + clock_t::time_point start = clock_t::now(); + + RT t(values.begin(), values.end()); + + BOOST_ASSERT(bgi::detail::rtree::utilities::are_boxes_ok(t)); + BOOST_ASSERT(bgi::detail::rtree::utilities::are_counts_ok(t)); + BOOST_ASSERT(bgi::detail::rtree::utilities::are_levels_ok(t)); + + dur_t time = clock_t::now() - start; + std::cout << "pack(" << values_count << ") - " << time.count() << ", "; + + test_queries(t, coords, queries_count); + } + + { + size_t n_per_max = values_count / max_range_inserts; + + for ( size_t j = 0 ; j < max_range_inserts ; ++j ) + { + clock_t::time_point start = clock_t::now(); + + RT t; + + // perform j range-inserts + for ( size_t i = 0 ; i < j ; ++i ) + { + t.insert(values.begin() + n_per_max * i, + values.begin() + (std::min)(n_per_max * (i + 1), values_count)); + } + + if ( !t.empty() ) + { + BOOST_ASSERT(bgi::detail::rtree::utilities::are_boxes_ok(t)); + BOOST_ASSERT(bgi::detail::rtree::utilities::are_counts_ok(t)); + BOOST_ASSERT(bgi::detail::rtree::utilities::are_levels_ok(t)); + } + + // perform n-n/max_inserts*j inserts + size_t inserted_count = (std::min)(n_per_max*j, values_count); + for ( size_t i = inserted_count ; i < values_count ; ++i ) + { + t.insert(values[i]); + } + + if ( !t.empty() ) + { + BOOST_ASSERT(bgi::detail::rtree::utilities::are_boxes_ok(t)); + BOOST_ASSERT(bgi::detail::rtree::utilities::are_counts_ok(t)); + BOOST_ASSERT(bgi::detail::rtree::utilities::are_levels_ok(t)); + } + + dur_t time = clock_t::now() - start; + std::cout << j << "*insert(N/" << max_range_inserts << ")+insert(" << (values_count - inserted_count) << ") - " << time.count() << ", "; + + test_queries(t, coords, queries_count); + } + } + + std::cout << "------------------------------------------------\n"; + } + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/glut_vis.cpp b/src/boost/libs/geometry/index/example/glut_vis.cpp new file mode 100644 index 00000000..2c5f5740 --- /dev/null +++ b/src/boost/libs/geometry/index/example/glut_vis.cpp @@ -0,0 +1,1094 @@ +// Boost.Geometry Index +// OpenGL visualization + +// 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <GL/glut.h> + +#include <boost/foreach.hpp> + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> + +#include <boost/geometry/geometries/linestring.hpp> +#include <boost/geometry/geometries/segment.hpp> +#include <boost/geometry/geometries/ring.hpp> +#include <boost/geometry/geometries/polygon.hpp> +#include <boost/geometry/geometries/multi_polygon.hpp> + +#include <boost/geometry/index/detail/rtree/utilities/gl_draw.hpp> +#include <boost/geometry/index/detail/rtree/utilities/print.hpp> +#include <boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp> +#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; +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; + +// containers variant + +template <typename V> +struct containers +{ + containers & operator=(containers const& c) + { + tree = c.tree; + values = c.values; + result = c.result; + return *this; + } + + 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; +size_t count = 5; + +P search_point; +B search_box; +R search_ring; +Poly search_poly; +MPoly search_multi_poly; +S search_segment; +LS search_linestring; +LS search_path; + +enum query_mode_type { + qm_knn, qm_knnb, qm_knns, qm_c, qm_d, qm_i, qm_o, qm_w, qm_nc, qm_nd, qm_ni, qm_no, qm_nw, qm_all, qm_ri, qm_pi, qm_mpi, qm_si, qm_lsi, qm_path +} query_mode = qm_knn; + +bool search_valid = false; + +// various queries + +void query_knn() +{ + float x = ( rand() % 1000 ) / 10.0f; + float y = ( rand() % 1000 ) / 10.0f; + + if ( query_mode == qm_knn ) + { + search_point = P(x, y); + 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 = query(cont, bgi::nearest(search_box, count)); + } + else if ( query_mode == qm_knns ) + { + int signx = rand() % 2 ? 1 : -1; + int signy = rand() % 2 ? 1 : -1; + 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 = query(cont, bgi::nearest(search_segment, count)); + } + else + { + BOOST_ASSERT(false); + } + + if ( found_count > 0 ) + { + if ( query_mode == qm_knn ) + { + 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; + float y = ( rand() % 1000 ) / 10.0f; + float w = 20 + ( rand() % 1000 ) / 100.0f; + float h = 20 + ( rand() % 1000 ) / 100.0f; + + search_path.resize(10); + float yy = y-h; + for ( int i = 0 ; i < 5 ; ++i, yy += h / 2 ) + { + search_path[2 * i] = P(x-w, yy); + search_path[2 * i + 1] = P(x+w, yy); + } + + found_count = query(cont, bgi::detail::path<LS>(search_path, count)); + + if ( found_count > 0 ) + { + std::cout << "search path: "; + BOOST_FOREACH(P const& p, search_path) + bgi::detail::utilities::print_indexable(std::cout, p); + std::cout << "\nfound: "; + print_result(cont); + } + else + std::cout << "values on path not found\n"; +} +#endif + +template <typename Predicate> +void query() +{ + if ( query_mode != qm_all ) + { + float x = ( rand() % 1000 ) / 10.0f; + float y = ( rand() % 1000 ) / 10.0f; + float w = 10 + ( rand() % 1000 ) / 100.0f; + float h = 10 + ( rand() % 1000 ) / 100.0f; + + search_box = B(P(x - w, y - h), P(x + w, y + h)); + } + else + { + 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: "; + print_result(cont); + } + else + std::cout << "boxes not found\n"; +} + +template <typename Predicate> +void query_ring() +{ + float x = ( rand() % 1000 ) / 10.0f; + float y = ( rand() % 1000 ) / 10.0f; + float w = 10 + ( rand() % 1000 ) / 100.0f; + float h = 10 + ( rand() % 1000 ) / 100.0f; + + search_ring.clear(); + search_ring.push_back(P(x - w, y - h)); + search_ring.push_back(P(x - w/2, y - h)); + search_ring.push_back(P(x, y - 3*h/2)); + search_ring.push_back(P(x + w/2, y - h)); + search_ring.push_back(P(x + w, y - h)); + search_ring.push_back(P(x + w, y - h/2)); + search_ring.push_back(P(x + 3*w/2, y)); + search_ring.push_back(P(x + w, y + h/2)); + search_ring.push_back(P(x + w, y + h)); + search_ring.push_back(P(x + w/2, y + h)); + search_ring.push_back(P(x, y + 3*h/2)); + search_ring.push_back(P(x - w/2, y + h)); + search_ring.push_back(P(x - w, y + h)); + search_ring.push_back(P(x - w, y + h/2)); + search_ring.push_back(P(x - 3*w/2, y)); + search_ring.push_back(P(x - w, y - h/2)); + search_ring.push_back(P(x - w, y - h)); + + found_count = query(cont, Predicate(search_ring)); + + if ( found_count > 0 ) + { + std::cout << "search ring: "; + BOOST_FOREACH(P const& p, search_ring) + { + bgi::detail::utilities::print_indexable(std::cout, p); + std::cout << ' '; + } + std::cout << "\nfound: "; + print_result(cont); + } + else + std::cout << "boxes not found\n"; +} + +template <typename Predicate> +void query_poly() +{ + float x = ( rand() % 1000 ) / 10.0f; + float y = ( rand() % 1000 ) / 10.0f; + float w = 10 + ( rand() % 1000 ) / 100.0f; + float h = 10 + ( rand() % 1000 ) / 100.0f; + + search_poly.clear(); + search_poly.outer().push_back(P(x - w, y - h)); + search_poly.outer().push_back(P(x - w/2, y - h)); + search_poly.outer().push_back(P(x, y - 3*h/2)); + search_poly.outer().push_back(P(x + w/2, y - h)); + search_poly.outer().push_back(P(x + w, y - h)); + search_poly.outer().push_back(P(x + w, y - h/2)); + search_poly.outer().push_back(P(x + 3*w/2, y)); + search_poly.outer().push_back(P(x + w, y + h/2)); + search_poly.outer().push_back(P(x + w, y + h)); + search_poly.outer().push_back(P(x + w/2, y + h)); + search_poly.outer().push_back(P(x, y + 3*h/2)); + search_poly.outer().push_back(P(x - w/2, y + h)); + search_poly.outer().push_back(P(x - w, y + h)); + search_poly.outer().push_back(P(x - w, y + h/2)); + search_poly.outer().push_back(P(x - 3*w/2, y)); + search_poly.outer().push_back(P(x - w, y - h/2)); + search_poly.outer().push_back(P(x - w, y - h)); + + search_poly.inners().push_back(Poly::ring_type()); + 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)); + 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)); + search_poly.inners()[0].push_back(P(x - w/2, y - h/2)); + + found_count = query(cont, Predicate(search_poly)); + + if ( found_count > 0 ) + { + std::cout << "search poly outer: "; + BOOST_FOREACH(P const& p, search_poly.outer()) + { + bgi::detail::utilities::print_indexable(std::cout, p); + std::cout << ' '; + } + std::cout << "\nfound: "; + print_result(cont); + } + else + std::cout << "boxes not found\n"; +} + +template <typename Predicate> +void query_multi_poly() +{ + float x = ( rand() % 1000 ) / 10.0f; + float y = ( rand() % 1000 ) / 10.0f; + float w = 10 + ( rand() % 1000 ) / 100.0f; + float h = 10 + ( rand() % 1000 ) / 100.0f; + + search_multi_poly.clear(); + + search_multi_poly.push_back(Poly()); + search_multi_poly[0].outer().push_back(P(x - w, y - h)); + search_multi_poly[0].outer().push_back(P(x - w/2, y - h)); + search_multi_poly[0].outer().push_back(P(x, y - 3*h/2)); + search_multi_poly[0].outer().push_back(P(x + w/2, y - h)); + search_multi_poly[0].outer().push_back(P(x + w, y - h)); + search_multi_poly[0].outer().push_back(P(x + w, y - h/2)); + search_multi_poly[0].outer().push_back(P(x + 3*w/2, y)); + search_multi_poly[0].outer().push_back(P(x + w, y + h/2)); + search_multi_poly[0].outer().push_back(P(x + w, y + h)); + search_multi_poly[0].outer().push_back(P(x + w/2, y + h)); + search_multi_poly[0].outer().push_back(P(x, y + 3*h/2)); + search_multi_poly[0].outer().push_back(P(x - w/2, y + h)); + search_multi_poly[0].outer().push_back(P(x - w, y + h)); + search_multi_poly[0].outer().push_back(P(x - w, y + h/2)); + search_multi_poly[0].outer().push_back(P(x - 3*w/2, y)); + search_multi_poly[0].outer().push_back(P(x - w, y - h/2)); + search_multi_poly[0].outer().push_back(P(x - w, y - h)); + + search_multi_poly[0].inners().push_back(Poly::ring_type()); + search_multi_poly[0].inners()[0].push_back(P(x - w/2, y - h/2)); + search_multi_poly[0].inners()[0].push_back(P(x + w/2, y - h/2)); + search_multi_poly[0].inners()[0].push_back(P(x + w/2, y + h/2)); + search_multi_poly[0].inners()[0].push_back(P(x - w/2, y + h/2)); + search_multi_poly[0].inners()[0].push_back(P(x - w/2, y - h/2)); + + search_multi_poly.push_back(Poly()); + search_multi_poly[1].outer().push_back(P(x - 2*w, y - 2*h)); + search_multi_poly[1].outer().push_back(P(x - 6*w/5, y - 2*h)); + search_multi_poly[1].outer().push_back(P(x - 6*w/5, y - 6*h/5)); + search_multi_poly[1].outer().push_back(P(x - 2*w, y - 6*h/5)); + search_multi_poly[1].outer().push_back(P(x - 2*w, y - 2*h)); + + search_multi_poly.push_back(Poly()); + search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 6*h/5)); + search_multi_poly[2].outer().push_back(P(x + 2*w, y + 6*h/5)); + search_multi_poly[2].outer().push_back(P(x + 2*w, y + 2*h)); + 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)); + + found_count = query(cont, Predicate(search_multi_poly)); + + if ( found_count > 0 ) + { + std::cout << "search multi_poly[0] outer: "; + BOOST_FOREACH(P const& p, search_multi_poly[0].outer()) + { + bgi::detail::utilities::print_indexable(std::cout, p); + std::cout << ' '; + } + std::cout << "\nfound: "; + print_result(cont); + } + else + std::cout << "boxes not found\n"; +} + +template <typename Predicate> +void query_segment() +{ + float x = ( rand() % 1000 ) / 10.0f; + float y = ( rand() % 1000 ) / 10.0f; + float w = 10.0f - ( rand() % 1000 ) / 50.0f; + float h = 10.0f - ( rand() % 1000 ) / 50.0f; + w += 0 <= w ? 10 : -10; + h += 0 <= h ? 10 : -10; + + boost::geometry::set<0, 0>(search_segment, x - w); + boost::geometry::set<0, 1>(search_segment, y - h); + boost::geometry::set<1, 0>(search_segment, x + w); + boost::geometry::set<1, 1>(search_segment, y + h); + + found_count = query(cont, Predicate(search_segment)); + + if ( found_count > 0 ) + { + std::cout << "search segment: "; + bgi::detail::utilities::print_indexable(std::cout, P(x-w, y-h)); + bgi::detail::utilities::print_indexable(std::cout, P(x+w, y+h)); + + std::cout << "\nfound: "; + print_result(cont); + } + else + std::cout << "boxes not found\n"; +} + +template <typename Predicate> +void query_linestring() +{ + float x = ( rand() % 1000 ) / 10.0f; + float y = ( rand() % 1000 ) / 10.0f; + float w = 10 + ( rand() % 1000 ) / 100.0f; + float h = 10 + ( rand() % 1000 ) / 100.0f; + + search_linestring.clear(); + float a = 0; + float d = 0; + for ( size_t i = 0 ; i < 300 ; ++i, a += 0.05, d += 0.005 ) + { + float xx = x + w * d * ::cos(a); + float yy = y + h * d * ::sin(a); + search_linestring.push_back(P(xx, yy)); + } + + found_count = query(cont, Predicate(search_linestring)); + + if ( found_count > 0 ) + { + std::cout << "search linestring: "; + BOOST_FOREACH(P const& p, search_linestring) + { + bgi::detail::utilities::print_indexable(std::cout, p); + std::cout << ' '; + } + std::cout << "\nfound: "; + 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_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_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_ri ) + query_ring< d::spatial_predicate<R, d::intersects_tag, false> >(); + else if ( query_mode == qm_pi ) + query_poly< d::spatial_predicate<Poly, d::intersects_tag, false> >(); + else if ( query_mode == qm_mpi ) + query_multi_poly< d::spatial_predicate<MPoly, d::intersects_tag, false> >(); + else if ( query_mode == qm_si ) + query_segment< d::spatial_predicate<S, d::intersects_tag, false> >(); + else if ( query_mode == qm_lsi ) + 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 = depth(cont); + + glBegin(GL_QUADS); + glVertex3f(x+1, y, z); + glVertex3f(x, y+1, z); + glVertex3f(x-1, y, z); + glVertex3f(x, y-1, z); + glEnd(); +} + +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 = depth(cont); + + draw_point(search_point); + + // search min circle + + glBegin(GL_LINE_LOOP); + for(float a = 0 ; a < 3.14158f * 2 ; a += 3.14158f / 180) + glVertex3f(x + min_distance * ::cos(a), y + min_distance * ::sin(a), z); + glEnd(); + + // search max circle + + glBegin(GL_LINE_LOOP); + for(float a = 0 ; a < 3.14158f * 2 ; a += 3.14158f / 180) + glVertex3f(x + max_distance * ::cos(a), y + max_distance * ::sin(a), z); + glEnd(); +} + +void draw_linestring(LS const& ls) +{ + glBegin(GL_LINE_STRIP); + + BOOST_FOREACH(P const& p, ls) + { + float x = boost::geometry::get<0>(p); + float y = boost::geometry::get<1>(p); + float z = depth(cont); + glVertex3f(x, y, z); + } + + glEnd(); +} + +void draw_segment(S const& s) +{ + float x1 = boost::geometry::get<0, 0>(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 = depth(cont); + + glBegin(GL_LINES); + glVertex3f(x1, y1, z); + glVertex3f(x2, y2, z); + glEnd(); +} + +template <typename Box> +void draw_box(Box const& box) +{ + float x1 = boost::geometry::get<bg::min_corner, 0>(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 = depth(cont); + + // search box + glBegin(GL_LINE_LOOP); + glVertex3f(x1, y1, z); + glVertex3f(x2, y1, z); + glVertex3f(x2, y2, z); + glVertex3f(x1, y2, z); + glEnd(); +} + +template <typename Range> +void draw_ring(Range const& range) +{ + float z = depth(cont); + + // search box + glBegin(GL_LINE_LOOP); + + BOOST_FOREACH(P const& p, range) + { + float x = boost::geometry::get<0>(p); + float y = boost::geometry::get<1>(p); + + glVertex3f(x, y, z); + } + glEnd(); +} + +template <typename Polygon> +void draw_polygon(Polygon const& polygon) +{ + draw_ring(polygon.outer()); + BOOST_FOREACH(Poly::ring_type const& r, polygon.inners()) + draw_ring(r); +} + +template <typename MultiPolygon> +void draw_multi_polygon(MultiPolygon const& multi_polygon) +{ + BOOST_FOREACH(Poly const& p, 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); + + draw_tree(cont); + + if ( search_valid ) + { + glColor3f(1.0f, 0.25f, 0.0f); + + if ( query_mode == qm_knn ) + draw_knn_area(0, 0); + else if ( query_mode == qm_knnb ) + draw_box(search_box); + else if ( query_mode == qm_knns ) + draw_segment(search_segment); + else if ( query_mode == qm_ri ) + draw_ring(search_ring); + else if ( query_mode == qm_pi ) + draw_polygon(search_poly); + else if ( query_mode == qm_mpi ) + draw_multi_polygon(search_multi_poly); + else if ( query_mode == qm_si ) + draw_segment(search_segment); + else if ( query_mode == qm_lsi ) + draw_linestring(search_linestring); + else if ( query_mode == qm_path ) + draw_linestring(search_path); + else + draw_box(search_box); + + glColor3f(1.0f, 0.5f, 0.0f); + + draw_result(cont); + } + + glFlush(); +} + +void resize(int w, int h) +{ + if ( h == 0 ) + h = 1; + + //float ratio = float(w) / h; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glViewport(0, 0, w, h); + + //gluPerspective(45, ratio, 1, 1000); + glOrtho(-150, 150, -150, 150, -150, 150); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + /*gluLookAt( + 120.0f, 120.0f, 120.0f, + 50.0f, 50.0f, -1.0f, + 0.0f, 1.0f, 0.0f);*/ + gluLookAt( + 50.0f, 50.0f, 75.0f, + 50.0f, 50.0f, -1.0f, + 0.0f, 1.0f, 0.0f); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glLineWidth(1.5f); + + 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 ) + { + insert_random_value(cont); + search_valid = false; + } + else if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN ) + { + remove_random_value(cont); + search_valid = false; + } + else if ( button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN ) + { + search(); + } + + 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 == "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"; + print_tree(cont); + std::cout << "\n"; + } + else if ( current_line == "rand" ) + { + insert_random_values(cont); + search_valid = false; + + glutPostRedisplay(); + } + else if ( current_line == "bulk" ) + { + bulk_insert_random_values(cont); + search_valid = false; + + glutPostRedisplay(); + } + else + { + if ( current_line == "knn" ) + query_mode = qm_knn; + else if ( current_line == "knnb" ) + query_mode = qm_knnb; + else if ( current_line == "knns" ) + query_mode = qm_knns; + else if ( current_line == "c" ) + query_mode = qm_c; + else if ( current_line == "d" ) + query_mode = qm_d; + else if ( current_line == "i" ) + query_mode = qm_i; + else if ( current_line == "o" ) + query_mode = qm_o; + else if ( current_line == "w" ) + query_mode = qm_w; + else if ( current_line == "nc" ) + query_mode = qm_nc; + else if ( current_line == "nd" ) + query_mode = qm_nd; + else if ( current_line == "ni" ) + query_mode = qm_ni; + else if ( current_line == "no" ) + query_mode = qm_no; + else if ( current_line == "nw" ) + query_mode = qm_nw; + else if ( current_line == "all" ) + query_mode = qm_all; + else if ( current_line == "ri" ) + query_mode = qm_ri; + else if ( current_line == "pi" ) + query_mode = qm_pi; + else if ( current_line == "mpi" ) + query_mode = qm_mpi; + else if ( current_line == "si" ) + query_mode = qm_si; + else if ( current_line == "lsi" ) + query_mode = qm_lsi; + else if ( current_line == "path" ) + query_mode = qm_path; + + search(); + glutPostRedisplay(); + } + + current_line.clear(); + std::cout << '\n'; + } + else + { + current_line += key; + std::cout << key; + } +} + +// main function + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); + glutInitWindowPosition(100,100); + glutInitWindowSize(600, 600); + glutCreateWindow("boost::geometry::index::rtree GLUT test"); + + glutDisplayFunc(render_scene); + glutReshapeFunc(resize); + glutMouseFunc(mouse); + glutKeyboardFunc(keyboard); + + glutMainLoop(); + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/random_test.cpp b/src/boost/libs/geometry/index/example/random_test.cpp new file mode 100644 index 00000000..1c40d155 --- /dev/null +++ b/src/boost/libs/geometry/index/example/random_test.cpp @@ -0,0 +1,185 @@ +// Boost.Geometry Index +// Additional tests + +// Copyright (c) 2011-2013 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> + +#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> + +#include <boost/foreach.hpp> +#include <boost/random.hpp> + +int main() +{ + namespace bg = boost::geometry; + namespace bgi = bg::index; + + size_t values_count = 1000000; + size_t queries_count = 10000; + size_t nearest_queries_count = 10000; + unsigned neighbours_count = 10; + + std::vector< std::pair<float, float> > coords; + + //randomize values + { + boost::mt19937 rng; + //rng.seed(static_cast<unsigned int>(std::time(0))); + float max_val = static_cast<float>(values_count / 2); + boost::uniform_real<float> range(-max_val, max_val); + boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > rnd(rng, range); + + coords.reserve(values_count); + + std::cout << "randomizing data\n"; + for ( size_t i = 0 ; i < values_count ; ++i ) + { + coords.push_back(std::make_pair(rnd(), rnd())); + } + std::cout << "randomized\n"; + } + + typedef bg::model::point<double, 2, bg::cs::cartesian> P; + typedef bg::model::box<P> B; + typedef bgi::rtree<B, bgi::linear<16, 4> > RT; + //typedef bgi::rtree<B, bgi::quadratic<8, 3> > RT; + //typedef bgi::rtree<B, bgi::rstar<8, 3> > RT; + + std::cout << "sizeof rtree: " << sizeof(RT) << std::endl; + + { + RT t; + + // inserting + { + for (size_t i = 0 ; i < values_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + B b(P(x - 0.5f, y - 0.5f), P(x + 0.5f, y + 0.5f)); + + t.insert(b); + } + std::cout << "inserted values: " << values_count << '\n'; + } + + std::vector<B> result; + result.reserve(100); + + // test + std::vector<size_t> spatial_query_data; + size_t spatial_query_index = 0; + + { + size_t found_count = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + t.query(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10))), std::back_inserter(result)); + + // test + spatial_query_data.push_back(result.size()); + found_count += result.size(); + } + std::cout << "spatial queries found: " << found_count << '\n'; + } + +#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + { + size_t found_count = 0; + for (size_t i = 0 ; i < queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + result.clear(); + std::copy(t.qbegin_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))), + t.qend_(bgi::intersects(B(P(x - 10, y - 10), P(x + 10, y + 10)))), + std::back_inserter(result)); + + // test + if ( spatial_query_data[spatial_query_index] != result.size() ) + std::cout << "Spatial query error - should be: " << spatial_query_data[spatial_query_index] << ", is: " << result.size() << '\n'; + ++spatial_query_index; + found_count += result.size(); + } + std::cout << "incremental spatial queries found: " << found_count << '\n'; + } +#endif + + // test + std::vector<float> nearest_query_data; + size_t nearest_query_data_index = 0; + + { + size_t found_count = 0; + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) + { + float x = coords[i].first + 100; + float y = coords[i].second + 100; + result.clear(); + t.query(bgi::nearest(P(x, y), neighbours_count), std::back_inserter(result)); + + // test + { + float max_dist = 0; + BOOST_FOREACH(B const& b, result) + { + float curr_dist = bgi::detail::comparable_distance_near(P(x, y), b); + if ( max_dist < curr_dist ) + max_dist = curr_dist; + } + nearest_query_data.push_back(max_dist); + } + found_count += result.size(); + } + std::cout << "nearest queries found: " << found_count << '\n'; + } + +#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + { + size_t found_count = 0; + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) + { + float x = coords[i].first + 100; + float y = coords[i].second + 100; + result.clear(); + + std::copy(t.qbegin_(bgi::nearest(P(x, y), neighbours_count)), + t.qend_(bgi::nearest(P(x, y), neighbours_count)), + std::back_inserter(result)); + + // test + { + float max_dist = 0; + BOOST_FOREACH(B const& b, result) + { + float curr_dist = bgi::detail::comparable_distance_near(P(x, y), b); + if ( max_dist < curr_dist ) + max_dist = curr_dist; + } + if ( nearest_query_data_index < nearest_query_data.size() && + nearest_query_data[nearest_query_data_index] != max_dist ) + std::cout << "Max distance error - should be: " << nearest_query_data[nearest_query_data_index] << ", and is: " << max_dist << "\n"; + ++nearest_query_data_index; + } + found_count += result.size(); + } + std::cout << "incremental nearest queries found: " << found_count << '\n'; + } +#endif + + std::cout << "finished\n"; + } + + return 0; +} diff --git a/src/boost/libs/geometry/index/example/serialize.cpp b/src/boost/libs/geometry/index/example/serialize.cpp new file mode 100644 index 00000000..11ce08bc --- /dev/null +++ b/src/boost/libs/geometry/index/example/serialize.cpp @@ -0,0 +1,168 @@ +// Boost.Geometry Index +// Additional tests + +// Copyright (c) 2011-2013 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> +#include <fstream> + +#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + +#include <boost/geometry.hpp> +#include <boost/geometry/index/rtree.hpp> +#include <boost/geometry/index/detail/rtree/utilities/statistics.hpp> + +#include <boost/archive/binary_oarchive.hpp> +#include <boost/archive/binary_iarchive.hpp> +#include <boost/archive/xml_oarchive.hpp> +#include <boost/archive/xml_iarchive.hpp> +#include <boost/serialization/vector.hpp> + +#include <boost/foreach.hpp> +#include <boost/timer.hpp> + +template <typename T, size_t I = 0, size_t S = boost::tuples::length<T>::value> +struct print_tuple +{ + template <typename Os> + static inline Os & apply(Os & os, T const& t) + { + os << boost::get<I>(t) << ", "; + return print_tuple<T, I+1>::apply(os, t); + } +}; + +template <typename T, size_t S> +struct print_tuple<T, S, S> +{ + template <typename Os> + static inline Os & apply(Os & os, T const&) + { + return os; + } +}; + +int main() +{ + namespace bg = boost::geometry; + namespace bgi = bg::index; + + typedef boost::tuple<std::size_t, std::size_t, std::size_t, std::size_t, std::size_t, std::size_t> S; + + typedef bg::model::point<double, 2, bg::cs::cartesian> P; + typedef bg::model::box<P> B; + typedef B V; + //typedef bgi::rtree<V, bgi::linear<16> > RT; + //typedef bgi::rtree<V, bgi::quadratic<8, 3> > RT; + //typedef bgi::rtree<V, bgi::rstar<8, 3> > RT; + typedef bgi::rtree<V, bgi::dynamic_linear > RT; + + //RT tree; + RT tree(bgi::dynamic_linear(16)); + std::vector<V> vect; + + boost::timer t; + + //insert values + { + for ( double x = 0 ; x < 1000 ; x += 1 ) + for ( double y = 0 ; y < 1000 ; y += 1 ) + vect.push_back(B(P(x, y), P(x+0.5, y+0.5))); + RT tmp(vect, tree.parameters()); + tree = boost::move(tmp); + } + B q(P(5, 5), P(6, 6)); + S s; + + std::cout << "vector and tree created in: " << t.elapsed() << std::endl; + + print_tuple<S>::apply(std::cout, bgi::detail::rtree::utilities::statistics(tree)) << std::endl; + std::cout << boost::get<0>(s) << std::endl; + BOOST_FOREACH(V const& v, tree | bgi::adaptors::queried(bgi::intersects(q))) + std::cout << bg::wkt<V>(v) << std::endl; + + // save + { + std::ofstream ofs("serialized_vector.bin", std::ios::binary | std::ios::trunc); + boost::archive::binary_oarchive oa(ofs); + t.restart(); + oa << vect; + std::cout << "vector saved to bin in: " << t.elapsed() << std::endl; + } + { + std::ofstream ofs("serialized_tree.bin", std::ios::binary | std::ios::trunc); + boost::archive::binary_oarchive oa(ofs); + t.restart(); + oa << tree; + std::cout << "tree saved to bin in: " << t.elapsed() << std::endl; + } + { + std::ofstream ofs("serialized_tree.xml", std::ios::trunc); + boost::archive::xml_oarchive oa(ofs); + t.restart(); + oa << boost::serialization::make_nvp("rtree", tree); + std::cout << "tree saved to xml in: " << t.elapsed() << std::endl; + } + + t.restart(); + vect.clear(); + std::cout << "vector cleared in: " << t.elapsed() << std::endl; + + t.restart(); + tree.clear(); + std::cout << "tree cleared in: " << t.elapsed() << std::endl; + + // load + + { + std::ifstream ifs("serialized_vector.bin", std::ios::binary); + boost::archive::binary_iarchive ia(ifs); + t.restart(); + ia >> vect; + std::cout << "vector loaded from bin in: " << t.elapsed() << std::endl; + t.restart(); + RT tmp(vect, tree.parameters()); + tree = boost::move(tmp); + std::cout << "tree rebuilt from vector in: " << t.elapsed() << std::endl; + } + + t.restart(); + tree.clear(); + std::cout << "tree cleared in: " << t.elapsed() << std::endl; + + { + std::ifstream ifs("serialized_tree.bin", std::ios::binary); + boost::archive::binary_iarchive ia(ifs); + t.restart(); + ia >> tree; + std::cout << "tree loaded from bin in: " << t.elapsed() << std::endl; + } + + std::cout << "loaded from bin" << std::endl; + print_tuple<S>::apply(std::cout, bgi::detail::rtree::utilities::statistics(tree)) << std::endl; + BOOST_FOREACH(V const& v, tree | bgi::adaptors::queried(bgi::intersects(q))) + std::cout << bg::wkt<V>(v) << std::endl; + + t.restart(); + tree.clear(); + std::cout << "tree cleared in: " << t.elapsed() << std::endl; + + { + std::ifstream ifs("serialized_tree.xml"); + boost::archive::xml_iarchive ia(ifs); + t.restart(); + ia >> boost::serialization::make_nvp("rtree", tree); + std::cout << "tree loaded from xml in: " << t.elapsed() << std::endl; + } + + std::cout << "loaded from xml" << std::endl; + print_tuple<S>::apply(std::cout, bgi::detail::rtree::utilities::statistics(tree)) << std::endl; + BOOST_FOREACH(V const& v, tree | bgi::adaptors::queried(bgi::intersects(q))) + std::cout << bg::wkt<V>(v) << std::endl; + + return 0; +} |