%PDF- %PDF-
| Direktori : /proc/thread-self/root/usr/include/boost/geometry/algorithms/detail/overlay/ |
| Current File : //proc/thread-self/root/usr/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp |
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 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_OVERLAY_HANDLE_SELF_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_SELF_TURNS_HPP
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/within.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
{
template
<
typename Point, typename Geometry,
typename Tag2 = typename geometry::tag<Geometry>::type
>
struct check_within_strategy
{
template <typename Strategy>
static inline typename Strategy::template point_in_geometry_strategy<Point, Geometry>::type
within(Strategy const& strategy)
{
return strategy.template get_point_in_geometry_strategy<Point, Geometry>();
}
template <typename Strategy>
static inline typename Strategy::template point_in_geometry_strategy<Point, Geometry>::type
covered_by(Strategy const& strategy)
{
return strategy.template get_point_in_geometry_strategy<Point, Geometry>();
}
};
template <typename Point, typename Geometry>
struct check_within_strategy<Point, Geometry, box_tag>
{
template <typename Strategy>
static inline typename Strategy::within_point_box_strategy_type
within(Strategy const& )
{
return typename Strategy::within_point_box_strategy_type();
}
template <typename Strategy>
static inline typename Strategy::covered_by_point_box_strategy_type
covered_by(Strategy const&)
{
return typename Strategy::covered_by_point_box_strategy_type();
}
};
template <overlay_type OverlayType>
struct check_within
{
template
<
typename Turn, typename Geometry0, typename Geometry1,
typename UmbrellaStrategy
>
static inline
bool apply(Turn const& turn, Geometry0 const& geometry0,
Geometry1 const& geometry1, UmbrellaStrategy const& strategy)
{
typedef typename Turn::point_type point_type;
// Operations 0 and 1 have the same source index in self-turns
return turn.operations[0].seg_id.source_index == 0
? geometry::within(turn.point, geometry1,
check_within_strategy<point_type, Geometry1>::within(strategy))
: geometry::within(turn.point, geometry0,
check_within_strategy<point_type, Geometry0>::within(strategy));
}
};
template <>
struct check_within<overlay_difference>
{
template
<
typename Turn, typename Geometry0, typename Geometry1,
typename UmbrellaStrategy
>
static inline
bool apply(Turn const& turn, Geometry0 const& geometry0,
Geometry1 const& geometry1, UmbrellaStrategy const& strategy)
{
typedef typename Turn::point_type point_type;
// difference = intersection(a, reverse(b))
// therefore we should reverse the meaning of within for geometry1
return turn.operations[0].seg_id.source_index == 0
? ! geometry::covered_by(turn.point, geometry1,
check_within_strategy<point_type, Geometry1>::covered_by(strategy))
: geometry::within(turn.point, geometry0,
check_within_strategy<point_type, Geometry0>::within(strategy));
}
};
struct discard_turns
{
template
<
typename Turns, typename Clusters,
typename Geometry0, typename Geometry1,
typename Strategy
>
static inline
void apply(Turns& , Clusters const& ,
Geometry0 const& , Geometry1 const& ,
Strategy const& )
{}
};
template <overlay_type OverlayType, operation_type OperationType>
struct discard_closed_turns : discard_turns {};
// It is only implemented for operation_union, not in buffer
template <>
struct discard_closed_turns<overlay_union, operation_union>
{
// Point in Geometry Strategy
template
<
typename Turns, typename Clusters,
typename Geometry0, typename Geometry1,
typename Strategy
>
static inline
void apply(Turns& turns, Clusters const& /*clusters*/,
Geometry0 const& geometry0, Geometry1 const& geometry1,
Strategy const& strategy)
{
typedef typename boost::range_value<Turns>::type turn_type;
for (typename boost::range_iterator<Turns>::type
it = boost::begin(turns);
it != boost::end(turns);
++it)
{
turn_type& turn = *it;
if (! turn.discarded
&& is_self_turn<overlay_union>(turn)
&& check_within<overlay_union>::apply(turn, geometry0,
geometry1, strategy))
{
// Turn is in the interior of other geometry
turn.discarded = true;
}
}
}
};
template <overlay_type OverlayType>
struct discard_self_intersection_turns
{
private :
template <typename Turns, typename Clusters>
static inline
bool is_self_cluster(signed_size_type cluster_id,
const Turns& turns, Clusters const& clusters)
{
typename Clusters::const_iterator cit = clusters.find(cluster_id);
if (cit == clusters.end())
{
return false;
}
cluster_info const& cinfo = cit->second;
for (std::set<signed_size_type>::const_iterator it
= cinfo.turn_indices.begin();
it != cinfo.turn_indices.end(); ++it)
{
if (! is_self_turn<OverlayType>(turns[*it]))
{
return false;
}
}
return true;
}
template <typename Turns, typename Clusters,
typename Geometry0, typename Geometry1, typename Strategy>
static inline
void discard_clusters(Turns& turns, Clusters const& clusters,
Geometry0 const& geometry0, Geometry1 const& geometry1,
Strategy const& strategy)
{
for (typename Clusters::const_iterator cit = clusters.begin();
cit != clusters.end(); ++cit)
{
signed_size_type const cluster_id = cit->first;
// If there are only self-turns in the cluster, the cluster should
// be located within the other geometry, for intersection
if (! cit->second.turn_indices.empty()
&& is_self_cluster(cluster_id, turns, clusters))
{
cluster_info const& cinfo = cit->second;
signed_size_type const index = *cinfo.turn_indices.begin();
if (! check_within<OverlayType>::apply(turns[index],
geometry0, geometry1,
strategy))
{
// Discard all turns in cluster
for (std::set<signed_size_type>::const_iterator sit
= cinfo.turn_indices.begin();
sit != cinfo.turn_indices.end(); ++sit)
{
turns[*sit].discarded = true;
}
}
}
}
}
public :
template <typename Turns, typename Clusters,
typename Geometry0, typename Geometry1, typename Strategy>
static inline
void apply(Turns& turns, Clusters const& clusters,
Geometry0 const& geometry0, Geometry1 const& geometry1,
Strategy const& strategy)
{
discard_clusters(turns, clusters, geometry0, geometry1, strategy);
typedef typename boost::range_value<Turns>::type turn_type;
for (typename boost::range_iterator<Turns>::type
it = boost::begin(turns);
it != boost::end(turns);
++it)
{
turn_type& turn = *it;
// It is a ii self-turn
// Check if it is within the other geometry
if (! turn.discarded
&& is_self_turn<overlay_intersection>(turn)
&& ! check_within<OverlayType>::apply(turn, geometry0,
geometry1, strategy))
{
// It is not within another geometry, set it as non startable.
// It still might be traveled (#case_recursive_boxes_70)
turn.operations[0].enriched.startable = false;
turn.operations[1].enriched.startable = false;
}
}
}
};
template <overlay_type OverlayType, operation_type OperationType>
struct discard_open_turns : discard_turns {};
// Handler for intersection
template <>
struct discard_open_turns<overlay_intersection, operation_intersection>
: discard_self_intersection_turns<overlay_intersection> {};
// Handler for difference, with different meaning of 'within'
template <>
struct discard_open_turns<overlay_difference, operation_intersection>
: discard_self_intersection_turns<overlay_difference> {};
}} // namespace detail::overlay
#endif //DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_SELF_TURNS_HPP