commit c5e823bbb5fa295306cdc992a4e9dbf351e18ebc Author: Adam Wulkiewicz Date: Thu Mar 24 23:52:27 2011 +0000 R*tree implementation based on boost::variant [SVN r70531] diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..3e84d7c70 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/include/boost/geometry/extensions/index/algorithms/area.hpp b/include/boost/geometry/extensions/index/algorithms/area.hpp new file mode 100644 index 000000000..d54ee8609 --- /dev/null +++ b/include/boost/geometry/extensions/index/algorithms/area.hpp @@ -0,0 +1,58 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - n-dimensional box's area/volume +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_AREA_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_AREA_HPP + +namespace boost { namespace geometry { namespace index { + +template +struct area_result +{ + typedef typename select_most_precise< + typename coordinate_type::type, + long double + >::type type; +}; + +namespace detail { + +template +struct area_for_each_dimension +{ + BOOST_STATIC_ASSERT(0 < CurrentDimension); + BOOST_STATIC_ASSERT(CurrentDimension <= traits::dimension::value); + + static inline typename area_result::type apply(Box const& b) + { + return area_for_each_dimension::apply(b) * + ( geometry::get(b) - geometry::get(b) ); + } +}; + +template +struct area_for_each_dimension +{ + static inline typename area_result::type apply(Box const& b) + { + return geometry::get(b) - geometry::get(b); + } +}; + +} // namespace detail + +template +typename area_result::type area(Box const& b) +{ + return detail::area_for_each_dimension::value>::apply(b); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_AREA_HPP diff --git a/include/boost/geometry/extensions/index/algorithms/margin.hpp b/include/boost/geometry/extensions/index/algorithms/margin.hpp new file mode 100644 index 000000000..44f0164f7 --- /dev/null +++ b/include/boost/geometry/extensions/index/algorithms/margin.hpp @@ -0,0 +1,102 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - n-dimensional box's margin value, 2d perimeter, 3d surface, etc... +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_MARGIN_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_MARGIN_HPP + +namespace boost { namespace geometry { namespace index { + +template +struct margin_result +{ + typedef typename select_most_precise< + typename coordinate_type::type, + long double + >::type type; +}; + +namespace detail { + +template +struct margin_for_each_edge +{ + BOOST_STATIC_ASSERT(0 < CurrentDimension); + BOOST_STATIC_ASSERT(0 < EdgeDimension); + + static inline typename margin_result::type apply(Box const& b) + { + return margin_for_each_edge::apply(b) * + ( geometry::get(b) - geometry::get(b) ); + } +}; + +template +struct margin_for_each_edge +{ + BOOST_STATIC_ASSERT(0 < CurrentDimension); + + static inline typename margin_result::type apply(Box const& b) + { + return margin_for_each_edge::apply(b); + } +}; + +template +struct margin_for_each_edge +{ + BOOST_STATIC_ASSERT(0 < CurrentDimension); + + static inline typename margin_result::type apply(Box const& b) + { + return geometry::get(b) - geometry::get(b); + } +}; + +template +struct margin_for_each_edge +{ + static inline typename margin_result::type apply(Box const& b) + { + return 1; + } +}; + +template +struct margin_for_each_dimension +{ + BOOST_STATIC_ASSERT(0 < CurrentDimension); + BOOST_STATIC_ASSERT(CurrentDimension <= traits::dimension::value); + + static inline typename margin_result::type apply(Box const& b) + { + return margin_for_each_dimension::apply(b) + + 2 * margin_for_each_edge::value>::apply(b); + } +}; + +template +struct margin_for_each_dimension +{ + static inline typename margin_result::type apply(Box const& b) + { + return 2 * margin_for_each_edge::value>::apply(b); + } +}; + +} // namespace detail + +template +typename margin_result::type margin(Box const& b) +{ + return detail::margin_for_each_dimension::value>::apply(b); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_MARGIN_HPP diff --git a/include/boost/geometry/extensions/index/algorithms/overlap.hpp b/include/boost/geometry/extensions/index/algorithms/overlap.hpp new file mode 100644 index 000000000..c2e98d12b --- /dev/null +++ b/include/boost/geometry/extensions/index/algorithms/overlap.hpp @@ -0,0 +1,34 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - n-dimensional area/volume of boxes intersecion/overlap +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_OVERLAP_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_OVERLAP_HPP + +#include +#include + +namespace boost { namespace geometry { namespace index { + +template +struct overlap_result +{ + typedef typename area_result::type type; +}; + +template +typename overlap_result::type overlap(Box const& b1, Box const& b2) +{ + Box inters; + geometry::intersection(b1, b2, inters); + return index::area(inters); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_OVERLAP_HPP diff --git a/include/boost/geometry/extensions/index/algorithms/union_area.hpp b/include/boost/geometry/extensions/index/algorithms/union_area.hpp new file mode 100644 index 000000000..38deeea25 --- /dev/null +++ b/include/boost/geometry/extensions/index/algorithms/union_area.hpp @@ -0,0 +1,32 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - boxes union/intersection area/volume +// +// Copyright 2008 Federico J. Fernandez. +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_UNION_AREA_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_UNION_AREA_HPP + +#include +#include + +namespace boost { namespace geometry { namespace index { + +/** + * \brief Compute the area of the union of b1 and b2 + */ +template +inline typename area_result::type union_area(Box const& b, Geometry const& g) +{ + Box expanded_box(b); + geometry::expand(expanded_box, g); + return index::area(expanded_box); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_ALGORITHMS_UNION_AREA_HPP diff --git a/include/boost/geometry/extensions/index/default_parameter.hpp b/include/boost/geometry/extensions/index/default_parameter.hpp new file mode 100644 index 000000000..beda15349 --- /dev/null +++ b/include/boost/geometry/extensions/index/default_parameter.hpp @@ -0,0 +1,62 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - default indexes parameters +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_DEFAULT_PARAMETER_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_DEFAULT_PARAMETER_HPP + +#include +#include +#include + +namespace boost { namespace geometry { namespace index { + +// TODO: awulkiew - move this elsewhere +struct default_parameter {}; + +namespace detail { + +template +struct geometry_box_type +{ + typedef geometry::model::box< + geometry::model::point< + typename index::traits::coordinate_type::type, + index::traits::dimension::value, + typename index::traits::coordinate_system::type + > + > type; +}; + +template +struct default_translator_type +{ + typedef Translator type; +}; +template +struct default_translator_type +{ + typedef translator::def type; +}; + +template +struct default_box_type +{ + typedef Box type; +}; +template +struct default_box_type +{ + typedef typename detail::geometry_box_type::type type; +}; + +} // namespace detail + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_DEFAULT_PARAMETER_HPP diff --git a/include/boost/geometry/extensions/index/filters/nearest_filter.hpp b/include/boost/geometry/extensions/index/filters/nearest_filter.hpp new file mode 100644 index 000000000..ec6fcd9e0 --- /dev/null +++ b/include/boost/geometry/extensions/index/filters/nearest_filter.hpp @@ -0,0 +1,78 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - nearest neighbour filter implementation +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_FILTERS_NEAREST_FILTER_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_FILTERS_NEAREST_FILTER_HPP + +namespace boost { namespace geometry { namespace index { namespace filters { + +template +class nearest_filter +{ +public: + typedef int* iterator; + typedef const int* const_iterator; + + template + nearest_filter( + SpacialIndex const&, + Point const&, + typename traits::coordinate_type::type const& + ) + {} + + iterator begin() { return 0; } + iterator end() { return 0; } + const_iterator begin() const { return 0; } + const_iterator end() const { return 0; } +}; + +namespace detail { + +template +class nearest_filtered +{ +public: + explicit nearest_filtered( + Point const& p, + typename traits::coordinate_type::type const& distance) + : m_point(p), m_distance(distance) {} + + Point const& point() const { return m_point; } + + typename traits::coordinate_type::type const& + distance() const { return m_distance; } + +private: + Point m_point; + typename traits::coordinate_type::type m_distance; +}; + +} // namespace detail + +template +detail::nearest_filtered nearest_filtered( + Point const& p, + typename traits::coordinate_type::type const& distance) +{ + return detail::nearest_filtered(p, distance); +} + +}}}} // namespace boost::geometry::index::filters + +template +boost::geometry::index::filters::nearest_filter + operator|( + SpacialIndex const& si, + boost::geometry::index::filters::detail::nearest_filtered const& f) +{ + return boost::geometry::index::filters::nearest_filter(si, f.point(), f.distance()); +} + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_FILTERS_NEAREST_FILTER_HPP diff --git a/include/boost/geometry/extensions/index/filters/spacial_filter.hpp b/include/boost/geometry/extensions/index/filters/spacial_filter.hpp new file mode 100644 index 000000000..7e8b69a6c --- /dev/null +++ b/include/boost/geometry/extensions/index/filters/spacial_filter.hpp @@ -0,0 +1,63 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - box query filter implementation +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_FILTERS_SPACIAL_FILTER_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_FILTERS_SPACIAL_FILTER_HPP + +namespace boost { namespace geometry { namespace index { namespace filters { + +template +class spatial_filter +{ +public: + typedef int* iterator; + typedef const int* const_iterator; + + template + spatial_filter(SpacialIndex const&, Geometry const&) {} + + iterator begin() { return 0; } + iterator end() { return 0; } + const_iterator begin() const { return 0; } + const_iterator end() const { return 0; } +}; + +namespace detail { + +template +class spatially_filtered +{ +public: + explicit spatially_filtered(Geometry const& geom) : m_geom(geom) {} + Geometry const& geometry() const { return m_geom; } + +private: + Geometry const& m_geom; +}; + +} // namespace detail + +template +detail::spatially_filtered spatially_filtered(Geometry const& geom) +{ + return detail::spatially_filtered(geom); +} + +}}}} // namespace boost::geometry::index::filters + +template +boost::geometry::index::filters::spatial_filter +operator|( + SpacialIndex const& si, + boost::geometry::index::filters::detail::spatially_filtered const& f) +{ + return boost::geometry::index::filters::spatial_filter(si, f.geometry()); +} + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_FILTERS_SPACIAL_FILTER_HPP diff --git a/include/boost/geometry/extensions/index/indexable.hpp b/include/boost/geometry/extensions/index/indexable.hpp new file mode 100644 index 000000000..d964e091e --- /dev/null +++ b/include/boost/geometry/extensions/index/indexable.hpp @@ -0,0 +1,160 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - indexable traits and functions +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_INDEXABLE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_INDEXABLE_HPP + +namespace boost { namespace geometry { namespace index { + +namespace dispatch { + +// Distinguish between indexables and other geometries + +template +struct indexable_type +{ + typedef void type; +}; + +template +struct indexable_type +{ + typedef Point type; +}; + +template +struct indexable_type +{ + typedef Box type; +}; + +} // namespace dispatch + +namespace traits +{ + +template +struct indexable_type +{ + typedef typename dispatch::indexable_type< + Indexable, + typename geometry::traits::tag::type + >::type type; +}; + +} // namespace traits + +namespace dispatch { + +template +struct point_type +{ + typedef void type; +}; + +template +struct point_type +{ + typedef typename geometry::traits::point_type::type type; +}; + +template +struct point_type +{ + typedef Indexable type; +}; + +} // namespace dispatch + +namespace traits { + +template +struct point_type +{ + typedef typename dispatch::point_type< + Indexable, + typename geometry::traits::tag::type + >::type type; +}; + +template +struct coordinate_system +{ + typedef typename geometry::traits::coordinate_system< + typename point_type::type + >::type type; +}; + +template +struct coordinate_type +{ + typedef typename geometry::traits::coordinate_type< + typename point_type::type + >::type type; +}; + +template +struct dimension +{ + static const size_t value = + geometry::traits::dimension< + typename point_type::type + >::value; +}; + +} // namespace traits + +namespace dispatch { + +template +struct indexable_indexed_access {}; + +template +struct indexable_indexed_access +{ + typedef typename traits::point_type::type point_type; + typedef typename traits::coordinate_type::type coordinate_type; + + static inline coordinate_type get(Indexable const& i) + { + return geometry::get(i); + } +}; + +template +struct indexable_indexed_access +{ + typedef typename traits::coordinate_type::type coordinate_type; + + static inline coordinate_type get(Indexable const& i) + { + return geometry::get(i); + } +}; + +} // namespace dispatch + +namespace detail { + +template +typename traits::coordinate_type::type get(Indexable const& i) +{ + return dispatch::indexable_indexed_access< + Corner, + DimensionIndex, + Indexable, + typename geometry::traits::tag::type + >::get(i); +} + +} // namespace detail + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_INDEXABLE_HPP diff --git a/include/boost/geometry/extensions/index/rtree/filters.hpp b/include/boost/geometry/extensions/index/rtree/filters.hpp new file mode 100644 index 000000000..15bef8fa6 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/filters.hpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - rtree queries filters implementation +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_FILTERS_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_FILTERS_HPP + +#include +#include + +#include +#include + +namespace boost { namespace geometry { namespace index { + +template +class rtree; + +namespace filters { + +template +class spatial_filter< index::rtree > +{ +public: + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + + template + spatial_filter(index::rtree const& rtree, Geometry const& geom) + { + m_result = rtree.find(geom); + } + + iterator begin() { return m_result.begin(); } + iterator end() { return m_result.end(); } + const_iterator begin() const { return m_result.begin(); } + const_iterator end() const { return m_result.end(); } + +private: + std::vector m_result; +}; + +} // namespace filters + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_FILTERS_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rstar/rstar.hpp b/include/boost/geometry/extensions/index/rtree/rstar/rstar.hpp new file mode 100644 index 000000000..d5d218195 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/rstar/rstar.hpp @@ -0,0 +1,16 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R*-tree +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_RSTAR_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_RSTAR_HPP + +#include +#include + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_RSTAR_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rstar/rtree_insert.hpp b/include/boost/geometry/extensions/index/rtree/rstar/rtree_insert.hpp new file mode 100644 index 000000000..e4aa929ab --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/rstar/rtree_insert.hpp @@ -0,0 +1,729 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R*-tree insert algorithm implementation +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_RTREE_INSERT_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_RTREE_INSERT_HPP + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +// ----------------------------------------------------------------------------- // +// rstar/choose_next_node +// ----------------------------------------------------------------------------- // + +// TODO: awulkiew - it's possible that goodness values may be used to choose next node + +// rtree choose_next_node algorithm for rstar variant + +template +class rtree_rstar_choose_next_node +{ + typedef typename index::detail::rtree_node::type node; + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + typedef typename internal_node::children_type children_type; + +public: + // TODO: awulkiew - alternative lower-cost version of overlap calculation may be used (branch_areas) + // TODO: awulkiew - further optimization: don't calculate area with the overlap, calculate it only if + // overlap < smallest_overlap (and current area must be stored) OR + // overlap == smallest_overlap (and area must be compared) + template + static inline size_t apply(internal_node & n, Indexable const& indexable) + { + assert(!n.children.empty()); + + bool has_leaves = boost::apply_visitor( + visitors::rtree_is_leaf(), + *n.children.front().second); + + if ( !has_leaves ) + return impl(n, indexable); + else + return impl(n, indexable); + } + +private: + template + static inline size_t impl(internal_node & n, Indexable const& indexable) + { + typedef typename children_type::iterator children_iterator; + + //assert(!n.children.empty()); + + children_iterator temp_it = n.children.begin(); + children_iterator child_it = temp_it; + Areas min_areas(n.children, child_it, indexable); + + for (children_iterator it = ++temp_it; + it != n.children.end(); ++it) + { + Areas areas(n.children, it, indexable); + + if ( areas < min_areas ) + { + child_it = it; + min_areas = areas; + } + } + + // TODO: awulkiew - switch to indexes in the whole class? + return child_it - n.children.begin(); + } + + struct branch_areas + { + typedef typename area_result::type area_type; + + template + inline branch_areas(children_type const& ch, typename children_type::iterator const& k_it, Indexable const& indexable) + { + overlap_area = 0; + for (typename children_type::const_iterator it = ch.begin(); it != ch.end(); ++it) + if ( it != k_it ) + overlap_area += index::overlap(k_it->first, it->first); + + area = index::area(k_it->first); + + diff_area = index::union_area(k_it->first, indexable) - area; + } + + inline bool operator<(branch_areas &a) const + { + return overlap_area < a.overlap_area || + ( overlap_area == a.overlap_area && diff_area < a.diff_area ) || + ( diff_area == a.diff_area && area < a.area ); + } + + area_type overlap_area; + area_type diff_area; + area_type area; + }; + + struct internal_node_areas + { + typedef typename area_result::type area_type; + + template + inline internal_node_areas(children_type const&, typename children_type::iterator const& k_it, Indexable const& indexable) + { + area = index::area(k_it->first); + diff_area = index::union_area(k_it->first, indexable) - area; + } + + inline bool operator<(internal_node_areas &a) const + { + return diff_area < a.diff_area || + ( diff_area == a.diff_area && area < a.area ); + } + + area_type diff_area; + area_type area; + }; +}; + +// ----------------------------------------------------------------------------- // +// rstar/sorts +// ----------------------------------------------------------------------------- // + +// elements ids less comparator + +template +class rtree_rstar_elements_indexes_less +{ +public: + rtree_rstar_elements_indexes_less(Elements const& elements, Translator const& tr) + : m_elements(elements), m_tr(tr) + {} + + bool operator()(size_t e1_index, size_t e2_index) + { + return + index::detail::get( + index::detail::rtree_element_indexable(m_elements[e1_index], m_tr) + ) + < + index::detail::get( + index::detail::rtree_element_indexable(m_elements[e2_index], m_tr) + ); + } + +private: + Elements const& m_elements; + Translator const& m_tr; +}; + +template +class rtree_rstar_vectors +{ +public: + inline rtree_rstar_vectors(size_t count) + : m_count(count), m_ids(Dimension * 2 * count) + {} + + template + inline typename std::vector::iterator begin() + { + BOOST_STATIC_ASSERT(AxisIndex < Dimension); + BOOST_STATIC_ASSERT(Corner < 2); + return m_ids.begin() + ( AxisIndex * 2 + Corner ) * m_count; + } + + template + inline typename std::vector::iterator end() + { + BOOST_STATIC_ASSERT(AxisIndex < Dimension); + BOOST_STATIC_ASSERT(Corner < 2); + return m_ids.begin() + ( AxisIndex * 2 + Corner + 1) * m_count; + } + + template + inline T const& get(size_t index) const + { + BOOST_STATIC_ASSERT(AxisIndex < Dimension); + BOOST_STATIC_ASSERT(Corner < 2); + assert(index < m_count); + return m_ids[( AxisIndex * 2 + Corner ) * m_count + index]; + } + + template + inline void set(size_t index, T const& v) + { + BOOST_STATIC_ASSERT(AxisIndex < Dimension); + BOOST_STATIC_ASSERT(Corner < 2); + assert(index < m_count); + m_ids[( AxisIndex * 2 + Corner ) * m_count + index] = v; + } + + inline T const& get(size_t axis, size_t corner, size_t index) const + { + assert(axis < Dimension); + assert(corner < 2); + assert(index < m_count); + return m_ids[( axis * 2 + corner ) * m_count + index]; + } + + inline size_t vector_size() const + { + return m_count; + } + +private: + size_t m_count; + std::vector m_ids; +}; + +// init indexes of elements and sort them + +template +class rtree_rstar_sorts_fill_ids +{ + BOOST_STATIC_ASSERT(0 < Dimension); + +public: + template + static inline void apply(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) + { + rtree_rstar_sorts_fill_ids::apply(ids, elements, tr); + + fill(ids, elements, tr); + fill(ids, elements, tr); + } + +private: + template + static inline void fill(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) + { + for ( size_t i = 0 ; i < elements.size() ; ++i ) + ids.set(i, i); + + rtree_rstar_elements_indexes_less less(elements, tr); + std::sort(ids.begin(), ids.end(), less); + } +}; + +template +class rtree_rstar_sorts_fill_ids +{ +public: + template + static inline void apply(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) + { + fill(ids, elements, tr); + fill(ids, elements, tr); + } + +private: + template + static inline void fill(rtree_rstar_vectors & ids, Elements const& elements, Translator const& tr) + { + for ( size_t i = 0 ; i < elements.size() ; ++i ) + ids.set<0, Corner>(i, i); + + rtree_rstar_elements_indexes_less less(elements, tr); + std::sort(ids.begin<0, Corner>(), ids.end<0, Corner>(), less); + } +}; + +// sorts for each axis for min and max + +template +class rtree_rstar_sorts +{ +public: + inline rtree_rstar_sorts(Elements const& elements, Translator const& tr) + : m_elems(elements), m_tr(tr), m_ids(m_elems.size()) + { + rtree_rstar_sorts_fill_ids::apply(m_ids, elements, tr); + } + + // TODO: awulkiew - should those methods be here? Just leave get_element? + + template + inline typename index::detail::rtree_element_indexable_type::type const& + get_indexable(size_t index) const + { + size_t id = m_ids.get(index); + return index::detail::rtree_element_indexable(m_elems[id], m_tr); + } + + inline typename index::detail::rtree_element_indexable_type::type const& + get_indexable(size_t axis, size_t corner, size_t index) const + { + size_t id = m_ids.get(axis, corner, index); + return index::detail::rtree_element_indexable(m_elems[id], m_tr); + } + + template + inline typename Elements::value_type const& get_element(size_t index) const + { + size_t id = m_ids.get(index); + return m_elems[id]; + } + + inline typename Elements::value_type const& get_element(size_t axis, size_t corner, size_t index) const + { + size_t id = m_ids.get(axis, corner, index); + return m_elems[id]; + } + + inline size_t sort_size() const + { + return m_ids.vector_size(); + } + +private: + Elements const& m_elems; + Translator const& m_tr; + + rtree_rstar_vectors m_ids; +}; + +// ----------------------------------------------------------------------------- // +// rstar/goodness_values +// ----------------------------------------------------------------------------- // + +// calculate margins, areas and overlaps + +template +class rtree_rstar_calculate_goodness_values_for_axis +{ + typedef typename geometry::traits::coordinate_type< + typename geometry::traits::point_type::type + >::type coordinate_type; + + static const size_t dimension = geometry::traits::dimension< + typename geometry::traits::point_type::type + >::value; + + typedef typename area_result::type area_type; + typedef typename margin_result::type margin_type; + typedef typename overlap_result::type overlap_type; + typedef boost::tuple goodness_type; + +public: + template + static inline void apply( + rtree_rstar_vectors & goodness_vectors, + rtree_rstar_sorts const& sorts, + size_t min_elems, + size_t max_elems) + { + assert(sorts.sort_size() == max_elems + 1); + assert(goodness_vectors.vector_size() == max_elems - 2 * min_elems + 2); + + size_t median_index_last = max_elems - min_elems + 2; + size_t i = 0; + for ( size_t median_index = min_elems ; median_index < median_index_last ; ++median_index, ++i ) + { + Box left_box = calculate_box(sorts, 0, median_index); + Box right_box = calculate_box(sorts, median_index, sorts.sort_size()); + + margin_type margin = index::margin(left_box) + index::margin(right_box); + area_type area = index::area(left_box) + index::area(right_box); + overlap_type overlap = index::overlap(left_box, right_box); + + goodness_vectors.set( + i, + boost::make_tuple(left_box, right_box, margin, overlap, area)); + } + } +private: + template + static inline Box calculate_box( + rtree_rstar_sorts const& sorts, + size_t index_first, + size_t index_last) + { + assert(index_first < index_last); + + Box result; + geometry::convert(sorts.template get_indexable(index_first), result); + ++index_first; + for ( ; index_first < index_last ; ++index_first ) + geometry::expand(result, sorts.template get_indexable(index_first)); + return result; + } +}; + +// calculate goodness values for all axis + +template +struct rtree_rstar_calculate_goodness_values +{ + BOOST_STATIC_ASSERT(0 < Dimension); + + typedef typename area_result::type area_type; + typedef typename margin_result::type margin_type; + typedef typename overlap_result::type overlap_type; + typedef boost::tuple goodness_type; + + template + static inline void apply( + rtree_rstar_vectors & goodness_vectors, + rtree_rstar_sorts const& sorts, + size_t min_elems, + size_t max_elems) + { + rtree_rstar_calculate_goodness_values + ::apply(goodness_vectors, sorts, min_elems, max_elems); + + rtree_rstar_calculate_goodness_values_for_axis + ::apply(goodness_vectors, sorts, min_elems, max_elems); + rtree_rstar_calculate_goodness_values_for_axis + ::apply(goodness_vectors, sorts, min_elems, max_elems); + } +}; + +template +struct rtree_rstar_calculate_goodness_values +{ + typedef typename area_result::type area_type; + typedef typename margin_result::type margin_type; + typedef typename overlap_result::type overlap_type; + typedef boost::tuple goodness_type; + + template + static inline void apply( + rtree_rstar_vectors & goodness_vectors, + rtree_rstar_sorts const& sorts, + size_t min_elems, + size_t max_elems) + { + rtree_rstar_calculate_goodness_values_for_axis + ::apply(goodness_vectors, sorts, min_elems, max_elems); + rtree_rstar_calculate_goodness_values_for_axis + ::apply(goodness_vectors, sorts, min_elems, max_elems); + } +}; + +// goodness values + +template +class rtree_rstar_goodness_values +{ + typedef typename geometry::traits::coordinate_type< + typename geometry::traits::point_type::type + >::type coordinate_type; + + static const size_t dimension = geometry::traits::dimension< + typename geometry::traits::point_type::type + >::value; + + typedef typename area_result::type area_type; + typedef typename margin_result::type margin_type; + typedef typename overlap_result::type overlap_type; + typedef boost::tuple goodness_type; + +public: + inline rtree_rstar_goodness_values( + Elements const& elements, + Translator const& tr, + size_t min_elems, + size_t max_elems) + : m_sorts(elements, tr) + , m_goodness_vectors(max_elems - 2 * min_elems + 2) + { + rtree_rstar_calculate_goodness_values::apply( + m_goodness_vectors, m_sorts, min_elems, max_elems); + } + + inline size_t elements_size() const + { + return m_sorts.sort_size(); + } + + inline size_t goodnesses_size() const + { + return m_goodness_vectors.vector_size(); + } + + inline goodness_type const& get_goodness(size_t axis, size_t corner, size_t index) const + { + return m_goodness_vectors.get(axis, corner, index); + } + + inline typename Elements::value_type const& get_element(size_t axis, size_t corner, size_t index) const + { + return m_sorts.get_element(axis, corner, index); + } + +private: + rtree_rstar_sorts m_sorts; + rtree_rstar_vectors m_goodness_vectors; +}; + +template +class rtree_rstar_choose_split_axis +{ + typedef typename margin_result::type margin_type; +public: + static inline std::pair apply(rtree_rstar_goodness_values const& gv) + { + std::pair smallest_distr = std::make_pair(0, 0); + margin_type smallest_margins_sum = calculate_margins_sum(0, 0, gv); + + margin_type margins_sum = calculate_margins_sum(0, 1, gv); + if ( margins_sum < smallest_margins_sum ) + { + smallest_distr.second = 1; + smallest_margins_sum = margins_sum; + } + + for ( size_t a = 1 ; a < traits::dimension::value ; ++a ) + { + for ( size_t c = 0 ; c < 2 ; ++c ) + { + margins_sum = calculate_margins_sum(a, c, gv); + if ( margins_sum < smallest_margins_sum ) + { + smallest_distr.first = a; + smallest_distr.second = c; + smallest_margins_sum = margins_sum; + } + } + } + return smallest_distr; + } +private: + static inline typename margin_result::type + calculate_margins_sum(size_t axis, size_t corner, rtree_rstar_goodness_values const& gv) + { + typename margin_result::type margins_sum = 0; + for ( size_t i = 0 ; i < gv.goodnesses_size() ; ++i ) + margins_sum += boost::get<2>(gv.get_goodness(axis, corner, i)); + return margins_sum; + } +}; + +template +class rtree_rstar_choose_split_index +{ + typedef typename area_result::type area_type; + typedef typename overlap_result::type overlap_type; +public: + static inline size_t apply(rtree_rstar_goodness_values const& gv, size_t axis, size_t corner) + { + size_t smallest_index = 0; + overlap_type smallest_overlap = boost::get<3>(gv.get_goodness(axis, corner, 0)); + overlap_type smallest_area = boost::get<4>(gv.get_goodness(axis, corner, 0)); + + for ( size_t i = 1 ; i < gv.goodnesses_size() ; ++i ) + { + overlap_type overlap = boost::get<3>(gv.get_goodness(axis, corner, i)); + if ( overlap < smallest_overlap ) + { + smallest_overlap = overlap; + smallest_area = boost::get<4>(gv.get_goodness(axis, corner, i)); + smallest_index = i; + } + else if ( overlap == smallest_overlap ) + { + area_type area = boost::get<4>(gv.get_goodness(axis, corner, i)); + if ( area < smallest_area ) + { + smallest_area = area; + smallest_index = i; + } + } + } + + return smallest_index; + } +}; + +// rtree insert routine for rstar variant + +template +class rtree_insert : public boost::static_visitor<> +{ + typedef typename index::detail::rtree_node::type node; + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + +public: + inline explicit rtree_insert(node* & root, Value const& v, size_t min_elements, size_t max_elements, Translator const& t) + : m_value(v), m_tr(t), m_min_elems_per_node(min_elements), m_max_elems_per_node(max_elements) + , m_root_node(root) + , m_parent(0), m_current_child_index(0) + {} + + inline void operator()(internal_node & n) + { + // save previous traverse inputs and set new ones + internal_node * parent_bckup = m_parent; + m_parent = &n; + size_t current_child_index_bckup = m_current_child_index; + + // choose next node, where value insert traversing should go + m_current_child_index = rtree_rstar_choose_next_node::apply(n, m_tr(m_value)); + + // TODO: awulkiew - if reinsert is implemented this must be changed + geometry::expand(n.children[m_current_child_index].first, m_tr(m_value)); + + // next traversing step + boost::apply_visitor(*this, *n.children[m_current_child_index].second); + + // restore previous traverse inputs + m_parent = parent_bckup; + m_current_child_index = current_child_index_bckup; + + if ( m_max_elems_per_node < n.children.size() ) + { + split(n); + } + } + + inline void operator()(leaf & n) + { + n.values.push_back(m_value); + + if ( m_max_elems_per_node < n.values.size() ) + { + split(n); + } + } + +private: + template + inline void split(Node & n) + { + typedef typename index::detail::rtree_elements_type::type elements_type; + typedef typename elements_type::value_type element_type; + + elements_type & elems = index::detail::get_elements(n); + + rtree_rstar_goodness_values gv(elems, m_tr, m_min_elems_per_node, m_max_elems_per_node); + + std::pair axis_and_corner = + rtree_rstar_choose_split_axis::apply(gv); + size_t axis = axis_and_corner.first; + size_t corner = axis_and_corner.second; + + size_t choosen_index = + rtree_rstar_choose_split_index::apply(gv, axis, corner); + + size_t median_index = m_min_elems_per_node + choosen_index; + assert(median_index <= m_max_elems_per_node + 1 - m_min_elems_per_node); + + // create new node + node * right_node = rtree_create_node(Node()); + elements_type & new_elems = index::detail::get_elements(boost::get(*right_node)); + + // update new node's elements + new_elems.reserve(m_max_elems_per_node + 1 - median_index); + for ( size_t i = median_index ; i < m_max_elems_per_node + 1 ; ++i) + new_elems.push_back(gv.get_element(axis, corner, i)); + + // fill temporary container with left node's elements + elements_type left_elems; + left_elems.reserve(median_index); + for ( size_t i = 0 ; i < median_index ; ++i ) + left_elems.push_back(gv.get_element(axis, corner, i)); + // update old node's elements + elems = left_elems; + + if ( m_parent != 0 ) + { + // update old node's box + m_parent->children[m_current_child_index].first = boost::get<0>(gv.get_goodness(axis, corner, choosen_index)); + // add new node to the parent's children + m_parent->children.push_back( std::make_pair( + boost::get<1>(gv.get_goodness(axis, corner, choosen_index)), right_node ) ); + } + else + { + assert(&n == boost::get(m_root_node)); + + // create new root and add nodes + node * new_root = rtree_create_node(internal_node()); + + boost::get(*new_root).children.push_back( + std::make_pair(boost::get<0>(gv.get_goodness(axis, corner, choosen_index)), m_root_node) + ); + boost::get(*new_root).children.push_back( + std::make_pair(boost::get<1>(gv.get_goodness(axis, corner, choosen_index)), right_node) + ); + + m_root_node = new_root; + } + } + + Value const& m_value; + Translator const& m_tr; + size_t m_min_elems_per_node; + size_t m_max_elems_per_node; + + node* & m_root_node; + + // traversing input parameters + internal_node *m_parent; + size_t m_current_child_index; +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_RTREE_INSERT_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rstar/tags.hpp b/include/boost/geometry/extensions/index/rtree/rstar/tags.hpp new file mode 100644 index 000000000..b19e29648 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/rstar/tags.hpp @@ -0,0 +1,19 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R*-tree tags +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_TAGS_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_TAGS_HPP + +namespace boost { namespace geometry { namespace index { + +struct rtree_rstar_tag {}; + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RSTAR_TAGS_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rtree.hpp b/include/boost/geometry/extensions/index/rtree/rtree.hpp new file mode 100644 index 000000000..8c26668dc --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/rtree.hpp @@ -0,0 +1,111 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree implementation +// +// Copyright 2008 Federico J. Fernandez. +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RTREE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_RTREE_HPP + +#include + +#include + +#include +#include + +#include + +namespace boost { namespace geometry { namespace index { + +// TODO: awulkiew - min and max elems as template parameters? + +template < + typename Value, + typename Translator = default_parameter, + typename Box = default_parameter, + typename Tag = rtree_rstar_tag +> +class rtree +{ +public: + typedef Value value_type; + typedef typename detail::default_translator_type::type translator_type; + typedef typename detail::default_box_type::type box_type; + + typedef typename detail::rtree_node::type node; + typedef typename detail::rtree_internal_node::type internal_node; + typedef typename detail::rtree_leaf::type leaf; + + inline explicit rtree(size_t max_elems_per_node = 4, size_t min_elems_per_node = 2, translator_type const& translator = translator_type()) + : m_values_count(0) + , m_max_elems_per_node(max_elems_per_node) + , m_min_elems_per_node(min_elems_per_node) + , m_root(0) + , m_translator(translator) + { + if ( min_elems_per_node < 2 ) + min_elems_per_node = 2; + + // TODO: awulkiew - reconsider following assert + assert(2 * m_min_elems_per_node <= m_max_elems_per_node); + + m_root = detail::rtree_create_node(leaf()); + } + + ~rtree() + { + visitors::rtree_delete del_v; + boost::apply_visitor(del_v, *m_root); + } + + template + inline std::vector find(Geometry const& geom) const + { + visitors::rtree_find find_v(geom, m_translator); + boost::apply_visitor(find_v, *m_root); + return find_v.result; + } + + void insert(Value const& value) + { + visitors::rtree_insert + insert_v(m_root, value, m_min_elems_per_node, m_max_elems_per_node, m_translator); + + boost::apply_visitor(insert_v, *m_root); + + ++m_values_count; + } + + template + void apply_visitor(Visitor & visitor) const + { + boost::apply_visitor(visitor, *m_root); + } + + translator_type const& get_translator() const + { + return m_translator; + } + +private: + size_t m_values_count; + size_t m_max_elems_per_node; + size_t m_min_elems_per_node; + node *m_root; + translator_type m_translator; +}; + +template +void insert(rtree & tree, Value const& v) +{ + tree.insert(v); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RSTREE_RSTREE_HPP diff --git a/include/boost/geometry/extensions/index/rtree/rtree_node.hpp b/include/boost/geometry/extensions/index/rtree/rtree_node.hpp new file mode 100644 index 000000000..e72baf688 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/rtree_node.hpp @@ -0,0 +1,196 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree details +// +// Copyright 2008 Federico J. Fernandez. +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_DEFAULT_NODE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_DEFAULT_NODE_HPP + +#include +#include + +namespace boost { namespace geometry { namespace index { + +namespace detail { + +template +struct rtree_node; + +// nodes default types + +template +struct rtree_internal_node_def +{ + typedef std::vector< + std::pair< + Box, + typename rtree_node::type * + > + > children_type; + + children_type children; +}; + +template +struct rtree_leaf_def +{ + typedef std::vector values_type; + values_type values; +}; + +// nodes traits + +template +struct rtree_node +{ + typedef boost::variant< + rtree_leaf_def, + rtree_internal_node_def + > type; +}; + +template +struct rtree_internal_node +{ + typedef rtree_internal_node_def type; +}; + +template +struct rtree_leaf +{ + typedef rtree_leaf_def type; +}; + +// nodes elements extractor + +template +struct rtree_elements_type +{ + typedef typename Node::elements_type type; +}; + +template +struct rtree_elements_type< rtree_internal_node_def > +{ + typedef typename rtree_internal_node_def::children_type type; +}; + +template +struct rtree_elements_type< rtree_leaf_def > +{ + typedef typename rtree_leaf_def::values_type type; +}; + +template +typename rtree_elements_type::type & get_elements(Node & n) +{ + return n.elements; +} + +template +typename rtree_internal_node_def::children_type & +get_elements(rtree_internal_node_def & n) +{ + return n.children; +} + +template +typename rtree_leaf_def::values_type & +get_elements(rtree_leaf_def & n) +{ + return n.values; +} + +// uniform indexable type for child node element's box and value's indexable + +template +struct rtree_element_indexable_type +{ + typedef typename Translator::indexable_type type; +}; + +template +struct rtree_element_indexable_type< + std::pair< + Box, + boost::variant< + rtree_leaf_def, + rtree_internal_node_def + > * + >, + Translator +> +{ + typedef Box type; +}; + +// uniform indexable getter for child node element's box and value's indexable + +template +Box const& +rtree_element_indexable( + std::pair< + Box, + boost::variant< + rtree_leaf_def, + rtree_internal_node_def + > * + > const& el, + Translator const&) +{ + return el.first; +} + +template +typename Translator::indexable_type const& +rtree_element_indexable(Value const& el, Translator const& tr) +{ + return tr(el); +}; + +// create leaf node + +template +typename rtree_node::type * +rtree_create_node(rtree_leaf_def const& l) +{ + typedef typename rtree_node::type node; + node * n = new node(); + *n = l; + return n; +} + +// create internal node + +template +typename rtree_node::type * +rtree_create_node(rtree_internal_node_def const& in) +{ + typedef typename rtree_node::type node; + node * n = new node(); + *n = in; + return n; +} + +// default node + +template +void rtree_delete_node( + boost::variant< + rtree_leaf_def, + rtree_internal_node_def + > * n) +{ + delete n; +} + +} // namespace detail + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_DEFAULT_NODE_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp b/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp new file mode 100644 index 000000000..666a48a4c --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/gl_draw.hpp @@ -0,0 +1,182 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree GL-draw visitor +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_GL_DRAW_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_GL_DRAW_HPP + +#include + +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +namespace dispatch { + +template +struct rtree_gl_draw_point +{}; + +template +struct rtree_gl_draw_point +{ + static inline void apply(Point const& p) + { + glBegin(GL_POINT); + glVertex2f(geometry::get<0>(p), geometry::get<1>(p)); + glEnd(); + } +}; + +template +struct rtree_gl_draw_box +{}; + +template +struct rtree_gl_draw_box +{ + static inline void apply(Box const& b) + { + glBegin(GL_LINE_LOOP); + glVertex2f(geometry::get(b), geometry::get(b)); + glVertex2f(geometry::get(b), geometry::get(b)); + glVertex2f(geometry::get(b), geometry::get(b)); + glVertex2f(geometry::get(b), geometry::get(b)); + glEnd(); + } +}; + +template +struct rtree_gl_draw_indexable +{ +}; + +template +struct rtree_gl_draw_indexable +{ + typedef typename geometry::traits::point_type::type point_type; + static const size_t dimension = geometry::traits::dimension::value; + + static inline void apply(Indexable const& i) + { + rtree_gl_draw_box::apply(i); + } +}; + +template +struct rtree_gl_draw_indexable +{ + static const size_t dimension = geometry::traits::dimension::value; + + static inline void apply(std::ostream &os, Indexable const& i) + { + rtree_gl_draw_point::apply(i); + } +}; + +} // namespace dispatch + +namespace detail { + +template +inline void rtree_gl_draw_indexable(Indexable const& i) +{ + dispatch::rtree_gl_draw_indexable< + Indexable, + typename geometry::traits::tag::type + >::apply(i); +} + +} // namespace detail + +template +struct rtree_gl_draw : public boost::static_visitor<> +{ + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + inline rtree_gl_draw(Translator const& t) + : tr(t), level(0) + {} + + inline void operator()(internal_node const& n) + { + typedef typename internal_node::children_type children_type; + + if ( level == 0 ) + glColor3f(1.0f, 0.0f, 0.0f); + else if ( level == 1 ) + glColor3f(0.0f, 1.0f, 0.0f); + else if ( level == 2 ) + glColor3f(0.0f, 0.0f, 1.0f); + else if ( level == 3 ) + glColor3f(1.0f, 1.0f, 0.0f); + else if ( level == 4 ) + glColor3f(1.0f, 0.0f, 1.0f); + else if ( level == 5 ) + glColor3f(0.0f, 1.0f, 1.0f); + else + glColor3f(0.5f, 0.5f, 0.5f); + + for (typename children_type::const_iterator it = n.children.begin(); + it != n.children.end(); ++it) + { + detail::rtree_gl_draw_indexable(it->first); + } + + size_t level_backup = level; + ++level; + + for (typename children_type::const_iterator it = n.children.begin(); + it != n.children.end(); ++it) + { + boost::apply_visitor(*this, *it->second); + } + + level = level_backup; + } + + inline void operator()(leaf const& n) + { + typedef typename leaf::values_type values_type; + + glColor3f(1.0f, 1.0f, 1.0f); + + for (typename values_type::const_iterator it = n.values.begin(); + it != n.values.end(); ++it) + { + detail::rtree_gl_draw_indexable(tr(*it)); + } + } + + Translator const& tr; + + size_t level; +}; + +} // namespace visitors + +template +void gl_draw(rtree const& tree) +{ + typedef typename rtree::translator_type translator_type; + typedef typename rtree::box_type box_type; + + glClear(GL_COLOR_BUFFER_BIT); + + visitors::rtree_gl_draw gl_draw_v(tree.get_translator()); + tree.apply_visitor(gl_draw_v); + + glFlush(); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_GL_DRAW_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/print.hpp b/include/boost/geometry/extensions/index/rtree/visitors/print.hpp new file mode 100644 index 000000000..23799f938 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/print.hpp @@ -0,0 +1,207 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree printing visitor +// +// Copyright 2008 Federico J. Fernandez. +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_PRINT_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_PRINT_HPP + +#include + +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +namespace dispatch { + +template +struct rtree_print_point +{ + BOOST_STATIC_ASSERT(0 < Dimension); + + static inline void apply(std::ostream & os, Point const& p) + { + rtree_print_point::apply(os, p); + + os << ", " << geometry::get(p); + } +}; + +template +struct rtree_print_point +{ + static inline void apply(std::ostream & os, Point const& p) + { + os << geometry::get<0>(p); + } +}; + +template +struct rtree_print_corner +{ + BOOST_STATIC_ASSERT(0 < Dimension); + + static inline void apply(std::ostream & os, Box const& b) + { + rtree_print_corner::apply(os, b); + + os << ", " << geometry::get(b); + } +}; + +template +struct rtree_print_corner +{ + static inline void apply(std::ostream & os, Box const& b) + { + os << geometry::get(b); + } +}; + +template +struct rtree_print_indexable +{ +}; + +template +struct rtree_print_indexable +{ + typedef typename geometry::traits::point_type::type point_type; + static const size_t dimension = geometry::traits::dimension::value; + + static inline void apply(std::ostream &os, Indexable const& i) + { + os << '('; + rtree_print_corner::apply(os, i); + os << ")x("; + rtree_print_corner::apply(os, i); + os << ')'; + } +}; + +template +struct rtree_print_indexable +{ + static const size_t dimension = geometry::traits::dimension::value; + + static inline void apply(std::ostream &os, Indexable const& i) + { + os << '('; + rtree_print_point::apply(os, i); + os << ')'; + } +}; + +} // namespace dispatch + +namespace detail { + +template +inline void rtree_print_indexable(std::ostream & os, Indexable const& i) +{ + dispatch::rtree_print_indexable< + Indexable, + typename geometry::traits::tag::type + >::apply(os, i); +} + +} // namespace detail + +template +struct rtree_print : public boost::static_visitor<> +{ + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + inline rtree_print(std::ostream & o, Translator const& t) + : os(o), tr(t), level(0) + {} + + inline void operator()(internal_node const& n) + { + typedef typename internal_node::children_type children_type; + + os << " --> Node --------" << std::endl; + os << " Address: " << this << std::endl; + os << " Level: " << level << std::endl; + os << " Children: " << n.children.size() << std::endl; + os << " | "; + + for (typename children_type::const_iterator it = n.children.begin(); + it != n.children.end(); ++it) + { + detail::rtree_print_indexable(os, it->first); + os << " | "; + } + os << std::endl; + os << " --< Node --------" << std::endl; + + os << " Children: " << std::endl; + + size_t level_backup = level; + ++level; + + for (typename children_type::const_iterator it = n.children.begin(); + it != n.children.end(); ++it) + { + boost::apply_visitor(*this, *it->second); + } + + level = level_backup; + } + + inline void operator()(leaf const& n) + { + typedef typename leaf::values_type values_type; + + os << "\t" << " --> Leaf --------" << std::endl; + os << "\t" << " Values: " << n.values.size() << std::endl; + for (typename values_type::const_iterator it = n.values.begin(); + it != n.values.end(); ++it) + { + os << "\t" << " | "; + detail::rtree_print_indexable(os, tr(*it)); + os << " | " << std::endl;; + } + os << "\t" << " --< Leaf --------" << std::endl; + + } + + std::ostream & os; + Translator const& tr; + + size_t level; +}; + +} // namespace visitors + +template +std::ostream & print(rtree const& tree, std::ostream & os = std::cout) +{ + typedef typename rtree::translator_type translator_type; + typedef typename rtree::box_type box_type; + visitors::rtree_print print_v(os, tree.get_translator()); + tree.apply_visitor(print_v); + return os; +} + +template +std::ostream & operator<<(std::ostream & os, rtree const& tree) +{ + typedef typename rtree::translator_type translator_type; + typedef typename rtree::box_type box_type; + visitors::rtree_print print_v(os, tree.get_translator()); + tree.apply_visitor(print_v); + return os; +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_PRINT_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/rtree_delete.hpp b/include/boost/geometry/extensions/index/rtree/visitors/rtree_delete.hpp new file mode 100644 index 000000000..549200df5 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/rtree_delete.hpp @@ -0,0 +1,47 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree delete visitor +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_DELETE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_DELETE_HPP + +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +template +struct rtree_delete : public boost::static_visitor<> +{ + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + inline void operator()(internal_node & n) const + { + typedef typename internal_node::children_type children_type; + + for (typename children_type::iterator it = n.children.begin(); + it != n.children.end(); ++it) + { + boost::apply_visitor(*this, *it->second); + + index::detail::rtree_delete_node(it->second); + } + } + + inline void operator()(leaf & n) const + { + } +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_DELETE_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/rtree_find.hpp b/include/boost/geometry/extensions/index/rtree/visitors/rtree_find.hpp new file mode 100644 index 000000000..d1fe369c6 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/rtree_find.hpp @@ -0,0 +1,66 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree find +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_FIND_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_FIND_HPP + +#include + +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +// rtree spatial query visitor + +template +struct rtree_find : public boost::static_visitor<> +{ + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + inline rtree_find(Geometry const& g, Translator const& t) + : geom(g), tr(t) + {} + + inline void operator()(internal_node const& n) + { + typedef typename internal_node::children_type children_type; + + for (typename children_type::const_iterator it = n.children.begin(); + it != n.children.end(); ++it) + { + if ( geometry::intersects(it->first, geom) ) + boost::apply_visitor(*this, *it->second); + } + } + + inline void operator()(leaf const& n) + { + typedef typename leaf::values_type values_type; + + for (typename values_type::const_iterator it = n.values.begin(); + it != n.values.end(); ++it) + { + if ( geometry::intersects(tr(*it), geom) ) + result.push_back(*it); + } + } + + Geometry const& geom; + Translator const& tr; + std::vector result; +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_FIND_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/rtree_insert.hpp b/include/boost/geometry/extensions/index/rtree/visitors/rtree_insert.hpp new file mode 100644 index 000000000..6317255e5 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/rtree_insert.hpp @@ -0,0 +1,29 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree details +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_INSERT_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_INSERT_HPP + +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +template +struct rtree_insert +{ + // not implemented here +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_INSERT_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/rtree_is_leaf.hpp b/include/boost/geometry/extensions/index/rtree/visitors/rtree_is_leaf.hpp new file mode 100644 index 000000000..50d6947f9 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/rtree_is_leaf.hpp @@ -0,0 +1,40 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree is leaf visitor +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_IS_LEAF_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_IS_LEAF_HPP + +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +template +struct rtree_is_leaf : public boost::static_visitor +{ + typedef typename index::detail::rtree_internal_node::type internal_node; + typedef typename index::detail::rtree_leaf::type leaf; + + inline bool operator()(internal_node const&) const + { + return false; + } + + inline bool operator()(leaf const&) const + { + return true; + } +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_IS_LEAF_HPP diff --git a/include/boost/geometry/extensions/index/rtree/visitors/rtree_remove.hpp b/include/boost/geometry/extensions/index/rtree/visitors/rtree_remove.hpp new file mode 100644 index 000000000..953fa49c3 --- /dev/null +++ b/include/boost/geometry/extensions/index/rtree/visitors/rtree_remove.hpp @@ -0,0 +1,29 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.Index - R-tree remove +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_REMOVE_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_REMOVE_HPP + +#include + +namespace boost { namespace geometry { namespace index { + +namespace visitors { + +template +struct rtree_remove +{ + // not implemented here +}; + +} // namespace visitors + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_RTREE_VISITORS_RTREE_REMOVE_HPP diff --git a/include/boost/geometry/extensions/index/translator/def.hpp b/include/boost/geometry/extensions/index/translator/def.hpp new file mode 100644 index 000000000..4780d45be --- /dev/null +++ b/include/boost/geometry/extensions/index/translator/def.hpp @@ -0,0 +1,103 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - default value to bounding object translation +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_DEF_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_DEF_HPP + +#include + +namespace boost { namespace geometry { namespace index { namespace translator { + +namespace dispatch { + +// Distinguish between def, def and def + +// Geometry +template +struct def +{ + typedef typename detail::extract_indexable::type indexable_type; + + indexable_type const& operator()(Value const& v) const + { + return detail::extract_indexable::get(v); + } + + /*bool equals(Value const& v1, Value const& v2) const + { + return detail::equals::apply(v1, v2); + }*/ +}; + +// Iterator +template +struct def +{ + typedef typename detail::extract_indexable::type indexable_type; + + indexable_type const& operator()(Value const& v) const + { + return detail::extract_indexable::get(*v); + } + + /*bool equals(Value const& v1, Value const& v2) const + { + return v1 == v2; + }*/ +}; + +// SmartPtr +template +struct def +{ + typedef typename detail::extract_indexable::type indexable_type; + + indexable_type const& operator()(Value const& v) const + { + return detail::extract_indexable::get(*v); + } + + /*bool equals(Value const& v1, Value const& v2) const + { + return v1 == v2; + }*/ +}; + +} // namespace dispatch + +template +struct def + : public dispatch::def + < + Value, + detail::is_iterator::value, + detail::is_smart_ptr::value + > +{ +}; + +template +struct def +{ + typedef typename detail::extract_indexable::type indexable_type; + + indexable_type const& operator()(const Value *v) const + { + return detail::extract_indexable::get(*v); + } + + /*bool equals(const Value* v1, const Value* v2) const + { + return v1 == v2; + }*/ +}; + +}}}} // namespace boost::geometry::index::translator + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_DEF_HPP diff --git a/include/boost/geometry/extensions/index/translator/helpers.hpp b/include/boost/geometry/extensions/index/translator/helpers.hpp new file mode 100644 index 000000000..b68ab9fd9 --- /dev/null +++ b/include/boost/geometry/extensions/index/translator/helpers.hpp @@ -0,0 +1,192 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - translators helper functions +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_HELPERS_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_HELPERS_HPP + +#include + +#include + +#include +#include + +#include + +namespace boost { namespace geometry { namespace index { namespace translator { + +namespace dispatch { + +// Extract object from std::pair by non-void tag + +template +struct choose_pair_element +{ + typedef typename Pair::first_type type; + static type const& get(Pair const& p) { return p.first; } +}; + +template +struct choose_pair_element +{ + typedef typename Pair::first_type type; + static type const& get(Pair const& p) { return p.first; } +}; + +template +struct choose_pair_element +{ + typedef typename Pair::second_type type; + static type const& get(Pair const& p) { return p.second; } +}; + +template +struct choose_pair_element +{ + typedef void type; +}; + +} // namespace dispatch + +namespace detail { + +template +struct indexable_not_found_error +{ + static const bool value = false; +}; +template <> +struct indexable_not_found_error +{ + static const bool value = true; +}; + +// Extract indexable + +template +struct extract_indexable +{ + typedef Value type; + + BOOST_STATIC_ASSERT(!indexable_not_found_error::value); + + static type const& get(Value const& v) { return v; } +}; + +template +struct extract_indexable< std::pair > +{ + typedef typename dispatch::choose_pair_element< + std::pair, + typename traits::indexable_type::type, + typename traits::indexable_type::type + > cp; + + typedef typename cp::type type; + + BOOST_STATIC_ASSERT(!indexable_not_found_error::value); + + static type const& get(std::pair const& v) + { + return cp::get(v); + } +}; + +// Recognize iterators and smart pointers + +BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category) +BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type) +BOOST_MPL_HAS_XXX_TRAIT_DEF(difference_type) +BOOST_MPL_HAS_XXX_TRAIT_DEF(pointer) +BOOST_MPL_HAS_XXX_TRAIT_DEF(reference) + +BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type) + +// TODO +// use has_operator_xxx in the future + +template +struct is_iterator +{ + static const bool value = boost::mpl::and_ + < + has_iterator_category, + has_value_type, + has_difference_type, + has_pointer, + has_reference + >::value; +}; + +template +struct is_smart_ptr +{ + static const bool value = has_element_type::value; +}; + +} // namespace detail + +//namespace dispatch { +// +//template +//struct equals +//{ +// static bool apply(Geometry const& g1, Geometry const& g2) +// { +// return geometry::equals(g1, g2); +// } +//}; +// +//template +//struct equals +//{ +// static bool apply(T const& v1, T const& v2) +// { +// return v1 == v2; +// } +//}; +// +//} // namespace dispatch +// +//namespace detail { +// +//template +//struct equals +//{ +// static bool apply(Geometry const& g1, Geometry const& g2) +// { +// return geometry::equals(g1, g2); +// } +//}; +// +//template +//struct equals< std::pair > +//{ +// static bool apply(std::pair const& p1, std::pair const& p2) +// { +// return +// dispatch::equals< +// First, +// typename traits::tag::type +// >::apply(p1.first, p2.first) +// && +// dispatch::equals< +// Second, +// typename traits::tag::type +// >::apply(p1.second, p2.second); +// } +//}; +// +//} // namespace detail + + + +}}}} // namespace boost::geometry::index::translator + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_HELPERS_HPP diff --git a/include/boost/geometry/extensions/index/translator/index.hpp b/include/boost/geometry/extensions/index/translator/index.hpp new file mode 100644 index 000000000..b0759393d --- /dev/null +++ b/include/boost/geometry/extensions/index/translator/index.hpp @@ -0,0 +1,43 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - container index value to bounding object translation +// +// Copyright 2011 Adam Wulkiewicz. +// 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) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_INDEX_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_INDEX_HPP + +#include + +namespace boost { namespace geometry { namespace index { namespace translator { + +template +class index +{ +public: + typedef typename detail::extract_indexable + ::type indexable_type; + + explicit index(Container const& c) : m_c(c) {} + + indexable_type const& operator()(size_t i) const + { + return detail::extract_indexable + ::get(m_c[i]); + } + + /*bool equals(size_t i1, size_t i2) const + { + return i1 == i2; + }*/ + +private: + Container const& m_c; +}; + +}}}} // namespace boost::geometry::index::translator + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_TRANSLATOR_INDEX_HPP diff --git a/tests/TODO.txt b/tests/TODO.txt new file mode 100644 index 000000000..4cad34427 --- /dev/null +++ b/tests/TODO.txt @@ -0,0 +1,20 @@ +// TODO +// wewnetrzny typ pudelek zmienic na geometry::box +// do kopiowania pudelek uzytkownik -> internal uzyc specjlnej funkcji +// przydalaby sie inna struktura wezlow - w tej powielane sa dane +// node <- internal_node, node <- leaf_node +// traktowanie liscia jako wezla wewnetrznego tez jest bez sensu (nie widze dobrej sytuacji) + +// czy translator powinien zwracac geometry::model::point czy Point +// a jesli zalozymy ze uzytkownik przechowuje Polygon to powinien on byc przechowywany z Boxem czy nie +// to przechowuje pair lub jesli przechowuje Box pisze sobie nowy translator + +// czy wewnatrz struktury powinny byc przechowywane: Box i geometry::box +// czy geometry::box::value>, ...> + +// 1. box wewnatrz wezlow +// 2. bounding object w lisciach + +// 3. jakis automatyczny przechowywacz innych obiektow? polygon, segment +// powinien istniec automatyczny translator obiekt -> box +// i box/point przechowywany w lisciach razem z obiektem \ No newline at end of file diff --git a/tests/additional_glut_vis.cpp b/tests/additional_glut_vis.cpp new file mode 100644 index 000000000..819dba15e --- /dev/null +++ b/tests/additional_glut_vis.cpp @@ -0,0 +1,70 @@ +#include +#define BOOST_GEOMETRY_INDEX_RTREE_ENABLE_GL_DRAW + +#include + +#include + +typedef boost::geometry::model::point P; +typedef boost::geometry::model::box

B; +boost::geometry::index::rtree t; + +void render_scene(void) +{ + boost::geometry::index::gl_draw(t); +} + +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); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( + 5.0f, 5.0f, 15.0f, + 5.0f, 5.0f, -1.0f, + 0.0f, 1.0f, 0.0f); +} + +void mouse(int button, int state, int x, int y) +{ + if ( state == GLUT_DOWN ) + { + float x = ( rand() % 10000 ) / 1000.0f; + float y = ( rand() % 10000 ) / 1000.0f; + float w = ( rand() % 10000 ) / 100000.0f; + float h = ( rand() % 10000 ) / 100000.0f; + + boost::geometry::index::insert(t, B(P(x - w, y - h),P(x + w, y + h))); + + glutPostRedisplay(); + } +} + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); + glutInitWindowPosition(100,100); + glutInitWindowSize(800, 600); + glutCreateWindow("Mouse click to insert new value"); + + glutDisplayFunc(render_scene); + glutReshapeFunc(resize); + glutMouseFunc(mouse); + + std::cout << "Mouse click to insert new value"; + + glutMainLoop(); + + return 0; +} diff --git a/tests/additional_sizes_and_times.cpp b/tests/additional_sizes_and_times.cpp new file mode 100644 index 000000000..c3ce00515 --- /dev/null +++ b/tests/additional_sizes_and_times.cpp @@ -0,0 +1,62 @@ +#include + +#include + +#include +#include + +int main() +{ + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + boost::geometry::index::rtree::leaf l; + boost::geometry::index::rtree::internal_node n; + + std::cout << "internal node size: " << sizeof(n) << '\n'; + std::cout << "leaf size: " << sizeof(l) << '\n'; + } + + boost::timer tim; + + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + // randomize boxes + const size_t n = 10000; + std::vector v(n); + for ( size_t i = 0 ; i < n ; ++i ) + { + float x = ( rand() % 10000 ) / 1000.0f; + float y = ( rand() % 10000 ) / 1000.0f; + float w = ( rand() % 10000 ) / 100000.0f; + float h = ( rand() % 10000 ) / 100000.0f; + v[i] = B(P(x - w, y - h),P(x + w, y + h)); + } + + boost::geometry::index::rtree t(4, 2); + + std::cout << "inserting time test...\n"; + + tim.restart(); + + BOOST_FOREACH(B &b, v) + { + boost::geometry::index::insert(t, b); + } + + std::cout << "time: " << tim.elapsed() << "s\n"; + + std::cout << "deleting time test...\n"; + tim.restart(); + } + std::cout << "time: " << tim.elapsed() << "s\n"; + +#ifdef _MSC_VER + std::cin.get(); +#endif + + return 0; +} diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 000000000..93fc439de --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +int main() +{ + tests_translators_hpp(); + tests_rtree_native_hpp(); + tests_rtree_filters_hpp(); + +#ifdef _MSC_VER + std::cin.get(); +#endif + + return 0; +} diff --git a/tests/rtree_filters.hpp b/tests/rtree_filters.hpp new file mode 100644 index 000000000..2162c6aa1 --- /dev/null +++ b/tests/rtree_filters.hpp @@ -0,0 +1,54 @@ +#ifndef TESTS_RTREE_FILTERS_HPP +#define TESTS_RTREE_FILTERS_HPP + +#include +#include + +#include +#include + +#include + +#include +#include + +template +void tests_rtree_filters_hpp_print_range(R const& r) +{ + BOOST_FOREACH(typename boost::iterator_value::type const& b, r) + { + float min_x = b.min_corner().template get<0>(); + float min_y = b.min_corner().template get<1>(); + float max_x = b.max_corner().template get<0>(); + float max_y = b.max_corner().template get<1>(); + std::cout << "(" << min_x << ", " << min_y << ")"; + std::cout << 'x'; + std::cout << "(" << max_x << ", " << max_y << ")"; + std::cout << '\n'; + } + std::cout << std::endl; +} + +void tests_rtree_filters_hpp() +{ + std::cout << "tests/rtree_filters.hpp\n"; + + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + { + boost::geometry::index::rtree t(4, 2); + boost::geometry::index::insert(t, B(P(0, 0), P(1, 1))); + boost::geometry::index::insert(t, B(P(2, 2), P(3, 3))); + boost::geometry::index::insert(t, B(P(4, 4), P(5, 5))); + boost::geometry::index::insert(t, B(P(6, 6), P(7, 7))); + boost::geometry::index::insert(t, B(P(8, 8), P(9, 9))); + std::cout << t; + + std::cout << "Query: (2.5, 2.5)x(4.5, 4.5)\n"; + namespace f = boost::geometry::index::filters; + tests_rtree_filters_hpp_print_range(t | f::spatially_filtered(B(P(2.5f, 2.5f), P(4.5f, 4.5f)))); + } +} + +#endif // TESTS_RTREE_FILTERS_HPP diff --git a/tests/rtree_native.hpp b/tests/rtree_native.hpp new file mode 100644 index 000000000..430c68bcd --- /dev/null +++ b/tests/rtree_native.hpp @@ -0,0 +1,150 @@ +#ifndef TESTS_RTREE_NATIVE_HPP +#define TESTS_RTREE_NATIVE_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include + +void tests_rtree_native_hpp() +{ + std::cout << "tests/rtree_native.hpp\n"; + + std::cout << "Boxes\n"; + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + boost::geometry::index::rtree t(4, 2); + boost::geometry::index::insert(t, B(P(0, 0), P(1, 1))); + boost::geometry::index::insert(t, B(P(2, 2), P(3, 3))); + boost::geometry::index::insert(t, B(P(4, 4), P(5, 5))); + boost::geometry::index::insert(t, B(P(6, 6), P(7, 7))); + boost::geometry::index::insert(t, B(P(8, 8), P(9, 9))); + std::cerr << t; + } + + std::cout << "-------------------------------------------------\n"; + std::cout << "-------------------------------------------------\n"; + + std::cout << "Points\n"; + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + boost::geometry::index::rtree

