From 21c42ed87e81e9cfc8d8f66b5b9ada3123562054 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 21 Mar 2014 17:24:21 +0100 Subject: [PATCH 01/31] [within][get_turns] implement within() using relate() for L/L and L/A. Add some basic/NOT_FULLY_WORKING handling of collinear spikes for get_turns(L/L) --- .../detail/overlay/get_turn_info_ll.hpp | 29 +++ include/boost/geometry/algorithms/within.hpp | 175 ++++++--------- .../geometry/multi/algorithms/within.hpp | 18 +- .../agnostic/point_in_poly_winding.hpp | 40 +++- .../geometry/strategies/agnostic/relate.hpp | 207 ++++++++++++++++++ .../boost/geometry/strategies/strategies.hpp | 2 + test/algorithms/relate.cpp | 8 +- test/algorithms/within.cpp | 13 +- 8 files changed, 370 insertions(+), 122 deletions(-) create mode 100644 include/boost/geometry/strategies/agnostic/relate.hpp diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 2cee246dc..0a80bee98 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -191,6 +191,10 @@ struct get_turn_info_linear_linear replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); + + handle_possible_spike_after_equal(tp.operations[0].operation, + tp.operations[1].operation, + side_calc); AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); *out++ = tp; @@ -236,6 +240,10 @@ struct get_turn_info_linear_linear replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); + + handle_possible_spike_after_equal(tp.operations[0].operation, + tp.operations[1].operation, + side_calc); } else { @@ -291,6 +299,27 @@ struct get_turn_info_linear_linear return out; } + template + static inline void handle_possible_spike_after_equal(operation_type & op0, + operation_type & op1, + SideCalc const& side_calc) + { + // spike on P + if ( op0 == operation_union + && side_calc.pk_wrt_p1() == 0 + && side_calc.qk_wrt_p1() == -side_calc.qk_wrt_p2() ) + { + op0 = operation_continue; + } + // spike on Q + if ( op1 == operation_union + && side_calc.qk_wrt_q1() == 0 + && side_calc.pk_wrt_q1() == -side_calc.pk_wrt_q2() ) + { + op1 = operation_continue; + } + } + static inline void replace_method_and_operations_tm(method_type & method, operation_type & op0, operation_type & op1) diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index 75040782b..4bedf9469 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013. -// Modifications copyright (c) 2013, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -14,6 +14,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + #ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP #define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP @@ -61,81 +63,21 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace within { -// currently works only for linestrings -template -struct linear_linear +struct use_point_in_geometry { - template + template + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) + { + return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1; + } +}; + +struct use_relate +{ + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/) { - // TODO within() should return FALSE if a length(geometry1) == 0 and is contained entirely within a boundary, - // also if geometry2 has length(geometry2) == 0, it should be considered as a point. - - // TODO: currently only for linestrings - std::size_t s1 = boost::size(geometry1); - std::size_t s2 = boost::size(geometry2); - if ( s1 == 0 || s2 == 0 || s2 == 1 ) - return false; - if ( s1 == 1 && s2 == 1 ) // within(Pt, Pt) - return false; - if ( s1 == 1 ) - return point_in_geometry(*boost::begin(geometry1), geometry2) > 0; - - typedef typename geometry::point_type::type point1_type; - typedef detail::overlay::turn_info turn_info; - - typedef detail::overlay::get_turn_info - < - detail::overlay::assign_null_policy - > policy_type; - - std::deque turns; - - detail::get_turns::no_interrupt_policy policy; - boost::geometry::get_turns - < - detail::overlay::do_reverse::value>::value, // should be false - detail::overlay::do_reverse::value>::value, // should be false - detail::overlay::assign_null_policy - >(geometry1, geometry2, detail::no_rescale_policy(), turns, policy); - - return analyse_turns(turns.begin(), turns.end()) - // TODO: currently only for linestrings - && point_in_geometry(*boost::begin(geometry1), geometry2) >= 0 - && point_in_geometry(*(boost::end(geometry1) - 1), geometry2) >= 0; - } - - template - static inline bool analyse_turns(TurnIt first, TurnIt last) - { - bool has_turns = false; - for ( TurnIt it = first ; it != last ; ++it ) - { - switch ( it->method ) - { - case overlay::method_crosses: - return false; - case overlay::method_touch: - case overlay::method_touch_interior: - if ( it->both(overlay::operation_continue) - || it->both(overlay::operation_blocked) ) - { - has_turns = true; - } - else - return false; - case overlay::method_equal: - case overlay::method_collinear: - has_turns = true; - break; - case overlay::method_none : - case overlay::method_disjoint : - case overlay::method_error : - break; - } - } - - return has_turns; + return Strategy::apply(geometry1, geometry2); } }; @@ -180,48 +122,73 @@ struct within } }; - +// P/A template struct within -{ - template - static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy) - { - return detail::within::point_in_geometry(point, ring, strategy) == 1; - } -}; + : public detail::within::use_point_in_geometry +{}; template struct within -{ - template - static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy) - { - return detail::within::point_in_geometry(point, polygon, strategy) == 1; - } -}; + : public detail::within::use_point_in_geometry +{}; + +// P/L template struct within -{ - template static inline - bool apply(Point const& point, Linestring const& linestring, Strategy const& strategy) - { - return detail::within::point_in_geometry(point, linestring, strategy) == 1; - } -}; + : public detail::within::use_point_in_geometry +{}; + +// L/L template struct within -{ - template static inline - bool apply(Linestring1 const& linestring1, Linestring2 const& linestring2, Strategy const& strategy) - { - return detail::within::linear_linear - ::apply(linestring1, linestring2, strategy); - } -}; + : public detail::within::use_relate +{}; + +template +struct within + : public detail::within::use_relate +{}; + +template +struct within + : public detail::within::use_relate +{}; + +// L/A + +template +struct within + : public detail::within::use_relate +{}; + +template +struct within + : public detail::within::use_relate +{}; + +template +struct within + : public detail::within::use_relate +{}; + +template +struct within + : public detail::within::use_relate +{}; + +template +struct within + : public detail::within::use_relate +{}; + +template +struct within + : public detail::within::use_relate +{}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/multi/algorithms/within.hpp b/include/boost/geometry/multi/algorithms/within.hpp index ef33029df..8c8917abd 100644 --- a/include/boost/geometry/multi/algorithms/within.hpp +++ b/include/boost/geometry/multi/algorithms/within.hpp @@ -81,7 +81,8 @@ struct within { template static inline bool apply(Point const& point, - MultiPolygon const& multi_polygon, Strategy const& strategy) + MultiPolygon const& multi_polygon, + Strategy const& strategy) { return detail::within::geometry_multi_within_code < @@ -101,12 +102,25 @@ struct within { template static inline bool apply(Point const& point, - MultiLinestring const& multi_linestring, Strategy const& strategy) + MultiLinestring const& multi_linestring, + Strategy const& strategy) { return detail::within::point_in_geometry(point, multi_linestring, strategy) == 1; } }; +template +struct within +{ + template + static inline bool apply(Point const& point, + MultiPoint const& multi_point, + Strategy const& strategy) + { + return detail::within::point_in_geometry(point, multi_point, strategy) == 1; + } +}; + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index eac68cbc8..ae7fcb7ec 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013. -// Modifications copyright (c) 2013, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -13,6 +13,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + #ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP #define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP @@ -198,23 +200,30 @@ struct default_strategy::type> type; }; +// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used + template struct default_strategy { - typedef strategy::within::winding::type> type; + typedef winding::type> type; +}; + +template +struct default_strategy +{ + typedef winding::type> type; }; -// TODO: later move it to multi/strategies/agnostic template struct default_strategy { - typedef strategy::within::winding::type> type; + typedef winding::type> type; }; -template -struct default_strategy +template +struct default_strategy { - typedef strategy::within::winding::type, typename geometry::point_type::type> type; + typedef winding::type> type; }; } // namespace services @@ -243,19 +252,32 @@ struct default_strategy::type> type; }; +// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used + template struct default_strategy { typedef strategy::within::winding::type> type; }; -// TODO: later move it to multi/strategies/agnostic +template +struct default_strategy +{ + typedef strategy::within::winding::type> type; +}; + template struct default_strategy { typedef strategy::within::winding::type> type; }; +template +struct default_strategy +{ + typedef strategy::within::winding::type> type; +}; + }}} // namespace strategy::covered_by::services #endif diff --git a/include/boost/geometry/strategies/agnostic/relate.hpp b/include/boost/geometry/strategies/agnostic/relate.hpp new file mode 100644 index 000000000..c61046fc8 --- /dev/null +++ b/include/boost/geometry/strategies/agnostic/relate.hpp @@ -0,0 +1,207 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014 Oracle and/or its affiliates. + +// 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) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP +#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace relate +{ + +template +struct relate +{ + template + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + { + return detail::relate::relate(geometry1, geometry2); + } +}; + +} // namespace relate + +namespace within +{ + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +// P/L + +//template +//struct default_strategy +//{ +// typedef strategy::relate::relate type; +//}; +// +//template +//struct default_strategy +//{ +// typedef strategy::relate::relate type; +//}; + +// L/L + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +// L/A + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +} // namespace services + +#endif + + +}} // namespace strategy::within + + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace strategy { namespace covered_by { namespace services +{ + +// P/L + +//template +//struct default_strategy +//{ +// typedef strategy::relate::relate type; +//}; +// +//template +//struct default_strategy +//{ +// typedef strategy::relate::relate type; +//}; + +// L/L + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +// L/A + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +template +struct default_strategy +{ + typedef strategy::relate::relate type; +}; + +}}} // namespace strategy::covered_by::services +#endif + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index 70cb2d95f..491c1d858 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -55,6 +55,8 @@ #include #include +#include + #include #include diff --git a/test/algorithms/relate.cpp b/test/algorithms/relate.cpp index 2ae078d25..7becd05e6 100644 --- a/test/algorithms/relate.cpp +++ b/test/algorithms/relate.cpp @@ -75,8 +75,8 @@ void check_geometry(Geometry1 const& geometry1, std::string expected_tr = transposed(expected); bool ok = boost::equal(res_str, expected_tr); BOOST_CHECK_MESSAGE(ok, - "relate: " << wkt1 - << " and " << wkt2 + "relate: " << wkt2 + << " and " << wkt1 << " -> Expected: " << expected_tr << " detected: " << res_str); } @@ -251,9 +251,11 @@ void test_linestring_linestring() test_geometry("LINESTRING(0 0,2 2,3 3,1 1,5 3)", "LINESTRING(6 3,3 3,0 0)", "1F100F102"); test_geometry("LINESTRING(5 3,1 1,3 3,2 2,0 0)", "LINESTRING(6 3,3 3,0 0)", "1F100F102"); - // spike + // spikes test_geometry("LINESTRING(0 0,10 0)", "LINESTRING(1 0,9 0,2 0)", "101FF0FF2"); + test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,3 3,6 3)", "1FF00F102"); + test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", "1FF00F102"); // loop i/i i/i u/u u/u test_geometry("LINESTRING(0 0,10 0)", diff --git a/test/algorithms/within.cpp b/test/algorithms/within.cpp index bf15c8385..9ee26bec3 100644 --- a/test/algorithms/within.cpp +++ b/test/algorithms/within.cpp @@ -41,13 +41,18 @@ void test_linestring_linestring() test_geometry("LINESTRING(1 0, 1 1, 2 2, 3 2)", "LINESTRING(0 0, 2 2, 4 2)", false); test_geometry("LINESTRING(1 0, 0 0, 2 2, 3 2)", "LINESTRING(0 0, 2 2, 4 2)", false); - test_geometry("LINESTRING(0 0)", "LINESTRING(0 0)", false); - test_geometry("LINESTRING(1 1)", "LINESTRING(0 0, 2 2)", true); - test_geometry("LINESTRING(0 0)", "LINESTRING(0 0, 2 2)", false); - test_geometry("LINESTRING(0 0, 1 1)", "LINESTRING(0 0)", false); +// test_geometry("LINESTRING(0 0)", "LINESTRING(0 0)", false); +// test_geometry("LINESTRING(1 1)", "LINESTRING(0 0, 2 2)", true); +// test_geometry("LINESTRING(0 0)", "LINESTRING(0 0, 2 2)", false); +// test_geometry("LINESTRING(0 0, 1 1)", "LINESTRING(0 0)", false); test_geometry("LINESTRING(0 0,5 0,3 0,6 0)", "LINESTRING(0 0,6 0)", true); + test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,3 3,6 3)", true); + test_geometry("LINESTRING(0 0,3 3,6 3)", "LINESTRING(0 0,2 2,3 3,1 1)", false); + test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", true); + test_geometry("LINESTRING(0 0,4 4,6 3)", "LINESTRING(0 0,2 2,3 3,1 1)", false); + test_geometry("LINESTRING(0 0,2 2,3 3,1 1,5 3)", "LINESTRING(0 0,3 3,6 3)", false); } From 5eec228f10f9687427d9e82f3e2bc629d82d9b88 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sat, 22 Mar 2014 11:21:49 +0100 Subject: [PATCH 02/31] [relate][get_turns] the code from handle_spike from get_turn_info_ll enclosed in spike detector (NOT FULLY WORKING) --- .../detail/overlay/get_turn_info_ll.hpp | 110 +++++++++++++----- test/algorithms/relate.cpp | 2 + 2 files changed, 85 insertions(+), 27 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 0a80bee98..e7a676122 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -22,6 +22,62 @@ namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay { +template > +class spike_detector +{ +public: + explicit spike_detector(SideCalc const& side_calc) + : m_side_calc(side_calc) + {} + + inline bool is_spike_p() const + { + if ( m_side_calc.pk_wrt_p1() == 0 ) + { + int const qk_p1 = m_side_calc.qk_wrt_p1(); + int const qk_p2 = m_side_calc.qk_wrt_p2(); + + if ( qk_p1 == -qk_p2 ) + { + if ( qk_p1 == 0 ) + { + // TODO check additional things + } + + return true; + } + } + + return false; + } + + inline bool is_spike_q() const + { + if ( m_side_calc.qk_wrt_q1() == 0 ) + { + int const pk_q1 = m_side_calc.pk_wrt_q1(); + int const pk_q2 = m_side_calc.pk_wrt_q2(); + + if ( pk_q1 == -pk_q2 ) + { + if ( pk_q1 == 0 ) + { + // TODO check additional things + } + + return true; + } + } + + return false; + } + +private: + SideCalc const& m_side_calc; +}; + template struct get_turn_info_linear_linear { @@ -192,9 +248,17 @@ struct get_turn_info_linear_linear replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); - handle_possible_spike_after_equal(tp.operations[0].operation, - tp.operations[1].operation, - side_calc); + spike_detector spike_detect(side_calc); + if ( tp.operations[0].operation == operation_union + && spike_detect.is_spike_p()) + { + tp.operations[0].operation = operation_continue; + } + if ( tp.operations[1].operation == operation_union + && spike_detect.is_spike_q()) + { + tp.operations[1].operation = operation_continue; + } AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); *out++ = tp; @@ -241,9 +305,17 @@ struct get_turn_info_linear_linear replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); - handle_possible_spike_after_equal(tp.operations[0].operation, - tp.operations[1].operation, - side_calc); + spike_detector spike_detect(side_calc); + if ( tp.operations[0].operation == operation_union + && spike_detect.is_spike_p()) + { + tp.operations[0].operation = operation_continue; + } + if ( tp.operations[1].operation == operation_union + && spike_detect.is_spike_q()) + { + tp.operations[1].operation = operation_continue; + } } else { @@ -252,6 +324,11 @@ struct get_turn_info_linear_linear replacer_of_method_and_operations_ec replacer(method_touch_interior); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); + + // TEST + spike_detector spike_detect(side_calc); + spike_detect.is_spike_p(); + spike_detect.is_spike_q(); } AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); @@ -299,27 +376,6 @@ struct get_turn_info_linear_linear return out; } - template - static inline void handle_possible_spike_after_equal(operation_type & op0, - operation_type & op1, - SideCalc const& side_calc) - { - // spike on P - if ( op0 == operation_union - && side_calc.pk_wrt_p1() == 0 - && side_calc.qk_wrt_p1() == -side_calc.qk_wrt_p2() ) - { - op0 = operation_continue; - } - // spike on Q - if ( op1 == operation_union - && side_calc.qk_wrt_q1() == 0 - && side_calc.pk_wrt_q1() == -side_calc.pk_wrt_q2() ) - { - op1 = operation_continue; - } - } - static inline void replace_method_and_operations_tm(method_type & method, operation_type & op0, operation_type & op1) diff --git a/test/algorithms/relate.cpp b/test/algorithms/relate.cpp index 7becd05e6..b319b3b67 100644 --- a/test/algorithms/relate.cpp +++ b/test/algorithms/relate.cpp @@ -257,6 +257,8 @@ void test_linestring_linestring() test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,3 3,6 3)", "1FF00F102"); test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", "1FF00F102"); + test_geometry("LINESTRING(0 0,2 2,3 3,4 4)", "LINESTRING(0 0,1 1,4 4)", "1FFF0FFF2"); + // loop i/i i/i u/u u/u test_geometry("LINESTRING(0 0,10 0)", "LINESTRING(1 1,1 0,6 0,6 1,4 1,4 0,9 0,9 1)", "1F1FF0102"); From 3b8f444e6ca10a7cd0ad443c17bf804ae89a2c79 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 22 Mar 2014 23:48:07 +0100 Subject: [PATCH 03/31] [geometry] added test to intersection unit test for issue reported at 2014/03/21 by 7415963@gmail.com The issue is not fixed yet. --- test/algorithms/intersection.cpp | 8 ++++++++ test/algorithms/overlay/overlay_cases.hpp | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/test/algorithms/intersection.cpp b/test/algorithms/intersection.cpp index a9b0617f0..fa5f385fd 100644 --- a/test/algorithms/intersection.cpp +++ b/test/algorithms/intersection.cpp @@ -198,6 +198,14 @@ void test_areal() ggl_list_20131119_james[0], ggl_list_20131119_james[1], 1, 4, 6.6125873045, 0.1); +#if 0 + // TODO: fix this testcase, it should give 0 but instead it gives one of the input polygons + // Mailed to the Boost.Geometry list on 2014/03/21 by 7415963@gmail.com + test_one("ggl_list_20140321_7415963", + ggl_list_20140321_7415963[0], ggl_list_20140321_7415963[1], + 0, 0, 0, 0.1); +#endif + test_one("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], 1, 4, 0.00029437899183903937, 0.01); diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index d600b6297..fa6647a02 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -538,6 +538,12 @@ static std::string ggl_list_20131119_james[2] = }; +static std::string ggl_list_20140321_7415963[2] = +{ + "POLYGON((-6.0 3.2500000000000013, -9.0 3.2500000000000022, -9.0 6.5, -6.0 6.5, -6.0 3.2500000000000013))", + "POLYGON((-3.0 0.0, -6.0 0.0, -6.0 3.2500000000000013, -3.0 3.2500000000000009, -3.0 0.0))", +}; + // GEOS "TestOverlay" test. // Note that the first one WAS invalid and is made valid using SQL Server 2008 Spatial MakeValid() function static std::string geos_1_test_overlay[2] = From 025bd3b2bcd1a3b5d1cf15fc1cd78d681ec438be Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 23 Mar 2014 15:17:05 +0100 Subject: [PATCH 04/31] [relate] overall cleanup, group_dim replaced by topological_dimension, group_tag by tag_cast, range moved to util/range.hpp, some temporary code commented out --- .../geometry/algorithms/detail/group_dim.hpp | 79 ------------------ .../detail/overlay/get_turn_info_la.hpp | 18 ++++ .../detail/overlay/get_turn_info_ll.hpp | 16 ++-- .../algorithms/detail/overlay/get_turns.hpp | 11 ++- .../algorithms/detail/range_helpers.hpp | 78 ------------------ .../algorithms/detail/relate/less.hpp | 31 ++++--- .../algorithms/detail/relate/linear_areal.hpp | 21 ++--- .../detail/relate/linear_linear.hpp | 3 +- .../algorithms/detail/relate/result.hpp | 14 ++-- include/boost/geometry/util/range.hpp | 82 +++++++++++++++++++ test/algorithms/relate.cpp | 7 +- 11 files changed, 161 insertions(+), 199 deletions(-) delete mode 100644 include/boost/geometry/algorithms/detail/group_dim.hpp delete mode 100644 include/boost/geometry/algorithms/detail/range_helpers.hpp create mode 100644 include/boost/geometry/util/range.hpp diff --git a/include/boost/geometry/algorithms/detail/group_dim.hpp b/include/boost/geometry/algorithms/detail/group_dim.hpp deleted file mode 100644 index a5c445b88..000000000 --- a/include/boost/geometry/algorithms/detail/group_dim.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2014 Oracle and/or its affiliates. - -// 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) - -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GROUP_DIM_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GROUP_DIM_HPP - -#include - -#include - -namespace boost { namespace geometry { - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { - -template ::type, - bool IsPoint = boost::is_base_of::value, - bool IsLinear = boost::is_base_of::value, - bool IsAreal = boost::is_base_of::value> -struct group_tag - : not_implemented -{}; - -template -struct group_tag -{ - typedef pointlike_tag type; -}; - -template -struct group_tag -{ - typedef linear_tag type; -}; - -template -struct group_tag -{ - typedef areal_tag type; -}; - -template ::type> -struct group_dim - : not_implemented -{}; - -template -struct group_dim -{ - static const int value = 0; -}; - -template -struct group_dim -{ - static const int value = 1; -}; - -template -struct group_dim -{ - static const int value = 2; -}; - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GROUP_DIM_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index db74ec40b..c303080fb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -17,6 +17,9 @@ #include #include +// TEMP, for spikes detector +//#include + namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL @@ -183,6 +186,14 @@ struct get_turn_info_linear_areal replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); + // TODO: This isn't correct handling, hence commented out + /*spike_detector spike_detect(side_calc); + if ( tp.operations[0].operation == operation_union + && spike_detect.is_spike_p()) + { + tp.operations[0].operation = operation_continue; + }*/ + AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); *out++ = tp; } @@ -219,6 +230,13 @@ struct get_turn_info_linear_areal equal::apply(pi, pj, pk, qi, qj, qk, tp, result.template get<0>(), result.template get<1>(), side_calc); + spike_detector spike_detect(side_calc); + if ( tp.operations[0].operation == operation_union + && spike_detect.is_spike_p()) + { + tp.operations[0].operation = operation_continue; + } + replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index e7a676122..d5d2cb17a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -248,7 +248,8 @@ struct get_turn_info_linear_linear replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); - spike_detector spike_detect(side_calc); + // TODO: This isn't correct handling, hence commented out + /*spike_detector spike_detect(side_calc); if ( tp.operations[0].operation == operation_union && spike_detect.is_spike_p()) { @@ -258,7 +259,7 @@ struct get_turn_info_linear_linear && spike_detect.is_spike_q()) { tp.operations[1].operation = operation_continue; - } + }*/ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); *out++ = tp; @@ -305,7 +306,8 @@ struct get_turn_info_linear_linear replacer_of_method_and_operations_ec replacer(method_touch); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); - spike_detector spike_detect(side_calc); + // TODO: This isn't correct handling, hence commented out + /*spike_detector spike_detect(side_calc); if ( tp.operations[0].operation == operation_union && spike_detect.is_spike_p()) { @@ -315,7 +317,7 @@ struct get_turn_info_linear_linear && spike_detect.is_spike_q()) { tp.operations[1].operation = operation_continue; - } + }*/ } else { @@ -326,9 +328,9 @@ struct get_turn_info_linear_linear replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); // TEST - spike_detector spike_detect(side_calc); - spike_detect.is_spike_p(); - spike_detect.is_spike_q(); + //spike_detector spike_detect(side_calc); + //spike_detect.is_spike_p(); + //spike_detect.is_spike_q(); } AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index fb0287466..0004646d6 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -54,7 +54,6 @@ #include #include #include -#include #include @@ -738,9 +737,15 @@ struct get_turns_polygon_cs // GET_TURN_INFO_TYPE +template +struct topological_tag_base +{ + typedef typename tag_cast::type, pointlike_tag, linear_tag, areal_tag>::type type; +}; + template ::type, typename Tag2 = typename tag::type, - typename TagBase1 = typename group_tag::type, typename TagBase2 = typename group_tag::type> + typename TagBase1 = typename topological_tag_base::type, typename TagBase2 = typename topological_tag_base::type> struct get_turn_info_type : overlay::get_turn_info {}; @@ -757,7 +762,7 @@ struct get_turn_info_type::type, typename Tag2 = typename tag::type, - typename TagBase1 = typename group_tag::type, typename TagBase2 = typename group_tag::type> + typename TagBase1 = typename topological_tag_base::type, typename TagBase2 = typename topological_tag_base::type> struct turn_operation_type { typedef overlay::turn_operation type; diff --git a/include/boost/geometry/algorithms/detail/range_helpers.hpp b/include/boost/geometry/algorithms/detail/range_helpers.hpp deleted file mode 100644 index 6f546e0a4..000000000 --- a/include/boost/geometry/algorithms/detail/range_helpers.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. - -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates. - -// 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) - -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RANGE_HELPERS_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RANGE_HELPERS_HPP - -#include - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace range { - -template -inline typename boost::range_value::type const& -at(Range const& rng, typename boost::range_size::type i) -{ - BOOST_ASSERT(i < boost::size(rng)); - return *(boost::begin(rng) + i); -} - -template -inline typename boost::range_value::type & -at(Range & rng, typename boost::range_size::type i) -{ - BOOST_ASSERT(i < boost::size(rng)); - return *(boost::begin(rng) + i); -} - -template -inline typename boost::range_value::type const& -front(Range const& rng) -{ - BOOST_ASSERT(!boost::empty(rng)); - return *boost::begin(rng); -} - -template -inline typename boost::range_value::type & -front(Range & rng) -{ - BOOST_ASSERT(!boost::empty(rng)); - return *boost::begin(rng); -} - -template -inline typename boost::range_value::type const& -back(Range const& rng) -{ - BOOST_ASSERT(!boost::empty(rng)); - return *(--boost::end(rng)); -} - -template -inline typename boost::range_value::type & -back(Range & rng) -{ - BOOST_ASSERT(!boost::empty(rng)); - return *(--boost::end(rng)); -} - -}} // namespace detail::range -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RANGE_HELPERS_HPP diff --git a/include/boost/geometry/algorithms/detail/relate/less.hpp b/include/boost/geometry/algorithms/detail/relate/less.hpp index 347686ff8..908ac3aa0 100644 --- a/include/boost/geometry/algorithms/detail/relate/less.hpp +++ b/include/boost/geometry/algorithms/detail/relate/less.hpp @@ -17,37 +17,37 @@ namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace relate { +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch { namespace relate { -// TODO: should this be integrated with geometry::less? +// TODO: Integrate it with geometry::less? template ::value> -struct less_dispatch +struct less { - static inline bool apply(Point1 const& l, Point2 const& r) + static inline bool apply(Point1 const& left, Point2 const& right) { typename geometry::coordinate_type::type - cl = geometry::get(l); + cleft = geometry::get(left); typename geometry::coordinate_type::type - cr = geometry::get(r); + cright = geometry::get(right); - if ( geometry::math::equals(cl, cr) ) + if ( geometry::math::equals(cleft, cright) ) { - return less_dispatch::apply(l, r); + return less::apply(left, right); } else { - return cl < cr; + return cleft < cright; } } }; template -struct less_dispatch +struct less { static inline bool apply(Point1 const&, Point2 const&) { @@ -55,12 +55,19 @@ struct less_dispatch } }; +}} // namespace detail_dispatch::relate + +#endif + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + struct less { template inline bool operator()(Point1 const& point1, Point2 const& point2) { - return less_dispatch::apply(point1, point2); + return detail_dispatch::relate::less::apply(point1, point2); } }; diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index eb3cc7e76..56ee7adf7 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -14,9 +14,10 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP -#include +#include +#include + #include -#include #include #include @@ -185,8 +186,8 @@ template struct linear_areal { // check Linear / Areal - BOOST_STATIC_ASSERT(detail::group_dim::value == 1 - && detail::group_dim::value == 2); + BOOST_STATIC_ASSERT(topological_dimension::value == 1 + && topological_dimension::value == 2); static const bool interruption_enabled = true; @@ -848,15 +849,15 @@ struct linear_areal BOOST_ASSERT(p_seg_ij + 1 < s1 && q_seg_ij + 1 < s2); - point1_type const& pi = range::at(range1, p_seg_ij); - point2_type const& qi = range::at(range2, q_seg_ij); - point2_type const& qj = range::at(range2, q_seg_ij + 1); + point1_type const& pi = geometry::range::at(range1, p_seg_ij); + point2_type const& qi = geometry::range::at(range2, q_seg_ij); + point2_type const& qj = geometry::range::at(range2, q_seg_ij + 1); point1_type qi_conv; geometry::convert(qi, qi_conv); bool is_ip_qj = equals::equals_point_point(turn.point, qj); // TODO: test this! - BOOST_ASSERT(!equals::equals_point_point(turn.point, pi)); - BOOST_ASSERT(!equals::equals_point_point(turn.point, qi)); +// BOOST_ASSERT(!equals::equals_point_point(turn.point, pi)); +// BOOST_ASSERT(!equals::equals_point_point(turn.point, qi)); point1_type new_pj; geometry::convert(turn.point, new_pj); @@ -864,7 +865,7 @@ struct linear_areal { std::size_t q_seg_jk = (q_seg_ij + 1) % seg_count2; BOOST_ASSERT(q_seg_jk + 1 < s2); - point2_type const& qk = range::at(range2, q_seg_jk + 1); + point2_type const& qk = geometry::range::at(range2, q_seg_jk + 1); // Will this sequence of point be always correct? overlay::side_calculator side_calc(qi_conv, new_pj, pi, qi, qj, qk); diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index cce713e5e..0b2312339 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -14,8 +14,9 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP +#include + #include -#include #include #include diff --git a/include/boost/geometry/algorithms/detail/relate/result.hpp b/include/boost/geometry/algorithms/detail/relate/result.hpp index 18d4c61c3..f177b7cc0 100644 --- a/include/boost/geometry/algorithms/detail/relate/result.hpp +++ b/include/boost/geometry/algorithms/detail/relate/result.hpp @@ -18,6 +18,8 @@ #include #include +#include + // TEMP - move this header to geometry/detail #include @@ -796,8 +798,8 @@ typedef static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> static_mask_dis // TOUCHES - NOT P/P template ::value, - std::size_t Dim2 = detail::group_dim::value> + std::size_t Dim1 = topological_dimension::value, + std::size_t Dim2 = topological_dimension::value> struct static_mask_touches_type { typedef boost::mpl::vector< @@ -829,8 +831,8 @@ typedef boost::mpl::vector< // dim(G1) < dim(G2) - P/L P/A L/A template ::value, - std::size_t Dim2 = detail::group_dim::value, + std::size_t Dim1 = topological_dimension::value, + std::size_t Dim2 = topological_dimension::value, bool D1LessD2 = (Dim1 < Dim2) > struct static_mask_crosses_type @@ -866,8 +868,8 @@ struct static_mask_crosses_type // dim(G1) != dim(G2) - NOT P/P, L/L, A/A template ::value, - std::size_t Dim2 = detail::group_dim::value + std::size_t Dim1 = topological_dimension::value, + std::size_t Dim2 = topological_dimension::value > struct static_mask_overlaps_type : not_implemented::type, diff --git a/include/boost/geometry/util/range.hpp b/include/boost/geometry/util/range.hpp new file mode 100644 index 000000000..2930dcffb --- /dev/null +++ b/include/boost/geometry/util/range.hpp @@ -0,0 +1,82 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates. + +// 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) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP +#define BOOST_GEOMETRY_UTIL_RANGE_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry { namespace range { + +template +inline typename boost::range_value::type const& +at(RandomAccessRange const& rng, + typename boost::range_size::type i) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept )); + BOOST_ASSERT(i < boost::size(rng)); + return *(boost::begin(rng) + i); +} + +template +inline typename boost::range_value::type & +at(RandomAccessRange & rng, + typename boost::range_size::type i) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept )); + BOOST_ASSERT(i < boost::size(rng)); + return *(boost::begin(rng) + i); +} + +template +inline typename boost::range_value::type const& +front(Range const& rng) +{ + BOOST_ASSERT(!boost::empty(rng)); + return *boost::begin(rng); +} + +template +inline typename boost::range_value::type & +front(Range & rng) +{ + BOOST_ASSERT(!boost::empty(rng)); + return *boost::begin(rng); +} + +template +inline typename boost::range_value::type const& +back(BidirectionalRange const& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept )); + BOOST_ASSERT(!boost::empty(rng)); + return *(--boost::end(rng)); +} + +template +inline typename boost::range_value::type & +back(BidirectionalRange & rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept )); + BOOST_ASSERT(!boost::empty(rng)); + return *(--boost::end(rng)); +} + +}}} // namespace boost::geometry::range + +#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP diff --git a/test/algorithms/relate.cpp b/test/algorithms/relate.cpp index b319b3b67..3b41ade12 100644 --- a/test/algorithms/relate.cpp +++ b/test/algorithms/relate.cpp @@ -40,7 +40,7 @@ #include //TEST -#include +//#include namespace bgdr = bg::detail::relate; @@ -252,10 +252,11 @@ void test_linestring_linestring() test_geometry("LINESTRING(5 3,1 1,3 3,2 2,0 0)", "LINESTRING(6 3,3 3,0 0)", "1F100F102"); // spikes - test_geometry("LINESTRING(0 0,10 0)", + // FOR NOW DISABLED + /*test_geometry("LINESTRING(0 0,10 0)", "LINESTRING(1 0,9 0,2 0)", "101FF0FF2"); test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,3 3,6 3)", "1FF00F102"); - test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", "1FF00F102"); + test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", "1FF00F102");*/ test_geometry("LINESTRING(0 0,2 2,3 3,4 4)", "LINESTRING(0 0,1 1,4 4)", "1FFF0FFF2"); From e99574f1edb24b8836429c995927c8e65b08d149 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 23 Mar 2014 15:21:36 +0100 Subject: [PATCH 05/31] [relate][get_turns] add missing brackets --- .../detail/overlay/get_turn_info_la.hpp | 12 ++++++++++ .../detail/overlay/get_turn_info_ll.hpp | 22 +++++++++++++++++-- .../detail/relate/linear_linear.hpp | 8 +++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index c303080fb..a66f7b293 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -306,12 +306,18 @@ struct get_turn_info_linear_areal // Assuming G1 is always Linear if ( op0 == operation_blocked ) + { op0 = operation_continue; + } if ( op1 == operation_blocked ) + { op1 = operation_continue; + } else if ( op1 == operation_intersection ) + { op1 = operation_union; + } } template @@ -336,12 +342,18 @@ struct get_turn_info_linear_areal // Assuming G1 is always Linear if ( op0 == operation_blocked ) + { op0 = operation_continue; + } if ( op1 == operation_blocked ) + { op1 = operation_continue; + } else if ( op1 == operation_intersection ) + { op1 = operation_union; + } } private: diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index d5d2cb17a..eb836582d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -392,14 +392,22 @@ struct get_turn_info_linear_linear else { if ( op0 == operation_continue || op0 == operation_blocked ) + { op0 = operation_intersection; + } else if ( op0 == operation_intersection ) + { op0 = operation_union; + } if ( op1 == operation_continue || op1 == operation_blocked ) + { op1 = operation_intersection; + } else if ( op1 == operation_intersection ) + { op1 = operation_union; + } } } @@ -417,14 +425,22 @@ struct get_turn_info_linear_linear BOOST_ASSERT(op0 != operation_blocked || op1 != operation_blocked ); if ( op0 == operation_blocked ) + { op0 = operation_intersection; + } else if ( op0 == operation_intersection ) + { op0 = operation_union; + } if ( op1 == operation_blocked ) + { op1 = operation_intersection; + } else if ( op1 == operation_intersection ) + { op1 = operation_union; + } if ( op0 == operation_intersection || op0 == operation_union || op1 == operation_intersection || op1 == operation_union ) @@ -440,13 +456,15 @@ struct get_turn_info_linear_linear static inline void replace_operations_i(operation_type & op0, operation_type & op1) { if ( op0 == operation_intersection ) + { op0 = operation_union; + } if ( op1 == operation_intersection ) + { op1 = operation_union; + } } - - }; }} // namespace detail::overlay diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 0b2312339..bf91c1e66 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -558,18 +558,26 @@ struct linear_linear { // it's also the boundary of the other geometry if ( other_b ) + { update(res); + } else + { update(res); + } } // if current IP is not on boundary of the geometry else { // it's also the boundary of the other geometry if ( other_b ) + { update(res); + } else + { update(res); + } } // first IP on the last segment point - this means that the first point is outside From bddaadd8bc006423986c476e7b8bbf3641d895e0 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 23 Mar 2014 16:34:06 +0100 Subject: [PATCH 06/31] [geometry] round() moved to util/math, added doxygen info to round() and range utils --- .../policies/relate/intersection_points.hpp | 36 ++----------------- include/boost/geometry/util/math.hpp | 36 +++++++++++++++++++ include/boost/geometry/util/range.hpp | 28 +++++++++++++++ 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/include/boost/geometry/policies/relate/intersection_points.hpp b/include/boost/geometry/policies/relate/intersection_points.hpp index 8a315ef57..7a378475b 100644 --- a/include/boost/geometry/policies/relate/intersection_points.hpp +++ b/include/boost/geometry/policies/relate/intersection_points.hpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace boost { namespace geometry { @@ -28,37 +29,6 @@ namespace boost { namespace geometry namespace policies { namespace relate { -template ::is_integer> -struct round_dispatch -{ - template - static inline Result apply(T const& v) - { - return v < 0 ? - boost::numeric_cast(ceil(v - 0.5f)) : - boost::numeric_cast(floor(v + 0.5f)); - } -}; - -template -struct round_dispatch -{ - template - static inline Result apply(T const& v) - { - return boost::numeric_cast(v); - } -}; - -template -inline Result round(T const& v) -{ - // NOTE: boost::round() could be used instead but it throws in some situations - - //BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); - return round_dispatch::apply(v); -} - template struct segments_intersection_points { @@ -89,9 +59,9 @@ struct segments_intersection_points return_type result; result.count = 1; set<0>(result.intersections[0], - round(R(s1x) + r * R(dx1))); + geometry::math::round(R(s1x) + r * R(dx1))); set<1>(result.intersections[0], - round(R(s1y) + r * R(dy1))); + geometry::math::round(R(s1y) + r * R(dy1))); return result; } diff --git a/include/boost/geometry/util/math.hpp b/include/boost/geometry/util/math.hpp index 1296321b4..4d9ca6b8a 100644 --- a/include/boost/geometry/util/math.hpp +++ b/include/boost/geometry/util/math.hpp @@ -111,6 +111,29 @@ struct relaxed_epsilon } }; +// ItoF ItoI FtoF +template ::is_integer, + bool SourceIsInteger = std::numeric_limits::is_integer> +struct round +{ + static inline Result apply(Source const& v) + { + return boost::numeric_cast(v); + } +}; + +// FtoI +template +struct round +{ + static inline Result apply(Source const& v) + { + return v < 0 + ? boost::numeric_cast(ceil(v - 0.5f)) + : boost::numeric_cast(floor(v + 0.5f)); + } +}; } // namespace detail #endif @@ -239,6 +262,19 @@ static inline int sign(T const& value) return value > zero ? 1 : value < zero ? -1 : 0; } +/*! +\brief Short utility to calculate the rounded value of a number. +\ingroup utility +\note If the source T is NOT an integral type and Result is an integral type + the value is rounded towards the closest integral value. Otherwise it's + just casted. +*/ +template +inline Result round(T const& v) +{ + // NOTE: boost::round() could be used instead but it throws in some situations + return detail::round::apply(v); +} } // namespace math diff --git a/include/boost/geometry/util/range.hpp b/include/boost/geometry/util/range.hpp index 2930dcffb..986aba660 100644 --- a/include/boost/geometry/util/range.hpp +++ b/include/boost/geometry/util/range.hpp @@ -23,6 +23,12 @@ namespace boost { namespace geometry { namespace range { +// NOTE: For SinglePassRanges at could iterate over all elements until the i-th element is met. + +/*! +\brief Short utility to conveniently return an element of a RandomAccessRange. +\ingroup utility +*/ template inline typename boost::range_value::type const& at(RandomAccessRange const& rng, @@ -33,6 +39,10 @@ at(RandomAccessRange const& rng, return *(boost::begin(rng) + i); } +/*! +\brief Short utility to conveniently return an element of a RandomAccessRange. +\ingroup utility +*/ template inline typename boost::range_value::type & at(RandomAccessRange & rng, @@ -43,6 +53,10 @@ at(RandomAccessRange & rng, return *(boost::begin(rng) + i); } +/*! +\brief Short utility to conveniently return the front element of a Range. +\ingroup utility +*/ template inline typename boost::range_value::type const& front(Range const& rng) @@ -51,6 +65,10 @@ front(Range const& rng) return *boost::begin(rng); } +/*! +\brief Short utility to conveniently return the front element of a Range. +\ingroup utility +*/ template inline typename boost::range_value::type & front(Range & rng) @@ -59,6 +77,12 @@ front(Range & rng) return *boost::begin(rng); } +// NOTE: For SinglePassRanges back() could iterate over all elements until the last element is met. + +/*! +\brief Short utility to conveniently return the back element of a BidirectionalRange. +\ingroup utility +*/ template inline typename boost::range_value::type const& back(BidirectionalRange const& rng) @@ -68,6 +92,10 @@ back(BidirectionalRange const& rng) return *(--boost::end(rng)); } +/*! +\brief Short utility to conveniently return the back element of a BidirectionalRange. +\ingroup utility +*/ template inline typename boost::range_value::type & back(BidirectionalRange & rng) From 5316d1f2add6566835596d8d2b6cd89a41ae6bb2 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 23 Mar 2014 17:16:56 +0100 Subject: [PATCH 07/31] [geometry] replace sub_geometry::get() by sub_range(), fix invalid #includes --- .../detail/relate/boundary_checker.hpp | 3 +- .../algorithms/detail/relate/linear_areal.hpp | 24 ++-- .../detail/relate/linear_linear.hpp | 10 +- .../detail/relate/topology_check.hpp | 3 +- .../algorithms/detail/sub_geometry.hpp | 131 ------------------ .../geometry/algorithms/detail/sub_range.hpp | 113 +++++++++++++++ include/boost/geometry/algorithms/touches.hpp | 6 +- test/algorithms/within.cpp | 14 +- 8 files changed, 147 insertions(+), 157 deletions(-) delete mode 100644 include/boost/geometry/algorithms/detail/sub_geometry.hpp create mode 100644 include/boost/geometry/algorithms/detail/sub_range.hpp diff --git a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index b16e6bae6..330cf38be 100644 --- a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -11,8 +11,9 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP +#include + #include -#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 56ee7adf7..395b2ffc1 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -622,7 +622,7 @@ struct linear_areal if ( first_in_range ) { bool front_b = is_endpoint_on_boundary( - range::front(sub_geometry::get(geometry, seg_id)), + range::front(sub_range(geometry, seg_id)), boundary_checker); // if there is a boundary on the first point @@ -713,7 +713,7 @@ struct linear_areal if ( first_in_range && ( !this_b || op_blocked ) ) { bool front_b = is_endpoint_on_boundary( - range::front(sub_geometry::get(geometry, seg_id)), + range::front(sub_range(geometry, seg_id)), boundary_checker); // if there is a boundary on the first point @@ -759,7 +759,7 @@ struct linear_areal segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; bool prev_back_b = is_endpoint_on_boundary( - range::back(sub_geometry::get(geometry, prev_seg_id)), + range::back(sub_range(geometry, prev_seg_id)), boundary_checker); // if there is a boundary on the last point @@ -780,7 +780,7 @@ struct linear_areal segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; bool prev_back_b = is_endpoint_on_boundary( - range::back(sub_geometry::get(geometry, prev_seg_id)), + range::back(sub_range(geometry, prev_seg_id)), boundary_checker); // if there is a boundary on the last point @@ -833,10 +833,10 @@ struct linear_areal reverse2 ? iterate_reverse : iterate_forward >::type range2_view; - typedef typename sub_geometry::result_type::type range1_ref; + typedef typename sub_range_return_type::type range1_ref; - range1_ref range1 = sub_geometry::get(geometry1, turn.operations[op_id].seg_id); - range2_cview const cview(sub_geometry::get(geometry2, turn.operations[other_op_id].seg_id)); + range1_ref range1 = sub_range(geometry1, turn.operations[op_id].seg_id); + range2_cview const cview(sub_range(geometry2, turn.operations[other_op_id].seg_id)); range2_view const range2(cview); std::size_t s1 = boost::size(range1); @@ -849,9 +849,9 @@ struct linear_areal BOOST_ASSERT(p_seg_ij + 1 < s1 && q_seg_ij + 1 < s2); - point1_type const& pi = geometry::range::at(range1, p_seg_ij); - point2_type const& qi = geometry::range::at(range2, q_seg_ij); - point2_type const& qj = geometry::range::at(range2, q_seg_ij + 1); + point1_type const& pi = range::at(range1, p_seg_ij); + point2_type const& qi = range::at(range2, q_seg_ij); + point2_type const& qj = range::at(range2, q_seg_ij + 1); point1_type qi_conv; geometry::convert(qi, qi_conv); bool is_ip_qj = equals::equals_point_point(turn.point, qj); @@ -865,7 +865,7 @@ struct linear_areal { std::size_t q_seg_jk = (q_seg_ij + 1) % seg_count2; BOOST_ASSERT(q_seg_jk + 1 < s2); - point2_type const& qk = geometry::range::at(range2, q_seg_jk + 1); + point2_type const& qk = range::at(range2, q_seg_jk + 1); // Will this sequence of point be always correct? overlay::side_calculator side_calc(qi_conv, new_pj, pi, qi, qj, qk); diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index bf91c1e66..ab21274b6 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include @@ -455,7 +455,7 @@ struct linear_linear if ( first_in_range ) { bool front_b = is_endpoint_on_boundary( - range::front(sub_geometry::get(geometry, seg_id)), + range::front(sub_range(geometry, seg_id)), boundary_checker); // if there is a boundary on the first point @@ -530,7 +530,7 @@ struct linear_linear if ( first_in_range ) { bool front_b = is_endpoint_on_boundary( - range::front(sub_geometry::get(geometry, seg_id)), + range::front(sub_range(geometry, seg_id)), boundary_checker); // if there is a boundary on the first point @@ -584,7 +584,7 @@ struct linear_linear if ( first_in_range && ( !this_b || op_blocked ) && was_outside /*&& !is_collinear*/ ) { bool front_b = is_endpoint_on_boundary( - range::front(sub_geometry::get(geometry, seg_id)), + range::front(sub_range(geometry, seg_id)), boundary_checker); // if there is a boundary on the first point @@ -620,7 +620,7 @@ struct linear_linear segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; bool prev_back_b = is_endpoint_on_boundary( - range::back(sub_geometry::get(geometry, prev_seg_id)), + range::back(sub_range(geometry, prev_seg_id)), boundary_checker); // if there is a boundary on the last point diff --git a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp index 37acb70d8..95bd88db9 100644 --- a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp @@ -11,8 +11,9 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP +#include + #include -#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/algorithms/detail/sub_geometry.hpp b/include/boost/geometry/algorithms/detail/sub_geometry.hpp deleted file mode 100644 index 98a1d617e..000000000 --- a/include/boost/geometry/algorithms/detail/sub_geometry.hpp +++ /dev/null @@ -1,131 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. - -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. - -// 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) - -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_GEOMETRY_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_GEOMETRY_HPP - -namespace boost { namespace geometry { - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace sub_geometry { - -// TODO: later implement Geometry-specialized index_type -// polygons/multi_polygons also need ring_index member -struct index_type -{ - index_type() : multi_index(-1) {} - - int multi_index; - - inline bool operator<(index_type const& i) const - { - return multi_index < i.multi_index; - } - - inline bool operator==(index_type const& i) const - { - return multi_index == i.multi_index; - } -}; - -}} // namespace detail::sub_geometry - -namespace detail_dispatch { namespace sub_geometry { - -// TODO: later remove IsMulti and move to multi directory -template ::type, - bool IsMulti = boost::is_base_of::value> -struct get : not_implemented -{}; - -template -struct get -{ - typedef Geometry & result_type; - - template static inline - result_type apply(Geometry & geometry, Id const&) - { - return geometry; - } -}; - -template -struct get -{ - typedef typename geometry::ring_type::type & result_type; - - template static inline - result_type apply(Geometry & geometry, Id const& id) - { - if ( id.ring_index < 0 ) - { - return geometry::exterior_ring(geometry); - } - else - { - std::size_t ri = static_cast(id.ring_index); - BOOST_ASSERT( ri < boost::size(geometry::interior_rings(geometry)) ); - - return *(boost::begin(geometry::interior_rings(geometry)) + ri); - } - } -}; - -template -struct get -{ - typedef typename boost::range_value::type value_type; - typedef typename boost::mpl::if_c - < - boost::is_const::value, - typename boost::add_const::type, - value_type - >::type sub_type; - typedef detail_dispatch::sub_geometry::get get_type; - typedef typename get_type::result_type result_type; - - template static inline - result_type apply(Geometry & geometry, Id const& id) - { - BOOST_ASSERT(0 <= id.multi_index); - return get_type::apply(*(boost::begin(geometry) + id.multi_index), id); - } -}; - -}} // namespace detail_dispatch::sub_geometry - -namespace detail { namespace sub_geometry { - -template -struct result_type -{ - typedef typename detail_dispatch::sub_geometry::get::result_type type; -}; - -// This function also works for geometry::segment_identifier - -template inline -typename detail_dispatch::sub_geometry::get::result_type -get(Geometry & geometry, Id const& id) -{ - return detail_dispatch::sub_geometry::get::apply(geometry, id); -}; - -}} // namespace detail::sub_geometry -#endif - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_GEOMETRY_HPP diff --git a/include/boost/geometry/algorithms/detail/sub_range.hpp b/include/boost/geometry/algorithms/detail/sub_range.hpp new file mode 100644 index 000000000..5c5b2f9c0 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/sub_range.hpp @@ -0,0 +1,113 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// 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) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP + +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch { + +template ::type, + bool IsMulti = boost::is_base_of::value> +struct sub_range : not_implemented +{}; + +template +struct sub_range +{ + typedef Geometry & return_type; + + template static inline + return_type apply(Geometry & geometry, Id const&) + { + return geometry; + } +}; + +template +struct sub_range +{ + typedef typename geometry::ring_type::type & return_type; + + template static inline + return_type apply(Geometry & geometry, Id const& id) + { + if ( id.ring_index < 0 ) + { + return geometry::exterior_ring(geometry); + } + else + { + std::size_t ri = static_cast(id.ring_index); + return range::at(geometry::interior_rings(geometry), ri); + } + } +}; + +template +struct sub_range +{ + typedef typename boost::range_value::type value_type; + typedef typename boost::mpl::if_c + < + boost::is_const::value, + typename boost::add_const::type, + value_type + >::type sub_type; + + typedef detail_dispatch::sub_range sub_sub_range; + + // TODO: shouldn't it be return_type? + typedef typename sub_sub_range::return_type return_type; + + template static inline + return_type apply(Geometry & geometry, Id const& id) + { + BOOST_ASSERT(0 <= id.multi_index); + return sub_sub_range::apply(range::at(geometry, id.multi_index), id); + } +}; + +} // namespace detail_dispatch +#endif // DOXYGEN_NO_DISPATCH + +namespace detail { + +template +struct sub_range_return_type +{ + typedef typename detail_dispatch::sub_range::return_type type; +}; + +// This function also works for geometry::segment_identifier + +template inline +typename sub_range_return_type::type +sub_range(Geometry & geometry, Id const& id) +{ + return detail_dispatch::sub_range::apply(geometry, id); +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP diff --git a/include/boost/geometry/algorithms/touches.hpp b/include/boost/geometry/algorithms/touches.hpp index 9992f6073..a34ac777e 100644 --- a/include/boost/geometry/algorithms/touches.hpp +++ b/include/boost/geometry/algorithms/touches.hpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -207,8 +207,8 @@ struct linear_areal_interrupt_policy template inline bool is_turn_on_last_point(Turn const& turn) { - typename sub_geometry::result_type::type - g = sub_geometry::get(linear, turn.operations[0].seg_id); + typename sub_range_return_type::type + g = sub_range(linear, turn.operations[0].seg_id); std::size_t s = boost::size(g); diff --git a/test/algorithms/within.cpp b/test/algorithms/within.cpp index 9ee26bec3..fe1580fd8 100644 --- a/test/algorithms/within.cpp +++ b/test/algorithms/within.cpp @@ -29,8 +29,6 @@ void test_linestring_linestring() test_geometry("LINESTRING(1 1, 2 2, 3 2)", "LINESTRING(4 2, 2 2, 0 0)", true); test_geometry("LINESTRING(3 2, 2 2, 1 1)", "LINESTRING(4 2, 2 2, 0 0)", true); - test_geometry("LINESTRING(1 1, 2 2, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true); - test_geometry("LINESTRING(1 1, 2 2, 3 3)", "LINESTRING(0 0, 2 2, 4 2)", false); test_geometry("LINESTRING(1 1, 2 2, 3 2, 3 3)", "LINESTRING(0 0, 2 2, 4 2)", false); test_geometry("LINESTRING(1 1, 2 2, 3 1)", "LINESTRING(0 0, 2 2, 4 2)", false); @@ -41,19 +39,27 @@ void test_linestring_linestring() test_geometry("LINESTRING(1 0, 1 1, 2 2, 3 2)", "LINESTRING(0 0, 2 2, 4 2)", false); test_geometry("LINESTRING(1 0, 0 0, 2 2, 3 2)", "LINESTRING(0 0, 2 2, 4 2)", false); + // duplicated points + test_geometry("LINESTRING(1 1, 2 2, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true); + test_geometry("LINESTRING(1 1, 1 1, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true); + + // invalid linestrings // test_geometry("LINESTRING(0 0)", "LINESTRING(0 0)", false); // test_geometry("LINESTRING(1 1)", "LINESTRING(0 0, 2 2)", true); // test_geometry("LINESTRING(0 0)", "LINESTRING(0 0, 2 2)", false); // test_geometry("LINESTRING(0 0, 1 1)", "LINESTRING(0 0)", false); - test_geometry("LINESTRING(0 0,5 0,3 0,6 0)", "LINESTRING(0 0,6 0)", true); + // spikes + // FOR NOW DISABLED + + /*test_geometry("LINESTRING(0 0,5 0,3 0,6 0)", "LINESTRING(0 0,6 0)", true); test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,3 3,6 3)", true); test_geometry("LINESTRING(0 0,3 3,6 3)", "LINESTRING(0 0,2 2,3 3,1 1)", false); test_geometry("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", true); test_geometry("LINESTRING(0 0,4 4,6 3)", "LINESTRING(0 0,2 2,3 3,1 1)", false); - test_geometry("LINESTRING(0 0,2 2,3 3,1 1,5 3)", "LINESTRING(0 0,3 3,6 3)", false); + test_geometry("LINESTRING(0 0,2 2,3 3,1 1,5 3)", "LINESTRING(0 0,3 3,6 3)", false);*/ } template From 3b91c7ed346c5b5350e24ccd34e38f11f2d1e339 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 23 Mar 2014 17:54:52 +0100 Subject: [PATCH 08/31] [relate] fix compile errors (use of old names) --- .../geometry/algorithms/detail/relate/boundary_checker.hpp | 5 +++-- include/boost/geometry/algorithms/detail/relate/turns.hpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index 330cf38be..d7506a40e 100644 --- a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -12,6 +12,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP #include +#include #include @@ -113,14 +114,14 @@ public: if ( BoundaryQuery == boundary_back ) { - if ( sid.segment_index + 2 != geometry::num_points(sub_geometry::get(geometry, sid)) ) + if ( sid.segment_index + 2 != geometry::num_points(sub_range(geometry, sid)) ) return false; } if ( BoundaryQuery == boundary_any ) { if ( sid.segment_index != 0 - && sid.segment_index + 2 != geometry::num_points(sub_geometry::get(geometry, sid)) ) + && sid.segment_index + 2 != geometry::num_points(sub_range(geometry, sid)) ) return false; } diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index 8467474c2..a396534a3 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -110,7 +110,7 @@ struct get_turns reverse1, reverse2, GetTurnPolicy - >::apply(0, geometry1, 1, geometry2, bg::detail::no_rescale_policy(), turns, interrupt_policy); + >::apply(0, geometry1, 1, geometry2, detail::no_rescale_policy(), turns, interrupt_policy); } }; From b6fc144de7a5354e65f49c62cda95fba82693963 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Mar 2014 19:27:35 +0100 Subject: [PATCH 09/31] [relate][within] add tests for Linestrings with duplicated points --- .../algorithms/detail/relate/linear_areal.hpp | 1 + test/algorithms/relate.cpp | 17 +++++++++++++++++ test/algorithms/within.cpp | 3 +++ 3 files changed, 21 insertions(+) diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 395b2ffc1..bb766a233 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -863,6 +863,7 @@ struct linear_areal if ( is_ip_qj ) { +// TODO: this won't work for duplicated points!!! std::size_t q_seg_jk = (q_seg_ij + 1) % seg_count2; BOOST_ASSERT(q_seg_jk + 1 < s2); point2_type const& qk = range::at(range2, q_seg_jk + 1); diff --git a/test/algorithms/relate.cpp b/test/algorithms/relate.cpp index 3b41ade12..6a4dd7d2b 100644 --- a/test/algorithms/relate.cpp +++ b/test/algorithms/relate.cpp @@ -433,6 +433,23 @@ void test_linestring_polygon() // II IB0 IE test_geometry("LINESTRING(5 5,10 5,15 10)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); + test_geometry("LINESTRING(5 5,5 5,5 5,10 5,10 5,10 5,15 10,15 10,15 10)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + test_geometry("LINESTRING(5 5,5 5,5 5,10 0,10 0,10 0,15 10,15 10,15 10)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + // IE IB0 II + test_geometry("LINESTRING(15 10,15 10,15 10,10 5,10 5,10 5,5 5,5 5,5 5)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + test_geometry("LINESTRING(15 10,15 10,15 10,10 0,10 0,10 0,5 5,5 5,5 5)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + + // TEST + test_geometry("LINESTRING(5 5,5 5,5 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); + test_geometry("LINESTRING(5 5,5 5,5 5,15 5,15 5,15 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); // non-simple polygon with hole test_geometry("LINESTRING(9 1,10 5,9 9)", diff --git a/test/algorithms/within.cpp b/test/algorithms/within.cpp index fe1580fd8..46a01d31d 100644 --- a/test/algorithms/within.cpp +++ b/test/algorithms/within.cpp @@ -43,6 +43,9 @@ void test_linestring_linestring() test_geometry("LINESTRING(1 1, 2 2, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true); test_geometry("LINESTRING(1 1, 1 1, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true); + test_geometry("LINESTRING(0 0, 0 0, 0 0, 1 1, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 3 3)", + "LINESTRING(0 0, 2 2, 4 2)", true); + // invalid linestrings // test_geometry("LINESTRING(0 0)", "LINESTRING(0 0)", false); // test_geometry("LINESTRING(1 1)", "LINESTRING(0 0, 2 2)", true); From ccbc15b8a1c14f76c07f1ed52e33468ba6505784 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 25 Mar 2014 00:29:25 +0100 Subject: [PATCH 10/31] [get_turns][relate] handle doubled points in relate L/L and L/A add info about the first/last non-doubled section to sectionalize modify get_turns() to pass info about the first/last segment to TurnPolicy::apply() modify parameters of TurnPolicy::apply() add searching for the next non-equal point in relate L/A when the segment of Linear must be checked if it starts in the interior or exterior of the Areal add tests for relate and within add relate L/A to Jamfile --- .../overlay/get_intersection_points.hpp | 5 +- .../detail/overlay/get_turn_info.hpp | 5 +- .../overlay/get_turn_info_for_endpoint.hpp | 10 +-- .../detail/overlay/get_turn_info_la.hpp | 30 +++---- .../detail/overlay/get_turn_info_ll.hpp | 24 ++--- .../algorithms/detail/overlay/get_turns.hpp | 26 ++++-- .../algorithms/detail/relate/linear_areal.hpp | 39 ++++++-- .../detail/sections/sectionalize.hpp | 88 ++++++++++++------- .../detail/sections/sectionalize.cpp | 6 +- test/algorithms/overlay/Jamfile.v2 | 1 + test/algorithms/overlay/get_turn_info.cpp | 2 +- test/algorithms/relate.cpp | 45 ++++++---- test/algorithms/within.cpp | 2 +- 13 files changed, 175 insertions(+), 108 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index 720f83e3a..7d882d003 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -52,9 +52,8 @@ struct get_turn_without_info static inline OutputIterator apply( Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, -// TODO: should this always be std::size_t or replace with template parameter? - std::size_t /*p_segments_count*/, - std::size_t /*q_segments_count*/, + bool /*is_p_first*/, bool /*is_p_last*/, + bool /*is_q_first*/, bool /*is_q_last*/, TurnInfo const& , RescalePolicy const& rescale_policy, OutputIterator out) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 0088c7b4c..5192b3aac 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -975,9 +975,8 @@ struct get_turn_info static inline OutputIterator apply( Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, -// TODO: should this always be std::size_t or replace with template parameter? - std::size_t /*p_segments_count*/, - std::size_t /*q_segments_count*/, + bool /*is_p_first*/, bool /*is_p_last*/, + bool /*is_q_first*/, bool /*is_q_last*/, TurnInfo const& tp_model, RescalePolicy const& , // TODO: this will be used. rescale_policy, OutputIterator out) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index fe1938496..78edbefb6 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -130,9 +130,8 @@ struct get_turn_info_for_endpoint > static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, -// TODO: should this always be std::size_t or replace with template parameter? - std::size_t p_segments_count, - std::size_t q_segments_count, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, TurnInfo const& tp_model, IntersectionResult const& result, method_type method, @@ -147,11 +146,6 @@ struct get_turn_info_for_endpoint int segment_index1 = tp_model.operations[1].seg_id.segment_index; BOOST_ASSERT(segment_index0 >= 0 && segment_index1 >= 0); - bool is_p_first = segment_index0 == 0; - bool is_q_first = segment_index1 == 0; - bool is_p_last = static_cast(segment_index0) + 1 == p_segments_count; - bool is_q_last = static_cast(segment_index1) + 1 == q_segments_count; - if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last ) return false; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index a66f7b293..0bbd1e57d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -39,9 +39,8 @@ struct get_turn_info_linear_areal static inline OutputIterator apply( Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, -// TODO: should this always be std::size_t or replace with template parameter? - std::size_t p_segments_count, - std::size_t q_segments_count, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, TurnInfo const& tp_model, RescalePolicy const& , // TODO: this will be used. rescale_policy, OutputIterator out) @@ -77,7 +76,8 @@ struct get_turn_info_linear_areal case 'f' : // collinear, "from" case 's' : // starts from the middle get_turn_info_for_endpoint( - pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_none, out); break; @@ -87,7 +87,8 @@ struct get_turn_info_linear_areal case 'm' : { if ( get_turn_info_for_endpoint( - pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_touch_interior, out) ) { // do nothing @@ -142,7 +143,8 @@ struct get_turn_info_linear_areal { // Both touch (both arrive there) if ( get_turn_info_for_endpoint( - pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_touch, out) ) { // do nothing @@ -167,7 +169,8 @@ struct get_turn_info_linear_areal case 'e': { if ( get_turn_info_for_endpoint( - pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_equal, out) ) { // do nothing @@ -213,7 +216,8 @@ struct get_turn_info_linear_areal { // Collinear if ( get_turn_info_for_endpoint( - pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_collinear, out) ) { // do nothing @@ -377,9 +381,8 @@ struct get_turn_info_linear_areal static inline bool get_turn_info_for_endpoint( Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, -// TODO: should this always be std::size_t or replace with template parameter? - std::size_t p_segments_count, - std::size_t q_segments_count, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, TurnInfo const& tp_model, IntersectionResult const& result, method_type method, @@ -397,11 +400,6 @@ struct get_turn_info_linear_areal const int segment_index1 = tp_model.operations[1].seg_id.segment_index; BOOST_ASSERT(segment_index0 >= 0 && segment_index1 >= 0); - const bool is_p_first = segment_index0 == 0; - const bool is_q_first = segment_index1 == 0; // not used - const bool is_p_last = static_cast(segment_index0) + 1 == p_segments_count; - const bool is_q_last = static_cast(segment_index1) + 1 == q_segments_count; // not used - if ( !is_p_first && !is_p_last ) return false; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index eb836582d..586bc3f91 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -92,9 +92,8 @@ struct get_turn_info_linear_linear static inline OutputIterator apply( Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, -// TODO: should this always be std::size_t or replace with template parameter? - std::size_t p_segments_count, - std::size_t q_segments_count, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, TurnInfo const& tp_model, RescalePolicy const& , // TODO: this will be used. rescale_policy, OutputIterator out) @@ -130,8 +129,9 @@ struct get_turn_info_linear_linear case 'f' : // collinear, "from" case 's' : // starts from the middle get_turn_info_for_endpoint - ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, - tp_model, result, method_none, out); + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, result, method_none, out); break; case 'd' : // disjoint: never do anything @@ -140,8 +140,9 @@ struct get_turn_info_linear_linear case 'm' : { if ( get_turn_info_for_endpoint - ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, - tp_model, result, method_touch_interior, out) ) + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, result, method_touch_interior, out) ) { // do nothing } @@ -199,7 +200,8 @@ struct get_turn_info_linear_linear { // Both touch (both arrive there) if ( get_turn_info_for_endpoint - ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_touch, out) ) { // do nothing @@ -228,7 +230,8 @@ struct get_turn_info_linear_linear case 'e': { if ( get_turn_info_for_endpoint - ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_equal, out) ) { // do nothing @@ -280,7 +283,8 @@ struct get_turn_info_linear_linear { // Collinear if ( get_turn_info_for_endpoint - ::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count, + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, tp_model, result, method_collinear, out) ) { // do nothing diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 0004646d6..4ca5c81bd 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -286,8 +286,13 @@ public : std::size_t const size_before = boost::size(turns); + bool const is_1_first = sec1.is_non_duplicate_first && index1 == sec1.begin_index; + bool const is_1_last = sec1.is_non_duplicate_last && index1+1 >= sec1.end_index; + bool const is_2_first = sec2.is_non_duplicate_first && index2 == sec2.begin_index; + bool const is_2_last = sec2.is_non_duplicate_last && index2+1 >= sec2.end_index; + TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2, - sec1.range_count - 1, sec2.range_count - 1, + is_1_first, is_1_last, is_2_first, is_2_last, ti, rescale_policy, std::back_inserter(turns)); if (InterruptPolicy::enabled) @@ -597,7 +602,9 @@ struct get_turns_cs get_turns_with_box(seg_id, source_id2, *prev, *it, *next, bp[0], bp[1], bp[2], bp[3], - segments_count1, + // NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes + index == 0, + unsigned(index) == segments_count1, rescale_policy, turns, interrupt_policy); // Future performance enhancement: @@ -638,7 +645,8 @@ private: box_point_type const& bp1, box_point_type const& bp2, box_point_type const& bp3, - std::size_t segments_count1, + bool const is_range_first, + bool const is_range_last, RescalePolicy const& rescale_policy, // Output Turns& turns, @@ -657,22 +665,26 @@ private: ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 0); TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2, - segments_count1, 4, + is_range_first, is_range_last, + true, false, ti, rescale_policy, std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1); TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3, - segments_count1, 4, + is_range_first, is_range_last, + false, false, ti, rescale_policy, std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2); TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0, - segments_count1, 4, + is_range_first, is_range_last, + false, false, ti, rescale_policy, std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3); TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1, - segments_count1, 4, + is_range_first, is_range_last, + false, true, ti, rescale_policy, std::back_inserter(turns)); if (InterruptPolicy::enabled) diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index bb766a233..8dd1fa896 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -608,6 +608,7 @@ struct linear_areal && !fake_enter_detected && it->operations[op_id].position != overlay::position_front ) { +// TODO: calculate_from_inside() is only needed if the current Linestring is not closed bool from_inside = first_in_range && calculate_from_inside(geometry, other_geometry, @@ -693,6 +694,7 @@ struct linear_areal // TODO: very similar code is used in the handling of intersection if ( it->operations[op_id].position != overlay::position_front ) { +// TODO: calculate_from_inside() is only needed if the current Linestring is not closed bool first_from_inside = first_in_range && calculate_from_inside(geometry, other_geometry, @@ -863,12 +865,16 @@ struct linear_areal if ( is_ip_qj ) { -// TODO: this won't work for duplicated points!!! std::size_t q_seg_jk = (q_seg_ij + 1) % seg_count2; - BOOST_ASSERT(q_seg_jk + 1 < s2); - point2_type const& qk = range::at(range2, q_seg_jk + 1); - // Will this sequence of point be always correct? - overlay::side_calculator side_calc(qi_conv, new_pj, pi, qi, qj, qk); +// TODO: the following function should return immediately, however the worst case complexity is O(N) +// It would be good to replace it with some O(1) mechanism + typename boost::range_iterator::type + qk_it = find_next_non_duplicated(boost::begin(range2), + boost::begin(range2) + q_seg_jk, + boost::end(range2)); + + // Will this sequence of points be always correct? + overlay::side_calculator side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it); return calculate_from_inside_sides(side_calc); } @@ -883,6 +889,29 @@ struct linear_areal } } + template + static inline It find_next_non_duplicated(It first, It current, It last) + { + BOOST_ASSERT( current != last ); + + It it = current; + + for ( ++it ; it != last ; ++it ) + { + if ( !equals::equals_point_point(*current, *it) ) + return it; + } + + // if not found start from the beginning + for ( it = first ; it != current ; ++it ) + { + if ( !equals::equals_point_point(*current, *it) ) + return it; + } + + return current; + } + // calculate inside or outside based on side_calc // this is simplified version of a check from equal<> template diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 82d9f7d32..71c3a9bb1 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -4,6 +4,9 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -11,6 +14,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP @@ -72,6 +77,9 @@ struct section bool duplicate; int non_duplicate_index; + bool is_non_duplicate_first; + bool is_non_duplicate_last; + inline section() : id(-1) , begin_index(-1) @@ -80,6 +88,8 @@ struct section , range_count(0) , duplicate(false) , non_duplicate_index(-1) + , is_non_duplicate_first(false) + , is_non_duplicate_last(false) { assign_inverse(bounding_box); for (std::size_t i = 0; i < DimensionCount; i++) @@ -251,13 +261,11 @@ struct sectionalize_part typename Sections > static inline void apply(Sections& sections, - typename boost::range_value::type& section, - int& index, int& ndi, - Range const& range, - RescalePolicy const& rescale_policy, - bool make_rescaled_boxes, - ring_identifier ring_id, - std::size_t max_count) + Range const& range, + RescalePolicy const& rescale_policy, + bool make_rescaled_boxes, + ring_identifier ring_id, + std::size_t max_count) { boost::ignore_unused_variable_warning(rescale_policy); boost::ignore_unused_variable_warning(make_rescaled_boxes); @@ -267,19 +275,20 @@ struct sectionalize_part typedef typename boost::range_iterator::type iterator_type; - if (int(boost::size(range)) <= index) + if ( boost::empty(range) ) { return; } - if (index == 0) - { - ndi = 0; - } + int index = 0; + int ndi = 0; // non duplicate index + section_type section; + + bool mark_first_non_duplicated = true; + std::size_t last_non_duplicate_index = 0; iterator_type it = boost::begin(range); - it += index; - + for(iterator_type previous = it++; it != boost::end(range); ++previous, ++it, index++) @@ -329,6 +338,11 @@ struct sectionalize_part ) ) { + if ( !section.duplicate ) + { + last_non_duplicate_index = sections.size(); + } + sections.push_back(section); section = section_type(); } @@ -341,6 +355,12 @@ struct sectionalize_part section.non_duplicate_index = ndi; section.range_count = boost::size(range); + if ( mark_first_non_duplicated && !duplicate ) + { + section.is_non_duplicate_first = true; + mark_first_non_duplicated = false; + } + copy_loop < int, 0, DimensionCount @@ -356,6 +376,23 @@ struct sectionalize_part ndi++; } } + + // Add last section if applicable + if (section.count > 0) + { + if ( !section.duplicate ) + { + last_non_duplicate_index = sections.size(); + } + + sections.push_back(section); + } + + if ( last_non_duplicate_index < sections.size() + && !sections[last_non_duplicate_index].duplicate ) + { + sections[last_non_duplicate_index].is_non_duplicate_last = true; + } } }; @@ -375,10 +412,11 @@ struct sectionalize_range typename Sections > static inline void apply(Range const& range, - RescalePolicy const& rescale_policy, - bool make_rescaled_boxes, - Sections& sections, - ring_identifier ring_id, std::size_t max_count) + RescalePolicy const& rescale_policy, + bool make_rescaled_boxes, + Sections& sections, + ring_identifier ring_id, + std::size_t max_count) { typedef typename closeable_view::type cview_type; typedef typename reversible_view @@ -403,20 +441,8 @@ struct sectionalize_range return; } - int index = 0; - int ndi = 0; // non duplicate index - - typedef typename boost::range_value::type section_type; - section_type section; - sectionalize_part - ::apply(sections, section, index, ndi, view, rescale_policy, make_rescaled_boxes, ring_id, max_count); - - // Add last section if applicable - if (section.count > 0) - { - sections.push_back(section); - } + ::apply(sections, view, rescale_policy, make_rescaled_boxes, ring_id, max_count); } }; diff --git a/test/algorithms/detail/sections/sectionalize.cpp b/test/algorithms/detail/sections/sectionalize.cpp index 212e95ea1..b4569fa24 100644 --- a/test/algorithms/detail/sections/sectionalize.cpp +++ b/test/algorithms/detail/sections/sectionalize.cpp @@ -61,13 +61,11 @@ void test_sectionalize_part() bg::detail::no_rescale_policy rescale_policy; bg::ring_identifier ring_id; - int index = 0; - int ndi = 0; - sectionalize_part::apply(sections, section, index, ndi, geometry, rescale_policy, false, ring_id, 10); + sectionalize_part::apply(sections, geometry, rescale_policy, false, ring_id, 10); // There should not yet be anything generated, because it is only ONE point geometry.push_back(bg::make(2, 2)); - sectionalize_part::apply(sections, section, index, ndi, geometry, rescale_policy, false, ring_id, 10); + sectionalize_part::apply(sections, geometry, rescale_policy, false, ring_id, 10); } diff --git a/test/algorithms/overlay/Jamfile.v2 b/test/algorithms/overlay/Jamfile.v2 index b18744d41..a97c6b256 100644 --- a/test/algorithms/overlay/Jamfile.v2 +++ b/test/algorithms/overlay/Jamfile.v2 @@ -20,6 +20,7 @@ test-suite boost-geometry-algorithms-overlay [ run get_turn_info.cpp ] [ run get_turns.cpp ] [ run get_turns_linear_linear.cpp ] + [ run get_turns_linear_areal.cpp ] [ run relative_order.cpp ] [ run select_rings.cpp ] [ run self_intersection_points.cpp ] diff --git a/test/algorithms/overlay/get_turn_info.cpp b/test/algorithms/overlay/get_turn_info.cpp index e6dca7db8..a58fcadaf 100644 --- a/test/algorithms/overlay/get_turn_info.cpp +++ b/test/algorithms/overlay/get_turn_info.cpp @@ -51,7 +51,7 @@ void test_with_point(std::string const& caseid, < bg::detail::overlay::assign_null_policy >::apply(pi, pj, pk, qi, qj, qk, - 10, 10, // dummy max numbers of segments + false, false, false, false, // dummy parameters model, bg::detail::no_rescale_policy(), std::back_inserter(info)); diff --git a/test/algorithms/relate.cpp b/test/algorithms/relate.cpp index 6a4dd7d2b..47ae063b0 100644 --- a/test/algorithms/relate.cpp +++ b/test/algorithms/relate.cpp @@ -318,6 +318,10 @@ void test_linestring_linestring() test_geometry("LINESTRING(1 0,5 0,7 0,8 1)", "LINESTRING(0 0,10 0,10 10,4 -1)", "1F10F0102"); + // duplicated points + test_geometry("LINESTRING(1 1, 2 2, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", "1FF0FF102"); + test_geometry("LINESTRING(1 1, 1 1, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", "1FF0FF102"); + // linear ring test_geometry("LINESTRING(0 0,10 0)", "LINESTRING(5 0,9 0,5 5,1 0,5 0)", "1F1FF01F2"); test_geometry("LINESTRING(0 0,5 0,10 0)", "LINESTRING(5 0,9 0,5 5,1 0,5 0)", "1F1FF01F2"); @@ -431,25 +435,28 @@ void test_linestring_polygon() // IB1 IE test_geometry("LINESTRING(10 10,10 5,15 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "F11F00212"); - // II IB0 IE - test_geometry("LINESTRING(5 5,10 5,15 10)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); - test_geometry("LINESTRING(5 5,5 5,5 5,10 5,10 5,10 5,15 10,15 10,15 10)", - "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", - "1010F0212"); - test_geometry("LINESTRING(5 5,5 5,5 5,10 0,10 0,10 0,15 10,15 10,15 10)", - "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", - "1010F0212"); - // IE IB0 II - test_geometry("LINESTRING(15 10,15 10,15 10,10 5,10 5,10 5,5 5,5 5,5 5)", - "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", - "1010F0212"); - test_geometry("LINESTRING(15 10,15 10,15 10,10 0,10 0,10 0,5 5,5 5,5 5)", - "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", - "1010F0212"); - - // TEST - test_geometry("LINESTRING(5 5,5 5,5 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); - test_geometry("LINESTRING(5 5,5 5,5 5,15 5,15 5,15 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); + // duplicated points + { + // II IB0 IE + test_geometry("LINESTRING(5 5,10 5,15 10)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); + test_geometry("LINESTRING(5 5,5 5,5 5,10 5,10 5,10 5,15 10,15 10,15 10)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + test_geometry("LINESTRING(5 5,5 5,5 5,10 0,10 0,10 0,15 10,15 10,15 10)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + // IE IB0 II + test_geometry("LINESTRING(15 10,15 10,15 10,10 5,10 5,10 5,5 5,5 5,5 5)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + test_geometry("LINESTRING(15 10,15 10,15 10,10 0,10 0,10 0,5 5,5 5,5 5)", + "POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))", + "1010F0212"); + + // TEST + //test_geometry("LINESTRING(5 5,5 5,5 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); + test_geometry("LINESTRING(5 5,5 5,5 5,15 5,15 5,15 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212"); + } // non-simple polygon with hole test_geometry("LINESTRING(9 1,10 5,9 9)", diff --git a/test/algorithms/within.cpp b/test/algorithms/within.cpp index 46a01d31d..dcc65c31b 100644 --- a/test/algorithms/within.cpp +++ b/test/algorithms/within.cpp @@ -44,7 +44,7 @@ void test_linestring_linestring() test_geometry("LINESTRING(1 1, 1 1, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true); test_geometry("LINESTRING(0 0, 0 0, 0 0, 1 1, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 3 3)", - "LINESTRING(0 0, 2 2, 4 2)", true); + "LINESTRING(0 0, 2 2, 4 4)", true); // invalid linestrings // test_geometry("LINESTRING(0 0)", "LINESTRING(0 0)", false); From 3a29d3a90c0415039108b87f1861f6c8125d4394 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 25 Mar 2014 03:16:40 +0100 Subject: [PATCH 11/31] [relate] fix MinGW compilation error - add includes missing in relate/result.hpp --- include/boost/geometry/algorithms/detail/relate/result.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/algorithms/detail/relate/result.hpp b/include/boost/geometry/algorithms/detail/relate/result.hpp index f177b7cc0..f32e7db7e 100644 --- a/include/boost/geometry/algorithms/detail/relate/result.hpp +++ b/include/boost/geometry/algorithms/detail/relate/result.hpp @@ -15,8 +15,13 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP #include -#include + +#include +#include +#include +#include #include +#include #include From 7abe47876b19831c399696ee197be4806f355d92 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 26 Mar 2014 10:22:31 +0200 Subject: [PATCH 12/31] [feature/point iterator] implementation of point iterator for most geometries (not yet for point, segment & box); --- .../geometry/core/dispatch/point_iterator.hpp | 47 +++ .../core/dispatch/point_iterator_type.hpp | 37 ++ .../boost/geometry/core/point_iterator.hpp | 242 +++++++++++++ .../geometry/core/point_iterator_type.hpp | 216 ++++++++++++ .../geometry/util/concatenate_iterator.hpp | 91 +++++ .../boost/geometry/util/flatten_iterator.hpp | 219 ++++++++++++ test/core/point_iterator.cpp | 331 ++++++++++++++++++ 7 files changed, 1183 insertions(+) create mode 100644 include/boost/geometry/core/dispatch/point_iterator.hpp create mode 100644 include/boost/geometry/core/dispatch/point_iterator_type.hpp create mode 100644 include/boost/geometry/core/point_iterator.hpp create mode 100644 include/boost/geometry/core/point_iterator_type.hpp create mode 100644 include/boost/geometry/util/concatenate_iterator.hpp create mode 100644 include/boost/geometry/util/flatten_iterator.hpp create mode 100644 test/core/point_iterator.cpp diff --git a/include/boost/geometry/core/dispatch/point_iterator.hpp b/include/boost/geometry/core/dispatch/point_iterator.hpp new file mode 100644 index 000000000..9d89ae737 --- /dev/null +++ b/include/boost/geometry/core/dispatch/point_iterator.hpp @@ -0,0 +1,47 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_CORE_DISPATCH_POINT_ITERATOR_HPP +#define BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_HPP + +#include +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace core_dispatch +{ + + +// dispatch for points_begin +template ::type> +struct points_begin + : not_implemented +{}; + + + +// dispatch for points_end +template ::type> +struct points_end + : not_implemented +{}; + + + +} // namespace core_dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_HPP diff --git a/include/boost/geometry/core/dispatch/point_iterator_type.hpp b/include/boost/geometry/core/dispatch/point_iterator_type.hpp new file mode 100644 index 000000000..abf91dd9a --- /dev/null +++ b/include/boost/geometry/core/dispatch/point_iterator_type.hpp @@ -0,0 +1,37 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_CORE_DISPATCH_POINT_ITERATOR_TYPE_HPP +#define BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_TYPE_HPP + +#include +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace core_dispatch +{ + +template ::type> +struct point_iterator_type + : not_implemented +{}; + + + +} // namespace core_dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_TYPE_HPP diff --git a/include/boost/geometry/core/point_iterator.hpp b/include/boost/geometry/core/point_iterator.hpp new file mode 100644 index 000000000..7339977c1 --- /dev/null +++ b/include/boost/geometry/core/point_iterator.hpp @@ -0,0 +1,242 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_CORE_POINT_ITERATOR_HPP +#define BOOST_GEOMETRY_CORE_POINT_ITERATOR_HPP + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace core_dispatch +{ + + +// specializations for points_begin + + +// linestring +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(Linestring& linestring) + { + return boost::begin(linestring); + } +}; + + +// ring +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(Ring& ring) + { + return boost::begin(ring); + } +}; + + +// polygon +template +struct points_begin +{ + typedef typename point_iterator_type::type return_type; + + static inline return_type apply(Polygon& polygon) + { + typedef typename return_type::second_iterator_type flatten_iterator; + + return return_type + (boost::begin(geometry::exterior_ring(polygon)), + boost::end(geometry::exterior_ring(polygon)), + flatten_iterator(boost::begin(geometry::interior_rings(polygon)), + boost::end(geometry::interior_rings(polygon)) + ) + ); + } +}; + + +// multi-point +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(MultiPoint& multipoint) + { + return boost::begin(multipoint); + } +}; + + +// multi-linestring +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(MultiLinestring& multilinestring) + { + return typename point_iterator_type + < + MultiLinestring + >::type(boost::begin(multilinestring), boost::end(multilinestring)); + } +}; + + +// multi-polygon +template +struct points_begin +{ + static inline typename point_iterator_type::type + apply(MultiPolygon& multipolygon) + { + return typename point_iterator_type + < + MultiPolygon + >::type(boost::begin(multipolygon), boost::end(multipolygon)); + } +}; + +} // namespace core_dispatch +#endif // DOXYGEN_NO_DISPATCH + + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace core_dispatch +{ + + +// specializations for points_end + + +// linestring +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(Linestring& linestring) + { + return boost::end(linestring); + } +}; + + +// ring +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(Ring& ring) + { + return boost::end(ring); + } +}; + + +// polygon +template +struct points_end +{ + typedef typename point_iterator_type::type return_type; + + static inline return_type apply(Polygon& polygon) + { + typedef typename return_type::second_iterator_type flatten_iterator; + + return return_type + (boost::end(geometry::exterior_ring(polygon)), + flatten_iterator( boost::end(geometry::interior_rings(polygon)) ) + ); + } +}; + + +// multi-point +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(MultiPoint& multipoint) + { + return boost::end(multipoint); + } +}; + + +// multi-linestring +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(MultiLinestring& multilinestring) + { + return typename point_iterator_type + < + MultiLinestring + >::type(boost::end(multilinestring)); + } +}; + + +// multi-polygon +template +struct points_end +{ + static inline typename point_iterator_type::type + apply(MultiPolygon& multipolygon) + { + return typename point_iterator_type + < + MultiPolygon + >::type(boost::end(multipolygon)); + } +}; + + +} // namespace core_dispatch +#endif // DOXYGEN_NO_DISPATCH + + + + +// MK:: need to add doc here +template +typename point_iterator_type::type +points_begin(Geometry& geometry) +{ + return core_dispatch::points_begin::apply(geometry); +} + + +// MK:: need to add doc here +template +typename point_iterator_type::type +points_end(Geometry& geometry) +{ + return core_dispatch::points_end::apply(geometry); +} + + + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_CORE_POINT_ITERATOR_HPP diff --git a/include/boost/geometry/core/point_iterator_type.hpp b/include/boost/geometry/core/point_iterator_type.hpp new file mode 100644 index 000000000..51e409d66 --- /dev/null +++ b/include/boost/geometry/core/point_iterator_type.hpp @@ -0,0 +1,216 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_CORE_POINT_ITERATOR_TYPE_HPP +#define BOOST_GEOMETRY_CORE_POINT_ITERATOR_TYPE_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + + +#ifndef DOXYGEN_NO_DETAIL +namespace core_detail +{ + + +template +struct point_iterator_value_type +{ + typedef typename boost::mpl::if_c + < + !boost::is_const::type::value, + typename geometry::point_type::type, + typename geometry::point_type::type const + >::type type; +}; + + + + +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct point_iterator_inner_range_type +{ + typedef typename boost::mpl::if_c + < + !boost::is_const::type::value, + typename boost::range_value::type, + typename boost::range_value::type const + >::type type; +}; + + +template +struct point_iterator_inner_range_type +{ + typedef typename boost::mpl::if_c + < + !boost::is_const::type::value, + typename geometry::ring_type::type, + typename geometry::ring_type::type const + >::type type; +}; + + + +} // namespace core_detail +#endif // DOXYGEN_NO_DETAIL + + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace core_dispatch +{ + + +// linestring +template +struct point_iterator_type +{ + typedef typename boost::range_iterator::type type; +}; + + +// ring +template +struct point_iterator_type +{ + typedef typename boost::range_iterator::type type; +}; + + +// polygon +template +class point_iterator_type +{ +private: + typedef typename core_detail::point_iterator_inner_range_type + < + Polygon + >::type InnerRange; + +public: + typedef util::concatenate_iterator + < + typename boost::range_iterator::type, + util::flatten_iterator + < + typename boost::range_iterator + < + typename geometry::interior_type::type + >::type, + typename core_dispatch::point_iterator_type + < + InnerRange + >::type, + typename core_detail::point_iterator_value_type + < + Polygon + >::type, + core_dispatch::points_begin, + core_dispatch::points_end + >, + typename core_detail::point_iterator_value_type::type + > type; +}; + + +// multi-point +template +struct point_iterator_type +{ + typedef typename boost::range_iterator::type type; +}; + + +// multi-linestring +template +class point_iterator_type +{ +private: + typedef typename core_detail::point_iterator_inner_range_type + < + MultiLinestring + >::type InnerRange; + +public: + typedef util::flatten_iterator + < + typename boost::range_iterator::type, + typename core_dispatch::point_iterator_type::type, + typename core_detail::point_iterator_value_type + < + MultiLinestring + >::type, + core_dispatch::points_begin, + core_dispatch::points_end + > type; +}; + + +// multi-polygon +template +class point_iterator_type +{ +private: + typedef typename core_detail::point_iterator_inner_range_type + < + MultiPolygon + >::type InnerRange; + +public: + typedef util::flatten_iterator + < + typename boost::range_iterator::type, + typename core_dispatch::point_iterator_type::type, + typename core_detail::point_iterator_value_type::type, + core_dispatch::points_begin, + core_dispatch::points_end + > type; +}; + + + + + +} // namespace core_dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +// MK::need to add doc here +template +struct point_iterator_type +{ + typedef typename core_dispatch::point_iterator_type::type type; +}; + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_CORE_POINT_ITERATOR_TYPE_HPP diff --git a/include/boost/geometry/util/concatenate_iterator.hpp b/include/boost/geometry/util/concatenate_iterator.hpp new file mode 100644 index 000000000..7071cf87b --- /dev/null +++ b/include/boost/geometry/util/concatenate_iterator.hpp @@ -0,0 +1,91 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_UTIL_POINT_CONCATENATE_ITERATOR_HPP +#define BOOST_GEOMETRY_UTIL_POINT_CONCATENATE_ITERATOR_HPP + +#include + + +namespace boost { namespace geometry +{ + + +namespace util +{ + + +template +struct concatenate_iterator + : public boost::iterator_facade + < + concatenate_iterator, + Value, + boost::forward_traversal_tag + > +{ +private: + Iterator1 m_it1, m_end1; + Iterator2 m_it2; + +public: + typedef Iterator1 first_iterator_type; + typedef Iterator2 second_iterator_type; + + // default constructor + concatenate_iterator() {} + + // for begin + concatenate_iterator(Iterator1 it1, Iterator1 end1, + Iterator2 it2) + : m_it1(it1), m_end1(end1), m_it2(it2) + {} + + // for end + concatenate_iterator(Iterator1 end1, Iterator2 end2) + : m_it1(end1), m_end1(end1), m_it2(end2) + {} + +private: + friend class boost::iterator_core_access; + + Value& dereference() const + { + if ( m_it1 == m_end1 ) + { + return *m_it2; + } + return *m_it1; + } + + bool equal(concatenate_iterator const& other) const + { + return m_it1 == other.m_it1 && m_it2 == other.m_it2; + } + + void increment() + { + if ( m_it1 == m_end1 ) + { + ++m_it2; + } + else + { + ++m_it1; + } + } +}; + + +} // namespace util + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_UTIL_CONCATENATE_ITERATOR_HPP diff --git a/include/boost/geometry/util/flatten_iterator.hpp b/include/boost/geometry/util/flatten_iterator.hpp new file mode 100644 index 000000000..9b44370bc --- /dev/null +++ b/include/boost/geometry/util/flatten_iterator.hpp @@ -0,0 +1,219 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, 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_UTIL_FLATTEN_ITERATOR_HPP +#define BOOST_GEOMETRY_UTIL_FLATTEN_ITERATOR_HPP + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +namespace util +{ + + +template +< + typename OuterIterator, + typename InnerIterator, + typename Value, + typename AccessInnerBegin, + typename AccessInnerEnd +> +struct flatten_iterator + : public boost::iterator_facade + < + flatten_iterator + < + OuterIterator, + InnerIterator, + Value, + AccessInnerBegin, + AccessInnerEnd>, + Value, + boost::forward_traversal_tag + > +{ +private: + OuterIterator m_outer_it, m_outer_end; + InnerIterator m_inner_it; + + struct enabler {}; + +public: + typedef OuterIterator outer_iterator_type; + typedef InnerIterator inner_iterator_type; + + // default constructor + flatten_iterator() {} + + // for begin + flatten_iterator(OuterIterator outer_it, OuterIterator outer_end) + : m_outer_it(outer_it), m_outer_end(outer_end) + { + if ( m_outer_it != m_outer_end ) + { + m_inner_it = AccessInnerBegin::apply(*m_outer_it); + // m_inner_it = AccessInnerBegin(*m_outer_it); + } + advance_through_empty(); + } + + // for end + flatten_iterator(OuterIterator outer_end) + : m_outer_it(outer_end), m_outer_end(outer_end) + {} + + template + < + typename OtherOuterIterator, + typename OtherInnerIterator, + typename OtherValue + > + explicit flatten_iterator(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + AccessInnerBegin, + AccessInnerEnd + > const& other, + typename boost::enable_if + < + boost::is_convertible + < + OtherOuterIterator*, OuterIterator* + >, enabler + >::type = enabler() + ) + : m_outer_it(other.m_outer_it), + m_outer_end(other.m_outer_end), + m_inner_it(other.m_inner_it) + {} + + template + < + typename OtherOuterIterator, + typename OtherInnerIterator, + typename OtherValue + > + flatten_iterator operator=(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + AccessInnerBegin, + AccessInnerEnd + > const& other) + { + m_outer_it = other.m_outer_it; + m_outer_end = other.m_outer_end; + m_inner_it = other.m_inner_it; + return *this; + } + +private: + friend class boost::iterator_core_access; + + template + < + typename OuterIterator1, + typename InnerIterator1, + typename Value1, + typename AccessInnerBegin1, + typename AccessInnerEnd1 + > + friend class flatten_iterator; + + static inline bool empty(OuterIterator outer_it) + { + return + AccessInnerBegin::apply(*outer_it) == AccessInnerEnd::apply(*outer_it); + // AccessInnerBegin(*outer_it) == AccessInnerEnd(*outer_it); + } + + void advance_through_empty() + { + while ( m_outer_it != m_outer_end && empty(m_outer_it) ) + { + ++m_outer_it; + } + + if ( m_outer_it != m_outer_end ) + { + m_inner_it = AccessInnerBegin::apply(*m_outer_it); + // m_inner_it = AccessInnerBegin(*m_outer_it); + } + } + + Value& dereference() const + { + BOOST_ASSERT( m_outer_it != m_outer_end ); + BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); + // BOOST_ASSERT( m_inner_it != AccessInnerEnd(*m_outer_it) ); + return *m_inner_it; + } + + + template + < + typename OtherOuterIterator, + typename OtherInnerIterator, + typename OtherValue + > + bool equal(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + AccessInnerBegin, + AccessInnerEnd + > const& other) const + { + if ( this->m_outer_it != other.m_outer_it ) + { + return false; + } + + if ( this->m_outer_it == m_outer_end ) + { + return true; + } + + return this->m_inner_it == other.m_inner_it; + } + + void increment() + { + BOOST_ASSERT( m_outer_it != m_outer_end ); + BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); + // BOOST_ASSERT( m_inner_it != AccessInnerEnd(*m_outer_it) ); + + ++m_inner_it; + if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) ) + //if ( m_inner_it == AccessInnerEnd(*m_outer_it) ) + { + ++m_outer_it; + advance_through_empty(); + } + } +}; + + +} // namespace util + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_UTIL_FLATTEN_INTERATOR_HPP diff --git a/test/core/point_iterator.cpp b/test/core/point_iterator.cpp new file mode 100644 index 000000000..a88a79b7d --- /dev/null +++ b/test/core/point_iterator.cpp @@ -0,0 +1,331 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014, 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 + + +#include + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_point_iterator +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../algorithms/from_wkt.hpp" + +#include + + +namespace bg = ::boost::geometry; + +typedef bg::model::point point_type; +typedef bg::model::linestring linestring_type; +typedef bg::model::polygon polygon_type; //ccw, open + +// multi geometries +typedef bg::model::multi_point multi_point_type; +typedef bg::model::multi_linestring multi_linestring_type; +typedef bg::model::multi_polygon multi_polygon_type; + +struct equals +{ + template + static inline std::size_t number_of_elements(Iterator begin, + Iterator end) + { + std::size_t num_elems(0); + for (Iterator it = begin; it != end; ++it) + { + ++num_elems; + } + return num_elems; + } + + template + static inline bool apply(Iterator1 begin1, Iterator1 end1, + Iterator2 begin2, Iterator2 end2) + { + std::size_t num_points1 = number_of_elements(begin1, end1); + std::size_t num_points2 = number_of_elements(begin2, end2); + + if ( num_points1 != num_points2 ) + { + return false; + } + + Iterator1 it1 = begin1; + Iterator2 it2 = begin2; + for (; it1 != end1; ++it1, ++it2) + { + if ( !bg::equals(*it1, *it2) ) + { + return false; + } + } + return true; + } +}; + +template +struct test_point_iterator_of_geometry +{ + template + static inline void base_test(G& geometry, + PointRange const& point_range, + std::string const& header) + { + typedef typename bg::point_iterator_type + < + G + >::type point_iterator_type; + + point_iterator_type begin = bg::points_begin(geometry); + point_iterator_type end = bg::points_end(geometry); + + BOOST_CHECK( equals::apply(begin, end, + boost::begin(point_range), + boost::end(point_range)) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << header << " geometry: " << bg::wkt(geometry) << std::endl; + std::cout << "point range: ("; + for (point_iterator_type pit = begin; pit != end; ++pit) + { + std::cout << " " << bg::dsv(*pit); + } + std::cout << " )" << std::endl; + std::cout << "expected point range: " << bg::wkt(point_range) + << std::endl; +#endif + } + + static inline void apply(Geometry geometry, PointRange const& point_range) + { + base_test(geometry, point_range, "non-const"); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; +#endif + + base_test(geometry, point_range, "const"); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif + } +}; + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_linestring_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** LINESTRING ***" << std::endl; +#endif + + typedef multi_point_type MP; + typedef linestring_type L; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("LINESTRING()"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("LINESTRING(3 3,4 4,5 5)"), + from_wkt("MULTIPOINT(3 3,4 4,5 5)") + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_polygon_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** POLYGON ***" << std::endl; +#endif + + typedef multi_point_type MP; + typedef polygon_type P; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt

("POLYGON()"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt

("POLYGON(())"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt

("POLYGON((3 3,4 4,5 5),(),(),(),\ + (6 6,7 7,8 8),(),(),(9 9),())"), + from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9)") + ); + + tester::apply(from_wkt

("POLYGON((),(3 3,4 4,5 5),(),(),\ + (6 6,7 7,8 8),(),(),(9 9),())"), + from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9)") + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multipoint_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTIPOINT ***" << std::endl; +#endif + + typedef multi_point_type MP; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTIPOINT()"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTIPOINT(3 3,4 4,5 5)"), + from_wkt("MULTIPOINT(3 3,4 4,5 5)") + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multilinestring_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTILINESTRING ***" << std::endl; +#endif + + typedef multi_point_type MP; + typedef linestring_type L; + typedef multi_linestring_type ML; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTILINESTRING()"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTILINESTRING(())"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTILINESTRING((),(),())"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTILINESTRING((),(),(0 0,1 1,2 2),(),(),\ + (3 3,4 4,5 5),(),(6 6),(),(),())"), + from_wkt("MULTIPOINT(0 0,1 1,2 2,3 3,4 4,5 5,6 6)") + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multipolygon_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTIPOLYGON ***" << std::endl; +#endif + + typedef multi_point_type MP; + typedef multi_polygon_type MPL; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTIPOLYGON()"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTIPOLYGON( () )"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTIPOLYGON( (()) )"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTIPOLYGON( ((),()) )"), + from_wkt("MULTIPOINT()") + ); + + tester::apply(from_wkt("MULTIPOLYGON(\ + ((3 3,4 4,5 5),(),(),(),\ + (6 6,7 7,8 8),(),(),(9 9),())\ + \ + ((),(1 1,2 2,10 10),(),(),(),\ + (11 11,12 12),(),(),(13 13),())\ + )"), + from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9,\ + 1 1,2 2,10 10,11 11,12 12,13 13)") + ); + + tester::apply(from_wkt("MULTIPOLYGON(\ + (),\ + \ + ((3 3,4 4,5 5),(),(),(),\ + (6 6,7 7,8 8),(),(),(9 9),())\ + \ + ((),(1 1,2 2,10 10),(),(),(),\ + (11 11,12 12),(),(),(13 13),())\ + \ + ((),(),()),\ + )"), + from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9,\ + 1 1,2 2,10 10,11 11,12 12,13 13)") + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif +} + From bed33a7ee40880a11e4c9ef1ab9aceaac5a64f7c Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 26 Mar 2014 11:25:06 +0200 Subject: [PATCH 13/31] [point iterator] add missing definition of from_wkt in unit test; --- test/core/point_iterator.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/core/point_iterator.cpp b/test/core/point_iterator.cpp index a88a79b7d..f06aac273 100644 --- a/test/core/point_iterator.cpp +++ b/test/core/point_iterator.cpp @@ -26,7 +26,6 @@ #include #include #include -#include "../algorithms/from_wkt.hpp" #include @@ -42,6 +41,16 @@ typedef bg::model::multi_point multi_point_type; typedef bg::model::multi_linestring multi_linestring_type; typedef bg::model::multi_polygon multi_polygon_type; + +template +Geometry from_wkt(std::string const& wkt) +{ + Geometry res; + boost::geometry::read_wkt(wkt, res); + return res; +} + + struct equals { template From 555947d8e2017ecffa7a6a7b0f80f7ff7b144e18 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 02:11:02 +0200 Subject: [PATCH 14/31] [point_iterator] define points_{begin,end} as inline free functions; --- include/boost/geometry/core/point_iterator.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/core/point_iterator.hpp b/include/boost/geometry/core/point_iterator.hpp index 7339977c1..9d5d13742 100644 --- a/include/boost/geometry/core/point_iterator.hpp +++ b/include/boost/geometry/core/point_iterator.hpp @@ -219,7 +219,7 @@ struct points_end // MK:: need to add doc here template -typename point_iterator_type::type +inline typename point_iterator_type::type points_begin(Geometry& geometry) { return core_dispatch::points_begin::apply(geometry); @@ -228,7 +228,7 @@ points_begin(Geometry& geometry) // MK:: need to add doc here template -typename point_iterator_type::type +inline typename point_iterator_type::type points_end(Geometry& geometry) { return core_dispatch::points_end::apply(geometry); From 64c11353be4fbdbdc19ab1cfba00d5aa936dd8ad Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 02:25:38 +0200 Subject: [PATCH 15/31] [point_iterator] move flatten and concatenate iterator implementation in iterators/ directory; --- .../concatenate_iterator.hpp | 12 ++++------ .../{util => iterators}/flatten_iterator.hpp | 24 +++++-------------- 2 files changed, 11 insertions(+), 25 deletions(-) rename include/boost/geometry/{util => iterators}/concatenate_iterator.hpp (86%) rename include/boost/geometry/{util => iterators}/flatten_iterator.hpp (87%) diff --git a/include/boost/geometry/util/concatenate_iterator.hpp b/include/boost/geometry/iterators/concatenate_iterator.hpp similarity index 86% rename from include/boost/geometry/util/concatenate_iterator.hpp rename to include/boost/geometry/iterators/concatenate_iterator.hpp index 7071cf87b..da2e78986 100644 --- a/include/boost/geometry/util/concatenate_iterator.hpp +++ b/include/boost/geometry/iterators/concatenate_iterator.hpp @@ -7,18 +7,18 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_UTIL_POINT_CONCATENATE_ITERATOR_HPP -#define BOOST_GEOMETRY_UTIL_POINT_CONCATENATE_ITERATOR_HPP +#ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP +#include #include +#include namespace boost { namespace geometry { -namespace util -{ template @@ -83,9 +83,7 @@ private: }; -} // namespace util - }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_UTIL_CONCATENATE_ITERATOR_HPP +#endif // BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP diff --git a/include/boost/geometry/util/flatten_iterator.hpp b/include/boost/geometry/iterators/flatten_iterator.hpp similarity index 87% rename from include/boost/geometry/util/flatten_iterator.hpp rename to include/boost/geometry/iterators/flatten_iterator.hpp index 9b44370bc..67847593d 100644 --- a/include/boost/geometry/util/flatten_iterator.hpp +++ b/include/boost/geometry/iterators/flatten_iterator.hpp @@ -7,21 +7,20 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_UTIL_FLATTEN_ITERATOR_HPP -#define BOOST_GEOMETRY_UTIL_FLATTEN_ITERATOR_HPP +#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP #include #include +#include #include +#include namespace boost { namespace geometry { -namespace util -{ - template < @@ -62,11 +61,6 @@ public: flatten_iterator(OuterIterator outer_it, OuterIterator outer_end) : m_outer_it(outer_it), m_outer_end(outer_end) { - if ( m_outer_it != m_outer_end ) - { - m_inner_it = AccessInnerBegin::apply(*m_outer_it); - // m_inner_it = AccessInnerBegin(*m_outer_it); - } advance_through_empty(); } @@ -140,7 +134,6 @@ private: { return AccessInnerBegin::apply(*outer_it) == AccessInnerEnd::apply(*outer_it); - // AccessInnerBegin(*outer_it) == AccessInnerEnd(*outer_it); } void advance_through_empty() @@ -153,7 +146,6 @@ private: if ( m_outer_it != m_outer_end ) { m_inner_it = AccessInnerBegin::apply(*m_outer_it); - // m_inner_it = AccessInnerBegin(*m_outer_it); } } @@ -161,7 +153,6 @@ private: { BOOST_ASSERT( m_outer_it != m_outer_end ); BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); - // BOOST_ASSERT( m_inner_it != AccessInnerEnd(*m_outer_it) ); return *m_inner_it; } @@ -198,11 +189,9 @@ private: { BOOST_ASSERT( m_outer_it != m_outer_end ); BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); - // BOOST_ASSERT( m_inner_it != AccessInnerEnd(*m_outer_it) ); ++m_inner_it; if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) ) - //if ( m_inner_it == AccessInnerEnd(*m_outer_it) ) { ++m_outer_it; advance_through_empty(); @@ -211,9 +200,8 @@ private: }; -} // namespace util - }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_UTIL_FLATTEN_INTERATOR_HPP + +#endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP From 8a8132e6c02ad69d7f5fa5440c11162777d568ab Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 23:23:51 +0200 Subject: [PATCH 16/31] [point_iterator] moved files to proper directories --- .../geometry/{core => iterators}/dispatch/point_iterator.hpp | 0 .../geometry/{core => iterators}/dispatch/point_iterator_type.hpp | 0 include/boost/geometry/{core => iterators}/point_iterator.hpp | 0 .../boost/geometry/{core => iterators}/point_iterator_type.hpp | 0 test/{core => iterators}/point_iterator.cpp | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename include/boost/geometry/{core => iterators}/dispatch/point_iterator.hpp (100%) rename include/boost/geometry/{core => iterators}/dispatch/point_iterator_type.hpp (100%) rename include/boost/geometry/{core => iterators}/point_iterator.hpp (100%) rename include/boost/geometry/{core => iterators}/point_iterator_type.hpp (100%) rename test/{core => iterators}/point_iterator.cpp (100%) diff --git a/include/boost/geometry/core/dispatch/point_iterator.hpp b/include/boost/geometry/iterators/dispatch/point_iterator.hpp similarity index 100% rename from include/boost/geometry/core/dispatch/point_iterator.hpp rename to include/boost/geometry/iterators/dispatch/point_iterator.hpp diff --git a/include/boost/geometry/core/dispatch/point_iterator_type.hpp b/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp similarity index 100% rename from include/boost/geometry/core/dispatch/point_iterator_type.hpp rename to include/boost/geometry/iterators/dispatch/point_iterator_type.hpp diff --git a/include/boost/geometry/core/point_iterator.hpp b/include/boost/geometry/iterators/point_iterator.hpp similarity index 100% rename from include/boost/geometry/core/point_iterator.hpp rename to include/boost/geometry/iterators/point_iterator.hpp diff --git a/include/boost/geometry/core/point_iterator_type.hpp b/include/boost/geometry/iterators/point_iterator_type.hpp similarity index 100% rename from include/boost/geometry/core/point_iterator_type.hpp rename to include/boost/geometry/iterators/point_iterator_type.hpp diff --git a/test/core/point_iterator.cpp b/test/iterators/point_iterator.cpp similarity index 100% rename from test/core/point_iterator.cpp rename to test/iterators/point_iterator.cpp From f5d48b379834d5093b483fc1f87b6c7dc8e75429 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 23:26:25 +0200 Subject: [PATCH 17/31] [point_iterator][concatenate_iterator] fix issues in copy constructor; --- .../iterators/concatenate_iterator.hpp | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/iterators/concatenate_iterator.hpp b/include/boost/geometry/iterators/concatenate_iterator.hpp index da2e78986..7321f1c81 100644 --- a/include/boost/geometry/iterators/concatenate_iterator.hpp +++ b/include/boost/geometry/iterators/concatenate_iterator.hpp @@ -20,7 +20,6 @@ namespace boost { namespace geometry - template struct concatenate_iterator : public boost::iterator_facade @@ -34,6 +33,19 @@ private: Iterator1 m_it1, m_end1; Iterator2 m_it2; + struct enabler {}; + + template + struct is_convertible + : boost::mpl::if_c + < + boost::is_convertible::value + && boost::is_convertible::value, + boost::true_type, + boost::false_type + >::type + {}; + public: typedef Iterator1 first_iterator_type; typedef Iterator2 second_iterator_type; @@ -52,9 +64,25 @@ public: : m_it1(end1), m_end1(end1), m_it2(end2) {} + template + concatenate_iterator + (concatenate_iterator const& other, + typename boost::enable_if + < + is_convertible, + enabler + >::type = enabler()) + : m_it1(other.m_it1), m_end1(other.m_end1), m_it2(other.m_it2) + {} + + + private: friend class boost::iterator_core_access; + template + friend class concatenate_iterator; + Value& dereference() const { if ( m_it1 == m_end1 ) From 5d27f4f30120f1b68a5fe2d98772a081a8ff1c35 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 23:27:23 +0200 Subject: [PATCH 18/31] [point_iterator][flatten_iterator] polish code a bit; fix problems with copy constructor; --- .../geometry/iterators/flatten_iterator.hpp | 79 ++++++++++--------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/include/boost/geometry/iterators/flatten_iterator.hpp b/include/boost/geometry/iterators/flatten_iterator.hpp index 67847593d..4a7c68a6d 100644 --- a/include/boost/geometry/iterators/flatten_iterator.hpp +++ b/include/boost/geometry/iterators/flatten_iterator.hpp @@ -71,26 +71,25 @@ public: template < - typename OtherOuterIterator, - typename OtherInnerIterator, - typename OtherValue + typename OtherOuterIterator, typename OtherInnerIterator, + typename OtherValue, + typename OtherAccessInnerBegin, typename OtherAccessInnerEnd > - explicit flatten_iterator(flatten_iterator - < - OtherOuterIterator, - OtherInnerIterator, - OtherValue, - AccessInnerBegin, - AccessInnerEnd - > const& other, - typename boost::enable_if - < - boost::is_convertible - < - OtherOuterIterator*, OuterIterator* - >, enabler - >::type = enabler() - ) + flatten_iterator(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + OtherAccessInnerBegin, + OtherAccessInnerEnd + > const& other, + typename boost::enable_if + < + boost::is_convertible + < + OtherValue*, Value* + >, enabler + >::type = enabler()) : m_outer_it(other.m_outer_it), m_outer_end(other.m_outer_end), m_inner_it(other.m_inner_it) @@ -100,15 +99,17 @@ public: < typename OtherOuterIterator, typename OtherInnerIterator, - typename OtherValue + typename OtherValue, + typename OtherAccessInnerBegin, + typename OtherAccessInnerEnd > flatten_iterator operator=(flatten_iterator < OtherOuterIterator, OtherInnerIterator, OtherValue, - AccessInnerBegin, - AccessInnerEnd + OtherAccessInnerBegin, + OtherAccessInnerEnd > const& other) { m_outer_it = other.m_outer_it; @@ -122,11 +123,11 @@ private: template < - typename OuterIterator1, - typename InnerIterator1, - typename Value1, - typename AccessInnerBegin1, - typename AccessInnerEnd1 + typename Outer, + typename Inner, + typename V, + typename InnerBegin, + typename InnerEnd > friend class flatten_iterator; @@ -136,7 +137,7 @@ private: AccessInnerBegin::apply(*outer_it) == AccessInnerEnd::apply(*outer_it); } - void advance_through_empty() + inline void advance_through_empty() { while ( m_outer_it != m_outer_end && empty(m_outer_it) ) { @@ -161,16 +162,18 @@ private: < typename OtherOuterIterator, typename OtherInnerIterator, - typename OtherValue + typename OtherValue, + typename OtherAccessInnerBegin, + typename OtherAccessInnerEnd > - bool equal(flatten_iterator - < - OtherOuterIterator, - OtherInnerIterator, - OtherValue, - AccessInnerBegin, - AccessInnerEnd - > const& other) const + inline bool equal(flatten_iterator + < + OtherOuterIterator, + OtherInnerIterator, + OtherValue, + OtherAccessInnerBegin, + OtherAccessInnerEnd + > const& other) const { if ( this->m_outer_it != other.m_outer_it ) { @@ -185,7 +188,7 @@ private: return this->m_inner_it == other.m_inner_it; } - void increment() + inline void increment() { BOOST_ASSERT( m_outer_it != m_outer_end ); BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) ); From 88264401a1e8b7a81d651c260ce5b18ec4f45428 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 23:28:07 +0200 Subject: [PATCH 19/31] [point_iterator] change namespace from core_dispatch to dispatch; fix macros of files due to new location; --- .../geometry/iterators/dispatch/point_iterator.hpp | 8 ++++---- .../iterators/dispatch/point_iterator_type.hpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/boost/geometry/iterators/dispatch/point_iterator.hpp b/include/boost/geometry/iterators/dispatch/point_iterator.hpp index 9d89ae737..c07f3a865 100644 --- a/include/boost/geometry/iterators/dispatch/point_iterator.hpp +++ b/include/boost/geometry/iterators/dispatch/point_iterator.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_HPP -#define BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_HPP +#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP #include #include @@ -18,7 +18,7 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DISPATCH -namespace core_dispatch +namespace dispatch { @@ -44,4 +44,4 @@ struct points_end }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_HPP +#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp b/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp index abf91dd9a..02c40acae 100644 --- a/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp +++ b/include/boost/geometry/iterators/dispatch/point_iterator_type.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_TYPE_HPP -#define BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_TYPE_HPP +#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP +#define BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP #include #include @@ -18,7 +18,7 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DISPATCH -namespace core_dispatch +namespace dispatch { template ::type> @@ -28,10 +28,10 @@ struct point_iterator_type -} // namespace core_dispatch +} // namespace dispatch #endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_CORE_DISPATCH_POINT_ITERATOR_TYPE_HPP +#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP From 25e746cd2a122f974b423c78ea40d13f2d072405 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 23:29:37 +0200 Subject: [PATCH 20/31] [point_iterator] move code to new namespace; remove comments; points_begin/point_end now return point_iterator class (suggested by Adam); --- .../geometry/iterators/point_iterator.hpp | 86 +++++++++++++------ 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/include/boost/geometry/iterators/point_iterator.hpp b/include/boost/geometry/iterators/point_iterator.hpp index 9d5d13742..192d75d57 100644 --- a/include/boost/geometry/iterators/point_iterator.hpp +++ b/include/boost/geometry/iterators/point_iterator.hpp @@ -7,11 +7,11 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_CORE_POINT_ITERATOR_HPP -#define BOOST_GEOMETRY_CORE_POINT_ITERATOR_HPP +#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP -#include -#include +#include +#include namespace boost { namespace geometry @@ -19,14 +19,13 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DISPATCH -namespace core_dispatch +namespace dispatch { // specializations for points_begin -// linestring template struct points_begin { @@ -38,7 +37,6 @@ struct points_begin }; -// ring template struct points_begin { @@ -50,7 +48,6 @@ struct points_begin }; -// polygon template struct points_begin { @@ -71,7 +68,6 @@ struct points_begin }; -// multi-point template struct points_begin { @@ -83,7 +79,6 @@ struct points_begin }; -// multi-linestring template struct points_begin { @@ -98,7 +93,6 @@ struct points_begin }; -// multi-polygon template struct points_begin { @@ -112,7 +106,7 @@ struct points_begin } }; -} // namespace core_dispatch +} // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -120,14 +114,13 @@ struct points_begin #ifndef DOXYGEN_NO_DISPATCH -namespace core_dispatch +namespace dispatch { // specializations for points_end -// linestring template struct points_end { @@ -139,7 +132,6 @@ struct points_end }; -// ring template struct points_end { @@ -151,7 +143,6 @@ struct points_end }; -// polygon template struct points_end { @@ -169,7 +160,6 @@ struct points_end }; -// multi-point template struct points_end { @@ -181,7 +171,6 @@ struct points_end }; -// multi-linestring template struct points_end { @@ -196,7 +185,6 @@ struct points_end }; -// multi-polygon template struct points_end { @@ -211,32 +199,76 @@ struct points_end }; -} // namespace core_dispatch +} // namespace dispatch #endif // DOXYGEN_NO_DISPATCH +// MK:: need to add doc here +template +class point_iterator + : public dispatch::point_iterator_type::type +{ +private: + typedef typename dispatch::point_iterator_type::type base; + + base* base_ptr() + { + return this; + } + + base const* base_ptr() const + { + return this; + } + + template + struct is_convertible + : boost::is_convertible + < + typename dispatch::point_iterator_type::type, + typename dispatch::point_iterator_type::type + > + {}; + + struct enabler {}; + + template friend class point_iterator; +public: + point_iterator() {} + + point_iterator(base const& base_it) : base(base_it) {} + + template + point_iterator(point_iterator const& other, + typename boost::enable_if + < + is_convertible, + enabler + >::type = enabler()) + + : base(*other.base_ptr()) + {} +}; // MK:: need to add doc here template -inline typename point_iterator_type::type +inline point_iterator points_begin(Geometry& geometry) { - return core_dispatch::points_begin::apply(geometry); + return dispatch::points_begin::apply(geometry); } // MK:: need to add doc here template -inline typename point_iterator_type::type +inline point_iterator points_end(Geometry& geometry) { - return core_dispatch::points_end::apply(geometry); + return dispatch::points_end::apply(geometry); } - - }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_CORE_POINT_ITERATOR_HPP +#endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP From c127c568716992e211f15b37a3d35619684bf11f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 23:32:05 +0200 Subject: [PATCH 21/31] [point_iterator] changes due to new location of files and namespaces used; --- .../iterators/point_iterator_type.hpp | 81 ++++++++----------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/include/boost/geometry/iterators/point_iterator_type.hpp b/include/boost/geometry/iterators/point_iterator_type.hpp index 51e409d66..4d50e42c4 100644 --- a/include/boost/geometry/iterators/point_iterator_type.hpp +++ b/include/boost/geometry/iterators/point_iterator_type.hpp @@ -7,18 +7,18 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_CORE_POINT_ITERATOR_TYPE_HPP -#define BOOST_GEOMETRY_CORE_POINT_ITERATOR_TYPE_HPP +#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP +#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP -#include -#include +#include +#include #include #include #include #include -#include -#include +#include +#include namespace boost { namespace geometry @@ -27,7 +27,7 @@ namespace boost { namespace geometry #ifndef DOXYGEN_NO_DETAIL -namespace core_detail +namespace detail_dispatch { @@ -74,7 +74,7 @@ struct point_iterator_inner_range_type -} // namespace core_detail +} // namespace detail_dispatch #endif // DOXYGEN_NO_DETAIL @@ -82,11 +82,10 @@ struct point_iterator_inner_range_type #ifndef DOXYGEN_NO_DISPATCH -namespace core_dispatch +namespace dispatch { -// linestring template struct point_iterator_type { @@ -94,7 +93,6 @@ struct point_iterator_type }; -// ring template struct point_iterator_type { @@ -102,43 +100,41 @@ struct point_iterator_type }; -// polygon template class point_iterator_type { private: - typedef typename core_detail::point_iterator_inner_range_type + typedef typename detail_dispatch::point_iterator_inner_range_type < Polygon >::type InnerRange; public: - typedef util::concatenate_iterator + typedef concatenate_iterator < typename boost::range_iterator::type, - util::flatten_iterator + flatten_iterator < typename boost::range_iterator < typename geometry::interior_type::type >::type, - typename core_dispatch::point_iterator_type + typename dispatch::point_iterator_type < InnerRange >::type, - typename core_detail::point_iterator_value_type + typename detail_dispatch::point_iterator_value_type < Polygon >::type, - core_dispatch::points_begin, - core_dispatch::points_end + dispatch::points_begin, + dispatch::points_end >, - typename core_detail::point_iterator_value_type::type + typename detail_dispatch::point_iterator_value_type::type > type; }; -// multi-point template struct point_iterator_type { @@ -146,49 +142,50 @@ struct point_iterator_type }; -// multi-linestring template class point_iterator_type { private: - typedef typename core_detail::point_iterator_inner_range_type + typedef typename detail_dispatch::point_iterator_inner_range_type < MultiLinestring >::type InnerRange; public: - typedef util::flatten_iterator + typedef flatten_iterator < typename boost::range_iterator::type, - typename core_dispatch::point_iterator_type::type, - typename core_detail::point_iterator_value_type + typename dispatch::point_iterator_type::type, + typename detail_dispatch::point_iterator_value_type < MultiLinestring >::type, - core_dispatch::points_begin, - core_dispatch::points_end + dispatch::points_begin, + dispatch::points_end > type; }; -// multi-polygon template class point_iterator_type { private: - typedef typename core_detail::point_iterator_inner_range_type + typedef typename detail_dispatch::point_iterator_inner_range_type < MultiPolygon >::type InnerRange; public: - typedef util::flatten_iterator + typedef flatten_iterator < typename boost::range_iterator::type, - typename core_dispatch::point_iterator_type::type, - typename core_detail::point_iterator_value_type::type, - core_dispatch::points_begin, - core_dispatch::points_end + typename dispatch::point_iterator_type::type, + typename detail_dispatch::point_iterator_value_type + < + MultiPolygon + >::type, + dispatch::points_begin, + dispatch::points_end > type; }; @@ -196,21 +193,11 @@ public: -} // namespace core_dispatch +} // namespace dispatch #endif // DOXYGEN_NO_DISPATCH - -// MK::need to add doc here -template -struct point_iterator_type -{ - typedef typename core_dispatch::point_iterator_type::type type; -}; - - - }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_CORE_POINT_ITERATOR_TYPE_HPP +#endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP From 8d09814c5090599456a6c67edaec27abec9f1ce3 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Thu, 27 Mar 2014 23:33:54 +0200 Subject: [PATCH 22/31] [point_iterator] adda bit more testing (dereference point iterator); now using boost::assign::tuple_list_of instead of multipoints for giving expected output; --- test/iterators/point_iterator.cpp | 271 ++++++++++++++++++++++-------- 1 file changed, 199 insertions(+), 72 deletions(-) diff --git a/test/iterators/point_iterator.cpp b/test/iterators/point_iterator.cpp index f06aac273..25e3a8421 100644 --- a/test/iterators/point_iterator.cpp +++ b/test/iterators/point_iterator.cpp @@ -17,6 +17,8 @@ #include +#include + #include #include #include @@ -27,27 +29,41 @@ #include #include -#include +#include +#include +#include namespace bg = ::boost::geometry; +namespace ba = ::boost::assign; typedef bg::model::point point_type; +typedef bg::model::point point_type_3d; typedef bg::model::linestring linestring_type; typedef bg::model::polygon polygon_type; //ccw, open // multi geometries typedef bg::model::multi_point multi_point_type; +typedef bg::model::multi_point multi_point_type_3d; typedef bg::model::multi_linestring multi_linestring_type; typedef bg::model::multi_polygon multi_polygon_type; +typedef boost::tuple tuple_point_type; +typedef boost::tuple tuple_point_type_3d; +typedef std::vector tuple_multi_point_type; +typedef std::vector tuple_multi_point_type_3d; + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type) +BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type_3d) + template Geometry from_wkt(std::string const& wkt) { - Geometry res; - boost::geometry::read_wkt(wkt, res); - return res; + Geometry geometry; + boost::geometry::read_wkt(wkt, geometry); + return geometry; } @@ -90,6 +106,58 @@ struct equals } }; + +struct test_assignment +{ + template + static inline void apply(Iterator it, ConstIterator cit, + Value const& value1, Value const& value2) + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "== before assignment ==" << std::endl; + std::cout << "value1: " << bg::wkt(value1) << std::endl; + std::cout << "value2: " << bg::wkt(value2) << std::endl; + std::cout << "*it : " << bg::wkt(*it) << std::endl; + std::cout << "*cit : " << bg::wkt(*cit) << std::endl; +#endif + + BOOST_CHECK( bg::equals(*it, value1) ); + BOOST_CHECK( !bg::equals(*it, value2) ); + BOOST_CHECK( bg::equals(*cit, value1) ); + BOOST_CHECK( !bg::equals(*cit, value2) ); + + *it = value2; + BOOST_CHECK( bg::equals(*it, value2) ); + BOOST_CHECK( !bg::equals(*it, value1) ); + BOOST_CHECK( bg::equals(*cit, value2) ); + BOOST_CHECK( !bg::equals(*cit, value1) ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "== after 1st assignment ==" << std::endl; + std::cout << "value1: " << bg::wkt(value1) << std::endl; + std::cout << "value2: " << bg::wkt(value2) << std::endl; + std::cout << "*it : " << bg::wkt(*it) << std::endl; + std::cout << "*cit : " << bg::wkt(*cit) << std::endl; +#endif + + *it = value1; + BOOST_CHECK( bg::equals(*it, value1) ); + BOOST_CHECK( !bg::equals(*it, value2) ); + BOOST_CHECK( bg::equals(*cit, value1) ); + BOOST_CHECK( !bg::equals(*cit, value2) ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "== after 2nd assignment ==" << std::endl; + std::cout << "value1: " << bg::wkt(value1) << std::endl; + std::cout << "value2: " << bg::wkt(value2) << std::endl; + std::cout << "*it : " << bg::wkt(*it) << std::endl; + std::cout << "*cit : " << bg::wkt(*cit) << std::endl; + std::cout << std::endl; +#endif + } +}; + + template struct test_point_iterator_of_geometry { @@ -98,29 +166,36 @@ struct test_point_iterator_of_geometry PointRange const& point_range, std::string const& header) { - typedef typename bg::point_iterator_type - < - G - >::type point_iterator_type; + typedef bg::point_iterator point_iterator; + typedef bg::point_iterator const_point_iterator; - point_iterator_type begin = bg::points_begin(geometry); - point_iterator_type end = bg::points_end(geometry); + point_iterator begin = bg::points_begin(geometry); + point_iterator end = bg::points_end(geometry); BOOST_CHECK( equals::apply(begin, end, - boost::begin(point_range), - boost::end(point_range)) + bg::points_begin(point_range), + bg::points_end(point_range)) ); #ifdef GEOMETRY_TEST_DEBUG std::cout << header << " geometry: " << bg::wkt(geometry) << std::endl; std::cout << "point range: ("; - for (point_iterator_type pit = begin; pit != end; ++pit) + for (point_iterator pit = begin; pit != end; ++pit) + { + std::cout << " " << bg::dsv(*pit); + } + std::cout << " )" << std::endl; + + typedef bg::point_iterator point_range_iterator; + + point_range_iterator rng_begin = bg::points_begin(point_range); + point_range_iterator rng_end = bg::points_end(point_range); + std::cout << "expected point range: ("; + for (point_range_iterator pit = rng_begin; pit != rng_end; ++pit) { std::cout << " " << bg::dsv(*pit); } std::cout << " )" << std::endl; - std::cout << "expected point range: " << bg::wkt(point_range) - << std::endl; #endif } @@ -129,14 +204,44 @@ struct test_point_iterator_of_geometry base_test(geometry, point_range, "non-const"); #ifdef GEOMETRY_TEST_DEBUG - std::cout << std::endl; + std::cout << std::endl; #endif base_test(geometry, point_range, "const"); #ifdef GEOMETRY_TEST_DEBUG - std::cout << std::endl << std::endl; + std::cout << std::endl << std::endl; #endif + + // testing construction of const and non-const iterator + typedef bg::point_iterator point_iterator; + typedef bg::point_iterator const_point_iterator; + + point_iterator begin = bg::points_begin(geometry); + point_iterator end = bg::points_end(geometry); + + const_point_iterator const_begin = bg::points_begin(geometry); + const_point_iterator const_end = bg::points_end(geometry); + + // testing assignment of non-const to const iterator + const_begin = begin; + const_end = end; + + // testing dereferencing/assignment + if ( begin != end ) + { + typedef typename bg::point_type::type point; + + point p = *begin; + point q = bg::make_zero(); + + test_assignment::apply(begin, const_begin, p, q); + test_assignment::apply(begin, const_begin, p, q); + + *begin = q; + test_assignment::apply(begin, const_begin, q, p); + *begin = p; + } } }; @@ -151,17 +256,17 @@ BOOST_AUTO_TEST_CASE( test_linestring_point_iterator ) std::cout << "*** LINESTRING ***" << std::endl; #endif - typedef multi_point_type MP; + typedef tuple_multi_point_type TMP; typedef linestring_type L; - typedef test_point_iterator_of_geometry tester; + typedef test_point_iterator_of_geometry tester; tester::apply(from_wkt("LINESTRING()"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt("LINESTRING(3 3,4 4,5 5)"), - from_wkt("MULTIPOINT(3 3,4 4,5 5)") + ba::tuple_list_of(3,3)(4,4)(5,5) ); #ifdef GEOMETRY_TEST_DEBUG @@ -180,27 +285,29 @@ BOOST_AUTO_TEST_CASE( test_polygon_point_iterator ) std::cout << "*** POLYGON ***" << std::endl; #endif - typedef multi_point_type MP; + typedef tuple_multi_point_type TMP; typedef polygon_type P; - typedef test_point_iterator_of_geometry tester; + typedef test_point_iterator_of_geometry tester; tester::apply(from_wkt

("POLYGON()"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt

("POLYGON(())"), - from_wkt("MULTIPOINT()") + TMP() ); - tester::apply(from_wkt

("POLYGON((3 3,4 4,5 5),(),(),(),\ - (6 6,7 7,8 8),(),(),(9 9),())"), - from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9)") + tester::apply(from_wkt

("POLYGON((1 1,9 1,9 9,1 9),(5 5,6 5,6 6,5 6))"), + ba::tuple_list_of(1,1)(9,1)(9,9)(1,9)(5,5)(6,5)(6,6)(5,6) ); - tester::apply(from_wkt

("POLYGON((),(3 3,4 4,5 5),(),(),\ - (6 6,7 7,8 8),(),(),(9 9),())"), - from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9)") + tester::apply(from_wkt

