Merge branch 'develop' of github.com:boostorg/geometry into develop

This commit is contained in:
Adam Wulkiewicz
2015-02-05 14:43:21 +01:00
18 changed files with 686 additions and 275 deletions

View File

@@ -109,9 +109,9 @@ class analyse_turn_wrt_piece
return geometry::covered_by(point, box);
}
template <typename Point>
template <typename Point, typename Turn>
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 <typename Point>
template <typename Point, typename Turn>
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<Point>::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 <typename Point, typename Piece>
static inline analyse_result check_helper_segments(Point const& point, Piece const& piece)
template <typename Turn, typename Piece>
static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)
{
geometry::equal_to<Point> comparator;
typedef typename Turn::robust_point_type point_type;
geometry::equal_to<point_type> 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<Point>::type
typename cs_tag<point_type>::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 <typename Point, typename Piece, typename Compare>
static inline analyse_result check_monotonic(Point const& point, Piece const& piece, Compare const& compare)
template <typename Turn, typename Piece, typename Compare>
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 <typename Point, typename Piece>
static inline analyse_result apply(Point const& point, Piece const& piece)
template <typename Turn, typename Piece>
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<Point> comparator;
geometry::equal_to<point_type> 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<Point, 0>());
code = check_monotonic(turn, piece, geometry::less<point_type, 0>());
if (code != analyse_continue) return code;
}
else if (piece.is_monotonic_increasing[1])
{
code = check_monotonic(point, piece, geometry::less<Point, 1>());
code = check_monotonic(turn, piece, geometry::less<point_type, 1>());
if (code != analyse_continue) return code;
}
else if (piece.is_monotonic_decreasing[0])
{
code = check_monotonic(point, piece, geometry::greater<Point, 0>());
code = check_monotonic(turn, piece, geometry::greater<point_type, 0>());
if (code != analyse_continue) return code;
}
else if (piece.is_monotonic_decreasing[1])
{
code = check_monotonic(point, piece, geometry::greater<Point, 1>());
code = check_monotonic(turn, piece, geometry::greater<point_type, 1>());
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)

View File

@@ -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&)
{}
};

View File

