mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-09 11:12:21 +00:00
Merge branch 'develop' of github.com:boostorg/geometry into develop
This commit is contained in:
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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)) )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user