mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-11 11:52:11 +00:00
[algorithms][is_simple] multi-linestring simplicity check:
pass an appropriate predicate based interrupt policy to self turns, so that when an unacceptable turn is found, self turn stops and returns
This commit is contained in:
@@ -75,34 +75,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:
|
||||
@@ -143,8 +180,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
|
||||
<
|
||||
@@ -157,34 +197,7 @@ public:
|
||||
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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user