%PDF- %PDF-
| Direktori : /usr/include/boost/geometry/algorithms/detail/buffer/ |
| Current File : //usr/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp |
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2016, 2018.
// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/buffer.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
struct original_get_box
{
template <typename Box, typename Original>
static inline void apply(Box& total, Original const& original)
{
typedef typename strategy::expand::services::default_strategy
<
box_tag, typename cs_tag<Box>::type
>::type expand_strategy_type;
geometry::expand(total, original.m_box, expand_strategy_type());
}
};
template <typename DisjointBoxBoxStrategy>
struct original_ovelaps_box
{
template <typename Box, typename Original>
static inline bool apply(Box const& box, Original const& original)
{
return ! detail::disjoint::disjoint_box_box(box, original.m_box,
DisjointBoxBoxStrategy());
}
};
struct include_turn_policy
{
template <typename Turn>
static inline bool apply(Turn const& turn)
{
return turn.is_turn_traversable;
}
};
template <typename DisjointPointBoxStrategy>
struct turn_in_original_ovelaps_box
{
template <typename Box, typename Turn>
static inline bool apply(Box const& box, Turn const& turn)
{
if (! turn.is_turn_traversable || turn.within_original)
{
// Skip all points already processed
return false;
}
return ! geometry::detail::disjoint::disjoint_point_box(
turn.point, box, DisjointPointBoxStrategy());
}
};
//! Check if specified is in range of specified iterators
//! Return value of strategy (true if we can bail out)
template
<
typename Strategy,
typename State,
typename Point,
typename Iterator
>
inline bool point_in_range(Strategy& strategy, State& state,
Point const& point, Iterator begin, Iterator end)
{
boost::ignore_unused(strategy);
Iterator it = begin;
for (Iterator previous = it++; it != end; ++previous, ++it)
{
if (! strategy.apply(point, *previous, *it, state))
{
// We're probably on the boundary
return false;
}
}
return true;
}
template
<
typename Strategy,
typename State,
typename Point,
typename CoordinateType,
typename Iterator
>
inline bool point_in_section(Strategy& strategy, State& state,
Point const& point, CoordinateType const& point_x,
Iterator begin, Iterator end,
int direction)
{
if (direction == 0)
{
// Not a monotonic section, or no change in X-direction
return point_in_range(strategy, state, point, begin, end);
}
// We're in a monotonic section in x-direction
Iterator it = begin;
for (Iterator previous = it++; it != end; ++previous, ++it)
{
// Depending on sections.direction we can quit for this section
CoordinateType const previous_x = geometry::get<0>(*previous);
if (direction == 1 && point_x < previous_x)
{
// Section goes upwards, x increases, point is is below section
return true;
}
else if (direction == -1 && point_x > previous_x)
{
// Section goes downwards, x decreases, point is above section
return true;
}
if (! strategy.apply(point, *previous, *it, state))
{
// We're probably on the boundary
return false;
}
}
return true;
}
template <typename Point, typename Original, typename PointInGeometryStrategy>
inline int point_in_original(Point const& point, Original const& original,
PointInGeometryStrategy const& strategy)
{
typename PointInGeometryStrategy::state_type state;
if (boost::size(original.m_sections) == 0
|| boost::size(original.m_ring) - boost::size(original.m_sections) < 16)
{
// There are no sections, or it does not profit to walk over sections
// instead of over points. Boundary of 16 is arbitrary but can influence
// performance
point_in_range(strategy, state, point,
original.m_ring.begin(), original.m_ring.end());
return strategy.result(state);
}
typedef typename Original::sections_type sections_type;
typedef typename boost::range_iterator<sections_type const>::type iterator_type;
typedef typename boost::range_value<sections_type const>::type section_type;
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
coordinate_type const point_x = geometry::get<0>(point);
// Walk through all monotonic sections of this original
for (iterator_type it = boost::begin(original.m_sections);
it != boost::end(original.m_sections);
++it)
{
section_type const& section = *it;
if (! section.duplicate
&& section.begin_index < section.end_index
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box)
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box))
{
// x-coordinate of point overlaps with section
if (! point_in_section(strategy, state, point, point_x,
boost::begin(original.m_ring) + section.begin_index,
boost::begin(original.m_ring) + section.end_index + 1,
section.directions[0]))
{
// We're probably on the boundary
break;
}
}
}
return strategy.result(state);
}
template <typename Turns, typename PointInGeometryStrategy>
class turn_in_original_visitor
{
public:
turn_in_original_visitor(Turns& turns, PointInGeometryStrategy const& strategy)
: m_mutable_turns(turns)
, m_point_in_geometry_strategy(strategy)
{}
template <typename Turn, typename Original>
inline bool apply(Turn const& turn, Original const& original)
{
if (boost::empty(original.m_ring))
{
// Skip empty rings
return true;
}
if (! turn.is_turn_traversable || turn.within_original)
{
// Skip all points already processed
return true;
}
if (geometry::disjoint(turn.point, original.m_box))
{
// Skip all disjoint
return true;
}
int const code = point_in_original(turn.point, original, m_point_in_geometry_strategy);
if (code == -1)
{
return true;
}
Turn& mutable_turn = m_mutable_turns[turn.turn_index];
if (code == 0)
{
// On border of original: always discard
mutable_turn.is_turn_traversable = false;
}
// Point is inside an original ring
if (original.m_is_interior)
{
mutable_turn.count_in_original--;
}
else if (original.m_has_interiors)
{
mutable_turn.count_in_original++;
}
else
{
// It is an exterior ring and there are no interior rings.
// Then we are completely ready with this turn
mutable_turn.within_original = true;
mutable_turn.count_in_original = 1;
}
return true;
}
private :
Turns& m_mutable_turns;
PointInGeometryStrategy const& m_point_in_geometry_strategy;
};
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR