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

This commit is contained in:
Barend Gehrels
2014-06-23 19:34:51 +02:00
13 changed files with 462 additions and 188 deletions

View File

@@ -10,6 +10,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
#include <boost/core/ignore_unused.hpp>
namespace boost { namespace geometry
{
@@ -22,7 +24,8 @@ namespace detail
// predicate.
// The predicate must be implemented as having a static apply unary
// method that returns a bool.
template <typename Predicate, bool AllowEmptyMultiRange = false>
// By default an empty range is accepted
template <typename Predicate, bool AllowEmptyRange = true>
struct check_iterator_range
{
template <typename InputIterator>
@@ -35,7 +38,28 @@ struct check_iterator_range
return false;
}
}
return AllowEmptyMultiRange || first != beyond;
return AllowEmptyRange || first != beyond;
};
// version where we can pass a predicate object
template <typename InputIterator>
static inline bool apply(InputIterator first,
InputIterator beyond,
Predicate const& predicate)
{
// in case predicate's apply method is static, MSVC will
// complain that predicate is not used
boost::ignore_unused(predicate);
for (InputIterator it = first; it != beyond; ++it)
{
if ( !predicate.apply(*it) )
{
return false;
}
}
return AllowEmptyRange || first != beyond;
};
};

View File

@@ -61,8 +61,7 @@ private:
is_simple_ring
<
typename boost::range_value<InteriorRings>::type
>,
true // allow the iterator range to be empty
>
>::apply(boost::begin(interior_rings),
boost::end(interior_rings));
}
@@ -126,7 +125,8 @@ struct is_simple<MultiPolygon, multi_polygon_tag>
detail::is_simple::is_simple_polygon
<
typename boost::range_value<MultiPolygon>::type
>
>,
false // do not allow empty multi-polygon
>::apply(boost::begin(multipolygon), boost::end(multipolygon));
}
};

View File

@@ -7,8 +7,8 @@
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_LINEAR_HPP
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP
#ifdef BOOST_GEOMETRY_TEST_DEBUG
#include <algorithm>
@@ -26,7 +26,6 @@
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
#endif
@@ -37,33 +36,6 @@ namespace detail { namespace is_simple
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
template <typename TurnIterator>
inline void debug_print_turns(TurnIterator first, TurnIterator beyond)
{
std::cout << "turns:";
for (TurnIterator tit = first; tit != beyond; ++tit)
{
std::cout << " ["
<< geometry::method_char(tit->method)
<< ","
<< geometry::operation_char(tit->operations[0].operation)
<< "/"
<< geometry::operation_char(tit->operations[1].operation)
<< " "
<< geometry::dsv(tit->point)
<< "] ";
}
std::cout << std::endl << std::endl;
}
#else
template <typename TurnIterator>
inline void debug_print_turns(TurnIterator, TurnIterator)
{
}
#endif // BOOST_GEOMETRY_TEST_DEBUG
#ifdef BOOST_GEOMETRY_TEST_DEBUG
template <typename MultiLinestring>
inline void debug_print_boundary_points(MultiLinestring const& multilinestring)
@@ -107,4 +79,4 @@ inline void debug_print_boundary_points(MultiLinestring const&)
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_LINEAR_HPP
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP

View File

@@ -38,7 +38,8 @@
#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
#include <boost/geometry/algorithms/detail/is_simple/debug_linear.hpp>
#include <boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp>
#include <boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp>
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
@@ -75,34 +76,71 @@ template <typename MultiLinestring>
class is_simple_multilinestring
{
private:
template <typename Point, typename Linestring>
static inline bool is_boundary_point_of(Point const& point,
Linestring const& linestring)
class is_acceptable_turn
{
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)) );
}
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 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))
)
;
}
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[0].other_id.multi_index);
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:
@@ -116,7 +154,8 @@ public:
// check each of the linestrings for simplicity
if ( !detail::check_iterator_range
<
is_simple_linestring<linestring>
is_simple_linestring<linestring>,
false // do not allow empty multilinestring
>::apply(boost::begin(multilinestring),
boost::end(multilinestring))
)
@@ -142,8 +181,11 @@ public:
detail::disjoint::assign_disjoint_policy
> turn_policy;
detail::self_get_turn_points::no_interrupt_policy
interrupt_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
<
@@ -153,37 +195,10 @@ public:
turns,
interrupt_policy);
debug_print_turns(turns.begin(), turns.end());
detail::is_valid::debug_print_turns(turns.begin(), turns.end());
debug_print_boundary_points(multilinestring);
// check if the generated turns are all boundary points of the
// linestrings in the multi-linestring
for (typename std::deque<turn_info>::const_iterator tit = turns.begin();
tit != turns.end(); ++tit)
{
linestring const& ls1 =
range::at(multilinestring,
tit->operations[0].seg_id.multi_index);
linestring const& ls2 =
range::at(multilinestring,
tit->operations[0].other_id.multi_index);
if ( !is_boundary_point_of(tit->point, ls1)
|| !is_boundary_point_of(tit->point, ls2) )
{
return false;
}
if ( boost::size(ls1) == 2
&& boost::size(ls2) == 2
&& have_same_boundary_points(ls1, ls2) )
{
return false;
}
}
return true;
return !interrupt_policy.has_intersections;
}
};

