From 31fe43b5efaa4dd514bd7c884a391aa99d9b8380 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 2 Jun 2015 00:01:52 +0300 Subject: [PATCH 01/26] [algorithms][expand] add range of dimensions as template parameters to dispatch::expand<>; update implementation to follow the design of implementing expand wrt a range of dimensions; --- .../geometry/algorithms/detail/expand/box.hpp | 40 +++- .../algorithms/detail/expand/indexed.hpp | 6 +- .../algorithms/detail/expand/point.hpp | 220 ++++++++++-------- .../algorithms/detail/expand/segment.hpp | 43 +++- .../geometry/algorithms/dispatch/expand.hpp | 5 + 5 files changed, 204 insertions(+), 110 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/expand/box.hpp b/include/boost/geometry/algorithms/detail/expand/box.hpp index 94ea10d50..a9581a814 100644 --- a/include/boost/geometry/algorithms/detail/expand/box.hpp +++ b/include/boost/geometry/algorithms/detail/expand/box.hpp @@ -20,6 +20,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP +#include #include #include @@ -38,19 +39,27 @@ namespace boost { namespace geometry namespace detail { namespace expand { - +template struct box_on_spheroid { template static inline void apply(BoxOut& box_out, BoxIn const& box_in) { + typedef detail::envelope::envelope_box + < + Dimension, DimensionCount, CS_Tag + > envelope_box; + // normalize both boxes and convert box-in to be of type of box-out BoxOut mbrs[2]; - detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]); - detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]); + envelope_box::apply(box_in, mbrs[0]); + envelope_box::apply(box_out, mbrs[1]); // compute the envelope of the two boxes - detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); + detail::envelope::envelope_range_of_boxes + < + Dimension, DimensionCount + >::apply(mbrs, box_out); } }; @@ -67,38 +76,53 @@ namespace dispatch template < typename BoxOut, typename BoxIn, + std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater, typename CSTagOut, typename CSTag > struct expand < - BoxOut, BoxIn, StrategyLess, StrategyGreater, + BoxOut, BoxIn, + Dimension, DimensionCount, StrategyLess, StrategyGreater, box_tag, box_tag, CSTagOut, CSTag - > : detail::expand::expand_indexed + > : detail::expand::expand_indexed + < + Dimension, DimensionCount, StrategyLess, StrategyGreater + > {}; template < typename BoxOut, typename BoxIn, + std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater > struct expand < - BoxOut, BoxIn, StrategyLess, StrategyGreater, + BoxOut, BoxIn, + Dimension, DimensionCount, StrategyLess, StrategyGreater, box_tag, box_tag, spherical_equatorial_tag, spherical_equatorial_tag > : detail::expand::box_on_spheroid + < + Dimension, DimensionCount, spherical_equatorial_tag + > {}; template < typename BoxOut, typename BoxIn, + std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater > struct expand < - BoxOut, BoxIn, StrategyLess, StrategyGreater, + BoxOut, BoxIn, + Dimension, DimensionCount, StrategyLess, StrategyGreater, box_tag, box_tag, geographic_tag, geographic_tag > : detail::expand::box_on_spheroid + < + Dimension, DimensionCount, geographic_tag + > {}; diff --git a/include/boost/geometry/algorithms/detail/expand/indexed.hpp b/include/boost/geometry/algorithms/detail/expand/indexed.hpp index 10b85b183..6eae62398 100644 --- a/include/boost/geometry/algorithms/detail/expand/indexed.hpp +++ b/include/boost/geometry/algorithms/detail/expand/indexed.hpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -113,6 +112,7 @@ struct indexed_loop // Changes a box such that the other box is also contained by the box template < + std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater > struct expand_indexed @@ -123,13 +123,13 @@ struct expand_indexed indexed_loop < StrategyLess, StrategyGreater, - 0, 0, dimension::type::value + 0, Dimension, DimensionCount >::apply(box, geometry); indexed_loop < StrategyLess, StrategyGreater, - 1, 0, dimension::type::value + 1, Dimension, DimensionCount >::apply(box, geometry); } }; diff --git a/include/boost/geometry/algorithms/detail/expand/point.hpp b/include/boost/geometry/algorithms/detail/expand/point.hpp index a510e37ed..e23e4bd91 100644 --- a/include/boost/geometry/algorithms/detail/expand/point.hpp +++ b/include/boost/geometry/algorithms/detail/expand/point.hpp @@ -23,8 +23,10 @@ #include #include +#include +#include + #include -#include #include #include #include @@ -33,14 +35,10 @@ #include #include -#include #include -#include -#include - #include -#include +#include #include @@ -53,11 +51,86 @@ namespace detail { namespace expand { -struct point_on_spheroid +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t Dimension, std::size_t DimensionCount, + typename CS_Tag +> +struct point_loop +{ + template + static inline void apply(Box& box, Point const& source) + { + typedef typename strategy::compare::detail::select_strategy + < + StrategyLess, 1, Point, Dimension + >::type less_type; + + typedef typename strategy::compare::detail::select_strategy + < + StrategyGreater, -1, Point, Dimension + >::type greater_type; + + typedef typename select_coordinate_type::type coordinate_type; + + less_type less; + greater_type greater; + + coordinate_type const coord = get(source); + + if (less(coord, get(box))) + { + set(box, coord); + } + + if (greater(coord, get(box))) + { + set(box, coord); + } + + point_loop + < + StrategyLess, StrategyGreater, Dimension + 1, DimensionCount, + CS_Tag + >::apply(box, source); + } +}; + + +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t DimensionCount, typename CS_Tag +> +struct point_loop + < + StrategyLess, StrategyGreater, DimensionCount, DimensionCount, + CS_Tag + > +{ + template + static inline void apply(Box&, Point const&) {} +}; + + +// specialization for the spherical equatorial coordinate system +template +< + typename StrategyLess, + typename StrategyGreater, + std::size_t DimensionCount +> +struct point_loop + < + StrategyLess, StrategyGreater, 0, DimensionCount, + spherical_equatorial_tag + > { template static inline void apply(Box& box, Point const& point) { + typedef typename point_type::type box_point_type; typedef typename coordinate_type::type box_coordinate_type; typedef math::detail::constants_on_spheroid @@ -70,9 +143,9 @@ struct point_on_spheroid Point p_normalized = detail::return_normalized(point); detail::normalize(box, box); - // transform input point to be the same type as the box point - typename point_type::type box_point; - geometry::transform(p_normalized, box_point); + // transform input point to be of the same type as the box point + box_point_type box_point; + detail::envelope::transform_units(p_normalized, box_point); box_coordinate_type p_lon = geometry::get<0>(box_point); box_coordinate_type p_lat = geometry::get<1>(box_point); @@ -89,11 +162,8 @@ struct point_on_spheroid // south pole; the only important coordinate here is the // pole's latitude, as the longitude can be anything; // we, thus, take into account the point's latitude only and return - assign_values(box, - b_lon_min, - (std::min)(p_lat, b_lat_min), - b_lon_max, - (std::max)(p_lat, b_lat_max)); + geometry::set(box, (std::min)(p_lat, b_lat_min)); + geometry::set(box, (std::max)(p_lat, b_lat_max)); return; } @@ -104,11 +174,10 @@ struct point_on_spheroid // the only important coordinate here is the pole's latitude, // as the longitude can be anything; // we thus take into account the box's latitude only and return - assign_values(box, - p_lon, - (std::min)(p_lat, b_lat_min), - p_lon, - (std::max)(p_lat, b_lat_max)); + geometry::set(box, p_lon); + geometry::set(box, (std::min)(p_lat, b_lat_min)); + geometry::set(box, p_lon); + geometry::set(box, (std::max)(p_lat, b_lat_max)); return; } @@ -151,56 +220,36 @@ struct point_on_spheroid } } - assign_values(box, b_lon_min, b_lat_min, b_lon_max, b_lat_max); + geometry::set(box, b_lon_min); + geometry::set(box, b_lat_min); + geometry::set(box, b_lon_max); + geometry::set(box, b_lat_max); + + point_loop + < + StrategyLess, StrategyGreater, 2, DimensionCount, + spherical_equatorial_tag + >::apply(box, point); } }; +// specializations for the geographic coordinate system template < typename StrategyLess, typename StrategyGreater, std::size_t Dimension, std::size_t DimensionCount > struct point_loop -{ - template - static inline void apply(Box& box, Point const& source) - { - typedef typename strategy::compare::detail::select_strategy - < - StrategyLess, 1, Point, Dimension - >::type less_type; - - typedef typename strategy::compare::detail::select_strategy - < - StrategyGreater, -1, Point, Dimension - >::type greater_type; - - typedef typename select_coordinate_type::type coordinate_type; - - less_type less; - greater_type greater; - - coordinate_type const coord = get(source); - - if (less(coord, get(box))) - { - set(box, coord); - } - - if (greater(coord, get(box))) - { - set(box, coord); - } - - point_loop - < - StrategyLess, StrategyGreater, - Dimension + 1, DimensionCount - >::apply(box, source); - } -}; - + < + StrategyLess, StrategyGreater, Dimension, DimensionCount, + geographic_tag + > : point_loop + < + StrategyLess, StrategyGreater, Dimension, DimensionCount, + spherical_equatorial_tag + > +{}; template < @@ -208,12 +257,14 @@ template > struct point_loop < - StrategyLess, StrategyGreater, DimensionCount, DimensionCount - > -{ - template - static inline void apply(Box&, Point const&) {} -}; + StrategyLess, StrategyGreater, DimensionCount, DimensionCount, + geographic_tag + > : point_loop + < + StrategyLess, StrategyGreater, DimensionCount, DimensionCount, + spherical_equatorial_tag + > +{}; }} // namespace detail::expand @@ -223,47 +274,30 @@ struct point_loop namespace dispatch { + // Box + point -> new box containing also point template < typename BoxOut, typename Point, + std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater, typename CSTagOut, typename CSTag > struct expand < - BoxOut, Point, StrategyLess, StrategyGreater, + BoxOut, Point, + Dimension, DimensionCount, StrategyLess, StrategyGreater, box_tag, point_tag, CSTagOut, CSTag > : detail::expand::point_loop < - StrategyLess, StrategyGreater, - 0, dimension::type::value + StrategyLess, StrategyGreater, Dimension, DimensionCount, CSTag > -{}; +{ + BOOST_MPL_ASSERT_MSG((boost::is_same::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types())); +}; -template -< - typename BoxOut, typename Point, - typename StrategyLess, typename StrategyGreater -> -struct expand - < - BoxOut, Point, StrategyLess, StrategyGreater, - box_tag, point_tag, spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::point_on_spheroid -{}; - -template -< - typename BoxOut, typename Point, - typename StrategyLess, typename StrategyGreater -> -struct expand - < - BoxOut, Point, StrategyLess, StrategyGreater, - box_tag, point_tag, geographic_tag, geographic_tag - > : detail::expand::point_on_spheroid -{}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/algorithms/detail/expand/segment.hpp b/include/boost/geometry/algorithms/detail/expand/segment.hpp index 917ab2002..411e698a2 100644 --- a/include/boost/geometry/algorithms/detail/expand/segment.hpp +++ b/include/boost/geometry/algorithms/detail/expand/segment.hpp @@ -22,9 +22,13 @@ #include +#include +#include #include + #include #include + #include @@ -36,14 +40,31 @@ namespace detail { namespace expand { +template struct segment_on_spheroid { template static inline void apply(Box& box, Segment const& segment) { - Box segment_envelope; - dispatch::envelope::apply(segment, segment_envelope); - box_on_spheroid::apply(box, segment_envelope); + Box mbrs[2]; + + // compute the envelope of the segment + dispatch::envelope + < + Segment, Dimension, DimensionCount + >::apply(segment, mbrs[0]); + + // normalize the box + detail::envelope::envelope_box + < + Dimension, DimensionCount, CS_Tag + >::apply(box, mbrs[1]); + + // compute the envelope of the two boxes + detail::envelope::envelope_range_of_boxes + < + Dimension, DimensionCount + >::apply(mbrs, box); } }; @@ -59,27 +80,37 @@ namespace dispatch template < typename Box, typename Segment, + std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater, typename CSTagOut, typename CSTag > struct expand < - Box, Segment, StrategyLess, StrategyGreater, + Box, Segment, + Dimension, DimensionCount, StrategyLess, StrategyGreater, box_tag, segment_tag, CSTagOut, CSTag - > : detail::expand::expand_indexed + > : detail::expand::expand_indexed + < + Dimension, DimensionCount, StrategyLess, StrategyGreater + > {}; template < typename Box, typename Segment, + std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater > struct expand < - Box, Segment, StrategyLess, StrategyGreater, + Box, Segment, + Dimension, DimensionCount, StrategyLess, StrategyGreater, box_tag, segment_tag, spherical_equatorial_tag, spherical_equatorial_tag > : detail::expand::segment_on_spheroid + < + Dimension, DimensionCount, spherical_equatorial_tag + > {}; diff --git a/include/boost/geometry/algorithms/dispatch/expand.hpp b/include/boost/geometry/algorithms/dispatch/expand.hpp index e290080ac..3aa5f67b1 100644 --- a/include/boost/geometry/algorithms/dispatch/expand.hpp +++ b/include/boost/geometry/algorithms/dispatch/expand.hpp @@ -20,6 +20,9 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP #define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP +#include + +#include #include #include @@ -39,6 +42,8 @@ namespace dispatch template < typename GeometryOut, typename Geometry, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension::value, typename StrategyLess = strategy::compare::default_strategy, typename StrategyGreater = strategy::compare::default_strategy, typename TagOut = typename tag::type, From a8c1eeaab31345804e7164374749c93aaddf5f76 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 2 Jun 2015 00:07:04 +0300 Subject: [PATCH 02/26] [algorithms][envelope] add range of dimensions as template parameters to dispatch::envelope<>; update implementation to follow the design of implementing envelope wrt a range of dimensions; --- .../algorithms/detail/envelope/box.hpp | 134 ++++++++++-- .../detail/envelope/implementation.hpp | 61 ++++-- .../algorithms/detail/envelope/linestring.hpp | 74 +++++-- .../detail/envelope/multilinestring.hpp | 78 +++++-- .../algorithms/detail/envelope/multipoint.hpp | 118 ++++++++--- .../algorithms/detail/envelope/point.hpp | 87 +++++--- .../algorithms/detail/envelope/range.hpp | 28 ++- .../detail/envelope/range_of_boxes.hpp | 105 ++++++++-- .../algorithms/detail/envelope/segment.hpp | 98 ++++++--- .../detail/envelope/transform_units.hpp | 102 +++++++++ .../geometry/algorithms/dispatch/envelope.hpp | 7 +- .../views/detail/two_dimensional_view.hpp | 194 ++++++++++++++++++ 12 files changed, 909 insertions(+), 177 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/envelope/transform_units.hpp create mode 100644 include/boost/geometry/views/detail/two_dimensional_view.hpp diff --git a/include/boost/geometry/algorithms/detail/envelope/box.hpp b/include/boost/geometry/algorithms/detail/envelope/box.hpp index 0b3f17709..d65fae019 100644 --- a/include/boost/geometry/algorithms/detail/envelope/box.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/box.hpp @@ -19,15 +19,17 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP +#include + #include #include #include -#include +#include -#include -#include +#include #include +#include #include @@ -40,36 +42,124 @@ namespace detail { namespace envelope { -struct envelope_box_on_spheroid +template +< + std::size_t Index, + std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> +struct envelope_indexed_box { - template + template static inline void apply(BoxIn const& box_in, BoxOut& mbr) { - BoxIn box_in_normalized = detail::return_normalized(box_in); + detail::indexed_point_view box_in_corner(box_in); + detail::indexed_point_view mbr_corner(mbr); - geometry::transform(box_in_normalized, mbr); + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(box_in_corner, mbr_corner); } }; +template +< + std::size_t Index, + std::size_t DimensionCount +> +struct envelope_indexed_box +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { -template + // transform() does not work with boxes of dimension higher + // than 2; to account for such boxes we transform the min/max + // points of the boxes using the indexed_point_view + detail::indexed_point_view box_in_corner(box_in); + detail::indexed_point_view mbr_corner(mbr); + + // first transform the units + transform_units(box_in_corner, mbr_corner); + + // now transform the remaining coordinates + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + 2, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + +template +< + std::size_t Index, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope_indexed_box + : envelope_indexed_box + < + Index, Dimension, DimensionCount, spherical_equatorial_tag + > +{}; + + +template +< + typename std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> struct envelope_box { template static inline void apply(BoxIn const& box_in, BoxOut& mbr) { - geometry::convert(box_in, mbr); + envelope_indexed_box + < + min_corner, Dimension, DimensionCount, CS_Tag + >::apply(box_in, mbr); + + envelope_indexed_box + < + max_corner, Dimension, DimensionCount, CS_Tag + >::apply(box_in, mbr); } }; -template <> -struct envelope_box - : envelope_box_on_spheroid -{}; -template <> -struct envelope_box - : envelope_box_on_spheroid +template +struct envelope_box<0, DimensionCount, spherical_equatorial_tag> +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + BoxIn box_in_normalized = detail::return_normalized(box_in); + + envelope_indexed_box + < + min_corner, 0, DimensionCount, spherical_equatorial_tag + >::apply(box_in_normalized, mbr); + + envelope_indexed_box + < + max_corner, 0, DimensionCount, spherical_equatorial_tag + >::apply(box_in_normalized, mbr); + } +}; + + +template +struct envelope_box<0, DimensionCount, geographic_tag> + : envelope_box<0, DimensionCount, spherical_equatorial_tag> {}; @@ -81,9 +171,15 @@ namespace dispatch { -template -struct envelope - : detail::envelope::envelope_box::type> +template +< + typename Box, + std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> +struct envelope + : detail::envelope::envelope_box {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp index c88adac7a..40027ec46 100644 --- a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -19,11 +19,11 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP +#include + #include #include -#include - #include #include #include @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -43,25 +44,44 @@ namespace detail { namespace envelope { +template +< + typename Geometry, std::size_t Dimension, std::size_t DimensionCount +> struct exterior_ring_expand_policy { - template + template static inline void apply(Box& mbr, Geometry const& geometry) { Box ring_mbr; - envelope_range<>::apply(exterior_ring(geometry), ring_mbr); - geometry::expand(mbr, ring_mbr); + envelope_range + < + typename ring_type::type, + Dimension, + DimensionCount + >::apply(exterior_ring(geometry), ring_mbr); + + dispatch::expand + < + Box, Box, Dimension, DimensionCount + >::apply(mbr, ring_mbr); } }; +template struct envelope_polygon { template static inline void apply(Polygon const& poly, Box& mbr) { // For polygon, inspecting outer ring is sufficient - envelope_range<>::apply(exterior_ring(poly), mbr); + envelope_range + < + typename ring_type::type, + Dimension, + DimensionCount + >::apply(exterior_ring(poly), mbr); } }; @@ -75,23 +95,36 @@ namespace dispatch { -template -struct envelope - : detail::envelope::envelope_range<> +template +struct envelope + : detail::envelope::envelope_range {}; -template -struct envelope - : detail::envelope::envelope_polygon +template +struct envelope + : detail::envelope::envelope_polygon {}; -template -struct envelope +template +< + typename MultiPolygon, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope : detail::envelope::envelope_range < + MultiPolygon, + Dimension, + DimensionCount, detail::envelope::exterior_ring_expand_policy + < + typename boost::range_value::type, + Dimension, + DimensionCount + > > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp index 99333f38d..205120b32 100644 --- a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp @@ -19,6 +19,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP +#include #include #include @@ -34,7 +35,6 @@ #include -#include #include #include @@ -51,7 +51,19 @@ namespace detail { namespace envelope { +template +< + typename Linear, + std::size_t Dimension, + std::size_t DimensionCount, + typename ExpandPolicy +> struct envelope_linear_on_spheroid + : envelope_range +{}; + +template +struct envelope_linear_on_spheroid { template static inline OutputIterator push_interval(Longitude const& lon1, @@ -81,7 +93,7 @@ struct envelope_linear_on_spheroid return oit; } - template + template static inline void apply(Linear const& linear, Box& mbr) { typedef typename coordinate_type::type box_coordinate_type; @@ -109,7 +121,9 @@ struct envelope_linear_on_spheroid Box segment_mbr; dispatch::envelope < - typename std::iterator_traits::value_type + typename std::iterator_traits::value_type, + 0, + DimensionCount >::apply(*seg_it, segment_mbr); oit = push_interval @@ -145,22 +159,19 @@ struct envelope_linear_on_spheroid typename coordinate_system::type::units >::apply(longitude_intervals, lon_min, lon_max); - assign_values(mbr, lon_min, lat_min, lon_max, lat_max); + geometry::set(mbr, lon_min); + geometry::set(mbr, lat_min); + geometry::set(mbr, lon_max); + geometry::set(mbr, lat_max); + + envelope_range + < + Linear, 2, DimensionCount, ExpandPolicy + >::apply(linear, mbr); } }; -template -struct envelope_linestring - : envelope_range<> -{}; - -template <> -struct envelope_linestring - : envelope_linear_on_spheroid -{}; - - }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -169,11 +180,38 @@ struct envelope_linestring namespace dispatch { -template -struct envelope - : detail::envelope::envelope_linestring::type> + +template +< + typename Linestring, + std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> +struct envelope + : detail::envelope::envelope_range {}; +template +< + typename Linestring, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope + < + Linestring, Dimension, DimensionCount, + linestring_tag, spherical_equatorial_tag + > : detail::envelope::envelope_linear_on_spheroid + < + Linestring, + Dimension, + DimensionCount, + detail::envelope::default_expand_policy + > +{}; + + } // namespace dispatch #endif diff --git a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp index fc15baa47..df4cd06ff 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp @@ -19,13 +19,14 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP +#include + #include #include -#include - #include #include +#include #include @@ -38,42 +39,79 @@ namespace detail { namespace envelope { +template struct envelope_range_expand_policy { template static inline void apply(Box& mbr, Geometry const& geometry) { - Box mbr2; - envelope_range<>::apply(geometry, mbr2); - geometry::expand(mbr, mbr2); + Box helper_mbr; + envelope_range + < + Geometry, Dimension, DimensionCount + >::apply(geometry, helper_mbr); + + dispatch::expand + < + Box, Box, Dimension, DimensionCount + >::apply(mbr, helper_mbr); } }; -template -struct envelope_multilinestring - : envelope_range -{}; - -template <> -struct envelope_multilinestring - : envelope_linear_on_spheroid -{}; - - }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL + #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -struct envelope - : detail::envelope::envelope_multilinestring +template +< + typename MultiLinestring, + std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> +struct envelope + < + MultiLinestring, + Dimension, DimensionCount, + multi_linestring_tag, CS_Tag + > : detail::envelope::envelope_range < - typename cs_tag::type + MultiLinestring, + Dimension, + DimensionCount, + detail::envelope::envelope_range_expand_policy + < + Dimension, DimensionCount + > + > +{}; + +template +< + typename MultiLinestring, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope + < + MultiLinestring, + Dimension, DimensionCount, + multi_linestring_tag, spherical_equatorial_tag + > : detail::envelope::envelope_linear_on_spheroid + < + MultiLinestring, + Dimension, + DimensionCount, + detail::envelope::envelope_range_expand_policy + < + Dimension, DimensionCount + > > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp index 92dc21148..ea01218b8 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -10,6 +10,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP +#include #include #include #include @@ -27,14 +28,11 @@ #include -#include - -#include -#include - #include +#include #include + #include @@ -46,21 +44,33 @@ namespace detail { namespace envelope { -class envelope_multipoint_on_spheroid +template +< + typename MultiPoint, + std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> +struct envelope_multipoint_on_spheroid + : envelope_range +{}; + +template +class envelope_multipoint_on_spheroid { private: - template + template struct coordinate_less { template inline bool operator()(Point const& point1, Point const& point2) const { - return math::smaller(geometry::get(point1), - geometry::get(point2)); + return math::smaller(geometry::get(point1), + geometry::get(point2)); } }; - template + template static inline void analyze_point_coordinates(MultiPoint const& multipoint, bool& has_south_pole, bool& has_north_pole, @@ -224,7 +234,7 @@ private: } public: - template + template static inline void apply(MultiPoint const& multipoint, Box& mbr) { typedef typename point_type::type point_type; @@ -246,7 +256,9 @@ public: { return dispatch::envelope < - typename boost::range_value::type + typename boost::range_value::type, + 0, + DimensionCount >::apply(range::front(multipoint), mbr); } @@ -301,16 +313,36 @@ public: lat_max); } - typename helper_geometry + typedef typename helper_geometry < Box, coordinate_type, typename coordinate_system::type::units - >::type helper_mbr; + >::type helper_box_type; - assign_values(helper_mbr, lon_min, lat_min, lon_max, lat_max); + helper_box_type helper_mbr; - geometry::transform(helper_mbr, mbr); + geometry::set(helper_mbr, lon_min); + geometry::set(helper_mbr, lat_min); + geometry::set(helper_mbr, lon_max); + geometry::set(helper_mbr, lat_max); + + // compute envelope for higher coordinates + envelope_multipoint_on_spheroid + < + MultiPoint, 2, DimensionCount, CS_Tag + >::apply(multipoint, helper_mbr); + + // now transform to output MBR (per index) + envelope_indexed_box + < + min_corner, 0, DimensionCount, CS_Tag + >::apply(helper_mbr, mbr); + + envelope_indexed_box + < + max_corner, 0, DimensionCount, CS_Tag + >::apply(helper_mbr, mbr); } }; @@ -318,24 +350,60 @@ public: }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL + + #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -struct envelope - : detail::envelope::envelope_range<> +template +< + typename MultiPoint, + std::size_t Dimension, + std::size_t DimensionCount, + typename CSTag +> +struct envelope + < + MultiPoint, + Dimension, DimensionCount, + multi_point_tag, CSTag + > : detail::envelope::envelope_range {}; -template -struct envelope - : detail::envelope::envelope_multipoint_on_spheroid +template +< + typename MultiPoint, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope + < + MultiPoint, + Dimension, DimensionCount, + multi_point_tag, spherical_equatorial_tag + > : detail::envelope::envelope_multipoint_on_spheroid + < + MultiPoint, Dimension, DimensionCount, spherical_equatorial_tag + > {}; -template -struct envelope - : detail::envelope::envelope_multipoint_on_spheroid +template +< + typename MultiPoint, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope + < + MultiPoint, + Dimension, DimensionCount, + multi_point_tag, geographic_tag + > : detail::envelope::envelope_multipoint_on_spheroid + < + MultiPoint, Dimension, DimensionCount, geographic_tag + > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/point.hpp b/include/boost/geometry/algorithms/detail/envelope/point.hpp index 9e9b01d22..6fd7f93a5 100644 --- a/include/boost/geometry/algorithms/detail/envelope/point.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/point.hpp @@ -19,17 +19,20 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP +#include + +#include #include #include #include -#include - -#include -#include +#include +#include #include +#include + #include @@ -40,7 +43,34 @@ namespace boost { namespace geometry namespace detail { namespace envelope { -struct envelope_point_on_spheroid + +template +struct envelope_one_point +{ + template + static inline void apply(Point const& point, Box& mbr) + { + detail::indexed_point_view box_corner(mbr); + detail::conversion::point_to_point + < + Point, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(point, box_corner); + } + + template + static inline void apply(Point const& point, Box& mbr) + { + apply(point, mbr); + apply(point, mbr); + } +}; + + +template +struct envelope_one_point<0, DimensionCount, spherical_equatorial_tag> { template static inline void apply(Point const& point, Box& mbr) @@ -49,33 +79,28 @@ struct envelope_point_on_spheroid typename point_type::type box_point; - // transform input point to a point of the same type as box's point - geometry::transform(normalized_point, box_point); + // transform units of input point to units of a box point + transform_units(normalized_point, box_point); - geometry::convert(box_point, mbr); + geometry::set(mbr, geometry::get<0>(box_point)); + geometry::set(mbr, geometry::get<1>(box_point)); + + geometry::set(mbr, geometry::get<0>(box_point)); + geometry::set(mbr, geometry::get<1>(box_point)); + + envelope_one_point + < + 2, DimensionCount, spherical_equatorial_tag + >::apply(normalized_point, mbr); } }; -template -struct envelope_one_point -{ - template - static inline void apply(Point const& point, Box& mbr) - { - geometry::convert(point, mbr); - } -}; - -template <> -struct envelope_one_point - : envelope_point_on_spheroid +template +struct envelope_one_point + : envelope_one_point {}; -template <> -struct envelope_one_point - : envelope_point_on_spheroid -{}; }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -85,9 +110,15 @@ namespace dispatch { -template -struct envelope - : detail::envelope::envelope_one_point::type> +template +< + typename Point, + std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> +struct envelope + : detail::envelope::envelope_one_point {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/range.hpp b/include/boost/geometry/algorithms/detail/envelope/range.hpp index b2023f338..1ec08717b 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -19,11 +19,15 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP +#include + #include + #include -#include - +#include +#include +#include #include @@ -35,12 +39,16 @@ namespace detail { namespace envelope { +template struct default_expand_policy { template static inline void apply(Box& mbr, Geometry const& geometry) { - geometry::expand(mbr, geometry); + dispatch::expand + < + Box, Geometry, Dimension, DimensionCount + >::apply(mbr, geometry); } }; @@ -55,11 +63,17 @@ inline void envelope_iterators(Iterator first, Iterator last, Box& mbr) } -template +template +< + typename Range, + std::size_t Dimension, + std::size_t DimensionCount, + typename ExpandPolicy = default_expand_policy +> struct envelope_range { /// Calculate envelope of range using a strategy - template + template static inline void apply(Range const& range, Box& mbr) { typename boost::range_iterator::type it @@ -70,7 +84,9 @@ struct envelope_range // initialize box with first element in range dispatch::envelope < - typename boost::range_value::type + typename boost::range_value::type, + Dimension, + DimensionCount >::apply(*it, mbr); // consider now the remaining elements in the range (if any) diff --git a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp index f408aec9b..85fb0fce2 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -23,9 +23,11 @@ #include #include +#include -#include +#include #include +#include namespace boost { namespace geometry @@ -92,8 +94,6 @@ struct envelope_range_of_longitudes Longitude const zero = 0; Longitude const period = constants::period(); - Longitude const min_longitude = constants::min_longitude(); - Longitude const max_longitude = constants::max_longitude(); lon_min = lon_max = zero; @@ -118,12 +118,16 @@ struct envelope_range_of_longitudes max_gap_right); BOOST_ASSERT(! math::larger(lon_min, lon_max)); - BOOST_ASSERT(! math::larger(lon_max, max_longitude)); - BOOST_ASSERT(! math::smaller(lon_min, min_longitude)); + BOOST_ASSERT(! math::larger(lon_max, + constants::max_longitude())); + BOOST_ASSERT(! math::smaller(lon_min, + constants::min_longitude())); BOOST_ASSERT(! math::larger(max_gap_left, max_gap_right)); - BOOST_ASSERT(! math::larger(max_gap_right, max_longitude)); - BOOST_ASSERT(! math::smaller(max_gap_left, min_longitude)); + BOOST_ASSERT(! math::larger(max_gap_right, + constants::max_longitude())); + BOOST_ASSERT(! math::smaller(max_gap_left, + constants::min_longitude())); if (math::larger(max_gap, zero)) { @@ -140,7 +144,73 @@ struct envelope_range_of_longitudes }; +template struct envelope_range_of_boxes +{ + template + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) + { + typedef typename boost::range_value::type box_type; + + typedef typename boost::range_iterator + < + RangeOfBoxes const + >::type iterator_type; + + // first initialize MBR + detail::indexed_point_view mbr_min(mbr); + detail::indexed_point_view mbr_max(mbr); + + detail::indexed_point_view + first_box_min(range::front(range_of_boxes)); + + detail::indexed_point_view + first_box_max(range::front(range_of_boxes)); + + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(first_box_min, mbr_min); + + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(first_box_max, mbr_max); + + // now expand using the remaining boxes + iterator_type it = boost::begin(range_of_boxes); + for (++it; it != boost::end(range_of_boxes); ++it) + { + detail::expand::indexed_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + min_corner, + Dimension, + DimensionCount + >::apply(mbr, *it); + + detail::expand::indexed_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + max_corner, + Dimension, + DimensionCount + >::apply(mbr, *it); + } + } + +}; + +template +struct envelope_range_of_boxes<0, DimensionCount> { template struct latitude_less @@ -217,7 +287,8 @@ struct envelope_range_of_boxes } } - coordinate_type lon_min(0), lon_max(0); + coordinate_type lon_min = 0; + coordinate_type lon_max = 0; envelope_range_of_longitudes < units_type @@ -225,11 +296,19 @@ struct envelope_range_of_boxes // do not convert units; conversion will be performed at a // higher level - assign_values(mbr, - lon_min, - geometry::get(*it_min), - lon_max, - geometry::get(*it_max)); + + // assign now the min/max longitude/latitude values + detail::indexed_point_view mbr_min(mbr); + detail::indexed_point_view mbr_max(mbr); + + geometry::set<0>(mbr_min, lon_min); + geometry::set<1>(mbr_min, geometry::get(*it_min)); + geometry::set<0>(mbr_max, lon_max); + geometry::set<1>(mbr_max, geometry::get(*it_max)); + + // what remains to be done is to compute the envelope range + // for the remaining dimensions (if any) + envelope_range_of_boxes<2, DimensionCount>::apply(range_of_boxes, mbr); } }; diff --git a/include/boost/geometry/algorithms/detail/envelope/segment.hpp b/include/boost/geometry/algorithms/detail/envelope/segment.hpp index 0b4f803f5..894b71f7c 100644 --- a/include/boost/geometry/algorithms/detail/envelope/segment.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -19,6 +19,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP +#include #include #include @@ -36,15 +37,14 @@ #include -#include - -#include -#include -#include +#include +#include #include #include +#include +#include #include @@ -56,6 +56,22 @@ namespace boost { namespace geometry namespace detail { namespace envelope { + +template +struct envelope_one_segment +{ + template + static inline void apply(Point const& p1, Point const& p2, Box& mbr) + { + envelope_one_point::apply(p1, mbr); + dispatch::expand + < + Box, Point, Dimension, DimensionCount + >::apply(mbr, p2); + } +}; + + // Computes the MBR of a segment given by (lon1, lat1) and (lon2, // lat2), and with azimuths a1 and a2 at the two endpoints of the // segment. @@ -256,29 +272,47 @@ public: { typedef typename coordinate_type::type box_coordinate_type; - typename helper_geometry + typedef typename helper_geometry < Box, box_coordinate_type, radian - >::type radian_mbr; + >::type helper_box_type; + + helper_box_type radian_mbr; apply(lon1, lat1, lon2, lat2); - assign_values(radian_mbr, - boost::numeric_cast(lon1), - boost::numeric_cast(lat1), - boost::numeric_cast(lon2), - boost::numeric_cast(lat2)); + geometry::set + < + min_corner, 0 + >(radian_mbr, boost::numeric_cast(lon1)); - geometry::transform(radian_mbr, mbr); + geometry::set + < + min_corner, 1 + >(radian_mbr, boost::numeric_cast(lat1)); + + geometry::set + < + max_corner, 0 + >(radian_mbr, boost::numeric_cast(lon2)); + + geometry::set + < + max_corner, 1 + >(radian_mbr, boost::numeric_cast(lat2)); + + transform_units(radian_mbr, mbr); } }; -struct envelope_segment_on_spheroid +template +struct envelope_one_segment<0, DimensionCount, spherical_equatorial_tag> { template static inline void apply(Point const& p1, Point const& p2, Box& mbr) { + // first compute the envelope range for the first two coordinates Point p1_normalized = detail::return_normalized(p1); Point p2_normalized = detail::return_normalized(p2); @@ -287,24 +321,16 @@ struct envelope_segment_on_spheroid geometry::get_as_radian<0>(p2_normalized), geometry::get_as_radian<1>(p2_normalized), mbr); + + // now compute the envelope range for coordinates of + // dimension 2 and higher + envelope_one_segment + < + 2, DimensionCount, spherical_equatorial_tag + >::apply(p1, p2, mbr); } }; -template -struct envelope_one_segment -{ - template - static inline void apply(Point const& p1, Point const& p2, Box& mbr) - { - envelope_one_point::apply(p1, mbr); - geometry::expand(mbr, p2); - } -}; - -template <> -struct envelope_one_segment - : envelope_segment_on_spheroid -{}; }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -315,8 +341,14 @@ namespace dispatch { -template -struct envelope +template +< + typename Segment, + std::size_t Dimension, + std::size_t DimensionCount, + typename CS_Tag +> +struct envelope { template static inline void apply(Segment const& segment, Box& mbr) @@ -326,14 +358,14 @@ struct envelope detail::assign_point_from_index<1>(segment, p[1]); detail::envelope::envelope_one_segment < - typename cs_tag::type + Dimension, DimensionCount, CS_Tag >::apply(p[0], p[1], mbr); } }; } // namespace dispatch -#endif +#endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp b/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp new file mode 100644 index 000000000..94f380a1c --- /dev/null +++ b/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp @@ -0,0 +1,102 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +< + typename GeometryIn, + typename GeometryOut, + typename TagIn = typename tag::type, + typename TagOut = typename tag::type +> +struct transform_units_impl + : not_implemented +{}; + +template +struct transform_units_impl +{ + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + detail::two_dimensional_view view_in(point_in); + detail::two_dimensional_view view_out(point_out); + + geometry::transform(view_in, view_out); + } +}; + +template +struct transform_units_impl +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + typedef detail::indexed_point_view view_in_type; + typedef detail::indexed_point_view view_out_type; + + view_in_type view_in(box_in); + view_out_type view_out(box_out); + + transform_units_impl + < + view_in_type, view_out_type + >::apply(view_in, view_out); + } + + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + apply(box_in, box_out); + apply(box_in, box_out); + } +}; + + +// Short utility to transform the units of the first two coordinates of +// geometry_in to the units of geometry_out +template +inline void transform_units(GeometryIn const& geometry_in, + GeometryOut& geometry_out) +{ + transform_units_impl + < + GeometryIn, GeometryOut + >::apply(geometry_in, geometry_out); +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost:geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP diff --git a/include/boost/geometry/algorithms/dispatch/envelope.hpp b/include/boost/geometry/algorithms/dispatch/envelope.hpp index 8b1324d72..3ac238754 100644 --- a/include/boost/geometry/algorithms/dispatch/envelope.hpp +++ b/include/boost/geometry/algorithms/dispatch/envelope.hpp @@ -19,6 +19,9 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP +#include + +#include #include #include @@ -35,8 +38,10 @@ namespace dispatch template < typename Geometry, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension::value, typename Tag = typename tag::type, - typename CSTag = typename cs_tag::type + typename CS_Tag = typename cs_tag::type > struct envelope : not_implemented {}; diff --git a/include/boost/geometry/views/detail/two_dimensional_view.hpp b/include/boost/geometry/views/detail/two_dimensional_view.hpp new file mode 100644 index 000000000..b33ede8e1 --- /dev/null +++ b/include/boost/geometry/views/detail/two_dimensional_view.hpp @@ -0,0 +1,194 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP +#define BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +< + typename Geometry, + std::size_t Dimension1 = 0, + std::size_t Dimension2 = 1, + typename Tag = typename tag::type +> +struct two_dimensional_view + : not_implemented +{}; + + +// View that enables to choose two dimensions of a point and see it as +// a two-dimensional point +template +struct two_dimensional_view +{ + BOOST_MPL_ASSERT_MSG((Dimension1 < dimension::value), + COORDINATE_DIMENSION1_IS_LARGER_THAN_POINT_DIMENSION, + (boost::mpl::int_)); + + BOOST_MPL_ASSERT_MSG((Dimension2 < dimension::value), + COORDINATE_DIMENSION2_IS_LARGER_THAN_POINT_DIMENSION, + (boost::mpl::int_)); + + two_dimensional_view(Point& point) + : m_point(point) + {} + + Point& m_point; +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS +namespace traits +{ + + +template +struct tag + < + geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + > + > +{ + typedef point_tag type; +}; + +template +struct coordinate_system + < + geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + > + > : coordinate_system::type> +{}; + +template +struct coordinate_type + < + geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + > + > : coordinate_type::type> +{}; + +template +struct dimension + < + geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + > + > : boost::mpl::int_<2> +{}; + +template +struct point_type + < + geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + > + > +{ + typedef typename geometry::point_type::type type; +}; + + +template +struct access + < + geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + >, + 0 + > +{ + typedef typename geometry::coordinate_type::type coordinate_type; + typedef geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + > view_type; + + static inline coordinate_type get(view_type const& view) + { + return geometry::get(view.m_point); + } + + static inline void set(view_type& view, coordinate_type const& value) + { + geometry::set(view.m_point, value); + } +}; + +template +struct access + < + geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + >, + 1 + > +{ + typedef typename geometry::coordinate_type::type coordinate_type; + typedef geometry::detail::two_dimensional_view + < + Point, Dimension1, Dimension2, point_tag + > view_type; + + static inline coordinate_type get(view_type const& view) + { + return geometry::get(view.m_point); + } + + static inline void set(view_type& view, coordinate_type const& value) + { + geometry::set(view.m_point, value); + } +}; + + +} // namespace traits +#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP From 5b370fdeb549e0850099133ddcbaafea0b5bc980 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 2 Jun 2015 00:07:40 +0300 Subject: [PATCH 03/26] [algorithms][buffer] update use of envelope_range<> (needs more template parameters) --- .../algorithms/detail/buffer/buffered_piece_collection.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 07a87d662..c8c960d94 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -979,8 +979,11 @@ struct buffered_piece_collection return; } - geometry::detail::envelope::envelope_range<>::apply(pc.robust_ring, - pc.robust_envelope); + geometry::detail::envelope::envelope_range + < + typename piece::piece_robust_ring_type, + 0, dimension::value + >::apply(pc.robust_ring, pc.robust_envelope); geometry::assign_inverse(pc.robust_offsetted_envelope); for (int i = 0; i < pc.offsetted_count; i++) From d117ade1f7680e994a04006e8a7dfbed2c6b6218 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 2 Jun 2015 00:16:37 +0300 Subject: [PATCH 04/26] [test][algorithms][envelope][expand] move common code to separate file; add test cases involving geometries with height; add test cases for geometries in the geographic coordinate system; --- test/algorithms/envelope_on_spheroid.cpp | 484 +++++++++++------- test/algorithms/expand_on_spheroid.cpp | 438 ++++++++++------ .../test_envelope_expand_on_spheroid.hpp | 192 +++++++ 3 files changed, 754 insertions(+), 360 deletions(-) create mode 100644 test/algorithms/test_envelope_expand_on_spheroid.hpp diff --git a/test/algorithms/envelope_on_spheroid.cpp b/test/algorithms/envelope_on_spheroid.cpp index 1f3aa4114..6892bb620 100644 --- a/test/algorithms/envelope_on_spheroid.cpp +++ b/test/algorithms/envelope_on_spheroid.cpp @@ -24,6 +24,7 @@ #include +#include #include #include @@ -38,125 +39,53 @@ #include #include - -typedef bg::cs::spherical_equatorial se_rad_type; -typedef bg::cs::spherical_equatorial se_deg_type; - -typedef bg::model::point rad_point_type; -typedef bg::model::point deg_point_type; - -typedef bg::model::multi_point rad_multipoint_type; -typedef bg::model::multi_point deg_multipoint_type; - -typedef bg::model::segment rad_segment_type; -typedef bg::model::segment deg_segment_type; - -typedef bg::model::box rad_box_type; -typedef bg::model::box deg_box_type; - -typedef bg::model::linestring rad_linestring_type; -typedef bg::model::linestring deg_linestring_type; - -typedef bg::model::multi_linestring - < - rad_linestring_type - > rad_multilinestring_type; - -typedef bg::model::multi_linestring - < - deg_linestring_type - > deg_multilinestring_type; - - -typedef bg::model::ring rad_cw_ring_type; -typedef bg::model::ring deg_cw_ring_type; - -typedef bg::model::ring rad_ccw_ring_type; -typedef bg::model::ring deg_ccw_ring_type; - - -template -char const* units2string() -{ - if (BOOST_GEOMETRY_CONDITION((boost::is_same::value))) - { - return "degrees"; - } - return "radians"; -} - -template -struct other_system_info -{ - typedef bg::degree units; - typedef bg::cs::spherical_equatorial type; - - template - static inline T convert(T const& value) - { - return value * bg::math::r2d(); - } -}; - -template <> -struct other_system_info -{ - typedef bg::radian units; - typedef bg::cs::spherical_equatorial type; - - template - static inline T convert(T const& value) - { - return value * bg::math::d2r(); - } -}; - - -class equals_with_tolerance -{ -private: - double m_tolerance; - - template - static inline T const& get_max(T const& a, T const& b, T const& c) - { - return (std::max)((std::max)(a, b), c); - } - - template - static inline bool check_close(T const& a, T const& b, double tol) - { - return (a == b) - || (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0)); - } - -public: - equals_with_tolerance(double tolerance) : m_tolerance(tolerance) {} - - template - inline bool operator()(T const& value1, T const& value2) const - { - return check_close(value1, value2, m_tolerance); - } -}; - - -template -inline bool box_equals(Box1 const& box1, Box2 const& box2, double tol) -{ - equals_with_tolerance equals(tol); - - return equals(bg::get<0, 0>(box1), bg::get<0, 0>(box2)) - && equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2)) - && equals(bg::get<1, 0>(box1), bg::get<1, 0>(box2)) - && equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2)); -} +#include "test_envelope_expand_on_spheroid.hpp" template class envelope_on_spheroid_basic_tester { private: + template + < + typename Geometry, + typename Tag = typename bg::tag::type + > + struct write_geometry + { + template + static inline OutputStream& apply(OutputStream& os, + Geometry const& geometry) + { + os << bg::wkt(geometry); + return os; + } + }; + + template + struct write_geometry + { + template + static inline OutputStream& apply(OutputStream& os, + Segment const& segment) + { + os << "SEGMENT" << bg::dsv(segment); + return os; + } + }; + + template + struct write_geometry + { + template + static inline OutputStream& apply(OutputStream& os, + Box const& box) + { + os << "BOX" << bg::dsv(box); + return os; + } + }; + template static inline void check_message(bool same_boxes, std::string const& case_id, @@ -165,33 +94,12 @@ private: Box const& expected, Box const& detected) { - bool const is_box = boost::is_same - < - typename bg::tag::type, bg::box_tag - >::value; - - bool const is_segment = boost::is_same - < - typename bg::tag::type, bg::segment_tag - >::value; - std::ostringstream stream; stream << "case ID: " << case_id << ", " << "MBR units: " << units_str << "; " << "geometry: "; - if (BOOST_GEOMETRY_CONDITION(is_box)) - { - stream << "BOX" << bg::dsv(geometry); - } - else if (BOOST_GEOMETRY_CONDITION(is_segment)) - { - stream << "SEGMENT" << bg::dsv(geometry); - } - else - { - stream << bg::wkt(geometry); - } + write_geometry::apply(stream, geometry); stream << "; " << "expected: " << bg::dsv(expected) << ", " << "detected: " << bg::dsv(detected); @@ -202,8 +110,8 @@ private: template static inline void base_test(std::string const& case_id, Geometry const& geometry, - double lon_min, double lat_min, - double lon_max, double lat_max, + double lon_min, double lat_min, double height_min, + double lon_max, double lat_max, double height_max, double tolerance) { typedef typename bg::coordinate_system::type::units box_units_type; @@ -214,32 +122,13 @@ private: bg::envelope(geometry, detected); Box expected; - bg::assign_values(expected, lon_min, lat_min, lon_max, lat_max); + initialize_box::apply(expected, + lon_min, lat_min, height_min, + lon_max, lat_max, height_max); #ifdef BOOST_GEOMETRY_TEST_DEBUG - bool const is_box = boost::is_same - < - typename bg::tag::type, bg::box_tag - >::value; - - bool const is_segment = boost::is_same - < - typename bg::tag::type, bg::segment_tag - >::value; - std::cout << "geometry: "; - if (BOOST_GEOMETRY_CONDITION(is_box)) - { - std::cout << "BOX" << bg::dsv(geometry); - } - else if(BOOST_GEOMETRY_CONDITION(is_segment)) - { - std::cout << "SEGMENT" << bg::dsv(geometry); - } - else - { - std::cout << bg::wkt(geometry); - } + write_geometry::apply(std::cout, geometry); std::cout << std::endl << "MBR units: " << units_str @@ -250,7 +139,7 @@ private: << std::endl << std::endl; #endif - check_message(box_equals(detected, expected, tolerance), + check_message(box_equals::apply(detected, expected, tolerance), case_id, units_str, geometry, expected, detected); } @@ -259,13 +148,13 @@ public: template static inline void apply(std::string const& case_id, Geometry const& geometry, - double lon_min, double lat_min, - double lon_max, double lat_max, + double lon_min, double lat_min, double height_min, + double lon_max, double lat_max, double height_max, double tolerance) { typedef other_system_info < - typename bg::coordinate_system::type::units + typename bg::coordinate_system::type > other; typedef bg::model::box @@ -273,7 +162,7 @@ public: bg::model::point < typename bg::coordinate_type::type, - 2, + bg::dimension::value, typename other::type > > other_mbr_type; @@ -284,14 +173,17 @@ public: #endif base_test(case_id, geometry, - lon_min, lat_min, lon_max, lat_max, + lon_min, lat_min, height_min, + lon_max, lat_max, height_max, tolerance); base_test(case_id, geometry, other::convert(lon_min), other::convert(lat_min), + height_min, other::convert(lon_max), other::convert(lat_max), + height_max, tolerance); } }; @@ -331,17 +223,18 @@ struct test_envelope_on_spheroid { static inline void apply(std::string const& case_id, Geometry const& geometry, - double lon_min1, double lat_min1, - double lon_max1, double lat_max1, - double lon_min2, double lat_min2, - double lon_max2, double lat_max2, + double lon_min1, double lat_min1, double height_min1, + double lon_max1, double lat_max1, double height_max1, + double lon_min2, double lat_min2, double height_min2, + double lon_max2, double lat_max2, double height_max2, double tolerance = std::numeric_limits::epsilon()) { envelope_on_spheroid_basic_tester < MBR >::apply(case_id, geometry, - lon_min1, lat_min1, lon_max1, lat_max1, + lon_min1, lat_min1, height_min1, + lon_max1, lat_max1, height_max1, tolerance); if (BOOST_GEOMETRY_CONDITION(TestReverse)) @@ -354,7 +247,8 @@ struct test_envelope_on_spheroid < MBR >::apply(reversed_case_id, reversed_geometry, - lon_min2, lat_min2, lon_max2, lat_max2, + lon_min2, lat_min2, height_min2, + lon_max2, lat_max2, height_max2, tolerance); } @@ -364,6 +258,34 @@ struct test_envelope_on_spheroid #endif } + static inline void apply(std::string const& case_id, + Geometry const& geometry, + double lon_min1, double lat_min1, + double lon_max1, double lat_max1, + double lon_min2, double lat_min2, + double lon_max2, double lat_max2, + double tolerance = std::numeric_limits::epsilon()) + { + apply(case_id, geometry, + lon_min1, lat_min1, 0, lon_max1, lat_max1, 0, + lon_min2, lat_min2, 0, lon_max2, lat_max2, 0, + tolerance); + } + + static inline void apply(std::string const& case_id, + Geometry const& geometry, + double lon_min, double lat_min, double height_min, + double lon_max, double lat_max, double height_max, + double tolerance = std::numeric_limits::epsilon()) + { + apply(case_id, geometry, + lon_min, lat_min, height_min, + lon_max, lat_max, height_max, + lon_min, lat_min, height_min, + lon_max, lat_max, height_max, + tolerance); + } + static inline void apply(std::string const& case_id, Geometry const& geometry, double lon_min, double lat_min, @@ -371,8 +293,7 @@ struct test_envelope_on_spheroid double tolerance = std::numeric_limits::epsilon()) { apply(case_id, geometry, - lon_min, lat_min, lon_max, lat_max, - lon_min, lat_min, lon_max, lat_max, + lon_min, lat_min, 0, lon_max, lat_max, 0, tolerance); } }; @@ -399,7 +320,10 @@ struct test_envelope_on_spheroid std::string ccw_case_id = case_id + "-2ccw"; - deg_ccw_ring_type ccw_ring; + bg::model::ring + < + typename bg::point_type::type, false + > ccw_ring; bg::convert(geometry, ccw_ring); envelope_on_spheroid_basic_tester @@ -429,10 +353,13 @@ struct test_envelope_on_spheroid }; -BOOST_AUTO_TEST_CASE( envelope_point ) +template +void test_envelope_point() { - typedef deg_point_type G; - typedef test_envelope_on_spheroid tester; + typedef bg::model::point point_type; + typedef point_type G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; tester::apply("p01", from_wkt("POINT(10 10)"), @@ -506,11 +433,43 @@ BOOST_AUTO_TEST_CASE( envelope_point ) 0, -90, 0, -90); } +BOOST_AUTO_TEST_CASE( envelope_point ) +{ + test_envelope_point >(); + test_envelope_point >(); +} + + +template +void test_envelope_point_with_height() +{ + typedef bg::model::point point_type; + typedef point_type G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; + + tester::apply("ph01", + from_wkt("POINT(10 10 1256)"), + 10, 10, 1256, 10, 10, 1256); +} + +BOOST_AUTO_TEST_CASE( envelope_point_with_height ) +{ + test_envelope_point_with_height + < + bg::cs::spherical_equatorial + >(); + test_envelope_point_with_height >(); +} + BOOST_AUTO_TEST_CASE( envelope_segment ) { - typedef deg_segment_type G; - typedef test_envelope_on_spheroid tester; + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::segment G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; tester::apply("s01", from_wkt("SEGMENT(10 10,40 40)"), @@ -661,10 +620,31 @@ BOOST_AUTO_TEST_CASE( envelope_segment ) } -BOOST_AUTO_TEST_CASE( envelope_multipoint ) +BOOST_AUTO_TEST_CASE( envelope_segment_with_height ) { - typedef deg_multipoint_type G; - typedef test_envelope_on_spheroid tester; + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::segment G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; + + tester::apply("sh01", + from_wkt("SEGMENT(10 10 567,40 40 1356)"), + 10, 10, 567, 40, 40, 1356); + + tester::apply("sh02", + from_wkt("SEGMENT(10 10 1356,40 40 567)"), + 10, 10, 567, 40, 40, 1356); +} + + +template +void test_envelope_multipoint() +{ + typedef bg::model::point point_type; + typedef bg::model::multi_point G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; tester::apply("mp01", from_wkt("MULTIPOINT(0 0,10 10)"), @@ -791,11 +771,48 @@ BOOST_AUTO_TEST_CASE( envelope_multipoint ) #endif } - -BOOST_AUTO_TEST_CASE( envelope_box ) +BOOST_AUTO_TEST_CASE( envelope_multipoint ) { - typedef deg_box_type G; - typedef test_envelope_on_spheroid tester; + test_envelope_multipoint >(); + test_envelope_multipoint >(); +} + + +template +void test_envelope_multipoint_with_height() +{ + typedef bg::model::point point_type; + typedef bg::model::multi_point G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; + + tester::apply("mph01", + from_wkt("MULTIPOINT(0 0 567,10 10 1456)"), + 0, 0, 567, 10, 10, 1456); + + tester::apply("mph02", + from_wkt("MULTIPOINT(0 0 567,10 10 1456,20 90 967)"), + 0, 0, 567, 10, 90, 1456); +} + +BOOST_AUTO_TEST_CASE( envelope_multipoint_with_height ) +{ + test_envelope_multipoint_with_height + < + bg::cs::spherical_equatorial + >(); + test_envelope_multipoint_with_height >(); +} + + +template +void test_envelope_box() +{ + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::box G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; tester::apply("b01", from_wkt("BOX(10 10,20 20)"), @@ -976,11 +993,49 @@ BOOST_AUTO_TEST_CASE( envelope_box ) 0, -90, 0, -90); } +BOOST_AUTO_TEST_CASE( envelope_box ) +{ + test_envelope_box >(); + test_envelope_box >(); +} + + +template +void test_envelope_box_with_height() +{ + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::box G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; + + tester::apply("bh01", + from_wkt("BOX(10 10 567,20 20 2834)"), + 10, 10, 567, 20, 20, 2834); + + tester::apply("bh02", + from_wkt("BOX(10 10 567,20 20 567)"), + 10, 10, 567, 20, 20, 567); + + tester::apply("bh03", + from_wkt("BOX(0 10 567,170 90 1567)"), + 0, 10, 567, 170, 90, 1567); +} + +BOOST_AUTO_TEST_CASE( envelope_box_with_height ) +{ + test_envelope_box_with_height >(); + test_envelope_box_with_height >(); +} + BOOST_AUTO_TEST_CASE( envelope_linestring ) { - typedef deg_linestring_type G; - typedef test_envelope_on_spheroid tester; + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::linestring G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; tester::apply("l01", from_wkt("LINESTRING(10 15)"), @@ -1090,14 +1145,37 @@ BOOST_AUTO_TEST_CASE( envelope_linestring ) } +BOOST_AUTO_TEST_CASE( envelope_linestring_with_height ) +{ + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::linestring G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; + + tester::apply("lh01", + from_wkt("LINESTRING(10 15 30,20 25 434,30 35 186)"), + 10, 15, 30, 30, 35, 434); +} + + BOOST_AUTO_TEST_CASE( envelope_multilinestring ) { - typedef deg_multilinestring_type G; - typedef test_envelope_on_spheroid tester; + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::multi_linestring > G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; tester::apply("ml01", + from_wkt("MULTILINESTRING((10 15))"), + 10, 15, 10, 15); + +#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS + tester::apply("ml01a", from_wkt("MULTILINESTRING((),(),(10 15),())"), 10, 15, 10, 15); +#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS tester::apply("ml02", from_wkt("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"), @@ -1125,6 +1203,30 @@ BOOST_AUTO_TEST_CASE( envelope_multilinestring ) } +BOOST_AUTO_TEST_CASE( envelope_multilinestring_with_height ) +{ + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::multi_linestring > G; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; + + tester::apply("mlh01", + from_wkt("MULTILINESTRING((10 15 1000))"), + 10, 15, 1000, 10, 15, 1000); + +#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS + tester::apply("mlh01a", + from_wkt("MULTILINESTRING((),(),(10 15 1000),())"), + 10, 15, 1000, 10, 15, 1000); +#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS + + tester::apply("mlh02", + from_wkt("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"), + -10, 25, 300, 260, 80, 700); +} + + #if 0 // unit test for rings de-activated for now (current implementation // for area on the spherical equatorial coordinate system is not complete) diff --git a/test/algorithms/expand_on_spheroid.cpp b/test/algorithms/expand_on_spheroid.cpp index 8199fe842..a4ed6a3e5 100644 --- a/test/algorithms/expand_on_spheroid.cpp +++ b/test/algorithms/expand_on_spheroid.cpp @@ -8,13 +8,14 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html - #ifndef BOOST_TEST_MODULE #define BOOST_TEST_MODULE test_expand_on_spheroid #endif #include +#include + #include #include @@ -23,112 +24,70 @@ #include +#include #include #include #include +#include + #include #include #include +#include #include +#include +#include -typedef bg::cs::spherical_equatorial se_rad_type; -typedef bg::cs::spherical_equatorial se_deg_type; - -typedef bg::model::point rad_point_type; -typedef bg::model::point deg_point_type; - -typedef bg::model::segment rad_segment_type; -typedef bg::model::segment deg_segment_type; - -typedef bg::model::box rad_box_type; -typedef bg::model::box deg_box_type; - - -template -char const* units2string() -{ - if (BOOST_GEOMETRY_CONDITION((boost::is_same::value))) - { - return "degrees"; - } - return "radians"; -} - -template -struct other_system_info -{ - typedef bg::degree units; - typedef bg::cs::spherical_equatorial type; - - template - static inline T convert(T const& value) - { - return value * bg::math::r2d(); - } -}; - -template <> -struct other_system_info -{ - typedef bg::radian units; - typedef bg::cs::spherical_equatorial type; - - template - static inline T convert(T const& value) - { - return value * bg::math::d2r(); - } -}; - - -class equals_with_tolerance -{ -private: - double m_tolerence; - - template - static inline T const& get_max(T const& a, T const& b, T const& c) - { - return (std::max)((std::max)(a, b), c); - } - - template - static inline bool check_close(T const& a, T const& b, double tol) - { - return (a == b) - || (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0)); - } - -public: - equals_with_tolerance(double tolerence) : m_tolerence(tolerence) {} - - template - inline bool operator()(T const& value1, T const& value2) const - { - return check_close(value1, value2, m_tolerence); - } -}; - - -template -inline bool box_equals(Box1 const& box1, Box2 const& box2, double tol) -{ - equals_with_tolerance equals(tol); - - return equals(bg::get<0, 0>(box1), bg::get<0, 0>(box2)) - && equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2)) - && equals(bg::get<1, 0>(box1), bg::get<1, 0>(box2)) - && equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2)); -} +#include "test_envelope_expand_on_spheroid.hpp" class test_expand_on_spheroid { private: + template + < + typename Geometry, + typename Tag = typename bg::tag::type + > + struct write_geometry + { + template + static inline OutputStream& apply(OutputStream& os, + Geometry const& geometry) + { + os << bg::wkt(geometry); + return os; + } + }; + + template + struct write_geometry + { + template + static inline OutputStream& apply(OutputStream& os, + Segment const& segment) + { + os << "SEGMENT" << bg::dsv(segment); + return os; + } + }; + + template + struct write_geometry + { + template + static inline OutputStream& apply(OutputStream& os, + Box const& box) + { + os << "BOX" << bg::dsv(box); + return os; + } + }; + template static inline void check_message(bool same_boxes, std::string const& case_id, @@ -140,34 +99,13 @@ private: Box const& expected2, Box const& detected) { - bool const is_box = boost::is_same - < - typename bg::tag::type, bg::box_tag - >::value; - - bool const is_segment = boost::is_same - < - typename bg::tag::type, bg::segment_tag - >::value; - std::ostringstream stream; stream << "case ID: " << case_id << ", " << "MBR units: " << units_str << "; " << "input box: BOX" << bg::dsv(box) << ", " << "geometry: "; - if (BOOST_GEOMETRY_CONDITION(is_box)) - { - stream << "BOX" << bg::dsv(geometry); - } - else if (BOOST_GEOMETRY_CONDITION(is_segment)) - { - stream << "SEGMENT" << bg::dsv(geometry); - } - else - { - stream << bg::wkt(geometry); - } + write_geometry::apply(stream, geometry); stream << "; " << "expected: " << bg::dsv(expected1); if (expected_are_different) @@ -188,9 +126,13 @@ private: Box const& box, Geometry const& geometry, double lon_min1, double lat_min1, + double height_min1, double lon_max1, double lat_max1, + double height_max1, double lon_min2, double lat_min2, + double height_min2, double lon_max2, double lat_max2, + double height_max2, double tolerance) { typedef typename bg::coordinate_system @@ -209,39 +151,20 @@ private: || (lon_max1 != lon_max2) || (lat_max1 != lat_max2); Box expected1; - bg::assign_values(expected1, - lon_min1, lat_min1, lon_max1, lat_max1); + initialize_box::apply(expected1, + lon_min1, lat_min1, height_min1, + lon_max1, lat_max1, height_max1); Box expected2; - bg::assign_values(expected2, - lon_min2, lat_min2, lon_max2, lat_max2); + initialize_box::apply(expected2, + lon_min2, lat_min2, height_min2, + lon_max2, lat_max2, height_max2); #ifdef BOOST_GEOMETRY_TEST_DEBUG - bool const is_box = boost::is_same - < - typename bg::tag::type, bg::box_tag - >::value; - - bool const is_segment = boost::is_same - < - typename bg::tag::type, bg::segment_tag - >::value; - std::cout << "input box: BOX" << bg::dsv(box) << std::endl; std::cout << "geometry: "; - if (BOOST_GEOMETRY_CONDITION(is_box)) - { - std::cout << "BOX" << bg::dsv(geometry); - } - else if(BOOST_GEOMETRY_CONDITION(is_segment)) - { - std::cout << "SEGMENT" << bg::dsv(geometry); - } - else - { - std::cout << bg::wkt(geometry); - } + write_geometry::apply(std::cout, geometry); std::cout << std::endl << "MBR units: " << units_str @@ -257,11 +180,13 @@ private: << "detected: " << bg::dsv(detected) << std::endl << std::endl; #endif - bool same_boxes = box_equals(detected, expected1, tolerance); + bool same_boxes + = box_equals::apply(detected, expected1, tolerance); + if (expected_are_different) { same_boxes = same_boxes - || box_equals(detected, expected2, tolerance); + || box_equals::apply(detected, expected2, tolerance); } check_message(same_boxes, case_id, units_str, @@ -274,14 +199,18 @@ private: Box const& box, Geometry const& geometry, double lon_min1, double lat_min1, + double height_min1, double lon_max1, double lat_max1, + double height_max1, double lon_min2, double lat_min2, + double height_min2, double lon_max2, double lat_max2, + double height_max2, double tolerance) { typedef other_system_info < - typename bg::coordinate_system::type::units + typename bg::coordinate_system::type > other; typedef bg::model::box @@ -289,7 +218,7 @@ private: bg::model::point < typename bg::coordinate_type::type, - 2, + bg::dimension::value, typename other::type > > other_mbr_type; @@ -300,26 +229,41 @@ private: #endif base_test(case_id, box, geometry, - lon_min1, lat_min1, lon_max1, lat_max1, - lon_min2, lat_min2, lon_max2, lat_max2, + lon_min1, lat_min1, height_min1, + lon_max1, lat_max1, height_max1, + lon_min2, lat_min2, height_min2, + lon_max2, lat_max2, height_max2, tolerance); other_mbr_type other_box; - bg::assign_values(other_box, - other::convert(bg::get<0, 0>(box)), - other::convert(bg::get<0, 1>(box)), - other::convert(bg::get<1, 0>(box)), - other::convert(bg::get<1, 1>(box))); + bg::detail::indexed_point_view p_min(box); + bg::detail::indexed_point_view p_max(box); + bg::detail::indexed_point_view + < + other_mbr_type, 0 + > other_min(other_box); + + bg::detail::indexed_point_view + < + other_mbr_type, 1 + > other_max(other_box); + + bg::transform(p_min, other_min); + bg::transform(p_max, other_max); base_test(case_id, other_box, geometry, other::convert(lon_min1), other::convert(lat_min1), + height_min1, other::convert(lon_max1), other::convert(lat_max1), + height_max1, other::convert(lon_min2), other::convert(lat_min2), + height_min2, other::convert(lon_max2), other::convert(lat_max2), + height_max2, tolerance); #ifdef BOOST_GEOMETRY_TEST_DEBUG @@ -337,17 +281,23 @@ private: Box const& box, Geometry const& geometry, double lon_min1, double lat_min1, + double height_min1, double lon_max1, double lat_max1, + double height_max1, double lon_min2, double lat_min2, + double height_min2, double lon_max2, double lat_max2, + double height_max2, double tolerance) { basic_tester < false >::apply(case_id, box, geometry, - lon_min1, lat_min1, lon_max1, lat_max1, - lon_min2, lat_min2, lon_max2, lat_max2, + lon_min1, lat_min1, height_min1, + lon_max1, lat_max1, height_max1, + lon_min2, lat_min2, height_min1, + lon_max2, lat_max2, height_max2, tolerance); std::string case_id_r = case_id + "[R]"; @@ -356,8 +306,10 @@ private: < false >::apply(case_id_r, geometry, box, - lon_min1, lat_min1, lon_max1, lat_max1, - lon_min2, lat_min2, lon_max2, lat_max2, + lon_min1, lat_min1, height_min1, + lon_max1, lat_max1, height_max1, + lon_min2, lat_min2, height_min2, + lon_max2, lat_max2, height_max2, tolerance); } }; @@ -368,10 +320,10 @@ public: static inline void apply(std::string const& case_id, Box const& box, Geometry const& geometry, - double lon_min1, double lat_min1, - double lon_max1, double lat_max1, - double lon_min2, double lat_min2, - double lon_max2, double lat_max2, + double lon_min1, double lat_min1, double height_min1, + double lon_max1, double lat_max1, double height_max1, + double lon_min2, double lat_min2, double height_min2, + double lon_max2, double lat_max2, double height_max2, double tolerance = std::numeric_limits::epsilon()) { @@ -383,11 +335,29 @@ public: bg::box_tag >::value >::apply(case_id, box, geometry, - lon_min1, lat_min1, lon_max1, lat_max1, - lon_min2, lat_min2, lon_max2, lat_max2, + lon_min1, lat_min1, height_min1, + lon_max1, lat_max1, height_max1, + lon_min2, lat_min2, height_min2, + lon_max2, lat_max2, height_max2, tolerance); } + template + static inline void apply(std::string const& case_id, + Box const& box, + Geometry const& geometry, + double lon_min1, double lat_min1, + double lon_max1, double lat_max1, + double lon_min2, double lat_min2, + double lon_max2, double lat_max2, + double tolerance = std::numeric_limits::epsilon()) + { + apply(case_id, box, geometry, + lon_min1, lat_min1, 0, lon_max1, lat_max1, 0, + lon_min2, lat_min2, 0, lon_max2, lat_max2, 0, + tolerance); + } + template static inline void apply(std::string const& case_id, Box const& box, @@ -397,17 +367,33 @@ public: double tolerance = std::numeric_limits::epsilon()) { apply(case_id, box, geometry, - lon_min, lat_min, lon_max, lat_max, - lon_min, lat_min, lon_max, lat_max, + lon_min, lat_min, 0, lon_max, lat_max, 0, + lon_min, lat_min, 0, lon_max, lat_max, 0, + tolerance); + } + + template + static inline void apply(std::string const& case_id, + Box const& box, + Geometry const& geometry, + double lon_min, double lat_min, double height_min, + double lon_max, double lat_max, double height_max, + double tolerance = std::numeric_limits::epsilon()) + { + apply(case_id, box, geometry, + lon_min, lat_min, height_min, lon_max, lat_max, height_max, + lon_min, lat_min, height_min, lon_max, lat_max, height_max, tolerance); } }; -BOOST_AUTO_TEST_CASE( expand_point ) +template +void test_expand_point() { - typedef deg_box_type B; - typedef deg_point_type G; + typedef bg::model::point point_type; + typedef bg::model::box B; + typedef point_type G; typedef test_expand_on_spheroid tester; tester::apply("p01", @@ -596,11 +582,51 @@ BOOST_AUTO_TEST_CASE( expand_point ) 10, -90, 100, 90); } +BOOST_AUTO_TEST_CASE( expand_point ) +{ + test_expand_point >(); + test_expand_point >(); +} + + +template +void test_expand_point_with_height() +{ + typedef bg::model::point point_type; + typedef bg::model::box B; + typedef point_type G; + typedef test_expand_on_spheroid tester; + + // deactivate this for now + tester::apply("ph01", + from_wkt("BOX(0 0 20,5 5 100)"), + from_wkt("POINT(10 10 80)"), + 0, 0, 20, 10, 10, 100); + + tester::apply("ph02", + from_wkt("BOX(0 0 20,5 5 100)"), + from_wkt("POINT(10 10 120)"), + 0, 0, 20, 10, 10, 120); + + tester::apply("ph03", + from_wkt("BOX(0 0 20,5 5 100)"), + from_wkt("POINT(10 10 5)"), + 0, 0, 5, 10, 10, 100); +} + +BOOST_AUTO_TEST_CASE( expand_point_with_height ) +{ + test_expand_point_with_height >(); + test_expand_point_with_height >(); +} + BOOST_AUTO_TEST_CASE( expand_segment ) { - typedef deg_box_type B; - typedef deg_segment_type G; + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::box B; + typedef bg::model::segment G; typedef test_expand_on_spheroid tester; tester::apply("s01", @@ -674,10 +700,42 @@ BOOST_AUTO_TEST_CASE( expand_segment ) } -BOOST_AUTO_TEST_CASE( expand_box ) +BOOST_AUTO_TEST_CASE( expand_segment_with_height ) { - typedef deg_box_type B; - typedef deg_box_type G; + typedef bg::cs::spherical_equatorial coordinate_system_type; + typedef bg::model::point point_type; + typedef bg::model::box B; + typedef bg::model::segment G; + typedef test_expand_on_spheroid tester; + + tester::apply("sh01", + from_wkt("BOX(20 20 100,50 50 1000)"), + from_wkt("SEGMENT(10 10 150,40 40 500)"), + 10, 10, 100, 50, 50, 1000); + + tester::apply("sh02", + from_wkt("BOX(20 20 100,50 50 1000)"), + from_wkt("SEGMENT(10 10 60,40 40 1500)"), + 10, 10, 60, 50, 50, 1500); + + tester::apply("sh03", + from_wkt("BOX(20 20 100,50 50 1000)"), + from_wkt("SEGMENT(10 10 150,40 40 1500)"), + 10, 10, 100, 50, 50, 1500); + + tester::apply("sh04", + from_wkt("BOX(20 20 100,50 50 1000)"), + from_wkt("SEGMENT(10 10 60,40 40 800)"), + 10, 10, 60, 50, 50, 1000); +} + + +template +void test_expand_box() +{ + typedef bg::model::point point_type; + typedef bg::model::box B; + typedef bg::model::box G; typedef test_expand_on_spheroid tester; tester::apply("b01", @@ -845,3 +903,45 @@ BOOST_AUTO_TEST_CASE( expand_box ) from_wkt("BOX(0 -10,185 50)"), -180, -40, 180, 50); } + +BOOST_AUTO_TEST_CASE( expand_box ) +{ + test_expand_box >(); + test_expand_box >(); +} + + +template +void test_expand_box_with_height() +{ + typedef bg::model::point point_type; + typedef bg::model::box B; + typedef bg::model::box G; + typedef test_expand_on_spheroid tester; + + tester::apply("bh01", + from_wkt("BOX(11 11 100,19 19 1000)"), + from_wkt("BOX(10 10 200,20 20 800)"), + 10, 10, 100, 20, 20, 1000); + + tester::apply("bh02", + from_wkt("BOX(11 11 200,19 19 1000)"), + from_wkt("BOX(10 10 100,20 20 800)"), + 10, 10, 100, 20, 20, 1000); + + tester::apply("bh03", + from_wkt("BOX(11 11 100,19 19 800)"), + from_wkt("BOX(10 10 200,20 20 1000)"), + 10, 10, 100, 20, 20, 1000); + + tester::apply("bh04", + from_wkt("BOX(11 11 200,19 19 1000)"), + from_wkt("BOX(10 10 100,20 20 800)"), + 10, 10, 100, 20, 20, 1000); +} + +BOOST_AUTO_TEST_CASE( expand_box_with_height ) +{ + test_expand_box_with_height >(); + test_expand_box_with_height >(); +} diff --git a/test/algorithms/test_envelope_expand_on_spheroid.hpp b/test/algorithms/test_envelope_expand_on_spheroid.hpp new file mode 100644 index 000000000..316b9cae2 --- /dev/null +++ b/test/algorithms/test_envelope_expand_on_spheroid.hpp @@ -0,0 +1,192 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP +#define BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + + +template +char const* units2string() +{ + if (BOOST_GEOMETRY_CONDITION((boost::is_same::value))) + { + return "degrees"; + } + return "radians"; +} + +template +struct other_system_info +{}; + +template <> +struct other_system_info > +{ + typedef bg::degree units; + typedef bg::cs::spherical_equatorial type; + + template + static inline T convert(T const& value) + { + return value * bg::math::r2d(); + } +}; + +template <> +struct other_system_info > +{ + typedef bg::radian units; + typedef bg::cs::spherical_equatorial type; + + template + static inline T convert(T const& value) + { + return value * bg::math::d2r(); + } +}; + +template <> +struct other_system_info > +{ + typedef bg::degree units; + typedef bg::cs::geographic type; + + template + static inline T convert(T const& value) + { + return value * bg::math::r2d(); + } +}; + +template <> +struct other_system_info > +{ + typedef bg::radian units; + typedef bg::cs::geographic type; + + template + static inline T convert(T const& value) + { + return value * bg::math::d2r(); + } +}; + + + +class equals_with_tolerance +{ +private: + double m_tolerence; + + template + static inline T const& get_max(T const& a, T const& b, T const& c) + { + return (std::max)((std::max)(a, b), c); + } + + template + static inline bool check_close(T const& a, T const& b, double tol) + { + return (a == b) + || (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0)); + } + +public: + equals_with_tolerance(double tolerence) : m_tolerence(tolerence) {} + + template + inline bool operator()(T const& value1, T const& value2) const + { + return check_close(value1, value2, m_tolerence); + } +}; + + +template +< + typename Box1, + typename Box2 = Box1, + std::size_t DimensionCount = bg::dimension::value +> +struct box_equals +{ + static inline bool apply(Box1 const& box1, Box2 const& box2, double tol) + { + equals_with_tolerance equals(tol); + + return equals(bg::get<0, 0>(box1), bg::get<0, 0>(box2)) + && equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2)) + && equals(bg::get<1, 0>(box1), bg::get<1, 0>(box2)) + && equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2)); + } +}; + +template +struct box_equals +{ + static inline bool apply(Box1 const& box1, Box2 const& box2, double tol) + { + equals_with_tolerance equals(tol); + + return box_equals::apply(box1, box2, tol) + && equals(bg::get<0, 2>(box1), bg::get<0, 2>(box2)) + && equals(bg::get<1, 2>(box1), bg::get<1, 2>(box2)); + } +}; + + +template ::value> +struct initialize_box +{ + static inline void apply(Box& box, + double lon_min, double lat_min, double, + double lon_max, double lat_max, double) + { + bg::detail::indexed_point_view p_min(box); + bg::detail::indexed_point_view p_max(box); + + bg::assign_values(p_min, lon_min, lat_min); + bg::assign_values(p_max, lon_max, lat_max); + } +}; + +template +struct initialize_box +{ + static inline void apply(Box& box, + double lon_min, double lat_min, double height_min, + double lon_max, double lat_max, double height_max) + { + bg::detail::indexed_point_view p_min(box); + bg::detail::indexed_point_view p_max(box); + + bg::assign_values(p_min, lon_min, lat_min, height_min); + bg::assign_values(p_max, lon_max, lat_max, height_max); + } +}; + +#endif // BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP From 76d7f7316bd76d0412105e90ae8debc63707de3a Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 5 Jun 2015 23:09:30 +0300 Subject: [PATCH 05/26] [algorithms][envelope] modify implementation logic so as to always initialize the MBR --- .../buffer/buffered_piece_collection.hpp | 6 +- .../detail/envelope/implementation.hpp | 43 ++----- .../algorithms/detail/envelope/initialize.hpp | 79 +++++++++++++ .../algorithms/detail/envelope/linestring.hpp | 50 ++++---- .../detail/envelope/multilinestring.hpp | 50 +++----- .../algorithms/detail/envelope/multipoint.hpp | 31 +++-- .../algorithms/detail/envelope/range.hpp | 110 ++++++++++++------ 7 files changed, 227 insertions(+), 142 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/envelope/initialize.hpp diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 7f0f523df..a1ff4afc5 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -979,11 +979,7 @@ struct buffered_piece_collection return; } - geometry::detail::envelope::envelope_range - < - typename piece::piece_robust_ring_type, - 0, dimension::value - >::apply(pc.robust_ring, pc.robust_envelope); + geometry::envelope(pc.robust_ring, pc.robust_envelope); geometry::assign_inverse(pc.robust_offsetted_envelope); for (int i = 0; i < pc.offsetted_count; i++) diff --git a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp index 40027ec46..90cc1ccee 100644 --- a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -24,6 +24,8 @@ #include #include +#include + #include #include #include @@ -44,27 +46,12 @@ namespace detail { namespace envelope { -template -< - typename Geometry, std::size_t Dimension, std::size_t DimensionCount -> -struct exterior_ring_expand_policy +struct polygon_is_empty_policy { - template - static inline void apply(Box& mbr, Geometry const& geometry) + template + static inline bool apply(Polygon const& polygon) { - Box ring_mbr; - envelope_range - < - typename ring_type::type, - Dimension, - DimensionCount - >::apply(exterior_ring(geometry), ring_mbr); - - dispatch::expand - < - Box, Box, Dimension, DimensionCount - >::apply(mbr, ring_mbr); + return geometry::is_empty(exterior_ring(polygon)); } }; @@ -78,12 +65,9 @@ struct envelope_polygon // For polygon, inspecting outer ring is sufficient envelope_range < - typename ring_type::type, - Dimension, - DimensionCount + Dimension, DimensionCount >::apply(exterior_ring(poly), mbr); } - }; @@ -97,7 +81,7 @@ namespace dispatch template struct envelope - : detail::envelope::envelope_range + : detail::envelope::envelope_range {}; @@ -114,17 +98,12 @@ template std::size_t DimensionCount > struct envelope - : detail::envelope::envelope_range + : detail::envelope::envelope_multi_range < - MultiPolygon, Dimension, DimensionCount, - detail::envelope::exterior_ring_expand_policy - < - typename boost::range_value::type, - Dimension, - DimensionCount - > + detail::envelope::polygon_is_empty_policy, + detail::envelope::envelope_polygon > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp new file mode 100644 index 000000000..4ce95f8f9 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp @@ -0,0 +1,79 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace detail { namespace envelope +{ + +template +struct initialize_loop +{ + template + static inline void apply(Box& box, + CoordinateType min_value, + CoordinateType max_value) + { + geometry::set(box, min_value); + geometry::set(box, max_value); + + initialize_loop + < + Dimension + 1, DimensionCount + >::apply(box, min_value, max_value); + } +}; + +template +struct initialize_loop +{ + template + static inline void apply(Box&, CoordinateType, CoordinateType) + { + } +}; + + +template +< + typename Box, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension::value +> +struct initialize +{ + typedef typename coordinate_type::type coordinate_type; + + static inline void apply(Box& box, + coordinate_type min_value = 1, + coordinate_type max_value = -1) + { + initialize_loop + < + Dimension, DimensionCount + >::apply(box, min_value, max_value); + } +}; + +}} // detail::envelope + +}} // boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp index 26b0bd683..1df9a0293 100644 --- a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp @@ -37,6 +37,7 @@ #include +#include #include #include @@ -51,19 +52,8 @@ namespace detail { namespace envelope { -template -< - typename Linear, - std::size_t Dimension, - std::size_t DimensionCount, - typename ExpandPolicy -> +template struct envelope_linear_on_spheroid - : envelope_range -{}; - -template -struct envelope_linear_on_spheroid { template static inline OutputIterator push_interval(Longitude const& lon1, @@ -93,7 +83,7 @@ struct envelope_linear_on_spheroid return oit; } - template + template static inline void apply(Linear const& linear, Box& mbr) { typedef typename coordinate_type::type box_coordinate_type; @@ -104,7 +94,13 @@ struct envelope_linear_on_spheroid Linear const > iterator_type; - BOOST_ASSERT(! geometry::is_empty(linear)); + if (geometry::is_empty(linear)) + { + initialize::apply(mbr); + return; + } + + initialize::apply(mbr); std::vector longitude_intervals; std::back_insert_iterator @@ -164,14 +160,25 @@ struct envelope_linear_on_spheroid geometry::set(mbr, lon_max); geometry::set(mbr, lat_max); - envelope_range + dispatch::envelope < - Linear, 2, DimensionCount, ExpandPolicy + Linear, 2, DimensionCount >::apply(linear, mbr); } }; +template +struct envelope_linestring_on_spheroid + : envelope_range +{}; + +template +struct envelope_linestring_on_spheroid<0, DimensionCount> + : envelope_linear_on_spheroid +{}; + + }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -189,7 +196,7 @@ template typename CS_Tag > struct envelope - : detail::envelope::envelope_range + : detail::envelope::envelope_range {}; template @@ -202,18 +209,15 @@ struct envelope < Linestring, Dimension, DimensionCount, linestring_tag, spherical_equatorial_tag - > : detail::envelope::envelope_linear_on_spheroid + > : detail::envelope::envelope_linestring_on_spheroid < - Linestring, - Dimension, - DimensionCount, - detail::envelope::default_expand_policy + Dimension, DimensionCount > {}; } // namespace dispatch -#endif +#endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp index df4cd06ff..6f1501905 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp @@ -26,7 +26,6 @@ #include #include -#include #include @@ -34,29 +33,27 @@ namespace boost { namespace geometry { + #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace envelope { template -struct envelope_range_expand_policy -{ - template - static inline void apply(Box& mbr, Geometry const& geometry) - { - Box helper_mbr; - envelope_range - < - Geometry, Dimension, DimensionCount - >::apply(geometry, helper_mbr); +struct envelope_multilinestring_on_spheroid + : envelope_multi_range + < + Dimension, + DimensionCount, + detail::envelope::default_is_empty_policy, + detail::envelope::envelope_range + > +{}; - dispatch::expand - < - Box, Box, Dimension, DimensionCount - >::apply(mbr, helper_mbr); - } -}; +template +struct envelope_multilinestring_on_spheroid<0, DimensionCount> + : envelope_linear_on_spheroid +{}; }} // namespace detail::envelope @@ -80,15 +77,12 @@ struct envelope MultiLinestring, Dimension, DimensionCount, multi_linestring_tag, CS_Tag - > : detail::envelope::envelope_range + > : detail::envelope::envelope_multi_range < - MultiLinestring, Dimension, DimensionCount, - detail::envelope::envelope_range_expand_policy - < - Dimension, DimensionCount - > + detail::envelope::default_is_empty_policy, + detail::envelope::envelope_range > {}; @@ -103,15 +97,9 @@ struct envelope MultiLinestring, Dimension, DimensionCount, multi_linestring_tag, spherical_equatorial_tag - > : detail::envelope::envelope_linear_on_spheroid + > : detail::envelope::envelope_multilinestring_on_spheroid < - MultiLinestring, - Dimension, - DimensionCount, - detail::envelope::envelope_range_expand_policy - < - Dimension, DimensionCount - > + Dimension, DimensionCount > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp index ea01218b8..36d33427a 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -44,19 +45,13 @@ namespace detail { namespace envelope { -template -< - typename MultiPoint, - std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag -> +template struct envelope_multipoint_on_spheroid - : envelope_range + : envelope_range {}; -template -class envelope_multipoint_on_spheroid +template +class envelope_multipoint_on_spheroid<0, DimensionCount, CS_Tag> { private: template @@ -70,7 +65,7 @@ private: } }; - template + template static inline void analyze_point_coordinates(MultiPoint const& multipoint, bool& has_south_pole, bool& has_north_pole, @@ -234,7 +229,7 @@ private: } public: - template + template static inline void apply(MultiPoint const& multipoint, Box& mbr) { typedef typename point_type::type point_type; @@ -246,12 +241,14 @@ public: typename coordinate_system::type::units > constants; - if (boost::empty(multipoint)) { + initialize::apply(mbr); return; } + initialize::apply(mbr); + if (boost::size(multipoint) == 1) { return dispatch::envelope @@ -330,7 +327,7 @@ public: // compute envelope for higher coordinates envelope_multipoint_on_spheroid < - MultiPoint, 2, DimensionCount, CS_Tag + 2, DimensionCount, CS_Tag >::apply(multipoint, helper_mbr); // now transform to output MBR (per index) @@ -369,7 +366,7 @@ struct envelope MultiPoint, Dimension, DimensionCount, multi_point_tag, CSTag - > : detail::envelope::envelope_range + > : detail::envelope::envelope_range {}; template @@ -385,7 +382,7 @@ struct envelope multi_point_tag, spherical_equatorial_tag > : detail::envelope::envelope_multipoint_on_spheroid < - MultiPoint, Dimension, DimensionCount, spherical_equatorial_tag + Dimension, DimensionCount, spherical_equatorial_tag > {}; @@ -402,7 +399,7 @@ struct envelope multi_point_tag, geographic_tag > : detail::envelope::envelope_multipoint_on_spheroid < - MultiPoint, Dimension, DimensionCount, geographic_tag + Dimension, DimensionCount, geographic_tag > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/range.hpp b/include/boost/geometry/algorithms/detail/envelope/range.hpp index 1ec08717b..09f78376e 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -25,6 +25,9 @@ #include +#include + +#include #include #include #include @@ -39,43 +42,28 @@ namespace detail { namespace envelope { -template -struct default_expand_policy +struct default_is_empty_policy { - template - static inline void apply(Box& mbr, Geometry const& geometry) + template + static inline bool apply(Geometry const& geometry) { - dispatch::expand - < - Box, Geometry, Dimension, DimensionCount - >::apply(mbr, geometry); + return geometry::is_empty(geometry); } }; -template -inline void envelope_iterators(Iterator first, Iterator last, Box& mbr) -{ - for (Iterator it = first; it != last; ++it) - { - ExpandPolicy::apply(mbr, *it); - } -} - - -template -< - typename Range, - std::size_t Dimension, - std::size_t DimensionCount, - typename ExpandPolicy = default_expand_policy -> +// implementation for simple ranges +template struct envelope_range { - /// Calculate envelope of range using a strategy - template + template static inline void apply(Range const& range, Box& mbr) { + typedef typename boost::range_value::type value_type; + + // initialize MBR + initialize::apply(mbr); + typename boost::range_iterator::type it = boost::begin(range); @@ -84,17 +72,71 @@ struct envelope_range // initialize box with first element in range dispatch::envelope < - typename boost::range_value::type, - Dimension, - DimensionCount + value_type, Dimension, DimensionCount >::apply(*it, mbr); // consider now the remaining elements in the range (if any) + for (++it; it != boost::end(range); ++it) + { + dispatch::expand + < + Box, value_type, Dimension, DimensionCount + >::apply(mbr, *it); + } + } + } +}; + + +// implementation for multi-ranges +template +< + std::size_t Dimension, + std::size_t DimensionCount, + typename IsEmptyPolicy, + typename EnvelopePolicy +> +struct envelope_multi_range +{ + template + static inline void apply(MultiRange const& multirange, Box& mbr) + { + typedef typename boost::range_iterator + < + MultiRange const + >::type iterator_type; + + // initialize MBR + initialize::apply(mbr); + + // skip through empty geometries + iterator_type it = boost::begin(multirange); + while (it != boost::end(multirange) && IsEmptyPolicy::apply(*it)) + { ++it; - envelope_iterators - < - ExpandPolicy - >(it, boost::end(range), mbr); + } + + // if there are still elements left, apply the envelope policy + if (it != boost::end(multirange)) + { + // compute the initial envelope + EnvelopePolicy::apply(*it, mbr); + + // for the remaining non-empty geometries just expand the mbr + // using the envelope + for (++it; it != boost::end(multirange); ++it) + { + if (! IsEmptyPolicy::apply(*it)) + { + Box helper_mbr; + EnvelopePolicy::apply(*it, helper_mbr); + + dispatch::expand + < + Box, Box, Dimension, DimensionCount + >::apply(mbr, helper_mbr); + } + } } } }; From 4199a92afece9c70a737853a87486c1a671214e8 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 5 Jun 2015 23:10:08 +0300 Subject: [PATCH 06/26] [test][algorithms][envelope] add test cases involving empty and invalid geometries --- test/algorithms/envelope.cpp | 101 ++++++++++++++++++++++- test/algorithms/envelope_on_spheroid.cpp | 73 ++++++++++++++-- 2 files changed, 163 insertions(+), 11 deletions(-) diff --git a/test/algorithms/envelope.cpp b/test/algorithms/envelope.cpp index 92d69e8ac..edc8b7e99 100644 --- a/test/algorithms/envelope.cpp +++ b/test/algorithms/envelope.cpp @@ -1,9 +1,14 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -57,6 +62,86 @@ void test_3d() test_envelope >("BOX(1 1 1,3 3 3)", 1, 3, 1, 3, 1, 3); } +template +void test_empty() +{ + test_envelope >("LINESTRING()", 1, -1, 1, -1); + test_envelope >("POLYGON(())", 1, -1, 1, -1); + + test_envelope >("POLYGON(())", 1, -1, 1, -1); + + test_envelope >("MULTIPOINT()", 1, -1, 1, -1); + + test_envelope + < + bg::model::multi_linestring > + >("MULTILINESTRING()", 1, -1, 1, -1); + + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON()", 1, -1, 1, -1); +} + +template +void test_invalid() +{ + // multilinestring with empty linestrings + test_envelope + < + bg::model::multi_linestring > + >("MULTILINESTRING((),(),())", 1, -1, 1, -1); + + // multilinestring with empty and non-empty linestrings + test_envelope + < + bg::model::multi_linestring > + >("MULTILINESTRING((),(10 20),())", 10, 10, 20, 20); + + // multipolygon with empty polygon + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON((()))", 1, -1, 1, -1); + + // multipolygon with many empty polygons + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON(((),(),()),(()),((),(),(),(),()))", 1, -1, 1, -1); + + // multipolygon with empty polygons and non-empty (valid) polygon + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON(((),(),()),((10 30,10 40,20 30,10 30)),\ + ((),(),()),(()))", 10, 20, 30, 40); + + // multipolygon with empty polygons and non-empty (valid) polygon + // that has an interior ring + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON(((),(),()),(()),\ + ((1 2,1 20,22 20,22 2,1 2),(3 4,19 4,19 18,3 18,3 4)),(()))", + 1, 22, 2, 20); + + // multipolygon with empty polygons and non-empty (invalid) polygon + // that has an interior ring but empty exterior ring + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON(((),(),()),(()),((),(3 4,19 4,19 18,3 18,3 4)),(()))", + 1, -1, 1, -1); + + // multipolygon with empty polygons and non-empty (invalid) polygon + // that has an interior ring but empty exterior ring + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON(((),(),()),((),(),(3 4,19 4,19 18,3 18,3 4),()),(()))", + 1, -1, 1, -1); +} int test_main(int, char* []) { @@ -71,6 +156,16 @@ int test_main(int, char* []) test_3d(); test_3d >(); + test_empty >(); + test_empty >(); + test_empty >(); + test_empty >(); + + test_invalid >(); + test_invalid >(); + test_invalid >(); + test_invalid >(); + #ifdef HAVE_TTMATH test_2d >(); test_3d >(); diff --git a/test/algorithms/envelope_on_spheroid.cpp b/test/algorithms/envelope_on_spheroid.cpp index 6892bb620..b280bec96 100644 --- a/test/algorithms/envelope_on_spheroid.cpp +++ b/test/algorithms/envelope_on_spheroid.cpp @@ -177,14 +177,26 @@ public: lon_max, lat_max, height_max, tolerance); - base_test(case_id, geometry, - other::convert(lon_min), - other::convert(lat_min), - height_min, - other::convert(lon_max), - other::convert(lat_max), - height_max, - tolerance); + if (lon_max < lon_min) + { + // we are in the case were a special MBR is returned; + // makes no sense to change units + base_test(case_id, geometry, + lon_min, lat_min, height_min, + lon_max, lat_max, height_max, + tolerance); + } + else + { + base_test(case_id, geometry, + other::convert(lon_min), + other::convert(lat_min), + height_min, + other::convert(lon_max), + other::convert(lat_max), + height_max, + tolerance); + } } }; @@ -646,6 +658,11 @@ void test_envelope_multipoint() typedef bg::model::box B; typedef test_envelope_on_spheroid tester; + // empty multipoint + tester::apply("mp00", + from_wkt("MULTIPOINT()"), + 1, 1, -1, -1); + tester::apply("mp01", from_wkt("MULTIPOINT(0 0,10 10)"), 0, 0, 10, 10); @@ -786,6 +803,11 @@ void test_envelope_multipoint_with_height() typedef bg::model::box B; typedef test_envelope_on_spheroid tester; + // empty multipoint + tester::apply("mph00", + from_wkt("MULTIPOINT()"), + 1, 1, 1, -1, -1, -1); + tester::apply("mph01", from_wkt("MULTIPOINT(0 0 567,10 10 1456)"), 0, 0, 567, 10, 10, 1456); @@ -1037,6 +1059,11 @@ BOOST_AUTO_TEST_CASE( envelope_linestring ) typedef bg::model::box B; typedef test_envelope_on_spheroid tester; + // empty linestring + tester::apply("l00", + from_wkt("LINESTRING()"), + 1, 1, -1, -1); + tester::apply("l01", from_wkt("LINESTRING(10 15)"), 10, 15, 10, 15); @@ -1153,6 +1180,11 @@ BOOST_AUTO_TEST_CASE( envelope_linestring_with_height ) typedef bg::model::box B; typedef test_envelope_on_spheroid tester; + // empty linestring + tester::apply("lh00", + from_wkt("LINESTRING()"), + 1, 1, 1, -1, -1, -1); + tester::apply("lh01", from_wkt("LINESTRING(10 15 30,20 25 434,30 35 186)"), 10, 15, 30, 30, 35, 434); @@ -1167,6 +1199,31 @@ BOOST_AUTO_TEST_CASE( envelope_multilinestring ) typedef bg::model::box B; typedef test_envelope_on_spheroid tester; + // empty multilinestring + tester::apply("ml00", + from_wkt("MULTILINESTRING()"), + 1, 1, -1, -1); + + // invalid multilinestring + tester::apply("ml00a", + from_wkt("MULTILINESTRING(())"), + 1, 1, -1, -1); + + // invalid multilinestring + tester::apply("ml00b", + from_wkt("MULTILINESTRING((),())"), + 1, 1, -1, -1); + + // invalid multilinestring + tester::apply("ml00c", + from_wkt("MULTILINESTRING((10 15),(),())"), + 10, 15, 10, 15); + + // invalid multilinestring + tester::apply("ml00d", + from_wkt("MULTILINESTRING((),(10 15),())"), + 10, 15, 10, 15); + tester::apply("ml01", from_wkt("MULTILINESTRING((10 15))"), 10, 15, 10, 15); From 25cc0042436f105ad2b26a6799b154bec05c0e4b Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 5 Jun 2015 23:15:24 +0300 Subject: [PATCH 07/26] [algorithms][envelope] add missing doxygen macros; fix namespace closing comments; --- .../geometry/algorithms/detail/envelope/initialize.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp index 4ce95f8f9..fe3f5bfac 100644 --- a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp @@ -20,6 +20,7 @@ namespace boost { namespace geometry { +#ifndef DOXYGEN_NO_DETAIL namespace detail { namespace envelope { @@ -72,8 +73,9 @@ struct initialize } }; -}} // detail::envelope +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL -}} // boost::geometry +}} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP From 37564000d0ca1ebe049b85b008b9ce3bf0693497 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 11 Jun 2015 00:18:06 +0300 Subject: [PATCH 08/26] [algorithms][envelope] fix compilation errors in assertions --- .../algorithms/detail/envelope/range_of_boxes.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp index bf456df4f..5d0ef3455 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -118,15 +118,17 @@ struct envelope_range_of_longitudes max_gap_right); BOOST_GEOMETRY_ASSERT(! math::larger(lon_min, lon_max)); - BOOST_GEOMETRY_ASSERT(! math::larger(lon_max, max_longitude)); - BOOST_GEOMETRY_ASSERT(! math::smaller(lon_min, min_longitude)); + BOOST_GEOMETRY_ASSERT + (! math::larger(lon_max, constants::max_longitude())); + BOOST_GEOMETRY_ASSERT + (! math::smaller(lon_min, constants::min_longitude())); BOOST_GEOMETRY_ASSERT (! math::larger(max_gap_left, max_gap_right)); BOOST_GEOMETRY_ASSERT - (! math::larger(max_gap_right, max_longitude)); + (! math::larger(max_gap_right, constants::max_longitude())); BOOST_GEOMETRY_ASSERT - (! math::smaller(max_gap_left, min_longitude)); + (! math::smaller(max_gap_left, constants::min_longitude())); if (math::larger(max_gap, zero)) { From 1a4d2504afd2acc9f2aaa07bff471781bb835e6d Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 11 Jun 2015 01:00:42 +0300 Subject: [PATCH 09/26] [algorithms][envelope] change how the envelope for polygons is implemented: for polygons with empty exterior ring, look at the interior rings --- .../detail/envelope/implementation.hpp | 36 ++++++++++--------- .../detail/envelope/multilinestring.hpp | 2 -- .../algorithms/detail/envelope/range.hpp | 15 ++------ 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp index 90cc1ccee..60d1394d9 100644 --- a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -46,27 +46,30 @@ namespace detail { namespace envelope { -struct polygon_is_empty_policy -{ - template - static inline bool apply(Polygon const& polygon) - { - return geometry::is_empty(exterior_ring(polygon)); - } -}; - - template struct envelope_polygon { template - static inline void apply(Polygon const& poly, Box& mbr) + static inline void apply(Polygon const& polygon, Box& mbr) { - // For polygon, inspecting outer ring is sufficient - envelope_range - < - Dimension, DimensionCount - >::apply(exterior_ring(poly), mbr); + typename ring_return_type::type ext_ring + = exterior_ring(polygon); + + if (geometry::is_empty(ext_ring)) + { + // if the exterior ring is empty, consider the interior rings + envelope_multi_range + < + Dimension, + DimensionCount, + envelope_range + >::apply(interior_rings(polygon), mbr); + } + else + { + // otherwise, consider only the exterior ring + envelope_range::apply(ext_ring, mbr); + } } }; @@ -102,7 +105,6 @@ struct envelope < Dimension, DimensionCount, - detail::envelope::polygon_is_empty_policy, detail::envelope::envelope_polygon > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp index 6f1501905..21888a65a 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp @@ -45,7 +45,6 @@ struct envelope_multilinestring_on_spheroid < Dimension, DimensionCount, - detail::envelope::default_is_empty_policy, detail::envelope::envelope_range > {}; @@ -81,7 +80,6 @@ struct envelope < Dimension, DimensionCount, - detail::envelope::default_is_empty_policy, detail::envelope::envelope_range > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/range.hpp b/include/boost/geometry/algorithms/detail/envelope/range.hpp index 09f78376e..d19469463 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -42,16 +42,6 @@ namespace detail { namespace envelope { -struct default_is_empty_policy -{ - template - static inline bool apply(Geometry const& geometry) - { - return geometry::is_empty(geometry); - } -}; - - // implementation for simple ranges template struct envelope_range @@ -93,7 +83,6 @@ template < std::size_t Dimension, std::size_t DimensionCount, - typename IsEmptyPolicy, typename EnvelopePolicy > struct envelope_multi_range @@ -111,7 +100,7 @@ struct envelope_multi_range // skip through empty geometries iterator_type it = boost::begin(multirange); - while (it != boost::end(multirange) && IsEmptyPolicy::apply(*it)) + while (it != boost::end(multirange) && geometry::is_empty(*it)) { ++it; } @@ -126,7 +115,7 @@ struct envelope_multi_range // using the envelope for (++it; it != boost::end(multirange); ++it) { - if (! IsEmptyPolicy::apply(*it)) + if (! geometry::is_empty(*it)) { Box helper_mbr; EnvelopePolicy::apply(*it, helper_mbr); From ef3e4f3fc76b60d98aa6af1a07ed1aeb15c3acb2 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 11 Jun 2015 01:01:41 +0300 Subject: [PATCH 10/26] [test][algorithms][envelope] update some test cases involving invalid polygons/multipolygons; add more test cases with invalid polygons/multipolygons; --- test/algorithms/envelope.cpp | 52 ++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/test/algorithms/envelope.cpp b/test/algorithms/envelope.cpp index edc8b7e99..20fe507ae 100644 --- a/test/algorithms/envelope.cpp +++ b/test/algorithms/envelope.cpp @@ -86,6 +86,44 @@ void test_empty() template void test_invalid() { + // polygon with empty exterior and interior rings + test_envelope >("POLYGON((),(),())", 1, -1, 1, -1); + + // polygon with empty interior rings + test_envelope + < + bg::model::polygon