t(4, 2); + boost::geometry::index::insert(t, P(0, 0)); + boost::geometry::index::insert(t, P(2, 2)); + boost::geometry::index::insert(t, P(4, 4)); + boost::geometry::index::insert(t, P(6, 6)); + boost::geometry::index::insert(t, P(8, 8)); + std::cerr << t; + } + + std::cout << "-------------------------------------------------\n"; + std::cout << "-------------------------------------------------\n"; + + std::cout << "std::pair\n"; + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + typedef std::pair V; + + boost::geometry::index::rtree t(4, 2); + boost::geometry::index::insert(t, V(B(P(0, 0), P(1, 1)), 0)); + boost::geometry::index::insert(t, V(B(P(2, 2), P(3, 3)), 1)); + boost::geometry::index::insert(t, V(B(P(4, 4), P(5, 5)), 2)); + boost::geometry::index::insert(t, V(B(P(6, 6), P(7, 7)), 3)); + boost::geometry::index::insert(t, V(B(P(8, 8), P(9, 9)), 4)); + std::cerr << t; + } + + std::cout << "-------------------------------------------------\n"; + std::cout << "-------------------------------------------------\n"; + + std::cout << "boost::shared_ptr< std::pair >\n"; + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + typedef boost::shared_ptr< std::pair > V; + + V v1( new std::pair(B(P(0, 0), P(1, 1)), 0) ); + V v2( new std::pair(B(P(2, 2), P(3, 3)), 1) ); + V v3( new std::pair(B(P(4, 4), P(5, 5)), 2) ); + V v4( new std::pair(B(P(6, 6), P(7, 7)), 3) ); + V v5( new std::pair(B(P(8, 8), P(9, 9)), 4) ); + + boost::geometry::index::rtree t(4, 2); + boost::geometry::index::insert(t, v1); + boost::geometry::index::insert(t, v2); + boost::geometry::index::insert(t, v3); + boost::geometry::index::insert(t, v4); + boost::geometry::index::insert(t, v5); + std::cerr << t; + } + + std::cout << "-------------------------------------------------\n"; + std::cout << "-------------------------------------------------\n"; + + std::cout << "std::map::iterator\n"; + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + typedef std::map::iterator V; + + std::map m; + m.insert(std::pair(0, B(P(0, 0), P(1, 1)))); + m.insert(std::pair(1, B(P(2, 2), P(3, 3)))); + m.insert(std::pair(2, B(P(4, 4), P(5, 5)))); + m.insert(std::pair(3, B(P(6, 6), P(7, 7)))); + m.insert(std::pair(4, B(P(8, 8), P(9, 9)))); + + boost::geometry::index::rtree t(4, 2); + V vit = m.begin(); + boost::geometry::index::insert(t, vit++); + boost::geometry::index::insert(t, vit++); + boost::geometry::index::insert(t, vit++); + boost::geometry::index::insert(t, vit++); + boost::geometry::index::insert(t, vit); + std::cerr << t; + } + + std::cout << "-------------------------------------------------\n"; + std::cout << "-------------------------------------------------\n"; + + std::cout << "size_t\n"; + { + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + + typedef size_t V; + typedef boost::geometry::index::translator::index > T; + + std::vector v; + v.push_back(B(P(0, 0), P(1, 1))); + v.push_back(B(P(2, 2), P(3, 3))); + v.push_back(B(P(4, 4), P(5, 5))); + v.push_back(B(P(6, 6), P(7, 7))); + v.push_back(B(P(8, 8), P(9, 9))); + + boost::geometry::index::rtree t(4, 2, T(v)); + + boost::geometry::index::insert(t, 0u); + boost::geometry::index::insert(t, 1u); + boost::geometry::index::insert(t, 2u); + boost::geometry::index::insert(t, 3u); + boost::geometry::index::insert(t, 4u); + std::cerr << t; + } +} + +#endif // TESTS_RTREE_NATIVE_HPP diff --git a/tests/translators.hpp b/tests/translators.hpp new file mode 100644 index 000000000..f53681c8c --- /dev/null +++ b/tests/translators.hpp @@ -0,0 +1,72 @@ +#ifndef TESTS_TRANSLATORS_HPP +#define TESTS_TRANSLATORS_HPP + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +void tests_translators_hpp() +{ + std::cout << "tests/translators.hpp\n"; + + typedef boost::geometry::model::point P; + typedef boost::geometry::model::box