@@ -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 <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/range.hpp>
@@ -26,7 +28,8 @@
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#endif
#include <boost/geometry/algorithms/not_implemented.hpp>
#endif // BOOST_GEOMETRY_TEST_DEBUG
namespace boost { namespace geometry
@@ -37,39 +40,67 @@ namespace detail { namespace is_simple
#ifdef BOOST_GEOMETRY_TEST_DEBUG
template <typename MultiLinestring>
inline void debug_print_boundary_points(MultiLinestring const& multilinestring)
template <typename Linear, typename Tag = typename tag<Linear>::type>
struct debug_boundary_points_printer
: not_implemented<Linear>
{};
template <typename Linestring>
struct debug_boundary_points_printer<Linestring, linestring_tag>
{
typedef typename point_type<MultiLinestring>::type point_type;
typedef std::vector<point_type> point_vector;
point_vector boundary_points;
for (typename boost::range_iterator<MultiLinestring const>::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 <typename MultiLinestring>
struct debug_boundary_points_printer<MultiLinestring, multi_linestring_tag>
{
static inline void apply(MultiLinestring const& multilinestring)
{
typedef typename point_type<MultiLinestring>::type point_type;
typedef std::vector<point_type> point_vector;
point_vector boundary_points;
for (typename boost::range_iterator<MultiLinestring const>::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<point_type>());
std::sort(boundary_points.begin(), boundary_points.end(),
geometry::less<point_type>());
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 <typename Linear>
inline void debug_print_boundary_points(Linear const& linear)
{
debug_boundary_points_printer<Linear>::apply(linear);
}
#else
template <typename MultiLinestring>
inline void debug_print_boundary_points(MultiLinestring const&)
template <typename Linear>
inline void debug_print_boundary_points(Linear const&)
{
}
#endif // BOOST_GEOMETRY_TEST_DEBUG

View File

@@ -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 <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/range.hpp>
@@ -29,8 +30,10 @@
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/signed_index_type.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
@@ -54,128 +57,210 @@ namespace detail { namespace is_simple
{
template <typename Turn>
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 <typename Geometry, typename Tag = typename tag<Geometry>::type>
class is_acceptable_turn
: not_implemented<Geometry>
{};
template <typename Linestring>
class is_acceptable_turn<Linestring, linestring_tag>
{
public:
is_acceptable_turn(Linestring const& linestring)
: m_linestring(linestring)
, m_is_closed(geometry::equals(range::front(linestring),
range::back(linestring)))
{}
template <typename Turn>
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 <typename MultiLinestring>
class is_acceptable_turn<MultiLinestring, multi_linestring_tag>
{
private:
typedef typename boost::range_value<MultiLinestring>::type linestring_type;
typedef is_acceptable_turn<linestring_type> base_type;
template <typename Point, typename Linestring>
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 <typename Turn, typename Linestring>
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 <typename Linestring1, typename Linestring2>
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 <typename Turn>
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 <typename Linear>
inline bool has_self_intersections(Linear const& linear)
{
typedef typename point_type<Linear>::type point_type;
// compute self turns
typedef detail::overlay::turn_info
<
point_type,
geometry::segment_ratio
<
typename geometry::coordinate_type<point_type>::type
>
> turn_info;
std::deque<turn_info> turns;
typedef detail::overlay::get_turn_info
<
detail::disjoint::assign_disjoint_policy
> turn_policy;
is_acceptable_turn<Linear> predicate(linear);
detail::overlay::predicate_based_interrupt_policy
<
is_acceptable_turn<Linear>
> 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 <typename Linestring, bool CheckSelfIntersections = true>
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 <typename MultiLinestring>
class is_simple_multilinestring
struct is_simple_multilinestring
{
private:
class is_acceptable_turn
{
private:
template <typename Point, typename Linestring>
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 <typename Point, typename Linestring>
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 <typename Linestring1, typename Linestring2>
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 <typename Turn>
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<MultiLinestring>::type linestring;
typedef typename point_type<MultiLinestring>::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<linestring>,
is_simple_linestring
<
typename boost::range_value<MultiLinestring>::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<point>::type
>
> turn_info;
std::deque<turn_info> 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);
}
};

View File

@@ -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)
<< "]";

View File

@@ -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

View File

@@ -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<TurnInfo>::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<TurnInfo>::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<TurnInfo>::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;
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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<append_touches>(tp, inters,
@@ -293,18 +293,24 @@ struct get_turn_info_linear_linear
equal<TurnInfo>::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;

View File

@@ -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& )
{
}
};

View File

@@ -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<G>("LINESTRING(0 0,3 0,5 0,4 0,2 0)"), false);
test_simple(from_wkt<G>("LINESTRING(0 0,3 0,2 0,5 0)"), false);
test_simple(from_wkt<G>("LINESTRING(0 0,2 0,2 2,1 0,0 0)"), false);
test_simple(from_wkt<G>("LINESTRING(0 0,1 0,2 0,2 2,1 0,0 0)"), false);
test_simple(from_wkt<G>("LINESTRING(0 0,10 0,10 10,0 10,0 0,0 0)"), false);
test_simple(from_wkt<G>("LINESTRING(0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0)"), false);
test_simple(from_wkt<G>("LINESTRING(0 0,0 0,10 0,10 10,0 10,0 0,0 0)"),
false);
test_simple(from_wkt<G>("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<G>("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<G>("LINESTRING(0 0,1 0,2 0,2 2,1 0)"), false);
test_simple(from_wkt<G>("LINESTRING(1 0,2 2,2 0,1 0,0 0)"), false);
test_simple(from_wkt<G>("LINESTRING(0 0,1 0,2 0,2 2,1 0,1 4,0 0)"), false);
test_simple(from_wkt<G>("LINESTRING(4 1,10 8,4 6,4 1,10 5,10 3)"),
false);
test_simple(from_wkt<G>("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<G>("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<G>("MULTILINESTRING((0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0))"), false);
test_simple(from_wkt<G>("MULTILINESTRING((0 0,0 10,5 10,0 0,10 10,10 5,10 0,0 0))"),
false);
test_simple(from_wkt<G>("MULTILINESTRING((4 1,10 8,4 6,4 1,10 5,10 3))"),
false);
test_simple(from_wkt<G>("MULTILINESTRING((10 3,10 5,4 1,4 6,10 8,4 1))"),
false);
}
BOOST_AUTO_TEST_CASE( test_is_simple_areal )

View File

@@ -604,6 +604,52 @@ void test_open_polygons()
false);
test::apply(from_wkt<OG>("POLYGON((-10 -10,1 0,1 1,0 1),(-10 -10,-10 10,10 10,10 -10))"),
false);
test::apply
(from_wkt<OG>("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 <typename Point>
@@ -718,6 +764,24 @@ void test_open_multipolygons()
// and the invalid case:
test::apply(from_wkt<OG>("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<OG>("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<OG>("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 )

View File

@@ -21,7 +21,7 @@
#include <boost/geometry/geometries/geometries.hpp>
//TEST
//#include <to_svg.hpp>
#include <to_svg.hpp>
template <typename T>
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<ls, ls>("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<ls, ls>("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<T, double>::value )
{
// FAILING
/*test_geometry<ls, ls>("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<ls, ls>("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<ls, ls>("LINESTRING(0 0,2 0,1 0)", "LINESTRING(0 1,0 0,2 0)", "1FF00F102");
//test_geometry<ls, ls>("LINESTRING(2 0,0 0,1 0)", "LINESTRING(0 1,0 0,2 0)", "1FF00F102");

View File

@@ -416,6 +416,125 @@ BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring )
from_wkt<ML>("MULTILINESTRING((1 1,2 1))"),
"lldf25"
);
tester::apply
(from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
from_wkt<L>("LINESTRING(2 0,-10 0)"),
from_wkt<ML>("MULTILINESTRING((6 0,2 0),(2 0,5 0))"),
"lldf27a"
);
tester::apply
(from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
from_wkt<L>("LINESTRING(2 0,-1 0,-10 0)"),
from_wkt<ML>("MULTILINESTRING((6 0,2 0),(2 0,5 0))"),
"lldf27b"
);
tester::apply
(from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
from_wkt<L>("LINESTRING(2 0,0 0,-10 0)"),
from_wkt<ML>("MULTILINESTRING((6 0,2 0),(2 0,5 0))"),
"lldf27c"
);
tester::apply
(from_wkt<L>("LINESTRING(2 0,0 0,-10 0)"),
from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
from_wkt<ML>("MULTILINESTRING((0 0,-10 0))"),
"lldf27d"
);
tester::apply
(from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
from_wkt<L>("LINESTRING(-3 2,-3 0,-3 -10)"),
from_wkt<ML>("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"),
"lldf28a"
);
tester::apply
(from_wkt<L>("LINESTRING(-3 2,-3 0,-3 -10)"),
from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
from_wkt<ML>("MULTILINESTRING((-3 0,-3 -10))"),
"lldf28b"
);
tester::apply
(from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
from_wkt<L>("LINESTRING(-3 2,-3 0,-3 -10)"),
from_wkt<ML>("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"),
"lldf28c"
);
tester::apply
(from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1)"),
from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4)"),
from_wkt<ML>("MULTILINESTRING((-7 -8,3 0))"),
"lldf29a"
);
tester::apply
(from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1,-7 10)"),
from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,2 -1)"),
from_wkt<ML>("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"),
"lldf29b"
);
tester::apply
(from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1,-7 10)"),
from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"),
from_wkt<ML>("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"),
"lldf29c"
);
tester::apply
(from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"),
from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1,-7 10)"),
from_wkt<ML>("MULTILINESTRING((-5 -4,3 0),(4 -1,7 -4,2 -1))"),
"lldf29c-r"
);
tester::apply
(from_wkt<L>("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,\
3 0,4 -1,-7 10,-4 10)"),
from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"),
from_wkt<ML>("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<L>("LINESTRING(8 5,5 1,-2 3,1 10)"),
from_wkt<L>("LINESTRING(1.9375 1.875,\
1.7441860465116283 1.9302325581395348,\
-0.7692307692307692 2.6483516483516487,\
-2 3,-1.0071942446043165 5.316546762589928)"),
from_wkt<ML>("MULTILINESTRING()"),
"lldf30a"
);
tester::apply
(from_wkt<L>("LINESTRING(1.9375 1.875,\
1.7441860465116283 1.9302325581395348,\
-0.7692307692307692 2.6483516483516487,\
-2 3,-1.0071942446043165 5.316546762589928)"),
from_wkt<L>("LINESTRING(8 5,5 1,-2 3,1 10)"),
from_wkt<ML>("MULTILINESTRING()"),
"lldf30b"
);
tester::apply
(from_wkt<L>("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<L>("LINESTRING(1.9375 1.875,\
1.7441860465116283 1.9302325581395348,\
-0.7692307692307692 2.6483516483516487,\
-2 3,-1.0071942446043165 5.316546762589928)"),
from_wkt<ML>("MULTILINESTRING()"),
"lldf30c"
);
#endif
}
@@ -696,6 +815,31 @@ BOOST_AUTO_TEST_CASE( test_difference_multilinestring_linestring )
from_wkt<ML>("MULTILINESTRING((-1 0,-1 10),(0 0,1 0),(19 0,20 0),(25 0,30 0))"),
"mlldf05"
);
tester::apply
(from_wkt<ML>("MULTILINESTRING((-3 2,-3 0,-3 -10))"),
from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
from_wkt<ML>("MULTILINESTRING((-3 0,-3 -10))"),
"mlldf06a"
);
tester::apply
(from_wkt<ML>("MULTILINESTRING((6 6,-3 2,-3 0,-3 -10,9 -2))"),
from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\
-6 1,10 -6)"),
from_wkt<ML>("MULTILINESTRING((6 6,-3 2),(-3 0,-3 -10,9 -2))"),
"mlldf06b"
);
tester::apply
(from_wkt<ML>("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<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\
-6 1,10 -6)"),
from_wkt<ML>("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\
(-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0))"),
"mlldf06c"
);
}

View File

@@ -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<L>("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<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,\
2 8,-6 1,10 -6)"),
from_wkt<ML>("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<L>("LINESTRING(1 5,4 2,1 -1.1,1 6,1 189.7654,2 5,-0.7654 3)"),
from_wkt<ML>("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<ML>("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<ML>("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<ML>("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<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\
-6 1,10 -6)"),
from_wkt<ML>("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"
);
}

View File

@@ -14,6 +14,8 @@
#include <boost/geometry/algorithms/reverse.hpp>
#include <boost/geometry/algorithms/detail/signed_index_type.hpp>
#include <boost/geometry/algorithms/detail/relate/turns.hpp>
#include <boost/geometry/algorithms/detail/turns/compare_turns.hpp>
@@ -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&)
{
}
};

View File

@@ -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<L>("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0,\
4 -1,-7 10,-4 10)"),
from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"),
from_wkt<ML>("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<ML>("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"
);
}