View File

@@ -46,7 +46,7 @@ struct has_valid_corners
template <typename Box>
struct has_valid_corners<Box, 0>
{
static inline bool apply(Box const& box)
static inline bool apply(Box const&)
{
return true;
}

View File

@@ -12,7 +12,6 @@
#include <cstddef>
#include <iostream>
#include <set>
#include <stack>
#include <utility>
@@ -232,29 +231,9 @@ public:
return false;
}
void print(std::ostream& os = std::cout) const
{
os << "num rings: " << m_num_rings << std::endl;
os << "vertex ids: {";
for (vertex_handle it = m_vertices.begin();
it != m_vertices.end(); ++it)
{
os << " " << it->id();
}
os << " }" << std::endl;
for (vertex_handle it = m_vertices.begin();
it != m_vertices.end(); ++it)
{
os << "neighbors of " << it->id() << ": {";
for (typename Vertex::neighbor_iterator nit = it->neighbors_begin();
nit != it->neighbors_end(); ++nit)
{
os << " " << (*nit)->id();
}
os << "}" << std::endl;
}
}
template <typename OStream, typename V>
friend inline
void debug_print_complement_graph(OStream&, complement_graph<V> const&);
private:
std::size_t m_num_rings, m_num_turns;

View File

@@ -0,0 +1,65 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_COMPLEMENT_GRAPH_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_COMPLEMENT_GRAPH_HPP
#ifdef BOOST_GEOMETRY_TEST_DEBUG
#include <iostream>
#endif
namespace boost { namespace geometry
{
namespace detail { namespace is_valid
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
template <typename OutputStream, typename Vertex>
inline void debug_print_complement_graph(OutputStream& os,
complement_graph<Vertex> const& graph)
{
typedef typename complement_graph<Vertex>::vertex_handle vertex_handle;
os << "num rings: " << graph.m_num_rings << std::endl;
os << "vertex ids: {";
for (vertex_handle it = graph.m_vertices.begin();
it != graph.m_vertices.end(); ++it)
{
os << " " << it->id();
}
os << " }" << std::endl;
for (vertex_handle it = graph.m_vertices.begin();
it != graph.m_vertices.end(); ++it)
{
os << "neighbors of " << it->id() << ": {";
for (typename Vertex::neighbor_iterator nit = it->neighbors_begin();
nit != it->neighbors_end(); ++nit)
{
os << " " << (*nit)->id();
}
os << "}" << std::endl;
}
}
#else
template <typename OutputStream, typename Vertex>
void debug_print_complement_graph(OutputStream&,
complement_graph<Vertex> const&)
{
}
#endif
}} // namespace detail::is_valid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP

View File

@@ -0,0 +1,64 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP
#ifdef BOOST_GEOMETRY_TEST_DEBUG
#include <iostream>
#include <boost/geometry/io/dsv/write.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
#endif
namespace boost { namespace geometry
{
namespace detail { namespace is_valid
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
template <typename TurnIterator>
inline void debug_print_turns(TurnIterator first, TurnIterator beyond)
{
std::cout << "turns:";
for (TurnIterator tit = first; tit != beyond; ++tit)
{
std::cout << " ["
<< geometry::method_char(tit->method)
<< ","
<< geometry::operation_char(tit->operations[0].operation)
<< "/"
<< geometry::operation_char(tit->operations[1].operation)
<< " {"
<< tit->operations[0].seg_id.multi_index
<< ", "
<< tit->operations[0].other_id.multi_index
<< "} {"
<< tit->operations[0].seg_id.ring_index
<< ", "
<< tit->operations[0].other_id.ring_index
<< "} "
<< geometry::dsv(tit->point)
<< "]";
}
std::cout << std::endl << std::endl;
}
#else
template <typename TurnIterator>
inline void debug_print_turns(TurnIterator, TurnIterator)
{}
#endif // BOOST_GEOMETRY_TEST_DEBUG
}} // namespace detail::is_valid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP

View File

@@ -0,0 +1,68 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP
#ifdef GEOMETRY_TEST_DEBUG
#include <iostream>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#endif
namespace boost { namespace geometry
{
namespace detail { namespace is_valid
{
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct debug_validity_phase
{
static inline void apply(int)
{
}
};
#ifdef BOOST_GEOMETRY_TEST_DEBUG
template <typename Polygon>
struct debug_validity_phase<Polygon, polygon_tag>
{
static inline void apply(int phase)
{
switch (phase)
{
case 1:
std::cout << "checking exterior ring..." << std::endl;
break;
case 2:
std::cout << "checking interior rings..." << std::endl;
break;
case 3:
std::cout << "computing and analyzing turns..." << std::endl;
break;
case 4:
std::cout << "checking if holes are inside the exterior ring..."
<< std::endl;
break;
case 5:
std::cout << "checking connectivity of interior..." << std::endl;
break;
}
}
};
#endif
}} // namespace detail::is_valid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP

View File

@@ -107,7 +107,8 @@ struct is_valid<MultiLinestring, multi_linestring_tag, AllowSpikes>
<
typename boost::range_value<MultiLinestring>::type,
AllowSpikes
>
>,
false // do not allow empty multilinestring
>::apply(boost::begin(multilinestring),
boost::end(multilinestring));
}

View File

@@ -25,6 +25,7 @@
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/policies/predicate_based_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
@@ -39,14 +40,12 @@
#include <boost/geometry/algorithms/detail/is_valid/ring.hpp>
#include <boost/geometry/algorithms/detail/is_valid/complement_graph.hpp>
#include <boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp>
#include <boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp>
#include <boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
#ifdef BOOST_GEOMETRY_TEST_DEBUG
#include <boost/geometry/io/dsv/write.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
#endif
namespace boost { namespace geometry
{
@@ -136,25 +135,27 @@ private:
&& turn.operations[1].operation == operation;
}
template <typename Turn>
static inline bool is_acceptable_turn(Turn const& turn)
struct is_acceptable_turn
{
if ( turn.operations[0].seg_id.ring_index
== turn.operations[0].other_id.ring_index )
template <typename Turn>
static inline bool apply(Turn const& turn)
{
return false;
if ( turn.operations[0].seg_id.ring_index
== turn.operations[0].other_id.ring_index )
{
return false;
}
detail::overlay::operation_type const op = acceptable_operation
<
geometry::point_order<Polygon>::value
>::value;
return check_turn(turn, detail::overlay::method_touch_interior, op)
|| check_turn(turn, detail::overlay::method_touch, op)
;
}
detail::overlay::operation_type const op = acceptable_operation
<
geometry::point_order<Polygon>::value
>::value;
return check_turn(turn, detail::overlay::method_touch_interior, op)
|| check_turn(turn, detail::overlay::method_touch, op)
;
}
};
template <typename InteriorRings>
@@ -169,8 +170,7 @@ private:
AllowDuplicates,
false, // do not check self-intersections
true // indicate that the ring is interior
>,
true // allow the iterator range to be empty
>
>::apply(boost::begin(interior_rings),
boost::end(interior_rings));
}
@@ -183,10 +183,11 @@ public:
typedef typename point_type<Polygon>::type point_type;
typedef typename ring_type<Polygon>::type ring_type;
typedef debug_validity_phase<Polygon> debug_phase;
// check validity of exterior ring
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "checking exterior ring..." << std::endl;
#endif
debug_phase::apply(1);
if ( !detail::is_valid::is_valid_ring
<
ring_type,
@@ -197,11 +198,9 @@ public:
return false;
}
// check validity of interior rings
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "checking interior rings..." << std::endl;
#endif
debug_phase::apply(2);
if ( !are_valid_interior_rings(geometry::interior_rings(polygon)) )
{
return false;
@@ -209,9 +208,8 @@ public:
// compute turns and check if all are acceptable
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "computing and analyzing turns..." << std::endl;
#endif
debug_phase::apply(3);
typedef typename geometry::rescale_policy_type
<
point_type
@@ -235,51 +233,38 @@ public:
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(polygon);
std::deque<turn_info> turns;
detail::self_get_turn_points::no_interrupt_policy interrupt_policy;
detail::overlay::stateless_predicate_based_interrupt_policy
<
is_acceptable_turn
> interrupt_policy;
std::deque<turn_info> turns;
geometry::self_turns<turn_policy>(polygon,
robust_policy,
turns,
interrupt_policy);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "turns:";
for (typename std::deque<turn_info>::const_iterator tit = turns.begin();
tit != turns.end(); ++tit)
if ( interrupt_policy.has_intersections )
{
std::cout << " [" << geometry::method_char(tit->method);
std::cout << ","
<< geometry::operation_char(tit->operations[0].operation);
std::cout << "/"
<< geometry::operation_char(tit->operations[1].operation);
std::cout << " {" << tit->operations[0].seg_id.ring_index
<< ", " << tit->operations[0].other_id.ring_index
<< "}";
std::cout << " " << geometry::dsv(tit->point);
std::cout << "] ";
return false;
}
std::cout << std::endl << std::endl;
#endif
debug_print_turns(turns.begin(), turns.end());
// put the ring id's that are associated with turns in a
// container with fast lookup (std::set)
std::set<int> rings_with_turns;
for (typename std::deque<turn_info>::const_iterator tit = turns.begin();
tit != turns.end(); ++tit)
{
if ( !is_acceptable_turn(*tit) )
{
return false;
}
rings_with_turns.insert(tit->operations[0].seg_id.ring_index);
rings_with_turns.insert(tit->operations[0].other_id.ring_index);
}
// check if all interior rings are inside the exterior ring
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "checking if holes are inside the exterior ring..."
<< std::endl;
#endif
debug_phase::apply(4);
if ( !are_holes_inside(geometry::interior_rings(polygon),
geometry::exterior_ring(polygon),
rings_with_turns) )
@@ -289,9 +274,8 @@ public:
// check whether the interior of the polygon is a connected set
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "checking connectivity of interior..." << std::endl;
#endif
debug_phase::apply(5);
typedef graph_vertex<typename turn_info::point_type> graph_vertex;
typedef complement_graph<graph_vertex> graph;
@@ -309,9 +293,8 @@ public:
g.add_edge(v2, vip);
}
#ifdef BOOST_GEOMETRY_TEST_DEBUG
g.print();
#endif
debug_print_complement_graph(std::cout, g);
return !g.has_cycles();
}
};
@@ -352,7 +335,8 @@ struct is_valid<MultiPolygon, multi_polygon_tag, AllowSpikes, AllowDuplicates>
<
typename boost::range_value<MultiPolygon>::type,
AllowDuplicates
>
>,
false // do not allow empty multi-polygons
>::apply(boost::begin(multipolygon),
boost::end(multipolygon)) )
{

View File

@@ -0,0 +1,101 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
{
template
<
typename IsAcceptableTurnPredicate,
bool AllowEmptyTurnRange = true // by default, allow an empty turn range
>
struct stateless_predicate_based_interrupt_policy
{
static bool const enabled = true;
bool has_intersections; // set to true if there is at least one
// unacceptable turn
inline stateless_predicate_based_interrupt_policy()
: has_intersections(false)
{}
template <typename Range>
inline bool apply(Range const& range)
{
// if there is at least one unacceptable turn in the range, return false
has_intersections = !detail::check_iterator_range
<
IsAcceptableTurnPredicate,
AllowEmptyTurnRange
>::apply(boost::begin(range), boost::end(range));
return has_intersections;
}
};
template
<
typename IsAcceptableTurnPredicate,
bool AllowEmptyTurnRange = true // by default, allow an empty turn range
>
struct predicate_based_interrupt_policy
{
static bool const enabled = true;
bool has_intersections; // set to true if there is at least one
// unacceptable turn
IsAcceptableTurnPredicate const& m_predicate;
inline
predicate_based_interrupt_policy(IsAcceptableTurnPredicate const& predicate)
: has_intersections(false)
, m_predicate(predicate)
{}
template <typename Range>
inline bool apply(Range const& range)
{
// if there is at least one unacceptable turn in the range, return false
has_intersections = !detail::check_iterator_range
<
IsAcceptableTurnPredicate,
AllowEmptyTurnRange
>::apply(boost::begin(range), boost::end(range), m_predicate);
return has_intersections;
}
};
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP

View File

@@ -129,7 +129,8 @@ struct is_convertible_to_closed<MultiPolygon, bg::multi_polygon_tag, bg::open>
{
return bg::detail::check_iterator_range
<
is_convertible_to_closed<polygon>
is_convertible_to_closed<polygon>,
false // do not allow empty multi-polygon
>::apply(boost::begin(multi_polygon),
boost::end(multi_polygon));
}