[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:
Menelaos Karavelas
2014-06-19 16:33:56 +03:00
parent 62dc84e14f
commit 4052cc85f9

View File

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