+ >("POLYGON((1 2,1 20,22 20,22 2,1 2),(),())", + 1, 22, 2, 20); + + // another polygon with empty interior rings + test_envelope + < + bg::model::polygon

+ >("POLYGON((1 2,1 20,22 20,22 2,1 2),(),(3 4,19 4,19 18,3 18,3 4),())", + 1, 22, 2, 20); + + // polygon with empty exterior ring + test_envelope + < + bg::model::polygon

+ >("POLYGON((),(),(3 4,19 4,19 18,3 18,3 4),())", + 3, 19, 4, 18); + + // another polygon with empty exterior ring + test_envelope + < + bg::model::polygon

+ >("POLYGON((),(),(3 4,19 4,19 18,3 18,3 4),(4 5,18 5,18 17,4 17,4 5))", + 3, 19, 4, 18); + + // yet one more polygon with empty exterior ring + test_envelope + < + bg::model::polygon

+ >("POLYGON((),(),(4 5,18 5,18 17,4 17,4 5),(3 4,19 4,19 18,3 18,3 4))", + 3, 19, 4, 18); + // multilinestring with empty linestrings test_envelope < @@ -132,7 +170,7 @@ void test_invalid() < bg::model::multi_polygon > >("MULTIPOLYGON(((),(),()),(()),((),(3 4,19 4,19 18,3 18,3 4)),(()))", - 1, -1, 1, -1); + 3, 19, 4, 18); // multipolygon with empty polygons and non-empty (invalid) polygon // that has an interior ring but empty exterior ring @@ -140,7 +178,17 @@ void test_invalid() < bg::model::multi_polygon > >("MULTIPOLYGON(((),(),()),((),(),(3 4,19 4,19 18,3 18,3 4),()),(()))", - 1, -1, 1, -1); + 3, 19, 4, 18); + + // multipolygon with empty polygons and non-empty (invalid) polygon + // that has two non-empty interior rings but empty exterior ring + test_envelope + < + bg::model::multi_polygon > + >("MULTIPOLYGON(((),(),()),\ + ((),(),(3 4,19 4,19 18,3 18,3 4),(4 5,18 5,18 17,4 17,4 5),()),\ + (()))", + 3, 19, 4, 18); } int test_main(int, char* []) From a38f7bf60b27f37bc12a26e648661c0514c46943 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 11 Jun 2015 01:13:47 +0300 Subject: [PATCH 11/26] [algorithms][envelope] make the initial box the same as that returned by assign_inverse (for consistency with older behavior; this might change in the future) --- .../geometry/algorithms/detail/envelope/initialize.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp index fe3f5bfac..1346fef02 100644 --- a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp @@ -11,6 +11,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP #include +#include #include #include @@ -63,8 +64,10 @@ struct initialize typedef typename coordinate_type::type coordinate_type; static inline void apply(Box& box, - coordinate_type min_value = 1, - coordinate_type max_value = -1) + coordinate_type min_value + = (std::numeric_limits::max)(), + coordinate_type max_value + = -(std::numeric_limits::max)()) { initialize_loop < From 9f760bcdc78c81d1b0b12a4adee26f392c8d7c15 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 11 Jun 2015 01:14:43 +0300 Subject: [PATCH 12/26] [test][algorithms][envelope] update test case results for empty geometries --- test/algorithms/envelope.cpp | 43 +++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/test/algorithms/envelope.cpp b/test/algorithms/envelope.cpp index 20fe507ae..9a59ebd52 100644 --- a/test/algorithms/envelope.cpp +++ b/test/algorithms/envelope.cpp @@ -17,6 +17,7 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include @@ -62,32 +63,44 @@ void test_3d() test_envelope >("BOX(1 1 1,3 3 3)", 1, 3, 1, 3, 1, 3); } +template +void test_empty_geometry(std::string const& wkt) +{ + typedef typename bg::coordinate_type::type coordinate_type; + coordinate_type max_val = (std::numeric_limits::max)(); + + test_envelope(wkt, max_val, -max_val, max_val, -max_val); +} + template void test_empty() { - test_envelope >("LINESTRING()", 1, -1, 1, -1); - test_envelope >("POLYGON(())", 1, -1, 1, -1); + typedef typename bg::coordinate_type

