mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-08 23:02:09 +00:00
[buffer] restructure buffer_range such that tag is not necessary
and behaviour per geometry-type is done in the dispatch itself. This also avoids generating side on perpendicular side for linestrings once (the second one cannot easily be avoided in the current structure)
This commit is contained in:
@@ -39,11 +39,7 @@ namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename RingOutput,
|
||||
typename Tag
|
||||
>
|
||||
template <typename RingOutput>
|
||||
struct buffer_range
|
||||
{
|
||||
typedef typename point_type<RingOutput>::type output_point_type;
|
||||
@@ -162,7 +158,10 @@ struct buffer_range
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool /*close*/ = false)
|
||||
output_point_type& first_p1,
|
||||
output_point_type& first_p2,
|
||||
output_point_type& last_p1,
|
||||
output_point_type& last_p2)
|
||||
{
|
||||
typedef typename std::iterator_traits
|
||||
<
|
||||
@@ -176,16 +175,14 @@ struct buffer_range
|
||||
>::type robust_point_type;
|
||||
|
||||
robust_point_type previous_robust_input;
|
||||
output_point_type previous_p1, previous_p2;
|
||||
output_point_type first_p1, first_p2;
|
||||
point_type second_point, penultimate_point, ultimate_point; // last two points from begin/end
|
||||
|
||||
/*
|
||||
* prev.p1 prev.p2 these are the "previous perpendicular points"
|
||||
* last.p1 last.p2 these are the "previous (last) perpendicular points"
|
||||
* --------------
|
||||
* | |
|
||||
* *------------*____ <- *prev
|
||||
* pup | | p1 "current perpendiculat point 1"
|
||||
* pup | | p1 "current perpendicular point 1"
|
||||
* | |
|
||||
* | | this forms a "side", a side is a piece
|
||||
* | |
|
||||
@@ -222,7 +219,7 @@ struct buffer_range
|
||||
{
|
||||
add_join(collection, phase,
|
||||
penultimate_point,
|
||||
*prev, previous_p1, previous_p2,
|
||||
*prev, last_p1, last_p2,
|
||||
*it, generated_side.front(), generated_side.back(),
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
@@ -234,8 +231,8 @@ struct buffer_range
|
||||
|
||||
penultimate_point = *prev;
|
||||
ultimate_point = *it;
|
||||
previous_p1 = generated_side.front();
|
||||
previous_p2 = generated_side.back();
|
||||
last_p1 = generated_side.front();
|
||||
last_p2 = generated_side.back();
|
||||
prev = it;
|
||||
if (first)
|
||||
{
|
||||
@@ -247,39 +244,6 @@ struct buffer_range
|
||||
}
|
||||
previous_robust_input = robust_input;
|
||||
}
|
||||
|
||||
// Might be replaced by specialization
|
||||
if(boost::is_same<Tag, ring_tag>::value)
|
||||
{
|
||||
// Generate closing corner
|
||||
add_join(collection, phase,
|
||||
penultimate_point,
|
||||
*(end - 1), previous_p1, previous_p2,
|
||||
*(begin + 1), first_p1, first_p2,
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy);
|
||||
|
||||
// Buffer is closed automatically by last closing corner (NOT FOR OPEN POLYGONS - TODO)
|
||||
}
|
||||
else if (boost::is_same<Tag, linestring_tag>::value)
|
||||
{
|
||||
|
||||
// Generate perpendicular points to the reverse side,
|
||||
// these points are necessary for all end-cap strategies
|
||||
// TODO fix this (approach) for one-side buffer (1.5 - -1.0)
|
||||
generated_side.clear();
|
||||
strategy::buffer::buffer_side::apply(ultimate_point,
|
||||
penultimate_point,
|
||||
side == strategy::buffer::buffer_side_left
|
||||
? strategy::buffer::buffer_side_right
|
||||
: strategy::buffer::buffer_side_left,
|
||||
distance_strategy, generated_side);
|
||||
|
||||
std::vector<output_point_type> range_out;
|
||||
end_strategy.apply(penultimate_point, previous_p2, ultimate_point, generated_side.front(), side, distance_strategy, range_out);
|
||||
collection.add_endcap(end_strategy, range_out, ultimate_point);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -456,17 +420,47 @@ template
|
||||
typename RingOutput
|
||||
>
|
||||
struct buffer_inserter<ring_tag, RingInput, RingOutput>
|
||||
: public detail::buffer::buffer_range
|
||||
<
|
||||
RingOutput,
|
||||
ring_tag
|
||||
>
|
||||
{
|
||||
typedef detail::buffer::buffer_range
|
||||
<
|
||||
RingOutput,
|
||||
ring_tag
|
||||
> base;
|
||||
typedef typename point_type<RingOutput>::type output_point_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Collection,
|
||||
typename Iterator,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
output_point_type first_p1, first_p2, last_p1, last_p2;
|
||||
|
||||
typedef detail::buffer::buffer_range<RingOutput> buffer_range;
|
||||
|
||||
buffer_range::iterate(collection, 0, begin, end,
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy, robust_policy,
|
||||
first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
// Generate closing join
|
||||
buffer_range::add_join(collection, 0,
|
||||
*(end - 2),
|
||||
*(end - 1), last_p1, last_p2,
|
||||
*(begin + 1), first_p1, first_p2,
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy);
|
||||
|
||||
// Buffer is closed automatically by last closing corner
|
||||
// (OPEN IT FOR OPEN POLYGONS - TODO)
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
@@ -502,16 +496,17 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
|
||||
// Walk backwards (rings will be reversed afterwards)
|
||||
// It might be that this will be changed later.
|
||||
// TODO: decide this.
|
||||
base::iterate(collection, 0, boost::rbegin(simplified), boost::rend(simplified),
|
||||
iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
|
||||
strategy::buffer::buffer_side_right,
|
||||
distance, join_strategy, end_strategy, robust_policy);
|
||||
}
|
||||
else
|
||||
{
|
||||
base::iterate(collection, 0, boost::begin(simplified), boost::end(simplified),
|
||||
iterate(collection, boost::begin(simplified), boost::end(simplified),
|
||||
strategy::buffer::buffer_side_left,
|
||||
distance, join_strategy, end_strategy, robust_policy);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -523,17 +518,64 @@ template
|
||||
typename Polygon
|
||||
>
|
||||
struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
: public detail::buffer::buffer_range
|
||||
<
|
||||
typename ring_type<Polygon>::type,
|
||||
linestring_tag
|
||||
>
|
||||
{
|
||||
typedef detail::buffer::buffer_range
|
||||
<
|
||||
typename ring_type<Polygon>::type,
|
||||
linestring_tag
|
||||
> base;
|
||||
typedef typename ring_type<Polygon>::type output_ring_type;
|
||||
typedef typename point_type<output_ring_type>::type output_point_type;
|
||||
typedef typename point_type<Linestring>::type input_point_type;
|
||||
|
||||
template <typename DistanceStrategy>
|
||||
static inline output_point_type first_perpendicular_point(
|
||||
input_point_type const& p1, input_point_type const& p2,
|
||||
DistanceStrategy const& distance_strategy)
|
||||
{
|
||||
std::vector<output_point_type> generated_side;
|
||||
strategy::buffer::buffer_side::apply(p1, p2,
|
||||
strategy::buffer::buffer_side_right,
|
||||
distance_strategy, generated_side);
|
||||
return generated_side.front();
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Collection,
|
||||
typename Iterator,
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void iterate(Collection& collection, int phase,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
output_point_type& first_p1)
|
||||
{
|
||||
input_point_type const& ultimate_point = *(end - 1);
|
||||
input_point_type const& penultimate_point = *(end - 2);
|
||||
|
||||
// For the end-cap, we need to have the last perpendicular point on the
|
||||
// other side of the linestring. If it is the second pass (right),
|
||||
// we have it already from the first phase (left).
|
||||
// But for the first pass, we have to generate it
|
||||
output_point_type reverse_p1
|
||||
= side == strategy::buffer::buffer_side_right
|
||||
? first_p1
|
||||
: first_perpendicular_point(ultimate_point, penultimate_point, distance_strategy);
|
||||
|
||||
output_point_type first_p2, last_p1, last_p2;
|
||||
|
||||
detail::buffer::buffer_range<output_ring_type>::iterate(collection,
|
||||
phase, begin, end, side,
|
||||
distance_strategy, join_strategy, end_strategy, robust_policy,
|
||||
first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
std::vector<output_point_type> 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);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
@@ -555,13 +597,16 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
geometry::simplify(linestring, simplified, distance.simplify_distance());
|
||||
|
||||
collection.start_new_ring();
|
||||
base::iterate(collection, 0, boost::begin(simplified), boost::end(simplified),
|
||||
output_point_type first_p1;
|
||||
iterate(collection, 0, boost::begin(simplified), boost::end(simplified),
|
||||
strategy::buffer::buffer_side_left,
|
||||
distance, join_strategy, end_strategy, robust_policy);
|
||||
distance, join_strategy, end_strategy, robust_policy,
|
||||
first_p1);
|
||||
|
||||
base::iterate(collection, 1, boost::rbegin(simplified), boost::rend(simplified),
|
||||
iterate(collection, 1, boost::rbegin(simplified), boost::rend(simplified),
|
||||
strategy::buffer::buffer_side_right,
|
||||
distance, join_strategy, end_strategy, robust_policy, true);
|
||||
distance, join_strategy, end_strategy, robust_policy,
|
||||
first_p1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user