blob: d4ebcf296bb015cfa47c64f6f9f74b7e4a87798c [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP
#include <algorithm>
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/relate/turns.hpp>
#include <boost/geometry/algorithms/detail/turns/compare_turns.hpp>
#include <boost/geometry/algorithms/detail/turns/filter_continue_turns.hpp>
#include <boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp>
#include <boost/geometry/algorithms/convert.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
{
template
<
typename LineStringOut,
overlay_type OverlayType,
typename Geometry,
typename GeometryTag
>
struct linear_linear_no_intersections;
template <typename LineStringOut, typename LineString>
struct linear_linear_no_intersections
<
LineStringOut, overlay_difference, LineString, linestring_tag
>
{
template <typename OutputIterator>
static inline OutputIterator apply(LineString const& linestring,
OutputIterator oit)
{
LineStringOut ls_out;
geometry::convert(linestring, ls_out);
*oit++ = ls_out;
return oit;
}
};
template <typename LineStringOut, typename MultiLineString>
struct linear_linear_no_intersections
<
LineStringOut,
overlay_difference,
MultiLineString,
multi_linestring_tag
>
{
template <typename OutputIterator>
static inline OutputIterator apply(MultiLineString const& multilinestring,
OutputIterator oit)
{
for (typename boost::range_iterator<MultiLineString const>::type
it = boost::begin(multilinestring);
it != boost::end(multilinestring); ++it)
{
LineStringOut ls_out;
geometry::convert(*it, ls_out);
*oit++ = ls_out;
}
return oit;
}
};
template <typename LineStringOut, typename Geometry, typename GeometryTag>
struct linear_linear_no_intersections
<
LineStringOut, overlay_intersection, Geometry, GeometryTag
>
{
template <typename OutputIterator>
static inline OutputIterator apply(Geometry const&,
OutputIterator oit)
{
return oit;
}
};
template
<
typename Linear1,
typename Linear2,
typename LinestringOut,
overlay_type OverlayType,
bool EnableFilterContinueTurns = false,
bool EnableRemoveDuplicateTurns = false,
bool EnableDegenerateTurns = true,
#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
bool EnableFollowIsolatedPoints = false
#else
bool EnableFollowIsolatedPoints = true
#endif
>
class linear_linear_linestring
{
protected:
struct assign_policy
{
static bool const include_no_turn = false;
static bool const include_degenerate = EnableDegenerateTurns;
static bool const include_opposite = false;
template
<
typename Info,
typename Point1,
typename Point2,
typename IntersectionInfo
>
static inline void apply(Info& , Point1 const& , Point2 const& ,
IntersectionInfo const& )
{
}
};
template
<
typename Turns,
typename LinearGeometry1,
typename LinearGeometry2
>
static inline void compute_turns(Turns& turns,
LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2)
{
turns.clear();
geometry::detail::relate::turns::get_turns
<
LinearGeometry1,
LinearGeometry2,
detail::get_turns::get_turn_info_type
<
LinearGeometry1,
LinearGeometry2,
assign_policy
>
>::apply(turns, linear1, linear2);
}
template
<
overlay_type OverlayTypeForFollow,
bool FollowIsolatedPoints,
typename Turns,
typename LinearGeometry1,
typename LinearGeometry2,
typename OutputIterator
>
static inline OutputIterator
sort_and_follow_turns(Turns& turns,
LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2,
OutputIterator oit)
{
// remove turns that have no added value
turns::filter_continue_turns
<
Turns,
EnableFilterContinueTurns && OverlayType != overlay_intersection
>::apply(turns);
// sort by seg_id, distance, and operation
std::sort(boost::begin(turns), boost::end(turns),
detail::turns::less_seg_fraction_other_op<>());
// remove duplicate turns
turns::remove_duplicate_turns
<
Turns, EnableRemoveDuplicateTurns
>::apply(turns);
return detail::overlay::following::linear::follow
<
LinestringOut,
LinearGeometry1,
LinearGeometry2,
OverlayTypeForFollow,
FollowIsolatedPoints,
!EnableFilterContinueTurns || OverlayType == overlay_intersection
>::apply(linear1, linear2, boost::begin(turns), boost::end(turns),
oit);
}
public:
template
<
typename RobustPolicy, typename OutputIterator, typename Strategy
>
static inline OutputIterator apply(Linear1 const& linear1,
Linear2 const& linear2,
RobustPolicy const&,
OutputIterator oit,
Strategy const& )
{
typedef typename detail::relate::turns::get_turns
<
Linear1, Linear2
>::turn_info turn_info;
typedef std::vector<turn_info> turns_container;
turns_container turns;
compute_turns(turns, linear1, linear2);
if ( turns.empty() )
{
// the two linear geometries are disjoint
return linear_linear_no_intersections
<
LinestringOut,
OverlayType,
Linear1,
typename tag<Linear1>::type
>::apply(linear1, oit);
}
return sort_and_follow_turns
<
OverlayType,
EnableFollowIsolatedPoints
&& OverlayType == overlay_intersection
>(turns, linear1, linear2, oit);
}
};
template
<
typename Linear1,
typename Linear2,
typename LinestringOut,
bool EnableFilterContinueTurns,
bool EnableRemoveDuplicateTurns,
bool EnableDegenerateTurns,
bool EnableFollowIsolatedPoints
>
struct linear_linear_linestring
<
Linear1, Linear2, LinestringOut, overlay_union,
EnableFilterContinueTurns, EnableRemoveDuplicateTurns,
EnableDegenerateTurns, EnableFollowIsolatedPoints
>
{
template
<
typename RobustPolicy, typename OutputIterator, typename Strategy
>
static inline OutputIterator apply(Linear1 const& linear1,
Linear2 const& linear2,
RobustPolicy const& robust_policy,
OutputIterator oit,
Strategy const& strategy)
{
oit = linear_linear_no_intersections
<
LinestringOut,
overlay_difference,
Linear1,
typename tag<Linear1>::type
>::apply(linear1, oit);
return linear_linear_linestring
<
Linear2, Linear1, LinestringOut, overlay_difference,
EnableFilterContinueTurns, EnableRemoveDuplicateTurns,
EnableDegenerateTurns, EnableFollowIsolatedPoints
>::apply(linear2, linear1, robust_policy, oit, strategy);
}
};
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP