diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 1b9ba325d..3aa7830e4 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -18,6 +18,19 @@ [section:release_notes Release Notes] +[/=================] +[heading Boost 1.60] +[/=================] + +[*Solved tickets] + +* [@https://svn.boost.org/trac/boost/ticket/11533 11533] Assert failure in rtree caused by a bug in remove() if min elements number is 1 +* [@https://svn.boost.org/trac/boost/ticket/11607 11607] Private geometry::exception::what() + +[*Bugfixes] + +* Fix removing values from an empty rtree - no effect and 0 returned instead of assertion failure. + [/=================] [heading Boost 1.59] [/=================] diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index b25bcc7fb..606726f33 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -135,6 +136,7 @@ struct buffer_range RobustPolicy const& ) { output_point_type intersection_point; + geometry::assign_zero(intersection_point); strategy::buffer::join_selector join = get_join_type(penultimate_input, previous_input, input); @@ -392,7 +394,7 @@ inline void buffer_point(Point const& point, Collection& collection, point_strategy.apply(point, distance_strategy, range_out); collection.add_piece(strategy::buffer::buffered_point, range_out, false); collection.set_piece_center(point); - collection.finish_ring(); + collection.finish_ring(strategy::buffer::result_normal); } @@ -680,7 +682,7 @@ struct buffer_inserter distance, side_strategy, join_strategy, end_strategy, robust_policy, first_p1); } - collection.finish_ring(); + collection.finish_ring(code); } if (code == strategy::buffer::result_no_output && n >= 1) { @@ -740,12 +742,7 @@ private: join_strategy, end_strategy, point_strategy, robust_policy); - if (code == strategy::buffer::result_error_numerical) - { - collection.abort_ring(); - return; - } - collection.finish_ring(is_interior); + collection.finish_ring(code, is_interior); } } @@ -805,14 +802,8 @@ public: join_strategy, end_strategy, point_strategy, robust_policy); - if (code == strategy::buffer::result_error_numerical) - { - collection.abort_ring(); - } - else - { - collection.finish_ring(false, geometry::num_interior_rings(polygon) > 0u); - } + collection.finish_ring(code, false, + geometry::num_interior_rings(polygon) > 0u); } apply_interior_rings(interior_rings(polygon), diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 545d89cb9..dd64261b0 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -860,8 +860,15 @@ struct buffered_piece_collection m_robust_policy); } - inline void finish_ring(bool is_interior = false, bool has_interiors = false) + inline void finish_ring(strategy::buffer::result_code code, + bool is_interior = false, bool has_interiors = false) { + if (code == strategy::buffer::result_error_numerical) + { + abort_ring(); + return; + } + if (m_first_piece_index == -1) { return; diff --git a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp index 84671f257..6074af982 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp @@ -1,12 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// 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. -// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -36,7 +36,6 @@ namespace boost { namespace geometry namespace detail { namespace disjoint { - template < typename Box1, typename Box2, diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp index 12213db05..73b7b7099 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp @@ -1,12 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// 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. -// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -29,7 +29,6 @@ #include - namespace boost { namespace geometry { diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index 783699ee0..fa9515247 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -562,11 +562,12 @@ private: // assert that the segment has non-negative slope BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1)) - && geometry::get<1>(p0) < geometry::get<1>(p1)) - || - ( geometry::get<0>(p0) < geometry::get<0>(p1) - && geometry::get<1>(p0) <= geometry::get<1>(p1) ) - ); + && geometry::get<1>(p0) < geometry::get<1>(p1)) + || + ( geometry::get<0>(p0) < geometry::get<0>(p1) + && geometry::get<1>(p0) <= geometry::get<1>(p1) ) + || geometry::has_nan_coordinate(p0) + || geometry::has_nan_coordinate(p1)); ReturnType result(0); @@ -617,8 +618,10 @@ private: typedef compare_less_equal greater_equal; // assert that the segment has negative slope - BOOST_GEOMETRY_ASSERT( geometry::get<0>(p0) < geometry::get<0>(p1) - && geometry::get<1>(p0) > geometry::get<1>(p1) ); + BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1) + && geometry::get<1>(p0) > geometry::get<1>(p1) ) + || geometry::has_nan_coordinate(p0) + || geometry::has_nan_coordinate(p1) ); ReturnType result(0); @@ -665,7 +668,9 @@ public: PPStrategy const& pp_strategy, PSStrategy const& ps_strategy) { - BOOST_GEOMETRY_ASSERT( geometry::less()(p0, p1) ); + BOOST_GEOMETRY_ASSERT( geometry::less()(p0, p1) + || geometry::has_nan_coordinate(p0) + || geometry::has_nan_coordinate(p1) ); if (geometry::get<0>(p0) < geometry::get<0>(p1) && geometry::get<1>(p0) > geometry::get<1>(p1)) diff --git a/include/boost/geometry/algorithms/detail/expand_by_epsilon.hpp b/include/boost/geometry/algorithms/detail/expand_by_epsilon.hpp new file mode 100644 index 000000000..7af08ee37 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/expand_by_epsilon.hpp @@ -0,0 +1,113 @@ +// Boost.Geometry + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP + +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + +template +< + typename Point, + template class PlusOrMinus, + std::size_t I = 0, + std::size_t D = dimension::value, + bool Enable = boost::is_floating_point + < + typename coordinate_type::type + >::value +> +struct corner_by_epsilon +{ + static inline void apply(Point & point) + { + typedef typename coordinate_type::type coord_type; + coord_type const coord = get(point); + coord_type const eps = math::scaled_epsilon(coord); + + set(point, PlusOrMinus()(coord, eps)); + + corner_by_epsilon::apply(point); + } +}; + +template +< + typename Point, + template class PlusOrMinus, + std::size_t I, + std::size_t D +> +struct corner_by_epsilon +{ + static inline void apply(Point const&) {} +}; + +template +< + typename Point, + template class PlusOrMinus, + std::size_t D, + bool Enable +> +struct corner_by_epsilon +{ + static inline void apply(Point const&) {} +}; + +template +< + typename Point, + template class PlusOrMinus, + std::size_t D +> +struct corner_by_epsilon +{ + static inline void apply(Point const&) {} +}; + +} // namespace expand + +template +inline void expand_by_epsilon(Box & box) +{ + typedef detail::indexed_point_view min_type; + min_type min_point(box); + expand::corner_by_epsilon::apply(min_point); + + typedef detail::indexed_point_view max_type; + max_type max_point(box); + expand::corner_by_epsilon::apply(max_point); +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index 6e87273aa..bbe8e8fc3 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -11,6 +11,9 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP #include +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#include +#endif // BOOST_GEOMETRY_TEST_DEBUG #include #include @@ -327,7 +330,9 @@ protected: g.add_edge(v2, vip); } +#ifdef BOOST_GEOMETRY_TEST_DEBUG debug_print_complement_graph(std::cout, g); +#endif // BOOST_GEOMETRY_TEST_DEBUG if (g.has_cycles()) { diff --git a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp index b1a25c9f5..8cb37d695 100644 --- a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp @@ -51,14 +51,14 @@ class liang_barsky private: typedef model::referring_segment segment_type; - template - inline bool check_edge(T const& p, T const& q, T& t1, T& t2) const + template + inline bool check_edge(CoordinateType const& p, CoordinateType const& q, CalcType& t1, CalcType& t2) const { bool visible = true; if(p < 0) { - T const r = q / p; + CalcType const r = static_cast(q) / p; if (r > t2) visible = false; else if (r > t1) @@ -66,7 +66,7 @@ private: } else if(p > 0) { - T const r = q / p; + CalcType const r = static_cast(q) / p; if (r < t1) visible = false; else if (r < t2) @@ -86,9 +86,10 @@ public: inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const { typedef typename select_coordinate_type::type coordinate_type; + typedef typename select_most_precise::type calc_type; - coordinate_type t1 = 0; - coordinate_type t2 = 1; + calc_type t1 = 0; + calc_type t2 = 1; coordinate_type const dx = get<1, 0>(s) - get<0, 0>(s); coordinate_type const dy = get<1, 1>(s) - get<0, 1>(s); diff --git a/include/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp index b2c383671..b9e48cdbf 100644 --- a/include/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -35,24 +36,6 @@ namespace boost { namespace geometry { -#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) -class inconsistent_turns_exception : public geometry::exception -{ -public: - - inline inconsistent_turns_exception() {} - - virtual ~inconsistent_turns_exception() throw() - {} - - virtual char const* what() const throw() - { - return "Boost.Geometry Inconsistent Turns exception"; - } -}; -#endif - - #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace overlay { 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 717f0b47a..ac36c530b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -585,8 +585,8 @@ struct collinear : public base_turn_handler typename SidePolicy > static inline void apply( - Point1 const& , Point1 const& , Point1 const& , - Point2 const& , Point2 const& , Point2 const& , + Point1 const& , Point1 const& pj, Point1 const& pk, + Point2 const& , Point2 const& qj, Point2 const& qk, TurnInfo& ti, IntersectionInfo const& info, DirInfo const& dir_info, @@ -623,8 +623,30 @@ struct collinear : public base_turn_handler { ui_else_iu(product == 1, ti); } + + // Calculate remaining distance. If it continues collinearly it is + // measured until the end of the next segment + ti.operations[0].remaining_distance + = side_p == 0 + ? distance_measure(ti.point, pk) + : distance_measure(ti.point, pj); + ti.operations[1].remaining_distance + = side_q == 0 + ? distance_measure(ti.point, qk) + : distance_measure(ti.point, qj); } + template + static inline typename geometry::coordinate_type::type + distance_measure(Point1 const& a, Point2 const& b) + { + // TODO: use comparable distance for point-point instead - but that + // causes currently cycling include problems + typedef typename geometry::coordinate_type::type ctype; + ctype const dx = get<0>(a) - get<0>(b); + ctype const dy = get<1>(b) - get<1>(b); + return dx * dx + dy * dy; + } }; template diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index e4f8de42e..ee0a93ae7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -23,9 +23,9 @@ namespace detail { namespace overlay { enum turn_position { position_middle, position_front, position_back }; -template +template struct turn_operation_linear - : public turn_operation + : public turn_operation { turn_operation_linear() : position(position_middle) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 098c7b564..b2b97c033 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -802,19 +802,19 @@ template ::type, typename TagBase2 = typename topological_tag_base::type> struct turn_operation_type { - typedef overlay::turn_operation type; + typedef overlay::turn_operation::type, SegmentRatio> type; }; template struct turn_operation_type { - typedef overlay::turn_operation_linear type; + typedef overlay::turn_operation_linear::type, SegmentRatio> type; }; template struct turn_operation_type { - typedef overlay::turn_operation_linear type; + typedef overlay::turn_operation_linear::type, SegmentRatio> type; }; }} // namespace detail::get_turns diff --git a/include/boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp b/include/boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp new file mode 100644 index 000000000..1486f94fb --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp @@ -0,0 +1,38 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) +#include + +namespace boost { namespace geometry +{ + +class inconsistent_turns_exception : public geometry::exception +{ +public: + + inline inconsistent_turns_exception() {} + + virtual ~inconsistent_turns_exception() throw() + {} + + virtual char const* what() const throw() + { + return "Boost.Geometry Inconsistent Turns exception"; + } +}; + +}} // boost::geometry + +#endif // BOOST_GEOMETRY_OVERLAY_NO_THROW + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp index dd041b0d7..c62b7d283 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp @@ -1,6 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, 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 @@ -39,19 +44,26 @@ struct intersection_box_box { typedef typename coordinate_type::type ct; - ct min1 = get(box1); - ct min2 = get(box2); ct max1 = get(box1); - ct max2 = get(box2); + ct min2 = get(box2); - if (max1 < min2 || max2 < min1) + if (max1 < min2) { return false; } + + ct max2 = get(box2); + ct min1 = get(box1); + + if (max2 < min1) + { + return false; + } + // Set dimensions of output coordinate set(box_out, min1 < min2 ? min2 : min1); set(box_out, max1 > max2 ? max2 : max1); - + return intersection_box_box ::apply(box1, box2, robust_policy, box_out, strategy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index af0731f5a..59c8f6f1f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -175,22 +176,116 @@ template struct intersection_of_linestring_with_areal { #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) - template - static inline void debug_follow(Turn const& turn, Operation op, - int index) - { - std::cout << index - << " at " << op.seg_id - << " meth: " << method_char(turn.method) - << " op: " << operation_char(op.operation) - << " vis: " << visited_char(op.visited) - << " of: " << operation_char(turn.operations[0].operation) - << operation_char(turn.operations[1].operation) - << " " << geometry::wkt(turn.point) - << std::endl; - } + template + static inline void debug_follow(Turn const& turn, Operation op, + int index) + { + std::cout << index + << " at " << op.seg_id + << " meth: " << method_char(turn.method) + << " op: " << operation_char(op.operation) + << " vis: " << visited_char(op.visited) + << " of: " << operation_char(turn.operations[0].operation) + << operation_char(turn.operations[1].operation) + << " " << geometry::wkt(turn.point) + << std::endl; + } + + template + static inline void debug_turn(Turn const& t, bool non_crossing) + { + std::cout << "checking turn @" + << geometry::wkt(t.point) + << "; " << method_char(t.method) + << ":" << operation_char(t.operations[0].operation) + << "/" << operation_char(t.operations[1].operation) + << "; non-crossing? " + << std::boolalpha << non_crossing << std::noboolalpha + << std::endl; + } #endif + class is_crossing_turn + { + // return true is the operation is intersection or blocked + template + static inline bool has_op_i_or_b(Turn const& t) + { + return + t.operations[Index].operation == overlay::operation_intersection + || + t.operations[Index].operation == overlay::operation_blocked; + } + + template + static inline bool has_method_crosses(Turn const& t) + { + return t.method == overlay::method_crosses; + } + + template + static inline bool is_cc(Turn const& t) + { + return + (t.method == overlay::method_touch_interior + || + t.method == overlay::method_equal + || + t.method == overlay::method_collinear) + && + t.operations[0].operation == t.operations[1].operation + && + t.operations[0].operation == overlay::operation_continue + ; + } + + template + static inline bool has_i_or_b_ops(Turn const& t) + { + return + (t.method == overlay::method_touch + || + t.method == overlay::method_touch_interior + || + t.method == overlay::method_collinear) + && + t.operations[1].operation != t.operations[0].operation + && + (has_op_i_or_b<0>(t) || has_op_i_or_b<1>(t)); + } + + public: + template + static inline bool apply(Turn const& t) + { + bool const is_crossing + = has_method_crosses(t) || is_cc(t) || has_i_or_b_ops(t); +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) + debug_turn(t, ! is_crossing); +#endif + return is_crossing; + } + }; + + struct is_non_crossing_turn + { + template + static inline bool apply(Turn const& t) + { + return ! is_crossing_turn::apply(t); + } + }; + + template + static inline bool no_crossing_turns_or_empty(Turns const& turns) + { + return detail::check_iterator_range + < + is_non_crossing_turn, + true // allow an empty turns range + >::apply(boost::begin(turns), boost::end(turns)); + } + template < typename LineString, typename Areal, @@ -212,7 +307,8 @@ struct intersection_of_linestring_with_areal LineStringOut, LineString, Areal, - OverlayType + OverlayType, + false // do not remove spikes for linear geometries > follower; typedef typename point_type::type point_type; @@ -231,7 +327,7 @@ struct intersection_of_linestring_with_areal detail::overlay::assign_null_policy >(linestring, areal, robust_policy, turns, policy); - if (turns.empty()) + if (no_crossing_turns_or_empty(turns)) { // No intersection points, it is either completely // inside (interior + borders) diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp index 6ee32c17c..8cabfb0d8 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp @@ -25,7 +25,7 @@ namespace detail { namespace overlay template -struct traversal_turn_operation : public turn_operation +struct traversal_turn_operation : public turn_operation { enrichment_info enriched; visit_info visited; diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index 803a16471..45e15d13d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -174,7 +174,17 @@ inline bool select_next_ip(operation_type operation, { return false; } + bool has_tp = false; + + typedef typename std::iterator_traits + < + Iterator + >::value_type operation_type; + + typename operation_type::comparable_distance_type + max_remaining_distance = 0; + selected = boost::end(turn.operations); for (Iterator it = boost::begin(turn.operations); it != boost::end(turn.operations); @@ -206,10 +216,24 @@ inline bool select_next_ip(operation_type operation, ) ) { + if (it->operation == operation_continue) + { + max_remaining_distance = it->remaining_distance; + } selected = it; debug_traverse(turn, *it, " Candidate"); has_tp = true; } + + if (it->operation == operation_continue && has_tp) + { + if (it->remaining_distance > max_remaining_distance) + { + max_remaining_distance = it->remaining_distance; + selected = it; + debug_traverse(turn, *it, " Candidate override"); + } + } } if (has_tp) diff --git a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp index 26669a4b1..6cb4d9cbb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp @@ -12,6 +12,7 @@ #include +#include #include namespace boost { namespace geometry @@ -54,15 +55,19 @@ enum method_type The class is to be included in the turn_info class, either direct or a derived or similar class with more (e.g. enrichment) information. */ -template +template struct turn_operation { operation_type operation; segment_identifier seg_id; SegmentRatio fraction; + typedef typename coordinate_type::type comparable_distance_type; + comparable_distance_type remaining_distance; + inline turn_operation() : operation(operation_none) + , remaining_distance(0) {} }; @@ -80,7 +85,7 @@ template < typename Point, typename SegmentRatio, - typename Operation = turn_operation, + typename Operation = turn_operation, typename Container = boost::array > struct turn_info diff --git a/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp b/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp index 9db1ef8e0..399c8fbef 100644 --- a/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp +++ b/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp @@ -1,9 +1,14 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2013 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2013 Mateusz Loskot, London, UK. -// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // 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,8 +17,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP -#include -#include #include #include #include @@ -28,6 +31,17 @@ namespace boost { namespace geometry namespace detail { +template +inline int sign_of_difference(Point1 const& point1, Point2 const& point2) +{ + return + math::equals(geometry::get(point1), geometry::get(point2)) + ? + 0 + : + (geometry::get(point1) > geometry::get(point2) ? 1 : -1); +} + // Checks if a point ("last_point") causes a spike w.r.t. // the specified two other points (segment_a, segment_b) // @@ -35,7 +49,9 @@ namespace detail // a lp b // // Above, lp generates a spike w.r.t. segment(a,b) -// So specify last point first, then (a,b) (this is unordered, so unintuitive) +// So specify last point first, then (a,b) +// The segment's orientation does matter: if lp is to the right of b +// no spike is reported template static inline bool point_is_spike_or_equal(Point1 const& last_point, Point2 const& segment_a, @@ -46,29 +62,21 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point, typename cs_tag::type >::type side_strategy; - typedef Point1 vector_type; - int const side = side_strategy::apply(last_point, segment_a, segment_b); if (side == 0) { // Last point is collinear w.r.t previous segment. // Check if it is equal - vector_type diff1; - conversion::convert_point_to_point(last_point, diff1); - geometry::subtract_point(diff1, segment_b); - int const sgn_x1 = math::sign(geometry::get<0>(diff1)); - int const sgn_y1 = math::sign(geometry::get<1>(diff1)); + int const sgn_x1 = sign_of_difference<0>(last_point, segment_b); + int const sgn_y1 = sign_of_difference<1>(last_point, segment_b); if (sgn_x1 == 0 && sgn_y1 == 0) { return true; } // Check if it moves forward - vector_type diff2; - conversion::convert_point_to_point(segment_b, diff2); - geometry::subtract_point(diff2, segment_a); - int const sgn_x2 = math::sign(geometry::get<0>(diff2)); - int const sgn_y2 = math::sign(geometry::get<1>(diff2)); + int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a); + int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a); return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2; } diff --git a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp index cc9c1b67c..a74954326 100644 --- a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp @@ -338,7 +338,7 @@ struct areal_areal template inline void per_turn(Turn const& turn) { - static const std::size_t other_op_id = (OpId + 1) % 2; + //static const std::size_t other_op_id = (OpId + 1) % 2; static const bool transpose_result = OpId != 0; overlay::operation_type const op = turn.operations[OpId].operation; @@ -357,11 +357,14 @@ struct areal_areal else if ( op == overlay::operation_intersection ) { // ignore i/i - if ( turn.operations[other_op_id].operation != overlay::operation_intersection ) + /*if ( turn.operations[other_op_id].operation != overlay::operation_intersection ) { - update(m_result); + // not correct e.g. for G1 touching G2 in a point where a hole is touching the exterior ring + // in this case 2 turns i/... and u/u will be generated for this IP + //update(m_result); + //update(m_result); - } + }*/ update(m_result); } @@ -473,8 +476,11 @@ struct areal_areal // ignore i/i if ( it->operations[other_op_id].operation != overlay::operation_intersection ) { - // already set in interrupt policy + // this was set in the interrupt policy but it was wrong + // also here it's wrong since it may be a fake entry point //update(result); + + // already set in interrupt policy //update(result); m_enter_detected = true; } @@ -523,6 +529,7 @@ struct areal_areal template static inline void update_enter(Result & result) { + update(result); update(result); update(result); } @@ -574,6 +581,7 @@ struct areal_areal , m_flags(0) { // check which relations must be analysed + // NOTE: 1 and 4 could probably be connected if ( ! may_update(m_result) ) { @@ -662,21 +670,12 @@ struct areal_areal if ( it->operations[0].operation == overlay::operation_intersection && it->operations[1].operation == overlay::operation_intersection ) { - // ignore exterior ring - if ( it->operations[OpId].seg_id.ring_index >= 0 ) - { - found_ii = true; - } + found_ii = true; } else if ( it->operations[0].operation == overlay::operation_union && it->operations[1].operation == overlay::operation_union ) { - // ignore if u/u is for holes - //if ( it->operations[OpId].seg_id.ring_index >= 0 - // && it->operations[other_id].seg_id.ring_index >= 0 ) - { - found_uu = true; - } + found_uu = true; } else // ignore { @@ -687,8 +686,11 @@ struct areal_areal // only i/i was generated for this ring if ( found_ii ) { - //update(m_result); - //update(m_result); + update(m_result); + m_flags |= 1; + + //update(m_result); + update(m_result); update(m_result); m_flags |= 4; diff --git a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index 9de1bacb7..1a9a5a8fd 100644 --- a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -17,6 +17,8 @@ #include +#include + namespace boost { namespace geometry { @@ -90,19 +92,43 @@ public: for ( multi_iterator it = boost::begin(geometry) ; it != boost::end(geometry) ; ++ it ) { + typename boost::range_reference::type + ls = *it; + // empty or point - no boundary - if ( boost::size(*it) < 2 ) + if (boost::size(ls) < 2) + { continue; + } + + typedef typename boost::range_reference + < + typename boost::range_value::type const + >::type point_reference; + + point_reference front_pt = range::front(ls); + point_reference back_pt = range::back(ls); // linear ring or point - no boundary - if ( equals::equals_point_point(range::front(*it), range::back(*it)) ) - continue; - - boundary_points.push_back(range::front(*it)); - boundary_points.push_back(range::back(*it)); + if (! equals::equals_point_point(front_pt, back_pt)) + { + // do not add points containing NaN coordinates + // because they cannot be reasonably compared, e.g. with MSVC + // an assertion failure is reported in std::equal_range() + if (! geometry::has_nan_coordinate(front_pt)) + { + boundary_points.push_back(front_pt); + } + if (! geometry::has_nan_coordinate(back_pt)) + { + boundary_points.push_back(back_pt); + } + } } - std::sort(boundary_points.begin(), boundary_points.end(), geometry::less()); + std::sort(boundary_points.begin(), + boundary_points.end(), + geometry::less()); is_filled = true; } diff --git a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp index 98b857a48..caa8a3c22 100644 --- a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp @@ -16,6 +16,8 @@ #include #include +#include + namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL @@ -106,20 +108,42 @@ struct topology_check typedef typename boost::range_iterator::type ls_iterator; for ( ls_iterator it = boost::begin(mls) ; it != boost::end(mls) ; ++it ) { - std::size_t count = boost::size(*it); + typename boost::range_reference::type + ls = *it; - if ( count > 0 ) + std::size_t count = boost::size(ls); + + if (count > 0) { has_interior = true; } - if ( count > 1 ) + if (count > 1) { + typedef typename boost::range_reference + < + typename boost::range_value::type const + >::type point_reference; + + point_reference front_pt = range::front(ls); + point_reference back_pt = range::back(ls); + // don't store boundaries of linear rings, this doesn't change anything - if ( ! equals::equals_point_point(range::front(*it), range::back(*it)) ) + if (! equals::equals_point_point(front_pt, back_pt)) { - endpoints.push_back(range::front(*it)); - endpoints.push_back(range::back(*it)); + // do not add points containing NaN coordinates + // because they cannot be reasonably compared, e.g. with MSVC + // an assertion failure is reported in std::equal_range() + // NOTE: currently ignoring_counter calling std::equal_range() + // is not used anywhere in the code, still it's safer this way + if (! geometry::has_nan_coordinate(front_pt)) + { + endpoints.push_back(front_pt); + } + if (! geometry::has_nan_coordinate(back_pt)) + { + endpoints.push_back(back_pt); + } } } } diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index d54948e1f..09d74dec3 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -128,8 +128,8 @@ struct get_turns template struct op_to_int { - template - inline int operator()(detail::overlay::turn_operation const& op) const + template + inline int operator()(Operation const& op) const { switch(op.operation) { diff --git a/include/boost/geometry/algorithms/detail/sections/section_functions.hpp b/include/boost/geometry/algorithms/detail/sections/section_functions.hpp index ba1cf931b..7bc5c0804 100644 --- a/include/boost/geometry/algorithms/detail/sections/section_functions.hpp +++ b/include/boost/geometry/algorithms/detail/sections/section_functions.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, 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 // http://www.boost.org/LICENSE_1_0.txt) diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 1ced39435..6443965e9 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -52,6 +52,8 @@ #include #include +#include + namespace boost { namespace geometry { @@ -599,19 +601,18 @@ inline void enlarge_sections(Sections& sections) // Reason: turns might, rarely, be missed otherwise (case: "buffer_mp1") // Drawback: not really, range is now completely inside the section. Section is a tiny bit too large, // which might cause (a small number) of more comparisons - // TODO: make dimension-agnostic + + // NOTE: above is old comment to the not used code expanding the Boxes by relaxed_epsilon(10) + + // Enlarge sections by scaled epsilon, this should be consistent with math::equals(). + // Points and Segments are equal-compared WRT machine epsilon, but Boxes aren't + // Enlarging Boxes ensures that they correspond to the bound objects, + // Segments in this case, since Sections are collections of Segments. for (typename boost::range_iterator::type it = boost::begin(sections); it != boost::end(sections); ++it) { - typedef typename boost::range_value::type section_type; - typedef typename section_type::box_type box_type; - typedef typename geometry::coordinate_type::type coordinate_type; - coordinate_type const reps = math::relaxed_epsilon(10.0); - geometry::set<0, 0>(it->bounding_box, geometry::get<0, 0>(it->bounding_box) - reps); - geometry::set<0, 1>(it->bounding_box, geometry::get<0, 1>(it->bounding_box) - reps); - geometry::set<1, 0>(it->bounding_box, geometry::get<1, 0>(it->bounding_box) + reps); - geometry::set<1, 1>(it->bounding_box, geometry::get<1, 1>(it->bounding_box) + reps); + detail::expand_by_epsilon(it->bounding_box); } } @@ -802,6 +803,8 @@ inline void sectionalize(Geometry const& geometry, Reverse, DimensionVector >::apply(geometry, robust_policy, sections, ring_id, max_count); + + detail::sectionalize::enlarge_sections(sections); } diff --git a/include/boost/geometry/algorithms/overlaps.hpp b/include/boost/geometry/algorithms/overlaps.hpp index 96310d6cb..9b5abdb2a 100644 --- a/include/boost/geometry/algorithms/overlaps.hpp +++ b/include/boost/geometry/algorithms/overlaps.hpp @@ -1,11 +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-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -14,8 +16,6 @@ // 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_OVERLAPS_HPP #define BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP @@ -31,6 +31,7 @@ #include #include + namespace boost { namespace geometry { @@ -83,6 +84,7 @@ struct box_box_loop { one_in_two = false; } + // Same other way round if (min2 < min1 || max2 > max1) { diff --git a/include/boost/geometry/algorithms/touches.hpp b/include/boost/geometry/algorithms/touches.hpp index d6f0df3c7..570c54797 100644 --- a/include/boost/geometry/algorithms/touches.hpp +++ b/include/boost/geometry/algorithms/touches.hpp @@ -1,12 +1,14 @@ // 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) 2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -15,8 +17,6 @@ // 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_TOUCHES_HPP #define BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP @@ -40,6 +40,7 @@ #include #include + namespace boost { namespace geometry { @@ -70,12 +71,12 @@ struct box_box_loop // TODO assert or exception? //BOOST_GEOMETRY_ASSERT(min1 <= max1 && min2 <= max2); - if ( max1 < min2 || max2 < min1 ) + if (max1 < min2 || max2 < min1) { return false; } - if ( max1 == min2 || max2 == min1 ) + if (max1 == min2 || max2 == min1) { touch = true; } @@ -385,6 +386,16 @@ struct touches template struct touches + : detail::relate::relate_impl + < + detail::de9im::static_mask_touches_type, + Areal1, + Areal2 + > +{}; + +template +struct touches : detail::touches::areal_areal {}; diff --git a/include/boost/geometry/core/exception.hpp b/include/boost/geometry/core/exception.hpp index 6868ca775..21abbd577 100644 --- a/include/boost/geometry/core/exception.hpp +++ b/include/boost/geometry/core/exception.hpp @@ -32,6 +32,7 @@ namespace boost { namespace geometry */ class exception : public std::exception { +public: virtual char const* what() const throw() { return "Boost.Geometry exception"; diff --git a/include/boost/geometry/index/detail/is_bounding_geometry.hpp b/include/boost/geometry/index/detail/is_bounding_geometry.hpp new file mode 100644 index 000000000..d14204af7 --- /dev/null +++ b/include/boost/geometry/index/detail/is_bounding_geometry.hpp @@ -0,0 +1,35 @@ +// Boost.Geometry Index +// +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. +// +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP +#define BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP + +#include +#include + +namespace boost { namespace geometry { namespace index { namespace detail { + +template +< + typename Geometry, + typename Tag = typename geometry::tag::type +> +struct is_bounding_geometry +{ + static const bool value = false; +}; + +template +struct is_bounding_geometry +{ + static const bool value = true; +}; + +}}}} // namespave boost::geometry::index::detail + +#endif // BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP diff --git a/include/boost/geometry/index/detail/is_indexable.hpp b/include/boost/geometry/index/detail/is_indexable.hpp new file mode 100644 index 000000000..1e86463a3 --- /dev/null +++ b/include/boost/geometry/index/detail/is_indexable.hpp @@ -0,0 +1,47 @@ +// Boost.Geometry Index +// +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. +// +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP +#define BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP + +#include +#include + +namespace boost { namespace geometry { namespace index { namespace detail { + +template +< + typename Geometry, + typename Tag = typename geometry::tag::type +> +struct is_indexable +{ + static const bool value = false; +}; + +template +struct is_indexable +{ + static const bool value = true; +}; + +template +struct is_indexable +{ + static const bool value = true; +}; + +template +struct is_indexable +{ + static const bool value = true; +}; + +}}}} // namespave boost::geometry::index::detail + +#endif // BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP diff --git a/include/boost/geometry/index/detail/rtree/node/node.hpp b/include/boost/geometry/index/detail/rtree/node/node.hpp index b04744c85..2b270319f 100644 --- a/include/boost/geometry/index/detail/rtree/node/node.hpp +++ b/include/boost/geometry/index/detail/rtree/node/node.hpp @@ -34,6 +34,7 @@ #include #include +#include namespace boost { namespace geometry { namespace index { @@ -45,8 +46,16 @@ template inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr) { Box result; + + // Only here to suppress 'uninitialized local variable used' warning + // until the suggestion below is not implemented + geometry::assign_inverse(result); - BOOST_GEOMETRY_INDEX_ASSERT(first != last, "non-empty range required"); + //BOOST_GEOMETRY_INDEX_ASSERT(first != last, "non-empty range required"); + // NOTE: this is not elegant temporary solution, + // reference to box could be passed as parameter and bool returned + if ( first == last ) + return result; detail::bounds(element_indexable(*first, tr), result); ++first; @@ -57,6 +66,35 @@ inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr) return result; } +// Enlarge bounds of a leaf node WRT epsilon if needed. +// It's because Points and Segments are compared WRT machine epsilon. +// This ensures that leafs bounds correspond to the stored elements. +// NOTE: this is done only if the Indexable is not a Box +// in the future don't do it also for NSphere +template +inline Box values_box(FwdIter first, FwdIter last, Translator const& tr) +{ + typedef typename std::iterator_traits::value_type element_type; + BOOST_MPL_ASSERT_MSG((is_leaf_element::value), + SHOULD_BE_CALLED_ONLY_FOR_LEAF_ELEMENTS, + (element_type)); + + Box result = elements_box(first, last, tr); + +#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON + if (BOOST_GEOMETRY_CONDITION(( + ! is_bounding_geometry + < + typename indexable_type::type + >::value))) + { + geometry::detail::expand_by_epsilon(result); + } +#endif + + return result; +} + // destroys subtree if the element is internal node's element template struct destroy_element diff --git a/include/boost/geometry/index/detail/rtree/node/node_elements.hpp b/include/boost/geometry/index/detail/rtree/node/node_elements.hpp index e3bfb701f..0e5848987 100644 --- a/include/boost/geometry/index/detail/rtree/node/node_elements.hpp +++ b/include/boost/geometry/index/detail/rtree/node/node_elements.hpp @@ -2,7 +2,7 @@ // // R-tree node elements access // -// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -12,6 +12,7 @@ #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_ELEMENTS_HPP #include +#include #include #include @@ -36,6 +37,20 @@ struct element_indexable_type< typedef First type; }; +// is leaf element + +template +struct is_leaf_element +{ + static const bool value = true; +}; + +template +struct is_leaf_element< rtree::ptr_pair > +{ + static const bool value = false; +}; + // element's indexable getter template diff --git a/include/boost/geometry/index/detail/rtree/pack_create.hpp b/include/boost/geometry/index/detail/rtree/pack_create.hpp index ce07d293d..e56ce076d 100644 --- a/include/boost/geometry/index/detail/rtree/pack_create.hpp +++ b/include/boost/geometry/index/detail/rtree/pack_create.hpp @@ -14,6 +14,8 @@ #include #include +#include + namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace pack_utils { @@ -214,6 +216,11 @@ private: } } + void expand_by_epsilon() + { + geometry::detail::expand_by_epsilon(m_box); + } + BoxType const& get() const { BOOST_GEOMETRY_INDEX_ASSERT(m_initialized, "uninitialized envelope accessed"); @@ -264,6 +271,23 @@ private: rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C) } +#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON + // Enlarge bounds of a leaf node. + // It's because Points and Segments are compared WRT machine epsilon + // This ensures that leafs bounds correspond to the stored elements + // NOTE: this is done only if the Indexable is a different kind of Geometry + // than the bounds (only Box for now). Spatial predicates are checked + // the same way for Geometry of the same kind. + if ( BOOST_GEOMETRY_CONDITION(( + ! index::detail::is_bounding_geometry + < + typename indexable_type::type + >::value )) ) + { + elements_box.expand_by_epsilon(); + } +#endif + auto_remover.release(); return internal_element(elements_box.get(), n); } diff --git a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp index ce9214087..127290194 100644 --- a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp +++ b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp @@ -2,7 +2,7 @@ // // R-tree R*-tree insert algorithm implementation // -// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -231,16 +231,28 @@ struct level_insert_base } template - inline void recalculate_aabb_if_necessary(Node &n) const + inline void recalculate_aabb_if_necessary(Node const& n) const { if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() ) { // calulate node's new box - base::m_traverse_data.current_element().first = - elements_box(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator); + recalculate_aabb(n); } } + template + inline void recalculate_aabb(Node const& n) const + { + base::m_traverse_data.current_element().first = + elements_box(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator); + } + + inline void recalculate_aabb(leaf const& n) const + { + base::m_traverse_data.current_element().first = + values_box(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator); + } + size_type result_relative_level; result_elements_type result_elements; }; diff --git a/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp b/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp index d2caa3670..8e0560379 100644 --- a/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp +++ b/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp @@ -2,7 +2,7 @@ // // R-tree boxes validating visitor implementation // -// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -60,13 +60,7 @@ public: m_box = box_bckup; m_is_root = is_root_bckup; - Box box_exp; - geometry::convert(elements.front().first, box_exp); - for( typename elements_type::const_iterator it = elements.begin() + 1; - it != elements.end() ; ++it) - { - geometry::expand(box_exp, it->first); - } + Box box_exp = rtree::elements_box(elements.begin(), elements.end(), m_tr); if ( m_exact_match ) result = m_is_root || geometry::equals(box_exp, m_box); @@ -88,15 +82,7 @@ public: return; } - Box box_exp; - geometry::convert( - index::detail::return_ref_or_bounds(m_tr(elements.front())), - box_exp); - for(typename elements_type::const_iterator it = elements.begin() + 1; - it != elements.end() ; ++it) - { - geometry::expand(box_exp, m_tr(*it)); - } + Box box_exp = rtree::values_box(elements.begin(), elements.end(), m_tr); if ( m_exact_match ) result = geometry::equals(box_exp, m_box); diff --git a/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp b/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp index 93726063b..6c1bafd3d 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp @@ -2,7 +2,7 @@ // // R-tree node children box calculating visitor implementation // -// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -40,7 +40,7 @@ public: typedef typename rtree::elements_type::type elements_type; elements_type const& elements = rtree::elements(n); - m_result = rtree::elements_box(elements.begin(), elements.end(), m_tr); + m_result = rtree::values_box(elements.begin(), elements.end(), m_tr); } private: diff --git a/include/boost/geometry/index/detail/rtree/visitors/insert.hpp b/include/boost/geometry/index/detail/rtree/visitors/insert.hpp index e697c065e..87d5bbbcc 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/insert.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/insert.hpp @@ -11,6 +11,11 @@ #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP +#include + +#include +#include + #include namespace boost { namespace geometry { namespace index { @@ -262,6 +267,29 @@ protected: BOOST_GEOMETRY_INDEX_ASSERT(0 != m_root_node, "there is no root node"); // TODO // assert - check if Box is correct + + // When a value is inserted, during the tree traversal bounds of nodes + // on a path from the root to a leaf must be expanded. So prepare + // a bounding object at the beginning to not do it later for each node. + // NOTE: This is actually only needed because conditionally the bounding + // object may be expanded below. Otherwise the indexable could be + // directly used instead + index::detail::bounds(rtree::element_indexable(m_element, m_translator), m_element_bounds); + +#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON + // Enlarge it in case if it's not bounding geometry type. + // It's because Points and Segments are compared WRT machine epsilon + // This ensures that leafs bounds correspond to the stored elements + if (BOOST_GEOMETRY_CONDITION(( + boost::is_same::value + && ! index::detail::is_bounding_geometry + < + typename indexable_type::type + >::value )) ) + { + geometry::detail::expand_by_epsilon(m_element_bounds); + } +#endif } template @@ -274,7 +302,8 @@ protected: // expand the node to contain value geometry::expand( rtree::elements(n)[choosen_node_index].first, - rtree::element_indexable(m_element, m_translator)); + m_element_bounds + /*rtree::element_indexable(m_element, m_translator)*/); // next traversing step traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V, E: alloc, copy, N:alloc) @@ -342,6 +371,22 @@ protected: // for exception safety subtree_destroyer additional_node_ptr(additional_nodes[0].second, m_allocators); +#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON + // Enlarge bounds of a leaf node. + // It's because Points and Segments are compared WRT machine epsilon + // This ensures that leafs' bounds correspond to the stored elements. + if (BOOST_GEOMETRY_CONDITION(( + boost::is_same::value + && ! index::detail::is_bounding_geometry + < + typename indexable_type::type + >::value ))) + { + geometry::detail::expand_by_epsilon(n_box); + geometry::detail::expand_by_epsilon(additional_nodes[0].first); + } +#endif + // node is not the root - just add the new node if ( !m_traverse_data.current_is_root() ) { @@ -383,6 +428,7 @@ protected: // TODO: awulkiew - implement dispatchable split::apply to enable additional nodes creation Element const& m_element; + Box m_element_bounds; parameters_type const& m_parameters; Translator const& m_translator; size_type const m_relative_level; diff --git a/include/boost/geometry/index/detail/rtree/visitors/remove.hpp b/include/boost/geometry/index/detail/rtree/visitors/remove.hpp index 494d5a019..6326f87db 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/remove.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/remove.hpp @@ -97,6 +97,9 @@ public: size_type relative_level = m_leafs_level - m_current_level; // move node to the container - store node's relative level as well and return new underflow state + // NOTE: if the min elements number is 1, then after an underflow + // here the child elements count is 0, so it's not required to store this node, + // it could just be destroyed m_is_underflow = store_underflowed_node(elements, underfl_el_it, relative_level); // MAY THROW (E: alloc, copy) } @@ -120,10 +123,16 @@ public: reinsert_removed_nodes_elements(); // MAY THROW (V, E: alloc, copy, N: alloc) // shorten the tree - if ( rtree::elements(n).size() == 1 ) + // NOTE: if the min elements number is 1, then after underflow + // here the number of elements may be equal to 0 + // this can occur only for the last removed element + if ( rtree::elements(n).size() <= 1 ) { node_pointer root_to_destroy = m_root_node; - m_root_node = rtree::elements(n)[0].second; + if ( rtree::elements(n).size() == 0 ) + m_root_node = 0; + else + m_root_node = rtree::elements(n)[0].second; --m_leafs_level; rtree::destroy_node::apply(m_allocators, root_to_destroy); @@ -161,7 +170,7 @@ public: if ( 0 != m_parent ) { rtree::elements(*m_parent)[m_current_child_index].first - = rtree::elements_box(elements.begin(), elements.end(), m_translator); + = rtree::values_box(elements.begin(), elements.end(), m_translator); } } } diff --git a/include/boost/geometry/index/indexable.hpp b/include/boost/geometry/index/indexable.hpp index 391b544f3..feaae557a 100644 --- a/include/boost/geometry/index/indexable.hpp +++ b/include/boost/geometry/index/indexable.hpp @@ -1,6 +1,6 @@ // Boost.Geometry Index // -// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -11,31 +11,10 @@ #include +#include + namespace boost { namespace geometry { namespace index { namespace detail { -template -struct is_indexable_impl { static const bool value = false; }; - -template -struct is_indexable_impl { static const bool value = true; }; - -template -struct is_indexable_impl { static const bool value = true; }; - -template -struct is_indexable_impl { static const bool value = true; }; - -template -struct is_indexable -{ - static const bool value = - is_indexable_impl - < - Indexable, - typename geometry::tag::type - >::value; -}; - /*! \brief The function object extracting Indexable from Value. diff --git a/include/boost/geometry/index/rtree.hpp b/include/boost/geometry/index/rtree.hpp index 84c4da8a2..ea7fc74ed 100644 --- a/include/boost/geometry/index/rtree.hpp +++ b/include/boost/geometry/index/rtree.hpp @@ -627,6 +627,9 @@ public: template inline void insert(ConvertibleOrRange const& conv_or_rng) { + if ( !m_members.root ) + this->raw_create(); + typedef boost::mpl::bool_ < boost::is_convertible::value @@ -657,6 +660,9 @@ public: */ inline size_type remove(value_type const& value) { + if ( !m_members.root ) + return 0; + return this->raw_remove(value); } @@ -687,6 +693,10 @@ public: inline size_type remove(Iterator first, Iterator last) { size_type result = 0; + + if ( !m_members.root ) + return result; + for ( ; first != last ; ++first ) result += this->raw_remove(*first); return result; @@ -716,6 +726,9 @@ public: template inline size_type remove(ConvertibleOrRange const& conv_or_rng) { + if ( !m_members.root ) + return 0; + typedef boost::mpl::bool_ < boost::is_convertible::value @@ -1279,6 +1292,9 @@ public: template size_type count(ValueOrIndexable const& vori) const { + if ( !m_members.root ) + return 0; + // the input should be convertible to Value or Indexable type enum { as_val = 0, as_ind, dont_know }; @@ -1570,9 +1586,6 @@ private: inline void insert_dispatch(ValueConvertible const& val_conv, boost::mpl::bool_ const& /*is_convertible*/) { - if ( !m_members.root ) - this->raw_create(); - this->raw_insert(val_conv); } @@ -1592,9 +1605,6 @@ private: PASSED_OBJECT_IS_NOT_CONVERTIBLE_TO_VALUE_NOR_A_RANGE, (Range)); - if ( !m_members.root ) - this->raw_create(); - typedef typename boost::range_const_iterator::type It; for ( It it = boost::const_begin(rng); it != boost::const_end(rng) ; ++it ) this->raw_insert(*it); @@ -1664,6 +1674,8 @@ private: template size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_ const& /*is_distance_predicate*/) const { + BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist"); + static const unsigned distance_predicate_index = detail::predicates_find_distance::value; detail::rtree::visitors::distance_query< value_type, @@ -1690,8 +1702,7 @@ private: template size_type raw_count(ValueOrIndexable const& vori) const { - if ( !m_members.root ) - return 0; + BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist"); detail::rtree::visitors::count < diff --git a/include/boost/geometry/strategies/cartesian/box_in_box.hpp b/include/boost/geometry/strategies/cartesian/box_in_box.hpp index 9889658a1..56aef9e4d 100644 --- a/include/boost/geometry/strategies/cartesian/box_in_box.hpp +++ b/include/boost/geometry/strategies/cartesian/box_in_box.hpp @@ -1,9 +1,14 @@ // 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) 2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -32,10 +37,10 @@ namespace within struct box_within_range { template - static inline bool apply(BoxContainedValue const& bed_min - , BoxContainedValue const& bed_max - , BoxContainingValue const& bing_min - , BoxContainingValue const& bing_max) + static inline bool apply(BoxContainedValue const& bed_min, + BoxContainedValue const& bed_max, + BoxContainingValue const& bing_min, + BoxContainingValue const& bing_max) { return bing_min <= bed_min && bed_max <= bing_max // contained in containing && bed_min < bed_max; // interiors overlap @@ -46,10 +51,10 @@ struct box_within_range struct box_covered_by_range { template - static inline bool apply(BoxContainedValue const& bed_min - , BoxContainedValue const& bed_max - , BoxContainingValue const& bing_min - , BoxContainingValue const& bing_max) + static inline bool apply(BoxContainedValue const& bed_min, + BoxContainedValue const& bed_max, + BoxContainingValue const& bing_min, + BoxContainingValue const& bing_max) { return bed_min >= bing_min && bed_max <= bing_max; } diff --git a/include/boost/geometry/strategies/cartesian/point_in_box.hpp b/include/boost/geometry/strategies/cartesian/point_in_box.hpp index 79f094113..bd2303cbc 100644 --- a/include/boost/geometry/strategies/cartesian/point_in_box.hpp +++ b/include/boost/geometry/strategies/cartesian/point_in_box.hpp @@ -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-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. diff --git a/include/boost/geometry/strategies/transform/inverse_transformer.hpp b/include/boost/geometry/strategies/transform/inverse_transformer.hpp index 685cf874b..e64a46e4a 100644 --- a/include/boost/geometry/strategies/transform/inverse_transformer.hpp +++ b/include/boost/geometry/strategies/transform/inverse_transformer.hpp @@ -16,6 +16,9 @@ // Remove the ublas checking, otherwise the inverse might fail // (while nothing seems to be wrong) +#ifdef BOOST_UBLAS_TYPE_CHECK +#undef BOOST_UBLAS_TYPE_CHECK +#endif #define BOOST_UBLAS_TYPE_CHECK 0 #include diff --git a/include/boost/geometry/strategies/transform/matrix_transformers.hpp b/include/boost/geometry/strategies/transform/matrix_transformers.hpp index 699b91b3a..d891263a7 100644 --- a/include/boost/geometry/strategies/transform/matrix_transformers.hpp +++ b/include/boost/geometry/strategies/transform/matrix_transformers.hpp @@ -24,6 +24,9 @@ // Remove the ublas checking, otherwise the inverse might fail // (while nothing seems to be wrong) +#ifdef BOOST_UBLAS_TYPE_CHECK +#undef BOOST_UBLAS_TYPE_CHECK +#endif #define BOOST_UBLAS_TYPE_CHECK 0 #include diff --git a/include/boost/geometry/util/has_nan_coordinate.hpp b/include/boost/geometry/util/has_nan_coordinate.hpp new file mode 100644 index 000000000..b442c1c2b --- /dev/null +++ b/include/boost/geometry/util/has_nan_coordinate.hpp @@ -0,0 +1,59 @@ +// Boost.Geometry + +// Copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP +#define BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { + +template ::value> +struct has_nan_coordinate +{ + static bool apply(Point const& point) + { + return boost::math::isnan(geometry::get(point)) + || has_nan_coordinate::apply(point); + } +}; + +template +struct has_nan_coordinate +{ + static bool apply(Point const& ) + { + return false; + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +template +bool has_nan_coordinate(Point const& point) +{ + return detail::has_nan_coordinate::apply(point); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP diff --git a/include/boost/geometry/util/math.hpp b/include/boost/geometry/util/math.hpp index d84b11f48..c193c8f3f 100644 --- a/include/boost/geometry/util/math.hpp +++ b/include/boost/geometry/util/math.hpp @@ -201,11 +201,36 @@ struct smaller { static inline bool apply(Type const& a, Type const& b) { - if (equals::apply(a, b, equals_default_policy())) + if (!(a < b)) // a >= b { return false; } - return a < b; + + return ! equals::apply(b, a, equals_default_policy()); + } +}; + +template ::value> +struct smaller_or_equals +{ + static inline bool apply(Type const& a, Type const& b) + { + return a <= b; + } +}; + +template +struct smaller_or_equals +{ + static inline bool apply(Type const& a, Type const& b) + { + if (a <= b) + { + return true; + } + + return equals::apply(a, b, equals_default_policy()); } }; @@ -407,6 +432,30 @@ struct relaxed_epsilon } }; +// This must be consistent with math::equals. +// By default math::equals() scales the error by epsilon using the greater of +// compared values but here is only one value, though it should work the same way. +// (a-a) <= max(a, a) * EPS -> 0 <= a*EPS +// (a+da-a) <= max(a+da, a) * EPS -> da <= (a+da)*EPS +template ::value> +struct scaled_epsilon +{ + static inline T apply(T const& val) + { + return (std::max)(abs::apply(val), T(1)) + * std::numeric_limits::epsilon(); + } +}; + +template +struct scaled_epsilon +{ + static inline T apply(T const&) + { + return T(0); + } +}; + // ItoF ItoI FtoF template ::is_integer, @@ -460,6 +509,12 @@ inline T relaxed_epsilon(T const& factor) return detail::relaxed_epsilon::apply(factor); } +template +inline T scaled_epsilon(T const& value) +{ + return detail::scaled_epsilon::apply(value); +} + // Maybe replace this by boost equals or boost ublas numeric equals or so @@ -512,6 +567,24 @@ inline bool larger(T1 const& a, T2 const& b) >::apply(b, a); } +template +inline bool smaller_or_equals(T1 const& a, T2 const& b) +{ + return detail::smaller_or_equals + < + typename select_most_precise::type + >::apply(a, b); +} + +template +inline bool larger_or_equals(T1 const& a, T2 const& b) +{ + return detail::smaller_or_equals + < + typename select_most_precise::type + >::apply(b, a); +} + template inline T d2r() diff --git a/index/example/benchmark_experimental.cpp b/index/example/benchmark_experimental.cpp index 55e29eb7f..6556d7662 100644 --- a/index/example/benchmark_experimental.cpp +++ b/index/example/benchmark_experimental.cpp @@ -1,7 +1,7 @@ // Boost.Geometry Index // Additional tests -// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -21,6 +21,9 @@ #include #include +#include +#include + namespace bg = boost::geometry; namespace bgi = bg::index; @@ -139,7 +142,10 @@ int main() RT t(values.begin(), values.end()); dur_t time = clock_t::now() - start; - std::cout << time << " - pack " << values_count << '\n'; + std::cout << time << " - pack " << values_count /*<< '\n'*/; + + std::cout << (bgi::detail::rtree::utilities::are_levels_ok(t) ? " ok" : " NOK") + << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " ok\n" : "NOK\n"); { clock_t::time_point start = clock_t::now(); @@ -164,7 +170,10 @@ int main() clock_t::time_point start = clock_t::now(); t.insert(values); dur_t time = clock_t::now() - start; - std::cout << time << " - insert " << values_count << '\n'; + std::cout << time << " - insert " << values_count /*<< '\n'*/; + + std::cout << (bgi::detail::rtree::utilities::are_levels_ok(t) ? " ok" : " NOK") + << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " ok\n" : "NOK\n"); } @@ -462,6 +471,8 @@ int main() } dur_t time = clock_t::now() - start; std::cout << time << " - remove " << values_count / 10 << '\n'; + + std::cout << (bgi::detail::rtree::utilities::are_boxes_ok(t) ? " boxes ok\n" : "boxes NOT ok\n"); } std::cout << "------------------------------------------------\n"; diff --git a/index/test/rtree/Jamfile.v2 b/index/test/rtree/Jamfile.v2 index 23578b4e9..6eb676a45 100644 --- a/index/test/rtree/Jamfile.v2 +++ b/index/test/rtree/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.Geometry Index # -# Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. +# Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. # # Use, modification and distribution is subject to the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -12,6 +12,8 @@ build-project generated ; test-suite boost-geometry-index-rtree : + [ run rtree_epsilon.cpp ] + [ run rtree_insert_remove.cpp ] [ run rtree_move_pack.cpp ] [ run rtree_values.cpp ] [ compile-fail rtree_values_invalid.cpp ] diff --git a/index/test/rtree/rtree_epsilon.cpp b/index/test/rtree/rtree_epsilon.cpp new file mode 100644 index 000000000..728e22d9c --- /dev/null +++ b/index/test/rtree/rtree_epsilon.cpp @@ -0,0 +1,95 @@ +// Boost.Geometry Index +// Unit Test + +// Copyright (c) 2015 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Enable enlargement of Values' bounds by epsilon in the rtree +// for Points and Segments +#define BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON + +#include + +#include + +#include +#include + +template +void test_rtree(unsigned vcount) +{ + typedef bg::model::point point_t; + + std::vector values; + + double eps = std::numeric_limits::epsilon(); + values.push_back(point_t(eps/2, eps/2)); + + for ( unsigned i = 1 ; i < vcount ; ++i ) + { + values.push_back(point_t(i, i)); + } + + point_t qpt(0, 0); + + BOOST_CHECK(bg::intersects(qpt, values[0])); + + { + bgi::rtree rt(values); + + std::vector result; + rt.query(bgi::intersects(qpt), std::back_inserter(result)); + BOOST_CHECK(result.size() == 1); + + rt.remove(values.begin() + vcount/2, values.end()); + + result.clear(); + rt.query(bgi::intersects(qpt), std::back_inserter(result)); + BOOST_CHECK(result.size() == 1); + } + + { + bgi::rtree rt; + rt.insert(values); + + std::vector result; + rt.query(bgi::intersects(qpt), std::back_inserter(result)); + BOOST_CHECK(result.size() == 1); + + rt.remove(values.begin() + vcount/2, values.end()); + + result.clear(); + rt.query(bgi::intersects(qpt), std::back_inserter(result)); + BOOST_CHECK(result.size() == 1); + } +} + +template +void test_rtree_all() +{ + int pow = Max; + for (int l = 0 ; l < 3 ; ++l) + { + pow *= Max; + int vcount = (pow * 8) / 10; + + //std::cout << Max << " " << Min << " " << vcount << std::endl; + + test_rtree< bgi::linear >(vcount); + test_rtree< bgi::quadratic >(vcount); + test_rtree< bgi::rstar >(vcount); + } +} + +int test_main(int, char* []) +{ + test_rtree_all<2, 1>(); + test_rtree_all<4, 1>(); + test_rtree_all<4, 2>(); + test_rtree_all<5, 3>(); + + return 0; +} diff --git a/index/test/rtree/rtree_insert_remove.cpp b/index/test/rtree/rtree_insert_remove.cpp new file mode 100644 index 000000000..068843fa8 --- /dev/null +++ b/index/test/rtree/rtree_insert_remove.cpp @@ -0,0 +1,82 @@ +// Boost.Geometry Index +// Unit Test + +// Copyright (c) 2015 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#include +#include + +template +void test_rtree(unsigned vcount) +{ + typedef bg::model::point point_t; + + bgi::rtree rt; + + BOOST_CHECK(rt.remove(point_t(0)) == 0); + + for ( unsigned i = 0 ; i < vcount ; ++i ) + { + rt.insert(point_t(static_cast(i))); + } + + BOOST_CHECK(rt.size() == vcount); + BOOST_CHECK(rt.count(point_t(vcount / 2)) == 1); + + for ( unsigned i = 0 ; i < vcount + 3 ; ++i ) + { + rt.remove(point_t((i + 3) % vcount)); + } + + BOOST_CHECK(rt.size() == 0); + BOOST_CHECK(rt.count(point_t(vcount / 2)) == 0); + + for ( unsigned i = 0 ; i < vcount ; ++i ) + { + rt.insert(point_t((i + 5) % vcount)); + } + + BOOST_CHECK(rt.size() == vcount); + BOOST_CHECK(rt.count(point_t(vcount / 2)) == 1); + + for ( unsigned i = 0 ; i < vcount + 3 ; ++i ) + { + rt.remove(point_t((i + 7) % vcount)); + } + + BOOST_CHECK(rt.size() == 0); + BOOST_CHECK(rt.count(point_t(vcount / 2)) == 0); +} + +template +void test_rtree_all() +{ + int pow = Max; + for (int l = 0 ; l < 3 ; ++l) + { + pow *= Max; + int vcount = (pow * 8) / 10; + + //std::cout << Max << " " << Min << " " << vcount << std::endl; + + test_rtree< bgi::linear >(vcount); + test_rtree< bgi::quadratic >(vcount); + test_rtree< bgi::rstar >(vcount); + } +} + +int test_main(int, char* []) +{ + test_rtree_all<2, 1>(); + test_rtree_all<4, 1>(); + test_rtree_all<4, 2>(); + test_rtree_all<5, 3>(); + + return 0; +} diff --git a/index/test/rtree/test_rtree.hpp b/index/test/rtree/test_rtree.hpp index 75f787947..92fff6be2 100644 --- a/index/test/rtree/test_rtree.hpp +++ b/index/test/rtree/test_rtree.hpp @@ -1,7 +1,7 @@ // Boost.Geometry Index // Unit Test -// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -1828,20 +1828,19 @@ void test_rtree_bounds(Parameters const& parameters, Allocator const& allocator) typedef typename Tree::bounds_type B; //typedef typename bg::traits::point_type::type P; - B b; - bg::assign_inverse(b); - Tree t(parameters, I(), E(), allocator); std::vector input; B qbox; + B b; + bg::assign_inverse(b); + BOOST_CHECK(bg::equals(t.bounds(), b)); generate::rtree(t, input, qbox); - BOOST_FOREACH(Value const& v, input) - bg::expand(b, t.indexable_get()(v)); - + b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get()); + BOOST_CHECK(bg::equals(t.bounds(), b)); BOOST_CHECK(bg::equals(t.bounds(), bgi::bounds(t))); @@ -1852,9 +1851,7 @@ void test_rtree_bounds(Parameters const& parameters, Allocator const& allocator) input.pop_back(); } - bg::assign_inverse(b); - BOOST_FOREACH(Value const& v, input) - bg::expand(b, t.indexable_get()(v)); + b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get()); BOOST_CHECK(bg::equals(t.bounds(), b)); diff --git a/test/algorithms/buffer/buffer_linestring.cpp b/test/algorithms/buffer/buffer_linestring.cpp index 3f3673593..87fed599a 100644 --- a/test/algorithms/buffer/buffer_linestring.cpp +++ b/test/algorithms/buffer/buffer_linestring.cpp @@ -93,6 +93,10 @@ static std::string const mysql_report_2015_06_11 = "LINESTRING(" "-162.7456296900030000 11.7183989853218000, 115.6208648232840000 " "51.0941612539320000, -48.7772321835054000 50.4339743128205000)"; +static std::string const mysql_report_2015_09_08a = "LINESTRING(1 1, 2 1, 1.765258e+308 4, -1 1, 10 4)"; +static std::string const mysql_report_2015_09_08b = "LINESTRING(2199023255556 16777218, 32770 8194, 1.417733e+308 7.823620e+307, -8 -9, 2147483649 20)"; +static std::string const mysql_report_2015_09_08c = "LINESTRING(-5 -8, 2 8, 2.160023e+307 1.937208e+307, -4 -3, -5 -4, 8796093022208 281474976710653)"; + template void test_all() { @@ -270,6 +274,12 @@ void test_all() mysql_report_2015_06_11, join_round32, end_round32, 27862.733459829971, 5.9518403867035365); + +#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS) + test_one("mysql_report_2015_09_08a", mysql_report_2015_09_08a, join_round32, end_round32, 0.0, 1.0); + test_one("mysql_report_2015_09_08b", mysql_report_2015_09_08b, join_round32, end_round32, 0.0, 1099511627778.0); + test_one("mysql_report_2015_09_08c", mysql_report_2015_09_08c, join_round32, end_round32, 0.0, 0xbe); +#endif } template diff --git a/test/algorithms/buffer/buffer_multi_linestring.cpp b/test/algorithms/buffer/buffer_multi_linestring.cpp index 11b191547..6501d131a 100644 --- a/test/algorithms/buffer/buffer_multi_linestring.cpp +++ b/test/algorithms/buffer/buffer_multi_linestring.cpp @@ -32,6 +32,9 @@ static std::string const mikado4 = "MULTILINESTRING((-15 2,-15 -17,-6 11,-1.9358 static std::string const mysql_2015_04_10a = "MULTILINESTRING((-58 19, 61 88),(1.922421e+307 1.520384e+308, 15 42, 89 -93,-89 -22),(-63 -5, -262141 -536870908, -3 87, 77 -69))"; static std::string const mysql_2015_04_10b = "MULTILINESTRING((-58 19, 61 88), (-63 -5, -262141 -536870908, -3 87, 77 -69))"; +static std::string const mysql_2015_09_08a = "MULTILINESTRING((7 -4, -3 -5), (72057594037927936 15, 72057594037927940 70368744177660, 32771 36028797018963964, 8589934589 2305843009213693953, 7 2, 9.300367e+307 9.649737e+307, -4092 -274877906946, 5 10, -3 4))"; +static std::string const mysql_2015_09_08b = "MULTILINESTRING((-9 -10, 0 -1, 5 -10, -6 7, -7 7, 5.041061e+307 9.926906e+307, 6.870356e+307 1.064454e+307, 35184372088830 288230376151711743, 183673728842483250000000000000000000000.000000 244323751784861950000000000000000000000.000000), (-23530 -7131, -6 1, 1 1, 2 -6, 32766 -4194302, -4 -6), (134217725 0, 50336782742294697000000000000000000000.000000 36696596077212901000000000000000000000.000000, 7434 16486, 3.025467e+307 8.926790e+307), (2147483646 67108868, 71328904281592545000000000000000000000.000000 225041650340452780000000000000000000000.000000, -7 4, 1.667154e+307 3.990414e+307))"; + template void test_all() { @@ -96,7 +99,7 @@ void test_all() test_one("mikado1_small", mikado1, join_round32, end_round32, 1057.37, 10.0); test_one("mikado1_small", mikado1, join_round32, end_flat, 874.590, 10.0); - test_one("mikado2_large", mikado2, join_round32, end_round32, 19878812253, 79610.0, same_distance, true, mikado_tolerance); + test_one("mikado2_large", mikado2, join_round32, end_round32, 19878812253, 79610.0, same_distance, true, 10 * mikado_tolerance); test_one("mikado2_small", mikado2, join_round32, end_round32, 1082.470, 10.0); test_one("mikado2_small", mikado2, join_round32, end_flat, 711.678, 10.0); @@ -104,7 +107,7 @@ void test_all() // msvc 29151950611 // clang/linux 29151950612 // mingw 29151950711 - test_one("mikado3_large", mikado3, join_round32, end_round32, 29151950650, 96375.0, same_distance, true, 3 * mikado_tolerance); + test_one("mikado3_large", mikado3, join_round32, end_round32, 29151950650, 96375.0, same_distance, true, 10 * mikado_tolerance); test_one("mikado3_small", mikado3, join_round32, end_round32, 2533.285, 10.0); test_one("mikado3_small", mikado3, join_round32, end_flat, 2136.236, 10.0); @@ -125,6 +128,17 @@ void test_all() test_one("mysql_2015_04_10a", mysql_2015_04_10a, join_round32, end_round32, 1063005187.214, 0.98); test_one("mysql_2015_04_10b", mysql_2015_04_10b, join_round32, end_round32, 1063005187.214, 0.98); #endif + + // Two other cases with inf for length calculation (tolerance quite high + // because the output area is quite high and varies between gcc/clang) + test_one("mysql_2015_09_08a", + mysql_2015_09_08a, join_round32, end_round32, + 5.12436196736438764e+19, 4051744443.0, + same_distance, true, 1.0e12); + test_one("mysql_2015_09_08b", + mysql_2015_09_08b, join_round32, end_round32, + 1.32832149026508268e+19, 2061380362.0, + same_distance, true, 1.0e12); } diff --git a/test/algorithms/buffer/buffer_polygon.cpp b/test/algorithms/buffer/buffer_polygon.cpp index 8db5c2cbd..31a91d024 100644 --- a/test/algorithms/buffer/buffer_polygon.cpp +++ b/test/algorithms/buffer/buffer_polygon.cpp @@ -570,7 +570,8 @@ void test_all() test_one("mysql_report_2015_07_05_1", mysql_report_2015_07_05_1, join_round32, end_round32, 2.07548405999982264e+19, 6); test_one("mysql_report_2015_07_05_2", mysql_report_2015_07_05_2, - join_round32, end_round32, 9.48681585720922691e+23, 549755813889); + join_round32, end_round32, 9.48681585720922691e+23, 549755813889, + same_distance, true, high_tolerance); test_one("mysql_report_2015_07_05_3", mysql_report_2015_07_05_3, join_round32, end_round32, 6.10005339242509925e+22, 49316, same_distance, false, high_tolerance); @@ -578,7 +579,8 @@ void test_all() join_round32, end_round32, 4.25405937213774089e+23, 1479986, same_distance, false, high_tolerance); test_one("mysql_report_2015_07_05_5", mysql_report_2015_07_05_5, - join_round32, end_round32, 644489321051.62439, 38141); + join_round32, end_round32, 644489321051.62439, 38141, + same_distance, false, 10000.0); } } diff --git a/test/algorithms/buffer/test_buffer_svg.hpp b/test/algorithms/buffer/test_buffer_svg.hpp index 82a04583e..4940f6b24 100644 --- a/test/algorithms/buffer/test_buffer_svg.hpp +++ b/test/algorithms/buffer/test_buffer_svg.hpp @@ -131,6 +131,8 @@ private : color = 'b'; is_good = false; break; + default: + ; // to avoid "enumeration value not handled" warning } if (!it->selectable_start) { diff --git a/test/algorithms/distance/distance_pointlike_linear.cpp b/test/algorithms/distance/distance_pointlike_linear.cpp index ad22bf120..3ab390bde 100644 --- a/test/algorithms/distance/distance_pointlike_linear.cpp +++ b/test/algorithms/distance/distance_pointlike_linear.cpp @@ -226,6 +226,19 @@ void test_distance_multipoint_multilinestring(Strategy const& strategy) tester::apply("multipoint(0 0,1 0,0 1,1 1)", "multilinestring((4 4,5 5),(),(3 3))", sqrt(8.0), 8, strategy); + + // 21890717 - assertion failure in distance(Pt, Box) + { + multi_point_type mpt; + bg::read_wkt("multipoint(1 1,1 1,1 1,1 1,1 1,1 1,1 1,1 1,1 1)", mpt); + multi_linestring_type mls; + linestring_type ls; + point_type pt(std::numeric_limits::quiet_NaN(), 1.0); + ls.push_back(pt); + ls.push_back(pt); + mls.push_back(ls); + bg::distance(mpt, mls); + } } //=========================================================================== diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index 7ec61eece..60dbd4883 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -713,6 +713,67 @@ inline void test_open_polygons() 0.7808688094430304 -0.6246950475544243,\ 0.7808688094430304 -0.6246950475544243))", AllowDuplicates); + + + // MySQL report on Sep 30, 2015 + test::apply + ("pg077", + "POLYGON((72.8714768817168 -167.0048853643874,9274.40641550926 3433.5957427942167,-58.09039811390054 187.50989457746405,-81.09039811390053 179.50989457746405,-207.99999999999997 135.36742435621204,-208 1,-208 0,-208 -276.9111154485375,49.8714768817168 -176.0048853643874))", + true); + + test::apply("pg077-simplified", + "POLYGON((-200 0,-207.99999999999997 135.36742435621204,-208 1,-208 0,-208 -276.9111154485375))", + true); + + test::apply + ("pg078", + "POLYGON((0 10,-10 0,0 0,10 0))", + true); + + test::apply + ("pg078spike1", + "POLYGON((0 10,-10 0,0 0,-10 0,10 0))", + false); + + test::apply + ("pg078spike2", + "POLYGON((0 10,-10 0,0 0,-8 0,10 0))", + false); + + test::apply + ("pg078spike3", + "POLYGON((0 10,-10 0,0 0,-11 0,10 0))", + false); + + test::apply + ("pg078reversed", + "POLYGON((0 10,10 0,0 0,-10 0))", + false); + + test::apply + ("pg079", + "POLYGON((10 0,0 10,0 0,0 -10))", + true); + + test::apply + ("pg079spike1", + "POLYGON((10 0,0 10,0 0,0 10,0 -10))", + false); + + test::apply + ("pg079spike2", + "POLYGON((10 0,0 10,0 0,0 8,0 -10))", + false); + + test::apply + ("pg079spike3", + "POLYGON((10 0,0 10,0 0,0 11,0 -10))", + false); + + test::apply + ("pg079reversed", + "POLYGON((10 0,0 -10,0 0,0 10))", + false); } template diff --git a/test/algorithms/num_geometries_multi.cpp b/test/algorithms/num_geometries_multi.cpp index 292e06ea9..9c18a9618 100644 --- a/test/algorithms/num_geometries_multi.cpp +++ b/test/algorithms/num_geometries_multi.cpp @@ -15,11 +15,11 @@ #include template -void test_geometry(std::string const& wkt, int expected) +void test_geometry(std::string const& wkt, std::size_t expected) { Geometry geometry; bg::read_wkt(wkt, geometry); - int detected = bg::num_geometries(geometry); + std::size_t detected = bg::num_geometries(geometry); BOOST_CHECK_MESSAGE(detected == expected, "num_geometries: " << wkt << " -> Expected: " << expected diff --git a/test/algorithms/num_interior_rings_multi.cpp b/test/algorithms/num_interior_rings_multi.cpp index 2f9991fe9..2ad958d81 100644 --- a/test/algorithms/num_interior_rings_multi.cpp +++ b/test/algorithms/num_interior_rings_multi.cpp @@ -15,11 +15,11 @@ #include template -void test_geometry(std::string const& wkt, int expected) +void test_geometry(std::string const& wkt, std::size_t expected) { Geometry geometry; bg::read_wkt(wkt, geometry); - int detected = bg::num_interior_rings(geometry); + std::size_t detected = bg::num_interior_rings(geometry); BOOST_CHECK_MESSAGE(detected == expected, "num_interior_rings: " << wkt << " -> Expected: " << expected diff --git a/test/algorithms/num_points_multi.cpp b/test/algorithms/num_points_multi.cpp index 68b814e32..dd96bf3a4 100644 --- a/test/algorithms/num_points_multi.cpp +++ b/test/algorithms/num_points_multi.cpp @@ -21,9 +21,9 @@ template -void check_geometry(Geometry const& geometry, std::string const& wkt, int expected) +void check_geometry(Geometry const& geometry, std::string const& wkt, std::size_t expected) { - int detected = bg::num_points(geometry); + std::size_t detected = bg::num_points(geometry); BOOST_CHECK_MESSAGE(detected == expected, "num_points: " << wkt << " -> Expected: " << expected diff --git a/test/algorithms/overlay/get_turns.cpp b/test/algorithms/overlay/get_turns.cpp index 90cc08277..4efea8e41 100644 --- a/test/algorithms/overlay/get_turns.cpp +++ b/test/algorithms/overlay/get_turns.cpp @@ -44,7 +44,7 @@ // To test that "get_turns" can be called using additional information template -struct my_turn_op : public bg::detail::overlay::turn_operation +struct my_turn_op : public bg::detail::overlay::turn_operation { }; diff --git a/test/algorithms/overlay/get_turns_linear_linear.cpp b/test/algorithms/overlay/get_turns_linear_linear.cpp index cc7003f8e..1db5ade85 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -285,6 +285,10 @@ void test_all() "LINESTRING(2 8,4 0.4,8 1,0 5)", expected("iuu++")("mui=+")("tiu+=")); +#if ! ( defined(BOOST_CLANG) && defined(BOOST_GEOMETRY_COMPILER_MODE_RELEASE) ) + + // In clang/release mode this testcase gives other results + // assertion failure in 1.57 // FAILING - no assertion failure but the result is not very good test_geometry("LINESTRING(-2305843009213693956 4611686018427387906, -33 -92, 78 83)", @@ -293,6 +297,9 @@ void test_all() test_geometry("LINESTRING(31 -97, -46 57, -20 -4)", "LINESTRING(-2305843009213693956 4611686018427387906, -33 -92, 78 83)", expected("")("")); + +#endif + } // In 1.57 the results of those combinations was different for MinGW @@ -511,6 +518,18 @@ void test_all() test_geometry("MULTILINESTRING((0 0,10 0))", "MULTILINESTRING((2 0,0 0,-1 -1))", expected("tiu+=")("mui=+")); + + // parts of boundaries taken from union A/A buffer_mp1 + if ( BOOST_GEOMETRY_CONDITION((boost::is_same::value)) ) + { + test_geometry("LINESTRING(6.95629520146761 5.415823381635526,6.989043790736545 5.209056926535316,7 5,6.989043790736547 4.790943073464693,6.956295201467611 4.584176618364482)", + "LINESTRING(7.415823381635519 5.043704798532389,7.209056926535308 5.010956209263453,7.000000000000001 5,6.790943073464693 5.010956209263453,6.584176618364483 5.043704798532389)", + expected("tuu++")); + // the above should give the same result as this: + test_geometry("LINESTRING(6.95629520146761 5.415823381635526,6.989043790736545 5.209056926535316,7 5,6.989043790736547 4.790943073464693,6.956295201467611 4.584176618364482)", + "LINESTRING(7.415823381635519 5.043704798532389,7.209056926535308 5.010956209263453,7 5,6.790943073464693 5.010956209263453,6.584176618364483 5.043704798532389)", + expected("tuu++")); + } } int test_main(int, char* []) diff --git a/test/algorithms/overlay/multi_overlay_cases.hpp b/test/algorithms/overlay/multi_overlay_cases.hpp index c44b17adb..fb9dd8b82 100644 --- a/test/algorithms/overlay/multi_overlay_cases.hpp +++ b/test/algorithms/overlay/multi_overlay_cases.hpp @@ -380,6 +380,13 @@ static std::string case_recursive_boxes_4[2] = "MULTIPOLYGON(((1 0,2 1,2 0,1 0)),((7 9,7 10,8 10,7 9)),((1 0,0 0,0 3,1 3,2 2,2 3,1 3,1 4,2 4,2 5,1 4,0 4,0 8,1 7,1 6,2 7,1 7,1 9,0 9,0 10,7 10,6 9,6.5 8.5,7 9,8 9,9 8,8 8,9 7,9 6,10 7,10 5,9 5,9 4,10 5,10 0,7 0,8 1,7 1,6 0,3 0,3 1,1 1,1 0),(5 1,5.5 0.5,6 1,6 2,6.5 1.5,7 2,8 2,8 4,7 3,6 3,6 2,5 2,6 1,5 1),(4 4,5 4,5 5,4 4),(4 6,4 7,3 7,2 6,3 6,3 7,4 6),(6 5,6.5 4.5,7 5,6 5,7 6,7 7,6 7,6 5),(3.5 7.5,4 8,4 9,3 8,3.5 7.5)),((9 8,9 9,8 9,9 10,10 10,10 8,9 8)))" }; +static std::string case_recursive_boxes_5[2] = +{ + // Occurs after refactoring uu / handle_touch (not yet integrated) + "MULTIPOLYGON(((0 9,0 10,1 10,1 9,0 9)),((9 0,9 1,10 1,10 0,9 0)),((5 6,5 7,6 7,6 6,7 6,7 4,6 4,6 5,5 5,5 6)),((5 3,7 3,7 2,4 2,4 3,5 3)),((5 8,5 9,7 9,7 8,5 8)),((4 0,1 0,1 1,5 1,5 0,4 0)),((3 5,3 4,4 4,4 3,2 3,2 2,1 2,1 3,0 3,0 4,2 4,2 5,1 5,1 6,4 6,4 5,3 5)),((0 2,1 2,1 1,0 1,0 2)),((4 10,4 7,1 7,1 6,0 6,0 8,1 8,1 9,2 9,2 10,4 10)),((9 4,9 3,8 3,8 5,9 5,9 4)),((7 2,8 2,8 0,7 0,7 2)),((8 7,10 7,10 6,7 6,7 8,8 8,8 7)))", + "MULTIPOLYGON(((2 3,2 4,3 4,3 3,2 3)),((1 5,1 6,2 6,2 5,1 5)),((2 1,2 2,3 2,3 1,2 1)),((8 1,9 1,9 0,8 0,8 1)),((9 7,10 7,10 6,9 6,9 7)),((1 4,1 3,0 3,0 5,1 5,1 4)),((7 6,7 7,8 7,8 6,7 6)),((7 1,7 2,8 2,8 1,7 1)),((6 2,6 3,7 3,7 2,6 2)),((6 8,6 9,7 9,7 8,6 8)),((5 0,3 0,3 1,4 1,4 2,6 2,6 1,7 1,7 0,5 0)),((5 5,5 6,6 6,6 5,8 5,8 6,9 6,9 4,8 4,8 3,7 3,7 4,6 4,6 3,5 3,5 4,3 4,3 6,2 6,2 8,3 8,3 7,5 7,5 6,4 6,4 5,5 5)),((1 1,2 1,2 0,1 0,1 1)),((1 3,2 3,2 2,1 2,1 3)),((3 10,4 10,4 9,2 9,2 8,0 8,0 10,3 10)),((10 3,10 1,9 1,9 2,8 2,8 3,9 3,9 4,10 4,10 3)),((9 9,10 9,10 8,9 8,9 7,8 7,8 10,9 10,9 9)))" +}; + static std::string pie_21_7_21_0_3[2] = { "MULTIPOLYGON(((2500 2500,2500 3875,2855 3828,3187 3690,3472 3472,3690 3187,3828 2855,3875 2500,3828 2144,3690 1812,3472 1527,3187 1309,2855 1171,2499 1125,2144 1171,1812 1309,1527 1527,1309 1812,1171 2144,1125 2499,1171 2855,1309 3187,2500 2500)))", diff --git a/test/algorithms/overlay/self_intersection_points.cpp b/test/algorithms/overlay/self_intersection_points.cpp index 9825018bf..d6471ff04 100644 --- a/test/algorithms/overlay/self_intersection_points.cpp +++ b/test/algorithms/overlay/self_intersection_points.cpp @@ -44,7 +44,7 @@ template static void test_self_intersection_points(std::string const& case_id, - int expected_count, + std::size_t expected_count, Geometry const& geometry, bool check_has_intersections, double /*precision*/ = 0.001) @@ -84,7 +84,7 @@ static void test_self_intersection_points(std::string const& case_id, x += bg::get<0>(turn.point); y += bg::get<1>(turn.point); } - int n = boost::size(turns); + std::size_t n = boost::size(turns); if (n > 0) { x /= n; diff --git a/test/algorithms/relational_operations/covered_by.cpp b/test/algorithms/relational_operations/covered_by.cpp index 15031487a..351efaad8 100644 --- a/test/algorithms/relational_operations/covered_by.cpp +++ b/test/algorithms/relational_operations/covered_by.cpp @@ -1,7 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, 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 @@ -145,6 +150,7 @@ int test_main( int , char* [] ) #if defined(HAVE_TTMATH) test_all >(); + test_eps >(); //test_spherical > >(); #endif diff --git a/test/algorithms/relational_operations/disjoint/disjoint_point_box_geometry.cpp b/test/algorithms/relational_operations/disjoint/disjoint_point_box_geometry.cpp index f1de2de0e..37fb8b15a 100644 --- a/test/algorithms/relational_operations/disjoint/disjoint_point_box_geometry.cpp +++ b/test/algorithms/relational_operations/disjoint/disjoint_point_box_geometry.cpp @@ -111,9 +111,11 @@ void test_3d() } + int test_main(int, char* []) { test_all >(); + test_all >(); #ifdef HAVE_TTMATH @@ -121,7 +123,6 @@ int test_main(int, char* []) #endif test_3d >(); - - + return 0; } diff --git a/test/algorithms/relational_operations/intersects/intersects_box_geometry.cpp b/test/algorithms/relational_operations/intersects/intersects_box_geometry.cpp index 50a332436..7c40efc3c 100644 --- a/test/algorithms/relational_operations/intersects/intersects_box_geometry.cpp +++ b/test/algorithms/relational_operations/intersects/intersects_box_geometry.cpp @@ -80,6 +80,30 @@ void test_additional() "LINESTRING(1 2)", "BOX(0 0,3 5)", true); + + // http://stackoverflow.com/questions/32457920/boost-rtree-of-box-gives-wrong-intersection-with-segment + // http://lists.boost.org/geometry/2015/09/3476.php + // For now disabled by default even though it works properly on MSVC14 + // it's probable that the result depends on the compiler +#ifdef BOOST_GEOMETRY_ENABLE_FAILING_TESTS + test_geometry, bg::model::box

>( + "SEGMENT(12 0,20 10)", + "BOX(0 0,10 10)", + false); + test_geometry, bg::model::box

>( + "SEGMENT(2 0,8 6)", + "BOX(0 0,10 10)", + true); + test_geometry, bg::model::box

>( + "SEGMENT(2 0,18 8)", + "BOX(0 0,10 10)", + true); + typedef bg::model::point::type, 3, bg::cs::cartesian> point3d_t; + test_geometry, bg::model::box >( + "SEGMENT(2 1 0,2 1 10)", + "BOX(0 0 0,10 0 10)", + false); +#endif } diff --git a/test/algorithms/relational_operations/nan_cases.hpp b/test/algorithms/relational_operations/nan_cases.hpp new file mode 100644 index 000000000..d6acbd6c9 --- /dev/null +++ b/test/algorithms/relational_operations/nan_cases.hpp @@ -0,0 +1,130 @@ +// Boost.Geometry + +// Copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#include +#include + +#include +#include + +template +struct pusher + : public Container +{ + typedef typename Container::value_type value_type; + pusher(value_type const& val) + { + this->push_back(val); + } + + pusher & operator()(value_type const& val) + { + this->push_back(val); + return *this; + } +}; + +template ::type, + typename Coord = typename bg::coordinate_type::type> +struct nan_case_generator +{ + static void apply(Geometry & , std::string & ) + {} +}; + +template +struct nan_case_generator +{ + static void apply(Geometry & geometry, std::string & wkt) + { + typedef typename boost::range_value::type ls; + typedef typename bg::point_type::type P; + typedef typename bg::coordinate_type::type coord_t; + coord_t nan = std::numeric_limits::quiet_NaN(); + + wkt = "MULTILINESTRING((3.1e+307 1,-nan -nan),(3.1e+307 1,-nan -nan),(3.1e+307 1,5.1e+307 6e+307,nan nan),(-nan -nan,nan nan),(-nan -nan,-1 -3.97843,-1 3.28571,-1 47.6364),(3 78.5455,3 2),(nan nan,3 12.9689),(3 -2,-nan -nan),(3 2,3 12.9689,3 78.5455),(-1 4.29497e+09,-1 7,-nan -nan),(9 5,-nan -nan),(-nan -nan,9 60.8755,9 124.909),(nan nan,1 6.87195e+10,-nan -nan),(nan nan,4 86.2727,4 20.9533),(4 -5,-nan -nan),(4 -5,-nan -nan),(4 -5,-nan -nan),(4 -5,1.1e+308 2.1e+307,nan nan),(-nan -nan,-1 -8),(-nan -nan,-9 -4))"; + + typedef pusher ml; + typedef pusher l; + geometry = ml(l(P(3.1e+307, 1))(P(-nan, -nan))) + (l(P(3.1e+307, 1))(P(-nan, -nan))) + (l(P(3.1e+307, 1))(P(5.1e+307, 6e+307))(P(nan, nan))) + (l(P(-nan, -nan))(P(nan, nan))) + (l(P(-nan, -nan))(P(-1, -3.97843))(P(-1, 3.28571))(P(-1, 47.6364))) + (l(P(3, 78.5455))(P(3, 2))) + (l(P(nan, nan))(P(3, 12.9689))) + (l(P(3, -2))(P(-nan, -nan))) + (l(P(3, 2))(P(3, 12.9689))(P(3, 78.5455))) + (l(P(-1, 4.29497e+09))(P(-1, 7))(P(-nan, -nan))) + (l(P(9, 5))(P(-nan, -nan))) + (l(P(-nan, -nan))(P(9, 60.8755))(P(9, 124.909))) + (l(P(nan, nan))(P(1, 6.87195e+10))(P(-nan, -nan))) + (l(P(nan, nan))(P(4, 86.2727))(P(4, 20.9533))) + (l(P(4, -5))(P(-nan, -nan))) + (l(P(4, -5))(P(-nan, -nan))) + (l(P(4, -5))(P(-nan, -nan))) + (l(P(4, -5))(P(1.1e+308, 2.1e+307))(P(nan, nan))) + (l(P(-nan, -nan))(P(-1, -8))) + (l(P(-nan, -nan))(P(-9, -4))); + } +}; + +template +struct nan_case_generator +{ + static void apply(Geometry & geometry, std::string & wkt) + { + typedef typename bg::point_type::type P; + typedef typename bg::coordinate_type::type coord_t; + coord_t nan = std::numeric_limits::quiet_NaN(); + + wkt = "MULTIPOINT((3.1e+307 1),(-nan -nan),(3.1e+307 1),(-nan -nan),(3.1e+307 1),(5.1e+307 6e+307),(nan nan),(-nan -nan),(nan nan),(-nan -nan),(-1 -3.97843),(-1 3.28571),(-1 47.6364),(3 78.5455),(3 2),(nan nan),(3 12.9689),(3 -2),(-nan -nan),(3 2),(3 12.9689),(3 78.5455),(-1 4.29497e+09),(-1 7),(-nan -nan),(9 5),(-nan -nan),(-nan -nan),(9 60.8755),(9 124.909),(nan nan),(1 6.87195e+10),(-nan -nan),(nan nan),(4 86.2727),(4 20.9533),(4 -5),(-nan -nan),(4 -5),(-nan -nan),(4 -5),(-nan -nan),(4 -5),(1.1e+308 2.1e+307),(nan nan),(-nan -nan),(-1 -8),(-nan -nan),(-9 -4))"; + + typedef pusher mp; + geometry = mp(P(3.1e+307, 1))(P(-nan, -nan)) + (P(3.1e+307, 1))(P(-nan, -nan)) + (P(3.1e+307, 1))(P(5.1e+307, 6e+307))(P(nan, nan)) + (P(-nan, -nan))(P(nan, nan)) + (P(-nan, -nan))(P(-1, -3.97843))(P(-1, 3.28571))(P(-1, 47.6364)) + (P(3, 78.5455))(P(3, 2)) + (P(nan, nan))(P(3, 12.9689)) + (P(3, -2))(P(-nan, -nan)) + (P(3, 2))(P(3, 12.9689))(P(3, 78.5455)) + (P(-1, 4.29497e+09))(P(-1, 7))(P(-nan, -nan)) + (P(9, 5))(P(-nan, -nan)) + (P(-nan, -nan))(P(9, 60.8755))(P(9, 124.909)) + (P(nan, nan))(P(1, 6.87195e+10))(P(-nan, -nan)) + (P(nan, nan))(P(4, 86.2727))(P(4, 20.9533)) + (P(4, -5))(P(-nan, -nan)) + (P(4, -5))(P(-nan, -nan)) + (P(4, -5))(P(-nan, -nan)) + (P(4, -5))(P(1.1e+308, 2.1e+307))(P(nan, nan)) + (P(-nan, -nan))(P(-1, -8)) + (P(-nan, -nan))(P(-9, -4)); + } +}; + +template +void nan_case(Geometry & geometry, std::string & wkt) +{ + nan_case_generator::apply(geometry, wkt); +} + +template +struct is_nan_case_supported +{ + typedef typename bg::coordinate_type::type coord_t; + + static const bool value = boost::is_same::value + && std::numeric_limits::has_quiet_NaN; +}; \ No newline at end of file diff --git a/test/algorithms/relational_operations/overlaps/overlaps_areal.cpp b/test/algorithms/relational_operations/overlaps/overlaps_areal.cpp index c41da0639..c7361f203 100644 --- a/test/algorithms/relational_operations/overlaps/overlaps_areal.cpp +++ b/test/algorithms/relational_operations/overlaps/overlaps_areal.cpp @@ -44,6 +44,14 @@ void test_aa() test_geometry("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((0 0,0 -10,-10 -10,-10 0,0 0)))", "POLYGON((0 0,0 10,10 10,10 0,0 0))", false); + + // mysql 21872795 + test_geometry("POLYGON((2 2,2 8,8 8,8 2,2 2))", + "POLYGON((0 0,0 10,10 10,10 0,0 0),(8 8,4 6,4 4,8 8))", + true); + test_geometry("POLYGON((2 2,2 8,8 8,8 2,2 2))", + "POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 4,4 6,2 2))", + true); } template diff --git a/test/algorithms/relational_operations/overlaps/overlaps_box.cpp b/test/algorithms/relational_operations/overlaps/overlaps_box.cpp index c80ff6de4..b58cfa967 100644 --- a/test/algorithms/relational_operations/overlaps/overlaps_box.cpp +++ b/test/algorithms/relational_operations/overlaps/overlaps_box.cpp @@ -43,6 +43,7 @@ void test_3d() test_geometry, bg::model::box

>("BOX(1 1 1, 3 3 3)", "BOX(4 4 4,6 6 6)", false); } + template void test_2d() { diff --git a/test/algorithms/relational_operations/overlaps/test_overlaps.hpp b/test/algorithms/relational_operations/overlaps/test_overlaps.hpp index 862fe7389..c631ae715 100644 --- a/test/algorithms/relational_operations/overlaps/test_overlaps.hpp +++ b/test/algorithms/relational_operations/overlaps/test_overlaps.hpp @@ -2,6 +2,12 @@ // Unit Test // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, 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 // http://www.boost.org/LICENSE_1_0.txt) @@ -22,15 +28,12 @@ template -void test_geometry(std::string const& wkt1, - std::string const& wkt2, bool expected) +void test_geometry(Geometry1 const& geometry1, + Geometry2 const& geometry2, + std::string const& wkt1, + std::string const& wkt2, + bool expected) { - Geometry1 geometry1; - Geometry2 geometry2; - - bg::read_wkt(wkt1, geometry1); - bg::read_wkt(wkt2, geometry2); - bool detected = bg::overlaps(geometry1, geometry2); BOOST_CHECK_MESSAGE(detected == expected, @@ -48,5 +51,19 @@ void test_geometry(std::string const& wkt1, << " detected: " << detected); } +template +void test_geometry(std::string const& wkt1, + std::string const& wkt2, + bool expected) +{ + Geometry1 geometry1; + Geometry2 geometry2; + + bg::read_wkt(wkt1, geometry1); + bg::read_wkt(wkt2, geometry2); + + test_geometry(geometry1, geometry2, wkt1, wkt2, expected); +} + #endif diff --git a/test/algorithms/relational_operations/relate/relate_areal_areal.cpp b/test/algorithms/relational_operations/relate/relate_areal_areal.cpp index 9a2b41aaf..81ced941e 100644 --- a/test/algorithms/relational_operations/relate/relate_areal_areal.cpp +++ b/test/algorithms/relational_operations/relate/relate_areal_areal.cpp @@ -343,6 +343,25 @@ void test_polygon_polygon() "POLYGON((1 1,1 2,2 2,2 1,1 1))", "****F****");*/ } + + // mysql 21872795 (overlaps) + test_geometry("POLYGON((2 2,2 8,8 8,8 2,2 2))", + "POLYGON((0 0,0 10,10 10,10 0,0 0),(8 8,4 6,4 4,8 8))", + "21210F212"); + test_geometry("POLYGON((2 2,2 8,8 8,8 2,2 2))", + "POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 4,4 6,2 2))", + "21210F212"); + // mysql 21873343 (touches) + test_geometry("POLYGON((0 0,0 10,10 10,10 0,0 0), (0 8, 8 5, 8 8, 0 8))", + "POLYGON((0 8,-8 5,-8 8,0 8))", + "FF2F01212"); + test_geometry("POLYGON((0 0,0 10,10 10,10 0,0 0), (0 6, 6 3, 6 6, 0 6))", + "POLYGON((0 6,-6 3,-6 6,0 6))", + "FF2F01212"); + // similar but touching from the inside of the hole + test_geometry("POLYGON((0 0,0 10,10 10,10 0,0 0), (0 8, 8 5, 8 8, 0 8))", + "POLYGON((0 8,7 7, 7 6,0 8))", + "FF2F01212"); } template diff --git a/test/algorithms/relational_operations/relate/relate_linear_areal.cpp b/test/algorithms/relational_operations/relate/relate_linear_areal.cpp index fbd399f01..a53e388fa 100644 --- a/test/algorithms/relational_operations/relate/relate_linear_areal.cpp +++ b/test/algorithms/relational_operations/relate/relate_linear_areal.cpp @@ -12,6 +12,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include "test_relate.hpp" +#include "../nan_cases.hpp" //TEST //#include @@ -381,6 +382,7 @@ void test_multi_linestring_polygon() typedef bg::model::linestring

ls; typedef bg::model::multi_linestring mls; typedef bg::model::polygon

poly; + typedef typename bg::coordinate_type

::type coord_t; test_geometry("MULTILINESTRING((11 11, 20 20),(5 7, 4 1))", "POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,4 4,2 4,2 2))", @@ -390,7 +392,7 @@ void test_multi_linestring_polygon() "1F10F0212"); if ( BOOST_GEOMETRY_CONDITION(( - boost::is_same::type, double>::value )) ) + boost::is_same::value )) ) { // assertion failure in 1.57 test_geometry("MULTILINESTRING((-0.59322033898305082 -8.0508474576271194,-2.882352941176471 -7.7647058823529411,-2.8823529411764706 -7.7647058823529411,-3.7361111111111112 -6.5694444444444446,-3.4404145077720205 -5.766839378238342,-4.1864406779661012 -3.6779661016949152,-7.5252525252525251 -5.5858585858585865,-7.5862068965517242 -5.1896551724137936,-4.47887323943662 -2.859154929577465,-4.5789473684210531 -2.5789473684210527,-3 -1,-2.9310344827586206 -0.86206896551724144,-3.1764705882352944 -0.70588235294117663,-4.7401960784313726 -2.1274509803921577,-5.3255813953488369 -0.48837209302325502,-4.7872340425531918 0.31914893617021284,-5.8571428571428577 1.0000000000000007,-5.3255813953488369 -0.48837209302325502,-5.9473684210526319 -1.4210526315789465,-8 2,-7.7333333333333334 2.1939393939393939,-8.8294573643410867 2.891472868217055,-8.8556701030927822 3.061855670103093,-7.5999999999999996 3.6000000000000001,-7.7999999999999998 3.7999999999999998,-7.75 3.7916666666666665,-7.5471698113207548 3.6226415094339623,-7.3200000000000003 3.7200000000000002,-3.473684210526315 3.0789473684210527,-3.2549019607843133 3.2156862745098036,-2.9999999999999982 3.1428571428571423,-3.1733333333333325 3.2666666666666666,-2.9180327868852456 3.4262295081967209,-2.8723404255319145 3.1063829787234041,-2.1111111111111112 2.8888888888888888,-2.1428571428571428 2.8571428571428572,-1.8433734939759043 2.8072289156626509,-1.8396226415094346 2.8113207547169816,-1.6486486486486487 2.756756756756757,-1.76510067114094 2.8926174496644301,-0.53846153846153855 4.2307692307692308,1.8148148148148147 5.4074074074074074,1.588235294117647 2.2352941176470589,1.819672131147541 2.1967213114754101,2 4,2 2.1666666666666665,2.3538461538461544 2.1076923076923078,2 1.6875000000000004,2 -2,1.2173913043478262 -3.8260869565217392,1.7375886524822697 1.3758865248226959,1.5073170731707317 1.1024390243902444,1.1428571428571428 -4,-0.59322033898305082 -8.0508474576271194),(1.666666666666667 1.5999999999999988,1.5675675675675675 1.8378378378378377,1.4374999999999991 1.8750000000000002,1.0487804878048776 2.3414634146341466,0.46666666666666712 2.6060606060606055,0.086956521739131043 2.2608695652173911,1.4374999999999991 1.8750000000000002,1.666666666666667 1.5999999999999988))", @@ -422,6 +424,21 @@ void test_multi_linestring_polygon() test_geometry("MULTILINESTRING((3 10, 1 5, 1 10, 3 4, 7 8, 6 10, 10 2))", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "10FF0F212"); + + // mysql bug + // assertion failure in relate->boundary_checker->std::equal_range with msvc + if (BOOST_GEOMETRY_CONDITION(is_nan_case_supported::value)) + { + mls g1; + std::string wkt1; + nan_case(g1, wkt1); + + std::string wkt2 = "POLYGON((1.1e+308 1.2e+308,-1 -9,1 1e+12,1.1e+308 7.8e+307,1.1e+308 1.2e+308),(3 2,1 1,8e+307 1e+308,3 2),(258 2049,1 -3,1 1,-6 9,258 2049))"; + poly g2; + bg::read_wkt(wkt2, g2); + + check_geometry(g1, g2, wkt1, wkt2, "*********"); + } } template diff --git a/test/algorithms/relational_operations/relate/relate_pointlike_geometry.cpp b/test/algorithms/relational_operations/relate/relate_pointlike_geometry.cpp index 95a415865..d06c6b7cb 100644 --- a/test/algorithms/relational_operations/relate/relate_pointlike_geometry.cpp +++ b/test/algorithms/relational_operations/relate/relate_pointlike_geometry.cpp @@ -12,6 +12,7 @@ // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle #include "test_relate.hpp" +#include "../nan_cases.hpp" //TEST //#include @@ -47,6 +48,16 @@ void test_multipoint_multipoint() //typedef bg::model::d2::point_xy ptf; //typedef bg::model::multi_point mptf; //test_geometry("MULTIPOINT(0 0)", "MULTIPOINT(0 0)", "0FFFFFFF2"); + + // assertion failure in relate->boundary_checker->std::equal_range with msvc + if (BOOST_GEOMETRY_CONDITION(is_nan_case_supported::value)) + { + mpt g; + std::string wkt; + nan_case(g, wkt); + + check_geometry(g, g, wkt, wkt, "*********"); + } } template @@ -78,6 +89,27 @@ void test_point_multilinestring() test_geometry("POINT(0 0)", "MULTILINESTRING((0 0,5 0),(0 0,0 5,5 0),(0 0,-5 0),(0 0,0 -5,-5 0))", "0FFFFF1F2"); test_geometry("POINT(5 0)", "MULTILINESTRING((0 0,5 0),(0 0,0 5,5 0),(0 0,-5 0),(0 0,0 -5,-5 0))", "0FFFFF1F2"); test_geometry("POINT(1 0)", "MULTILINESTRING((0 0,5 0),(0 0,0 5,5 0),(0 0,-5 0),(0 0,0 -5,-5 0))", "0FFFFF1F2"); + + // assertion failure in relate->boundary_checker->std::equal_range with msvc + if (BOOST_GEOMETRY_CONDITION(is_nan_case_supported::value)) + { + // on the boundary + std::string wkt0 = "POINT(3.1e+307 1)"; + P g0; + bg::read_wkt(wkt0, g0); + + // disjoint + std::string wkt1 = "POINT(1.1e+308 1.2e+308)"; + P g1; + bg::read_wkt(wkt1, g1); + + mls g2; + std::string wkt2; + nan_case(g2, wkt2); + + check_geometry(g0, g2, wkt0, wkt2, "*********"); + check_geometry(g1, g2, wkt1, wkt2, "*********"); + } } template diff --git a/test/algorithms/relational_operations/touches/test_touches.hpp b/test/algorithms/relational_operations/touches/test_touches.hpp index 60df672c5..2bc0db86d 100644 --- a/test/algorithms/relational_operations/touches/test_touches.hpp +++ b/test/algorithms/relational_operations/touches/test_touches.hpp @@ -1,10 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// 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, 2015. +// Modifications copyright (c) 2013, 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, 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 @@ -43,8 +45,8 @@ void check_touches(Geometry1 const& geometry1, detected = bg::touches(geometry2, geometry1); BOOST_CHECK_MESSAGE(detected == expected, - "touches: " << wkt2 - << " with " << wkt1 + "touches: " << wkt1 + << " with " << wkt2 << " -> Expected: " << expected << " detected: " << detected); } diff --git a/test/algorithms/relational_operations/touches/touches.cpp b/test/algorithms/relational_operations/touches/touches.cpp index 88a0cc269..536250cee 100644 --- a/test/algorithms/relational_operations/touches/touches.cpp +++ b/test/algorithms/relational_operations/touches/touches.cpp @@ -118,6 +118,20 @@ void test_all() true ); + // mysql 21873343 + test_touches + ( + "POLYGON((0 0,0 10,10 10,10 0,0 0), (0 8, 8 5, 8 8, 0 8))", + "POLYGON((0 8,-8 5,-8 8,0 8))", + true + ); + test_touches + ( + "POLYGON((0 0,0 10,10 10,10 0,0 0), (0 6, 6 3, 6 6, 0 6))", + "POLYGON((0 6,-6 3,-6 6,0 6))", + true + ); + // Point-Polygon test_touches("POINT(40 50)", "POLYGON((40 40,40 60,60 60,60 40,40 40))", true); test_touches("POINT(40 50)", "POLYGON((40 40,40 60,60 60,60 40,40 40))", true); diff --git a/test/algorithms/relational_operations/touches/touches_box.cpp b/test/algorithms/relational_operations/touches/touches_box.cpp index 4e8b932f1..7325bc2c2 100644 --- a/test/algorithms/relational_operations/touches/touches_box.cpp +++ b/test/algorithms/relational_operations/touches/touches_box.cpp @@ -2,7 +2,7 @@ // // Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014. 2015. +// This file was modified by Oracle on 2013, 2014, 2015. // Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -42,6 +42,7 @@ void test_box_3d() true); } + int test_main( int , char* [] ) { test_all >(); diff --git a/test/algorithms/relational_operations/within/within.cpp b/test/algorithms/relational_operations/within/within.cpp index c8999e4db..11e86b46d 100644 --- a/test/algorithms/relational_operations/within/within.cpp +++ b/test/algorithms/relational_operations/within/within.cpp @@ -6,12 +6,12 @@ // This file was modified by Oracle on 2014, 2015. // Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, 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 // http://www.boost.org/LICENSE_1_0.txt) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #include "test_within.hpp" diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index 1e6a23c2a..8b9297322 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -7,6 +7,7 @@ // Modifications copyright (c) 2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, 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 @@ -86,6 +87,81 @@ void test_areal_linear() test_one_lp("case25", "LINESTRING(4 0,4 5,7 5)", poly_9, 2, 5, 5.0); test_one_lp("case26", "LINESTRING(4 0,4 3,4 5,7 5)", poly_9, 2, 5, 5.0); test_one_lp("case27", "LINESTRING(4 4,4 5,5 5)", poly_9, 1, 3, 2.0); + + test_one_lp("case28", + "LINESTRING(-1.3 0,-15 0,-1.3 0)", + "POLYGON((2 3,-9 -7,12 -13,2 3))", + 1, 3, 27.4); + + test_one_lp("case29", + "LINESTRING(5 5,-10 5,5 5)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 1, 3, 20); + + test_one_lp("case29a", + "LINESTRING(1 1,5 5,-10 5,5 5,6 6)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 1, 3, 20); + + test_one_lp("case30", + "LINESTRING(-10 5,5 5,-10 5)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 2, 4, 20); + + test_one_lp("case30a", + "LINESTRING(-20 10,-10 5,5 5,-10 5,-20 -10)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 2, 6, 49.208096); + + test_one_lp("case31", + "LINESTRING(0 5,5 5,0 5)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 0, 0, 0); + + test_one_lp("case31", + "LINESTRING(0 5,5 5,1 1,9 1,5 5,0 5)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 0, 0, 0); + + test_one_lp("case32", + "LINESTRING(5 5,0 5,5 5)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 0, 0, 0); + + test_one_lp("case32a", + "LINESTRING(-10 10,5 5,0 5,5 5,20 10)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 2, 4, 21.081851); + + test_one_lp("case33", + "LINESTRING(-5 5,0 5,-5 5)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 1, 3, 10); + + test_one_lp("case33a", + "LINESTRING(-10 10,-5 5,0 5,-5 5,-10 -10)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 1, 5, 32.882456); + + test_one_lp("case33b", + "LINESTRING(0 5,-5 5,0 5)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 1, 3, 10); + + test_one_lp("case34", + "LINESTRING(5 5,0 5,5 5,5 4,0 4,5 4)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 0, 0, 0); + + test_one_lp("case35", + "LINESTRING(5 5,0 5,5 5,5 4,0 4,5 3)", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + 0, 0, 0); + + test_one_lp("case36", + "LINESTRING(-1 -1,10 10)", + "POLYGON((5 5,15 15,15 5,5 5))", + 1, 2, 6 * std::sqrt(2.0)); } template @@ -599,6 +675,21 @@ void test_all() 5, 22, 1.1901714, 5, 27, 1.6701714); ***/ + +#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING + test_one("ticket_11725_2", + "POLYGON((0 0,0 3,3 3,3 0,0 0))", + "POLYGON((3 1,1 1,1 2,2 2,3 1))", + 2, -1, 7.5, 0, -1, 0.0); + test_one("mysql_21977775", + "POLYGON((8 6,5 7,-1 4,-8 -7, 0 -17, 8 6), (3 6, 5 5, 0 -2, 3 6))", + "POLYGON((3 3,-17 11,-8 -3, 3 3))", + 2, -1, 160.856568913, 2, -1, 92.3565689126); + test_one("mysql_21965285", + "POLYGON((7 3,0 10,0 -6, 9 -5, 7 7, 7 3), (0 8, 2 3, 2 -2, 0 8))", + "POLYGON((0 6,0 8,-14 13,0 6))", + 0, -1, 0.0, 0, -1, 0.0); +#endif } /******* diff --git a/test/algorithms/set_operations/difference/difference_linear_linear.cpp b/test/algorithms/set_operations/difference/difference_linear_linear.cpp index e08166658..701ec4612 100644 --- a/test/algorithms/set_operations/difference/difference_linear_linear.cpp +++ b/test/algorithms/set_operations/difference/difference_linear_linear.cpp @@ -553,7 +553,7 @@ BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring ) from_wkt("LINESTRING(0 -.2, 8 1)"), from_wkt("MULTILINESTRING((4 .4,2 8))"), "lldf31x", - 4.0 * std::numeric_limits::epsilon() + 1e-10 ); tester::apply @@ -561,7 +561,7 @@ BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring ) from_wkt("LINESTRING(0 -.2, 8 1)"), from_wkt("MULTILINESTRING((2 8,4 .4))"), "lldf31x-r", - 4.0 * std::numeric_limits::epsilon() + 1e-10 ); tester::apply diff --git a/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp b/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp index 4245f8306..258d5cfb4 100644 --- a/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp +++ b/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp @@ -64,6 +64,7 @@ private: << ", difference L/L: " << bg::wkt(geometry1) << " " << bg::wkt(geometry2) << " -> Expected: " << bg::wkt(mls_diff) + << std::setprecision(20) << " computed: " << bg::wkt(mls_output) ); set_operation_output("difference", case_id, diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index 95b0f6973..53676cc8e 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -9,6 +9,7 @@ // Modifications copyright (c) 2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -323,14 +324,20 @@ void test_areal() test_one("buffer_mp2", buffer_mp2[0], buffer_mp2[1], 1, 29, 0.457126); +#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING + test_one("mysql_21964465", + "POLYGON((0 0,0 10,10 10,10 0, 0 0), (0 8, 4 4, 4 6, 0 8))", + "POLYGON((0 8,-8 8,-2 2,0 8))", + 0, -1, 0.0); +#endif + return; - test_one( - "polygon_pseudo_line", - "Polygon((0 0,0 4,4 4,4 0,0 0))", - "Polygon((2 -2,2 -1,2 6,2 -2))", - 5, 22, 1.1901714); + "polygon_pseudo_line", + "Polygon((0 0,0 4,4 4,4 0,0 0))", + "Polygon((2 -2,2 -1,2 6,2 -2))", + 5, 22, 1.1901714); } template @@ -446,6 +453,86 @@ void test_areal_linear() test_one_lp("case19", poly_9, "LINESTRING(1 2,1 3,0 3)", 1, 2, 1.0); test_one_lp("case20", poly_9, "LINESTRING(1 2,1 3,2 3)", 1, 3, 2.0); + test_one_lp("case21", + "POLYGON((2 3,-9 -7,12 -13,2 3))", + "LINESTRING(-1.3 0,-15 0,-1.3 0)", + 0, 0, 0); + + test_one_lp("case22", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(5 5,-10 5,5 5)", + 2, 4, 10); + + test_one_lp("case22a", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(1 1,5 5,-10 5,5 5,6 6)", + 2, 6, 17.071068); + + test_one_lp("case23", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(-10 5,5 5,-10 5)", + 1, 3, 10); + + test_one_lp("case23a", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(-20 10,-10 5,5 5,-10 5,-20 -10)", + 1, 3, 10); + + test_one_lp("case24", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(0 5,5 5,0 5)", + 1, 3, 10); + + test_one_lp("case24", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(0 5,5 5,1 1,9 1,5 5,0 5)", + 1, 6, 29.313708); + + test_one_lp("case25", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(5 5,0 5,5 5)", + 1, 3, 10); + + test_one_lp("case25a", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(-10 10,5 5,0 5,5 5,20 10)", + 1, 4, 20.540925); + + test_one_lp("case25b", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(-10 10,5 5,1 5,5 5,20 10)", + 1, 4, 18.540925); + + test_one_lp("case25c", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(-10 10,5 5,-1 5,5 5,20 10)", + 2, 6, 20.540925); + + test_one_lp("case26", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(-5 5,0 5,-5 5)", + 0, 0, 0); + + test_one_lp("case26a", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(-10 10,-5 5,0 5,-5 5,-10 -10)", + 0, 0, 0); + + test_one_lp("case27", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(5 5,0 5,5 5,5 4,0 4,5 4)", + 1, 6, 21.0); + + test_one_lp("case28", + "POLYGON((0 0,0 10,10 10,10 0,0 0))", + "LINESTRING(5 5,0 5,5 5,5 4,0 4,5 3)", + 1, 6, 21.099019); + + test_one_lp("case29", + "POLYGON((5 5,15 15,15 5,5 5))", + "LINESTRING(0 0,10 10)", + 1, 2, 5 * std::sqrt(2.0)); + // PROPERTIES CHANGED BY switch_to_integer // TODO test_one_lp("case21", poly_9, "LINESTRING(1 2,1 4,4 4,4 1,2 1,2 2)", 1, 6, 11.0); @@ -681,6 +768,7 @@ void test_boxes_nd() test_boxes_per_d(p3(0,0,0), p3(5,5,5), p3(3,3,3), p3(6,6,6), true); } + template void test_ticket_10868(std::string const& wkt_out) { diff --git a/test/algorithms/set_operations/intersection/test_intersection.hpp b/test/algorithms/set_operations/intersection/test_intersection.hpp index 1c45032a9..512bc9c95 100644 --- a/test/algorithms/set_operations/intersection/test_intersection.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection.hpp @@ -257,6 +257,9 @@ void test_one_lp(std::string const& caseid, double percentage = 0.0001, bool debug1 = false, bool debug2 = false) { +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << caseid << " -- start" << std::endl; +#endif Areal areal; bg::read_wkt(wkt_areal, areal); bg::correct(areal); @@ -274,6 +277,9 @@ void test_one_lp(std::string const& caseid, test_intersection(caseid + "_rev", areal, linear, expected_count, expected_point_count, expected_length, percentage, debug2); +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << caseid << " -- end" << std::endl; +#endif } template diff --git a/test/algorithms/set_operations/union/test_union.hpp b/test/algorithms/set_operations/union/test_union.hpp index 6a769827c..3d582d2ca 100644 --- a/test/algorithms/set_operations/union/test_union.hpp +++ b/test/algorithms/set_operations/union/test_union.hpp @@ -7,6 +7,7 @@ // Modifications copyright (c) 2015 Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, 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 @@ -51,6 +52,7 @@ void test_union(std::string const& caseid, G1 const& g1, G2 const& g2, { typedef typename bg::coordinate_type::type coordinate_type; boost::ignore_unused(); + boost::ignore_unused(expected_point_count); std::vector clip; diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index a2bfa9b98..596880247 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -1,9 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -248,7 +248,7 @@ void test_areal() 1, 0, -1, - 313.36036462, 0.01); + 313.36036462, 0.1); // SQL Server gives: 313.360374193241 // PostGIS gives: 313.360364623393 @@ -319,10 +319,8 @@ void test_areal() 1, 0, if_typed(18, 23), 4.60853); #endif -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], 1, 0, if_typed(18, 17), 16.571); -#endif test_one("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0], 1, 0, if_typed(18, 17), 16.571); @@ -355,10 +353,8 @@ void test_areal() test_one("buffer_rt_m2_rev", buffer_rt_m2[1], buffer_rt_m2[0], 1, 0, if_typed_tt(20, 19), 21.4853); -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_rt_q", buffer_rt_q[0], buffer_rt_q[1], 1, 0, 18, 18.5710); -#endif test_one("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0], 1, 0, 18, 18.5710); @@ -376,13 +372,30 @@ void test_areal() 1, 0, if_typed_tt(16, if_typed(15, 14)), 15.6569); #endif -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_mp1", buffer_mp1[0], buffer_mp1[1], 1, 0, if_typed_tt(93, 91), 22.815); -#endif test_one("buffer_mp2", buffer_mp2[0], buffer_mp2[1], 1, 0, 217, 36.752837); + +#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING + test_one("ticket_11725", + "POLYGON((0 0, 0 1, 3 1, 3 0, 0 0))", + "POLYGON((0 1, 0 3, 3 3, 3 1, 2 2, 1 2 , 1 1, 0 1))", + 1, 1, -1, 7.5); + test_one("mysql_21964079_1", + "POLYGON((7 3,0 10,0 -6,9 -5, 7 7, 7 3), (0 8, 2 3, 2 -2, 0 8))", + "POLYGON((0 8,-8 14,-11 18,-19 11, -3 1, 0 8))", + 2, 1, -1, 234.5); + test_one("mysql_21964079_2", + "POLYGON((0 0,0 10,10 10,10 0,0 0), (0 8, 4 4, 4 6, 0 8))", + "POLYGON((0 8,-8 8,-10 4,0 8))", + 2, 1, -1, 112.0); + test_one("mysql_21964049", + "POLYGON((7 0,10 -3,7 1,7 0))", + "POLYGON((7 4,-14 10,7 -17,7 4),(7 1,0 3,-2 4,7 1))", + 1, 1, -1, 220.5); +#endif } template diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index a80a249ca..2af15780c 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -113,6 +113,13 @@ void test_areal() case_recursive_boxes_3[0], case_recursive_boxes_3[1], 17, 0, 159, 56.5); // Area from SQL Server + test_one("case_recursive_boxes_4", + case_recursive_boxes_4[0], case_recursive_boxes_4[1], + 1, 1, 42, 96.75); + test_one("case_recursive_boxes_5", + case_recursive_boxes_5[0], case_recursive_boxes_5[1], + 3, 2, 110, 70.0); + test_one("ggl_list_20120915_h2_a", ggl_list_20120915_h2[0], ggl_list_20120915_h2[1], 1, 0, 12, 23.0); // Area from SQL Server diff --git a/test/arithmetic/Jamfile.v2 b/test/arithmetic/Jamfile.v2 index ac1ad55b5..23a11b2bd 100644 --- a/test/arithmetic/Jamfile.v2 +++ b/test/arithmetic/Jamfile.v2 @@ -11,6 +11,6 @@ test-suite boost-geometry-arithmetic : - [ run arithmetic.cpp : : : : arithmetic ] + [ run general.cpp : : : : arithmetic_general ] [ run dot_product.cpp : : : : arithmetic_dot_product ] ; diff --git a/test/arithmetic/arithmetic.cpp b/test/arithmetic/general.cpp similarity index 100% rename from test/arithmetic/arithmetic.cpp rename to test/arithmetic/general.cpp diff --git a/test/geometries/Jamfile.v2 b/test/geometries/Jamfile.v2 index cde618d06..c6b360f7a 100644 --- a/test/geometries/Jamfile.v2 +++ b/test/geometries/Jamfile.v2 @@ -25,6 +25,6 @@ test-suite boost-geometry-geometries # geometries_custom_linestring_test_fail_clear #] [ run custom_linestring.cpp : : : : geometries_custom_linestring ] - [ run geometries.cpp : : : : geometries ] + [ run initialization.cpp : : : : geometries_initialization ] [ run segment.cpp : : : : geometries_segment ] ; diff --git a/test/geometries/geometries.cpp b/test/geometries/initialization.cpp similarity index 100% rename from test/geometries/geometries.cpp rename to test/geometries/initialization.cpp diff --git a/test/iterators/ever_circling_iterator.cpp b/test/iterators/ever_circling_iterator.cpp index 90142e13d..1e4c254fd 100644 --- a/test/iterators/ever_circling_iterator.cpp +++ b/test/iterators/ever_circling_iterator.cpp @@ -33,12 +33,12 @@ void test_geometry(std::string const& wkt) // Run 3 times through the geometry - int n = boost::size(geo) * 3; + std::size_t n = boost::size(geo) * 3; { std::ostringstream out; bg::ever_circling_iterator it(boost::begin(geo), boost::end(geo)); - for (int i = 0; i < n; ++i, ++it) + for (std::size_t i = 0; i < n; ++i, ++it) { out << bg::get<0>(*it); } @@ -50,7 +50,7 @@ void test_geometry(std::string const& wkt) // Start somewhere bg::ever_circling_iterator it( boost::begin(geo), boost::end(geo), boost::begin(geo) + 1); - for (int i = 0; i < n; ++i, ++it) + for (std::size_t i = 0; i < n; ++i, ++it) { out << bg::get<0>(*it); } @@ -62,9 +62,9 @@ void test_geometry(std::string const& wkt) // Navigate to somewhere bg::ever_circling_iterator it(boost::begin(geo), boost::end(geo)); - for (int i = 0; i < n; ++i, ++it) + for (std::size_t i = 0; i < n; ++i, ++it) { - const int m = boost::size(geo); + std::size_t const m = boost::size(geo); it.moveto(boost::begin(geo) + m - (i % m) - 1); out << bg::get<0>(*it); } @@ -75,7 +75,7 @@ void test_geometry(std::string const& wkt) { std::ostringstream out; bg::ever_circling_range_iterator it(geo); - for (int i = 0; i < n; ++i, ++it) + for (std::size_t i = 0; i < n; ++i, ++it) { out << bg::get<0>(*it); } diff --git a/test/views/Jamfile.v2 b/test/views/Jamfile.v2 index cb2f5fb5a..3b23c2f36 100644 --- a/test/views/Jamfile.v2 +++ b/test/views/Jamfile.v2 @@ -1,8 +1,9 @@ # 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-2015 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +# Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +# Copyright (c) 2015 Adam Wulkiewicz, Lodz, Poland. # # Use, modification and distribution is subject to the Boost Software License, # Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -10,9 +11,9 @@ test-suite boost-geometry-views : - [ run segment_view.cpp ] - [ run box_view.cpp ] - [ run reversible_view.cpp ] - [ run closeable_view.cpp ] - [ run reversible_closeable.cpp ] + [ run segment_view.cpp : : : : views_segment_view ] + [ run box_view.cpp : : : : views_box_view ] + [ run reversible_view.cpp : : : : views_reversible_view ] + [ run closeable_view.cpp : : : : views_closeable_view ] + [ run reversible_closeable.cpp : : : : views_reversible_closeable ] ;