// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// struct to check whether a ring is topologically closed
-template <typename Ring, closure_selector Closure /* open */>
+template <typename Ring, closure_selector Closure = geometry::closure<Ring>::value>
struct is_topologically_closed
{
- template <typename VisitPolicy, typename EqPPStrategy>
- static inline bool apply(Ring const&, VisitPolicy& visitor, EqPPStrategy const&)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Ring const&, VisitPolicy& visitor, Strategy const&)
{
boost::ignore_unused(visitor);
template <typename Ring>
struct is_topologically_closed<Ring, closed>
{
- template <typename VisitPolicy, typename EqPPStrategy>
- static inline bool apply(Ring const& ring, VisitPolicy& visitor, EqPPStrategy const&)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor, Strategy const& strategy)
{
boost::ignore_unused(visitor);
- if (geometry::detail::equals::equals_point_point(range::front(ring),
- range::back(ring),
- EqPPStrategy()))
+ using geometry::detail::equals::equals_point_point;
+ if (equals_point_point(range::front(ring), range::back(ring), strategy))
{
return visitor.template apply<no_failure>();
}
};
-
-template <typename ResultType, bool IsInteriorRing /* false */>
-struct ring_area_predicate
-{
- typedef std::greater<ResultType> type;
-};
-
-template <typename ResultType>
-struct ring_area_predicate<ResultType, true>
-{
- typedef std::less<ResultType> type;
-};
-
-
-
+// TODO: use calculate_point_order here
template <typename Ring, bool IsInteriorRing>
struct is_properly_oriented
{
{
boost::ignore_unused(visitor);
- typedef detail::area::ring_area
- <
- order_as_direction<geometry::point_order<Ring>::value>::value,
- geometry::closure<Ring>::value
- > ring_area_type;
-
- typedef typename Strategy::template area_strategy
- <
- Ring
- >::type::template result_type<Ring>::type area_result_type;
-
- typename ring_area_predicate
- <
- area_result_type, IsInteriorRing
- >::type predicate;
-
// Check area
- area_result_type const zero = 0;
- area_result_type const area
- = ring_area_type::apply(ring,
- // TEMP - in the future (umbrella) strategy will be passed here
- geometry::strategies::area::services::strategy_converter
- <
- decltype(strategy.template get_area_strategy<Ring>())
- >::get(strategy.template get_area_strategy<Ring>()));
- if (predicate(area, zero))
+ auto const area = detail::area::ring_area::apply(ring, strategy);
+ decltype(area) const zero = 0;
+
+ if (IsInteriorRing ? (area < zero) : (area > zero))
{
return visitor.template apply<no_failure>();
}
static inline bool apply(Ring const& ring, VisitPolicy& visitor,
Strategy const& strategy)
{
- typedef typename Strategy::cs_tag cs_tag;
-
// return invalid if any of the following condition holds:
// (a) the ring's point coordinates are not invalid (e.g., NaN)
// (b) the ring's size is below the minimal one
return false;
}
- closure_selector const closure = geometry::closure<Ring>::value;
- typedef typename closeable_view<Ring const, closure>::type view_type;
-
- if (boost::size(ring)
- < core_detail::closure::minimum_ring_size<closure>::value)
+ if (boost::size(ring) < detail::minimum_ring_size<Ring>::value)
{
return visitor.template apply<failure_few_points>();
}
- view_type const view(ring);
+ detail::closed_view<Ring const> const view(ring);
+
if (detail::num_distinct_consecutive_points
<
- view_type, 4u, true,
- not_equal_to
- <
- typename point_type<Ring>::type,
- typename Strategy::equals_point_point_strategy_type
- >
- >::apply(view)
+ decltype(view), 4u, true
+ >::apply(view, strategy)
< 4u)
{
return
}
return
- is_topologically_closed<Ring, closure>::apply(ring, visitor, strategy.get_equals_point_point_strategy())
- && ! has_duplicates<Ring, closure, cs_tag>::apply(ring, visitor)
- && ! has_spikes<Ring, closure>::apply(ring, visitor, strategy.get_side_strategy())
+ is_topologically_closed<Ring>::apply(ring, visitor, strategy)
+ && ! has_duplicates<Ring>::apply(ring, visitor, strategy)
+ && ! has_spikes<Ring>::apply(ring, visitor, strategy)
&& (! CheckSelfIntersections
|| has_valid_self_turns<Ring, typename Strategy::cs_tag>::apply(ring, visitor, strategy))
&& is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy);