update boost on linux
This commit is contained in:
62
linx64/include/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
Executable file
62
linx64/include/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
Executable file
@@ -0,0 +1,62 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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_BUFFER_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
|
||||
struct box_loop
|
||||
{
|
||||
typedef typename coordinate_type<BoxOut>::type coordinate_type;
|
||||
|
||||
static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
coordinate_type d = distance;
|
||||
set<C, D>(box_out, get<C, D>(box_in) + d);
|
||||
box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
|
||||
struct box_loop<BoxIn, BoxOut, T, C, N, N>
|
||||
{
|
||||
static inline void apply(BoxIn const&, T const&, BoxOut&) {}
|
||||
};
|
||||
|
||||
// Extends a box with the same amount in all directions
|
||||
template<typename BoxIn, typename BoxOut, typename T>
|
||||
inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
assert_dimension_equal<BoxIn, BoxOut>();
|
||||
|
||||
static const std::size_t N = dimension<BoxIn>::value;
|
||||
|
||||
box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
|
||||
box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
|
||||
@@ -41,10 +41,6 @@
|
||||
|
||||
#include <boost/geometry/views/detail/normalized_view.hpp>
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)
|
||||
#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -67,45 +63,21 @@ inline void simplify_input(Range const& range,
|
||||
// sensitive to small scale input features, however the result will
|
||||
// look better.
|
||||
// It also gets rid of duplicate points
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)
|
||||
geometry::simplify(range, simplified, distance.simplify_distance());
|
||||
#else
|
||||
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
typedef strategy::distance::detail::projected_point_ax<> ax_type;
|
||||
typedef typename strategy::distance::services::return_type
|
||||
typedef typename geometry::point_type<Range>::type point_type;
|
||||
typedef typename strategy::distance::services::default_strategy
|
||||
<
|
||||
strategy::distance::detail::projected_point_ax<>,
|
||||
point_type,
|
||||
point_type
|
||||
>::type return_type;
|
||||
|
||||
typedef strategy::distance::detail::projected_point_ax_less
|
||||
point_tag, segment_tag, point_type
|
||||
>::type ds_strategy_type;
|
||||
typedef strategy::simplify::douglas_peucker
|
||||
<
|
||||
return_type
|
||||
> comparator_type;
|
||||
point_type, ds_strategy_type
|
||||
> strategy_type;
|
||||
|
||||
typedef strategy::simplify::detail::douglas_peucker
|
||||
<
|
||||
point_type,
|
||||
strategy::distance::detail::projected_point_ax<>,
|
||||
comparator_type
|
||||
> dp_ax;
|
||||
geometry::detail::simplify::simplify_range<2>::apply(range,
|
||||
simplified, distance.simplify_distance(),
|
||||
strategy_type());
|
||||
|
||||
return_type max_distance(distance.simplify_distance() * 2.0,
|
||||
distance.simplify_distance());
|
||||
comparator_type comparator(max_distance);
|
||||
dp_ax strategy(comparator);
|
||||
|
||||
geometry::simplify(range, simplified, max_distance, strategy);
|
||||
#endif
|
||||
|
||||
if (boost::size(simplified) == 2
|
||||
&& geometry::equals(geometry::range::front(simplified),
|
||||
geometry::range::back(simplified)))
|
||||
{
|
||||
traits::resize<Range>::apply(simplified, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +94,8 @@ struct buffer_range
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
void add_join(Collection& collection,
|
||||
@@ -133,18 +106,19 @@ struct buffer_range
|
||||
Point const& input,
|
||||
output_point_type const& perp1,
|
||||
output_point_type const& perp2,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& )
|
||||
RobustPolicy const& ,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
output_point_type intersection_point;
|
||||
geometry::assign_zero(intersection_point);
|
||||
|
||||
strategy::buffer::join_selector join
|
||||
= get_join_type(penultimate_input, previous_input, input);
|
||||
if (join == strategy::buffer::join_convex)
|
||||
geometry::strategy::buffer::join_selector join
|
||||
= get_join_type(penultimate_input, previous_input, input, strategy);
|
||||
if (join == geometry::strategy::buffer::join_convex)
|
||||
{
|
||||
// Calculate the intersection-point formed by the two sides.
|
||||
// It might be that the two sides are not convex, but continue
|
||||
@@ -157,23 +131,23 @@ struct buffer_range
|
||||
|
||||
switch(join)
|
||||
{
|
||||
case strategy::buffer::join_continue :
|
||||
case geometry::strategy::buffer::join_continue :
|
||||
// No join, we get two consecutive sides
|
||||
break;
|
||||
case strategy::buffer::join_concave :
|
||||
case geometry::strategy::buffer::join_concave :
|
||||
{
|
||||
std::vector<output_point_type> range_out;
|
||||
range_out.push_back(prev_perp2);
|
||||
range_out.push_back(previous_input);
|
||||
collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
|
||||
range_out.clear();
|
||||
range_out.push_back(previous_input);
|
||||
range_out.push_back(perp1);
|
||||
collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
}
|
||||
break;
|
||||
case strategy::buffer::join_spike :
|
||||
case geometry::strategy::buffer::join_spike :
|
||||
{
|
||||
// For linestrings, only add spike at one side to avoid
|
||||
// duplicates
|
||||
@@ -183,7 +157,7 @@ struct buffer_range
|
||||
collection.set_current_ring_concave();
|
||||
}
|
||||
break;
|
||||
case strategy::buffer::join_convex :
|
||||
case geometry::strategy::buffer::join_convex :
|
||||
{
|
||||
// The corner is convex, we create a join
|
||||
// TODO (future) - avoid a separate vector, add the piece directly
|
||||
@@ -193,7 +167,7 @@ struct buffer_range
|
||||
distance.apply(previous_input, input, side),
|
||||
range_out))
|
||||
{
|
||||
collection.add_piece(strategy::buffer::buffered_join,
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_join,
|
||||
previous_input, range_out);
|
||||
}
|
||||
}
|
||||
@@ -201,27 +175,24 @@ struct buffer_range
|
||||
}
|
||||
}
|
||||
|
||||
static inline strategy::buffer::join_selector get_join_type(
|
||||
template <typename Strategy>
|
||||
static inline geometry::strategy::buffer::join_selector get_join_type(
|
||||
output_point_type const& p0,
|
||||
output_point_type const& p1,
|
||||
output_point_type const& p2)
|
||||
output_point_type const& p2,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<output_point_type>::type
|
||||
>::type side_strategy;
|
||||
|
||||
int const side = side_strategy::apply(p0, p1, p2);
|
||||
return side == -1 ? strategy::buffer::join_convex
|
||||
: side == 1 ? strategy::buffer::join_concave
|
||||
int const side = strategy.apply(p0, p1, p2);
|
||||
return side == -1 ? geometry::strategy::buffer::join_convex
|
||||
: side == 1 ? geometry::strategy::buffer::join_concave
|
||||
: parallel_continue
|
||||
(
|
||||
get<0>(p2) - get<0>(p1),
|
||||
get<1>(p2) - get<1>(p1),
|
||||
get<0>(p1) - get<0>(p0),
|
||||
get<1>(p1) - get<1>(p0)
|
||||
) ? strategy::buffer::join_continue
|
||||
: strategy::buffer::join_spike;
|
||||
) ? geometry::strategy::buffer::join_continue
|
||||
: geometry::strategy::buffer::join_spike;
|
||||
}
|
||||
|
||||
template
|
||||
@@ -232,16 +203,19 @@ struct buffer_range
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code iterate(Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
bool linear,
|
||||
output_point_type& first_p1,
|
||||
output_point_type& first_p2,
|
||||
output_point_type& last_p1,
|
||||
@@ -273,7 +247,11 @@ struct buffer_range
|
||||
* pup: penultimate_point
|
||||
*/
|
||||
|
||||
strategy::buffer::result_code result = strategy::buffer::result_no_output;
|
||||
bool const mark_flat
|
||||
= linear
|
||||
&& end_strategy.get_piece_type() == geometry::strategy::buffer::buffered_flat_end;
|
||||
|
||||
geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
|
||||
bool first = true;
|
||||
|
||||
Iterator it = begin;
|
||||
@@ -284,25 +262,25 @@ struct buffer_range
|
||||
for (Iterator prev = it++; it != end; ++it)
|
||||
{
|
||||
generated_side.clear();
|
||||
strategy::buffer::result_code error_code
|
||||
geometry::strategy::buffer::result_code error_code
|
||||
= side_strategy.apply(*prev, *it, side,
|
||||
distance_strategy, generated_side);
|
||||
|
||||
if (error_code == strategy::buffer::result_no_output)
|
||||
if (error_code == geometry::strategy::buffer::result_no_output)
|
||||
{
|
||||
// Because input is simplified, this is improbable,
|
||||
// but it can happen for degenerate geometries
|
||||
// Further handling of this side is skipped
|
||||
continue;
|
||||
}
|
||||
else if (error_code == strategy::buffer::result_error_numerical)
|
||||
else if (error_code == geometry::strategy::buffer::result_error_numerical)
|
||||
{
|
||||
return error_code;
|
||||
}
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! generated_side.empty());
|
||||
|
||||
result = strategy::buffer::result_normal;
|
||||
result = geometry::strategy::buffer::result_normal;
|
||||
|
||||
if (! first)
|
||||
{
|
||||
@@ -312,11 +290,16 @@ struct buffer_range
|
||||
*it, generated_side.front(), generated_side.back(),
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
|
||||
collection.add_side_piece(*prev, *it, generated_side, first);
|
||||
|
||||
if (first && mark_flat)
|
||||
{
|
||||
collection.mark_flat_start();
|
||||
}
|
||||
|
||||
penultimate_point = *prev;
|
||||
ultimate_point = *it;
|
||||
last_p1 = generated_side.front();
|
||||
@@ -330,6 +313,12 @@ struct buffer_range
|
||||
first_p2 = generated_side.back();
|
||||
}
|
||||
}
|
||||
|
||||
if (mark_flat)
|
||||
{
|
||||
collection.mark_flat_end();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -350,7 +339,8 @@ struct buffer_multi
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Multi const& multi,
|
||||
Collection& collection,
|
||||
@@ -359,7 +349,8 @@ struct buffer_multi
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
for (typename boost::range_iterator<Multi const>::type
|
||||
it = boost::begin(multi);
|
||||
@@ -369,7 +360,7 @@ struct buffer_multi
|
||||
Policy::apply(*it, collection,
|
||||
distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -393,12 +384,12 @@ inline void buffer_point(Point const& point, Collection& collection,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
PointStrategy const& point_strategy)
|
||||
{
|
||||
collection.start_new_ring();
|
||||
collection.start_new_ring(false);
|
||||
std::vector<OutputPointType> range_out;
|
||||
point_strategy.apply(point, distance_strategy, range_out);
|
||||
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_point, range_out, false);
|
||||
collection.set_piece_center(point);
|
||||
collection.finish_ring(strategy::buffer::result_normal);
|
||||
collection.finish_ring(geometry::strategy::buffer::result_normal);
|
||||
}
|
||||
|
||||
|
||||
@@ -436,7 +427,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Point const& point, Collection& collection,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
@@ -444,7 +436,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
|
||||
JoinStrategy const& ,
|
||||
EndStrategy const& ,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& )
|
||||
RobustPolicy const& ,
|
||||
Strategy const& ) // side strategy
|
||||
{
|
||||
detail::buffer::buffer_point
|
||||
<
|
||||
@@ -472,29 +465,32 @@ struct buffer_inserter_ring
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code iterate(Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
output_point_type first_p1, first_p2, last_p1, last_p2;
|
||||
|
||||
typedef detail::buffer::buffer_range<RingOutput> buffer_range;
|
||||
|
||||
strategy::buffer::result_code result
|
||||
geometry::strategy::buffer::result_code result
|
||||
= buffer_range::iterate(collection, begin, end,
|
||||
side,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
first_p1, first_p2, last_p1, last_p2);
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
false, first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
// Generate closing join
|
||||
if (result == strategy::buffer::result_normal)
|
||||
if (result == geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
buffer_range::add_join(collection,
|
||||
*(end - 2),
|
||||
@@ -502,7 +498,7 @@ struct buffer_inserter_ring
|
||||
*(begin + 1), first_p1, first_p2,
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
|
||||
// Buffer is closed automatically by last closing corner
|
||||
@@ -517,21 +513,23 @@ struct buffer_inserter_ring
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code apply(RingInput const& ring,
|
||||
static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
RingInput simplified;
|
||||
detail::buffer::simplify_input(ring, distance, simplified);
|
||||
|
||||
strategy::buffer::result_code code = strategy::buffer::result_no_output;
|
||||
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
|
||||
|
||||
std::size_t n = boost::size(simplified);
|
||||
std::size_t const min_points = core_detail::closure::minimum_ring_size
|
||||
@@ -546,18 +544,20 @@ struct buffer_inserter_ring
|
||||
{
|
||||
// Walk backwards (rings will be reversed afterwards)
|
||||
code = iterate(collection, boost::rbegin(view), boost::rend(view),
|
||||
strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy);
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
code = iterate(collection, boost::begin(view), boost::end(view),
|
||||
strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy);
|
||||
geometry::strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
if (code == strategy::buffer::result_no_output && n >= 1)
|
||||
if (code == geometry::strategy::buffer::result_no_output && n >= 1)
|
||||
{
|
||||
// Use point_strategy to buffer degenerated ring
|
||||
detail::buffer::buffer_point<output_point_type>
|
||||
@@ -586,23 +586,25 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code apply(RingInput const& ring,
|
||||
static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
collection.start_new_ring();
|
||||
strategy::buffer::result_code const code
|
||||
collection.start_new_ring(distance.negative());
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= buffer_inserter_ring<RingInput, RingOutput>::apply(ring,
|
||||
collection, distance,
|
||||
side_strategy, join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
collection.finish_ring(code);
|
||||
return code;
|
||||
}
|
||||
@@ -627,16 +629,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code iterate(Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
output_point_type& first_p1)
|
||||
{
|
||||
input_point_type const& ultimate_point = *(end - 1);
|
||||
@@ -647,18 +651,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
// we have it already from the first phase (left).
|
||||
// But for the first pass, we have to generate it
|
||||
output_point_type reverse_p1;
|
||||
if (side == strategy::buffer::buffer_side_right)
|
||||
if (side == geometry::strategy::buffer::buffer_side_right)
|
||||
{
|
||||
reverse_p1 = first_p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<output_point_type> generated_side;
|
||||
strategy::buffer::result_code code
|
||||
geometry::strategy::buffer::result_code code
|
||||
= side_strategy.apply(ultimate_point, penultimate_point,
|
||||
strategy::buffer::buffer_side_right,
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance_strategy, generated_side);
|
||||
if (code != strategy::buffer::result_normal)
|
||||
if (code != geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
// No output or numerical error
|
||||
return code;
|
||||
@@ -668,16 +672,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
|
||||
output_point_type first_p2, last_p1, last_p2;
|
||||
|
||||
strategy::buffer::result_code result
|
||||
geometry::strategy::buffer::result_code result
|
||||
= detail::buffer::buffer_range<output_ring_type>::iterate(collection,
|
||||
begin, end, side,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
first_p1, first_p2, last_p1, last_p2);
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
true, first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
if (result == strategy::buffer::result_normal)
|
||||
if (result == geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
std::vector<output_point_type> range_out;
|
||||
end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);
|
||||
end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1,
|
||||
side, distance_strategy, range_out);
|
||||
collection.add_endcap(end_strategy, range_out, ultimate_point);
|
||||
}
|
||||
return result;
|
||||
@@ -691,42 +697,47 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code apply(Linestring const& linestring, Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code apply(Linestring const& linestring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
Linestring simplified;
|
||||
detail::buffer::simplify_input(linestring, distance, simplified);
|
||||
|
||||
strategy::buffer::result_code code = strategy::buffer::result_no_output;
|
||||
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
|
||||
std::size_t n = boost::size(simplified);
|
||||
if (n > 1)
|
||||
{
|
||||
collection.start_new_ring();
|
||||
collection.start_new_ring(false);
|
||||
output_point_type first_p1;
|
||||
code = iterate(collection,
|
||||
boost::begin(simplified), boost::end(simplified),
|
||||
strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
geometry::strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
first_p1);
|
||||
|
||||
if (code == strategy::buffer::result_normal)
|
||||
if (code == geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
code = iterate(collection,
|
||||
boost::rbegin(simplified), boost::rend(simplified),
|
||||
strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
first_p1);
|
||||
}
|
||||
collection.finish_ring(code);
|
||||
}
|
||||
if (code == strategy::buffer::result_no_output && n >= 1)
|
||||
if (code == geometry::strategy::buffer::result_no_output && n >= 1)
|
||||
{
|
||||
// Use point_strategy to buffer degenerated linestring
|
||||
detail::buffer::buffer_point<output_point_type>
|
||||
@@ -763,7 +774,8 @@ private:
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
void iterate(Iterator begin, Iterator end,
|
||||
@@ -774,15 +786,22 @@ private:
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
bool is_interior)
|
||||
{
|
||||
for (Iterator it = begin; it != end; ++it)
|
||||
{
|
||||
collection.start_new_ring();
|
||||
strategy::buffer::result_code const code
|
||||
// For exterior rings, it deflates if distance is negative.
|
||||
// For interior rings, it is vice versa
|
||||
bool const deflate = is_interior
|
||||
? ! distance.negative()
|
||||
: distance.negative();
|
||||
|
||||
collection.start_new_ring(deflate);
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= policy::apply(*it, collection, distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
|
||||
collection.finish_ring(code, is_interior);
|
||||
}
|
||||
@@ -797,7 +816,8 @@ private:
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
void apply_interior_rings(InteriorRings const& interior_rings,
|
||||
@@ -807,12 +827,13 @@ private:
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
iterate(boost::begin(interior_rings), boost::end(interior_rings),
|
||||
collection, distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, true);
|
||||
robust_policy, strategy, true);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -824,7 +845,8 @@ public:
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(PolygonInput const& polygon,
|
||||
Collection& collection,
|
||||
@@ -833,16 +855,17 @@ public:
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
{
|
||||
collection.start_new_ring();
|
||||
collection.start_new_ring(distance.negative());
|
||||
|
||||
strategy::buffer::result_code const code
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= policy::apply(exterior_ring(polygon), collection,
|
||||
distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
|
||||
collection.finish_ring(code, false,
|
||||
geometry::num_interior_rings(polygon) > 0u);
|
||||
@@ -851,7 +874,7 @@ public:
|
||||
apply_interior_rings(interior_rings(polygon),
|
||||
collection, distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -927,11 +950,6 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
typename tag_cast<typename tag<GeometryInput>::type, areal_tag>::type,
|
||||
areal_tag
|
||||
>::type::value;
|
||||
bool const linear = boost::is_same
|
||||
<
|
||||
typename tag_cast<typename tag<GeometryInput>::type, linear_tag>::type,
|
||||
linear_tag
|
||||
>::type::value;
|
||||
|
||||
dispatch::buffer_inserter
|
||||
<
|
||||
@@ -945,10 +963,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
>::apply(geometry_input, collection,
|
||||
distance_strategy, side_strategy, join_strategy,
|
||||
end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, intersection_strategy.get_side_strategy());
|
||||
|
||||
collection.get_turns();
|
||||
collection.classify_turns(linear);
|
||||
collection.classify_turns();
|
||||
if (BOOST_GEOMETRY_CONDITION(areal))
|
||||
{
|
||||
collection.check_remaining_points(distance_strategy);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-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,
|
||||
@@ -13,10 +13,6 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
|
||||
# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
@@ -26,6 +22,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
@@ -127,6 +124,10 @@ public :
|
||||
void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,
|
||||
detail::overlay::traverse_error_type )
|
||||
{}
|
||||
|
||||
template <typename Rings>
|
||||
void visit_generated_rings(Rings const& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -177,9 +178,7 @@ struct buffer_turn_info
|
||||
|
||||
intersection_location_type location;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;
|
||||
#endif
|
||||
|
||||
std::size_t count_within;
|
||||
|
||||
@@ -189,9 +188,7 @@ struct buffer_turn_info
|
||||
|
||||
std::size_t count_on_offsetted;
|
||||
std::size_t count_on_helper;
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
std::size_t count_within_near_offsetted;
|
||||
#endif
|
||||
|
||||
bool remove_on_multi;
|
||||
|
||||
@@ -208,9 +205,7 @@ struct buffer_turn_info
|
||||
, count_in_original(0)
|
||||
, count_on_offsetted(0)
|
||||
, count_on_helper(0)
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
, count_within_near_offsetted(0)
|
||||
#endif
|
||||
, remove_on_multi(false)
|
||||
, count_on_occupied(0)
|
||||
, count_on_multi(0)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2016-2017.
|
||||
// Modifications copyright (c) 2016-2017 Oracle and/or its affiliates.
|
||||
// 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,
|
||||
@@ -46,6 +47,7 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
@@ -142,10 +144,34 @@ struct buffered_piece_collection
|
||||
robust_point_type
|
||||
>::type robust_comparable_radius_type;
|
||||
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
|
||||
typedef typename IntersectionStrategy::envelope_strategy_type envelope_strategy_type;
|
||||
typedef typename IntersectionStrategy::expand_strategy_type expand_strategy_type;
|
||||
|
||||
typedef typename IntersectionStrategy::template area_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type
|
||||
>::type side_strategy;
|
||||
point_type
|
||||
>::type area_strategy_type;
|
||||
|
||||
typedef typename IntersectionStrategy::template area_strategy
|
||||
<
|
||||
robust_point_type
|
||||
>::type robust_area_strategy_type;
|
||||
|
||||
typedef typename area_strategy_type::template result_type
|
||||
<
|
||||
point_type
|
||||
>::type area_result_type;
|
||||
typedef typename robust_area_strategy_type::template result_type
|
||||
<
|
||||
robust_point_type
|
||||
>::type robust_area_result_type;
|
||||
|
||||
typedef typename strategy::point_in_geometry::services::default_strategy
|
||||
<
|
||||
robust_point_type,
|
||||
robust_ring_type
|
||||
>::type point_in_geometry_strategy_type;
|
||||
|
||||
typedef typename geometry::rescale_policy_type
|
||||
<
|
||||
@@ -206,7 +232,10 @@ struct buffered_piece_collection
|
||||
// 2: half, not part of offsetted rings - part of robust ring
|
||||
std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
|
||||
#endif
|
||||
bool is_flat_start;
|
||||
bool is_flat_end;
|
||||
|
||||
bool is_deflated;
|
||||
bool is_convex;
|
||||
bool is_monotonic_increasing[2]; // 0=x, 1=y
|
||||
bool is_monotonic_decreasing[2]; // 0=x, 1=y
|
||||
@@ -234,6 +263,9 @@ struct buffered_piece_collection
|
||||
, right_index(-1)
|
||||
, last_segment_index(-1)
|
||||
, offsetted_count(-1)
|
||||
, is_flat_start(false)
|
||||
, is_flat_end(false)
|
||||
, is_deflated(false)
|
||||
, is_convex(false)
|
||||
, robust_min_comparable_radius(0)
|
||||
, robust_max_comparable_radius(0)
|
||||
@@ -256,12 +288,14 @@ struct buffered_piece_collection
|
||||
{}
|
||||
|
||||
inline robust_original(robust_ring_type const& ring,
|
||||
bool is_interior, bool has_interiors)
|
||||
bool is_interior, bool has_interiors,
|
||||
envelope_strategy_type const& envelope_strategy,
|
||||
expand_strategy_type const& expand_strategy)
|
||||
: m_ring(ring)
|
||||
, m_is_interior(is_interior)
|
||||
, m_has_interiors(has_interiors)
|
||||
{
|
||||
geometry::envelope(m_ring, m_box);
|
||||
geometry::envelope(m_ring, m_box, envelope_strategy);
|
||||
|
||||
// create monotonic sections in x-dimension
|
||||
// The dimension is critical because the direction is later used
|
||||
@@ -269,7 +303,8 @@ struct buffered_piece_collection
|
||||
// and this strategy is scanning in x direction.
|
||||
typedef boost::mpl::vector_c<std::size_t, 0> dimensions;
|
||||
geometry::sectionalize<false, dimensions>(m_ring,
|
||||
detail::no_rescale_policy(), m_sections);
|
||||
detail::no_rescale_policy(), m_sections,
|
||||
envelope_strategy, expand_strategy);
|
||||
}
|
||||
|
||||
robust_ring_type m_ring;
|
||||
@@ -285,6 +320,8 @@ struct buffered_piece_collection
|
||||
piece_vector_type m_pieces;
|
||||
turn_vector_type m_turns;
|
||||
signed_size_type m_first_piece_index;
|
||||
bool m_deflate;
|
||||
bool m_has_deflated;
|
||||
|
||||
buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index
|
||||
std::vector<robust_original> robust_originals; // robust representation of the original(s)
|
||||
@@ -306,7 +343,13 @@ struct buffered_piece_collection
|
||||
|
||||
cluster_type m_clusters;
|
||||
|
||||
IntersectionStrategy const& m_intersection_strategy;
|
||||
IntersectionStrategy m_intersection_strategy;
|
||||
side_strategy_type m_side_strategy;
|
||||
area_strategy_type m_area_strategy;
|
||||
envelope_strategy_type m_envelope_strategy;
|
||||
expand_strategy_type m_expand_strategy;
|
||||
|
||||
robust_area_strategy_type m_robust_area_strategy;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
struct redundant_turn
|
||||
@@ -320,7 +363,14 @@ struct buffered_piece_collection
|
||||
buffered_piece_collection(IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_first_piece_index(-1)
|
||||
, m_deflate(false)
|
||||
, m_has_deflated(false)
|
||||
, m_intersection_strategy(intersection_strategy)
|
||||
, m_side_strategy(intersection_strategy.get_side_strategy())
|
||||
, m_area_strategy(intersection_strategy.template get_area_strategy<point_type>())
|
||||
, m_envelope_strategy(intersection_strategy.get_envelope_strategy())
|
||||
, m_expand_strategy(intersection_strategy.get_expand_strategy())
|
||||
, m_robust_area_strategy(intersection_strategy.template get_area_strategy<robust_point_type>())
|
||||
, m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
@@ -478,11 +528,11 @@ struct buffered_piece_collection
|
||||
for (typename occupation_map_type::iterator it = occupation_map.begin();
|
||||
it != occupation_map.end(); ++it)
|
||||
{
|
||||
it->second.get_left_turns(it->first, m_turns);
|
||||
it->second.get_left_turns(it->first, m_turns, m_side_strategy);
|
||||
}
|
||||
}
|
||||
|
||||
inline void classify_turns(bool linear)
|
||||
inline void classify_turns()
|
||||
{
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
@@ -491,11 +541,10 @@ struct buffered_piece_collection
|
||||
{
|
||||
it->location = inside_buffer;
|
||||
}
|
||||
if (it->count_on_original_boundary > 0 && ! linear)
|
||||
if (it->count_on_original_boundary > 0)
|
||||
{
|
||||
it->location = inside_buffer;
|
||||
}
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
if (it->count_within_near_offsetted > 0)
|
||||
{
|
||||
// Within can have in rare cases a rounding issue. We don't discard this
|
||||
@@ -504,7 +553,94 @@ struct buffered_piece_collection
|
||||
it->operations[0].enriched.startable = false;
|
||||
it->operations[1].enriched.startable = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
struct deflate_properties
|
||||
{
|
||||
bool has_inflated;
|
||||
std::size_t count;
|
||||
|
||||
inline deflate_properties()
|
||||
: has_inflated(false)
|
||||
, count(0u)
|
||||
{}
|
||||
};
|
||||
|
||||
inline void discard_turns_for_deflate()
|
||||
{
|
||||
// Deflate cases should have at least 3 points PER deflated original
|
||||
// to form a correct triangle
|
||||
|
||||
// But if there are intersections between a deflated ring and another
|
||||
// ring, it is all accepted
|
||||
|
||||
// In deflate most turns are i/u by nature, but u/u is also possible
|
||||
|
||||
std::map<signed_size_type, deflate_properties> properties;
|
||||
|
||||
for (typename boost::range_iterator<turn_vector_type const>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
{
|
||||
const buffer_turn_info_type& turn = *it;
|
||||
if (turn.location == location_ok)
|
||||
{
|
||||
const buffer_turn_operation_type& op0 = turn.operations[0];
|
||||
const buffer_turn_operation_type& op1 = turn.operations[1];
|
||||
|
||||
if (! m_pieces[op0.seg_id.piece_index].is_deflated
|
||||
|| ! m_pieces[op1.seg_id.piece_index].is_deflated)
|
||||
{
|
||||
properties[op0.seg_id.multi_index].has_inflated = true;
|
||||
properties[op1.seg_id.multi_index].has_inflated = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is deflated, update counts
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
const buffer_turn_operation_type& op = turn.operations[i];
|
||||
if (op.operation == detail::overlay::operation_union
|
||||
|| op.operation == detail::overlay::operation_continue)
|
||||
{
|
||||
properties[op.seg_id.multi_index].count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
{
|
||||
buffer_turn_info_type& turn = *it;
|
||||
|
||||
if (turn.location == location_ok)
|
||||
{
|
||||
const buffer_turn_operation_type& op0 = turn.operations[0];
|
||||
const buffer_turn_operation_type& op1 = turn.operations[1];
|
||||
signed_size_type const multi0 = op0.seg_id.multi_index;
|
||||
signed_size_type const multi1 = op1.seg_id.multi_index;
|
||||
|
||||
if (multi0 == multi1)
|
||||
{
|
||||
const deflate_properties& prop = properties[multi0];
|
||||
|
||||
// NOTE: Keep brackets around prop.count
|
||||
// avoid gcc-bug "parse error in template argument list"
|
||||
// GCC versions 5.4 and 5.5 (and probably more)
|
||||
if (! prop.has_inflated && (prop.count) < 3)
|
||||
{
|
||||
// Property is not inflated
|
||||
// Not enough points, this might be caused by <float> where
|
||||
// detection turn-in-original failed because of numeric errors
|
||||
turn.location = location_discard;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Two different (possibly deflated) rings
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,6 +649,15 @@ struct buffered_piece_collection
|
||||
{
|
||||
// Check if a turn is inside any of the originals
|
||||
|
||||
typedef turn_in_original_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_point_box_strategy_type
|
||||
> turn_in_original_ovelaps_box_type;
|
||||
typedef original_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_box_box_strategy_type
|
||||
> original_ovelaps_box_type;
|
||||
|
||||
turn_in_original_visitor<turn_vector_type> visitor(m_turns);
|
||||
geometry::partition
|
||||
<
|
||||
@@ -520,8 +665,8 @@ struct buffered_piece_collection
|
||||
include_turn_policy,
|
||||
detail::partition::include_all_policy
|
||||
>::apply(m_turns, robust_originals, visitor,
|
||||
turn_get_box(), turn_in_original_ovelaps_box(),
|
||||
original_get_box(), original_ovelaps_box());
|
||||
turn_get_box(), turn_in_original_ovelaps_box_type(),
|
||||
original_get_box(), original_ovelaps_box_type());
|
||||
|
||||
bool const deflate = distance_strategy.negative();
|
||||
|
||||
@@ -533,7 +678,7 @@ struct buffered_piece_collection
|
||||
{
|
||||
if (deflate && turn.count_in_original <= 0)
|
||||
{
|
||||
// For deflate: it is not in original, discard
|
||||
// For deflate/negative buffers: it is not in original, discard
|
||||
turn.location = location_discard;
|
||||
}
|
||||
else if (! deflate && turn.count_in_original > 0)
|
||||
@@ -543,6 +688,12 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_has_deflated)
|
||||
{
|
||||
// Either strategy was negative, or there were interior rings
|
||||
discard_turns_for_deflate();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool assert_indices_in_robust_rings() const
|
||||
@@ -599,46 +750,47 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// Insert all rescaled turn-points into these rings, to form a
|
||||
// reliable integer-based ring. All turns can be compared (inside) to this
|
||||
// rings to see if they are inside.
|
||||
|
||||
for (typename boost::range_iterator<piece_vector_type>::type
|
||||
it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it)
|
||||
if (! use_side_of_intersection<typename geometry::cs_tag<point_type>::type>::value)
|
||||
{
|
||||
piece& pc = *it;
|
||||
signed_size_type piece_segment_index = pc.first_seg_id.segment_index;
|
||||
if (! pc.robust_turns.empty())
|
||||
// Insert all rescaled turn-points into these rings, to form a
|
||||
// reliable integer-based ring. All turns can be compared (inside) to this
|
||||
// rings to see if they are inside.
|
||||
|
||||
for (typename boost::range_iterator<piece_vector_type>::type
|
||||
it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it)
|
||||
{
|
||||
if (pc.robust_turns.size() > 1u)
|
||||
piece& pc = *it;
|
||||
signed_size_type piece_segment_index = pc.first_seg_id.segment_index;
|
||||
if (! pc.robust_turns.empty())
|
||||
{
|
||||
std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less());
|
||||
}
|
||||
// Walk through them, in reverse to insert at right index
|
||||
signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1;
|
||||
for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type
|
||||
rit = boost::const_rbegin(pc.robust_turns);
|
||||
rit != boost::const_rend(pc.robust_turns);
|
||||
++rit, --index_offset)
|
||||
{
|
||||
signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(
|
||||
index_in_vector > 0
|
||||
&& index_in_vector < pc.offsetted_count
|
||||
);
|
||||
if (pc.robust_turns.size() > 1u)
|
||||
{
|
||||
std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less());
|
||||
}
|
||||
// Walk through them, in reverse to insert at right index
|
||||
signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1;
|
||||
for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type
|
||||
rit = boost::const_rbegin(pc.robust_turns);
|
||||
rit != boost::const_rend(pc.robust_turns);
|
||||
++rit, --index_offset)
|
||||
{
|
||||
signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(
|
||||
index_in_vector > 0
|
||||
&& index_in_vector < pc.offsetted_count
|
||||
);
|
||||
|
||||
pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point);
|
||||
pc.offsetted_count++;
|
||||
pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point);
|
||||
pc.offsetted_count++;
|
||||
|
||||
m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset;
|
||||
m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings());
|
||||
#endif
|
||||
BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings());
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
@@ -699,7 +851,7 @@ struct buffered_piece_collection
|
||||
++it)
|
||||
{
|
||||
piece& pc = *it;
|
||||
if (geometry::area(pc.robust_ring) < 0)
|
||||
if (geometry::area(pc.robust_ring, m_robust_area_strategy) < 0)
|
||||
{
|
||||
// Rings can be ccw:
|
||||
// - in a concave piece
|
||||
@@ -714,7 +866,8 @@ struct buffered_piece_collection
|
||||
// create monotonic sections in y-dimension
|
||||
typedef boost::mpl::vector_c<std::size_t, 1> dimensions;
|
||||
geometry::sectionalize<false, dimensions>(pc.robust_ring,
|
||||
detail::no_rescale_policy(), pc.sections);
|
||||
detail::no_rescale_policy(), pc.sections,
|
||||
m_envelope_strategy, m_expand_strategy);
|
||||
|
||||
// Determine min/max radius
|
||||
typedef geometry::model::referring_segment<robust_point_type const>
|
||||
@@ -778,12 +931,21 @@ struct buffered_piece_collection
|
||||
> visitor(m_pieces, offsetted_rings, m_turns,
|
||||
m_intersection_strategy, m_robust_policy);
|
||||
|
||||
typedef detail::section::get_section_box
|
||||
<
|
||||
typename IntersectionStrategy::expand_box_strategy_type
|
||||
> get_section_box_type;
|
||||
typedef detail::section::overlaps_section_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_box_box_strategy_type
|
||||
> overlaps_section_box_type;
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
robust_box_type
|
||||
>::apply(monotonic_sections, visitor,
|
||||
detail::section::get_section_box(),
|
||||
detail::section::overlaps_section_box());
|
||||
get_section_box_type(),
|
||||
overlaps_section_box_type());
|
||||
}
|
||||
|
||||
insert_rescaled_piece_turns();
|
||||
@@ -798,20 +960,31 @@ struct buffered_piece_collection
|
||||
// Check if it is inside any of the pieces
|
||||
turn_in_piece_visitor
|
||||
<
|
||||
turn_vector_type, piece_vector_type
|
||||
> visitor(m_turns, m_pieces);
|
||||
typename geometry::cs_tag<point_type>::type,
|
||||
turn_vector_type, piece_vector_type,
|
||||
point_in_geometry_strategy_type
|
||||
> visitor(m_turns, m_pieces, point_in_geometry_strategy_type());
|
||||
|
||||
typedef turn_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_point_box_strategy_type
|
||||
> turn_ovelaps_box_type;
|
||||
typedef piece_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_box_box_strategy_type
|
||||
> piece_ovelaps_box_type;
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
robust_box_type
|
||||
>::apply(m_turns, m_pieces, visitor,
|
||||
turn_get_box(), turn_ovelaps_box(),
|
||||
piece_get_box(), piece_ovelaps_box());
|
||||
turn_get_box(), turn_ovelaps_box_type(),
|
||||
piece_get_box(), piece_ovelaps_box_type());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline void start_new_ring()
|
||||
inline void start_new_ring(bool deflate)
|
||||
{
|
||||
signed_size_type const n = static_cast<signed_size_type>(offsetted_rings.size());
|
||||
current_segment_id.source_index = 0;
|
||||
@@ -823,6 +996,13 @@ struct buffered_piece_collection
|
||||
current_robust_ring.clear();
|
||||
|
||||
m_first_piece_index = static_cast<signed_size_type>(boost::size(m_pieces));
|
||||
m_deflate = deflate;
|
||||
if (deflate)
|
||||
{
|
||||
// Pieces contain either deflated exterior rings, or inflated
|
||||
// interior rings which are effectively deflated too
|
||||
m_has_deflated = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void abort_ring()
|
||||
@@ -922,7 +1102,7 @@ struct buffered_piece_collection
|
||||
|
||||
robust_originals.push_back(
|
||||
robust_original(current_robust_ring,
|
||||
is_interior, has_interiors));
|
||||
is_interior, has_interiors, m_envelope_strategy, m_expand_strategy));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -957,12 +1137,12 @@ struct buffered_piece_collection
|
||||
piece pc;
|
||||
pc.type = type;
|
||||
pc.index = static_cast<signed_size_type>(boost::size(m_pieces));
|
||||
pc.is_deflated = m_deflate;
|
||||
|
||||
current_segment_id.piece_index = pc.index;
|
||||
|
||||
pc.first_seg_id = current_segment_id;
|
||||
|
||||
|
||||
// Assign left/right (for first/last piece per ring they will be re-assigned later)
|
||||
pc.left_index = pc.index - 1;
|
||||
pc.right_index = pc.index + 1;
|
||||
@@ -1039,7 +1219,7 @@ struct buffered_piece_collection
|
||||
return;
|
||||
}
|
||||
|
||||
geometry::envelope(pc.robust_ring, pc.robust_envelope);
|
||||
geometry::envelope(pc.robust_ring, pc.robust_envelope, m_envelope_strategy);
|
||||
|
||||
geometry::assign_inverse(pc.robust_offsetted_envelope);
|
||||
for (signed_size_type i = 0; i < pc.offsetted_count; i++)
|
||||
@@ -1216,18 +1396,31 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
inline void mark_flat_start()
|
||||
{
|
||||
if (! m_pieces.empty())
|
||||
{
|
||||
piece& back = m_pieces.back();
|
||||
back.is_flat_start = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void mark_flat_end()
|
||||
{
|
||||
if (! m_pieces.empty())
|
||||
{
|
||||
piece& back = m_pieces.back();
|
||||
back.is_flat_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
inline void enrich()
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Ring>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
enrich_intersection_points<false, false, overlay_buffer>(m_turns,
|
||||
m_clusters, offsetted_rings, offsetted_rings,
|
||||
m_robust_policy, side_strategy_type());
|
||||
m_robust_policy, m_side_strategy);
|
||||
}
|
||||
|
||||
// Discards all rings which do have not-OK intersection points only.
|
||||
@@ -1252,6 +1445,8 @@ struct buffered_piece_collection
|
||||
|
||||
inline bool point_coveredby_original(point_type const& point)
|
||||
{
|
||||
typedef typename IntersectionStrategy::disjoint_point_box_strategy_type d_pb_strategy_type;
|
||||
|
||||
robust_point_type any_point;
|
||||
geometry::recalculate(any_point, point, m_robust_policy);
|
||||
|
||||
@@ -1268,14 +1463,15 @@ struct buffered_piece_collection
|
||||
{
|
||||
robust_original const& original = *it;
|
||||
if (detail::disjoint::disjoint_point_box(any_point,
|
||||
original.m_box))
|
||||
original.m_box,
|
||||
d_pb_strategy_type()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int const geometry_code
|
||||
= detail::within::point_in_geometry(any_point,
|
||||
original.m_ring);
|
||||
original.m_ring, point_in_geometry_strategy_type());
|
||||
|
||||
if (geometry_code == -1)
|
||||
{
|
||||
@@ -1314,7 +1510,7 @@ struct buffered_piece_collection
|
||||
buffered_ring<Ring>& ring = *it;
|
||||
if (! ring.has_intersections()
|
||||
&& boost::size(ring) > 0u
|
||||
&& geometry::area(ring) < 0)
|
||||
&& geometry::area(ring, m_area_strategy) < 0)
|
||||
{
|
||||
if (! point_coveredby_original(geometry::range::front(ring)))
|
||||
{
|
||||
@@ -1358,12 +1554,14 @@ struct buffered_piece_collection
|
||||
overlay_buffer,
|
||||
backtrack_for_buffer
|
||||
> traverser;
|
||||
std::map<ring_identifier, overlay::ring_turn_info> turn_info_per_ring;
|
||||
|
||||
traversed_rings.clear();
|
||||
buffer_overlay_visitor visitor;
|
||||
traverser::apply(offsetted_rings, offsetted_rings,
|
||||
m_intersection_strategy, m_robust_policy,
|
||||
m_turns, traversed_rings,
|
||||
turn_info_per_ring,
|
||||
m_clusters, visitor);
|
||||
}
|
||||
|
||||
@@ -1391,7 +1589,7 @@ struct buffered_piece_collection
|
||||
template <typename GeometryOutput, typename OutputIterator>
|
||||
inline OutputIterator assign(OutputIterator out) const
|
||||
{
|
||||
typedef detail::overlay::ring_properties<point_type> properties;
|
||||
typedef detail::overlay::ring_properties<point_type, area_result_type> properties;
|
||||
|
||||
std::map<ring_identifier, properties> selected;
|
||||
|
||||
@@ -1407,7 +1605,7 @@ struct buffered_piece_collection
|
||||
if (! it->has_intersections()
|
||||
&& ! it->is_untouched_outside_original)
|
||||
{
|
||||
properties p = properties(*it);
|
||||
properties p = properties(*it, m_area_strategy);
|
||||
if (p.valid)
|
||||
{
|
||||
ring_identifier id(0, index, -1);
|
||||
@@ -1423,7 +1621,7 @@ struct buffered_piece_collection
|
||||
it != boost::end(traversed_rings);
|
||||
++it, ++index)
|
||||
{
|
||||
properties p = properties(*it);
|
||||
properties p = properties(*it, m_area_strategy);
|
||||
if (p.valid)
|
||||
{
|
||||
ring_identifier id(2, index, -1);
|
||||
@@ -1431,8 +1629,10 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);
|
||||
detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings,
|
||||
selected, m_intersection_strategy);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out,
|
||||
m_area_strategy);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-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,
|
||||
@@ -13,8 +14,10 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
@@ -32,34 +35,81 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
struct buffer_assign_turn
|
||||
// Implements a unique_sub_range for a buffered piece,
|
||||
// the range can return subsequent points
|
||||
// known as "i", "j" and "k" (and further), indexed as 0,1,2,3
|
||||
template <typename Ring>
|
||||
struct unique_sub_range_from_piece
|
||||
{
|
||||
static bool const include_no_turn = false;
|
||||
static bool const include_degenerate = false;
|
||||
static bool const include_opposite = false;
|
||||
typedef typename boost::range_iterator<Ring const>::type iterator_type;
|
||||
typedef typename geometry::point_type<Ring const>::type point_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Info,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline void apply(Info& info,
|
||||
Point1 const& /*p1*/,
|
||||
Point2 const& /*p2*/,
|
||||
IntersectionInfo const& iinfo)
|
||||
unique_sub_range_from_piece(Ring const& ring,
|
||||
iterator_type iterator_at_i, iterator_type iterator_at_j)
|
||||
: m_ring(ring)
|
||||
, m_iterator_at_i(iterator_at_i)
|
||||
, m_iterator_at_j(iterator_at_j)
|
||||
, m_point_retrieved(false)
|
||||
{}
|
||||
|
||||
static inline bool is_first_segment() { return false; }
|
||||
static inline bool is_last_segment() { return false; }
|
||||
|
||||
static inline std::size_t size() { return 3u; }
|
||||
|
||||
inline point_type const& at(std::size_t index) const
|
||||
{
|
||||
info.rob_pi = iinfo.rpi();
|
||||
info.rob_pj = iinfo.rpj();
|
||||
info.rob_qi = iinfo.rqi();
|
||||
info.rob_qj = iinfo.rqj();
|
||||
BOOST_GEOMETRY_ASSERT(index < size());
|
||||
switch (index)
|
||||
{
|
||||
case 0 : return *m_iterator_at_i;
|
||||
case 1 : return *m_iterator_at_j;
|
||||
case 2 : return get_point_k();
|
||||
default : return *m_iterator_at_i;
|
||||
}
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
inline point_type const& get_point_k() const
|
||||
{
|
||||
if (! m_point_retrieved)
|
||||
{
|
||||
m_iterator_at_k = advance_one(m_iterator_at_j);
|
||||
m_point_retrieved = true;
|
||||
}
|
||||
return *m_iterator_at_k;
|
||||
}
|
||||
|
||||
inline void circular_advance_one(iterator_type& next) const
|
||||
{
|
||||
++next;
|
||||
if (next == boost::end(m_ring))
|
||||
{
|
||||
next = boost::begin(m_ring) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline iterator_type advance_one(iterator_type it) const
|
||||
{
|
||||
iterator_type result = it;
|
||||
circular_advance_one(result);
|
||||
|
||||
// TODO: we could also use piece-boundaries
|
||||
// to check if the point equals the last one
|
||||
while (geometry::equals(*it, *result))
|
||||
{
|
||||
circular_advance_one(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Ring const& m_ring;
|
||||
iterator_type m_iterator_at_i;
|
||||
iterator_type m_iterator_at_j;
|
||||
mutable iterator_type m_iterator_at_k;
|
||||
mutable bool m_point_retrieved;
|
||||
};
|
||||
#endif
|
||||
|
||||
template
|
||||
<
|
||||
@@ -100,52 +150,34 @@ class piece_turn_visitor
|
||||
return ! m_rings[piece1.first_seg_id.multi_index].has_concave;
|
||||
}
|
||||
|
||||
template <typename Range, typename Iterator>
|
||||
inline void move_to_next_point(Range const& range, Iterator& next) const
|
||||
{
|
||||
++next;
|
||||
if (next == boost::end(range))
|
||||
{
|
||||
next = boost::begin(range) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range, typename Iterator>
|
||||
inline Iterator next_point(Range const& range, Iterator it) const
|
||||
{
|
||||
Iterator result = it;
|
||||
move_to_next_point(range, result);
|
||||
// TODO: we could use either piece-boundaries, or comparison with
|
||||
// robust points, to check if the point equals the last one
|
||||
while(geometry::equals(*it, *result))
|
||||
{
|
||||
move_to_next_point(range, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
|
||||
signed_size_type& index, int dir, Box const& other_bounding_box)
|
||||
signed_size_type& index, int dir,
|
||||
Box const& this_bounding_box,
|
||||
Box const& other_bounding_box)
|
||||
{
|
||||
for(; it_begin != it_beyond
|
||||
&& it_begin + 1 != it_beyond
|
||||
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1),
|
||||
other_bounding_box, m_robust_policy);
|
||||
this_bounding_box,
|
||||
other_bounding_box,
|
||||
m_robust_policy);
|
||||
++it_begin, index++)
|
||||
{}
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
|
||||
int dir, Box const& other_bounding_box)
|
||||
int dir, Box const& this_bounding_box,
|
||||
Box const& other_bounding_box)
|
||||
{
|
||||
while (it_beyond != it_begin
|
||||
&& it_beyond - 1 != it_begin
|
||||
&& it_beyond - 2 != it_begin)
|
||||
{
|
||||
if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
|
||||
other_bounding_box, m_robust_policy))
|
||||
this_bounding_box, other_bounding_box, m_robust_policy))
|
||||
{
|
||||
--it_beyond;
|
||||
}
|
||||
@@ -191,23 +223,23 @@ class piece_turn_visitor
|
||||
// Set begin/end of monotonic ranges, in both x/y directions
|
||||
signed_size_type index1 = sec1_first_index;
|
||||
move_begin_iterator<0>(it1_first, it1_beyond, index1,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
section1.directions[0], section1.bounding_box, section2.bounding_box);
|
||||
move_end_iterator<0>(it1_first, it1_beyond,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
section1.directions[0], section1.bounding_box, section2.bounding_box);
|
||||
move_begin_iterator<1>(it1_first, it1_beyond, index1,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
section1.directions[1], section1.bounding_box, section2.bounding_box);
|
||||
move_end_iterator<1>(it1_first, it1_beyond,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
section1.directions[1], section1.bounding_box, section2.bounding_box);
|
||||
|
||||
signed_size_type index2 = sec2_first_index;
|
||||
move_begin_iterator<0>(it2_first, it2_beyond, index2,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
section2.directions[0], section2.bounding_box, section1.bounding_box);
|
||||
move_end_iterator<0>(it2_first, it2_beyond,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
section2.directions[0], section2.bounding_box, section1.bounding_box);
|
||||
move_begin_iterator<1>(it2_first, it2_beyond, index2,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
section2.directions[1], section2.bounding_box, section1.bounding_box);
|
||||
move_end_iterator<1>(it2_first, it2_beyond,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
section2.directions[1], section2.bounding_box, section1.bounding_box);
|
||||
|
||||
turn_type the_model;
|
||||
the_model.operations[0].piece_index = piece1.index;
|
||||
@@ -222,15 +254,19 @@ class piece_turn_visitor
|
||||
the_model.operations[1].piece_index = piece2.index;
|
||||
the_model.operations[1].seg_id = piece2.first_seg_id;
|
||||
the_model.operations[1].seg_id.segment_index = index2; // override
|
||||
geometry::recalculate(the_model.rob_pi, *prev1, m_robust_policy);
|
||||
geometry::recalculate(the_model.rob_pj, *it1, m_robust_policy);
|
||||
|
||||
iterator next1 = next_point(ring1, it1);
|
||||
unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
|
||||
|
||||
iterator it2 = it2_first;
|
||||
for (iterator prev2 = it2++;
|
||||
it2 != it2_beyond;
|
||||
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
|
||||
{
|
||||
iterator next2 = next_point(ring2, it2);
|
||||
unique_sub_range_from_piece<ring_type> unique_sub_range2(ring2, prev2, it2);
|
||||
geometry::recalculate(the_model.rob_qi, *prev2, m_robust_policy);
|
||||
geometry::recalculate(the_model.rob_qj, *it2, m_robust_policy);
|
||||
|
||||
// TODO: internally get_turn_info calculates robust points.
|
||||
// But they are already calculated.
|
||||
@@ -239,20 +275,14 @@ class piece_turn_visitor
|
||||
// and iterating in sync with them...
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
buffer_assign_turn
|
||||
#else
|
||||
detail::overlay::assign_null_policy
|
||||
#endif
|
||||
> turn_policy;
|
||||
|
||||
turn_policy::apply(*prev1, *it1, *next1,
|
||||
*prev2, *it2, *next2,
|
||||
false, false, false, false,
|
||||
the_model,
|
||||
m_intersection_strategy,
|
||||
m_robust_policy,
|
||||
std::back_inserter(m_turns));
|
||||
turn_policy::apply(unique_sub_range1, unique_sub_range2,
|
||||
the_model,
|
||||
m_intersection_strategy,
|
||||
m_robust_policy,
|
||||
std::back_inserter(m_turns));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,10 +302,10 @@ public:
|
||||
{}
|
||||
|
||||
template <typename Section>
|
||||
inline void apply(Section const& section1, Section const& section2,
|
||||
inline bool apply(Section const& section1, Section const& section2,
|
||||
bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
boost::ignore_unused(first);
|
||||
|
||||
typedef typename boost::range_value<Pieces const>::type piece_type;
|
||||
piece_type const& piece1 = m_pieces[section1.ring_id.source_index];
|
||||
@@ -285,12 +315,15 @@ public:
|
||||
|| is_adjacent(piece1, piece2)
|
||||
|| is_on_same_convex_ring(piece1, piece2)
|
||||
|| detail::disjoint::disjoint_box_box(section1.bounding_box,
|
||||
section2.bounding_box) )
|
||||
section2.bounding_box,
|
||||
m_intersection_strategy.get_disjoint_box_box_strategy()) )
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
calculate_turns(piece1, piece2, section1, section2);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// 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,
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#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>
|
||||
@@ -38,12 +39,14 @@ struct original_get_box
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
return ! detail::disjoint::disjoint_box_box(box, original.m_box,
|
||||
DisjointBoxBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -56,6 +59,7 @@ struct include_turn_policy
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct turn_in_original_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
@@ -68,7 +72,7 @@ struct turn_in_original_ovelaps_box
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(
|
||||
turn.robust_point, box);
|
||||
turn.robust_point, box, DisjointPointBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -212,27 +216,27 @@ public:
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Original>
|
||||
inline void apply(Turn const& turn, Original const& original, bool first = true)
|
||||
inline bool apply(Turn const& turn, Original const& original, bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
boost::ignore_unused(first);
|
||||
|
||||
if (turn.location != location_ok || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (geometry::disjoint(turn.robust_point, original.m_box))
|
||||
{
|
||||
// Skip all disjoint
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
int const code = point_in_original(turn.robust_point, original);
|
||||
|
||||
if (code == -1)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
Turn& mutable_turn = m_mutable_turns[turn.turn_index];
|
||||
@@ -259,6 +263,8 @@ public:
|
||||
mutable_turn.within_original = true;
|
||||
mutable_turn.count_in_original = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// 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,
|
||||
@@ -19,6 +20,7 @@
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/config.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/dot_product.hpp>
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
@@ -33,9 +35,8 @@
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
|
||||
#endif
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -55,6 +56,7 @@ struct piece_get_box
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
struct piece_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Piece>
|
||||
@@ -70,7 +72,8 @@ struct piece_ovelaps_box
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope,
|
||||
DisjointBoxBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,12 +86,14 @@ struct turn_get_box
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct turn_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline bool apply(Box const& box, Turn const& turn)
|
||||
{
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box);
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box,
|
||||
DisjointPointBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -100,10 +105,8 @@ enum analyse_result
|
||||
analyse_disjoint,
|
||||
analyse_within,
|
||||
analyse_on_original_boundary,
|
||||
analyse_on_offsetted
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
, analyse_near_offsetted
|
||||
#endif
|
||||
analyse_on_offsetted,
|
||||
analyse_near_offsetted
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
@@ -120,85 +123,115 @@ inline bool in_box(Point const& previous,
|
||||
return geometry::covered_by(point, box);
|
||||
}
|
||||
|
||||
template <typename Point, typename Turn>
|
||||
inline analyse_result check_segment(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (side == -1 && from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
if (side == 1 && from_monotonic)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
return analyse_continue;
|
||||
// meta-programming-structure defining if to use side-of-intersection
|
||||
// (only for cartesian / only necessary with rescaling)
|
||||
template <typename Tag>
|
||||
struct use_side_of_intersection {};
|
||||
|
||||
#if defined(BOOST_GEOMETRY_USE_RESCALING)
|
||||
// With rescaling, let Cartesian use side-of-intersection
|
||||
template <>
|
||||
struct use_side_of_intersection<cartesian_tag> { static bool const value = true; };
|
||||
#else
|
||||
template <>
|
||||
struct use_side_of_intersection<cartesian_tag> { static bool const value = false; };
|
||||
#endif
|
||||
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
template <>
|
||||
struct use_side_of_intersection<spherical_tag> { static bool const value = false; };
|
||||
|
||||
coordinate_type const twice_area
|
||||
= side_strategy::template side_value
|
||||
<
|
||||
coordinate_type,
|
||||
coordinate_type
|
||||
>(previous, current, turn.robust_point);
|
||||
template <>
|
||||
struct use_side_of_intersection<geographic_tag> { static bool const value = false; };
|
||||
|
||||
if (twice_area == 0)
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
struct check_segment {};
|
||||
|
||||
// Implementation using side-of-intersection
|
||||
template <>
|
||||
struct check_segment<true>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
else if (twice_area < 0)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (twice_area * twice_area < geometry::comparable_distance(previous, current)
|
||||
&& in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
if (side == -1 && from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
if (side == 1 && from_monotonic)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
return analyse_continue;
|
||||
}
|
||||
else if (twice_area > 0 && from_monotonic)
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_segment<false>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
|
||||
int const side = side_strategy::apply(previous, current, turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
else if (side == -1)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
#endif
|
||||
}
|
||||
template <bool UseSideOfIntersection>
|
||||
class analyse_turn_wrt_point_piece {};
|
||||
|
||||
|
||||
class analyse_turn_wrt_point_piece
|
||||
template <>
|
||||
class analyse_turn_wrt_point_piece<true>
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
@@ -208,17 +241,9 @@ public :
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
typedef geometry::model::referring_segment<point_type const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
#else
|
||||
typedef strategy::within::winding<point_type> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
boost::ignore_unused(strategy);
|
||||
#endif
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
|
||||
|
||||
@@ -238,7 +263,6 @@ public :
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
|
||||
// First check if it is in range - if it is not, the
|
||||
// expensive side_of_intersection does not need to be
|
||||
@@ -269,8 +293,51 @@ public :
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
#else
|
||||
analyse_result code = check_segment(previous, current, turn, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It is nowhere outside, and not on segment, so it is within
|
||||
return analyse_within;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
class analyse_turn_wrt_point_piece<false>
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Piece::section_type section_type;
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef strategy::within::winding<point_type> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
|
||||
|
||||
coordinate_type const point_x = geometry::get<0>(turn.robust_point);
|
||||
|
||||
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
||||
{
|
||||
section_type const& section = piece.sections[s];
|
||||
// If point within horizontal range of monotonic section:
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1
|
||||
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1)
|
||||
{
|
||||
for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
analyse_result code = check_segment<false>::apply(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
@@ -279,15 +346,10 @@ public :
|
||||
// Get the state (to determine it is within), we don't have
|
||||
// to cover the on-segment case (covered above)
|
||||
strategy.apply(turn.robust_point, previous, current, state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// It is nowhere outside, and not on segment, so it is within
|
||||
return analyse_within;
|
||||
#else
|
||||
int const code = strategy.result(state);
|
||||
if (code == 1)
|
||||
{
|
||||
@@ -300,21 +362,24 @@ public :
|
||||
|
||||
// Should normally not occur - on-segment is covered
|
||||
return analyse_unknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class analyse_turn_wrt_piece
|
||||
template <bool UseSideOfIntersection>
|
||||
struct check_helper_segment {};
|
||||
|
||||
template <>
|
||||
struct check_helper_segment<true>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result check_helper_segment(Point const& s1,
|
||||
static inline analyse_result apply(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
bool is_original,
|
||||
Point const& offsetted)
|
||||
{
|
||||
boost::ignore_unused(offsetted);
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
boost::ignore_unused(is_original);
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
@@ -339,11 +404,9 @@ class analyse_turn_wrt_piece
|
||||
|
||||
if (geometry::covered_by(turn.robust_point, box))
|
||||
{
|
||||
// Points on helper-segments are considered as within
|
||||
// Points on original boundary are processed differently
|
||||
return is_original
|
||||
? analyse_on_original_boundary
|
||||
: analyse_within;
|
||||
// Points on helper-segments (and not on its corners)
|
||||
// are considered as within
|
||||
return analyse_within;
|
||||
}
|
||||
|
||||
// It is collinear but not on the segment. Because these
|
||||
@@ -355,7 +418,20 @@ class analyse_turn_wrt_piece
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
#else
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_helper_segment<false>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
bool is_original,
|
||||
Point const& offsetted)
|
||||
{
|
||||
boost::ignore_unused(offsetted);
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
@@ -404,9 +480,12 @@ class analyse_turn_wrt_piece
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
class analyse_turn_wrt_piece
|
||||
{
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
@@ -423,6 +502,13 @@ class analyse_turn_wrt_piece
|
||||
{
|
||||
points[i] = piece.robust_ring[piece.offsetted_count + i];
|
||||
}
|
||||
|
||||
// 3--offsetted outline--0
|
||||
// | |
|
||||
// left | | right
|
||||
// | |
|
||||
// 2===>==original===>===1
|
||||
|
||||
}
|
||||
else if (helper_count == 3)
|
||||
{
|
||||
@@ -446,14 +532,20 @@ class analyse_turn_wrt_piece
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (comparator(point, points[1]) || comparator(point, points[2]))
|
||||
if (comparator(point, points[1]))
|
||||
{
|
||||
return analyse_on_original_boundary;
|
||||
// On original, right corner
|
||||
return piece.is_flat_end ? analyse_continue : analyse_on_original_boundary;
|
||||
}
|
||||
if (comparator(point, points[2]))
|
||||
{
|
||||
// On original, left corner
|
||||
return piece.is_flat_start ? analyse_continue : analyse_on_original_boundary;
|
||||
}
|
||||
|
||||
// Right side of the piece
|
||||
analyse_result result
|
||||
= check_helper_segment(points[0], points[1], turn,
|
||||
= check_helper_segment<UseSideOfIntersection>::apply(points[0], points[1], turn,
|
||||
false, points[0]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
@@ -461,7 +553,7 @@ class analyse_turn_wrt_piece
|
||||
}
|
||||
|
||||
// Left side of the piece
|
||||
result = check_helper_segment(points[2], points[3], turn,
|
||||
result = check_helper_segment<UseSideOfIntersection>::apply(points[2], points[3], turn,
|
||||
false, points[3]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
@@ -471,7 +563,7 @@ class analyse_turn_wrt_piece
|
||||
if (! comparator(points[1], points[2]))
|
||||
{
|
||||
// Side of the piece at side of original geometry
|
||||
result = check_helper_segment(points[1], points[2], turn,
|
||||
result = check_helper_segment<UseSideOfIntersection>::apply(points[1], points[2], turn,
|
||||
true, point);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
@@ -518,7 +610,7 @@ class analyse_turn_wrt_piece
|
||||
// w.r.t. specified direction, and prev points to a point smaller
|
||||
// We now know if it is inside/outside
|
||||
it_type prev = it - 1;
|
||||
return check_segment(*prev, *it, turn, true);
|
||||
return check_segment<UseSideOfIntersection>::apply(*prev, *it, turn, true);
|
||||
}
|
||||
return analyse_continue;
|
||||
}
|
||||
@@ -575,7 +667,7 @@ public :
|
||||
// (on which any side or side-value would return 0)
|
||||
if (! comparator(previous, current))
|
||||
{
|
||||
code = check_segment(previous, current, turn, false);
|
||||
code = check_segment<UseSideOfIntersection>::apply(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
@@ -588,45 +680,17 @@ public :
|
||||
|
||||
};
|
||||
|
||||
// Helper Structure, of which the apply method returns a side value in {-1, 0, 1}
|
||||
template <bool UseSideOfIntersection>
|
||||
struct turn_in_piece {};
|
||||
|
||||
template <typename Turns, typename Pieces>
|
||||
class turn_in_piece_visitor
|
||||
template <>
|
||||
struct turn_in_piece<true>
|
||||
{
|
||||
Turns& m_turns; // because partition is currently operating on const input only
|
||||
Pieces const& m_pieces; // to check for piece-type
|
||||
|
||||
template <typename Operation, typename Piece>
|
||||
inline bool skip(Operation const& op, Piece const& piece) const
|
||||
{
|
||||
if (op.piece_index == piece.index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Piece const& pc = m_pieces[op.piece_index];
|
||||
if (pc.left_index == piece.index || pc.right_index == piece.index)
|
||||
{
|
||||
if (pc.type == strategy::buffer::buffered_flat_end)
|
||||
{
|
||||
// If it is a flat end, don't compare against its neighbor:
|
||||
// it will always be located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
if (pc.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// If it is concave, the same applies: the IP will be
|
||||
// located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// NOTE: this function returns a side value in {-1, 0, 1}
|
||||
private :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline int turn_in_convex_piece(Turn const& turn,
|
||||
Piece const& piece)
|
||||
static inline int in_convex_piece(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename Piece::piece_robust_ring_type ring_type;
|
||||
@@ -675,43 +739,119 @@ class turn_in_piece_visitor
|
||||
}
|
||||
return 1; // inside
|
||||
}
|
||||
#endif
|
||||
|
||||
public :
|
||||
|
||||
template <typename Turn, typename Piece, typename Strategy>
|
||||
static inline int apply(Turn const& turn, Piece const& piece,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (piece.is_convex)
|
||||
{
|
||||
return in_convex_piece(turn, piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
// side-of-intersection only supported for convex pieces
|
||||
// Call point_in_geometry, a performance-bottleneck
|
||||
// TODO: might be replaced by extending analysing piece
|
||||
return detail::within::point_in_geometry(turn.robust_point,
|
||||
piece.robust_ring, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_piece<false>
|
||||
{
|
||||
public :
|
||||
|
||||
template <typename Turn, typename Piece, typename Strategy>
|
||||
static inline int apply(Turn const& turn, Piece const& piece,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::within::point_in_geometry(turn.robust_point,
|
||||
piece.robust_ring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename CsTag,
|
||||
typename Turns,
|
||||
typename Pieces,
|
||||
typename PointInGeometryStrategy
|
||||
>
|
||||
class turn_in_piece_visitor
|
||||
{
|
||||
Turns& m_turns; // because partition is currently operating on const input only
|
||||
Pieces const& m_pieces; // to check for piece-type
|
||||
PointInGeometryStrategy const& m_point_in_geometry_strategy;
|
||||
|
||||
template <typename Operation, typename Piece>
|
||||
inline bool skip(Operation const& op, Piece const& piece) const
|
||||
{
|
||||
if (op.piece_index == piece.index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Piece const& pc = m_pieces[op.piece_index];
|
||||
if (pc.left_index == piece.index || pc.right_index == piece.index)
|
||||
{
|
||||
if (pc.type == strategy::buffer::buffered_flat_end)
|
||||
{
|
||||
// If it is a flat end, don't compare against its neighbor:
|
||||
// it will always be located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
if (pc.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// If it is concave, the same applies: the IP will be
|
||||
// located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces)
|
||||
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
|
||||
PointInGeometryStrategy const& strategy)
|
||||
: m_turns(turns)
|
||||
, m_pieces(pieces)
|
||||
, m_point_in_geometry_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Piece>
|
||||
inline void apply(Turn const& turn, Piece const& piece, bool first = true)
|
||||
inline bool apply(Turn const& turn, Piece const& piece, bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
boost::ignore_unused(first);
|
||||
|
||||
if (turn.count_within > 0)
|
||||
{
|
||||
// Already inside - no need to check again
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (piece.type == strategy::buffer::buffered_flat_end
|
||||
|| piece.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// Turns cannot be located within flat-end or concave pieces
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! geometry::covered_by(turn.robust_point, piece.robust_envelope))
|
||||
{
|
||||
// Easy check: if the turn is not in the envelope, we can safely return
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: mutable_piece to make some on-demand preparations in analyse
|
||||
@@ -733,63 +873,51 @@ public:
|
||||
if (cd < piece.robust_min_comparable_radius)
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (cd > piece.robust_max_comparable_radius)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const bool use_soi = use_side_of_intersection<CsTag>::value;
|
||||
boost::ignore_unused(use_soi);
|
||||
|
||||
analyse_result analyse_code =
|
||||
piece.type == geometry::strategy::buffer::buffered_point
|
||||
? analyse_turn_wrt_point_piece::apply(turn, piece)
|
||||
: analyse_turn_wrt_piece::apply(turn, piece);
|
||||
? analyse_turn_wrt_point_piece<use_soi>::apply(turn, piece)
|
||||
: analyse_turn_wrt_piece<use_soi>::apply(turn, piece);
|
||||
|
||||
switch(analyse_code)
|
||||
{
|
||||
case analyse_disjoint :
|
||||
return;
|
||||
return true;
|
||||
case analyse_on_offsetted :
|
||||
mutable_turn.count_on_offsetted++; // value is not used anymore
|
||||
return;
|
||||
return true;
|
||||
case analyse_on_original_boundary :
|
||||
mutable_turn.count_on_original_boundary++;
|
||||
return;
|
||||
return true;
|
||||
case analyse_within :
|
||||
mutable_turn.count_within++;
|
||||
return;
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
return true;
|
||||
case analyse_near_offsetted :
|
||||
mutable_turn.count_within_near_offsetted++;
|
||||
return;
|
||||
#endif
|
||||
return true;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// We don't know (yet)
|
||||
int geometry_code = 0;
|
||||
if (piece.is_convex)
|
||||
{
|
||||
geometry_code = turn_in_convex_piece(turn, piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// TODO: this point_in_geometry is a performance-bottleneck here and
|
||||
// will be replaced completely by extending analyse_piece functionality
|
||||
geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||
}
|
||||
#else
|
||||
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||
#endif
|
||||
int const geometry_code = turn_in_piece<use_soi>::apply(turn, piece,
|
||||
m_point_in_geometry_strategy);
|
||||
|
||||
if (geometry_code == 1)
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user