B; + typedef boost::geometry::index::rtree I; + + using namespace boost::geometry; + + index::translator::def

p; + index::translator::def pp; + index::translator::def*> pip; + index::translator::def< boost::shared_ptr

> sp; + index::translator::def< std::vector

::iterator > ip; + index::translator::def< std::map::iterator > mip; + index::translator::def< std::pair > ppi; + index::translator::def< boost::shared_ptr< std::pair > > spip; + index::translator::def< boost::shared_ptr< std::pair > > sppi; + index::translator::def< boost::scoped_ptr< std::pair > > scppi; + index::translator::def< boost::scoped_ptr< std::pair > > scpip; + + P tmp_p; + boost::shared_ptr

tmp_sp(new P()); + std::vector

tmp_v(1); + std::map tmp_m; + tmp_m.insert(std::pair(0, P())); + std::pair tmp_pip; + boost::shared_ptr< std::pair > tmp_spip(new std::pair(0, P())); + boost::shared_ptr< std::pair > tmp_sppi(new std::pair(P(), 0)); + boost::scoped_ptr< std::pair > tmp_scpip(new std::pair(0, P())); + boost::scoped_ptr< std::pair > tmp_scppi(new std::pair(P(), 0)); + + tmp_p = p(P()); + tmp_p = pp(&tmp_p); + tmp_p = pip(&tmp_pip); + tmp_p = sp(tmp_sp); + tmp_p = ip(tmp_v.begin()); + tmp_p = mip(tmp_m.begin()); + tmp_p = ppi(std::pair(P(), 0)); + tmp_p = spip(tmp_spip); + tmp_p = sppi(tmp_sppi); + tmp_p = scpip(tmp_scpip); + tmp_p = scppi(tmp_scppi); + + //index::translator::def d; // error + //index::translator::def< model::segment

> d; // error + + index::translator::def< std::pair, B> > d; + index::translator::def< std::pair > > dd; + + B tmp_b; + tmp_b = d( std::pair, B>() ); + tmp_b = dd( std::pair >() ); +} + +#endif // TESTS_TRANSLATORS_HPP