diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index 0374b53a9..c0b5d4a54 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -181,9 +181,7 @@ struct buffer_turn_info intersection_location_type location; -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) robust_point_type rob_pi, rob_pj, rob_qi, rob_qj; -#endif std::size_t count_within; @@ -193,9 +191,7 @@ struct buffer_turn_info std::size_t count_on_offsetted; std::size_t count_on_helper; -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) std::size_t count_within_near_offsetted; -#endif bool remove_on_multi; @@ -212,9 +208,7 @@ struct buffer_turn_info , count_in_original(0) , count_on_offsetted(0) , count_on_helper(0) -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) , count_within_near_offsetted(0) -#endif , remove_on_multi(false) , count_on_occupied(0) , count_on_multi(0) 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 ba824243c..a3e7dc4a2 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -529,7 +529,6 @@ struct buffered_piece_collection { it->location = inside_buffer; } -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) if (it->count_within_near_offsetted > 0) { // Within can have in rare cases a rounding issue. We don't discard this @@ -538,7 +537,6 @@ struct buffered_piece_collection it->operations[0].enriched.startable = false; it->operations[1].enriched.startable = false; } -#endif } } diff --git a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index 948ba149d..33e3a2a59 100644 --- a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -254,10 +254,8 @@ class piece_turn_visitor the_model.operations[1].piece_index = piece2.index; the_model.operations[1].seg_id = piece2.first_seg_id; the_model.operations[1].seg_id.segment_index = index2; // override -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) geometry::recalculate(the_model.rob_pi, *prev1, m_robust_policy); geometry::recalculate(the_model.rob_pj, *it1, m_robust_policy); -#endif unique_sub_range_from_piece unique_sub_range1(ring1, prev1, it1); diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index e066c27f3..bc2f4dbba 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -34,11 +34,8 @@ #include #include -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) #include -#else #include -#endif namespace boost { namespace geometry @@ -103,10 +100,8 @@ enum analyse_result analyse_disjoint, analyse_within, analyse_on_original_boundary, - analyse_on_offsetted -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - , analyse_near_offsetted -#endif + analyse_on_offsetted, + analyse_near_offsetted }; template @@ -123,82 +118,85 @@ inline bool in_box(Point const& previous, return geometry::covered_by(point, box); } -template -inline analyse_result check_segment(Point const& previous, - Point const& current, Turn const& turn, - bool from_monotonic) +struct check_segment { - -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - typedef geometry::model::referring_segment segment_type; - segment_type const p(turn.rob_pi, turn.rob_pj); - segment_type const q(turn.rob_qi, turn.rob_qj); - segment_type const r(previous, current); - int const side = strategy::side::side_of_intersection::apply(p, q, r, - turn.robust_point); - - if (side == 0) + template + static inline analyse_result apply(Point const& previous, + Point const& current, Turn const& turn, + bool from_monotonic) { - return analyse_on_offsetted; - } - if (side == -1 && from_monotonic) - { - return analyse_within; - } - if (side == 1 && from_monotonic) - { - return analyse_disjoint; - } - return analyse_continue; -#else + #if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + typedef geometry::model::referring_segment segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); + segment_type const r(previous, current); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type side_strategy; - typedef typename geometry::coordinate_type::type coordinate_type; - - coordinate_type const twice_area - = side_strategy::template side_value - < - coordinate_type, - coordinate_type - >(previous, current, turn.robust_point); - - if (twice_area == 0) - { - // Collinear, only on segment if it is covered by its bbox - if (in_box(previous, current, turn.robust_point)) + if (side == 0) { return analyse_on_offsetted; } - } - else if (twice_area < 0) - { - // It is in the triangle right-of the segment where the - // segment is the hypothenusa. Check if it is close - // (within rounding-area) - if (twice_area * twice_area < geometry::comparable_distance(previous, current) - && in_box(previous, current, turn.robust_point)) - { - return analyse_near_offsetted; - } - else if (from_monotonic) + if (side == -1 && from_monotonic) { return analyse_within; } - } - else if (twice_area > 0 && from_monotonic) - { - // Left of segment - return analyse_disjoint; - } + if (side == 1 && from_monotonic) + { + return analyse_disjoint; + } + return analyse_continue; - // Not monotonic, on left or right side: continue analysing - return analyse_continue; -#endif -} + #else + + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy; + typedef typename geometry::coordinate_type::type coordinate_type; + + coordinate_type const twice_area + = side_strategy::template side_value + < + coordinate_type, + coordinate_type + >(previous, current, turn.robust_point); + + if (twice_area == 0) + { + // Collinear, only on segment if it is covered by its bbox + if (in_box(previous, current, turn.robust_point)) + { + return analyse_on_offsetted; + } + } + else if (twice_area < 0) + { + // It is in the triangle right-of the segment where the + // segment is the hypothenusa. Check if it is close + // (within rounding-area) + if (twice_area * twice_area < geometry::comparable_distance(previous, current) + && in_box(previous, current, turn.robust_point)) + { + return analyse_near_offsetted; + } + else if (from_monotonic) + { + return analyse_within; + } + } + else if (twice_area > 0 && from_monotonic) + { + // Left of segment + return analyse_disjoint; + } + + // Not monotonic, on left or right side: continue analysing + return analyse_continue; + #endif + } +}; class analyse_turn_wrt_point_piece @@ -273,7 +271,7 @@ public : } } #else - analyse_result code = check_segment(previous, current, turn, false); + analyse_result code = check_segment::apply(previous, current, turn, false); if (code != analyse_continue) { return code; @@ -313,11 +311,7 @@ class analyse_turn_wrt_piece template static inline analyse_result check_helper_segment(Point const& s1, Point const& s2, Turn const& turn, -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - bool , // is on original, to be reused -#else bool is_original, -#endif Point const& offsetted) { boost::ignore_unused(offsetted); @@ -536,7 +530,7 @@ class analyse_turn_wrt_piece // w.r.t. specified direction, and prev points to a point smaller // We now know if it is inside/outside it_type prev = it - 1; - return check_segment(*prev, *it, turn, true); + return check_segment::apply(*prev, *it, turn, true); } return analyse_continue; } @@ -593,7 +587,7 @@ public : // (on which any side or side-value would return 0) if (! comparator(previous, current)) { - code = check_segment(previous, current, turn, false); + code = check_segment::apply(previous, current, turn, false); if (code != analyse_continue) { return code; @@ -606,45 +600,14 @@ public : }; - -template -class turn_in_piece_visitor +struct turn_in_piece { - Turns& m_turns; // because partition is currently operating on const input only - Pieces const& m_pieces; // to check for piece-type - - template - inline bool skip(Operation const& op, Piece const& piece) const - { - if (op.piece_index == piece.index) - { - return true; - } - Piece const& pc = m_pieces[op.piece_index]; - if (pc.left_index == piece.index || pc.right_index == piece.index) - { - if (pc.type == strategy::buffer::buffered_flat_end) - { - // If it is a flat end, don't compare against its neighbor: - // it will always be located on one of the helper segments - return true; - } - if (pc.type == strategy::buffer::buffered_concave) - { - // If it is concave, the same applies: the IP will be - // located on one of the helper segments - return true; - } - } - - return false; - } +private : #if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) // NOTE: this function returns a side value in {-1, 0, 1} template - static inline int turn_in_convex_piece(Turn const& turn, - Piece const& piece) + static inline int in_convex_piece(Turn const& turn, Piece const& piece) { typedef typename Turn::robust_point_type point_type; typedef typename Piece::piece_robust_ring_type ring_type; @@ -694,6 +657,67 @@ class turn_in_piece_visitor return 1; // inside } #endif +public : + + // NOTE: this function returns a side value in {-1, 0, 1} + template + static inline int apply(Turn const& turn, Piece const& piece) + { +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // We don't know (yet) + int geometry_code = 0; + if (piece.is_convex) + { + return in_convex_piece(turn, piece); + } + else + { + + // TODO: this point_in_geometry is a performance-bottleneck here and + // will be replaced completely by extending analyse_piece functionality + return detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); + } +#else + return detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); +#endif + + } + +}; + + +template +class turn_in_piece_visitor +{ + Turns& m_turns; // because partition is currently operating on const input only + Pieces const& m_pieces; // to check for piece-type + + template + inline bool skip(Operation const& op, Piece const& piece) const + { + if (op.piece_index == piece.index) + { + return true; + } + Piece const& pc = m_pieces[op.piece_index]; + if (pc.left_index == piece.index || pc.right_index == piece.index) + { + if (pc.type == strategy::buffer::buffered_flat_end) + { + // If it is a flat end, don't compare against its neighbor: + // it will always be located on one of the helper segments + return true; + } + if (pc.type == strategy::buffer::buffered_concave) + { + // If it is concave, the same applies: the IP will be + // located on one of the helper segments + return true; + } + } + + return false; + } public: @@ -777,32 +801,14 @@ public: case analyse_within : mutable_turn.count_within++; return true; -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) case analyse_near_offsetted : mutable_turn.count_within_near_offsetted++; return true; -#endif default : break; } -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - // We don't know (yet) - int geometry_code = 0; - if (piece.is_convex) - { - geometry_code = turn_in_convex_piece(turn, piece); - } - else - { - - // TODO: this point_in_geometry is a performance-bottleneck here and - // will be replaced completely by extending analyse_piece functionality - geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); - } -#else - int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); -#endif + int const geometry_code = turn_in_piece::apply(turn, piece); if (geometry_code == 1) {