("POLYGON((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),())"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9) + ); + + tester::apply(from_wkt

("POLYGON((),(3 3,4 4,5 5),(),(),(6 6,7 7,8 8),(),(),(9 9),())"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9) ); #ifdef GEOMETRY_TEST_DEBUG @@ -219,16 +326,46 @@ BOOST_AUTO_TEST_CASE( test_multipoint_point_iterator ) std::cout << "*** MULTIPOINT ***" << std::endl; #endif + typedef tuple_multi_point_type TMP; typedef multi_point_type MP; - typedef test_point_iterator_of_geometry tester; + typedef test_point_iterator_of_geometry tester; tester::apply(from_wkt("MULTIPOINT()"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt("MULTIPOINT(3 3,4 4,5 5)"), - from_wkt("MULTIPOINT(3 3,4 4,5 5)") + ba::tuple_list_of(3,3)(4,4)(5,5) + ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl << std::endl; +#endif +} + + +//====================================================================== +//====================================================================== + + +BOOST_AUTO_TEST_CASE( test_multipoint_3d_point_iterator ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "*** MULTIPOINT 3D ***" << std::endl; +#endif + + typedef tuple_multi_point_type_3d TMP; + typedef multi_point_type_3d MP; + + typedef test_point_iterator_of_geometry tester; + + tester::apply(from_wkt("MULTIPOINT()"), + TMP() + ); + + tester::apply(from_wkt("MULTIPOINT(3 3 3,4 4 4,5 5 5)"), + ba::tuple_list_of(3,3,3)(4,4,4)(5,5,5) ); #ifdef GEOMETRY_TEST_DEBUG @@ -247,27 +384,29 @@ BOOST_AUTO_TEST_CASE( test_multilinestring_point_iterator ) std::cout << "*** MULTILINESTRING ***" << std::endl; #endif - typedef multi_point_type MP; - typedef linestring_type L; + typedef tuple_multi_point_type TMP; typedef multi_linestring_type ML; - typedef test_point_iterator_of_geometry tester; + typedef test_point_iterator_of_geometry tester; tester::apply(from_wkt("MULTILINESTRING()"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt("MULTILINESTRING(())"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt("MULTILINESTRING((),(),())"), - from_wkt("MULTIPOINT()") + TMP() ); - tester::apply(from_wkt("MULTILINESTRING((),(),(0 0,1 1,2 2),(),(),\ - (3 3,4 4,5 5),(),(6 6),(),(),())"), - from_wkt("MULTIPOINT(0 0,1 1,2 2,3 3,4 4,5 5,6 6)") + tester::apply(from_wkt("MULTILINESTRING((1 1,2 2,3 3),(3 3,4 4,5 5),(6 6))"), + ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6) + ); + + tester::apply(from_wkt("MULTILINESTRING((),(),(1 1,2 2,3 3),(),(),(3 3,4 4,5 5),(),(6 6),(),(),())"), + ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6) ); #ifdef GEOMETRY_TEST_DEBUG @@ -286,55 +425,43 @@ BOOST_AUTO_TEST_CASE( test_multipolygon_point_iterator ) std::cout << "*** MULTIPOLYGON ***" << std::endl; #endif - typedef multi_point_type MP; + typedef tuple_multi_point_type TMP; typedef multi_polygon_type MPL; - typedef test_point_iterator_of_geometry tester; + typedef test_point_iterator_of_geometry tester; tester::apply(from_wkt("MULTIPOLYGON()"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt("MULTIPOLYGON( () )"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt("MULTIPOLYGON( (()) )"), - from_wkt("MULTIPOINT()") + TMP() ); tester::apply(from_wkt("MULTIPOLYGON( ((),()) )"), - from_wkt("MULTIPOINT()") + TMP() ); - tester::apply(from_wkt("MULTIPOLYGON(\ - ((3 3,4 4,5 5),(),(),(),\ - (6 6,7 7,8 8),(),(),(9 9),())\ - \ - ((),(1 1,2 2,10 10),(),(),(),\ - (11 11,12 12),(),(),(13 13),())\ - )"), - from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9,\ - 1 1,2 2,10 10,11 11,12 12,13 13)") + tester::apply(from_wkt("MULTIPOLYGON(((3 3,4 4,5 5),(6 6,7 7,8 8),(9 9)),((1 1,2 2,10 10),(11 11,12 12)))"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\ + (1,1)(2,2)(10,10)(11,11)(12,12) ); - tester::apply(from_wkt("MULTIPOLYGON(\ - (),\ - \ - ((3 3,4 4,5 5),(),(),(),\ - (6 6,7 7,8 8),(),(),(9 9),())\ - \ - ((),(1 1,2 2,10 10),(),(),(),\ - (11 11,12 12),(),(),(13 13),())\ - \ - ((),(),()),\ - )"), - from_wkt("MULTIPOINT(3 3,4 4,5 5,6 6,7 7,8 8,9 9,\ - 1 1,2 2,10 10,11 11,12 12,13 13)") + tester::apply(from_wkt("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()))"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\ + (1,1)(2,2)(10,10)(11,11)(12,12)(13,13) + ); + + tester::apply(from_wkt("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()),((),(),()))"), + ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\ + (1,1)(2,2)(10,10)(11,11)(12,12)(13,13) ); #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; #endif } - From 5e96c27c8492a73b24a6bc039ec06b85b9a45743 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 28 Mar 2014 00:11:16 +0200 Subject: [PATCH 23/31] [point_iterator] make private the constructor of point_iterator that takes the base class as argument; --- include/boost/geometry/iterators/point_iterator.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/iterators/point_iterator.hpp b/include/boost/geometry/iterators/point_iterator.hpp index 192d75d57..50613fafc 100644 --- a/include/boost/geometry/iterators/point_iterator.hpp +++ b/include/boost/geometry/iterators/point_iterator.hpp @@ -233,11 +233,14 @@ private: struct enabler {}; template friend class point_iterator; -public: - point_iterator() {} + template friend inline point_iterator points_begin(G&); + template friend inline point_iterator points_end(G&); point_iterator(base const& base_it) : base(base_it) {} +public: + point_iterator() {} + template point_iterator(point_iterator const& other, typename boost::enable_if From e1f39cd0657f192fa1fa37f85ecd5494afdb871c Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 28 Mar 2014 00:30:50 +0200 Subject: [PATCH 24/31] [point_iterator] minor and stylistic changes; in concatenate_iterator use enable_if_c instead of enable_if (shorter code); --- .../iterators/concatenate_iterator.hpp | 18 +++++------------- .../geometry/iterators/flatten_iterator.hpp | 6 ++---- .../geometry/iterators/point_iterator.hpp | 1 + 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/include/boost/geometry/iterators/concatenate_iterator.hpp b/include/boost/geometry/iterators/concatenate_iterator.hpp index 7321f1c81..32a8b2332 100644 --- a/include/boost/geometry/iterators/concatenate_iterator.hpp +++ b/include/boost/geometry/iterators/concatenate_iterator.hpp @@ -10,6 +10,8 @@ #ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP #define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP +#include +#include #include #include #include @@ -35,17 +37,6 @@ private: struct enabler {}; - template - struct is_convertible - : boost::mpl::if_c - < - boost::is_convertible::value - && boost::is_convertible::value, - boost::true_type, - boost::false_type - >::type - {}; - public: typedef Iterator1 first_iterator_type; typedef Iterator2 second_iterator_type; @@ -67,9 +58,10 @@ public: template concatenate_iterator (concatenate_iterator const& other, - typename boost::enable_if + typename boost::enable_if_c < - is_convertible, + boost::is_convertible::value + && boost::is_convertible::value, enabler >::type = enabler()) : m_it1(other.m_it1), m_end1(other.m_end1), m_it2(other.m_it2) diff --git a/include/boost/geometry/iterators/flatten_iterator.hpp b/include/boost/geometry/iterators/flatten_iterator.hpp index 4a7c68a6d..9e3983cc4 100644 --- a/include/boost/geometry/iterators/flatten_iterator.hpp +++ b/include/boost/geometry/iterators/flatten_iterator.hpp @@ -85,10 +85,8 @@ public: > const& other, typename boost::enable_if < - boost::is_convertible - < - OtherValue*, Value* - >, enabler + boost::is_convertible, + enabler >::type = enabler()) : m_outer_it(other.m_outer_it), m_outer_end(other.m_outer_end), diff --git a/include/boost/geometry/iterators/point_iterator.hpp b/include/boost/geometry/iterators/point_iterator.hpp index 50613fafc..07a70c4e0 100644 --- a/include/boost/geometry/iterators/point_iterator.hpp +++ b/include/boost/geometry/iterators/point_iterator.hpp @@ -10,6 +10,7 @@ #ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP #define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP +#include #include #include From 38682d9b41d479a5f516ff2889967258e8cea4b2 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 28 Mar 2014 00:45:06 +0200 Subject: [PATCH 25/31] [point_iterator] remove function call that is not meaningful; --- test/iterators/point_iterator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/iterators/point_iterator.cpp b/test/iterators/point_iterator.cpp index 25e3a8421..c144bf7dc 100644 --- a/test/iterators/point_iterator.cpp +++ b/test/iterators/point_iterator.cpp @@ -235,11 +235,11 @@ struct test_point_iterator_of_geometry point p = *begin; point q = bg::make_zero(); - test_assignment::apply(begin, const_begin, p, q); test_assignment::apply(begin, const_begin, p, q); *begin = q; test_assignment::apply(begin, const_begin, q, p); + *begin = p; } } From d5d4b08a0ce98621949adc82ac34f524bd87a7a3 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 28 Mar 2014 11:57:05 +0200 Subject: [PATCH 26/31] [point_iterator] minor stylistic changes; --- test/iterators/concatenate_iterator.cpp | 261 ++++++++++++++++++++++++ test/iterators/point_iterator.cpp | 9 +- 2 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 test/iterators/concatenate_iterator.cpp diff --git a/test/iterators/concatenate_iterator.cpp b/test/iterators/concatenate_iterator.cpp new file mode 100644 index 000000000..9d0d3335a --- /dev/null +++ b/test/iterators/concatenate_iterator.cpp @@ -0,0 +1,261 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014, 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_TEST_MODULE +#define BOOST_TEST_MODULE test_concatenate_iterator +#endif + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace boost::assign; + +template +std::ostream& print_container(std::ostream& os, + Iterator begin, Iterator end, + std::string const& header) +{ + std::cout << header; + for (Iterator it = begin; it != end; ++it) + { + os << " " << *it; + } + return os; +} + + +template +struct is_odd +{ + inline bool operator()(T const& t) const + { + return t % 2 != 0; + } +}; + +struct test_concat_iterator +{ + template + static inline void apply(Container1& c1, Container2& c2, + std::string const& case_id) + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "case id: " << case_id << std::endl; +#endif + + typedef boost::geometry::concatenate_iterator + < + typename Container1::const_iterator, + typename Container2::const_iterator, + typename Container1::value_type const + > const_concat_iterator; + + typedef boost::geometry::concatenate_iterator + < + typename Container1::iterator, + typename Container2::iterator, + typename Container1::value_type + > concat_iterator; + + + concat_iterator begin(c1.begin(), c1.end(), c2.begin()); + concat_iterator end(c1.end(), c2.end()); + const_concat_iterator const_begin(begin); + const_concat_iterator const_end(end); + const_begin = begin; + const_end = end; + + std::size_t size(0); + for (const_concat_iterator it = const_begin; it != const_end; ++it) + { + ++size; + } + BOOST_CHECK( c1.size() + c2.size() == size ); + + size = 0; + for (concat_iterator it = begin; it != end; ++it) + { + ++size; + } + BOOST_CHECK( c1.size() + c2.size() == size ); + +#ifdef GEOMETRY_TEST_DEBUG + print_container(std::cout, c1.begin(), c1.end(), "first :") + << std::endl; + + print_container(std::cout, c2.begin(), c2.end(), "second :") + << std::endl; + + print_container(std::cout, begin, end, "combined:") + << std::endl; + + if ( begin != end ) + { + std::cout << "min element: " + << *std::min_element(begin, end) + << std::endl; + std::cout << "max element: " + << *std::max_element(const_begin, const_end) + << std::endl; + } +#endif + + { + typename Container1::const_iterator it1 = c1.begin(); + typename Container2::const_iterator it2 = c2.begin(); + for (const_concat_iterator it = const_begin; it != const_end; ++it) + { + if ( it1 != c1.end() ) + { + BOOST_CHECK( *it == *it1 ); + ++it1; + } + else + { + BOOST_CHECK( *it == *it2 ); + ++it2; + } + } + } + + typedef typename std::iterator_traits + < + concat_iterator + >::value_type value_type; + + if ( c1.size() != 0 ) + { + concat_iterator it_max = std::max_element(begin, end); + const_concat_iterator const_it_max = + std::max_element(const_begin, const_end); + + BOOST_CHECK( it_max == const_it_max ); + + value_type old_value = *const_begin; + value_type new_value = *it_max + 1; + + *begin = *it_max + 1; + BOOST_CHECK( *c1.begin() == new_value ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "modified element of 1st container:" << std::endl; + print_container(std::cout, c1.begin(), c1.end(), "first :") + << std::endl; + print_container(std::cout, begin, end, "combined:") + << std::endl; +#endif + + *begin = old_value; + BOOST_CHECK( *c1.begin() == old_value ); + } + + if ( c2.size() != 0 ) + { + concat_iterator begin2 = begin; + std::size_t counter(0); + while ( counter != c1.size() ) + { + ++counter; + begin2++; + } + + concat_iterator it_max = std::max_element(begin, end); + const_concat_iterator const_it_max = + std::max_element(const_begin, const_end); + + BOOST_CHECK( it_max == const_it_max ); + + value_type old_value = *begin2; + value_type new_value = *it_max + 1; + + *begin2 = *it_max + 1; + BOOST_CHECK( *c2.begin() == new_value ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "modified element of 2nd container:" << std::endl; + print_container(std::cout, c2.begin(), c2.end(), "second :") + << std::endl; + print_container(std::cout, begin, end, "combined:") + << std::endl; +#endif + + *begin2 = old_value; + BOOST_CHECK( *c2.begin() == old_value ); + } + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "odd elements removed:" << std::endl; + print_container(std::cout, begin, end, "before:") + << std::endl; +#endif + concat_iterator new_end = + std::remove_if(begin, end, is_odd()); + + for (const_concat_iterator it = const_begin; it != new_end; ++it) + { + BOOST_CHECK( !is_odd()(*it) ); + } + +#ifdef GEOMETRY_TEST_DEBUG + print_container(std::cout, begin, new_end, "after :") + << std::endl; +#endif + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "====================" << std::endl << std::endl; +#endif + } +}; + + +BOOST_AUTO_TEST_CASE( test_concatenate_iterator ) +{ + { + std::vector v; + std::list l; + + test_concat_iterator::apply(v, l, "empty_both"); + } + { + std::vector v; + std::list l; + l += 10,11,12,13,14,15,16,17,18,19,20; + + test_concat_iterator::apply(v, l, "empty_first"); + } + { + std::vector v; + v += 0,1,2,3,4,5,6; + std::list l; + + test_concat_iterator::apply(v, l, "empty_second"); + } + { + std::vector v; + v += 0,1,2,3,4,5,6; + std::list l; + l += 10,11,12,13,14,15,16,17,18,19,20; + + test_concat_iterator::apply(l, v, "non_empty"); + } +} diff --git a/test/iterators/point_iterator.cpp b/test/iterators/point_iterator.cpp index c144bf7dc..13d77fdf8 100644 --- a/test/iterators/point_iterator.cpp +++ b/test/iterators/point_iterator.cpp @@ -20,8 +20,12 @@ #include #include -#include +#include #include +#include + +#include + #include #include #include @@ -29,9 +33,6 @@ #include #include -#include -#include - #include namespace bg = ::boost::geometry; From 5da4191c59ee99e7f466312c05aa8f2838c4f573 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 28 Mar 2014 11:57:35 +0200 Subject: [PATCH 27/31] [point_iterator][concatenate_iterator] add separate unit test; --- test/iterators/concatenate_iterator.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/iterators/concatenate_iterator.cpp b/test/iterators/concatenate_iterator.cpp index 9d0d3335a..941cf612d 100644 --- a/test/iterators/concatenate_iterator.cpp +++ b/test/iterators/concatenate_iterator.cpp @@ -59,19 +59,20 @@ struct test_concat_iterator #ifdef GEOMETRY_TEST_DEBUG std::cout << "case id: " << case_id << std::endl; #endif + typedef typename Container1::const_iterator const_iterator1; + typedef typename Container2::const_iterator const_iterator2; + typedef typename Container1::iterator iterator1; + typedef typename Container2::iterator iterator2; typedef boost::geometry::concatenate_iterator < - typename Container1::const_iterator, - typename Container2::const_iterator, + const_iterator1, const_iterator2, typename Container1::value_type const > const_concat_iterator; typedef boost::geometry::concatenate_iterator < - typename Container1::iterator, - typename Container2::iterator, - typename Container1::value_type + iterator1, iterator2, typename Container1::value_type > concat_iterator; @@ -99,10 +100,8 @@ struct test_concat_iterator #ifdef GEOMETRY_TEST_DEBUG print_container(std::cout, c1.begin(), c1.end(), "first :") << std::endl; - print_container(std::cout, c2.begin(), c2.end(), "second :") << std::endl; - print_container(std::cout, begin, end, "combined:") << std::endl; @@ -118,8 +117,8 @@ struct test_concat_iterator #endif { - typename Container1::const_iterator it1 = c1.begin(); - typename Container2::const_iterator it2 = c2.begin(); + const_iterator1 it1 = c1.begin(); + const_iterator2 it2 = c2.begin(); for (const_concat_iterator it = const_begin; it != const_end; ++it) { if ( it1 != c1.end() ) From b0221bcda1ca5862c2d49a50f66f8ba5c1d299cd Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sat, 29 Mar 2014 14:08:11 +0100 Subject: [PATCH 28/31] [get_turns] fix invalid equal<> use (convert() for uninitialized Point) in get_turn_info_for_endpoints and get_turn_info_linear_areal --- .../overlay/get_turn_info_for_endpoint.hpp | 78 ++++++++++++++++--- .../detail/overlay/get_turn_info_la.hpp | 22 ++++-- 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index 78edbefb6..d960dd0aa 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -412,14 +412,13 @@ struct get_turn_info_for_endpoint geometry::convert(i2, i2_conv); side_calculator side_calc(i2_conv, i1, j1, i2, j2, k2); - TurnInfo tp = tp_model; - equal::apply(i2_conv, i1, j1, i2, j2, k2, - tp, result.template get<0>(), result.template get<1>(), side_calc); + std::pair + operations = operations_of_equal(side_calc); // TODO: must the above be calculated? // wouldn't it be enough to check if segments are collinear? - if ( tp.both(operation_continue) ) + if ( operations_both(operations, operation_continue) ) { // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE! bool opposite = result.template get<1>().opposite; @@ -429,7 +428,7 @@ struct get_turn_info_for_endpoint } else { - BOOST_ASSERT(tp.combination(operation_intersection, operation_union)); + BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union)); //op1 = operation_union; //op2 = operation_union; } @@ -460,14 +459,13 @@ struct get_turn_info_for_endpoint side_calculator side_calc(i2_conv, j1, i1, i2, j2, k2); - TurnInfo tp = tp_model; - equal::apply(i2_conv, j1, i1, i2, j2, k2, - tp, result.template get<0>(), result.template get<1>(), side_calc); + std::pair + operations = operations_of_equal(side_calc); // TODO: must the above be calculated? // wouldn't it be enough to check if segments are collinear? - if ( tp.both(operation_continue) ) + if ( operations_both(operations, operation_continue) ) { // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE! bool second_going_out = result.template get<0>().count > 1; @@ -477,7 +475,7 @@ struct get_turn_info_for_endpoint } else { - BOOST_ASSERT(tp.combination(operation_intersection, operation_union)); + BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union)); //op1 = operation_blocked; //op2 = operation_union; } @@ -552,6 +550,66 @@ struct get_turn_info_for_endpoint AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); *out++ = tp; } + + template + static inline std::pair operations_of_equal(SidePolicy const& side) + { + int const side_pk_q2 = side.pk_wrt_q2(); + int const side_pk_p = side.pk_wrt_p1(); + int const side_qk_p = side.qk_wrt_p1(); + + // If pk is collinear with qj-qk, they continue collinearly. + // This can be on either side of p1 (== q1), or collinear + // The second condition checks if they do not continue + // oppositely + if ( side_pk_q2 == 0 && side_pk_p == side_qk_p ) + { + return std::make_pair(operation_continue, operation_continue); + } + + // If they turn to same side (not opposite sides) + if ( ! base_turn_handler::opposite(side_pk_p, side_qk_p) ) + { + int const side_pk_q2 = side.pk_wrt_q2(); + // If pk is left of q2 or collinear: p: union, q: intersection + if ( side_pk_q2 != -1 ) + { + return std::make_pair(operation_union, operation_intersection); + } + else + { + return std::make_pair(operation_intersection, operation_union); + } + } + else + { + // They turn opposite sides. If p turns left (or collinear), + // p: union, q: intersection + if ( side_pk_p != -1 ) + { + return std::make_pair(operation_union, operation_intersection); + } + else + { + return std::make_pair(operation_intersection, operation_union); + } + } + } + + static inline bool operations_both( + std::pair const& operations, + operation_type const op) + { + return operations.first == op && operations.second == op; + } + + static inline bool operations_combination( + std::pair const& operations, + operation_type const op1, operation_type const op2) + { + return ( operations.first == op1 && operations.second == op2 ) + || ( operations.first == op2 && operations.second == op1 ); + } }; }} // namespace detail::overlay diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 0bbd1e57d..73b811aea 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -458,8 +458,11 @@ struct get_turn_info_linear_areal { side_calculator side_calc(qi_conv, pi, pj, qi, qj, qk); - equal::apply(qi_conv, pi, pj, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>(), side_calc); + std::pair + operations = get_info_e::operations_of_equal(side_calc); + + tp.operations[0].operation = operations.first; + tp.operations[1].operation = operations.second; replaced_method = method_touch; } @@ -471,9 +474,11 @@ struct get_turn_info_linear_areal side_calculator side_calc(qi_conv, pi, pj, qi, pi_conv, qj); - // Collinear, but similar thus handled as equal - equal::apply(qi_conv, pi, pj, qi, pi_conv, qj, - tp, result.template get<0>(), result.template get<1>(), side_calc); + std::pair + operations = get_info_e::operations_of_equal(side_calc); + + tp.operations[0].operation = operations.first; + tp.operations[1].operation = operations.second; } replacer_of_method_and_operations_ec replacer(replaced_method); @@ -519,8 +524,11 @@ struct get_turn_info_linear_areal geometry::convert(qi, qi_conv); side_calculator side_calc(qi_conv, pj, pi, qi, qj, qk); - equal::apply(qi_conv, pj, pi, qi, qj, qk, - tp, result.template get<0>(), result.template get<1>(), side_calc); + std::pair + operations = get_info_e::operations_of_equal(side_calc); + + tp.operations[0].operation = operations.first; + tp.operations[1].operation = operations.second; replacer_of_method_and_operations_ec replacer(method_none); replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation); From fc1a2545a511f499c2da2c302367986af20ebb5a Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sat, 29 Mar 2014 14:41:51 +0100 Subject: [PATCH 29/31] [get_turns] Fix test for L/L and L/A - missing functions in expected_pusher range --- test/algorithms/overlay/test_get_turns.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/algorithms/overlay/test_get_turns.hpp b/test/algorithms/overlay/test_get_turns.hpp index 4ca5198d3..41ee8400c 100644 --- a/test/algorithms/overlay/test_get_turns.hpp +++ b/test/algorithms/overlay/test_get_turns.hpp @@ -152,8 +152,8 @@ struct expected_pusher typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; - //iterator begin() { return vec.begin(); } - //iterator end() { return vec.end(); } + iterator begin() { return vec.begin(); } + iterator end() { return vec.end(); } const_iterator begin() const { return vec.begin(); } const_iterator end() const { return vec.end(); } From 861e094b7cf7fb8680307013c749c0d6d63448c1 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Mon, 31 Mar 2014 09:33:23 +0300 Subject: [PATCH 30/31] [point_iterator] add separate unit test for flatten iterator; updated Jamfile to run the unit tests for point/concatenate/flatten iterator; --- test/iterators/Jamfile.v2 | 14 +- test/iterators/flatten_iterator.cpp | 430 ++++++++++++++++++++++++++++ 2 files changed, 441 insertions(+), 3 deletions(-) create mode 100644 test/iterators/flatten_iterator.cpp diff --git a/test/iterators/Jamfile.v2 b/test/iterators/Jamfile.v2 index 72091f21f..40273145d 100644 --- a/test/iterators/Jamfile.v2 +++ b/test/iterators/Jamfile.v2 @@ -1,8 +1,13 @@ # Boost.Geometry (aka GGL, Generic Geometry Library) # -# 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-2014 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +# Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +# +# This file was modified by Oracle on 2014. +# Modifications copyright (c) 2014, Oracle and/or its affiliates. +# +# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle # # Use, modification and distribution is subject to the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -12,4 +17,7 @@ test-suite boost-geometry-iterators : [ run closing_iterator.cpp ] [ run ever_circling_iterator.cpp ] + [ run point_iterator.cpp ] + [ run concatenate_iterator.cpp ] + [ run flatten_iterator.cpp ] ; diff --git a/test/iterators/flatten_iterator.cpp b/test/iterators/flatten_iterator.cpp new file mode 100644 index 000000000..98e8643e2 --- /dev/null +++ b/test/iterators/flatten_iterator.cpp @@ -0,0 +1,430 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014, 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_TEST_MODULE +#define BOOST_TEST_MODULE test_flatten_iterator +#endif + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace boost::assign; + +template +std::ostream& print_container(std::ostream& os, + Iterator begin, Iterator end, + std::string const& header) +{ + std::cout << header; + for (Iterator it = begin; it != end; ++it) + { + os << " " << *it; + } + return os; +} + + +template +std::ostream& print_nested_container(std::ostream& os, + Iterator begin, Iterator end, + std::string const& header) +{ + std::cout << header; + for (Iterator outer = begin; outer != end; ++outer) + { + os << " ("; + for (BOOST_AUTO_TPL(inner, outer->begin()); + inner != outer->end(); ++inner) + { + if ( inner != outer->begin() ) + { + os << " "; + } + os << *inner; + } + os << ") "; + } + return os; +} + + +template +struct is_odd +{ + inline bool operator()(T const& t) const + { + return t % 2 != 0; + } +}; + + +template +struct is_even +{ + inline bool operator()(T const& t) const + { + return !is_odd()(t); + } +}; + + + +template +struct access_begin +{ + typedef typename boost::mpl::if_ + < + typename boost::is_const::type, + typename InnerContainer::const_iterator, + typename InnerContainer::iterator + >::type return_type; + + static inline return_type apply(InnerContainer& inner) + { + return inner.begin(); + } +}; + + +template +struct access_end +{ + typedef typename boost::mpl::if_ + < + typename boost::is_const::type, + typename InnerContainer::const_iterator, + typename InnerContainer::iterator + >::type return_type; + + static inline return_type apply(InnerContainer& inner) + { + return inner.end(); + } +}; + + +template +std::size_t number_of_elements(NestedContainer const& c) +{ + std::size_t num_elements(0); + for (typename NestedContainer::const_iterator outer = c.begin(); + outer != c.end(); ++outer) + { + num_elements += outer->size(); + } + return num_elements; +} + + +struct test_flatten_iterator +{ + template + static inline void apply(NestedContainer& c, + std::string const& case_id, + std::string const& container_id) + { +#ifdef GEOMETRY_TEST_DEBUG + std::stringstream sstream; + sstream << case_id << " " << "[" << container_id << "]"; + + std::cout << "case id: " << sstream.str() << std::endl; +#endif + typedef typename NestedContainer::const_iterator const_outer_iterator; + typedef typename NestedContainer::iterator outer_iterator; + typedef typename NestedContainer::value_type inner_container; + + typedef typename inner_container::const_iterator const_inner_iterator; + typedef typename inner_container::iterator inner_iterator; + + typedef boost::geometry::flatten_iterator + < + const_outer_iterator, + const_inner_iterator, + typename inner_container::value_type const, + access_begin, + access_end + > const_flatten_iterator; + + typedef boost::geometry::flatten_iterator + < + outer_iterator, + inner_iterator, + typename inner_container::value_type, + access_begin, + access_end + > flatten_iterator; + + + flatten_iterator begin(c.begin(), c.end()); + flatten_iterator end(c.end()); + const_flatten_iterator const_begin(begin); + const_flatten_iterator const_end(end); + const_begin = begin; + const_end = end; + + std::size_t size(0); + for (const_flatten_iterator it = const_begin; it != const_end; ++it) + { + ++size; + } + BOOST_CHECK( number_of_elements(c) == size ); + + size = 0; + for (flatten_iterator it = begin; it != end; ++it) + { + ++size; + } + BOOST_CHECK( number_of_elements(c) == size ); + +#ifdef GEOMETRY_TEST_DEBUG + print_nested_container(std::cout, c.begin(), c.end(), "nested :") + << std::endl; + print_container(std::cout, begin, end, "flattened :") + << std::endl; + + if ( begin != end ) + { + std::cout << "min element: " + << *std::min_element(begin, end) + << std::endl; + std::cout << "max element: " + << *std::max_element(const_begin, const_end) + << std::endl; + } +#endif + + { + const_flatten_iterator it = begin; + const_outer_iterator outer_begin = c.begin(); + const_outer_iterator outer_end = c.end(); + for (const_outer_iterator outer = outer_begin; + outer != outer_end; ++outer) + { + const_inner_iterator inner_begin = outer->begin(); + const_inner_iterator inner_end = outer->end(); + for (const_inner_iterator inner = inner_begin; + inner != inner_end; ++inner, it++) + // it++, instead of ++it, on purpose here + { + BOOST_CHECK( *it == *inner ); + } + } + } + + typedef typename std::iterator_traits + < + flatten_iterator + >::value_type value_type; + + if ( begin != end ) + { + flatten_iterator it_max = std::max_element(begin, end); + const_flatten_iterator const_it_max = + std::max_element(const_begin, const_end); + + BOOST_CHECK( it_max == const_it_max ); + BOOST_CHECK( *it_max == *const_it_max ); + + value_type old_value = *const_begin; + value_type new_value = *it_max + 1; + + *begin = *it_max + 1; + const_outer_iterator outer = c.begin(); + while ( outer->begin() == outer->end() ) + { + ++outer; + } + const_inner_iterator inner = outer->begin(); + + BOOST_CHECK( *inner == new_value ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "modified 1st element of 1st non-empty " + << "inner container:" << std::endl; + print_nested_container(std::cout, c.begin(), c.end(), "nested :") + << std::endl; + print_container(std::cout, begin, end, "flattened:") + << std::endl; +#endif + + *begin = old_value; + BOOST_CHECK( *inner == old_value ); + } + + + if ( begin != end ) + { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "odd elements removed:" << std::endl; + print_nested_container(std::cout, c.begin(), c.end(), + "nested before:") + << std::endl; + print_container(std::cout, begin, end, + "flattended before:") + << std::endl; +#endif + typename std::iterator_traits::difference_type + num_even = std::count_if(begin, end, is_even()); + + flatten_iterator new_end = + std::remove_if(begin, end, is_odd()); + + std::size_t new_size(0); + for (const_flatten_iterator it = const_begin; it != new_end; ++it) + { + ++new_size; + BOOST_CHECK( !is_odd()(*it) ); + } + BOOST_CHECK( new_size == static_cast(num_even) ); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + print_nested_container(std::cout, c.begin(), c.end(), + "nested after (all elements) :") + << std::endl; + print_container(std::cout, begin, new_end, "flattened after :") + << std::endl; +#endif + } + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "====================" << std::endl << std::endl; +#endif + } +}; + + + +// the actual test cases -- START +template +struct test_case_per_container; + +template<> +struct test_case_per_container<0> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + test_flatten_iterator::apply(c, case_id, container_id); + } +}; + +template<> +struct test_case_per_container<1> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + for (int i = 0; i < 5; ++i) + { + c += typename NestedContainer::value_type(); + } + test_flatten_iterator::apply(c, case_id, container_id); + } +}; + +template<> +struct test_case_per_container<2> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + typename NestedContainer::value_type ic[4]; + + ic[0] += 5,4,3,2,1; + ic[1] += 6,7,8; + ic[2] += 9; + ic[3] += 9,8,7,6,5; + c += ic[0],ic[1],ic[2],ic[3]; + + test_flatten_iterator::apply(c, case_id, container_id); + } +}; + +template<> +struct test_case_per_container<3> +{ + template + static inline void apply(std::string const& case_id, + std::string const& container_id) + { + NestedContainer c; + typename NestedContainer::value_type ic[20]; + + ic[2] += 5,4,3,2,1; + ic[3] += 6,7,8; + ic[8] += 9; + ic[9] += 9,8,7,6,5; + ic[14] += 4,3,2,1; + for (std::size_t i = 0; i < 20; ++i) + { + c += ic[i]; + } + + test_flatten_iterator::apply(c, case_id, container_id); + } +}; +// the actual test cases -- END + + + +template +inline void test_case_all_containers(std::string const& case_id) +{ + typedef typename std::vector > VV; + typedef typename std::vector > VL; + typedef typename std::list > LV; + typedef typename std::list > LL; + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; +#endif + test_case_per_container::template apply(case_id, "VV"); + test_case_per_container::template apply(case_id, "VL"); + test_case_per_container::template apply(case_id, "LV"); + test_case_per_container::template apply(case_id, "LL"); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "********************************************************" + << std::endl << std::endl; +#endif +} + + + +BOOST_AUTO_TEST_CASE( test_flatten_iterator_all ) +{ + test_case_all_containers<0>("empty"); + test_case_all_containers<1>("case1"); + test_case_all_containers<2>("case2"); + test_case_all_containers<3>("case3"); +} From 415500955ab633270096618f6a4d983f3086332f Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Mon, 31 Mar 2014 14:52:03 +0300 Subject: [PATCH 31/31] [point iterator] minor staylistic changes in unit test for concatenate iterator; --- test/iterators/concatenate_iterator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/iterators/concatenate_iterator.cpp b/test/iterators/concatenate_iterator.cpp index 941cf612d..6a488bcde 100644 --- a/test/iterators/concatenate_iterator.cpp +++ b/test/iterators/concatenate_iterator.cpp @@ -50,7 +50,7 @@ struct is_odd } }; -struct test_concat_iterator +struct test_concatenate_iterator { template static inline void apply(Container1& c1, Container2& c2, @@ -227,27 +227,27 @@ struct test_concat_iterator }; -BOOST_AUTO_TEST_CASE( test_concatenate_iterator ) +BOOST_AUTO_TEST_CASE( test_concatenate_iterator_all ) { { std::vector v; std::list l; - test_concat_iterator::apply(v, l, "empty_both"); + test_concatenate_iterator::apply(v, l, "empty_both"); } { std::vector v; std::list l; l += 10,11,12,13,14,15,16,17,18,19,20; - test_concat_iterator::apply(v, l, "empty_first"); + test_concatenate_iterator::apply(v, l, "empty_first"); } { std::vector v; v += 0,1,2,3,4,5,6; std::list l; - test_concat_iterator::apply(v, l, "empty_second"); + test_concatenate_iterator::apply(v, l, "empty_second"); } { std::vector v; @@ -255,6 +255,6 @@ BOOST_AUTO_TEST_CASE( test_concatenate_iterator ) std::list l; l += 10,11,12,13,14,15,16,17,18,19,20; - test_concat_iterator::apply(l, v, "non_empty"); + test_concatenate_iterator::apply(l, v, "non_empty"); } }