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 d8344ba75..b94628aeb 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 @@ -109,9 +109,9 @@ class analyse_turn_wrt_piece return geometry::covered_by(point, box); } - template + template static inline analyse_result check_segment(Point const& previous, - Point const& current, Point const& point, + Point const& current, Turn const& turn, bool from_monotonic) { typedef typename strategy::side::services::default_strategy @@ -125,12 +125,12 @@ class analyse_turn_wrt_piece < coordinate_type, coordinate_type - >(previous, current, point); + >(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, point)) + if (in_box(previous, current, turn.robust_point)) { return analyse_on_offsetted; } @@ -141,7 +141,7 @@ class analyse_turn_wrt_piece // 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, point)) + && in_box(previous, current, turn.robust_point)) { return analyse_near_offsetted; } @@ -161,9 +161,9 @@ class analyse_turn_wrt_piece } - template + template static inline analyse_result check_helper_segment(Point const& s1, - Point const& s2, Point const& point, + Point const& s2, Turn const& turn, bool is_original, Point const& offsetted) { @@ -172,7 +172,7 @@ class analyse_turn_wrt_piece typename cs_tag::type >::type side_strategy; - switch(side_strategy::apply(s1, s2, point)) + switch(side_strategy::apply(s1, s2, turn.robust_point)) { case 1 : return analyse_disjoint; // left of segment @@ -186,11 +186,11 @@ class analyse_turn_wrt_piece geometry::expand(box, s1); geometry::expand(box, s2); - if (geometry::covered_by(point, box)) + if (geometry::covered_by(turn.robust_point, box)) { // It is on the segment if (! is_original - && geometry::comparable_distance(point, offsetted) <= 1) + && geometry::comparable_distance(turn.robust_point, offsetted) <= 1) { // It is close to the offsetted-boundary, take // any rounding-issues into account @@ -217,12 +217,13 @@ class analyse_turn_wrt_piece return analyse_continue; } - template - static inline analyse_result check_helper_segments(Point const& point, Piece const& piece) + template + static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece) { - geometry::equal_to comparator; + typedef typename Turn::robust_point_type point_type; + geometry::equal_to comparator; - Point points[4]; + point_type points[4]; int helper_count = piece.robust_ring.size() - piece.offsetted_count; if (helper_count == 4) @@ -249,6 +250,7 @@ class analyse_turn_wrt_piece } // First check point-equality + point_type const& point = turn.robust_point; if (comparator(point, points[0]) || comparator(point, points[3])) { return analyse_on_offsetted; @@ -260,7 +262,7 @@ class analyse_turn_wrt_piece // Right side of the piece analyse_result result - = check_helper_segment(points[0], points[1], point, + = check_helper_segment(points[0], points[1], turn, false, points[0]); if (result != analyse_continue) { @@ -268,7 +270,7 @@ class analyse_turn_wrt_piece } // Left side of the piece - result = check_helper_segment(points[2], points[3], point, + result = check_helper_segment(points[2], points[3], turn, false, points[3]); if (result != analyse_continue) { @@ -278,7 +280,7 @@ class analyse_turn_wrt_piece if (! comparator(points[1], points[2])) { // Side of the piece at side of original geometry - result = check_helper_segment(points[1], points[2], point, + result = check_helper_segment(points[1], points[2], turn, true, point); if (result != analyse_continue) { @@ -293,7 +295,7 @@ class analyse_turn_wrt_piece // Not in offsetted-area. This makes a cheap check possible typedef typename strategy::side::services::default_strategy < - typename cs_tag::type + typename cs_tag::type >::type side_strategy; switch(side_strategy::apply(points[3], points[0], point)) @@ -307,15 +309,15 @@ class analyse_turn_wrt_piece return analyse_continue; } - template - static inline analyse_result check_monotonic(Point const& point, Piece const& piece, Compare const& compare) + template + static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare) { typedef typename Piece::piece_robust_ring_type ring_type; typedef typename ring_type::const_iterator it_type; it_type end = piece.robust_ring.begin() + piece.offsetted_count; it_type it = std::lower_bound(piece.robust_ring.begin(), end, - point, + turn.robust_point, compare); if (it != end @@ -325,22 +327,23 @@ 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, point, true); + return check_segment(*prev, *it, turn, true); } return analyse_continue; } public : - template - static inline analyse_result apply(Point const& point, Piece const& piece) + template + static inline analyse_result apply(Turn const& turn, Piece const& piece) { - analyse_result code = check_helper_segments(point, piece); + typedef typename Turn::robust_point_type point_type; + analyse_result code = check_helper_segments(turn, piece); if (code != analyse_continue) { return code; } - geometry::equal_to comparator; + geometry::equal_to comparator; if (piece.offsetted_count > 8) { @@ -349,22 +352,22 @@ public : // We try it only once. if (piece.is_monotonic_increasing[0]) { - code = check_monotonic(point, piece, geometry::less()); + code = check_monotonic(turn, piece, geometry::less()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_increasing[1]) { - code = check_monotonic(point, piece, geometry::less()); + code = check_monotonic(turn, piece, geometry::less()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[0]) { - code = check_monotonic(point, piece, geometry::greater()); + code = check_monotonic(turn, piece, geometry::greater()); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[1]) { - code = check_monotonic(point, piece, geometry::greater()); + code = check_monotonic(turn, piece, geometry::greater()); if (code != analyse_continue) return code; } } @@ -374,14 +377,14 @@ public : for (int i = 1; i < piece.offsetted_count; i++) { - Point const& previous = piece.robust_ring[i - 1]; - Point const& current = piece.robust_ring[i]; + point_type const& previous = piece.robust_ring[i - 1]; + point_type const& current = piece.robust_ring[i]; // The robust ring can contain duplicates // (on which any side or side-value would return 0) if (! comparator(previous, current)) { - code = check_segment(previous, current, point, false); + code = check_segment(previous, current, turn, false); if (code != analyse_continue) { return code; @@ -460,7 +463,7 @@ public: // TODO: mutable_piece to make some on-demand preparations in analyse analyse_result analyse_code - = analyse_turn_wrt_piece::apply(turn.robust_point, piece); + = analyse_turn_wrt_piece::apply(turn, piece); Turn& mutable_turn = m_turns[turn.turn_index]; switch(analyse_code) diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp index e569d9b54..91f985edb 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp @@ -98,11 +98,10 @@ struct assign_disjoint_policy typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Info& , Point1 const& , Point2 const&, - IntersectionInfo const&, DirInfo const&) + IntersectionInfo const&) {} }; diff --git a/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp b/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp index 75c37c68f..196d89b92 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.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. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -18,6 +18,8 @@ #include #include +#include +#include #include @@ -26,7 +28,8 @@ #include #include -#endif +#include +#endif // BOOST_GEOMETRY_TEST_DEBUG namespace boost { namespace geometry @@ -37,39 +40,67 @@ namespace detail { namespace is_simple #ifdef BOOST_GEOMETRY_TEST_DEBUG -template -inline void debug_print_boundary_points(MultiLinestring const& multilinestring) +template ::type> +struct debug_boundary_points_printer + : not_implemented +{}; + +template +struct debug_boundary_points_printer { - typedef typename point_type::type point_type; - typedef std::vector point_vector; - - point_vector boundary_points; - for (typename boost::range_iterator::type it - = boost::begin(multilinestring); - it != boost::end(multilinestring); ++it) + static inline void apply(Linestring const& linestring) { - if ( boost::size(*it) > 1 - && !geometry::equals(range::front(*it), range::back(*it)) ) + std::cout << "boundary points: "; + std::cout << " " << geometry::dsv(range::front(linestring)); + std::cout << " " << geometry::dsv(range::back(linestring)); + std::cout << std::endl << std::endl; + } +}; + +template +struct debug_boundary_points_printer +{ + static inline void apply(MultiLinestring const& multilinestring) + { + typedef typename point_type::type point_type; + typedef std::vector point_vector; + + point_vector boundary_points; + for (typename boost::range_iterator::type it + = boost::begin(multilinestring); + it != boost::end(multilinestring); ++it) { - boundary_points.push_back( range::front(*it) ); - boundary_points.push_back( range::back(*it) ); + if ( boost::size(*it) > 1 + && !geometry::equals(range::front(*it), range::back(*it)) ) + { + boundary_points.push_back( range::front(*it) ); + boundary_points.push_back( range::back(*it) ); + } } - } - std::sort(boundary_points.begin(), boundary_points.end(), - geometry::less()); + std::sort(boundary_points.begin(), boundary_points.end(), + geometry::less()); - std::cout << "boundary points: "; - for (typename point_vector::const_iterator pit = boundary_points.begin(); - pit != boundary_points.end(); ++pit) - { - std::cout << " " << geometry::dsv(*pit); + std::cout << "boundary points: "; + for (typename point_vector::const_iterator + pit = boundary_points.begin(); + pit != boundary_points.end(); ++pit) + { + std::cout << " " << geometry::dsv(*pit); + } + std::cout << std::endl << std::endl; } - std::cout << std::endl << std::endl; +}; + + +template +inline void debug_print_boundary_points(Linear const& linear) +{ + debug_boundary_points_printer::apply(linear); } #else -template -inline void debug_print_boundary_points(MultiLinestring const&) +template +inline void debug_print_boundary_points(Linear const&) { } #endif // BOOST_GEOMETRY_TEST_DEBUG diff --git a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp index 90810d27e..e07926e37 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/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. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,8 +30,10 @@ #include #include +#include #include +#include #include #include @@ -54,128 +57,210 @@ namespace detail { namespace is_simple { +template +inline bool check_segment_indices(Turn const& turn, + signed_index_type last_index) +{ + return + (turn.operations[0].seg_id.segment_index == 0 + && turn.operations[1].seg_id.segment_index == last_index) + || + (turn.operations[0].seg_id.segment_index == 0 + && turn.operations[1].seg_id.segment_index == last_index); +} + + +template ::type> +class is_acceptable_turn + : not_implemented +{}; + +template +class is_acceptable_turn +{ +public: + is_acceptable_turn(Linestring const& linestring) + : m_linestring(linestring) + , m_is_closed(geometry::equals(range::front(linestring), + range::back(linestring))) + {} + + template + inline bool apply(Turn const& turn) const + { + BOOST_ASSERT(boost::size(m_linestring) > 1); + return m_is_closed + && turn.method == overlay::method_none + && check_segment_indices(turn, boost::size(m_linestring) - 2) + && turn.operations[0].fraction.is_zero(); + } + +private: + Linestring const& m_linestring; + bool const m_is_closed; +}; + +template +class is_acceptable_turn +{ +private: + typedef typename boost::range_value::type linestring_type; + typedef is_acceptable_turn base_type; + + template + static inline bool is_boundary_point_of(Point const& point, + Linestring const& linestring) + { + BOOST_ASSERT(boost::size(linestring) > 1); + return + ! geometry::equals(range::front(linestring), + range::back(linestring)) + && + (geometry::equals(point, range::front(linestring)) + || geometry::equals(point, range::back(linestring))); + } + + template + static inline bool is_closing_point_of(Turn const& turn, + Linestring const& linestring) + { + BOOST_ASSERT(boost::size(linestring) > 1); + return + turn.method == overlay::method_none + && + check_segment_indices(turn, boost::size(linestring) - 2) + && + geometry::equals(range::front(linestring), range::back(linestring)) + && + turn.operations[0].fraction.is_zero(); + ; + } + + template + static inline bool have_same_boundary_points(Linestring1 const& ls1, + Linestring2 const& ls2) + { + return + geometry::equals(range::front(ls1), range::front(ls2)) + ? + geometry::equals(range::back(ls1), range::back(ls2)) + : + (geometry::equals(range::front(ls1), range::back(ls2)) + && + geometry::equals(range::back(ls1), range::front(ls2))) + ; + } + +public: + is_acceptable_turn(MultiLinestring const& multilinestring) + : m_multilinestring(multilinestring) + {} + + template + inline bool apply(Turn const& turn) const + { + linestring_type const& ls1 = + range::at(m_multilinestring, turn.operations[0].seg_id.multi_index); + + linestring_type const& ls2 = + range::at(m_multilinestring, turn.operations[1].seg_id.multi_index); + + if (turn.operations[0].seg_id.multi_index + == turn.operations[1].seg_id.multi_index) + { + return is_closing_point_of(turn, ls1); + } + + return + is_boundary_point_of(turn.point, ls1) + && is_boundary_point_of(turn.point, ls2) + && + ( boost::size(ls1) != 2 + || boost::size(ls2) != 2 + || ! have_same_boundary_points(ls1, ls2) ); + } + +private: + MultiLinestring const& m_multilinestring; +}; + + +template +inline bool has_self_intersections(Linear const& linear) +{ + typedef typename point_type::type point_type; + + // compute self turns + typedef detail::overlay::turn_info + < + point_type, + geometry::segment_ratio + < + typename geometry::coordinate_type::type + > + > turn_info; + + std::deque turns; + + typedef detail::overlay::get_turn_info + < + detail::disjoint::assign_disjoint_policy + > turn_policy; + + is_acceptable_turn predicate(linear); + detail::overlay::predicate_based_interrupt_policy + < + is_acceptable_turn + > interrupt_policy(predicate); + + detail::self_get_turn_points::get_turns + < + turn_policy + >::apply(linear, + detail::no_rescale_policy(), + turns, + interrupt_policy); + + detail::is_valid::debug_print_turns(turns.begin(), turns.end()); + debug_print_boundary_points(linear); + + return interrupt_policy.has_intersections; +} + + template struct is_simple_linestring { static inline bool apply(Linestring const& linestring) { - return !detail::is_valid::has_duplicates + return ! detail::is_valid::has_duplicates < Linestring, closed >::apply(linestring) - && !detail::is_valid::has_spikes + && ! detail::is_valid::has_spikes < Linestring, closed >::apply(linestring) - && !(CheckSelfIntersections && geometry::intersects(linestring)); + && ! (CheckSelfIntersections && has_self_intersections(linestring)); } }; - template -class is_simple_multilinestring +struct is_simple_multilinestring { -private: - class is_acceptable_turn - { - private: - template - static inline bool is_boundary_point_of(Point const& point, - Linestring const& linestring) - { - BOOST_ASSERT( boost::size(linestring) > 1 ); - return - !geometry::equals(range::front(linestring), - range::back(linestring)) - && - ( geometry::equals(point, range::front(linestring)) - || geometry::equals(point, range::back(linestring)) ); - } - - template - static inline bool is_closing_point_of(Point const& point, - Linestring const& linestring) - { - BOOST_ASSERT( boost::size(linestring) > 1 ); - return - geometry::equals(range::front(linestring), - range::back(linestring)) - && - geometry::equals(range::front(linestring), point) - ; - } - - template - static inline bool have_same_boundary_points(Linestring1 const& ls1, - Linestring2 const& ls2) - { - return - geometry::equals(range::front(ls1), range::front(ls2)) - ? - geometry::equals(range::back(ls1), range::back(ls2)) - : - (geometry::equals(range::front(ls1), range::back(ls2)) - && - geometry::equals(range::back(ls1), range::front(ls2)) - ) - ; - } - - public: - is_acceptable_turn(MultiLinestring const& multilinestring) - : m_multilinestring(multilinestring) - {} - - template - inline bool apply(Turn const& turn) const - { - typedef typename boost::range_value - < - MultiLinestring - >::type linestring; - - linestring const& ls1 = - range::at(m_multilinestring, - turn.operations[0].seg_id.multi_index); - - linestring const& ls2 = - range::at(m_multilinestring, - turn.operations[1].seg_id.multi_index); - - if (turn.operations[0].seg_id.multi_index - == turn.operations[1].seg_id.multi_index) - { - BOOST_ASSERT(is_closing_point_of(turn.point, ls1)); - return true; - } - - return - is_boundary_point_of(turn.point, ls1) - && is_boundary_point_of(turn.point, ls2) - && - ( boost::size(ls1) != 2 - || boost::size(ls2) != 2 - || !have_same_boundary_points(ls1, ls2) ); - } - - private: - MultiLinestring const& m_multilinestring; - }; - - -public: static inline bool apply(MultiLinestring const& multilinestring) { - typedef typename boost::range_value::type linestring; - typedef typename point_type::type point_type; - typedef point_type point; - - // check each of the linestrings for simplicity - if ( !detail::check_iterator_range + // but do not compute self-intersections yet; these will be + // computed for the entire multilinestring + if ( ! detail::check_iterator_range < - is_simple_linestring, + is_simple_linestring + < + typename boost::range_value::type, + false // do not compute self-intersections + >, false // do not allow empty multilinestring >::apply(boost::begin(multilinestring), boost::end(multilinestring)) @@ -184,44 +269,8 @@ public: return false; } - - // compute self turns - typedef detail::overlay::turn_info - < - point_type, - geometry::segment_ratio - < - typename geometry::coordinate_type::type - > - > turn_info; - - std::deque turns; - - typedef detail::overlay::get_turn_info - < - detail::disjoint::assign_disjoint_policy - > turn_policy; - - is_acceptable_turn predicate(multilinestring); - detail::overlay::predicate_based_interrupt_policy - < - is_acceptable_turn - > interrupt_policy(predicate); - - detail::self_get_turn_points::get_turns - < - turn_policy - >::apply(multilinestring, - detail::no_rescale_policy(), - turns, - interrupt_policy); - - detail::is_valid::debug_print_turns(turns.begin(), turns.end()); - debug_print_boundary_points(multilinestring); - - return !interrupt_policy.has_intersections; + return ! has_self_intersections(multilinestring); } - }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp b/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp index 6824921b6..d648412e4 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.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. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -45,6 +45,10 @@ inline void debug_print_turns(TurnIterator first, TurnIterator beyond) << tit->operations[0].seg_id.ring_index << ", " << tit->operations[1].seg_id.ring_index + << "} {" + << tit->operations[0].seg_id.segment_index + << ", " + << tit->operations[1].seg_id.segment_index << "} " << geometry::dsv(tit->point) << "]"; diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp index c88df79b0..628fb4df7 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.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. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -144,7 +144,7 @@ struct is_valid_ring }; -}} // namespace dispatch +}} // namespace detail::is_valid #endif // DOXYGEN_NO_DETAIL 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 240b6de03..82de1a1c4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -503,14 +503,12 @@ struct equal_opposite : public base_turn_handler typename Point1, typename Point2, typename OutputIterator, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Point1 const& pi, Point2 const& qi, /* by value: */ TurnInfo tp, OutputIterator& out, - IntersectionInfo const& intersection_info, - DirInfo const& dir_info) + IntersectionInfo const& intersection_info) { // For equal-opposite segments, normally don't do anything. if (AssignPolicy::include_opposite) @@ -520,10 +518,10 @@ struct equal_opposite : public base_turn_handler { tp.operations[i].operation = operation_opposite; } - for (unsigned int i = 0; i < intersection_info.count; i++) + for (unsigned int i = 0; i < intersection_info.i_info().count; i++) { - assign_point(tp, method_none, intersection_info, i); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + assign_point(tp, method_none, intersection_info.i_info(), i); + AssignPolicy::apply(tp, pi, qi, intersection_info); *out++ = tp; } } @@ -715,7 +713,6 @@ public: typename Point2, typename OutputIterator, typename IntersectionInfo, - typename DirInfo, typename SidePolicy > static inline void apply( @@ -727,10 +724,9 @@ public: OutputIterator& out, IntersectionInfo const& intersection_info, - DirInfo const& dir_info, SidePolicy const& side) { - apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, dir_info, side, empty_transformer); + apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, side, empty_transformer); } public: @@ -740,7 +736,6 @@ public: typename Point2, typename OutputIterator, typename IntersectionInfo, - typename DirInfo, typename SidePolicy, typename TurnTransformer > @@ -752,50 +747,52 @@ public: TurnInfo const& tp_model, OutputIterator& out, - IntersectionInfo const& intersection_info, - DirInfo const& dir_info, + IntersectionInfo const& info, SidePolicy const& side, TurnTransformer turn_transformer, bool const is_pk_valid = true, bool const is_qk_valid = true) { TurnInfo tp = tp_model; + int const p_arrival = info.d_info().arrival[0]; + int const q_arrival = info.d_info().arrival[1]; + // If P arrives within Q, there is a turn dependent on P - if ( dir_info.arrival[0] == 1 + if ( p_arrival == 1 && is_pk_valid - && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, intersection_info) ) + && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) ) { turn_transformer(tp); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } // If Q arrives within P, there is a turn dependent on Q - if ( dir_info.arrival[1] == 1 + if ( q_arrival == 1 && is_qk_valid - && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, intersection_info) ) + && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) ) { turn_transformer(tp); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } if (AssignPolicy::include_opposite) { // Handle cases not yet handled above - if ((dir_info.arrival[1] == -1 && dir_info.arrival[0] == 0) - || (dir_info.arrival[0] == -1 && dir_info.arrival[1] == 0)) + if ((q_arrival == -1 && p_arrival == 0) + || (p_arrival == -1 && q_arrival == 0)) { for (int i = 0; i < 2; i++) { tp.operations[i].operation = operation_opposite; } - for (unsigned int i = 0; i < intersection_info.count; i++) + for (unsigned int i = 0; i < info.i_info().count; i++) { - assign_point(tp, method_collinear, intersection_info, i); - AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info); + assign_point(tp, method_collinear, info.i_info(), i); + AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } } @@ -867,10 +864,9 @@ struct assign_null_policy typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > - static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&, DirInfo const&) + static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&) {} }; @@ -933,7 +929,7 @@ struct get_turn_info && inters.i_info().count > 0) { only_convert::apply(tp, inters.i_info()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -968,7 +964,7 @@ struct get_turn_info tp, inters.i_info(), inters.d_info(), swapped_side_calc); } - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -976,7 +972,7 @@ struct get_turn_info { crosses::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -985,7 +981,7 @@ struct get_turn_info // Both touch (both arrive there) touch::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info(), inters.sides()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -997,7 +993,7 @@ struct get_turn_info // or collinear-and-ending at intersection point equal::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info(), inters.sides()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } else @@ -1007,7 +1003,7 @@ struct get_turn_info TurnInfo, AssignPolicy >::apply(pi, qi, - tp, out, inters.i_info(), inters.d_info()); + tp, out, inters); } } break; @@ -1032,7 +1028,7 @@ struct get_turn_info tp, inters.i_info(), inters.d_info(), inters.sides()); } - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } else @@ -1042,7 +1038,7 @@ struct get_turn_info TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, inters.i_info(), inters.d_info(), inters.sides()); + tp, out, inters, inters.sides()); } } break; @@ -1052,7 +1048,7 @@ struct get_turn_info if (AssignPolicy::include_degenerate) { only_convert::apply(tp, inters.i_info()); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index ca1b9d9d0..b4af0b416 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -585,7 +585,9 @@ struct get_turn_info_for_endpoint } } - AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>()); + // TODO: this should get an intersection_info, which is unavailable here + // Because the assign_null policy accepts any structure, we pass the result instead for now + AssignPolicy::apply(tp, pi, qi, result); *out++ = tp; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index efe996fc0..d314ccbbc 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -124,7 +124,7 @@ struct get_turn_info_linear_areal calculate_spike_operation(tp.operations[0].operation, inters, is_p_last); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } @@ -137,7 +137,7 @@ struct get_turn_info_linear_areal replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -222,7 +222,7 @@ struct get_turn_info_linear_areal inters, is_p_last); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); if ( ! handle_spikes || ignore_spike @@ -258,7 +258,7 @@ struct get_turn_info_linear_areal transformer(tp); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); // conditionally handle spikes if ( ! handle_spikes @@ -275,7 +275,7 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, qi, - tp, out, inters.i_info(), inters.d_info()); + tp, out, inters); } } } @@ -321,7 +321,7 @@ struct get_turn_info_linear_areal transformer(tp); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); // conditionally handle spikes if ( ! handle_spikes @@ -353,7 +353,7 @@ struct get_turn_info_linear_areal TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, inters.i_info(), inters.d_info(), + tp, out, inters, inters.sides(), transformer, !is_p_last, true); // qk is always valid } @@ -379,7 +379,7 @@ struct get_turn_info_linear_areal } // tp.operations[1].position = position_middle; - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } @@ -567,7 +567,7 @@ struct get_turn_info_linear_areal BOOST_ASSERT(inters.i_info().count > 1); base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_blocked; @@ -793,7 +793,7 @@ struct get_turn_info_linear_areal // here is_p_first_ip == true tp.operations[0].is_collinear = false; - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; was_first_point_handled = true; @@ -846,7 +846,7 @@ struct get_turn_info_linear_areal int ip_index = ip_count > 1 ? 1 : 0; base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; // don't ignore the first IP if the segment is opposite diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 731a72e7e..4ab9bb03c 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -120,7 +120,7 @@ struct get_turn_info_linear_linear tp.operations[0].operation, tp.operations[1].operation); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } @@ -132,7 +132,7 @@ struct get_turn_info_linear_linear replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -260,7 +260,7 @@ struct get_turn_info_linear_linear tp.operations[1].operation); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); if ( ! handle_spikes || ! append_opposite_spikes(tp, inters, @@ -293,18 +293,24 @@ struct get_turn_info_linear_linear equal::apply(pi, pj, pk, qi, qj, qk, tp, inters.i_info(), inters.d_info(), inters.sides()); + operation_type spike_op + = ( tp.operations[0].operation != operation_continue + || tp.operations[1].operation != operation_continue ) ? + operation_union : + operation_continue; + // transform turn turn_transformer_ec transformer(method_touch); transformer(tp); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); // conditionally handle spikes if ( ! handle_spikes || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, - method_touch, operation_union, + method_touch, spike_op, out) ) { *out++ = tp; // no spikes @@ -318,7 +324,7 @@ struct get_turn_info_linear_linear < TurnInfo, AssignPolicy - >::apply(pi, qi, tp, out, inters.i_info(), inters.d_info()); + >::apply(pi, qi, tp, out, inters); } } } @@ -371,7 +377,7 @@ struct get_turn_info_linear_linear transformer(tp); // TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); // conditionally handle spikes if ( ! handle_spikes @@ -406,7 +412,7 @@ struct get_turn_info_linear_linear TurnInfo, AssignPolicy >::apply(pi, pj, pk, qi, qj, qk, - tp, out, inters.i_info(), inters.d_info(), inters.sides(), + tp, out, inters, inters.sides(), transformer, !is_p_last, !is_q_last); } } @@ -441,7 +447,7 @@ struct get_turn_info_linear_linear tp.operations[1].position = position_back; } - AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } @@ -482,6 +488,14 @@ struct get_turn_info_linear_linear if ( is_p_spike && is_q_spike ) { + if ( tp.method == method_equal + && tp.operations[0].operation == operation_continue + && tp.operations[1].operation == operation_continue ) + { + // treat both non-opposite collinear spikes as no-spikes + return false; + } + tp.method = method; tp.operations[0].operation = operation_blocked; tp.operations[1].operation = operation_blocked; @@ -564,8 +578,7 @@ struct get_turn_info_linear_linear base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - AssignPolicy::apply(tp, inters.pi(), inters.qi(), - inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_blocked; @@ -595,8 +608,7 @@ struct get_turn_info_linear_linear base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0); - AssignPolicy::apply(tp, inters.pi(), inters.qi(), - inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_intersection; diff --git a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index 3a7a7a7f3..d4ebcf296 100644 --- a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -144,11 +144,10 @@ protected: typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Info& , Point1 const& , Point2 const& , - IntersectionInfo const& , DirInfo const& ) + IntersectionInfo const& ) { } }; diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index e4acf36e5..bd6ceb668 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -174,7 +174,22 @@ BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) test_simple(from_wkt("LINESTRING(0 0,3 0,5 0,4 0,2 0)"), false); test_simple(from_wkt("LINESTRING(0 0,3 0,2 0,5 0)"), false); test_simple(from_wkt("LINESTRING(0 0,2 0,2 2,1 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,2 2,1 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,10 0,10 10,0 10,0 0,0 0)"), false); test_simple(from_wkt("LINESTRING(0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,0 0,10 0,10 10,0 10,0 0,0 0)"), + false); + test_simple(from_wkt("LINESTRING(0 0,0 0,0 0,10 0,10 10,0 10,0 0,0 0,0 0,0 0)"), + false); + test_simple(from_wkt("LINESTRING(0 0,0 0,10 0,10 10,10 10,10 10,10 10,10 10,0 10,0 0,0 0)"), + false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,2 2,1 0)"), false); + test_simple(from_wkt("LINESTRING(1 0,2 2,2 0,1 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,2 2,1 0,1 4,0 0)"), false); + test_simple(from_wkt("LINESTRING(4 1,10 8,4 6,4 1,10 5,10 3)"), + false); + test_simple(from_wkt("LINESTRING(10 3,10 5,4 1,4 6,10 8,4 1)"), + false); } BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) @@ -249,7 +264,12 @@ BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) false); test_simple(from_wkt("MULTILINESTRING((0 0,1 0,1 1,0 1,0 0),(-1 -1,-1 0,0 0,0 -1,-1 -1))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0))"), + false); + test_simple(from_wkt("MULTILINESTRING((4 1,10 8,4 6,4 1,10 5,10 3))"), + false); + test_simple(from_wkt("MULTILINESTRING((10 3,10 5,4 1,4 6,10 8,4 1))"), + false); } BOOST_AUTO_TEST_CASE( test_is_simple_areal ) diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index 36e7d78df..ab8d205cc 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -604,6 +604,52 @@ void test_open_polygons() false); test::apply(from_wkt("POLYGON((-10 -10,1 0,1 1,0 1),(-10 -10,-10 10,10 10,10 -10))"), false); + + test::apply + (from_wkt("POLYGON((-6 -10,-6.6923076923076925 -6.711538461538462,\ + -9 -7,-8.824742268041238 -6.123711340206185,\ + -10 -6,-8.583333333333332 -4.916666666666667,\ + -8.094117647058823 -2.4705882352941173,-10 -3,\ + -8.526315789473683 -0.05263157894736803,-10 1,\ + -10 10,-7.764705882352941 8.509803921568627,\ + -7.65090909090909 7.789090909090909,-10 10,\ + -7.574468085106383 7.304964539007091,-7.4375 6.4375,\ + -6.5 5.5,-6.4 6,-7.574468085106383 7.304964539007091,\ + -7.65090909090909 7.789090909090909,\ + -6.297029702970297 6.514851485148515,\ + 0 0,-6.297029702970297 6.514851485148515,\ + -4.848484848484849 5.151515151515151,-4 6,\ + -6.117647058823529 7.411764705882352,\ + 0 0,-6.11764705882353 7.411764705882353,\ + -7.764705882352941 8.509803921568627,-8 10,\ + -2.9473684210526314 7.052631578947368,-2 8,\ + -0.17821782178217824 6.633663366336634,1 10,\ + 1.8095238095238098 5.142857142857142,\ + 3.2038834951456314 4.097087378640777,7 7,\ + 3.7142857142857144 3.7142857142857144,\ + 4.4 3.1999999999999997,8 2,\ + 6.540540540540541 1.5945945945945947,10 -1,\ + 7.454545454545455 -4.393939393939394,8 -5,\ + 7.320754716981132 -4.716981132075472,7 -6,\ + 6.062068965517241 -5.117241379310345,\ + 4.9504132231404965 -5.256198347107438,\ + 6.1506849315068495 -7.123287671232877,9 -8,\ + 6.548387096774194 -7.741935483870968,8 -10,\ + 5.906976744186046 -7.674418604651163,\ + 3.9107142857142856 -7.464285714285714,4 -8,\ + 2.8043478260869565 -7.3478260869565215,\ + 1.7829457364341086 -7.24031007751938,2 -8,\ + 1.0728476821192054 -7.1655629139072845,\ + -4.3583617747440275 -6.593856655290103,-5 -9,\ + -5.2020725388601035 -7.720207253886011,-6 -10),\ + (5.127659574468085 -6.808510638297872,\ + 3.72972972972973 -6.378378378378379,\ + 3.571428571428571 -5.428571428571429,\ + 3.8539325842696632 -5.393258426966292,\ + 5.127659574468085 -6.808510638297872),\ + (-5.5 4.5,-6.5 5.5,-6.4 6,\ + -5.263157894736842 4.736842105263158,-5.5 4.5))"), + false); } template @@ -718,6 +764,24 @@ void test_open_multipolygons() // and the invalid case: test::apply(from_wkt("MULTIPOLYGON(((0 0,100 0,100 100,0 100),(3 3,3 97,97 97,97 3)),((2 2,98 2,98 98,2 98),(1 1,1 99,99 99,99 1)))"), false); + + test::apply + (from_wkt("MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\ + -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\ + ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\ + ((-6 -10,1 10,4 -8,-7 -2,2 0,-4 3,-10 9)),\ + ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\ + ((7 7,-4 -4,9 -8,-10 -6)))"), + false); + + test::apply + (from_wkt("MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\ + -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\ + ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\ + ((-6 -10,-10 9,-4 3,2 0,-7 -2,4 -8,1 10)),\ + ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\ + ((7 7,-10 -6,9 -8,-4 -4)))"), + false); } BOOST_AUTO_TEST_CASE( test_is_valid_multipolygon ) diff --git a/test/algorithms/overlay/get_turns_linear_linear.cpp b/test/algorithms/overlay/get_turns_linear_linear.cpp index 12328d3db..cde102aea 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -21,7 +21,7 @@ #include //TEST -//#include +#include template void test_all() @@ -256,6 +256,26 @@ void test_all() "LINESTRING(2 0,0 0,-10 0)", expected("tiu+=")("mui=+")); + // 03.02.2015 + test_geometry("LINESTRING(-7 -8,3 0,4 -1,-7 10)", + "LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)", + expected("tii++")("txu==")("tiu==")("mui=+")); + test_geometry("LINESTRING(-7 -8,3 0,4 -1,-7 10)", + "LINESTRING(-5 -4,3 0,7 -4,2 -1)", + expected("tii++")("mxu==")("miu==")("mui=+")); + + if ( boost::is_same::value ) + { + // FAILING + /*test_geometry("LINESTRING(8 5,5 1,-2 3,1 10)", + "LINESTRING(1.9375 1.875, 1.7441860465116283 1.9302325581395348, -0.7692307692307692 2.6483516483516487, -2 3, -1.0071942446043165 5.316546762589928)", + expected("")); + test_geometry("LINESTRING(8 5,5 1,-2 3,1 10)", + "LINESTRING(1.9375 1.875, 1.7441860465116283 1.9302325581395348, -0.7692307692307692 2.6483516483516487, -2 3, -0.5 6.5)", + expected(""));*/ + } + + // TODO: //test_geometry("LINESTRING(0 0,2 0,1 0)", "LINESTRING(0 1,0 0,2 0)", "1FF00F102"); //test_geometry("LINESTRING(2 0,0 0,1 0)", "LINESTRING(0 1,0 0,2 0)", "1FF00F102"); diff --git a/test/algorithms/set_operations/difference/difference_linear_linear.cpp b/test/algorithms/set_operations/difference/difference_linear_linear.cpp index 6d3d8029e..214c6abba 100644 --- a/test/algorithms/set_operations/difference/difference_linear_linear.cpp +++ b/test/algorithms/set_operations/difference/difference_linear_linear.cpp @@ -416,6 +416,125 @@ BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring ) from_wkt("MULTILINESTRING((1 1,2 1))"), "lldf25" ); + + tester::apply + (from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("LINESTRING(2 0,-10 0)"), + from_wkt("MULTILINESTRING((6 0,2 0),(2 0,5 0))"), + "lldf27a" + ); + + tester::apply + (from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("LINESTRING(2 0,-1 0,-10 0)"), + from_wkt("MULTILINESTRING((6 0,2 0),(2 0,5 0))"), + "lldf27b" + ); + + tester::apply + (from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("LINESTRING(2 0,0 0,-10 0)"), + from_wkt("MULTILINESTRING((6 0,2 0),(2 0,5 0))"), + "lldf27c" + ); + + tester::apply + (from_wkt("LINESTRING(2 0,0 0,-10 0)"), + from_wkt("LINESTRING(6 0,0 0,5 0)"), + from_wkt("MULTILINESTRING((0 0,-10 0))"), + "lldf27d" + ); + + tester::apply + (from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("LINESTRING(-3 2,-3 0,-3 -10)"), + from_wkt("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"), + "lldf28a" + ); + + tester::apply + (from_wkt("LINESTRING(-3 2,-3 0,-3 -10)"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("MULTILINESTRING((-3 0,-3 -10))"), + "lldf28b" + ); + + tester::apply + (from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("LINESTRING(-3 2,-3 0,-3 -10)"), + from_wkt("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"), + "lldf28c" + ); + + tester::apply + (from_wkt("LINESTRING(-7 -8,3 0,4 -1)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4)"), + from_wkt("MULTILINESTRING((-7 -8,3 0))"), + "lldf29a" + ); + + tester::apply + (from_wkt("LINESTRING(-7 -8,3 0,4 -1,-7 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,2 -1)"), + from_wkt("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"), + "lldf29b" + ); + + tester::apply + (from_wkt("LINESTRING(-7 -8,3 0,4 -1,-7 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"), + from_wkt("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"), + "lldf29c" + ); + + tester::apply + (from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"), + from_wkt("LINESTRING(-7 -8,3 0,4 -1,-7 10)"), + from_wkt("MULTILINESTRING((-5 -4,3 0),(4 -1,7 -4,2 -1))"), + "lldf29c-r" + ); + + tester::apply + (from_wkt("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,\ + 3 0,4 -1,-7 10,-4 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"), + from_wkt("MULTILINESTRING((-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,\ + 3 0),(3 0,-7 10,-4 10))"), + "lldf29d" + ); + +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + tester::apply + (from_wkt("LINESTRING(8 5,5 1,-2 3,1 10)"), + from_wkt("LINESTRING(1.9375 1.875,\ + 1.7441860465116283 1.9302325581395348,\ + -0.7692307692307692 2.6483516483516487,\ + -2 3,-1.0071942446043165 5.316546762589928)"), + from_wkt("MULTILINESTRING()"), + "lldf30a" + ); + + tester::apply + (from_wkt("LINESTRING(1.9375 1.875,\ + 1.7441860465116283 1.9302325581395348,\ + -0.7692307692307692 2.6483516483516487,\ + -2 3,-1.0071942446043165 5.316546762589928)"), + from_wkt("LINESTRING(8 5,5 1,-2 3,1 10)"), + from_wkt("MULTILINESTRING()"), + "lldf30b" + ); + + tester::apply + (from_wkt("LINESTRING(5 -8,-7 -6,-3 6,-3 1,-5 4,-1 0,8 5,\ + 5 1,-2 3,1 10,8 5,6 2,7 4)"), + from_wkt("LINESTRING(1.9375 1.875,\ + 1.7441860465116283 1.9302325581395348,\ + -0.7692307692307692 2.6483516483516487,\ + -2 3,-1.0071942446043165 5.316546762589928)"), + from_wkt("MULTILINESTRING()"), + "lldf30c" + ); +#endif } @@ -696,6 +815,31 @@ BOOST_AUTO_TEST_CASE( test_difference_multilinestring_linestring ) from_wkt("MULTILINESTRING((-1 0,-1 10),(0 0,1 0),(19 0,20 0),(25 0,30 0))"), "mlldf05" ); + + tester::apply + (from_wkt("MULTILINESTRING((-3 2,-3 0,-3 -10))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5)"), + from_wkt("MULTILINESTRING((-3 0,-3 -10))"), + "mlldf06a" + ); + + tester::apply + (from_wkt("MULTILINESTRING((6 6,-3 2,-3 0,-3 -10,9 -2))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\ + -6 1,10 -6)"), + from_wkt("MULTILINESTRING((6 6,-3 2),(-3 0,-3 -10,9 -2))"), + "mlldf06b" + ); + + tester::apply + (from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2,-3 0,-3 -10,\ + 9 -2,9 5,5 -5,-4 -8,9 0))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\ + -6 1,10 -6)"), + from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\ + (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0))"), + "mlldf06c" + ); } diff --git a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp index fa14fe307..bc72e1037 100644 --- a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp +++ b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp @@ -376,6 +376,17 @@ BOOST_AUTO_TEST_CASE( test_sym_difference_linestring_linestring ) (2 2,5 -1,15 2,18 0))"), "llsdf21" ); + + tester::apply + (from_wkt("LINESTRING(0 -3,5 4,6 6,-3 2,-3 0,-3 -10,9 -2,\ + 9 5,5 -5,-4 -8,9 0)"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,\ + 2 8,-6 1,10 -6)"), + from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\ + (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0),(-3 6,-3 2),\ + (-3 2,-3 5,2 -3,-6 10,5 0,2 8,-6 1,10 -6))"), + "llsdf22" + ); } @@ -617,6 +628,30 @@ BOOST_AUTO_TEST_CASE( test_sym_difference_linestring_multilinestring ) (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,25 0))"), "lmlsdf18d" ); + +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + tester::apply + (from_wkt("LINESTRING(1 5,4 2,1 -1.1,1 6,1 189.7654,2 5,-0.7654 3)"), + from_wkt("MULTILINESTRING((2 5,-0.7654 2),\ + (-1032.34324 4,1 5,9 7,3 9,0.2 5,1 -0.3),\ + (1 0.9,1 6,1 -0.6,2.232432 -0.7654,0.9 3,1 5,\ + -0.7654 9,3 0.1,9 0,-6 8,-0.7 8,0 1,-1032.34324 0))"), + /* + from_wkt("MULTILINESTRING((-0.7654 2,2 5),\ + (1 -0.3,0.2 5,3 9,9 7,1 5,-1032.34 4),\ + (-1032.34 0,0 1,-0.7 8,-6 8,9 0,3 0.1,\ + -0.7654 9,1 5,0.9 3,2.23243 -0.7654,1 -0.6),\ + (-0.7654 3,2 5,1 189.765,1 6),\ + (1 -0.6,1 -1.1,4 2,1 5))"), + */ + from_wkt("MULTILINESTRING((1 5,4 2,1 -1.1,1 -0.6),\ + (1 6,1 189.7654,2 5,-0.7654 3),(2 5,-0.7654 2),\ + (-1032.34324 4,1 5,9 7,3 9,0.2 5,1 -0.3),\ + (1 -0.6,2.232432 -0.7654,0.9 3,1 5,-0.7654 9,\ + 3 0.1,9 0,-6 8,-0.7 8,0 1,-1032.34324 0))"), + "lmlsdf19" + ); +#endif } @@ -669,6 +704,25 @@ BOOST_AUTO_TEST_CASE( test_sym_difference_multilinestring_linestring ) (17 0,18 1,17 1,16 0),(4 0,3 1))"), "mllsdf04" ); + + tester::apply + (from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2,-3 0,\ + -3 -10,9 -2,9 5,5 -5,-4 -8,9 0),\ + (-7 9,-4 -9,-5 -10,5 3),\ + (-8 -3,-6 6,-9 0,-4 -3,-1 -10),\ + (0 1,7 -1,-2 3,-7 1),\ + (-5 -9,-4 -10,7 -10,0 -6,1 6,2 -1,1 5,-5 -5))"), + from_wkt("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\ + -6 1,10 -6)"), + from_wkt("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\ + (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0),\ + (-7 9,-4 -9,-5 -10,5 3),\ + (-8 -3,-6 6,-9 0,-4 -3,-1 -10),\ + (0 1,7 -1,-2 3,-7 1),\ + (-5 -9,-4 -10,7 -10,0 -6,1 6,2 -1,1 5,-5 -5),\ + (-3 6,-3 2),(-3 2,-3 5,2 -3,-6 10,5 0,2 8,-6 1,10 -6))"), + "mllsdf05" + ); } diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index c0a59c1c4..7ea3359f6 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -14,6 +14,8 @@ #include +#include + #include #include @@ -44,11 +46,10 @@ private: typename Info, typename Point1, typename Point2, - typename IntersectionInfo, - typename DirInfo + typename IntersectionInfo > static inline void apply(Info& , Point1 const& , Point2 const& , - IntersectionInfo const& , DirInfo const& ) + IntersectionInfo const&) { } }; diff --git a/test/algorithms/set_operations/union/union_linear_linear.cpp b/test/algorithms/set_operations/union/union_linear_linear.cpp index 461653d0b..925c8363b 100644 --- a/test/algorithms/set_operations/union/union_linear_linear.cpp +++ b/test/algorithms/set_operations/union/union_linear_linear.cpp @@ -461,6 +461,19 @@ BOOST_AUTO_TEST_CASE( test_union_linestring_linestring ) (2 2,5 -1,15 2,18 0))"), "llu21a" ); + + tester::apply + (from_wkt("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0,\ + 4 -1,-7 10,-4 10)"), + from_wkt("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"), + from_wkt("MULTILINESTRING((-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0,\ + 4 -1,-7 10,-4 10),(-5 -4,3 0),\ + (4 -1,7 -4,2 -1,-4 -1,-2 6))"), + from_wkt("MULTILINESTRING((-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6),\ + (-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0),\ + (3 0,-7 10,-4 10))"), + "llu22" + ); }