::type coordinate_type; + coordinate_type max_val = (std::numeric_limits::max)(); - test_envelope >("POLYGON(())", 1, -1, 1, -1); + test_empty_geometry >("LINESTRING()"); + test_empty_geometry >("POLYGON(())"); - test_envelope >("MULTIPOINT()", 1, -1, 1, -1); + test_empty_geometry >("POLYGON(())"); - test_envelope + test_empty_geometry >("MULTIPOINT()"); + + test_empty_geometry < bg::model::multi_linestring > - >("MULTILINESTRING()", 1, -1, 1, -1); + >("MULTILINESTRING()"); - test_envelope + test_empty_geometry < bg::model::multi_polygon > - >("MULTIPOLYGON()", 1, -1, 1, -1); + >("MULTIPOLYGON()"); } template void test_invalid() { // polygon with empty exterior and interior rings - test_envelope >("POLYGON((),(),())", 1, -1, 1, -1); + test_empty_geometry >("POLYGON((),(),())"); // polygon with empty interior rings test_envelope @@ -125,10 +138,10 @@ void test_invalid() 3, 19, 4, 18); // multilinestring with empty linestrings - test_envelope + test_empty_geometry < bg::model::multi_linestring > - >("MULTILINESTRING((),(),())", 1, -1, 1, -1); + >("MULTILINESTRING((),(),())"); // multilinestring with empty and non-empty linestrings test_envelope @@ -137,16 +150,16 @@ void test_invalid() >("MULTILINESTRING((),(10 20),())", 10, 10, 20, 20); // multipolygon with empty polygon - test_envelope + test_empty_geometry < bg::model::multi_polygon > - >("MULTIPOLYGON((()))", 1, -1, 1, -1); + >("MULTIPOLYGON((()))"); // multipolygon with many empty polygons - test_envelope + test_empty_geometry < bg::model::multi_polygon > - >("MULTIPOLYGON(((),(),()),(()),((),(),(),(),()))", 1, -1, 1, -1); + >("MULTIPOLYGON(((),(),()),(()),((),(),(),(),()))"); // multipolygon with empty polygons and non-empty (valid) polygon test_envelope From 3f80fe7ce6395599d7faa97ed976c6d50dfa1668 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 3 Jul 2015 00:24:45 +0300 Subject: [PATCH 13/26] [test][algorithms][envelope] fix testing of empty geometries --- test/algorithms/envelope.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/algorithms/envelope.cpp b/test/algorithms/envelope.cpp index 9a59ebd52..1cb989786 100644 --- a/test/algorithms/envelope.cpp +++ b/test/algorithms/envelope.cpp @@ -17,7 +17,7 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include #include @@ -66,18 +66,16 @@ void test_3d() template void test_empty_geometry(std::string const& wkt) { - typedef typename bg::coordinate_type::type coordinate_type; - coordinate_type max_val = (std::numeric_limits::max)(); + typedef typename bg::coordinate_type::type ct; + ct high_val = boost::numeric::bounds::highest(); + ct low_val = boost::numeric::bounds::lowest(); - test_envelope(wkt, max_val, -max_val, max_val, -max_val); + test_envelope(wkt, high_val, low_val, high_val, low_val); } template void test_empty() { - typedef typename bg::coordinate_type

::type coordinate_type; - coordinate_type max_val = (std::numeric_limits::max)(); - test_empty_geometry >("LINESTRING()"); test_empty_geometry >("POLYGON(())"); From 07f0faad7c4825d38fe603d3ffb05861a9fb0d86 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 3 Jul 2015 00:25:13 +0300 Subject: [PATCH 14/26] [test][algorithms][envelope] update results for empty geometries --- test/algorithms/envelope_on_spheroid.cpp | 60 +++++++++++++++--------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/test/algorithms/envelope_on_spheroid.cpp b/test/algorithms/envelope_on_spheroid.cpp index b280bec96..72b45ec9b 100644 --- a/test/algorithms/envelope_on_spheroid.cpp +++ b/test/algorithms/envelope_on_spheroid.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include +#include #include #include @@ -365,6 +367,34 @@ struct test_envelope_on_spheroid }; +template +void test_empty_geometry(std::string const& case_id, std::string const& wkt) +{ + std::size_t const dim = bg::dimension::value; + + typedef bg::model::point point_type; + typedef bg::model::box B; + typedef test_envelope_on_spheroid tester; + + typedef typename bg::coordinate_type::type ct; + ct high_val = boost::numeric::bounds::highest(); + ct low_val = boost::numeric::bounds::lowest(); + + if (BOOST_GEOMETRY_CONDITION(dim == 2)) + { + tester::apply(case_id, + from_wkt(wkt), + high_val, high_val, low_val, low_val); + } + else + { + tester::apply(case_id, + from_wkt(wkt), + high_val, high_val, high_val, low_val, low_val, low_val); + } +} + + template void test_envelope_point() { @@ -659,9 +689,7 @@ void test_envelope_multipoint() typedef test_envelope_on_spheroid tester; // empty multipoint - tester::apply("mp00", - from_wkt("MULTIPOINT()"), - 1, 1, -1, -1); + test_empty_geometry("mp00", "MULTIPOINT()"); tester::apply("mp01", from_wkt("MULTIPOINT(0 0,10 10)"), @@ -804,9 +832,7 @@ void test_envelope_multipoint_with_height() typedef test_envelope_on_spheroid tester; // empty multipoint - tester::apply("mph00", - from_wkt("MULTIPOINT()"), - 1, 1, 1, -1, -1, -1); + test_empty_geometry("mph00", "MULTIPOINT()"); tester::apply("mph01", from_wkt("MULTIPOINT(0 0 567,10 10 1456)"), @@ -1060,9 +1086,7 @@ BOOST_AUTO_TEST_CASE( envelope_linestring ) typedef test_envelope_on_spheroid tester; // empty linestring - tester::apply("l00", - from_wkt("LINESTRING()"), - 1, 1, -1, -1); + test_empty_geometry("l00", "LINESTRING()"); tester::apply("l01", from_wkt("LINESTRING(10 15)"), @@ -1181,9 +1205,7 @@ BOOST_AUTO_TEST_CASE( envelope_linestring_with_height ) typedef test_envelope_on_spheroid tester; // empty linestring - tester::apply("lh00", - from_wkt("LINESTRING()"), - 1, 1, 1, -1, -1, -1); + test_empty_geometry("lh00", "LINESTRING()"); tester::apply("lh01", from_wkt("LINESTRING(10 15 30,20 25 434,30 35 186)"), @@ -1200,19 +1222,15 @@ BOOST_AUTO_TEST_CASE( envelope_multilinestring ) typedef test_envelope_on_spheroid tester; // empty multilinestring - tester::apply("ml00", - from_wkt("MULTILINESTRING()"), - 1, 1, -1, -1); + test_empty_geometry("ml00", "MULTILINESTRING()"); // invalid multilinestring - tester::apply("ml00a", - from_wkt("MULTILINESTRING(())"), - 1, 1, -1, -1); + test_empty_geometry("ml00a", + "MULTILINESTRING(())"); // invalid multilinestring - tester::apply("ml00b", - from_wkt("MULTILINESTRING((),())"), - 1, 1, -1, -1); + test_empty_geometry("ml00b", + "MULTILINESTRING((),())"); // invalid multilinestring tester::apply("ml00c", From bfe3279990845cb74cf66494d6c224a3f469f680 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 3 Jul 2015 00:26:06 +0300 Subject: [PATCH 15/26] [algorithms][envelope] initialize consistently with assign_inverse() --- .../geometry/algorithms/detail/envelope/initialize.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp index 1346fef02..df74a1721 100644 --- a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp @@ -11,7 +11,8 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP #include -#include + +#include #include #include @@ -65,9 +66,9 @@ struct initialize static inline void apply(Box& box, coordinate_type min_value - = (std::numeric_limits::max)(), + = boost::numeric::bounds::highest(), coordinate_type max_value - = -(std::numeric_limits::max)()) + = boost::numeric::bounds::lowest()) { initialize_loop < From eec0091bc0519734e18dea9f998eee227bea94f0 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 3 Jul 2015 21:08:56 +0200 Subject: [PATCH 16/26] [get_turns][strategies] Optimize get_turns(). The optimization is based on the fact that in the most cases the segments handled in the TurnInfoPolicy are disjoint. For disjoint segments first the points are rescaled, then the test for disjoint is run, next the TurnInfoPolicy just returns and the next pair of segments is handled. Therefore to optimze the get_turns() this commit changes two things: 1. the cart_intersect strategy may return just after the calculation of sides for the first segment (2 sides calculation instead of 4), 2. the points are rescaled only one time in the intersection_helper, already rescaled points are passed into the intersection strategy --- .../detail/overlay/get_turn_info_helpers.hpp | 4 ++- .../strategies/cartesian/cart_intersect.hpp | 27 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index e0d75108b..fdae07842 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -217,7 +217,9 @@ public: : base_t(pi, pj, pk, qi, qj, qk, robust_policy) , m_result(strategy::apply(segment_type1(pi, pj), segment_type2(qi, qj), - robust_policy)) + robust_policy, + base_t::rpi(), base_t::rpj(), + base_t::rqi(), base_t::rqj())) , m_robust_policy(robust_policy) {} diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index 4b3010a40..8a9857376 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -119,15 +119,10 @@ struct relate_cartesian_segments boost::ignore_unused_variable_warning(robust_policy); - typedef typename select_calculation_type - ::type coordinate_type; - using geometry::detail::equals::equals_point_point; bool const a_is_point = equals_point_point(robust_a1, robust_a2); bool const b_is_point = equals_point_point(robust_b1, robust_b2); - typedef side::side_by_triangle side; - if(a_is_point && b_is_point) { return equals_point_point(robust_a1, robust_b2) @@ -136,20 +131,32 @@ struct relate_cartesian_segments ; } + typedef typename select_calculation_type + ::type coordinate_type; + + typedef side::side_by_triangle side; + side_info sides; sides.set<0>(side::apply(robust_b1, robust_b2, robust_a1), side::apply(robust_b1, robust_b2, robust_a2)); - sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1), - side::apply(robust_a1, robust_a2, robust_b2)); - bool collinear = sides.collinear(); - - if (sides.same<0>() || sides.same<1>()) + if (sides.same<0>()) { // Both points are at same side of other segment, we can leave return Policy::disjoint(); } + sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1), + side::apply(robust_a1, robust_a2, robust_b2)); + + if (sides.same<1>()) + { + // Both points are at same side of other segment, we can leave + return Policy::disjoint(); + } + + bool collinear = sides.collinear(); + typedef typename select_most_precise < coordinate_type, double From b376567de96680dcff2c5066ad69b07a9ffd437f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 7 Jul 2015 04:11:21 +0300 Subject: [PATCH 17/26] [algorithms][expand] remove Dimension and DimensionCount template parameters from bg::dispatch::expand --- .../geometry/algorithms/detail/expand/box.hpp | 55 +++++---- .../algorithms/detail/expand/point.hpp | 104 +++++++++--------- .../algorithms/detail/expand/segment.hpp | 44 ++++---- .../geometry/algorithms/dispatch/expand.hpp | 5 - 4 files changed, 95 insertions(+), 113 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/expand/box.hpp b/include/boost/geometry/algorithms/detail/expand/box.hpp index a9581a814..89637047e 100644 --- a/include/boost/geometry/algorithms/detail/expand/box.hpp +++ b/include/boost/geometry/algorithms/detail/expand/box.hpp @@ -23,12 +23,17 @@ #include #include -#include +#include +#include + +#include #include #include #include + #include + #include @@ -39,27 +44,19 @@ namespace boost { namespace geometry namespace detail { namespace expand { -template + struct box_on_spheroid { template static inline void apply(BoxOut& box_out, BoxIn const& box_in) { - typedef detail::envelope::envelope_box - < - Dimension, DimensionCount, CS_Tag - > envelope_box; - // normalize both boxes and convert box-in to be of type of box-out BoxOut mbrs[2]; - envelope_box::apply(box_in, mbrs[0]); - envelope_box::apply(box_out, mbrs[1]); + detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]); + detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]); // compute the envelope of the two boxes - detail::envelope::envelope_range_of_boxes - < - Dimension, DimensionCount - >::apply(mbrs, box_out); + detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); } }; @@ -76,53 +73,51 @@ namespace dispatch template < typename BoxOut, typename BoxIn, - std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater, typename CSTagOut, typename CSTag > struct expand < BoxOut, BoxIn, - Dimension, DimensionCount, StrategyLess, StrategyGreater, - box_tag, box_tag, CSTagOut, CSTag + StrategyLess, StrategyGreater, + box_tag, box_tag, + CSTagOut, CSTag > : detail::expand::expand_indexed < - Dimension, DimensionCount, StrategyLess, StrategyGreater + 0, dimension::value, StrategyLess, StrategyGreater > -{}; +{ + BOOST_MPL_ASSERT_MSG((boost::is_same::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types())); +}; template < typename BoxOut, typename BoxIn, - std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater > struct expand < BoxOut, BoxIn, - Dimension, DimensionCount, StrategyLess, StrategyGreater, - box_tag, box_tag, spherical_equatorial_tag, spherical_equatorial_tag + StrategyLess, StrategyGreater, + box_tag, box_tag, + spherical_equatorial_tag, spherical_equatorial_tag > : detail::expand::box_on_spheroid - < - Dimension, DimensionCount, spherical_equatorial_tag - > {}; template < typename BoxOut, typename BoxIn, - std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater > struct expand < BoxOut, BoxIn, - Dimension, DimensionCount, StrategyLess, StrategyGreater, - box_tag, box_tag, geographic_tag, geographic_tag + StrategyLess, StrategyGreater, + box_tag, box_tag, + geographic_tag, geographic_tag > : detail::expand::box_on_spheroid - < - Dimension, DimensionCount, geographic_tag - > {}; diff --git a/include/boost/geometry/algorithms/detail/expand/point.hpp b/include/boost/geometry/algorithms/detail/expand/point.hpp index e23e4bd91..9e96d9c7c 100644 --- a/include/boost/geometry/algorithms/detail/expand/point.hpp +++ b/include/boost/geometry/algorithms/detail/expand/point.hpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -54,8 +55,7 @@ namespace detail { namespace expand template < typename StrategyLess, typename StrategyGreater, - std::size_t Dimension, std::size_t DimensionCount, - typename CS_Tag + std::size_t Dimension, std::size_t DimensionCount > struct point_loop { @@ -72,7 +72,10 @@ struct point_loop StrategyGreater, -1, Point, Dimension >::type greater_type; - typedef typename select_coordinate_type::type coordinate_type; + typedef typename select_coordinate_type + < + Point, Box + >::type coordinate_type; less_type less; greater_type greater; @@ -91,8 +94,7 @@ struct point_loop point_loop < - StrategyLess, StrategyGreater, Dimension + 1, DimensionCount, - CS_Tag + StrategyLess, StrategyGreater, Dimension + 1, DimensionCount >::apply(box, source); } }; @@ -100,13 +102,11 @@ struct point_loop template < - typename StrategyLess, typename StrategyGreater, - std::size_t DimensionCount, typename CS_Tag + typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount > struct point_loop < - StrategyLess, StrategyGreater, DimensionCount, DimensionCount, - CS_Tag + StrategyLess, StrategyGreater, DimensionCount, DimensionCount > { template @@ -114,18 +114,14 @@ struct point_loop }; -// specialization for the spherical equatorial coordinate system +// implementation for the spherical equatorial and geographic coordinate systems template < typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount > -struct point_loop - < - StrategyLess, StrategyGreater, 0, DimensionCount, - spherical_equatorial_tag - > +struct point_loop_on_spheroid { template static inline void apply(Box& box, Point const& point) @@ -227,46 +223,12 @@ struct point_loop point_loop < - StrategyLess, StrategyGreater, 2, DimensionCount, - spherical_equatorial_tag + StrategyLess, StrategyGreater, 2, DimensionCount >::apply(box, point); } }; -// specializations for the geographic coordinate system -template -< - typename StrategyLess, typename StrategyGreater, - std::size_t Dimension, std::size_t DimensionCount -> -struct point_loop - < - StrategyLess, StrategyGreater, Dimension, DimensionCount, - geographic_tag - > : point_loop - < - StrategyLess, StrategyGreater, Dimension, DimensionCount, - spherical_equatorial_tag - > -{}; - -template -< - typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount -> -struct point_loop - < - StrategyLess, StrategyGreater, DimensionCount, DimensionCount, - geographic_tag - > : point_loop - < - StrategyLess, StrategyGreater, DimensionCount, DimensionCount, - spherical_equatorial_tag - > -{}; - - }} // namespace detail::expand #endif // DOXYGEN_NO_DETAIL @@ -279,18 +241,18 @@ namespace dispatch template < typename BoxOut, typename Point, - std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater, typename CSTagOut, typename CSTag > struct expand < BoxOut, Point, - Dimension, DimensionCount, StrategyLess, StrategyGreater, - box_tag, point_tag, CSTagOut, CSTag + StrategyLess, StrategyGreater, + box_tag, point_tag, + CSTagOut, CSTag > : detail::expand::point_loop < - StrategyLess, StrategyGreater, Dimension, DimensionCount, CSTag + StrategyLess, StrategyGreater, 0, dimension::value > { BOOST_MPL_ASSERT_MSG((boost::is_same::value), @@ -298,6 +260,40 @@ struct expand (types())); }; +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::expand::point_loop_on_spheroid + < + StrategyLess, StrategyGreater, dimension::value + > +{}; + +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + geographic_tag, geographic_tag + > : detail::expand::point_loop_on_spheroid + < + StrategyLess, StrategyGreater, dimension::value + > +{}; + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/algorithms/detail/expand/segment.hpp b/include/boost/geometry/algorithms/detail/expand/segment.hpp index 411e698a2..e78cf466d 100644 --- a/include/boost/geometry/algorithms/detail/expand/segment.hpp +++ b/include/boost/geometry/algorithms/detail/expand/segment.hpp @@ -20,13 +20,16 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP +#include +#include + +#include #include #include #include #include -#include #include #include @@ -40,8 +43,7 @@ namespace detail { namespace expand { -template -struct segment_on_spheroid +struct segment_on_sphere { template static inline void apply(Box& box, Segment const& segment) @@ -49,22 +51,16 @@ struct segment_on_spheroid Box mbrs[2]; // compute the envelope of the segment - dispatch::envelope + detail::envelope::envelope_segment_on_sphere < - Segment, Dimension, DimensionCount + dimension::value >::apply(segment, mbrs[0]); // normalize the box - detail::envelope::envelope_box - < - Dimension, DimensionCount, CS_Tag - >::apply(box, mbrs[1]); + detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]); // compute the envelope of the two boxes - detail::envelope::envelope_range_of_boxes - < - Dimension, DimensionCount - >::apply(mbrs, box); + detail::envelope::envelope_range_of_boxes::apply(mbrs, box); } }; @@ -80,37 +76,37 @@ namespace dispatch template < typename Box, typename Segment, - std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater, typename CSTagOut, typename CSTag > struct expand < Box, Segment, - Dimension, DimensionCount, StrategyLess, StrategyGreater, - box_tag, segment_tag, CSTagOut, CSTag + StrategyLess, StrategyGreater, + box_tag, segment_tag, + CSTagOut, CSTag > : detail::expand::expand_indexed < - Dimension, DimensionCount, StrategyLess, StrategyGreater + 0, dimension::value, StrategyLess, StrategyGreater > -{}; +{ + BOOST_MPL_ASSERT_MSG((boost::is_same::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types())); +}; template < typename Box, typename Segment, - std::size_t Dimension, std::size_t DimensionCount, typename StrategyLess, typename StrategyGreater > struct expand < Box, Segment, - Dimension, DimensionCount, StrategyLess, StrategyGreater, + StrategyLess, StrategyGreater, box_tag, segment_tag, spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::segment_on_spheroid - < - Dimension, DimensionCount, spherical_equatorial_tag - > + > : detail::expand::segment_on_sphere {}; diff --git a/include/boost/geometry/algorithms/dispatch/expand.hpp b/include/boost/geometry/algorithms/dispatch/expand.hpp index 3aa5f67b1..e290080ac 100644 --- a/include/boost/geometry/algorithms/dispatch/expand.hpp +++ b/include/boost/geometry/algorithms/dispatch/expand.hpp @@ -20,9 +20,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP #define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP -#include - -#include #include #include @@ -42,8 +39,6 @@ namespace dispatch template < typename GeometryOut, typename Geometry, - std::size_t Dimension = 0, - std::size_t DimensionCount = dimension::value, typename StrategyLess = strategy::compare::default_strategy, typename StrategyGreater = strategy::compare::default_strategy, typename TagOut = typename tag::type, From fc7ed8f7ab2ac0fd9364c97d5f9580e5e89d0d41 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 7 Jul 2015 04:29:58 +0300 Subject: [PATCH 18/26] [algorithms][envelope] remove Dimension and DimensionCount template parameters from bg::dispatch::envelope --- .../algorithms/detail/envelope/box.hpp | 75 +++----- .../detail/envelope/implementation.hpp | 39 ++-- .../algorithms/detail/envelope/linestring.hpp | 170 ++---------------- .../detail/envelope/multilinestring.hpp | 63 +------ .../algorithms/detail/envelope/multipoint.hpp | 102 ++++------- .../algorithms/detail/envelope/point.hpp | 40 ++--- .../algorithms/detail/envelope/range.hpp | 109 +++++++---- .../detail/envelope/range_of_boxes.hpp | 11 +- .../algorithms/detail/envelope/segment.hpp | 56 ++++-- .../geometry/algorithms/dispatch/envelope.hpp | 5 - 10 files changed, 230 insertions(+), 440 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/box.hpp b/include/boost/geometry/algorithms/detail/envelope/box.hpp index d65fae019..37c37dc5e 100644 --- a/include/boost/geometry/algorithms/detail/envelope/box.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/box.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -46,8 +47,7 @@ template < std::size_t Index, std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag + std::size_t DimensionCount > struct envelope_indexed_box { @@ -72,13 +72,12 @@ template std::size_t Index, std::size_t DimensionCount > -struct envelope_indexed_box +struct envelope_indexed_box_on_spheroid { template static inline void apply(BoxIn const& box_in, BoxOut& mbr) { - - // transform() does not work with boxes of dimension higher + // transform() does not work with boxes of dimension higher // than 2; to account for such boxes we transform the min/max // points of the boxes using the indexed_point_view detail::indexed_point_view box_in_corner(box_in); @@ -98,26 +97,7 @@ struct envelope_indexed_box } }; -template -< - std::size_t Index, - std::size_t Dimension, - std::size_t DimensionCount -> -struct envelope_indexed_box - : envelope_indexed_box - < - Index, Dimension, DimensionCount, spherical_equatorial_tag - > -{}; - -template -< - typename std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag -> struct envelope_box { template @@ -125,44 +105,37 @@ struct envelope_box { envelope_indexed_box < - min_corner, Dimension, DimensionCount, CS_Tag + min_corner, 0, dimension::value >::apply(box_in, mbr); envelope_indexed_box < - max_corner, Dimension, DimensionCount, CS_Tag + max_corner, 0, dimension::value >::apply(box_in, mbr); } }; -template -struct envelope_box<0, DimensionCount, spherical_equatorial_tag> +struct envelope_box_on_spheroid { template static inline void apply(BoxIn const& box_in, BoxOut& mbr) { BoxIn box_in_normalized = detail::return_normalized(box_in); - envelope_indexed_box + envelope_indexed_box_on_spheroid < - min_corner, 0, DimensionCount, spherical_equatorial_tag + min_corner, dimension::value >::apply(box_in_normalized, mbr); - envelope_indexed_box + envelope_indexed_box_on_spheroid < - max_corner, 0, DimensionCount, spherical_equatorial_tag + max_corner, dimension::value >::apply(box_in_normalized, mbr); } }; -template -struct envelope_box<0, DimensionCount, geographic_tag> - : envelope_box<0, DimensionCount, spherical_equatorial_tag> -{}; - - }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -171,20 +144,26 @@ namespace dispatch { -template -< - typename Box, - std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag -> -struct envelope - : detail::envelope::envelope_box +template +struct envelope + : detail::envelope::envelope_box +{}; + + +template +struct envelope + : detail::envelope::envelope_box_on_spheroid +{}; + + +template +struct envelope + : detail::envelope::envelope_box_on_spheroid {}; } // namespace dispatch -#endif +#endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp index 60d1394d9..0691dda94 100644 --- a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -19,9 +19,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP -#include - #include +#include #include #include @@ -33,7 +32,6 @@ #include #include #include -#include #include @@ -46,7 +44,6 @@ namespace detail { namespace envelope { -template struct envelope_polygon { template @@ -60,15 +57,13 @@ struct envelope_polygon // if the exterior ring is empty, consider the interior rings envelope_multi_range < - Dimension, - DimensionCount, - envelope_range + envelope_range >::apply(interior_rings(polygon), mbr); } else { // otherwise, consider only the exterior ring - envelope_range::apply(ext_ring, mbr); + envelope_range::apply(ext_ring, mbr); } } }; @@ -82,36 +77,30 @@ namespace dispatch { -template -struct envelope - : detail::envelope::envelope_range +template +struct envelope + : detail::envelope::envelope_range {}; -template -struct envelope - : detail::envelope::envelope_polygon +template +struct envelope + : detail::envelope::envelope_polygon {}; -template -< - typename MultiPolygon, - std::size_t Dimension, - std::size_t DimensionCount -> -struct envelope +template +struct envelope : detail::envelope::envelope_multi_range < - Dimension, - DimensionCount, - detail::envelope::envelope_polygon + detail::envelope::envelope_polygon > {}; } // namespace dispatch -#endif +#endif // DOXYGEN_NO_DISPATCH + }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp index fab2588d0..2eedb7bf7 100644 --- a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/linestring.hpp @@ -19,26 +19,12 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP -#include -#include -#include - -#include -#include -#include -#include #include #include #include -#include - -#include - -#include #include -#include #include @@ -51,133 +37,18 @@ namespace detail { namespace envelope { -template -struct envelope_linear_on_spheroid +struct envelope_linestring_on_spheroid { - template - static inline OutputIterator push_interval(Longitude const& lon1, - Longitude const& lon2, - OutputIterator oit) + template + static inline void apply(Linestring const& linestring, Box& mbr) { - typedef longitude_interval interval_type; - - typedef math::detail::constants_on_spheroid - < - Longitude, Units - > constants; - - BOOST_GEOMETRY_ASSERT(! math::larger(lon1, lon2)); - BOOST_GEOMETRY_ASSERT(! math::larger(lon1, constants::max_longitude())); - - if (math::larger(lon2, constants::max_longitude())) - { - *oit++ = interval_type(lon1, constants::max_longitude()); - *oit++ = interval_type(constants::min_longitude(), - lon2 - constants::period()); - } - else - { - *oit++ = interval_type(lon1, lon2); - } - return oit; - } - - template - static inline void apply(Linear const& linear, Box& mbr) - { - typedef typename coordinate_type::type box_coordinate_type; - typedef longitude_interval interval_type; - - typedef typename geometry::segment_iterator - < - Linear const - > iterator_type; - - if (geometry::is_empty(linear)) - { - initialize::apply(mbr); - return; - } - - initialize::apply(mbr); - - std::vector longitude_intervals; - std::back_insert_iterator - < - std::vector - > oit(longitude_intervals); - - box_coordinate_type lat_min = 0, lat_max = 0; - bool first = true; - for (iterator_type seg_it = geometry::segments_begin(linear); - seg_it != geometry::segments_end(linear); - ++seg_it, first = false) - { - Box segment_mbr; - dispatch::envelope - < - typename std::iterator_traits::value_type, - 0, - DimensionCount - >::apply(*seg_it, segment_mbr); - - oit = push_interval - < - typename coordinate_system::type::units - >(geometry::get(segment_mbr), - geometry::get(segment_mbr), - oit); - - if (first) - { - lat_min = geometry::get(segment_mbr); - lat_max = geometry::get(segment_mbr); - } - - // update min and max latitude, if needed - if (math::smaller(geometry::get(segment_mbr), - lat_min)) - { - lat_min = geometry::get(segment_mbr); - } - - if (math::larger(geometry::get(segment_mbr), - lat_max)) - { - lat_max = geometry::get(segment_mbr); - } - } - - box_coordinate_type lon_min = 0, lon_max = 0; - envelope_range_of_longitudes - < - typename coordinate_system::type::units - >::apply(longitude_intervals, lon_min, lon_max); - - geometry::set(mbr, lon_min); - geometry::set(mbr, lat_min); - geometry::set(mbr, lon_max); - geometry::set(mbr, lat_max); - - dispatch::envelope - < - Linear, 2, DimensionCount - >::apply(linear, mbr); + envelope_range::apply(geometry::segments_begin(linestring), + geometry::segments_end(linestring), + mbr); } }; -template -struct envelope_linestring_on_spheroid - : envelope_range -{}; - -template -struct envelope_linestring_on_spheroid<0, DimensionCount> - : envelope_linear_on_spheroid -{}; - - }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -187,31 +58,14 @@ namespace dispatch { -template -< - typename Linestring, - std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag -> -struct envelope - : detail::envelope::envelope_range +template +struct envelope + : detail::envelope::envelope_range {}; -template -< - typename Linestring, - std::size_t Dimension, - std::size_t DimensionCount -> -struct envelope - < - Linestring, Dimension, DimensionCount, - linestring_tag, spherical_equatorial_tag - > : detail::envelope::envelope_linestring_on_spheroid - < - Dimension, DimensionCount - > +template +struct envelope + : detail::envelope::envelope_linestring_on_spheroid {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp index 21888a65a..06e7b7c70 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp @@ -19,12 +19,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP -#include - -#include #include -#include #include #include @@ -34,76 +30,35 @@ namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace envelope -{ - - -template -struct envelope_multilinestring_on_spheroid - : envelope_multi_range - < - Dimension, - DimensionCount, - detail::envelope::envelope_range - > -{}; - -template -struct envelope_multilinestring_on_spheroid<0, DimensionCount> - : envelope_linear_on_spheroid -{}; - - -}} // namespace detail::envelope -#endif // DOXYGEN_NO_DETAIL - - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -< - typename MultiLinestring, - std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag -> +template struct envelope < - MultiLinestring, - Dimension, DimensionCount, - multi_linestring_tag, CS_Tag + MultiLinestring, multi_linestring_tag, CS_Tag > : detail::envelope::envelope_multi_range < - Dimension, - DimensionCount, - detail::envelope::envelope_range + detail::envelope::envelope_range > {}; -template -< - typename MultiLinestring, - std::size_t Dimension, - std::size_t DimensionCount -> +template struct envelope < - MultiLinestring, - Dimension, DimensionCount, - multi_linestring_tag, spherical_equatorial_tag - > : detail::envelope::envelope_multilinestring_on_spheroid + MultiLinestring, multi_linestring_tag, spherical_equatorial_tag + > : detail::envelope::envelope_multi_range_on_spheroid < - Dimension, DimensionCount + detail::envelope::envelope_linestring_on_spheroid > {}; } // namespace dispatch -#endif +#endif // DOXYGEN_NO_DISPATCH + }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp index 29a17b6a1..093734432 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -46,13 +47,7 @@ namespace detail { namespace envelope { -template -struct envelope_multipoint_on_spheroid - : envelope_range -{}; - -template -class envelope_multipoint_on_spheroid<0, DimensionCount, CS_Tag> +class envelope_multipoint_on_spheroid { private: template @@ -235,6 +230,10 @@ public: { typedef typename point_type::type point_type; typedef typename coordinate_type::type coordinate_type; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; typedef math::detail::constants_on_spheroid < @@ -244,7 +243,7 @@ public: if (boost::empty(multipoint)) { - initialize::apply(mbr); + initialize::value>::apply(mbr); return; } @@ -254,9 +253,7 @@ public: { return dispatch::envelope < - typename boost::range_value::type, - 0, - DimensionCount + typename boost::range_value::type >::apply(range::front(multipoint), mbr); } @@ -325,22 +322,23 @@ public: geometry::set(helper_mbr, lon_max); geometry::set(helper_mbr, lat_max); - // compute envelope for higher coordinates - envelope_multipoint_on_spheroid - < - 2, DimensionCount, CS_Tag - >::apply(multipoint, helper_mbr); - // now transform to output MBR (per index) - envelope_indexed_box - < - min_corner, 0, DimensionCount, CS_Tag - >::apply(helper_mbr, mbr); + envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); + envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); - envelope_indexed_box - < - max_corner, 0, DimensionCount, CS_Tag - >::apply(helper_mbr, mbr); + // compute envelope for higher coordinates + iterator_type it = boost::begin(multipoint); + envelope_one_point<2, dimension::value>::apply(*it, mbr); + + for (++it; it != boost::end(multipoint); ++it) + { + detail::expand::point_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + 2, dimension::value + >::apply(mbr, *it); + } } }; @@ -355,58 +353,24 @@ namespace dispatch { -template -< - typename MultiPoint, - std::size_t Dimension, - std::size_t DimensionCount, - typename CSTag -> -struct envelope - < - MultiPoint, - Dimension, DimensionCount, - multi_point_tag, CSTag - > : detail::envelope::envelope_range +template +struct envelope + : detail::envelope::envelope_range {}; -template -< - typename MultiPoint, - std::size_t Dimension, - std::size_t DimensionCount -> -struct envelope - < - MultiPoint, - Dimension, DimensionCount, - multi_point_tag, spherical_equatorial_tag - > : detail::envelope::envelope_multipoint_on_spheroid - < - Dimension, DimensionCount, spherical_equatorial_tag - > +template +struct envelope + : detail::envelope::envelope_multipoint_on_spheroid {}; -template -< - typename MultiPoint, - std::size_t Dimension, - std::size_t DimensionCount -> -struct envelope - < - MultiPoint, - Dimension, DimensionCount, - multi_point_tag, geographic_tag - > : detail::envelope::envelope_multipoint_on_spheroid - < - Dimension, DimensionCount, geographic_tag - > +template +struct envelope + : detail::envelope::envelope_multipoint_on_spheroid {}; } // namespace dispatch -#endif +#endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/envelope/point.hpp b/include/boost/geometry/algorithms/detail/envelope/point.hpp index 6fd7f93a5..0955a7ffc 100644 --- a/include/boost/geometry/algorithms/detail/envelope/point.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/point.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -44,7 +45,7 @@ namespace detail { namespace envelope { -template +template struct envelope_one_point { template @@ -69,8 +70,7 @@ struct envelope_one_point }; -template -struct envelope_one_point<0, DimensionCount, spherical_equatorial_tag> +struct envelope_point_on_spheroid { template static inline void apply(Point const& point, Box& mbr) @@ -90,18 +90,12 @@ struct envelope_one_point<0, DimensionCount, spherical_equatorial_tag> envelope_one_point < - 2, DimensionCount, spherical_equatorial_tag + 2, dimension::value >::apply(normalized_point, mbr); } }; -template -struct envelope_one_point - : envelope_one_point -{}; - - }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -110,20 +104,26 @@ namespace dispatch { -template -< - typename Point, - std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag -> -struct envelope - : detail::envelope::envelope_one_point +template +struct envelope + : detail::envelope::envelope_one_point<0, dimension::value> +{}; + + +template +struct envelope + : detail::envelope::envelope_point_on_spheroid +{}; + + +template +struct envelope + : detail::envelope::envelope_point_on_spheroid {}; } // namespace dispatch -#endif +#endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/envelope/range.hpp b/include/boost/geometry/algorithms/detail/envelope/range.hpp index d19469463..0d4a74513 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -19,18 +19,24 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP -#include +#include +#include #include +#include + #include #include #include +#include + #include #include #include + #include @@ -43,48 +49,40 @@ namespace detail { namespace envelope // implementation for simple ranges -template struct envelope_range { + template + static inline void apply(Iterator first, Iterator last, Box& mbr) + { + typedef typename std::iterator_traits::value_type value_type; + + // initialize MBR + initialize::value>::apply(mbr); + + Iterator it = first; + if (it != last) + { + // initialize box with first element in range + dispatch::envelope::apply(*it, mbr); + + // consider now the remaining elements in the range (if any) + for (++it; it != last; ++it) + { + dispatch::expand::apply(mbr, *it); + } + } + } + template static inline void apply(Range const& range, Box& mbr) { - typedef typename boost::range_value::type value_type; - - // initialize MBR - initialize::apply(mbr); - - typename boost::range_iterator::type it - = boost::begin(range); - - if (it != boost::end(range)) - { - // initialize box with first element in range - dispatch::envelope - < - value_type, Dimension, DimensionCount - >::apply(*it, mbr); - - // consider now the remaining elements in the range (if any) - for (++it; it != boost::end(range); ++it) - { - dispatch::expand - < - Box, value_type, Dimension, DimensionCount - >::apply(mbr, *it); - } - } + return apply(boost::begin(range), boost::end(range), mbr); } }; // implementation for multi-ranges -template -< - std::size_t Dimension, - std::size_t DimensionCount, - typename EnvelopePolicy -> +template struct envelope_multi_range { template @@ -96,7 +94,7 @@ struct envelope_multi_range >::type iterator_type; // initialize MBR - initialize::apply(mbr); + initialize::value>::apply(mbr); // skip through empty geometries iterator_type it = boost::begin(multirange); @@ -120,10 +118,7 @@ struct envelope_multi_range Box helper_mbr; EnvelopePolicy::apply(*it, helper_mbr); - dispatch::expand - < - Box, Box, Dimension, DimensionCount - >::apply(mbr, helper_mbr); + dispatch::expand::apply(mbr, helper_mbr); } } } @@ -131,6 +126,44 @@ struct envelope_multi_range }; +// implementation for multi-range on a spheroid (longitude is periodic) +template +struct envelope_multi_range_on_spheroid +{ + template + static inline void apply(MultiRange const& multirange, Box& mbr) + { + typedef typename boost::range_iterator + < + MultiRange const + >::type iterator_type; + + // initialize MBR + initialize::value>::apply(mbr); + + // compute the boxes of the single geometries + std::vector boxes; + for (iterator_type it = boost::begin(multirange); + it != boost::end(multirange); + ++it) + { + if (! geometry::is_empty(*it)) + { + Box helper_box; + EnvelopePolicy::apply(*it, helper_box); + boxes.push_back(helper_box); + } + } + + // compute the envelope of the range of boxes + if (! boxes.empty()) + { + envelope_range_of_boxes::apply(boxes, mbr); + } + } +}; + + }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp index 5d0ef3455..b7d9e57b7 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -146,7 +146,7 @@ struct envelope_range_of_longitudes template -struct envelope_range_of_boxes +struct envelope_range_of_boxes_by_expansion { template static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) @@ -210,8 +210,8 @@ struct envelope_range_of_boxes }; -template -struct envelope_range_of_boxes<0, DimensionCount> + +struct envelope_range_of_boxes { template struct latitude_less @@ -309,7 +309,10 @@ struct envelope_range_of_boxes<0, DimensionCount> // what remains to be done is to compute the envelope range // for the remaining dimensions (if any) - envelope_range_of_boxes<2, DimensionCount>::apply(range_of_boxes, mbr); + envelope_range_of_boxes_by_expansion + < + 2, dimension::value + >::apply(range_of_boxes, mbr); } }; diff --git a/include/boost/geometry/algorithms/detail/envelope/segment.hpp b/include/boost/geometry/algorithms/detail/envelope/segment.hpp index cf90b551c..5970cae8d 100644 --- a/include/boost/geometry/algorithms/detail/envelope/segment.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -43,6 +43,7 @@ #include #include + #include #include @@ -56,16 +57,19 @@ namespace detail { namespace envelope { -template +template struct envelope_one_segment { template static inline void apply(Point const& p1, Point const& p2, Box& mbr) { - envelope_one_point::apply(p1, mbr); - dispatch::expand + envelope_one_point::apply(p1, mbr); + detail::expand::point_loop < - Box, Point, Dimension, DimensionCount + strategy::compare::default_strategy, + strategy::compare::default_strategy, + Dimension, + DimensionCount >::apply(mbr, p2); } }; @@ -306,7 +310,7 @@ public: template -struct envelope_one_segment<0, DimensionCount, spherical_equatorial_tag> +struct envelope_segment_on_sphere { template static inline void apply(Point const& p1, Point const& p2, Box& mbr) @@ -323,14 +327,34 @@ struct envelope_one_segment<0, DimensionCount, spherical_equatorial_tag> // now compute the envelope range for coordinates of // dimension 2 and higher - envelope_one_segment - < - 2, DimensionCount, spherical_equatorial_tag - >::apply(p1, p2, mbr); + envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr); + } + + template + static inline void apply(Segment const& segment, Box& mbr) + { + typename point_type::type p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + apply(p[0], p[1], mbr); } }; + +template +struct envelope_segment + : envelope_one_segment<0, DimensionCount> +{}; + + +template +struct envelope_segment + : envelope_segment_on_sphere +{}; + + + }} // namespace detail::envelope #endif // DOXYGEN_NO_DETAIL @@ -340,14 +364,8 @@ namespace dispatch { -template -< - typename Segment, - std::size_t Dimension, - std::size_t DimensionCount, - typename CS_Tag -> -struct envelope +template +struct envelope { template static inline void apply(Segment const& segment, Box& mbr) @@ -355,9 +373,9 @@ struct envelope typename point_type::type p[2]; detail::assign_point_from_index<0>(segment, p[0]); detail::assign_point_from_index<1>(segment, p[1]); - detail::envelope::envelope_one_segment + detail::envelope::envelope_segment < - Dimension, DimensionCount, CS_Tag + dimension::value, CS_Tag >::apply(p[0], p[1], mbr); } }; diff --git a/include/boost/geometry/algorithms/dispatch/envelope.hpp b/include/boost/geometry/algorithms/dispatch/envelope.hpp index 3ac238754..dcf3362ae 100644 --- a/include/boost/geometry/algorithms/dispatch/envelope.hpp +++ b/include/boost/geometry/algorithms/dispatch/envelope.hpp @@ -19,9 +19,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP -#include - -#include #include #include @@ -38,8 +35,6 @@ namespace dispatch template < typename Geometry, - std::size_t Dimension = 0, - std::size_t DimensionCount = dimension::value, typename Tag = typename tag::type, typename CS_Tag = typename cs_tag::type > From ba8bc966b136405822acd1b2147878f039d436de Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 7 Jul 2015 04:32:30 +0300 Subject: [PATCH 19/26] [algorithms][envelope] merge implementation of envelope for linestrings and multilinestrings into a single file for linear geometries --- .../detail/envelope/implementation.hpp | 3 +- .../envelope/{linestring.hpp => linear.hpp} | 27 +++++++- .../detail/envelope/multilinestring.hpp | 65 ------------------- 3 files changed, 25 insertions(+), 70 deletions(-) rename include/boost/geometry/algorithms/detail/envelope/{linestring.hpp => linear.hpp} (73%) delete mode 100644 include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp diff --git a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp index 0691dda94..191fb777b 100644 --- a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -26,8 +26,7 @@ #include #include -#include -#include +#include #include #include #include diff --git a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp b/include/boost/geometry/algorithms/detail/envelope/linear.hpp similarity index 73% rename from include/boost/geometry/algorithms/detail/envelope/linestring.hpp rename to include/boost/geometry/algorithms/detail/envelope/linear.hpp index 2eedb7bf7..24bfce57a 100644 --- a/include/boost/geometry/algorithms/detail/envelope/linestring.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/linear.hpp @@ -16,8 +16,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR _HPP #include #include @@ -69,10 +69,31 @@ struct envelope {}; +template +struct envelope + < + MultiLinestring, multi_linestring_tag, CS_Tag + > : detail::envelope::envelope_multi_range + < + detail::envelope::envelope_range + > +{}; + +template +struct envelope + < + MultiLinestring, multi_linestring_tag, spherical_equatorial_tag + > : detail::envelope::envelope_multi_range_on_spheroid + < + detail::envelope::envelope_linestring_on_spheroid + > +{}; + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINESTRING_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp b/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp deleted file mode 100644 index 06e7b7c70..000000000 --- a/include/boost/geometry/algorithms/detail/envelope/multilinestring.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. - -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. - -// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle - -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. - -// 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_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP - -#include - -#include - -#include - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - - -template -struct envelope - < - MultiLinestring, multi_linestring_tag, CS_Tag - > : detail::envelope::envelope_multi_range - < - detail::envelope::envelope_range - > -{}; - -template -struct envelope - < - MultiLinestring, multi_linestring_tag, spherical_equatorial_tag - > : detail::envelope::envelope_multi_range_on_spheroid - < - detail::envelope::envelope_linestring_on_spheroid - > -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTILINESTRING_HPP From 7947be9bf5dfeca49aec2701398442d311252283 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 9 Jul 2015 11:21:07 +0300 Subject: [PATCH 20/26] [algorithms][expand] update copyright headers to follow latest license-related wording --- include/boost/geometry/algorithms/detail/expand/box.hpp | 7 ++----- .../geometry/algorithms/detail/expand/implementation.hpp | 4 ++-- .../boost/geometry/algorithms/detail/expand/indexed.hpp | 4 ++-- .../boost/geometry/algorithms/detail/expand/interface.hpp | 4 ++-- include/boost/geometry/algorithms/detail/expand/point.hpp | 4 ++-- .../boost/geometry/algorithms/detail/expand/segment.hpp | 7 ++----- include/boost/geometry/algorithms/dispatch/expand.hpp | 4 ++-- include/boost/geometry/algorithms/expand.hpp | 4 ++-- 8 files changed, 16 insertions(+), 22 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/expand/box.hpp b/include/boost/geometry/algorithms/detail/expand/box.hpp index 89637047e..4c89e6f1d 100644 --- a/include/boost/geometry/algorithms/detail/expand/box.hpp +++ b/include/boost/geometry/algorithms/detail/expand/box.hpp @@ -10,11 +10,8 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_EXPAND_BOX_HPP diff --git a/include/boost/geometry/algorithms/detail/expand/implementation.hpp b/include/boost/geometry/algorithms/detail/expand/implementation.hpp index c48f2e681..95de1b504 100644 --- a/include/boost/geometry/algorithms/detail/expand/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/expand/implementation.hpp @@ -13,8 +13,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP diff --git a/include/boost/geometry/algorithms/detail/expand/indexed.hpp b/include/boost/geometry/algorithms/detail/expand/indexed.hpp index 6eae62398..bdd6eb450 100644 --- a/include/boost/geometry/algorithms/detail/expand/indexed.hpp +++ b/include/boost/geometry/algorithms/detail/expand/indexed.hpp @@ -13,8 +13,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP diff --git a/include/boost/geometry/algorithms/detail/expand/interface.hpp b/include/boost/geometry/algorithms/detail/expand/interface.hpp index 3064f1236..01936387a 100644 --- a/include/boost/geometry/algorithms/detail/expand/interface.hpp +++ b/include/boost/geometry/algorithms/detail/expand/interface.hpp @@ -13,8 +13,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP diff --git a/include/boost/geometry/algorithms/detail/expand/point.hpp b/include/boost/geometry/algorithms/detail/expand/point.hpp index 9e96d9c7c..56b7f1c73 100644 --- a/include/boost/geometry/algorithms/detail/expand/point.hpp +++ b/include/boost/geometry/algorithms/detail/expand/point.hpp @@ -13,8 +13,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_EXPAND_POINT_HPP diff --git a/include/boost/geometry/algorithms/detail/expand/segment.hpp b/include/boost/geometry/algorithms/detail/expand/segment.hpp index e78cf466d..041c1e175 100644 --- a/include/boost/geometry/algorithms/detail/expand/segment.hpp +++ b/include/boost/geometry/algorithms/detail/expand/segment.hpp @@ -10,11 +10,8 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP diff --git a/include/boost/geometry/algorithms/dispatch/expand.hpp b/include/boost/geometry/algorithms/dispatch/expand.hpp index e290080ac..2c23d6a1c 100644 --- a/include/boost/geometry/algorithms/dispatch/expand.hpp +++ b/include/boost/geometry/algorithms/dispatch/expand.hpp @@ -13,8 +13,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DISPATCH_EXPAND_HPP diff --git a/include/boost/geometry/algorithms/expand.hpp b/include/boost/geometry/algorithms/expand.hpp index 6b4820d8a..f41df5380 100644 --- a/include/boost/geometry/algorithms/expand.hpp +++ b/include/boost/geometry/algorithms/expand.hpp @@ -13,8 +13,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_EXPAND_HPP From 388c77cf25a3e44668aa52f39b540f9b04a31b7c Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 9 Jul 2015 11:21:53 +0300 Subject: [PATCH 21/26] [algorithms][envelope] update copyright headers to follow latest license-related wording; rewrite envelope_multi_range and envelope_multi_range_on_spheroid algorithms in a more clear form; --- .../algorithms/detail/envelope/box.hpp | 7 +-- .../detail/envelope/implementation.hpp | 4 +- .../algorithms/detail/envelope/initialize.hpp | 5 +- .../algorithms/detail/envelope/interface.hpp | 4 +- .../envelope/intersects_antimeridian.hpp | 5 +- .../algorithms/detail/envelope/linear.hpp | 9 ++-- .../algorithms/detail/envelope/multipoint.hpp | 5 +- .../algorithms/detail/envelope/point.hpp | 7 +-- .../algorithms/detail/envelope/range.hpp | 52 ++++++++++--------- .../detail/envelope/range_of_boxes.hpp | 5 +- .../algorithms/detail/envelope/segment.hpp | 7 +-- .../detail/envelope/transform_units.hpp | 5 +- .../geometry/algorithms/dispatch/envelope.hpp | 4 +- .../boost/geometry/algorithms/envelope.hpp | 4 +- 14 files changed, 59 insertions(+), 64 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/box.hpp b/include/boost/geometry/algorithms/detail/envelope/box.hpp index 37c37dc5e..379026294 100644 --- a/include/boost/geometry/algorithms/detail/envelope/box.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/box.hpp @@ -9,11 +9,8 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp index 191fb777b..c1dbf8e58 100644 --- a/include/boost/geometry/algorithms/detail/envelope/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -12,8 +12,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp index df74a1721..d8e252b53 100644 --- a/include/boost/geometry/algorithms/detail/envelope/initialize.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/initialize.hpp @@ -4,8 +4,9 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Licensed under the Boost Software License version 1.0. -// http://www.boost.org/users/license.html +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/interface.hpp b/include/boost/geometry/algorithms/detail/envelope/interface.hpp index 3c1b2b9fe..997ac1b23 100644 --- a/include/boost/geometry/algorithms/detail/envelope/interface.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/interface.hpp @@ -12,8 +12,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp b/include/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp index 4bd917796..47937bf74 100644 --- a/include/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp @@ -4,8 +4,9 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Licensed under the Boost Software License version 1.0. -// http://www.boost.org/users/license.html +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/linear.hpp b/include/boost/geometry/algorithms/detail/envelope/linear.hpp index 24bfce57a..49c3cf313 100644 --- a/include/boost/geometry/algorithms/detail/envelope/linear.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/linear.hpp @@ -9,15 +9,12 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR _HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP #include #include diff --git a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp index 093734432..210debfdb 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -4,8 +4,9 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Licensed under the Boost Software License version 1.0. -// http://www.boost.org/users/license.html +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/point.hpp b/include/boost/geometry/algorithms/detail/envelope/point.hpp index 0955a7ffc..e914e7e8a 100644 --- a/include/boost/geometry/algorithms/detail/envelope/point.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/point.hpp @@ -9,11 +9,8 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/range.hpp b/include/boost/geometry/algorithms/detail/envelope/range.hpp index 0d4a74513..be520c55f 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -12,8 +12,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP @@ -93,35 +93,34 @@ struct envelope_multi_range MultiRange const >::type iterator_type; - // initialize MBR - initialize::value>::apply(mbr); - - // skip through empty geometries - iterator_type it = boost::begin(multirange); - while (it != boost::end(multirange) && geometry::is_empty(*it)) + bool initialized = false; + for (iterator_type it = boost::begin(multirange); + it != boost::end(multirange); + ++it) { - ++it; - } - - // if there are still elements left, apply the envelope policy - if (it != boost::end(multirange)) - { - // compute the initial envelope - EnvelopePolicy::apply(*it, mbr); - - // for the remaining non-empty geometries just expand the mbr - // using the envelope - for (++it; it != boost::end(multirange); ++it) + if (! geometry::is_empty(*it)) { - if (! geometry::is_empty(*it)) + if (initialized) { Box helper_mbr; EnvelopePolicy::apply(*it, helper_mbr); dispatch::expand::apply(mbr, helper_mbr); } + else + { + // compute the initial envelope + EnvelopePolicy::apply(*it, mbr); + initialized = true; + } } } + + if (! initialized) + { + // if not already initialized, initialize MBR + initialize::value>::apply(mbr); + } } }; @@ -138,9 +137,6 @@ struct envelope_multi_range_on_spheroid MultiRange const >::type iterator_type; - // initialize MBR - initialize::value>::apply(mbr); - // compute the boxes of the single geometries std::vector boxes; for (iterator_type it = boost::begin(multirange); @@ -155,11 +151,17 @@ struct envelope_multi_range_on_spheroid } } - // compute the envelope of the range of boxes + // compute the envelope of the range of boxes or initialize if + // no boxes have been found if (! boxes.empty()) { envelope_range_of_boxes::apply(boxes, mbr); } + else + { + initialize::value>::apply(mbr); + } + } }; diff --git a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp index b7d9e57b7..64bdb9b9c 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -4,8 +4,9 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Licensed under the Boost Software License version 1.0. -// http://www.boost.org/users/license.html +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/segment.hpp b/include/boost/geometry/algorithms/detail/envelope/segment.hpp index 5970cae8d..570f0e1a4 100644 --- a/include/boost/geometry/algorithms/detail/envelope/segment.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -9,11 +9,8 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library -// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP diff --git a/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp b/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp index 94f380a1c..0c5382a47 100644 --- a/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp @@ -4,8 +4,9 @@ // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle -// Licensed under the Boost Software License version 1.0. -// http://www.boost.org/users/license.html +// Distributed under 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_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP diff --git a/include/boost/geometry/algorithms/dispatch/envelope.hpp b/include/boost/geometry/algorithms/dispatch/envelope.hpp index dcf3362ae..bb8a99f5a 100644 --- a/include/boost/geometry/algorithms/dispatch/envelope.hpp +++ b/include/boost/geometry/algorithms/dispatch/envelope.hpp @@ -12,8 +12,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_DISPATCH_ENVELOPE_HPP diff --git a/include/boost/geometry/algorithms/envelope.hpp b/include/boost/geometry/algorithms/envelope.hpp index 2f5c7430b..00981224b 100644 --- a/include/boost/geometry/algorithms/envelope.hpp +++ b/include/boost/geometry/algorithms/envelope.hpp @@ -12,8 +12,8 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// Distributed under 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_ALGORITHMS_ENVELOPE_HPP From 327df52ec5b9a7c6ced50e442967a112f095b517 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 9 Jul 2015 11:32:40 +0300 Subject: [PATCH 22/26] [algorithms][envelope] enrich comments regarding the implementation of envelope_multi_range_on_spheroid --- .../geometry/algorithms/detail/envelope/range.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/envelope/range.hpp b/include/boost/geometry/algorithms/detail/envelope/range.hpp index be520c55f..63b518114 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -137,7 +137,8 @@ struct envelope_multi_range_on_spheroid MultiRange const >::type iterator_type; - // compute the boxes of the single geometries + // due to the periodicity of longitudes we need to compute the boxes + // of all the single geometries and keep them in a container std::vector boxes; for (iterator_type it = boost::begin(multirange); it != boost::end(multirange); @@ -151,8 +152,11 @@ struct envelope_multi_range_on_spheroid } } - // compute the envelope of the range of boxes or initialize if - // no boxes have been found + // now we need to compute the envelope of the range of boxes + // (cannot be done in an incremental fashion as in the + // Cartesian coordinate system) + // if all single geometries are empty no boxes have been found + // and the MBR is simply initialized if (! boxes.empty()) { envelope_range_of_boxes::apply(boxes, mbr); From ee906b2f40a10f27b4a44b7396a611323310f2ce Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 9 Jul 2015 11:50:59 +0300 Subject: [PATCH 23/26] [algorithms][is_valid] avoid potential infinite loop in has_spikes (such an infinite loop can happen if the points in the range have NaN coordinates) --- .../algorithms/detail/is_valid/has_spikes.hpp | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index d12838de6..727057e3f 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -77,13 +78,23 @@ struct not_equal_to template struct has_spikes { + template + static inline Iterator find_not_equal(Iterator first, Iterator last) + { + typedef not_equal_to::type> not_equal; + + BOOST_ASSERT(first != last); + + Iterator second = first; + ++second; + return std::find_if(second, last, not_equal(*first)); + } + template static inline bool apply(Range const& range, VisitPolicy& visitor) { boost::ignore_unused(visitor); - typedef not_equal_to::type> not_equal; - typedef typename closeable_view::type view_type; typedef typename boost::range_iterator::type iterator; @@ -94,23 +105,23 @@ struct has_spikes iterator prev = boost::begin(view); - iterator cur = std::find_if(prev, boost::end(view), not_equal(*prev)); - if ( cur == boost::end(view) ) + iterator cur = find_not_equal(prev, boost::end(view)); + if (cur == boost::end(view)) { // the range has only one distinct point, so it // cannot have a spike return ! visitor.template apply(); } - iterator next = std::find_if(cur, boost::end(view), not_equal(*cur)); - if ( next == boost::end(view) ) + iterator next = find_not_equal(cur, boost::end(view)); + if (next == boost::end(view)) { // the range has only two distinct points, so it // cannot have a spike return ! visitor.template apply(); } - while ( next != boost::end(view) ) + while (next != boost::end(view)) { if ( geometry::detail::point_is_spike_or_equal(*prev, *next, @@ -121,20 +132,19 @@ struct has_spikes } prev = cur; cur = next; - next = std::find_if(cur, boost::end(view), not_equal(*cur)); + next = find_not_equal(cur, boost::end(view)); } - if ( geometry::equals(range::front(view), range::back(view)) ) + if (geometry::equals(range::front(view), range::back(view))) { iterator cur = boost::begin(view); typename boost::range_reverse_iterator < view_type const - >::type prev = std::find_if(boost::rbegin(view), - boost::rend(view), - not_equal(range::back(view))); - iterator next = - std::find_if(cur, boost::end(view), not_equal(*cur)); + >::type prev = find_not_equal(boost::rbegin(view), + boost::rend(view)); + + iterator next = find_not_equal(cur, boost::end(view)); if (detail::point_is_spike_or_equal(*prev, *next, *cur)) { return From 78296da4a2a61fa9480d84723ececf54d836c39b Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 10 Jul 2015 07:32:51 +0300 Subject: [PATCH 24/26] [algorithms][is_valid] replace BOOST_ASSERT by BOOST_GEOMETRY_ASSERT --- .../boost/geometry/algorithms/detail/is_valid/has_spikes.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index 727057e3f..c2eb638aa 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -12,11 +12,11 @@ #include -#include #include #include #include +#include #include #include #include @@ -83,7 +83,7 @@ struct has_spikes { typedef not_equal_to::type> not_equal; - BOOST_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(first != last); Iterator second = first; ++second; From 73960f31ca3e6483a5846bbf0b6ad601a4640fbe Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 10 Jul 2015 07:40:10 +0300 Subject: [PATCH 25/26] [test][algorithms][is_valid][is_simple] add test case with geometry that has NaN coordinates --- test/algorithms/is_simple.cpp | 22 ++++++++++++++++++++++ test/algorithms/is_valid.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index bd6ceb668..f73d6309c 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -33,6 +33,7 @@ #include +#include #include #include @@ -296,6 +297,27 @@ BOOST_AUTO_TEST_CASE( test_is_simple_areal ) false); } +BOOST_AUTO_TEST_CASE( test_geometry_with_NaN_coordinates ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; + std::cout << "************************************" << std::endl; + std::cout << " is_valid: geometry with NaN coordinates" << std::endl; + std::cout << "************************************" << std::endl; +#endif + + linestring_type ls1, ls2; + bg::read_wkt("LINESTRING(1 1,1.115235e+308 1.738137e+308)", ls1); + bg::read_wkt("LINESTRING(-1 1,1.115235e+308 1.738137e+308)", ls2); + + // the intersection of the two linestrings is a new linestring + // (multilinestring with a single element) that has NaN coordinates + multi_linestring_type mls; + bg::intersection(ls1, ls2, mls); + + test_simple(mls, true); +} + BOOST_AUTO_TEST_CASE( test_is_simple_variant ) { #ifdef BOOST_GEOMETRY_TEST_DEBUG diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index e4ead8d4d..7ec61eece 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -20,6 +20,7 @@ #include "test_is_valid.hpp" #include +#include #include BOOST_AUTO_TEST_CASE( test_is_valid_point ) @@ -1114,6 +1115,38 @@ BOOST_AUTO_TEST_CASE( test_is_valid_multipolygon ) test_open_multipolygons(); } +BOOST_AUTO_TEST_CASE( test_geometry_with_NaN_coordinates ) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; + std::cout << "************************************" << std::endl; + std::cout << " is_valid: geometry with NaN coordinates" << std::endl; + std::cout << "************************************" << std::endl; +#endif + + linestring_type ls1, ls2; + bg::read_wkt("LINESTRING(1 1,1.115235e+308 1.738137e+308)", ls1); + bg::read_wkt("LINESTRING(-1 1,1.115235e+308 1.738137e+308)", ls2); + + // the intersection of the two linestrings is a new linestring + // (multilinestring with a single element) that has NaN coordinates + multi_linestring_type mls; + bg::intersection(ls1, ls2, mls); + + typedef validity_tester_linear tester_allow_spikes; + typedef validity_tester_linear tester_disallow_spikes; + + test_valid + < + tester_allow_spikes, multi_linestring_type + >::apply("mls-NaN", mls, true); + + test_valid + < + tester_disallow_spikes, multi_linestring_type + >::apply("mls-NaN", mls, true); +} + BOOST_AUTO_TEST_CASE( test_is_valid_variant ) { #ifdef BOOST_GEOMETRY_TEST_DEBUG From 4e5da910afb89b321733f348448796813fcd3ce1 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 14 Jul 2015 20:42:16 +0300 Subject: [PATCH 26/26] [algorithms][is_valid] rename method find_not_equal to find_different_from_first (for clarity) --- .../algorithms/detail/is_valid/has_spikes.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index c2eb638aa..aa90e52db 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -79,7 +79,8 @@ template struct has_spikes { template - static inline Iterator find_not_equal(Iterator first, Iterator last) + static inline Iterator find_different_from_first(Iterator first, + Iterator last) { typedef not_equal_to::type> not_equal; @@ -105,7 +106,7 @@ struct has_spikes iterator prev = boost::begin(view); - iterator cur = find_not_equal(prev, boost::end(view)); + iterator cur = find_different_from_first(prev, boost::end(view)); if (cur == boost::end(view)) { // the range has only one distinct point, so it @@ -113,7 +114,7 @@ struct has_spikes return ! visitor.template apply(); } - iterator next = find_not_equal(cur, boost::end(view)); + iterator next = find_different_from_first(cur, boost::end(view)); if (next == boost::end(view)) { // the range has only two distinct points, so it @@ -132,7 +133,7 @@ struct has_spikes } prev = cur; cur = next; - next = find_not_equal(cur, boost::end(view)); + next = find_different_from_first(cur, boost::end(view)); } if (geometry::equals(range::front(view), range::back(view))) @@ -141,10 +142,10 @@ struct has_spikes typename boost::range_reverse_iterator < view_type const - >::type prev = find_not_equal(boost::rbegin(view), - boost::rend(view)); + >::type prev = find_different_from_first(boost::rbegin(view), + boost::rend(view)); - iterator next = find_not_equal(cur, boost::end(view)); + iterator next = find_different_from_first(cur, boost::end(view)); if (detail::point_is_spike_or_equal(*prev, *next, *cur)) { return