Merge branch 'develop' into feature/intvalid

This commit is contained in:
Barend Gehrels 2017-08-30 13:30:46 +02:00
commit 0591aa63ea
45 changed files with 1414 additions and 552 deletions

View File

@ -69,14 +69,19 @@ Examples of some basic queries may be found in the tables below. The query regio
] ]
[table [table
[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)] [intersects(Segment)] [intersects(Linestring)]] [[intersects(Segment)] [intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]]
[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]] [[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/intersects_linestring.png]]] [[[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]]
] ]
[table [/table
[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)] [intersects(Segment)] [intersects(Linestring)]]
[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]] [[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/intersects_linestring.png]]]
/]
[/table
[[intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]] [[intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]]
[[[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]] [[[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]]
] /]
Spatial predicates are generated by functions defined in `boost::geometry::index` namespace. Spatial predicates are generated by functions defined in `boost::geometry::index` namespace.

View File

@ -25,6 +25,7 @@
[*Improvements] [*Improvements]
* Add correct() overload taking area strategy * Add correct() overload taking area strategy
* Add is_convex() overload taking side strategy
* Add missing relational operations (covered_by, crosses, equals, etc.) for MultiPoint/AnyGeometry * Add missing relational operations (covered_by, crosses, equals, etc.) for MultiPoint/AnyGeometry
[*Solved issues] [*Solved issues]
@ -43,6 +44,7 @@
* Fix propagation of area strategy into the internals of various algorithms from intersection strategy * Fix propagation of area strategy into the internals of various algorithms from intersection strategy
* Fix uninitialized variable in relate and reference to temporary in overlay * Fix uninitialized variable in relate and reference to temporary in overlay
* Fix error in disjoint for geographic Segment/Box * Fix error in disjoint for geographic Segment/Box
* Fix handling of non-cartesian geometries in various algorithms
[/=================] [/=================]
[heading Boost 1.64] [heading Boost 1.64]

View File

@ -122,7 +122,8 @@ struct buffer_range
typename DistanceStrategy, typename DistanceStrategy,
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename RobustPolicy typename RobustPolicy,
typename Strategy
> >
static inline static inline
void add_join(Collection& collection, void add_join(Collection& collection,
@ -133,18 +134,19 @@ struct buffer_range
Point const& input, Point const& input,
output_point_type const& perp1, output_point_type const& perp1,
output_point_type const& perp2, output_point_type const& perp2,
strategy::buffer::buffer_side_selector side, geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance, DistanceStrategy const& distance,
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
RobustPolicy const& ) RobustPolicy const& ,
Strategy const& strategy) // side strategy
{ {
output_point_type intersection_point; output_point_type intersection_point;
geometry::assign_zero(intersection_point); geometry::assign_zero(intersection_point);
strategy::buffer::join_selector join geometry::strategy::buffer::join_selector join
= get_join_type(penultimate_input, previous_input, input); = get_join_type(penultimate_input, previous_input, input, strategy);
if (join == strategy::buffer::join_convex) if (join == geometry::strategy::buffer::join_convex)
{ {
// Calculate the intersection-point formed by the two sides. // Calculate the intersection-point formed by the two sides.
// It might be that the two sides are not convex, but continue // It might be that the two sides are not convex, but continue
@ -157,23 +159,23 @@ struct buffer_range
switch(join) switch(join)
{ {
case strategy::buffer::join_continue : case geometry::strategy::buffer::join_continue :
// No join, we get two consecutive sides // No join, we get two consecutive sides
break; break;
case strategy::buffer::join_concave : case geometry::strategy::buffer::join_concave :
{ {
std::vector<output_point_type> range_out; std::vector<output_point_type> range_out;
range_out.push_back(prev_perp2); range_out.push_back(prev_perp2);
range_out.push_back(previous_input); 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.clear();
range_out.push_back(previous_input); range_out.push_back(previous_input);
range_out.push_back(perp1); 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; break;
case strategy::buffer::join_spike : case geometry::strategy::buffer::join_spike :
{ {
// For linestrings, only add spike at one side to avoid // For linestrings, only add spike at one side to avoid
// duplicates // duplicates
@ -183,7 +185,7 @@ struct buffer_range
collection.set_current_ring_concave(); collection.set_current_ring_concave();
} }
break; break;
case strategy::buffer::join_convex : case geometry::strategy::buffer::join_convex :
{ {
// The corner is convex, we create a join // The corner is convex, we create a join
// TODO (future) - avoid a separate vector, add the piece directly // TODO (future) - avoid a separate vector, add the piece directly
@ -193,7 +195,7 @@ struct buffer_range
distance.apply(previous_input, input, side), distance.apply(previous_input, input, side),
range_out)) range_out))
{ {
collection.add_piece(strategy::buffer::buffered_join, collection.add_piece(geometry::strategy::buffer::buffered_join,
previous_input, range_out); previous_input, range_out);
} }
} }
@ -201,27 +203,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& p0,
output_point_type const& p1, 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 int const side = strategy.apply(p0, p1, p2);
< return side == -1 ? geometry::strategy::buffer::join_convex
typename cs_tag<output_point_type>::type : side == 1 ? geometry::strategy::buffer::join_concave
>::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
: parallel_continue : parallel_continue
( (
get<0>(p2) - get<0>(p1), get<0>(p2) - get<0>(p1),
get<1>(p2) - get<1>(p1), get<1>(p2) - get<1>(p1),
get<0>(p1) - get<0>(p0), get<0>(p1) - get<0>(p0),
get<1>(p1) - get<1>(p0) get<1>(p1) - get<1>(p0)
) ? strategy::buffer::join_continue ) ? geometry::strategy::buffer::join_continue
: strategy::buffer::join_spike; : geometry::strategy::buffer::join_spike;
} }
template template
@ -232,16 +231,18 @@ struct buffer_range
typename SideStrategy, typename SideStrategy,
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, 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, Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side, geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy, DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy, SideStrategy const& side_strategy,
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Strategy const& strategy, // side strategy
output_point_type& first_p1, output_point_type& first_p1,
output_point_type& first_p2, output_point_type& first_p2,
output_point_type& last_p1, output_point_type& last_p1,
@ -273,7 +274,7 @@ struct buffer_range
* pup: penultimate_point * pup: penultimate_point
*/ */
strategy::buffer::result_code result = strategy::buffer::result_no_output; geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
bool first = true; bool first = true;
Iterator it = begin; Iterator it = begin;
@ -284,25 +285,25 @@ struct buffer_range
for (Iterator prev = it++; it != end; ++it) for (Iterator prev = it++; it != end; ++it)
{ {
generated_side.clear(); generated_side.clear();
strategy::buffer::result_code error_code geometry::strategy::buffer::result_code error_code
= side_strategy.apply(*prev, *it, side, = side_strategy.apply(*prev, *it, side,
distance_strategy, generated_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, // Because input is simplified, this is improbable,
// but it can happen for degenerate geometries // but it can happen for degenerate geometries
// Further handling of this side is skipped // Further handling of this side is skipped
continue; continue;
} }
else if (error_code == strategy::buffer::result_error_numerical) else if (error_code == geometry::strategy::buffer::result_error_numerical)
{ {
return error_code; return error_code;
} }
BOOST_GEOMETRY_ASSERT(! generated_side.empty()); BOOST_GEOMETRY_ASSERT(! generated_side.empty());
result = strategy::buffer::result_normal; result = geometry::strategy::buffer::result_normal;
if (! first) if (! first)
{ {
@ -312,7 +313,7 @@ struct buffer_range
*it, generated_side.front(), generated_side.back(), *it, generated_side.front(), generated_side.back(),
side, side,
distance_strategy, join_strategy, end_strategy, distance_strategy, join_strategy, end_strategy,
robust_policy); robust_policy, strategy);
} }
collection.add_side_piece(*prev, *it, generated_side, first); collection.add_side_piece(*prev, *it, generated_side, first);
@ -350,7 +351,8 @@ struct buffer_multi
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, typename PointStrategy,
typename RobustPolicy typename RobustPolicy,
typename Strategy
> >
static inline void apply(Multi const& multi, static inline void apply(Multi const& multi,
Collection& collection, Collection& collection,
@ -359,7 +361,8 @@ struct buffer_multi
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_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 for (typename boost::range_iterator<Multi const>::type
it = boost::begin(multi); it = boost::begin(multi);
@ -369,7 +372,7 @@ struct buffer_multi
Policy::apply(*it, collection, Policy::apply(*it, collection,
distance_strategy, side_strategy, distance_strategy, side_strategy,
join_strategy, end_strategy, point_strategy, join_strategy, end_strategy, point_strategy,
robust_policy); robust_policy, strategy);
} }
} }
}; };
@ -396,9 +399,9 @@ inline void buffer_point(Point const& point, Collection& collection,
collection.start_new_ring(); collection.start_new_ring();
std::vector<OutputPointType> range_out; std::vector<OutputPointType> range_out;
point_strategy.apply(point, distance_strategy, 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.set_piece_center(point);
collection.finish_ring(strategy::buffer::result_normal); collection.finish_ring(geometry::strategy::buffer::result_normal);
} }
@ -436,7 +439,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, typename PointStrategy,
typename RobustPolicy typename RobustPolicy,
typename Strategy
> >
static inline void apply(Point const& point, Collection& collection, static inline void apply(Point const& point, Collection& collection,
DistanceStrategy const& distance_strategy, DistanceStrategy const& distance_strategy,
@ -444,7 +448,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
JoinStrategy const& , JoinStrategy const& ,
EndStrategy const& , EndStrategy const& ,
PointStrategy const& point_strategy, PointStrategy const& point_strategy,
RobustPolicy const& ) RobustPolicy const& ,
Strategy const& ) // side strategy
{ {
detail::buffer::buffer_point detail::buffer::buffer_point
< <
@ -472,29 +477,32 @@ struct buffer_inserter_ring
typename SideStrategy, typename SideStrategy,
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, 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, Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side, geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy, DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy, SideStrategy const& side_strategy,
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_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; output_point_type first_p1, first_p2, last_p1, last_p2;
typedef detail::buffer::buffer_range<RingOutput> buffer_range; 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, = buffer_range::iterate(collection, begin, end,
side, side,
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, distance_strategy, side_strategy, join_strategy, end_strategy,
robust_policy, strategy,
first_p1, first_p2, last_p1, last_p2); first_p1, first_p2, last_p1, last_p2);
// Generate closing join // Generate closing join
if (result == strategy::buffer::result_normal) if (result == geometry::strategy::buffer::result_normal)
{ {
buffer_range::add_join(collection, buffer_range::add_join(collection,
*(end - 2), *(end - 2),
@ -502,7 +510,7 @@ struct buffer_inserter_ring
*(begin + 1), first_p1, first_p2, *(begin + 1), first_p1, first_p2,
side, side,
distance_strategy, join_strategy, end_strategy, distance_strategy, join_strategy, end_strategy,
robust_policy); robust_policy, strategy);
} }
// Buffer is closed automatically by last closing corner // Buffer is closed automatically by last closing corner
@ -517,21 +525,23 @@ struct buffer_inserter_ring
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, 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, Collection& collection,
DistanceStrategy const& distance, DistanceStrategy const& distance,
SideStrategy const& side_strategy, SideStrategy const& side_strategy,
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_strategy, PointStrategy const& point_strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy,
Strategy const& strategy) // side strategy
{ {
RingInput simplified; RingInput simplified;
detail::buffer::simplify_input(ring, distance, 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 n = boost::size(simplified);
std::size_t const min_points = core_detail::closure::minimum_ring_size std::size_t const min_points = core_detail::closure::minimum_ring_size
@ -546,18 +556,20 @@ struct buffer_inserter_ring
{ {
// Walk backwards (rings will be reversed afterwards) // Walk backwards (rings will be reversed afterwards)
code = iterate(collection, boost::rbegin(view), boost::rend(view), code = iterate(collection, boost::rbegin(view), boost::rend(view),
strategy::buffer::buffer_side_right, geometry::strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy); distance, side_strategy, join_strategy, end_strategy,
robust_policy, strategy);
} }
else else
{ {
code = iterate(collection, boost::begin(view), boost::end(view), code = iterate(collection, boost::begin(view), boost::end(view),
strategy::buffer::buffer_side_left, geometry::strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy); 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 // Use point_strategy to buffer degenerated ring
detail::buffer::buffer_point<output_point_type> detail::buffer::buffer_point<output_point_type>
@ -586,23 +598,25 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, 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, Collection& collection,
DistanceStrategy const& distance, DistanceStrategy const& distance,
SideStrategy const& side_strategy, SideStrategy const& side_strategy,
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_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();
strategy::buffer::result_code const code geometry::strategy::buffer::result_code const code
= buffer_inserter_ring<RingInput, RingOutput>::apply(ring, = buffer_inserter_ring<RingInput, RingOutput>::apply(ring,
collection, distance, collection, distance,
side_strategy, join_strategy, end_strategy, point_strategy, side_strategy, join_strategy, end_strategy, point_strategy,
robust_policy); robust_policy, strategy);
collection.finish_ring(code); collection.finish_ring(code);
return code; return code;
} }
@ -627,16 +641,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename SideStrategy, typename SideStrategy,
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, 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, Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side, geometry::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy, DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy, SideStrategy const& side_strategy,
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Strategy const& strategy, // side strategy
output_point_type& first_p1) output_point_type& first_p1)
{ {
input_point_type const& ultimate_point = *(end - 1); input_point_type const& ultimate_point = *(end - 1);
@ -647,18 +663,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
// we have it already from the first phase (left). // we have it already from the first phase (left).
// But for the first pass, we have to generate it // But for the first pass, we have to generate it
output_point_type reverse_p1; output_point_type reverse_p1;
if (side == strategy::buffer::buffer_side_right) if (side == geometry::strategy::buffer::buffer_side_right)
{ {
reverse_p1 = first_p1; reverse_p1 = first_p1;
} }
else else
{ {
std::vector<output_point_type> generated_side; 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, = side_strategy.apply(ultimate_point, penultimate_point,
strategy::buffer::buffer_side_right, geometry::strategy::buffer::buffer_side_right,
distance_strategy, generated_side); distance_strategy, generated_side);
if (code != strategy::buffer::result_normal) if (code != geometry::strategy::buffer::result_normal)
{ {
// No output or numerical error // No output or numerical error
return code; return code;
@ -668,16 +684,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
output_point_type first_p2, last_p1, last_p2; 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, = detail::buffer::buffer_range<output_ring_type>::iterate(collection,
begin, end, side, begin, end, side,
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, distance_strategy, side_strategy, join_strategy, end_strategy,
robust_policy, strategy,
first_p1, first_p2, last_p1, last_p2); 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; 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); collection.add_endcap(end_strategy, range_out, ultimate_point);
} }
return result; return result;
@ -691,20 +709,23 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, 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, DistanceStrategy const& distance,
SideStrategy const& side_strategy, SideStrategy const& side_strategy,
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_strategy, PointStrategy const& point_strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy,
Strategy const& strategy) // side strategy
{ {
Linestring simplified; Linestring simplified;
detail::buffer::simplify_input(linestring, distance, 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); std::size_t n = boost::size(simplified);
if (n > 1) if (n > 1)
{ {
@ -712,21 +733,23 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
output_point_type first_p1; output_point_type first_p1;
code = iterate(collection, code = iterate(collection,
boost::begin(simplified), boost::end(simplified), boost::begin(simplified), boost::end(simplified),
strategy::buffer::buffer_side_left, geometry::strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy, distance, side_strategy, join_strategy, end_strategy,
robust_policy, strategy,
first_p1); first_p1);
if (code == strategy::buffer::result_normal) if (code == geometry::strategy::buffer::result_normal)
{ {
code = iterate(collection, code = iterate(collection,
boost::rbegin(simplified), boost::rend(simplified), boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right, geometry::strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy, distance, side_strategy, join_strategy, end_strategy,
robust_policy, strategy,
first_p1); first_p1);
} }
collection.finish_ring(code); 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 // Use point_strategy to buffer degenerated linestring
detail::buffer::buffer_point<output_point_type> detail::buffer::buffer_point<output_point_type>
@ -763,7 +786,8 @@ private:
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, typename PointStrategy,
typename RobustPolicy typename RobustPolicy,
typename Strategy
> >
static inline static inline
void iterate(Iterator begin, Iterator end, void iterate(Iterator begin, Iterator end,
@ -774,15 +798,16 @@ private:
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_strategy, PointStrategy const& point_strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Strategy const& strategy, // side strategy
bool is_interior) bool is_interior)
{ {
for (Iterator it = begin; it != end; ++it) for (Iterator it = begin; it != end; ++it)
{ {
collection.start_new_ring(); collection.start_new_ring();
strategy::buffer::result_code const code geometry::strategy::buffer::result_code const code
= policy::apply(*it, collection, distance, side_strategy, = policy::apply(*it, collection, distance, side_strategy,
join_strategy, end_strategy, point_strategy, join_strategy, end_strategy, point_strategy,
robust_policy); robust_policy, strategy);
collection.finish_ring(code, is_interior); collection.finish_ring(code, is_interior);
} }
@ -797,7 +822,8 @@ private:
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, typename PointStrategy,
typename RobustPolicy typename RobustPolicy,
typename Strategy
> >
static inline static inline
void apply_interior_rings(InteriorRings const& interior_rings, void apply_interior_rings(InteriorRings const& interior_rings,
@ -807,12 +833,13 @@ private:
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_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), iterate(boost::begin(interior_rings), boost::end(interior_rings),
collection, distance, side_strategy, collection, distance, side_strategy,
join_strategy, end_strategy, point_strategy, join_strategy, end_strategy, point_strategy,
robust_policy, true); robust_policy, strategy, true);
} }
public: public:
@ -824,7 +851,8 @@ public:
typename JoinStrategy, typename JoinStrategy,
typename EndStrategy, typename EndStrategy,
typename PointStrategy, typename PointStrategy,
typename RobustPolicy typename RobustPolicy,
typename Strategy
> >
static inline void apply(PolygonInput const& polygon, static inline void apply(PolygonInput const& polygon,
Collection& collection, Collection& collection,
@ -833,16 +861,17 @@ public:
JoinStrategy const& join_strategy, JoinStrategy const& join_strategy,
EndStrategy const& end_strategy, EndStrategy const& end_strategy,
PointStrategy const& point_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();
strategy::buffer::result_code const code geometry::strategy::buffer::result_code const code
= policy::apply(exterior_ring(polygon), collection, = policy::apply(exterior_ring(polygon), collection,
distance, side_strategy, distance, side_strategy,
join_strategy, end_strategy, point_strategy, join_strategy, end_strategy, point_strategy,
robust_policy); robust_policy, strategy);
collection.finish_ring(code, false, collection.finish_ring(code, false,
geometry::num_interior_rings(polygon) > 0u); geometry::num_interior_rings(polygon) > 0u);
@ -851,7 +880,7 @@ public:
apply_interior_rings(interior_rings(polygon), apply_interior_rings(interior_rings(polygon),
collection, distance, side_strategy, collection, distance, side_strategy,
join_strategy, end_strategy, point_strategy, join_strategy, end_strategy, point_strategy,
robust_policy); robust_policy, strategy);
} }
}; };
@ -945,7 +974,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
>::apply(geometry_input, collection, >::apply(geometry_input, collection,
distance_strategy, side_strategy, join_strategy, distance_strategy, side_strategy, join_strategy,
end_strategy, point_strategy, end_strategy, point_strategy,
robust_policy); robust_policy, intersection_strategy.get_side_strategy());
collection.get_turns(); collection.get_turns();
collection.classify_turns(linear); collection.classify_turns(linear);

View File

@ -494,7 +494,7 @@ struct buffered_piece_collection
for (typename occupation_map_type::iterator it = occupation_map.begin(); for (typename occupation_map_type::iterator it = occupation_map.begin();
it != occupation_map.end(); ++it) 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);
} }
} }

View File

@ -127,26 +127,31 @@ class piece_turn_visitor
template <std::size_t Dimension, typename Iterator, typename Box> template <std::size_t Dimension, typename Iterator, typename Box>
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond, 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 for(; it_begin != it_beyond
&& it_begin + 1 != it_beyond && it_begin + 1 != it_beyond
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1), && 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++) ++it_begin, index++)
{} {}
} }
template <std::size_t Dimension, typename Iterator, typename Box> template <std::size_t Dimension, typename Iterator, typename Box>
inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond, 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 while (it_beyond != it_begin
&& it_beyond - 1 != it_begin && it_beyond - 1 != it_begin
&& it_beyond - 2 != it_begin) && it_beyond - 2 != it_begin)
{ {
if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2), 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; --it_beyond;
} }
@ -192,23 +197,23 @@ class piece_turn_visitor
// Set begin/end of monotonic ranges, in both x/y directions // Set begin/end of monotonic ranges, in both x/y directions
signed_size_type index1 = sec1_first_index; signed_size_type index1 = sec1_first_index;
move_begin_iterator<0>(it1_first, it1_beyond, index1, 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, 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, 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, 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; signed_size_type index2 = sec2_first_index;
move_begin_iterator<0>(it2_first, it2_beyond, index2, 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, 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, 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, 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; turn_type the_model;
the_model.operations[0].piece_index = piece1.index; the_model.operations[0].piece_index = piece1.index;

View File

@ -2,10 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015. // This file was modified by Oracle on 2015, 2017.
// Modifications copyright (c) 2015 Oracle and/or its affiliates. // Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -17,14 +18,22 @@
#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp> #include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
#ifndef DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DETAIL
namespace detail namespace detail
{ {
// TODO: remove
template <std::size_t Index, typename Point1, typename Point2> template <std::size_t Index, typename Point1, typename Point2>
inline int sign_of_difference(Point1 const& point1, Point2 const& point2) inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
{ {
@ -37,6 +46,193 @@ inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
} }
template <typename Point, typename CSTag = typename cs_tag<Point>::type>
struct direction_code_impl
{
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_CS, (CSTag));
};
template <typename Point>
struct direction_code_impl<Point, cartesian_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
Point2 const& p)
{
typedef typename geometry::select_coordinate_type
<
Point1, Point2
>::type calc_t;
if ( (math::equals(geometry::get<0>(segment_b), geometry::get<0>(segment_a))
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(segment_a)))
|| (math::equals(geometry::get<0>(segment_b), geometry::get<0>(p))
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(p))) )
{
return 0;
}
calc_t x1 = geometry::get<0>(segment_b) - geometry::get<0>(segment_a);
calc_t y1 = geometry::get<1>(segment_b) - geometry::get<1>(segment_a);
calc_t x2 = geometry::get<0>(segment_b) - geometry::get<0>(p);
calc_t y2 = geometry::get<1>(segment_b) - geometry::get<1>(p);
calc_t ax = (std::min)(math::abs(x1), math::abs(x2));
calc_t ay = (std::min)(math::abs(y1), math::abs(y2));
int s1 = 0, s2 = 0;
if (ax >= ay)
{
s1 = x1 > 0 ? 1 : -1;
s2 = x2 > 0 ? 1 : -1;
}
else
{
s1 = y1 > 0 ? 1 : -1;
s2 = y2 > 0 ? 1 : -1;
}
return s1 == s2 ? -1 : 1;
}
};
template <typename Point>
struct direction_code_impl<Point, spherical_equatorial_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
Point2 const& p)
{
typedef typename coordinate_type<Point1>::type coord1_t;
typedef typename coordinate_type<Point2>::type coord2_t;
typedef typename coordinate_system<Point1>::type::units units_t;
typedef typename coordinate_system<Point2>::type::units units2_t;
BOOST_MPL_ASSERT_MSG((boost::is_same<units_t, units2_t>::value),
NOT_IMPLEMENTED_FOR_DIFFERENT_UNITS,
(units_t, units2_t));
typedef typename geometry::select_coordinate_type <Point1, Point2>::type calc_t;
typedef math::detail::constants_on_spheroid<coord1_t, units_t> constants1;
typedef math::detail::constants_on_spheroid<coord2_t, units_t> constants2;
static coord1_t const pi_half1 = constants1::max_latitude();
static coord2_t const pi_half2 = constants2::max_latitude();
static calc_t const c0 = 0;
coord1_t const a0 = geometry::get<0>(segment_a);
coord1_t const a1 = geometry::get<1>(segment_a);
coord1_t const b0 = geometry::get<0>(segment_b);
coord1_t const b1 = geometry::get<1>(segment_b);
coord2_t const p0 = geometry::get<0>(p);
coord2_t const p1 = geometry::get<1>(p);
if ( (math::equals(b0, a0) && math::equals(b1, a1))
|| (math::equals(b0, p0) && math::equals(b1, p1)) )
{
return 0;
}
bool const is_a_pole = math::equals(pi_half1, math::abs(a1));
bool const is_b_pole = math::equals(pi_half1, math::abs(b1));
bool const is_p_pole = math::equals(pi_half2, math::abs(p1));
if ( is_b_pole && ((is_a_pole && math::sign(b1) == math::sign(a1))
|| (is_p_pole && math::sign(b1) == math::sign(p1))) )
{
return 0;
}
// NOTE: as opposed to the implementation for cartesian CS
// here point b is the origin
calc_t const dlon1 = math::longitude_distance_signed<units_t, calc_t>(b0, a0);
calc_t const dlon2 = math::longitude_distance_signed<units_t, calc_t>(b0, p0);
bool is_antilon1 = false, is_antilon2 = false;
calc_t const dlat1 = latitude_distance_signed<units_t, calc_t>(b1, a1, dlon1, is_antilon1);
calc_t const dlat2 = latitude_distance_signed<units_t, calc_t>(b1, p1, dlon2, is_antilon2);
calc_t mx = is_a_pole || is_b_pole || is_p_pole ?
c0 :
(std::min)(is_antilon1 ? c0 : math::abs(dlon1),
is_antilon2 ? c0 : math::abs(dlon2));
calc_t my = (std::min)(math::abs(dlat1),
math::abs(dlat2));
int s1 = 0, s2 = 0;
if (mx >= my)
{
s1 = dlon1 > 0 ? 1 : -1;
s2 = dlon2 > 0 ? 1 : -1;
}
else
{
s1 = dlat1 > 0 ? 1 : -1;
s2 = dlat2 > 0 ? 1 : -1;
}
return s1 == s2 ? -1 : 1;
}
template <typename Units, typename T>
static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, bool & is_antilon)
{
typedef math::detail::constants_on_spheroid<T, Units> constants;
static T const pi = constants::half_period();
static T const c0 = 0;
T res = lat2 - lat1;
is_antilon = math::equals(math::abs(lon_ds), pi);
if (is_antilon)
{
res = lat2 + lat1;
if (res >= c0)
res = pi - res;
else
res = -pi - res;
}
return res;
}
};
template <typename Point>
struct direction_code_impl<Point, spherical_polar_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 segment_a, Point1 segment_b,
Point2 p)
{
typedef math::detail::constants_on_spheroid
<
typename coordinate_type<Point1>::type,
typename coordinate_system<Point1>::type::units
> constants1;
typedef math::detail::constants_on_spheroid
<
typename coordinate_type<Point2>::type,
typename coordinate_system<Point2>::type::units
> constants2;
geometry::set<1>(segment_a,
constants1::max_latitude() - geometry::get<1>(segment_a));
geometry::set<1>(segment_b,
constants1::max_latitude() - geometry::get<1>(segment_b));
geometry::set<1>(p,
constants2::max_latitude() - geometry::get<1>(p));
return direction_code_impl
<
Point, spherical_equatorial_tag
>::apply(segment_a, segment_b, p);
}
};
template <typename Point>
struct direction_code_impl<Point, geographic_tag>
: direction_code_impl<Point, spherical_equatorial_tag>
{};
// Gives sense of direction for point p, collinear w.r.t. segment (a,b) // Gives sense of direction for point p, collinear w.r.t. segment (a,b)
// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a // Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a
// Returns 1 if p goes forward, so extends (a,b) // Returns 1 if p goes forward, so extends (a,b)
@ -44,28 +240,9 @@ inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
// Note that it does not do any collinearity test, that should be done before // Note that it does not do any collinearity test, that should be done before
template <typename Point1, typename Point2> template <typename Point1, typename Point2>
inline int direction_code(Point1 const& segment_a, Point1 const& segment_b, inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
const Point2& p) Point2 const& p)
{ {
// Suppose segment = (4 3,4 4) and p =(4 2) return direction_code_impl<Point1>::apply(segment_a, segment_b, p);
// Then sign_a1 = 1 and sign_p1 = 1 -> goes backward -> return -1
int const sign_a0 = sign_of_difference<0>(segment_b, segment_a);
int const sign_a1 = sign_of_difference<1>(segment_b, segment_a);
if (sign_a0 == 0 && sign_a1 == 0)
{
return 0;
}
int const sign_p0 = sign_of_difference<0>(segment_b, p);
int const sign_p1 = sign_of_difference<1>(segment_b, p);
if (sign_p0 == 0 && sign_p1 == 0)
{
return 0;
}
return sign_a0 == sign_p0 && sign_a1 == sign_p1 ? -1 : 1;
} }
@ -73,7 +250,6 @@ inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
#endif //DOXYGEN_NO_DETAIL #endif //DOXYGEN_NO_DETAIL
}} // namespace boost::geometry }} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP

View File

@ -5,6 +5,11 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK. // Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -117,12 +122,6 @@ struct extreme_points_on_ring
typedef typename boost::range_iterator<Ring const>::type range_iterator; typedef typename boost::range_iterator<Ring const>::type range_iterator;
typedef typename geometry::point_type<Ring>::type point_type; typedef typename geometry::point_type<Ring>::type point_type;
typedef typename geometry::strategy::side::services::default_strategy
<
typename geometry::cs_tag<point_type>::type
>::type side_strategy;
template <typename CirclingIterator, typename Points> template <typename CirclingIterator, typename Points>
static inline bool extend(CirclingIterator& it, static inline bool extend(CirclingIterator& it,
std::size_t n, std::size_t n,
@ -214,10 +213,11 @@ struct extreme_points_on_ring
return true; return true;
} }
template <typename Extremes, typename Intruders, typename CirclingIterator> template <typename Extremes, typename Intruders, typename CirclingIterator, typename SideStrategy>
static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right, static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right,
Extremes const& extremes, Extremes const& extremes,
Intruders& intruders) Intruders& intruders,
SideStrategy const& strategy)
{ {
if (boost::size(extremes) < 3) if (boost::size(extremes) < 3)
{ {
@ -238,8 +238,8 @@ struct extreme_points_on_ring
if (coordinate > min_value && other_coordinate > other_min && other_coordinate < other_max) if (coordinate > min_value && other_coordinate > other_min && other_coordinate < other_max)
{ {
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1; int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
int const first_side = side_strategy::apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor; int const first_side = strategy.apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;
int const last_side = side_strategy::apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor; int const last_side = strategy.apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;
// If not lying left from any of the extemes side // If not lying left from any of the extemes side
if (first_side != 1 && last_side != 1) if (first_side != 1 && last_side != 1)
@ -263,10 +263,11 @@ struct extreme_points_on_ring
} }
} }
template <typename Extremes, typename Intruders> template <typename Extremes, typename Intruders, typename SideStrategy>
static inline void get_intruders(Ring const& ring, static inline void get_intruders(Ring const& ring,
Extremes const& extremes, Extremes const& extremes,
Intruders& intruders) Intruders& intruders,
SideStrategy const& strategy)
{ {
std::size_t const n = boost::size(ring); std::size_t const n = boost::size(ring);
if (n >= 3) if (n >= 3)
@ -275,12 +276,12 @@ struct extreme_points_on_ring
geometry::ever_circling_range_iterator<Ring const> right(ring); geometry::ever_circling_range_iterator<Ring const> right(ring);
++right; ++right;
get_intruders(ring, left, right, extremes, intruders); get_intruders(ring, left, right, extremes, intruders, strategy);
} }
} }
template <typename Iterator> template <typename Iterator, typename SideStrategy>
static inline bool right_turn(Ring const& ring, Iterator it) static inline bool right_turn(Ring const& ring, Iterator it, SideStrategy const& strategy)
{ {
typename std::iterator_traits<Iterator>::difference_type const index typename std::iterator_traits<Iterator>::difference_type const index
= std::distance(boost::begin(ring), it); = std::distance(boost::begin(ring), it);
@ -295,8 +296,8 @@ struct extreme_points_on_ring
} }
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1; int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
int const first_side = side_strategy::apply(*(right - 1), *right, *left) * factor; int const first_side = strategy.apply(*(right - 1), *right, *left) * factor;
int const last_side = side_strategy::apply(*left, *(left + 1), *right) * factor; int const last_side = strategy.apply(*left, *(left + 1), *right) * factor;
//std::cout << "Candidate at " << geometry::wkt(*it) << " first=" << first_side << " last=" << last_side << std::endl; //std::cout << "Candidate at " << geometry::wkt(*it) << " first=" << first_side << " last=" << last_side << std::endl;
@ -306,8 +307,11 @@ struct extreme_points_on_ring
// Gets the extreme segments (top point plus neighbouring points), plus intruders, if any, on the same ring // Gets the extreme segments (top point plus neighbouring points), plus intruders, if any, on the same ring
template <typename Extremes, typename Intruders> template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Ring const& ring, Extremes& extremes, Intruders& intruders) static inline bool apply(Ring const& ring,
Extremes& extremes,
Intruders& intruders,
SideStrategy const& strategy)
{ {
std::size_t const n = boost::size(ring); std::size_t const n = boost::size(ring);
if (n < 3) if (n < 3)
@ -321,7 +325,7 @@ struct extreme_points_on_ring
compare<Dimension> smaller; compare<Dimension> smaller;
for (range_iterator it = max_it + 1; it != boost::end(ring); ++it) for (range_iterator it = max_it + 1; it != boost::end(ring); ++it)
{ {
if (smaller(*max_it, *it) && right_turn(ring, it)) if (smaller(*max_it, *it) && right_turn(ring, it, strategy))
{ {
max_it = it; max_it = it;
} }
@ -365,7 +369,7 @@ struct extreme_points_on_ring
std::copy(points.begin(), points.end(), std::back_inserter(extremes)); std::copy(points.begin(), points.end(), std::back_inserter(extremes));
get_intruders(ring, left, right, extremes, intruders); get_intruders(ring, left, right, extremes, intruders, strategy);
return true; return true;
} }
@ -403,8 +407,9 @@ struct extreme_points<Ring, Dimension, ring_tag>
template<typename Polygon, std::size_t Dimension> template<typename Polygon, std::size_t Dimension>
struct extreme_points<Polygon, Dimension, polygon_tag> struct extreme_points<Polygon, Dimension, polygon_tag>
{ {
template <typename Extremes, typename Intruders> template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders) static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders,
SideStrategy const& strategy)
{ {
typedef typename geometry::ring_type<Polygon>::type ring_type; typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef detail::extreme_points::extreme_points_on_ring typedef detail::extreme_points::extreme_points_on_ring
@ -412,7 +417,8 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
ring_type, Dimension ring_type, Dimension
> ring_implementation; > ring_implementation;
if (! ring_implementation::apply(geometry::exterior_ring(polygon), extremes, intruders)) if (! ring_implementation::apply(geometry::exterior_ring(polygon),
extremes, intruders, strategy))
{ {
return false; return false;
} }
@ -423,7 +429,7 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
for (typename detail::interior_iterator<Polygon const>::type for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it) it = boost::begin(rings); it != boost::end(rings); ++it)
{ {
ring_implementation::get_intruders(*it, extremes, intruders); ring_implementation::get_intruders(*it, extremes, intruders, strategy);
} }
return true; return true;
@ -433,8 +439,9 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
template<typename Box> template<typename Box>
struct extreme_points<Box, 1, box_tag> struct extreme_points<Box, 1, box_tag>
{ {
template <typename Extremes, typename Intruders> template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ) static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
SideStrategy const& )
{ {
extremes.resize(4); extremes.resize(4);
geometry::detail::assign_box_corners_oriented<false>(box, extremes); geometry::detail::assign_box_corners_oriented<false>(box, extremes);
@ -446,8 +453,9 @@ struct extreme_points<Box, 1, box_tag>
template<typename Box> template<typename Box>
struct extreme_points<Box, 0, box_tag> struct extreme_points<Box, 0, box_tag>
{ {
template <typename Extremes, typename Intruders> template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ) static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
SideStrategy const& )
{ {
extremes.resize(4); extremes.resize(4);
geometry::detail::assign_box_corners_oriented<false>(box, extremes); geometry::detail::assign_box_corners_oriented<false>(box, extremes);
@ -460,8 +468,9 @@ struct extreme_points<Box, 0, box_tag>
template<typename MultiPolygon, std::size_t Dimension> template<typename MultiPolygon, std::size_t Dimension>
struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag> struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
{ {
template <typename Extremes, typename Intruders> template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(MultiPolygon const& multi, Extremes& extremes, Intruders& intruders) static inline bool apply(MultiPolygon const& multi, Extremes& extremes,
Intruders& intruders, SideStrategy const& strategy)
{ {
// Get one for the very first polygon, that is (for the moment) enough. // Get one for the very first polygon, that is (for the moment) enough.
// It is not guaranteed the "extreme" then, but for the current purpose // It is not guaranteed the "extreme" then, but for the current purpose
@ -473,7 +482,7 @@ struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
typename boost::range_value<MultiPolygon const>::type, typename boost::range_value<MultiPolygon const>::type,
Dimension, Dimension,
polygon_tag polygon_tag
>::apply(*boost::begin(multi), extremes, intruders); >::apply(*boost::begin(multi), extremes, intruders, strategy);
} }
return false; return false;
@ -489,8 +498,18 @@ struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
for Edge=0 in dimension 0, the right side) for Edge=0 in dimension 0, the right side)
\note We could specify a strategy (less/greater) to get bottom/left side too. However, until now we don't need that. \note We could specify a strategy (less/greater) to get bottom/left side too. However, until now we don't need that.
*/ */
template <std::size_t Edge, typename Geometry, typename Extremes, typename Intruders> template
inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders) <
std::size_t Edge,
typename Geometry,
typename Extremes,
typename Intruders,
typename SideStrategy
>
inline bool extreme_points(Geometry const& geometry,
Extremes& extremes,
Intruders& intruders,
SideStrategy const& strategy)
{ {
concepts::check<Geometry const>(); concepts::check<Geometry const>();
@ -509,7 +528,11 @@ inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intrude
const const
>(); >();
return dispatch::extreme_points<Geometry, Edge>::apply(geometry, extremes, intruders); return dispatch::extreme_points
<
Geometry,
Edge
>::apply(geometry, extremes, intruders, strategy);
} }

View File

@ -2,6 +2,11 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. // 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -60,17 +65,14 @@ inline int squared_length(Vector const& vector)
} }
template <typename Point> template <typename Point, typename SideStrategy>
struct angle_less struct angle_less
{ {
typedef Point vector_type; typedef Point vector_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type side_strategy_type;
angle_less(Point const& origin) angle_less(Point const& origin, SideStrategy const& strategy)
: m_origin(origin) : m_origin(origin)
, m_strategy(strategy)
{} {}
template <typename Angle> template <typename Angle>
@ -89,8 +91,7 @@ struct angle_less
return quadrant_p < quadrant_q; return quadrant_p < quadrant_q;
} }
// Same quadrant, check if p is located left of q // Same quadrant, check if p is located left of q
int const side = side_strategy_type::apply(m_origin, q.point, int const side = m_strategy.apply(m_origin, q.point, p.point);
p.point);
if (side != 0) if (side != 0)
{ {
return side == 1; return side == 1;
@ -114,19 +115,17 @@ struct angle_less
private: private:
Point m_origin; Point m_origin;
SideStrategy m_strategy;
}; };
template <typename Point> template <typename Point, typename SideStrategy>
struct angle_equal_to struct angle_equal_to
{ {
typedef Point vector_type; typedef Point vector_type;
typedef typename strategy::side::services::default_strategy
< inline angle_equal_to(Point const& origin, SideStrategy const& strategy)
typename cs_tag<Point>::type
>::type side_strategy_type;
inline angle_equal_to(Point const& origin)
: m_origin(origin) : m_origin(origin)
, m_strategy(strategy)
{} {}
template <typename Angle> template <typename Angle>
@ -143,13 +142,13 @@ struct angle_equal_to
return false; return false;
} }
// Same quadrant, check if p/q are collinear // Same quadrant, check if p/q are collinear
int const side = side_strategy_type::apply(m_origin, q.point, int const side = m_strategy.apply(m_origin, q.point, p.point);
p.point);
return side == 0; return side == 0;
} }
private: private:
Point m_origin; Point m_origin;
SideStrategy m_strategy;
}; };
template <typename AngleCollection, typename Turns> template <typename AngleCollection, typename Turns>
@ -193,13 +192,14 @@ inline void get_left_turns(AngleCollection const& sorted_angles,
//! Returns the number of clusters //! Returns the number of clusters
template <typename Point, typename AngleCollection> template <typename Point, typename AngleCollection, typename SideStrategy>
inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin) inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin,
SideStrategy const& strategy)
{ {
// Assign same cluster_index for all turns in same direction // Assign same cluster_index for all turns in same direction
BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u); BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u);
angle_equal_to<Point> comparator(origin); angle_equal_to<Point, SideStrategy> comparator(origin, strategy);
typename boost::range_iterator<AngleCollection>::type it = sorted.begin(); typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
std::size_t cluster_index = 0; std::size_t cluster_index = 0;

View File

@ -236,7 +236,9 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
template <typename Linestring, bool CheckSelfIntersections = true> template <typename Linestring, bool CheckSelfIntersections = true>
struct is_simple_linestring struct is_simple_linestring
{ {
static inline bool apply(Linestring const& linestring) template <typename Strategy>
static inline bool apply(Linestring const& linestring,
Strategy const& strategy)
{ {
simplicity_failure_policy policy; simplicity_failure_policy policy;
return ! boost::empty(linestring) return ! boost::empty(linestring)
@ -247,7 +249,7 @@ struct is_simple_linestring
&& ! detail::is_valid::has_spikes && ! detail::is_valid::has_spikes
< <
Linestring, closed Linestring, closed
>::apply(linestring, policy); >::apply(linestring, policy, strategy.get_side_strategy());
} }
}; };
@ -258,7 +260,10 @@ struct is_simple_linestring<Linestring, true>
static inline bool apply(Linestring const& linestring, static inline bool apply(Linestring const& linestring,
Strategy const& strategy) Strategy const& strategy)
{ {
return is_simple_linestring<Linestring, false>::apply(linestring) return is_simple_linestring
<
Linestring, false
>::apply(linestring, strategy)
&& ! has_self_intersections(linestring, strategy); && ! has_self_intersections(linestring, strategy);
} }
}; };
@ -267,23 +272,44 @@ struct is_simple_linestring<Linestring, true>
template <typename MultiLinestring> template <typename MultiLinestring>
struct is_simple_multilinestring struct is_simple_multilinestring
{ {
private:
template <typename Strategy>
struct per_linestring
{
per_linestring(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Linestring>
inline bool apply(Linestring const& linestring) const
{
return detail::is_simple::is_simple_linestring
<
Linestring,
false // do not compute self-intersections
>::apply(linestring, m_strategy);
}
Strategy const& m_strategy;
};
public:
template <typename Strategy> template <typename Strategy>
static inline bool apply(MultiLinestring const& multilinestring, static inline bool apply(MultiLinestring const& multilinestring,
Strategy const& strategy) Strategy const& strategy)
{ {
typedef per_linestring<Strategy> per_ls;
// check each of the linestrings for simplicity // check each of the linestrings for simplicity
// but do not compute self-intersections yet; these will be // but do not compute self-intersections yet; these will be
// computed for the entire multilinestring // computed for the entire multilinestring
if ( ! detail::check_iterator_range if ( ! detail::check_iterator_range
< <
is_simple_linestring per_ls, // do not compute self-intersections
<
typename boost::range_value<MultiLinestring>::type,
false // do not compute self-intersections
>,
true // allow empty multilinestring true // allow empty multilinestring
>::apply(boost::begin(multilinestring), >::apply(boost::begin(multilinestring),
boost::end(multilinestring)) boost::end(multilinestring),
per_ls(strategy))
) )
{ {
return false; return false;

View File

@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0. // Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html // http://www.boost.org/users/license.html
@ -91,8 +92,9 @@ struct has_spikes
return std::find_if(second, last, not_equal(*first)); return std::find_if(second, last, not_equal(*first));
} }
template <typename VisitPolicy> template <typename VisitPolicy, typename SideStrategy>
static inline bool apply(Range const& range, VisitPolicy& visitor) static inline bool apply(Range const& range, VisitPolicy& visitor,
SideStrategy const& strategy)
{ {
boost::ignore_unused(visitor); boost::ignore_unused(visitor);
@ -124,9 +126,8 @@ struct has_spikes
while (next != boost::end(view)) while (next != boost::end(view))
{ {
if ( geometry::detail::point_is_spike_or_equal(*prev, if ( geometry::detail::point_is_spike_or_equal(*prev, *next, *cur,
*next, strategy) )
*cur) )
{ {
return return
! visitor.template apply<failure_spikes>(is_linear, *cur); ! visitor.template apply<failure_spikes>(is_linear, *cur);
@ -146,7 +147,7 @@ struct has_spikes
boost::rend(view)); boost::rend(view));
iterator next = find_different_from_first(cur, boost::end(view)); iterator next = find_different_from_first(cur, boost::end(view));
if (detail::point_is_spike_or_equal(*prev, *next, *cur)) if (detail::point_is_spike_or_equal(*prev, *next, *cur, strategy))
{ {
return return
! visitor.template apply<failure_spikes>(is_linear, *cur); ! visitor.template apply<failure_spikes>(is_linear, *cur);

View File

@ -43,9 +43,10 @@ namespace detail { namespace is_valid
template <typename Linestring> template <typename Linestring>
struct is_valid_linestring struct is_valid_linestring
{ {
template <typename VisitPolicy> template <typename VisitPolicy, typename Strategy>
static inline bool apply(Linestring const& linestring, static inline bool apply(Linestring const& linestring,
VisitPolicy& visitor) VisitPolicy& visitor,
Strategy const& strategy)
{ {
if (has_invalid_coordinate<Linestring>::apply(linestring, visitor)) if (has_invalid_coordinate<Linestring>::apply(linestring, visitor))
{ {
@ -75,15 +76,12 @@ struct is_valid_linestring
{ {
return visitor.template apply<no_failure>(); return visitor.template apply<no_failure>();
} }
return ! has_spikes<Linestring, closed>::apply(linestring, visitor);
}
template <typename VisitPolicy, typename Strategy> return ! has_spikes
static inline bool apply(Linestring const& linestring, <
VisitPolicy& visitor, Linestring, closed
Strategy const&) >::apply(linestring, visitor,
{ strategy.get_side_strategy());
return apply(linestring, visitor);
} }
}; };
@ -132,10 +130,13 @@ class is_valid
> >
{ {
private: private:
template <typename VisitPolicy> template <typename VisitPolicy, typename Strategy>
struct per_linestring struct per_linestring
{ {
per_linestring(VisitPolicy& policy) : m_policy(policy) {} per_linestring(VisitPolicy& policy, Strategy const& strategy)
: m_policy(policy)
, m_strategy(strategy)
{}
template <typename Linestring> template <typename Linestring>
inline bool apply(Linestring const& linestring) const inline bool apply(Linestring const& linestring) const
@ -143,17 +144,18 @@ private:
return detail::is_valid::is_valid_linestring return detail::is_valid::is_valid_linestring
< <
Linestring Linestring
>::apply(linestring, m_policy); >::apply(linestring, m_policy, m_strategy);
} }
VisitPolicy& m_policy; VisitPolicy& m_policy;
Strategy const& m_strategy;
}; };
public: public:
template <typename VisitPolicy, typename Strategy> template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiLinestring const& multilinestring, static inline bool apply(MultiLinestring const& multilinestring,
VisitPolicy& visitor, VisitPolicy& visitor,
Strategy const&) Strategy const& strategy)
{ {
if (BOOST_GEOMETRY_CONDITION( if (BOOST_GEOMETRY_CONDITION(
AllowEmptyMultiGeometries && boost::empty(multilinestring))) AllowEmptyMultiGeometries && boost::empty(multilinestring)))
@ -161,13 +163,15 @@ public:
return visitor.template apply<no_failure>(); return visitor.template apply<no_failure>();
} }
typedef per_linestring<VisitPolicy, Strategy> per_ls;
return detail::check_iterator_range return detail::check_iterator_range
< <
per_linestring<VisitPolicy>, per_ls,
false // do not check for empty multilinestring (done above) false // do not check for empty multilinestring (done above)
>::apply(boost::begin(multilinestring), >::apply(boost::begin(multilinestring),
boost::end(multilinestring), boost::end(multilinestring),
per_linestring<VisitPolicy>(visitor)); per_ls(visitor, strategy));
} }
}; };

View File

@ -198,7 +198,7 @@ struct is_valid_ring
return return
is_topologically_closed<Ring, closure>::apply(ring, visitor) is_topologically_closed<Ring, closure>::apply(ring, visitor)
&& ! has_duplicates<Ring, closure>::apply(ring, visitor) && ! has_duplicates<Ring, closure>::apply(ring, visitor)
&& ! has_spikes<Ring, closure>::apply(ring, visitor) && ! has_spikes<Ring, closure>::apply(ring, visitor, strategy.get_side_strategy())
&& (! CheckSelfIntersections && (! CheckSelfIntersections
|| has_valid_self_turns<Ring>::apply(ring, visitor, strategy)) || has_valid_self_turns<Ring>::apply(ring, visitor, strategy))
&& is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy); && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy);

View File

@ -2,6 +2,11 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. // 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -99,12 +104,18 @@ public :
} }
} }
template <typename RobustPoint, typename Turns> template <typename RobustPoint, typename Turns, typename SideStrategy>
inline void get_left_turns(RobustPoint const& origin, Turns& turns) inline void get_left_turns(RobustPoint const& origin, Turns& turns,
SideStrategy const& strategy)
{ {
typedef detail::left_turns::angle_less
<
typename AngleInfo::point_type,
SideStrategy
> angle_less;
// Sort on angle // Sort on angle
std::sort(m_angles.begin(), m_angles.end(), std::sort(m_angles.begin(), m_angles.end(), angle_less(origin, strategy));
detail::left_turns::angle_less<typename AngleInfo::point_type>(origin));
// Group same-angled elements // Group same-angled elements
std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin); std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin);

View File

@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014. // This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014 Oracle and/or its affiliates. // Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -63,8 +63,9 @@ inline bool points_equal_or_close(Point1 const& point1,
} }
template <typename Range, typename Point, typename RobustPolicy> template <typename Range, typename Point, typename SideStrategy, typename RobustPolicy>
inline void append_no_dups_or_spikes(Range& range, Point const& point, inline void append_no_dups_or_spikes(Range& range, Point const& point,
SideStrategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
@ -92,6 +93,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
&& point_is_spike_or_equal(point, && point_is_spike_or_equal(point,
*(boost::end(range) - 3), *(boost::end(range) - 3),
*(boost::end(range) - 2), *(boost::end(range) - 2),
strategy,
robust_policy)) robust_policy))
{ {
// Use the Concept/traits, so resize and append again // Use the Concept/traits, so resize and append again
@ -100,8 +102,9 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
} }
} }
template <typename Range, typename RobustPolicy> template <typename Range, typename SideStrategy, typename RobustPolicy>
inline void clean_closing_dups_and_spikes(Range& range, inline void clean_closing_dups_and_spikes(Range& range,
SideStrategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
std::size_t const minsize std::size_t const minsize
@ -135,7 +138,7 @@ inline void clean_closing_dups_and_spikes(Range& range,
// Check if closing point is a spike (this is so if the second point is // Check if closing point is a spike (this is so if the second point is
// considered as a spike w.r.t. the last segment) // considered as a spike w.r.t. the last segment)
if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy)) if (point_is_spike_or_equal(*second, *ultimate, *first, strategy, robust_policy))
{ {
range::erase(range, first); range::erase(range, first);
if (BOOST_GEOMETRY_CONDITION(closed)) if (BOOST_GEOMETRY_CONDITION(closed))

View File

@ -2,8 +2,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014. // This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014 Oracle and/or its affiliates. // Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -57,12 +57,14 @@ struct copy_segments_ring
< <
typename Ring, typename Ring,
typename SegmentIdentifier, typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy, typename RobustPolicy,
typename RangeOut typename RangeOut
> >
static inline void apply(Ring const& ring, static inline void apply(Ring const& ring,
SegmentIdentifier const& seg_id, SegmentIdentifier const& seg_id,
signed_size_type to_index, signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
RangeOut& current_output) RangeOut& current_output)
{ {
@ -109,7 +111,7 @@ struct copy_segments_ring
for (signed_size_type i = 0; i < count; ++i, ++it) for (signed_size_type i = 0; i < count; ++i, ++it)
{ {
detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy); detail::overlay::append_no_dups_or_spikes(current_output, *it, strategy, robust_policy);
} }
} }
}; };
@ -119,20 +121,23 @@ class copy_segments_linestring
{ {
private: private:
// remove spikes // remove spikes
template <typename RangeOut, typename Point, typename RobustPolicy> template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy>
static inline void append_to_output(RangeOut& current_output, static inline void append_to_output(RangeOut& current_output,
Point const& point, Point const& point,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
boost::true_type const&) boost::true_type const&)
{ {
detail::overlay::append_no_dups_or_spikes(current_output, point, detail::overlay::append_no_dups_or_spikes(current_output, point,
strategy,
robust_policy); robust_policy);
} }
// keep spikes // keep spikes
template <typename RangeOut, typename Point, typename RobustPolicy> template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy>
static inline void append_to_output(RangeOut& current_output, static inline void append_to_output(RangeOut& current_output,
Point const& point, Point const& point,
SideStrategy const&,
RobustPolicy const&, RobustPolicy const&,
boost::false_type const&) boost::false_type const&)
{ {
@ -144,12 +149,14 @@ public:
< <
typename LineString, typename LineString,
typename SegmentIdentifier, typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy, typename RobustPolicy,
typename RangeOut typename RangeOut
> >
static inline void apply(LineString const& ls, static inline void apply(LineString const& ls,
SegmentIdentifier const& seg_id, SegmentIdentifier const& seg_id,
signed_size_type to_index, signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
RangeOut& current_output) RangeOut& current_output)
{ {
@ -170,7 +177,7 @@ public:
for (signed_size_type i = 0; i < count; ++i, ++it) for (signed_size_type i = 0; i < count; ++i, ++it)
{ {
append_to_output(current_output, *it, robust_policy, append_to_output(current_output, *it, strategy, robust_policy,
boost::integral_constant<bool, RemoveSpikes>()); boost::integral_constant<bool, RemoveSpikes>());
} }
} }
@ -183,12 +190,14 @@ struct copy_segments_polygon
< <
typename Polygon, typename Polygon,
typename SegmentIdentifier, typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy, typename RobustPolicy,
typename RangeOut typename RangeOut
> >
static inline void apply(Polygon const& polygon, static inline void apply(Polygon const& polygon,
SegmentIdentifier const& seg_id, SegmentIdentifier const& seg_id,
signed_size_type to_index, signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
RangeOut& current_output) RangeOut& current_output)
{ {
@ -199,6 +208,7 @@ struct copy_segments_polygon
? geometry::exterior_ring(polygon) ? geometry::exterior_ring(polygon)
: range::at(geometry::interior_rings(polygon), seg_id.ring_index), : range::at(geometry::interior_rings(polygon), seg_id.ring_index),
seg_id, to_index, seg_id, to_index,
strategy,
robust_policy, robust_policy,
current_output current_output
); );
@ -213,12 +223,14 @@ struct copy_segments_box
< <
typename Box, typename Box,
typename SegmentIdentifier, typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy, typename RobustPolicy,
typename RangeOut typename RangeOut
> >
static inline void apply(Box const& box, static inline void apply(Box const& box,
SegmentIdentifier const& seg_id, SegmentIdentifier const& seg_id,
signed_size_type to_index, signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
RangeOut& current_output) RangeOut& current_output)
{ {
@ -239,7 +251,7 @@ struct copy_segments_box
for (signed_size_type i = 0; i < count; i++, index++) for (signed_size_type i = 0; i < count; i++, index++)
{ {
detail::overlay::append_no_dups_or_spikes(current_output, detail::overlay::append_no_dups_or_spikes(current_output,
bp[index % 5], robust_policy); bp[index % 5], strategy, robust_policy);
} }
} }
@ -253,12 +265,14 @@ struct copy_segments_multi
< <
typename MultiGeometry, typename MultiGeometry,
typename SegmentIdentifier, typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy, typename RobustPolicy,
typename RangeOut typename RangeOut
> >
static inline void apply(MultiGeometry const& multi_geometry, static inline void apply(MultiGeometry const& multi_geometry,
SegmentIdentifier const& seg_id, SegmentIdentifier const& seg_id,
signed_size_type to_index, signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
RangeOut& current_output) RangeOut& current_output)
{ {
@ -272,6 +286,7 @@ struct copy_segments_multi
// Call the single-version // Call the single-version
Policy::apply(range::at(multi_geometry, seg_id.multi_index), Policy::apply(range::at(multi_geometry, seg_id.multi_index),
seg_id, to_index, seg_id, to_index,
strategy,
robust_policy, robust_policy,
current_output); current_output);
} }
@ -341,12 +356,14 @@ template
bool Reverse, bool Reverse,
typename Geometry, typename Geometry,
typename SegmentIdentifier, typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy, typename RobustPolicy,
typename RangeOut typename RangeOut
> >
inline void copy_segments(Geometry const& geometry, inline void copy_segments(Geometry const& geometry,
SegmentIdentifier const& seg_id, SegmentIdentifier const& seg_id,
signed_size_type to_index, signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
RangeOut& range_out) RangeOut& range_out)
{ {
@ -356,7 +373,7 @@ inline void copy_segments(Geometry const& geometry,
< <
typename tag<Geometry>::type, typename tag<Geometry>::type,
Reverse Reverse
>::apply(geometry, seg_id, to_index, robust_policy, range_out); >::apply(geometry, seg_id, to_index, strategy, robust_policy, range_out);
} }

View File

@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -59,7 +64,7 @@ template
typename Turns, typename Turns,
typename Geometry1, typename Geometry2, typename Geometry1, typename Geometry2,
typename RobustPolicy, typename RobustPolicy,
typename Strategy typename SideStrategy
> >
inline void enrich_sort(Operations& operations, inline void enrich_sort(Operations& operations,
Turns const& turns, Turns const& turns,
@ -67,7 +72,7 @@ inline void enrich_sort(Operations& operations,
Geometry1 const& geometry1, Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Strategy const& /*strategy*/) SideStrategy const& strategy)
{ {
std::sort(boost::begin(operations), std::sort(boost::begin(operations),
boost::end(operations), boost::end(operations),
@ -77,8 +82,9 @@ inline void enrich_sort(Operations& operations,
typename boost::range_value<Operations>::type, typename boost::range_value<Operations>::type,
Geometry1, Geometry2, Geometry1, Geometry2,
RobustPolicy, RobustPolicy,
SideStrategy,
Reverse1, Reverse2 Reverse1, Reverse2
>(turns, for_operation, geometry1, geometry2, robust_policy)); >(turns, for_operation, geometry1, geometry2, robust_policy, strategy));
} }
@ -275,7 +281,7 @@ inline void calculate_remaining_distance(Turns& turns)
\tparam Clusters type of cluster container \tparam Clusters type of cluster container
\tparam Geometry1 \tparam_geometry \tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry \tparam Geometry2 \tparam_geometry
\tparam Strategy side strategy type \tparam SideStrategy side strategy type
\param turns container containing intersection points \param turns container containing intersection points
\param clusters container containing clusters \param clusters container containing clusters
\param geometry1 \param_geometry \param geometry1 \param_geometry
@ -291,13 +297,13 @@ template
typename Clusters, typename Clusters,
typename Geometry1, typename Geometry2, typename Geometry1, typename Geometry2,
typename RobustPolicy, typename RobustPolicy,
typename Strategy typename SideStrategy
> >
inline void enrich_intersection_points(Turns& turns, inline void enrich_intersection_points(Turns& turns,
Clusters& clusters, Clusters& clusters,
Geometry1 const& geometry1, Geometry2 const& geometry2, Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Strategy const& strategy) SideStrategy const& strategy)
{ {
static const detail::overlay::operation_type target_operation static const detail::overlay::operation_type target_operation
= detail::overlay::operation_from_overlay<OverlayType>::value; = detail::overlay::operation_from_overlay<OverlayType>::value;
@ -420,7 +426,8 @@ inline void enrich_intersection_points(Turns& turns,
Reverse1, Reverse1,
Reverse2, Reverse2,
OverlayType OverlayType
>(clusters, turns, target_operation, geometry1, geometry2); >(clusters, turns, target_operation,
geometry1, geometry2, strategy);
detail::overlay::cleanup_clusters(turns, clusters); detail::overlay::cleanup_clusters(turns, clusters);
} }

View File

@ -157,6 +157,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
typename LineString, typename LineString,
typename Point, typename Point,
typename Operation, typename Operation,
typename SideStrategy,
typename RobustPolicy typename RobustPolicy
> >
static inline void enter(LineStringOut& current_piece, static inline void enter(LineStringOut& current_piece,
@ -164,6 +165,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
segment_identifier& segment_id, segment_identifier& segment_id,
signed_size_type , Point const& point, signed_size_type , Point const& point,
Operation const& operation, Operation const& operation,
SideStrategy const& ,
RobustPolicy const& , RobustPolicy const& ,
OutputIterator& ) OutputIterator& )
{ {
@ -180,6 +182,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
typename LineString, typename LineString,
typename Point, typename Point,
typename Operation, typename Operation,
typename SideStrategy,
typename RobustPolicy typename RobustPolicy
> >
static inline void leave(LineStringOut& current_piece, static inline void leave(LineStringOut& current_piece,
@ -187,6 +190,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
segment_identifier& segment_id, segment_identifier& segment_id,
signed_size_type index, Point const& point, signed_size_type index, Point const& point,
Operation const& , Operation const& ,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
OutputIterator& out) OutputIterator& out)
{ {
@ -195,7 +199,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
detail::copy_segments::copy_segments_linestring detail::copy_segments::copy_segments_linestring
< <
false, RemoveSpikes false, RemoveSpikes
>::apply(linestring, segment_id, index, robust_policy, current_piece); >::apply(linestring, segment_id, index, strategy, robust_policy, current_piece);
detail::overlay::append_no_duplicates(current_piece, point); detail::overlay::append_no_duplicates(current_piece, point);
if (::boost::size(current_piece) > 1) if (::boost::size(current_piece) > 1)
{ {
@ -254,6 +258,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
typename LineString, typename LineString,
typename Point, typename Point,
typename Operation, typename Operation,
typename SideStrategy,
typename RobustPolicy typename RobustPolicy
> >
static inline void enter(LineStringOut& current_piece, static inline void enter(LineStringOut& current_piece,
@ -261,11 +266,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
segment_identifier& segment_id, segment_identifier& segment_id,
signed_size_type index, Point const& point, signed_size_type index, Point const& point,
Operation const& operation, Operation const& operation,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
OutputIterator& out) OutputIterator& out)
{ {
normal_action::leave(current_piece, linestring, segment_id, index, normal_action::leave(current_piece, linestring, segment_id, index,
point, operation, robust_policy, out); point, operation, strategy, robust_policy, out);
} }
template template
@ -275,6 +281,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
typename LineString, typename LineString,
typename Point, typename Point,
typename Operation, typename Operation,
typename SideStrategy,
typename RobustPolicy typename RobustPolicy
> >
static inline void leave(LineStringOut& current_piece, static inline void leave(LineStringOut& current_piece,
@ -282,11 +289,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
segment_identifier& segment_id, segment_identifier& segment_id,
signed_size_type index, Point const& point, signed_size_type index, Point const& point,
Operation const& operation, Operation const& operation,
SideStrategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
OutputIterator& out) OutputIterator& out)
{ {
normal_action::enter(current_piece, linestring, segment_id, index, normal_action::enter(current_piece, linestring, segment_id, index,
point, operation, robust_policy, out); point, operation, strategy, robust_policy, out);
} }
template template
@ -456,7 +464,7 @@ public :
entered = true; entered = true;
action::enter(current_piece, linestring, current_segment_id, action::enter(current_piece, linestring, current_segment_id,
iit->seg_id.segment_index, it->point, *iit, iit->seg_id.segment_index, it->point, *iit,
robust_policy, strategy, robust_policy,
out); out);
} }
else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy)) else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
@ -466,7 +474,7 @@ public :
entered = false; entered = false;
action::leave(current_piece, linestring, current_segment_id, action::leave(current_piece, linestring, current_segment_id,
iit->seg_id.segment_index, it->point, *iit, iit->seg_id.segment_index, it->point, *iit,
robust_policy, strategy, robust_policy,
out); out);
} }
first = false; first = false;
@ -480,7 +488,7 @@ public :
>::apply(linestring, >::apply(linestring,
current_segment_id, current_segment_id,
static_cast<signed_size_type>(boost::size(linestring) - 1), static_cast<signed_size_type>(boost::size(linestring) - 1),
robust_policy, strategy, robust_policy,
current_piece); current_piece);
} }

View File

@ -2,12 +2,14 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0. // Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html // http://www.boost.org/users/license.html
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
@ -183,7 +185,8 @@ protected:
typename TurnIterator, typename TurnIterator,
typename TurnOperationIterator, typename TurnOperationIterator,
typename SegmentIdentifier, typename SegmentIdentifier,
typename OutputIterator typename OutputIterator,
typename SideStrategy
> >
static inline OutputIterator static inline OutputIterator
process_turn(TurnIterator it, process_turn(TurnIterator it,
@ -193,7 +196,8 @@ protected:
Linestring const& linestring, Linestring const& linestring,
LinestringOut& current_piece, LinestringOut& current_piece,
SegmentIdentifier& current_segment_id, SegmentIdentifier& current_segment_id,
OutputIterator oit) OutputIterator oit,
SideStrategy const& strategy)
{ {
// We don't rescale linear/linear // We don't rescale linear/linear
detail::no_rescale_policy robust_policy; detail::no_rescale_policy robust_policy;
@ -208,7 +212,7 @@ protected:
action::enter(current_piece, linestring, action::enter(current_piece, linestring,
current_segment_id, current_segment_id,
op_it->seg_id.segment_index, op_it->seg_id.segment_index,
it->point, *op_it, robust_policy, oit); it->point, *op_it, strategy, robust_policy, oit);
} }
++enter_count; ++enter_count;
} }
@ -223,7 +227,7 @@ protected:
action::leave(current_piece, linestring, action::leave(current_piece, linestring,
current_segment_id, current_segment_id,
op_it->seg_id.segment_index, op_it->seg_id.segment_index,
it->point, *op_it, robust_policy, oit); it->point, *op_it, strategy, robust_policy, oit);
} }
} }
else if ( FollowIsolatedPoints else if ( FollowIsolatedPoints
@ -249,14 +253,16 @@ protected:
template template
< <
typename SegmentIdentifier, typename SegmentIdentifier,
typename OutputIterator typename OutputIterator,
typename SideStrategy
> >
static inline OutputIterator static inline OutputIterator
process_end(bool entered, process_end(bool entered,
Linestring const& linestring, Linestring const& linestring,
SegmentIdentifier const& current_segment_id, SegmentIdentifier const& current_segment_id,
LinestringOut& current_piece, LinestringOut& current_piece,
OutputIterator oit) OutputIterator oit,
SideStrategy const& strategy)
{ {
if ( action::is_entered(entered) ) if ( action::is_entered(entered) )
{ {
@ -269,6 +275,7 @@ protected:
>::apply(linestring, >::apply(linestring,
current_segment_id, current_segment_id,
static_cast<signed_size_type>(boost::size(linestring) - 1), static_cast<signed_size_type>(boost::size(linestring) - 1),
strategy,
robust_policy, robust_policy,
current_piece); current_piece);
} }
@ -283,11 +290,12 @@ protected:
} }
public: public:
template <typename TurnIterator, typename OutputIterator> template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
static inline OutputIterator static inline OutputIterator
apply(Linestring const& linestring, Linear const&, apply(Linestring const& linestring, Linear const&,
TurnIterator first, TurnIterator beyond, TurnIterator first, TurnIterator beyond,
OutputIterator oit) OutputIterator oit,
SideStrategy const& strategy)
{ {
// Iterate through all intersection points (they are // Iterate through all intersection points (they are
// ordered along the each line) // ordered along the each line)
@ -304,7 +312,8 @@ public:
entered, enter_count, entered, enter_count,
linestring, linestring,
current_piece, current_segment_id, current_piece, current_segment_id,
oit); oit,
strategy);
} }
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) #if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
@ -318,7 +327,8 @@ public:
return process_end(entered, linestring, return process_end(entered, linestring,
current_segment_id, current_piece, current_segment_id, current_piece,
oit); oit,
strategy);
} }
}; };
@ -413,11 +423,12 @@ protected:
}; };
public: public:
template <typename TurnIterator, typename OutputIterator> template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
static inline OutputIterator static inline OutputIterator
apply(MultiLinestring const& multilinestring, Linear const& linear, apply(MultiLinestring const& multilinestring, Linear const& linear,
TurnIterator first, TurnIterator beyond, TurnIterator first, TurnIterator beyond,
OutputIterator oit) OutputIterator oit,
SideStrategy const& strategy)
{ {
BOOST_GEOMETRY_ASSERT( first != beyond ); BOOST_GEOMETRY_ASSERT( first != beyond );
@ -447,7 +458,7 @@ public:
has_other_multi_id(current_multi_id)); has_other_multi_id(current_multi_id));
oit = Base::apply(*(ls_first + current_multi_id), oit = Base::apply(*(ls_first + current_multi_id),
linear, per_ls_current, per_ls_next, oit); linear, per_ls_current, per_ls_next, oit, strategy);
signed_size_type next_multi_id = -1; signed_size_type next_multi_id = -1;
linestring_iterator ls_next = ls_beyond; linestring_iterator ls_next = ls_beyond;

View File

@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -31,20 +36,15 @@ namespace detail { namespace overlay
but we still need to know which comes first. but we still need to know which comes first.
Therefore, it is useful that using sides we are able to discover this. Therefore, it is useful that using sides we are able to discover this.
*/ */
template <typename Point1>
struct get_relative_order struct get_relative_order
{ {
typedef typename strategy::side::services::default_strategy template <typename Point, typename SideStrategy>
<
typename cs_tag<Point1>::type
>::type strategy;
template <typename Point>
static inline int value_via_product(Point const& ti, Point const& tj, static inline int value_via_product(Point const& ti, Point const& tj,
Point const& ui, Point const& uj, int factor) Point const& ui, Point const& uj, int factor,
SideStrategy const& strategy)
{ {
int const side_ti_u = strategy::apply(ti, tj, ui); int const side_ti_u = strategy.apply(ti, tj, ui);
int const side_tj_u = strategy::apply(ti, tj, uj); int const side_tj_u = strategy.apply(ti, tj, uj);
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER #ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
std::cout << (factor == 1 ? " r//s " : " s//r ") std::cout << (factor == 1 ? " r//s " : " s//r ")
@ -57,13 +57,15 @@ struct get_relative_order
} }
template <typename Point1, typename SideStrategy>
static inline int apply( static inline int apply(
Point1 const& pi, Point1 const& pj, Point1 const& pi, Point1 const& pj,
Point1 const& ri, Point1 const& rj, Point1 const& ri, Point1 const& rj,
Point1 const& si, Point1 const& sj) Point1 const& si, Point1 const& sj,
SideStrategy const& strategy)
{ {
int const side_ri_p = strategy::apply(pi, pj, ri); int const side_ri_p = strategy.apply(pi, pj, ri);
int const side_si_p = strategy::apply(pi, pj, si); int const side_si_p = strategy.apply(pi, pj, si);
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER #ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
int const side_rj_p = strategy::apply(pi, pj, rj); int const side_rj_p = strategy::apply(pi, pj, rj);
@ -72,10 +74,10 @@ struct get_relative_order
std::cout << " s//p: " << side_si_p << " / " << side_sj_p; std::cout << " s//p: " << side_si_p << " / " << side_sj_p;
#endif #endif
int value = value_via_product(si, sj, ri, rj, 1); int value = value_via_product(si, sj, ri, rj, 1, strategy);
if (value == 0) if (value == 0)
{ {
value = value_via_product(ri, rj, si, sj, -1); value = value_via_product(ri, rj, si, sj, -1, strategy);
} }
int const order = side_ri_p * side_ri_p * side_si_p * value; int const order = side_ri_p * side_ri_p * side_si_p * value;

View File

@ -233,7 +233,7 @@ public :
// section 2: [--------------] // section 2: [--------------]
// section 1: |----|---|---|---|---| // section 1: |----|---|---|---|---|
for (prev1 = it1++, next1++; for (prev1 = it1++, next1++;
it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy); it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec1.bounding_box, sec2.bounding_box, robust_policy);
++prev1, ++it1, ++index1, ++next1, ++ndi1) ++prev1, ++it1, ++index1, ++next1, ++ndi1)
{ {
ever_circling_iterator<range1_iterator> nd_next1( ever_circling_iterator<range1_iterator> nd_next1(
@ -251,7 +251,7 @@ public :
next2++; next2++;
for (prev2 = it2++, next2++; for (prev2 = it2++, next2++;
it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy); it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec2.bounding_box, sec1.bounding_box, robust_policy);
++prev2, ++it2, ++index2, ++next2, ++ndi2) ++prev2, ++it2, ++index2, ++next2, ++ndi2)
{ {
bool skip = same_source; bool skip = same_source;
@ -359,7 +359,7 @@ private :
// skips to the begin-point, we loose the index or have to recalculate it) // skips to the begin-point, we loose the index or have to recalculate it)
// So we mimic it here // So we mimic it here
template <typename Range, typename Section, typename Box, typename RobustPolicy> template <typename Range, typename Section, typename Box, typename RobustPolicy>
static inline void get_start_point_iterator(Section & section, static inline void get_start_point_iterator(Section const& section,
Range const& range, Range const& range,
typename boost::range_iterator<Range const>::type& it, typename boost::range_iterator<Range const>::type& it,
typename boost::range_iterator<Range const>::type& prev, typename boost::range_iterator<Range const>::type& prev,
@ -373,7 +373,7 @@ private :
// Mimic section-iterator: // Mimic section-iterator:
// Skip to point such that section interects other box // Skip to point such that section interects other box
prev = it++; prev = it++;
for(; it != end && detail::section::preceding<0>(dir, *it, other_bounding_box, robust_policy); for(; it != end && detail::section::preceding<0>(dir, *it, section.bounding_box, other_bounding_box, robust_policy);
prev = it++, index++, ndi++) prev = it++, index++, ndi++)
{} {}
// Go back one step because we want to start completely preceding // Go back one step because we want to start completely preceding

View File

@ -2,6 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -728,11 +733,13 @@ template
typename Turns, typename Turns,
typename Clusters, typename Clusters,
typename Geometry1, typename Geometry1,
typename Geometry2 typename Geometry2,
typename SideStrategy
> >
inline void gather_cluster_properties(Clusters& clusters, Turns& turns, inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
operation_type for_operation, operation_type for_operation,
Geometry1 const& geometry1, Geometry2 const& geometry2) Geometry1 const& geometry1, Geometry2 const& geometry2,
SideStrategy const& strategy)
{ {
typedef typename boost::range_value<Turns>::type turn_type; typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::point_type point_type; typedef typename turn_type::point_type point_type;
@ -742,7 +749,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
// right side // right side
typedef sort_by_side::side_sorter typedef sort_by_side::side_sorter
< <
Reverse1, Reverse2, OverlayType, point_type, std::less<int> Reverse1, Reverse2, OverlayType, point_type, SideStrategy, std::less<int>
> sbs_type; > sbs_type;
for (typename Clusters::iterator mit = clusters.begin(); for (typename Clusters::iterator mit = clusters.begin();
@ -755,7 +762,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
continue; continue;
} }
sbs_type sbs; sbs_type sbs(strategy);
point_type turn_point; // should be all the same for all turns in cluster point_type turn_point; // should be all the same for all turns in cluster
bool first = true; bool first = true;

View File

@ -2,6 +2,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -60,6 +65,7 @@ template
typename Indexed, typename Indexed,
typename Geometry1, typename Geometry2, typename Geometry1, typename Geometry2,
typename RobustPolicy, typename RobustPolicy,
typename SideStrategy,
bool Reverse1, bool Reverse2 bool Reverse1, bool Reverse2
> >
struct less_by_segment_ratio struct less_by_segment_ratio
@ -68,12 +74,14 @@ struct less_by_segment_ratio
, operation_type for_operation , operation_type for_operation
, Geometry1 const& geometry1 , Geometry1 const& geometry1
, Geometry2 const& geometry2 , Geometry2 const& geometry2
, RobustPolicy const& robust_policy) , RobustPolicy const& robust_policy
, SideStrategy const& strategy)
: m_turns(turns) : m_turns(turns)
, m_for_operation(for_operation) , m_for_operation(for_operation)
, m_geometry1(geometry1) , m_geometry1(geometry1)
, m_geometry2(geometry2) , m_geometry2(geometry2)
, m_robust_policy(robust_policy) , m_robust_policy(robust_policy)
, m_strategy(strategy)
{ {
} }
@ -84,6 +92,7 @@ private :
Geometry1 const& m_geometry1; Geometry1 const& m_geometry1;
Geometry2 const& m_geometry2; Geometry2 const& m_geometry2;
RobustPolicy const& m_robust_policy; RobustPolicy const& m_robust_policy;
SideStrategy const& m_strategy;
typedef typename geometry::point_type<Geometry1>::type point_type; typedef typename geometry::point_type<Geometry1>::type point_type;
@ -108,13 +117,8 @@ private :
*right.other_seg_id, *right.other_seg_id,
si, sj); si, sj);
typedef typename strategy::side::services::default_strategy int const side_rj_p = m_strategy.apply(pi, pj, rj);
< int const side_sj_p = m_strategy.apply(pi, pj, sj);
typename cs_tag<point_type>::type
>::type strategy;
int const side_rj_p = strategy::apply(pi, pj, rj);
int const side_sj_p = strategy::apply(pi, pj, sj);
// Put the one turning left (1; right == -1) as last // Put the one turning left (1; right == -1) as last
if (side_rj_p != side_sj_p) if (side_rj_p != side_sj_p)
@ -122,8 +126,8 @@ private :
return side_rj_p < side_sj_p; return side_rj_p < side_sj_p;
} }
int const side_sj_r = strategy::apply(ri, rj, sj); int const side_sj_r = m_strategy.apply(ri, rj, sj);
int const side_rj_s = strategy::apply(si, sj, rj); int const side_rj_s = m_strategy.apply(si, sj, rj);
// If they both turn left: the most left as last // If they both turn left: the most left as last
// If they both turn right: this is not relevant, but take also here most left // If they both turn right: this is not relevant, but take also here most left

View File

@ -194,13 +194,15 @@ protected:
typename Turns, typename Turns,
typename LinearGeometry1, typename LinearGeometry1,
typename LinearGeometry2, typename LinearGeometry2,
typename OutputIterator typename OutputIterator,
typename IntersectionStrategy
> >
static inline OutputIterator static inline OutputIterator
sort_and_follow_turns(Turns& turns, sort_and_follow_turns(Turns& turns,
LinearGeometry1 const& linear1, LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2, LinearGeometry2 const& linear2,
OutputIterator oit) OutputIterator oit,
IntersectionStrategy const& strategy)
{ {
// remove turns that have no added value // remove turns that have no added value
turns::filter_continue_turns turns::filter_continue_turns
@ -228,7 +230,7 @@ protected:
FollowIsolatedPoints, FollowIsolatedPoints,
!EnableFilterContinueTurns || OverlayType == overlay_intersection !EnableFilterContinueTurns || OverlayType == overlay_intersection
>::apply(linear1, linear2, boost::begin(turns), boost::end(turns), >::apply(linear1, linear2, boost::begin(turns), boost::end(turns),
oit); oit, strategy.get_side_strategy());
} }
public: public:
@ -277,7 +279,7 @@ public:
OverlayType, OverlayType,
EnableFollowIsolatedPoints EnableFollowIsolatedPoints
&& OverlayType == overlay_intersection && OverlayType == overlay_intersection
>(turns, linear1, linear2, oit); >(turns, linear1, linear2, oit, strategy);
} }
}; };

View File

@ -2,6 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -18,7 +23,6 @@
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp> #include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/direction_code.hpp> #include <boost/geometry/algorithms/detail/direction_code.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -106,17 +110,13 @@ struct less_false
} }
}; };
template <typename Point, typename LessOnSame, typename Compare> template <typename Point, typename SideStrategy, typename LessOnSame, typename Compare>
struct less_by_side struct less_by_side
{ {
typedef typename strategy::side::services::default_strategy less_by_side(const Point& p1, const Point& p2, SideStrategy const& strategy)
<
typename cs_tag<Point>::type
>::type side;
less_by_side(const Point& p1, const Point& p2)
: m_p1(p1) : m_p1(p1)
, m_p2(p2) , m_p2(p2)
, m_strategy(strategy)
{} {}
template <typename T> template <typename T>
@ -125,8 +125,8 @@ struct less_by_side
LessOnSame on_same; LessOnSame on_same;
Compare compare; Compare compare;
int const side_first = side::apply(m_p1, m_p2, first.point); int const side_first = m_strategy.apply(m_p1, m_p2, first.point);
int const side_second = side::apply(m_p1, m_p2, second.point); int const side_second = m_strategy.apply(m_p1, m_p2, second.point);
if (side_first == 0 && side_second == 0) if (side_first == 0 && side_second == 0)
{ {
@ -166,7 +166,7 @@ struct less_by_side
// They are both left, both right, and/or both collinear (with each other and/or with p1,p2) // They are both left, both right, and/or both collinear (with each other and/or with p1,p2)
// Check mutual side // Check mutual side
int const side_second_wrt_first = side::apply(m_p2, first.point, second.point); int const side_second_wrt_first = m_strategy.apply(m_p2, first.point, second.point);
if (side_second_wrt_first == 0) if (side_second_wrt_first == 0)
{ {
@ -184,6 +184,7 @@ struct less_by_side
private : private :
Point m_p1, m_p2; Point m_p1, m_p2;
SideStrategy const& m_strategy;
}; };
// Sorts vectors in counter clockwise order (by default) // Sorts vectors in counter clockwise order (by default)
@ -193,6 +194,7 @@ template
bool Reverse2, bool Reverse2,
overlay_type OverlayType, overlay_type OverlayType,
typename Point, typename Point,
typename SideStrategy,
typename Compare typename Compare
> >
struct side_sorter struct side_sorter
@ -223,9 +225,10 @@ private :
}; };
public : public :
side_sorter() side_sorter(SideStrategy const& strategy)
: m_origin_count(0) : m_origin_count(0)
, m_origin_segment_distance(0) , m_origin_segment_distance(0)
, m_strategy(strategy)
{} {}
template <typename Operation, typename Geometry1, typename Geometry2> template <typename Operation, typename Geometry1, typename Geometry2>
@ -309,8 +312,8 @@ public :
// to give colinear points // to give colinear points
// Sort by side and assign rank // Sort by side and assign rank
less_by_side<Point, less_by_index, Compare> less_unique(m_origin, turn_point); less_by_side<Point, SideStrategy, less_by_index, Compare> less_unique(m_origin, turn_point, m_strategy);
less_by_side<Point, less_false, Compare> less_non_unique(m_origin, turn_point); less_by_side<Point, SideStrategy, less_false, Compare> less_non_unique(m_origin, turn_point, m_strategy);
std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique); std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique);
@ -425,6 +428,7 @@ public :
Point m_origin; Point m_origin;
std::size_t m_origin_count; std::size_t m_origin_count;
int m_origin_segment_distance; int m_origin_segment_distance;
SideStrategy m_strategy;
private : private :

View File

@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -94,6 +99,7 @@ template
typename Turns, typename Turns,
typename Clusters, typename Clusters,
typename RobustPolicy, typename RobustPolicy,
typename SideStrategy,
typename Visitor typename Visitor
> >
struct traversal struct traversal
@ -108,17 +114,19 @@ struct traversal
typedef sort_by_side::side_sorter typedef sort_by_side::side_sorter
< <
Reverse1, Reverse2, OverlayType, Reverse1, Reverse2, OverlayType,
point_type, side_compare_type point_type, SideStrategy, side_compare_type
> sbs_type; > sbs_type;
inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2, inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2,
Turns& turns, Clusters const& clusters, Turns& turns, Clusters const& clusters,
RobustPolicy const& robust_policy, Visitor& visitor) RobustPolicy const& robust_policy, SideStrategy const& strategy,
Visitor& visitor)
: m_geometry1(geometry1) : m_geometry1(geometry1)
, m_geometry2(geometry2) , m_geometry2(geometry2)
, m_turns(turns) , m_turns(turns)
, m_clusters(clusters) , m_clusters(clusters)
, m_robust_policy(robust_policy) , m_robust_policy(robust_policy)
, m_strategy(strategy)
, m_visitor(visitor) , m_visitor(visitor)
{ {
} }
@ -579,7 +587,7 @@ struct traversal
cluster_info const& cinfo = mit->second; cluster_info const& cinfo = mit->second;
std::set<signed_size_type> const& ids = cinfo.turn_indices; std::set<signed_size_type> const& ids = cinfo.turn_indices;
sbs_type sbs; sbs_type sbs(m_strategy);
for (typename std::set<signed_size_type>::const_iterator sit = ids.begin(); for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();
sit != ids.end(); ++sit) sit != ids.end(); ++sit)
@ -625,7 +633,7 @@ struct traversal
turn_type const& current_turn, turn_type const& current_turn,
segment_identifier const& previous_seg_id) segment_identifier const& previous_seg_id)
{ {
sbs_type sbs; sbs_type sbs(m_strategy);
// Add this turn to the sort-by-side sorter // Add this turn to the sort-by-side sorter
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
@ -817,6 +825,7 @@ private :
Turns& m_turns; Turns& m_turns;
Clusters const& m_clusters; Clusters const& m_clusters;
RobustPolicy const& m_robust_policy; RobustPolicy const& m_robust_policy;
SideStrategy m_strategy;
Visitor& m_visitor; Visitor& m_visitor;
}; };

View File

@ -50,9 +50,13 @@ template
> >
struct traversal_ring_creator struct traversal_ring_creator
{ {
typedef traversal<Reverse1, Reverse2, OverlayType, typedef traversal
Geometry1, Geometry2, Turns, Clusters, RobustPolicy, Visitor> <
traversal_type; Reverse1, Reverse2, OverlayType,
Geometry1, Geometry2, Turns, Clusters,
RobustPolicy, typename IntersectionStrategy::side_strategy_type,
Visitor
> traversal_type;
typedef typename boost::range_value<Turns>::type turn_type; typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::turn_operation_type turn_operation_type; typedef typename turn_type::turn_operation_type turn_operation_type;
@ -65,7 +69,9 @@ struct traversal_ring_creator
Clusters const& clusters, Clusters const& clusters,
IntersectionStrategy const& intersection_strategy, IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy, Visitor& visitor) RobustPolicy const& robust_policy, Visitor& visitor)
: m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor) : m_trav(geometry1, geometry2, turns, clusters,
robust_policy, intersection_strategy.get_side_strategy(),
visitor)
, m_geometry1(geometry1) , m_geometry1(geometry1)
, m_geometry2(geometry2) , m_geometry2(geometry2)
, m_turns(turns) , m_turns(turns)
@ -106,12 +112,14 @@ struct traversal_ring_creator
{ {
geometry::copy_segments<Reverse1>(m_geometry1, geometry::copy_segments<Reverse1>(m_geometry1,
previous_op.seg_id, to_vertex_index, previous_op.seg_id, to_vertex_index,
m_intersection_strategy.get_side_strategy(),
m_robust_policy, current_ring); m_robust_policy, current_ring);
} }
else else
{ {
geometry::copy_segments<Reverse2>(m_geometry2, geometry::copy_segments<Reverse2>(m_geometry2,
previous_op.seg_id, to_vertex_index, previous_op.seg_id, to_vertex_index,
m_intersection_strategy.get_side_strategy(),
m_robust_policy, current_ring); m_robust_policy, current_ring);
} }
} }
@ -155,6 +163,7 @@ struct traversal_ring_creator
turn_type& current_turn = m_turns[turn_index]; turn_type& current_turn = m_turns[turn_index];
turn_operation_type& op = current_turn.operations[op_index]; turn_operation_type& op = current_turn.operations[op_index];
detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point, detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point,
m_intersection_strategy.get_side_strategy(),
m_robust_policy); m_robust_policy);
// Register the visit // Register the visit
@ -172,6 +181,7 @@ struct traversal_ring_creator
turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index]; turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index];
detail::overlay::append_no_dups_or_spikes(ring, start_turn.point, detail::overlay::append_no_dups_or_spikes(ring, start_turn.point,
m_intersection_strategy.get_side_strategy(),
m_robust_policy); m_robust_policy);
signed_size_type current_turn_index = start_turn_index; signed_size_type current_turn_index = start_turn_index;
@ -274,7 +284,9 @@ struct traversal_ring_creator
if (geometry::num_points(ring) >= min_num_points) if (geometry::num_points(ring) >= min_num_points)
{ {
clean_closing_dups_and_spikes(ring, m_robust_policy); clean_closing_dups_and_spikes(ring,
m_intersection_strategy.get_side_strategy(),
m_robust_policy);
rings.push_back(ring); rings.push_back(ring);
m_trav.finalize_visit_info(m_turn_info_map); m_trav.finalize_visit_info(m_turn_info_map);

View File

@ -5,10 +5,11 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015. // This file was modified by Oracle on 2015, 2017.
// Modifications copyright (c) 2015 Oracle and/or its affiliates. // Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -19,11 +20,13 @@
#include <boost/geometry/algorithms/detail/direction_code.hpp> #include <boost/geometry/algorithms/detail/direction_code.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp> #include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp> #include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp> #include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -32,6 +35,26 @@ namespace boost { namespace geometry
namespace detail namespace detail
{ {
template <typename Point1, typename Point2, typename Point3>
inline bool collinear_point_is_spike_or_equal(Point1 const& last_point,
Point2 const& segment_a,
Point3 const& segment_b)
{
// Check if segment is equal
int const sgn_x1 = sign_of_difference<0>(last_point, segment_b);
int const sgn_y1 = sign_of_difference<1>(last_point, segment_b);
if (sgn_x1 == 0 && sgn_y1 == 0)
{
return true;
}
// Check if segment moves forward
int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);
int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);
return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;
}
// Checks if a point ("last_point") causes a spike w.r.t. // Checks if a point ("last_point") causes a spike w.r.t.
// the specified two other points (segment_a, segment_b) // the specified two other points (segment_a, segment_b)
// //
@ -42,33 +65,29 @@ namespace detail
// So specify last point first, then (a,b) // So specify last point first, then (a,b)
// The segment's orientation does matter: if lp is to the right of b // The segment's orientation does matter: if lp is to the right of b
// no spike is reported // no spike is reported
template <typename Point1, typename Point2, typename Point3> template
static inline bool point_is_spike_or_equal(Point1 const& last_point, <
Point2 const& segment_a, typename Point1, typename Point2, typename Point3,
Point3 const& segment_b) typename SideStrategy
>
static inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back
Point2 const& segment_a, // next | back - 2
Point3 const& segment_b, // curr | back - 1 | spike's vertex
SideStrategy const& strategy)
{ {
typedef typename strategy::side::services::default_strategy int const side = strategy.apply(segment_a, segment_b, last_point);
<
typename cs_tag<Point1>::type
>::type side_strategy;
int const side = side_strategy::apply(last_point, segment_a, segment_b);
if (side == 0) if (side == 0)
{ {
// Last point is collinear w.r.t previous segment. // Last point is collinear w.r.t previous segment.
// Check if it is equal #ifdef BOOST_GEOMETRY_ENABLE_POINT_IS_SPIKE_OR_EQUAL_TEST
int const sgn_x1 = sign_of_difference<0>(last_point, segment_b); bool r1 = collinear_point_is_spike_or_equal(last_point, segment_a, segment_b);
int const sgn_y1 = sign_of_difference<1>(last_point, segment_b); bool r2 = direction_code(segment_a, segment_b, last_point) < 1;
if (sgn_x1 == 0 && sgn_y1 == 0) if (r1 != r2)
{ std::cout << "spike detection failure with: " << r1 << " " << r2 << std::endl;
return true; return r2;
} #else
return direction_code(segment_a, segment_b, last_point) < 1;
// Check if it moves forward #endif
int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);
int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);
return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;
} }
return false; return false;
} }
@ -78,14 +97,16 @@ template
typename Point1, typename Point1,
typename Point2, typename Point2,
typename Point3, typename Point3,
typename SideStrategy,
typename RobustPolicy typename RobustPolicy
> >
static inline bool point_is_spike_or_equal(Point1 const& last_point, static inline bool point_is_spike_or_equal(Point1 const& last_point,
Point2 const& segment_a, Point2 const& segment_a,
Point3 const& segment_b, Point3 const& segment_b,
SideStrategy const& strategy,
RobustPolicy const& robust_policy) RobustPolicy const& robust_policy)
{ {
if (point_is_spike_or_equal(last_point, segment_a, segment_b)) if (point_is_spike_or_equal(last_point, segment_a, segment_b, strategy))
{ {
return true; return true;
} }
@ -111,7 +132,8 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point,
( (
last_point_rob, last_point_rob,
segment_a_rob, segment_a_rob,
segment_b_rob segment_b_rob,
strategy
); );
} }

View File

@ -2,8 +2,8 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015. // This file was modified by Oracle on 2015, 2017.
// Modifications copyright (c) 2015, Oracle and/or its affiliates. // Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -27,6 +27,74 @@ namespace boost { namespace geometry
namespace detail { namespace section namespace detail { namespace section
{ {
template
<
std::size_t Dimension,
typename Geometry,
typename CastedCSTag = typename tag_cast
<
typename cs_tag<Geometry>::type,
spherical_tag
>::type
>
struct preceding_check
{
template <typename Point, typename Box>
static inline bool apply(int dir, Point const& point, Box const& /*point_box*/, Box const& other_box)
{
return (dir == 1 && get<Dimension>(point) < get<min_corner, Dimension>(other_box))
|| (dir == -1 && get<Dimension>(point) > get<max_corner, Dimension>(other_box));
}
};
template <typename Geometry>
struct preceding_check<0, Geometry, spherical_tag>
{
template <typename Point, typename Box>
static inline bool apply(int dir, Point const& point, Box const& point_box, Box const& other_box)
{
typedef typename select_coordinate_type
<
Point, Box
>::type calc_t;
typedef typename coordinate_system<Point>::type::units units_t;
calc_t const c0 = 0;
if (dir == 1)
{
calc_t const diff_min = math::longitude_distance_signed
<
units_t, calc_t
>(get<min_corner, 0>(other_box), get<0>(point));
calc_t const diff_min_min = math::longitude_distance_signed
<
units_t, calc_t
>(get<min_corner, 0>(other_box), get<min_corner, 0>(point_box));
return diff_min < c0 && diff_min_min <= c0 && diff_min_min <= diff_min;
}
else if (dir == -1)
{
calc_t const diff_max = math::longitude_distance_signed
<
units_t, calc_t
>(get<max_corner, 0>(other_box), get<0>(point));
calc_t const diff_max_max = math::longitude_distance_signed
<
units_t, calc_t
>(get<max_corner, 0>(other_box), get<max_corner, 0>(point_box));
return diff_max > c0 && diff_max_max >= c0 && diff_max <= diff_max_max;
}
return false;
}
};
template template
< <
std::size_t Dimension, std::size_t Dimension,
@ -34,14 +102,15 @@ template
typename RobustBox, typename RobustBox,
typename RobustPolicy typename RobustPolicy
> >
static inline bool preceding(int dir, Point const& point, static inline bool preceding(int dir,
RobustBox const& robust_box, Point const& point,
RobustPolicy const& robust_policy) RobustBox const& point_robust_box,
RobustBox const& other_robust_box,
RobustPolicy const& robust_policy)
{ {
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point; typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
geometry::recalculate(robust_point, point, robust_policy); geometry::recalculate(robust_point, point, robust_policy);
return (dir == 1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box)) return preceding_check<Dimension, Point>::apply(dir, robust_point, point_robust_box, other_robust_box);
|| (dir == -1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box));
} }
template template
@ -51,14 +120,13 @@ template
typename RobustBox, typename RobustBox,
typename RobustPolicy typename RobustPolicy
> >
static inline bool exceeding(int dir, Point const& point, static inline bool exceeding(int dir,
RobustBox const& robust_box, Point const& point,
RobustPolicy const& robust_policy) RobustBox const& point_robust_box,
RobustBox const& other_robust_box,
RobustPolicy const& robust_policy)
{ {
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point; return preceding<Dimension>(-dir, point, point_robust_box, other_robust_box, robust_policy);
geometry::recalculate(robust_point, point, robust_policy);
return (dir == 1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box))
|| (dir == -1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box));
} }

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2015. // This file was modified by Oracle on 2013, 2014, 2015, 2017.
// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. // Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -136,11 +136,21 @@ struct sections : std::vector<section<Box, DimensionCount> >
namespace detail { namespace sectionalize namespace detail { namespace sectionalize
{ {
// NOTE: This utility will NOT work for latitudes, dimension 1 in spherical
// and geographic coordinate system because in these coordinate systems
// e.g. a segment on northern hemisphere may go towards greater latitude
// and then towards lesser latitude.
template template
< <
typename Point,
typename DimensionVector, typename DimensionVector,
std::size_t Index, std::size_t Index,
std::size_t Count std::size_t Count,
typename CastedCSTag = typename tag_cast
<
typename cs_tag<Point>::type,
spherical_tag
>::type
> >
struct get_direction_loop struct get_direction_loop
{ {
@ -161,21 +171,67 @@ struct get_direction_loop
get_direction_loop get_direction_loop
< <
Point,
DimensionVector, DimensionVector,
Index + 1, Index + 1,
Count Count,
CastedCSTag
>::apply(seg, directions); >::apply(seg, directions);
} }
}; };
template <typename DimensionVector, std::size_t Count> template
struct get_direction_loop<DimensionVector, Count, Count> <
typename Point,
typename DimensionVector,
std::size_t Count
>
struct get_direction_loop<Point, DimensionVector, 0, Count, spherical_tag>
{
typedef typename boost::mpl::at_c<DimensionVector, 0>::type dimension;
template <typename Segment>
static inline void apply(Segment const& seg,
int directions[Count])
{
typedef typename coordinate_type<Segment>::type coordinate_type;
typedef typename coordinate_system<Point>::type::units units_t;
coordinate_type const diff = math::longitude_distance_signed
<
units_t, coordinate_type
>(geometry::get<0, 0>(seg),
geometry::get<1, 0>(seg));
coordinate_type zero = coordinate_type();
directions[0] = diff > zero ? 1 : diff < zero ? -1 : 0;
get_direction_loop
<
Point,
DimensionVector,
1,
Count,
spherical_tag
>::apply(seg, directions);
}
};
template
<
typename Point,
typename DimensionVector,
std::size_t Count,
typename CastedCSTag
>
struct get_direction_loop<Point, DimensionVector, Count, Count, CastedCSTag>
{ {
template <typename Segment> template <typename Segment>
static inline void apply(Segment const&, int [Count]) static inline void apply(Segment const&, int [Count])
{} {}
}; };
//! Copy one static array to another //! Copy one static array to another
template <typename T, std::size_t Index, std::size_t Count> template <typename T, std::size_t Index, std::size_t Count>
struct copy_loop struct copy_loop
@ -410,7 +466,7 @@ struct sectionalize_part
int direction_classes[dimension_count] = {0}; int direction_classes[dimension_count] = {0};
get_direction_loop get_direction_loop
< <
DimensionVector, 0, dimension_count Point, DimensionVector, 0, dimension_count
>::apply(robust_segment, direction_classes); >::apply(robust_segment, direction_classes);
// if "dir" == 0 for all point-dimensions, it is duplicate. // if "dir" == 0 for all point-dimensions, it is duplicate.
@ -929,9 +985,12 @@ inline void sectionalize(Geometry const& geometry,
typename cs_tag<Geometry>::type typename cs_tag<Geometry>::type
>::type envelope_strategy_type; >::type envelope_strategy_type;
sectionalize<Reverse, DimensionVector>(geometry, robust_policy, sections, boost::geometry::sectionalize
envelope_strategy_type(), <
source_index, max_count); Reverse, DimensionVector
>(geometry, robust_policy, sections,
envelope_strategy_type(),
source_index, max_count);
} }
}} // namespace boost::geometry }} // namespace boost::geometry

View File

@ -2,6 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -10,17 +15,23 @@
#define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP #define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp> #include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp> #include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp> #include <boost/geometry/views/detail/normalized_view.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -31,15 +42,9 @@ namespace detail { namespace is_convex
struct ring_is_convex struct ring_is_convex
{ {
template <typename Ring> template <typename Ring, typename SideStrategy>
static inline bool apply(Ring const& ring) static inline bool apply(Ring const& ring, SideStrategy const& strategy)
{ {
typedef typename geometry::point_type<Ring>::type point_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<point_type>::type
>::type side_strategy_type;
std::size_t n = boost::size(ring); std::size_t n = boost::size(ring);
if (boost::size(ring) < core_detail::closure::minimum_ring_size if (boost::size(ring) < core_detail::closure::minimum_ring_size
< <
@ -86,7 +91,7 @@ struct ring_is_convex
// iterator // iterator
for (std::size_t i = 0; i < n; i++) for (std::size_t i = 0; i < n; i++)
{ {
int const side = side_strategy_type::apply(*previous, *current, *next); int const side = strategy.apply(*previous, *current, *next);
if (side == 1) if (side == 1)
{ {
// Next is on the left side of clockwise ring: // Next is on the left side of clockwise ring:
@ -129,7 +134,8 @@ struct is_convex : not_implemented<Tag>
template <typename Box> template <typename Box>
struct is_convex<Box, box_tag> struct is_convex<Box, box_tag>
{ {
static inline bool apply(Box const& ) template <typename Strategy>
static inline bool apply(Box const& , Strategy const& )
{ {
// Any box is convex (TODO: consider spherical boxes) // Any box is convex (TODO: consider spherical boxes)
return true; return true;
@ -144,13 +150,71 @@ struct is_convex<Box, ring_tag> : detail::is_convex::ring_is_convex
} // namespace dispatch } // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH #endif // DOXYGEN_NO_DISPATCH
// TODO: variants namespace resolve_variant {
template <typename Geometry>
struct is_convex
{
template <typename Strategy>
static bool apply(Geometry const& geometry, Strategy const& strategy)
{
concepts::check<Geometry>();
return dispatch::is_convex<Geometry>::apply(geometry, strategy);
}
static bool apply(Geometry const& geometry, geometry::default_strategy const&)
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type side_strategy;
return apply(geometry, side_strategy());
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_convex<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy) : m_strategy(strategy) {}
template <typename Geometry>
bool operator()(Geometry const& geometry) const
{
return is_convex<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
}
};
} // namespace resolve_variant
// TODO: documentation / qbk // TODO: documentation / qbk
template<typename Geometry> template<typename Geometry>
inline bool is_convex(Geometry const& geometry) inline bool is_convex(Geometry const& geometry)
{ {
return dispatch::is_convex<Geometry>::apply(geometry); return resolve_variant::is_convex
<
Geometry
>::apply(geometry, geometry::default_strategy());
}
// TODO: documentation / qbk
template<typename Geometry, typename Strategy>
inline bool is_convex(Geometry const& geometry, Strategy const& strategy)
{
return resolve_variant::is_convex<Geometry>::apply(geometry, strategy);
} }

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK. // Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014. // This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014 Oracle and/or its affiliates. // Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -33,6 +33,7 @@
#include <boost/geometry/algorithms/detail/extreme_points.hpp> #include <boost/geometry/algorithms/detail/extreme_points.hpp>
#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp> #include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
@ -241,8 +242,9 @@ inline void replace_extremes_for_self_tangencies(Extremes& extremes, Intruders&
extremes = triangle; extremes = triangle;
} }
template <int Dimension, typename Geometry, typename Point> template <int Dimension, typename Geometry, typename Point, typename SideStrategy>
inline bool calculate_point_on_surface(Geometry const& geometry, Point& point) inline bool calculate_point_on_surface(Geometry const& geometry, Point& point,
SideStrategy const& strategy)
{ {
typedef typename geometry::point_type<Geometry>::type point_type; typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename geometry::coordinate_type<Geometry>::type coordinate_type; typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
@ -250,7 +252,7 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
typedef std::vector<std::vector<point_type> > intruders_type; typedef std::vector<std::vector<point_type> > intruders_type;
intruders_type intruders; intruders_type intruders;
geometry::extreme_points<Dimension>(geometry, extremes, intruders); geometry::extreme_points<Dimension>(geometry, extremes, intruders, strategy);
if (extremes.size() < 3) if (extremes.size() < 3)
{ {
@ -291,21 +293,57 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
\tparam Geometry geometry type. This also defines the type of the output point \tparam Geometry geometry type. This also defines the type of the output point
\param geometry Geometry to take point from \param geometry Geometry to take point from
\param point Point to assign \param point Point to assign
\param strategy side strategy
*/ */
template <typename Geometry, typename Point> template <typename Geometry, typename Point, typename SideStrategy>
inline void point_on_surface(Geometry const& geometry, Point & point) inline void point_on_surface(Geometry const& geometry, Point & point,
SideStrategy const& strategy)
{ {
concepts::check<Point>(); concepts::check<Point>();
concepts::check<Geometry const>(); concepts::check<Geometry const>();
// First try in Y-direction (which should always succeed for valid polygons) // First try in Y-direction (which should always succeed for valid polygons)
if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point)) if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point, strategy))
{ {
// For invalid polygons, we might try X-direction // For invalid polygons, we might try X-direction
detail::point_on_surface::calculate_point_on_surface<0>(geometry, point); detail::point_on_surface::calculate_point_on_surface<0>(geometry, point, strategy);
} }
} }
/*!
\brief Assigns a Point guaranteed to lie on the surface of the Geometry
\tparam Geometry geometry type. This also defines the type of the output point
\param geometry Geometry to take point from
\param point Point to assign
*/
template <typename Geometry, typename Point>
inline void point_on_surface(Geometry const& geometry, Point & point)
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type strategy_type;
point_on_surface(geometry, point, strategy_type());
}
/*!
\brief Returns point guaranteed to lie on the surface of the Geometry
\tparam Geometry geometry type. This also defines the type of the output point
\param geometry Geometry to take point from
\param strategy side strategy
\return The Point guaranteed to lie on the surface of the Geometry
*/
template<typename Geometry, typename SideStrategy>
inline typename geometry::point_type<Geometry>::type
return_point_on_surface(Geometry const& geometry, SideStrategy const& strategy)
{
typename geometry::point_type<Geometry>::type result;
geometry::point_on_surface(geometry, result, strategy);
return result;
}
/*! /*!
\brief Returns point guaranteed to lie on the surface of the Geometry \brief Returns point guaranteed to lie on the surface of the Geometry
\tparam Geometry geometry type. This also defines the type of the output point \tparam Geometry geometry type. This also defines the type of the output point

View File

@ -5,6 +5,11 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK. // Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -34,6 +39,8 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp> #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/clear.hpp> #include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/condition.hpp>
@ -59,20 +66,13 @@ namespace detail { namespace remove_spikes
{ {
template <typename Range>
struct range_remove_spikes struct range_remove_spikes
{ {
typedef typename strategy::side::services::default_strategy template <typename Range, typename SideStrategy>
< static inline void apply(Range& range, SideStrategy const& strategy)
typename cs_tag<Range>::type
>::type side_strategy;
typedef typename coordinate_type<Range>::type coordinate_type;
typedef typename point_type<Range>::type point_type;
static inline void apply(Range& range)
{ {
typedef typename point_type<Range>::type point_type;
std::size_t n = boost::size(range); std::size_t n = boost::size(range);
std::size_t const min_num_points = core_detail::closure::minimum_ring_size std::size_t const min_num_points = core_detail::closure::minimum_ring_size
< <
@ -91,7 +91,10 @@ struct range_remove_spikes
cleaned.push_back(*it); cleaned.push_back(*it);
while(cleaned.size() >= 3 while(cleaned.size() >= 3
&& detail::point_is_spike_or_equal(cleaned.back(), *(cleaned.end() - 3), *(cleaned.end() - 2))) && detail::point_is_spike_or_equal(cleaned.back(),
*(cleaned.end() - 3),
*(cleaned.end() - 2),
strategy))
{ {
// Remove pen-ultimate point causing the spike (or which was equal) // Remove pen-ultimate point causing the spike (or which was equal)
cleaned.erase(cleaned.end() - 2); cleaned.erase(cleaned.end() - 2);
@ -110,13 +113,21 @@ struct range_remove_spikes
found = false; found = false;
// Check for spike in first point // Check for spike in first point
int const penultimate = 2; int const penultimate = 2;
while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(cleaned.front(), *(cleaned.end() - penultimate), cleaned.back())) while(cleaned.size() >= 3
&& detail::point_is_spike_or_equal(cleaned.front(),
*(cleaned.end() - penultimate),
cleaned.back(),
strategy))
{ {
cleaned.pop_back(); cleaned.pop_back();
found = true; found = true;
} }
// Check for spike in second point // Check for spike in second point
while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(*(cleaned.begin() + 1), cleaned.back(), cleaned.front())) while(cleaned.size() >= 3
&& detail::point_is_spike_or_equal(*(cleaned.begin() + 1),
cleaned.back(),
cleaned.front(),
strategy))
{ {
cleaned.pop_front(); cleaned.pop_front();
found = true; found = true;
@ -144,15 +155,13 @@ struct range_remove_spikes
}; };
template <typename Polygon>
struct polygon_remove_spikes struct polygon_remove_spikes
{ {
static inline void apply(Polygon& polygon) template <typename Polygon, typename SideStrategy>
static inline void apply(Polygon& polygon, SideStrategy const& strategy)
{ {
typedef typename geometry::ring_type<Polygon>::type ring_type; typedef range_remove_spikes per_range;
per_range::apply(exterior_ring(polygon), strategy);
typedef range_remove_spikes<ring_type> per_range;
per_range::apply(exterior_ring(polygon));
typename interior_return_type<Polygon>::type typename interior_return_type<Polygon>::type
rings = interior_rings(polygon); rings = interior_rings(polygon);
@ -160,23 +169,24 @@ struct polygon_remove_spikes
for (typename detail::interior_iterator<Polygon>::type for (typename detail::interior_iterator<Polygon>::type
it = boost::begin(rings); it != boost::end(rings); ++it) it = boost::begin(rings); it != boost::end(rings); ++it)
{ {
per_range::apply(*it); per_range::apply(*it, strategy);
} }
} }
}; };
template <typename MultiGeometry, typename SingleVersion> template <typename SingleVersion>
struct multi_remove_spikes struct multi_remove_spikes
{ {
static inline void apply(MultiGeometry& multi) template <typename MultiGeometry, typename SideStrategy>
static inline void apply(MultiGeometry& multi, SideStrategy const& strategy)
{ {
for (typename boost::range_iterator<MultiGeometry>::type for (typename boost::range_iterator<MultiGeometry>::type
it = boost::begin(multi); it = boost::begin(multi);
it != boost::end(multi); it != boost::end(multi);
++it) ++it)
{ {
SingleVersion::apply(*it); SingleVersion::apply(*it, strategy);
} }
} }
}; };
@ -199,21 +209,22 @@ template
> >
struct remove_spikes struct remove_spikes
{ {
static inline void apply(Geometry&) template <typename SideStrategy>
static inline void apply(Geometry&, SideStrategy const&)
{} {}
}; };
template <typename Ring> template <typename Ring>
struct remove_spikes<Ring, ring_tag> struct remove_spikes<Ring, ring_tag>
: detail::remove_spikes::range_remove_spikes<Ring> : detail::remove_spikes::range_remove_spikes
{}; {};
template <typename Polygon> template <typename Polygon>
struct remove_spikes<Polygon, polygon_tag> struct remove_spikes<Polygon, polygon_tag>
: detail::remove_spikes::polygon_remove_spikes<Polygon> : detail::remove_spikes::polygon_remove_spikes
{}; {};
@ -221,11 +232,7 @@ template <typename MultiPolygon>
struct remove_spikes<MultiPolygon, multi_polygon_tag> struct remove_spikes<MultiPolygon, multi_polygon_tag>
: detail::remove_spikes::multi_remove_spikes : detail::remove_spikes::multi_remove_spikes
< <
MultiPolygon,
detail::remove_spikes::polygon_remove_spikes detail::remove_spikes::polygon_remove_spikes
<
typename boost::range_value<MultiPolygon>::type
>
> >
{}; {};
@ -239,28 +246,46 @@ namespace resolve_variant {
template <typename Geometry> template <typename Geometry>
struct remove_spikes struct remove_spikes
{ {
static void apply(Geometry& geometry) template <typename Strategy>
static void apply(Geometry& geometry, Strategy const& strategy)
{ {
concepts::check<Geometry>(); concepts::check<Geometry>();
dispatch::remove_spikes<Geometry>::apply(geometry); dispatch::remove_spikes<Geometry>::apply(geometry, strategy);
}
static void apply(Geometry& geometry, geometry::default_strategy const&)
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type side_strategy;
apply(geometry, side_strategy());
} }
}; };
template <BOOST_VARIANT_ENUM_PARAMS(typename T)> template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{ {
template <typename Strategy>
struct visitor: boost::static_visitor<void> struct visitor: boost::static_visitor<void>
{ {
Strategy const& m_strategy;
visitor(Strategy const& strategy) : m_strategy(strategy) {}
template <typename Geometry> template <typename Geometry>
void operator()(Geometry& geometry) const void operator()(Geometry& geometry) const
{ {
remove_spikes<Geometry>::apply(geometry); remove_spikes<Geometry>::apply(geometry, m_strategy);
} }
}; };
static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry) template <typename Strategy>
static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry,
Strategy const& strategy)
{ {
boost::apply_visitor(visitor(), geometry); boost::apply_visitor(visitor<Strategy>(strategy), geometry);
} }
}; };
@ -275,7 +300,20 @@ struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry> template <typename Geometry>
inline void remove_spikes(Geometry& geometry) inline void remove_spikes(Geometry& geometry)
{ {
resolve_variant::remove_spikes<Geometry>::apply(geometry); resolve_variant::remove_spikes<Geometry>::apply(geometry, geometry::default_strategy());
}
/*!
\ingroup remove_spikes
\tparam Geometry geometry type
\tparam Strategy side strategy type
\param geometry the geometry to make remove_spikes
\param strategy the side strategy used by the algorithm
*/
template <typename Geometry, typename Strategy>
inline void remove_spikes(Geometry& geometry, Strategy const& strategy)
{
resolve_variant::remove_spikes<Geometry>::apply(geometry, strategy);
} }

View File

@ -83,7 +83,7 @@ protected :
CT const m_e2; // squared eccentricity CT const m_e2; // squared eccentricity
CT const m_ep2; // squared second eccentricity CT const m_ep2; // squared second eccentricity
CT const m_ep; // second eccentricity CT const m_ep; // second eccentricity
CT const m_c2; // authalic radius CT const m_c2; // squared authalic radius
inline spheroid_constants(Spheroid const& spheroid) inline spheroid_constants(Spheroid const& spheroid)
: m_spheroid(spheroid) : m_spheroid(spheroid)
@ -92,12 +92,27 @@ protected :
* (CT(2.0) - CT(formula::flattening<CT>(spheroid)))) * (CT(2.0) - CT(formula::flattening<CT>(spheroid))))
, m_ep2(m_e2 / (CT(1.0) - m_e2)) , m_ep2(m_e2 / (CT(1.0) - m_e2))
, m_ep(math::sqrt(m_ep2)) , m_ep(math::sqrt(m_ep2))
, m_c2((m_a2 / CT(2.0)) + , m_c2(authalic_radius(spheroid, m_a2, m_e2))
((math::sqr(get_radius<2>(spheroid)) * boost::math::atanh(math::sqrt(m_e2)))
/ (CT(2.0) * math::sqrt(m_e2))))
{} {}
}; };
static inline CT authalic_radius(Spheroid const& sph, CT const& a2, CT const& e2)
{
CT const c0 = 0;
if (math::equals(e2, c0))
{
return a2;
}
CT const sqrt_e2 = math::sqrt(e2);
CT const c2 = 2;
return (a2 / c2) +
((math::sqr(get_radius<2>(sph)) * boost::math::atanh(sqrt_e2))
/ (c2 * sqrt_e2));
}
struct area_sums struct area_sums
{ {
CT m_excess_sum; CT m_excess_sum;

View File

@ -4,7 +4,7 @@
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France. # Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK. # Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
# #
# This file was modified by Oracle on 2014, 2015, 2016,2017. # This file was modified by Oracle on 2014, 2015, 2016, 2017.
# Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. # Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
# #
# Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle # Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
@ -33,8 +33,10 @@ test-suite boost-geometry-algorithms
[ run is_convex.cpp : : : : algorithms_is_convex ] [ run is_convex.cpp : : : : algorithms_is_convex ]
[ run is_empty.cpp : : : : algorithms_is_empty ] [ run is_empty.cpp : : : : algorithms_is_empty ]
[ run is_simple.cpp : : : : algorithms_is_simple ] [ run is_simple.cpp : : : : algorithms_is_simple ]
[ run is_simple_geo.cpp : : : : algorithms_is_simple_geo ]
[ run is_valid.cpp : : : : algorithms_is_valid ] [ run is_valid.cpp : : : : algorithms_is_valid ]
[ run is_valid_failure.cpp : : : : algorithms_is_valid_failure ] [ run is_valid_failure.cpp : : : : algorithms_is_valid_failure ]
[ run is_valid_geo.cpp : : : : algorithms_is_valid_geo ]
[ run make.cpp : : : : algorithms_make ] [ run make.cpp : : : : algorithms_make ]
[ run maximum_gap.cpp : : : : algorithms_maximum_gap ] [ run maximum_gap.cpp : : : : algorithms_maximum_gap ]
[ run num_geometries.cpp : : : : algorithms_num_geometries ] [ run num_geometries.cpp : : : : algorithms_num_geometries ]

View File

@ -389,6 +389,21 @@ void test_spherical_geo()
// for select geography::STGeomFromText('POLYGON((4.892 52.373,4.23 52.08, // for select geography::STGeomFromText('POLYGON((4.892 52.373,4.23 52.08,
// 4.479 51.930,5.119 52.093,4.892 52.373))',4326).STArea()/1000000.0 // 4.479 51.930,5.119 52.093,4.892 52.373))',4326).STArea()/1000000.0
} }
{
bg::model::polygon<pt, false> geometry_sph;
std::string wkt = "POLYGON((0 0, 5 0, 5 5, 0 5, 0 0))";
bg::read_wkt(wkt, geometry_sph);
area = bg::area(geometry_sph, bg::strategy::area::spherical<pt>(6371228.0));
BOOST_CHECK_CLOSE(area, 308932296103.83051, 0.0001);
bg::model::polygon<pt_geo, false> geometry_geo;
bg::read_wkt(wkt, geometry_geo);
area = bg::area(geometry_geo, bg::strategy::area::geographic<pt_geo>(bg::srs::spheroid<double>(6371228.0, 6371228.0)));
BOOST_CHECK_CLOSE(area, 308932296103.82574, 0.001);
}
} }
int test_main(int, char* []) int test_main(int, char* [])

View File

@ -24,6 +24,8 @@ static std::string const grid_a = "MULTIPOINT(5 0,6 0,7 0, 5 1,7 1, 0 13,8 13)
static std::string const mysql_report_2015_02_25_1 = "MULTIPOINT(-9 19,9 -6,-4 4,16 -14,-3 16,14 9)"; static std::string const mysql_report_2015_02_25_1 = "MULTIPOINT(-9 19,9 -6,-4 4,16 -14,-3 16,14 9)";
static std::string const mysql_report_2015_02_25_2 = "MULTIPOINT(-2 11,-15 3,6 4,-14 0,20 -7,-17 -1)"; static std::string const mysql_report_2015_02_25_2 = "MULTIPOINT(-2 11,-15 3,6 4,-14 0,20 -7,-17 -1)";
static std::string const mysql_report_3 = "MULTIPOINT(0 0,0 0,0 0,0 0,0 0)";
template <bool Clockwise, typename P> template <bool Clockwise, typename P>
void test_all() void test_all()
{ {
@ -78,6 +80,18 @@ void test_all()
mysql_report_2015_02_25_1, join, end_flat, mysql_report_2015_02_25_1, join, end_flat,
distance_strategy(6051788), side_strategy, distance_strategy(6051788), side_strategy,
bg::strategy::buffer::point_circle(800), 115057490003226.125, 1.0); bg::strategy::buffer::point_circle(800), 115057490003226.125, 1.0);
{
multi_point_type g;
bg::read_wkt(mysql_report_3, g);
test_buffer<polygon>("mysql_report_3", g,
bg::strategy::buffer::join_round(36),
bg::strategy::buffer::end_round(36),
distance_strategy(1),
side_strategy,
bg::strategy::buffer::point_circle(36),
true, 1, 0, 3.12566719800474635, 1.0, NULL);
}
} }
template <typename P> template <typename P>

View File

@ -13,36 +13,7 @@
#define BOOST_TEST_MODULE test_is_simple #define BOOST_TEST_MODULE test_is_simple
#endif #endif
#include <iostream> #include "test_is_simple.hpp"
#include <string>
#include <boost/assert.hpp>
#include <boost/variant/variant.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/multi_point.hpp>
#include <boost/geometry/geometries/multi_linestring.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
#include <boost/geometry/algorithms/is_simple.hpp>
#include <from_wkt.hpp>
#ifdef BOOST_GEOMETRY_TEST_DEBUG
#include "pretty_print_geometry.hpp"
#endif
namespace bg = ::boost::geometry; namespace bg = ::boost::geometry;
@ -61,71 +32,6 @@ typedef bg::model::multi_polygon<open_ccw_polygon_type> multi_polygon_type;
typedef bg::model::box<point_type> box_type; typedef bg::model::box<point_type> box_type;
//----------------------------------------------------------------------------
template <typename CSTag, typename Geometry>
void test_simple(Geometry const& geometry, bool expected_result,
bool check_validity = true)
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "=======" << std::endl;
#endif
bool simple = bg::is_simple(geometry);
BOOST_ASSERT( ! check_validity || bg::is_valid(geometry) );
BOOST_CHECK_MESSAGE( simple == expected_result,
"Expected: " << expected_result
<< " detected: " << simple
<< " wkt: " << bg::wkt(geometry) );
typedef typename bg::strategy::intersection::services::default_strategy
<
CSTag
>::type strategy_type;
bool simple_s = bg::is_simple(geometry, strategy_type());
BOOST_CHECK_EQUAL(simple, simple_s);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "Geometry: ";
pretty_print_geometry<Geometry>::apply(std::cout, geometry);
std::cout << std::endl;
std::cout << std::boolalpha;
std::cout << "is simple: " << simple << std::endl;
std::cout << "expected result: " << expected_result << std::endl;
std::cout << "=======" << std::endl;
std::cout << std::endl << std::endl;
std::cout << std::noboolalpha;
#endif
}
template <typename Geometry>
void test_simple(Geometry const& geometry,
bool expected_result,
bool check_validity = true)
{
typedef typename bg::cs_tag<Geometry>::type cs_tag;
test_simple<cs_tag>(geometry, expected_result, check_validity);
}
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
void test_simple(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& variant_geometry,
bool expected_result,
bool check_validity = true)
{
typedef typename bg::cs_tag<T0>::type cs_tag;
test_simple<cs_tag>(variant_geometry, expected_result, check_validity);
}
//----------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE( test_is_simple_point ) BOOST_AUTO_TEST_CASE( test_is_simple_point )
{ {
#ifdef BOOST_GEOMETRY_TEST_DEBUG #ifdef BOOST_GEOMETRY_TEST_DEBUG

View File

@ -0,0 +1,59 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_is_simple_geo
#endif
#include "test_is_simple.hpp"
typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > point_type;
typedef bg::model::segment<point_type> segment_type;
typedef bg::model::linestring<point_type> linestring_type;
typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
// ccw open and closed polygons
typedef bg::model::polygon<point_type,false,false> open_ccw_polygon_type;
typedef bg::model::polygon<point_type,false,true> closed_ccw_polygon_type;
// multi-geometries
typedef bg::model::multi_point<point_type> multi_point_type;
typedef bg::model::multi_polygon<open_ccw_polygon_type> multi_polygon_type;
// box
typedef bg::model::box<point_type> box_type;
BOOST_AUTO_TEST_CASE( test_is_simple_geo_linestring )
{
typedef linestring_type G;
bg::strategy::intersection::geographic_segments<> s;
test_simple_s(from_wkt<G>("LINESTRING(0 0, -90 0, 90 0)"), s, true);
test_simple_s(from_wkt<G>("LINESTRING(0 90, -90 0, 90 0)"), s, false);
test_simple_s(from_wkt<G>("LINESTRING(0 90, -90 50, 90 0)"), s, false);
test_simple_s(from_wkt<G>("LINESTRING(0 90, -90 -50, 90 0)"), s, true);
test_simple_s(from_wkt<G>("LINESTRING(35 0, 110 36, 159 0, 82 30)"), s, false);
test_simple_s(from_wkt<G>("LINESTRING(135 0, -150 36, -101 0, -178 30)"), s, false);
test_simple_s(from_wkt<G>("LINESTRING(45 0, 120 36, 169 0, 92 30)"), s, false);
test_simple_s(from_wkt<G>("LINESTRING(179 0, -179 1, -179 0, 179 1)"), s, false);
}
BOOST_AUTO_TEST_CASE( test_is_simple_geo_multilinestring )
{
typedef multi_linestring_type G;
bg::strategy::intersection::geographic_segments<> s;
test_simple_s(from_wkt<G>("MULTILINESTRING((35 0, 110 36),(159 0, 82 30))"), s, false);
test_simple_s(from_wkt<G>("MULTILINESTRING((135 0, -150 36),(-101 0, -178 30))"), s, false);
test_simple_s(from_wkt<G>("MULTILINESTRING((45 0, 120 36),(169 0, 92 30))"), s, false);
test_simple_s(from_wkt<G>("MULTILINESTRING((179 0, -179 1),(-179 0, 179 1))"), s, false);
}

View File

@ -0,0 +1,38 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_is_valid_geo
#endif
#include <limits>
#include <iostream>
#include <boost/test/included/unit_test.hpp>
#include "test_is_valid.hpp"
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/reverse.hpp>
BOOST_AUTO_TEST_CASE( test_is_valid_geo_polygon )
{
typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > pt;
typedef bg::model::polygon<pt, false> G;
typedef validity_tester_geo_areal<false> tester;
typedef test_valid<tester, G> test;
test::apply("p01", "POLYGON((-1 -1, 1 -1, 1 1, -1 1, -1 -1),(-0.5 -0.5, -0.5 0.5, 0.0 0.0, -0.5 -0.5),(0.0 0.0, 0.5 0.5, 0.5 -0.5, 0.0 0.0))", true);
}

View File

@ -31,6 +31,9 @@
# include <boost/geometry/io/svg/svg_mapper.hpp> # include <boost/geometry/io/svg/svg_mapper.hpp>
#endif #endif
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
template <typename P, typename T> template <typename P, typename T>
void test_with_point(std::string const& /*caseid*/, void test_with_point(std::string const& /*caseid*/,
@ -46,7 +49,12 @@ void test_with_point(std::string const& /*caseid*/,
P si = bg::make<P>(si_x, si_y); P si = bg::make<P>(si_x, si_y);
P sj = bg::make<P>(sj_x, sj_y); P sj = bg::make<P>(sj_x, sj_y);
int order = bg::detail::overlay::get_relative_order<P>::apply(pi, pj, ri, rj, si, sj); typedef typename bg::strategy::side::services::default_strategy
<
typename bg::cs_tag<P>::type
>::type strategy_type;
int order = bg::detail::overlay::get_relative_order::apply(pi, pj, ri, rj, si, sj, strategy_type());
BOOST_CHECK_EQUAL(order, expected_order); BOOST_CHECK_EQUAL(order, expected_order);

View File

@ -49,12 +49,14 @@ template
typename Turns, typename Turns,
typename Clusters, typename Clusters,
typename Geometry1, typename Geometry1,
typename Geometry2 typename Geometry2,
typename SideStrategy
> >
std::vector<std::size_t> test_gather_cluster_properties(std::string const& case_id, std::vector<std::size_t> test_gather_cluster_properties(std::string const& case_id,
Clusters& clusters, Turns& turns, Clusters& clusters, Turns& turns,
bg::detail::overlay::operation_type for_operation, bg::detail::overlay::operation_type for_operation,
Geometry1 const& geometry1, Geometry2 const& geometry2) Geometry1 const& geometry1, Geometry2 const& geometry2,
SideStrategy const& strategy)
{ {
using namespace boost::geometry; using namespace boost::geometry;
using namespace boost::geometry::detail::overlay; using namespace boost::geometry::detail::overlay;
@ -69,7 +71,7 @@ std::vector<std::size_t> test_gather_cluster_properties(std::string const& case_
// right side // right side
typedef sort_by_side::side_sorter typedef sort_by_side::side_sorter
< <
Reverse1, Reverse2, OverlayType, point_type, std::less<int> Reverse1, Reverse2, OverlayType, point_type, SideStrategy, std::less<int>
> sbs_type; > sbs_type;
for (typename Clusters::iterator mit = clusters.begin(); for (typename Clusters::iterator mit = clusters.begin();
@ -82,7 +84,7 @@ std::vector<std::size_t> test_gather_cluster_properties(std::string const& case_
return result; return result;
} }
sbs_type sbs; sbs_type sbs(strategy);
point_type turn_point; // should be all the same for all turns in cluster point_type turn_point; // should be all the same for all turns in cluster
bool first = true; bool first = true;
@ -165,7 +167,7 @@ std::vector<std::size_t> apply_overlay(std::string const& case_id,
// Gather cluster properties, with test option // Gather cluster properties, with test option
return test_gather_cluster_properties<Reverse1, Reverse2, OverlayType>(case_id, return test_gather_cluster_properties<Reverse1, Reverse2, OverlayType>(case_id,
clusters, turns, bg::detail::overlay::operation_from_overlay<OverlayType>::value, clusters, turns, bg::detail::overlay::operation_from_overlay<OverlayType>::value,
geometry1, geometry2); geometry1, geometry2, strategy.get_side_strategy());
} }

View File

@ -89,13 +89,14 @@ std::vector<std::size_t> apply_get_turns(std::string const& case_id,
// Define sorter, sorting counter-clockwise such that polygons are on the // Define sorter, sorting counter-clockwise such that polygons are on the
// right side // right side
typedef typename Strategy::side_strategy_type side_strategy;
typedef bg::detail::overlay::sort_by_side::side_sorter typedef bg::detail::overlay::sort_by_side::side_sorter
< <
false, false, overlay_union, false, false, overlay_union,
point_type, std::less<int> point_type, side_strategy, std::less<int>
> sbs_type; > sbs_type;
sbs_type sbs; sbs_type sbs(strategy.get_side_strategy());
std::cout << "Case: " << case_id << std::endl; std::cout << "Case: " << case_id << std::endl;
@ -187,7 +188,7 @@ std::vector<std::size_t> apply_get_turns(std::string const& case_id,
} }
else else
{ {
BOOST_CHECK_MESSAGE(right_count[rank] == ranked_point.count_right, BOOST_CHECK_MESSAGE(right_count[rank] == int(ranked_point.count_right),
" caseid=" << case_id " caseid=" << case_id
<< " ranks: conflict in right_count=" << ranked_point.count_right << " ranks: conflict in right_count=" << ranked_point.count_right
<< " vs " << right_count[rank]); << " vs " << right_count[rank]);

View File

@ -398,9 +398,9 @@ void test_areal()
// Robustness issues, followed out buffer-robustness-tests, test them also reverse // Robustness issues, followed out buffer-robustness-tests, test them also reverse
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<Polygon, Polygon, Polygon>("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], test_one<Polygon, Polygon, Polygon>("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1],
1, 0, if_typed<ct, double>(18, 23), 4.60853); 1, 0, 23, 4.60853);
test_one<Polygon, Polygon, Polygon>("buffer_rt_f_rev", buffer_rt_f[1], buffer_rt_f[0], test_one<Polygon, Polygon, Polygon>("buffer_rt_f_rev", buffer_rt_f[1], buffer_rt_f[0],
1, 0, if_typed<ct, double>(18, 23), 4.60853); 1, 0, 23, 4.60853);
test_one<Polygon, Polygon, Polygon>("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], test_one<Polygon, Polygon, Polygon>("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1],
1, 0, if_typed<ct, float>(18, 17), 16.571); 1, 0, if_typed<ct, float>(18, 17), 16.571);
test_one<Polygon, Polygon, Polygon>("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0], test_one<Polygon, Polygon, Polygon>("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0],

View File

@ -0,0 +1,121 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#include <iostream>
#include <string>
#include <boost/assert.hpp>
#include <boost/variant/variant.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/multi_point.hpp>
#include <boost/geometry/geometries/multi_linestring.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
#include <boost/geometry/algorithms/is_simple.hpp>
#include <from_wkt.hpp>
#ifdef BOOST_GEOMETRY_TEST_DEBUG
#include "pretty_print_geometry.hpp"
#endif
namespace bg = ::boost::geometry;
template <typename Geometry, typename Strategy>
void test_simple_s(Geometry const& geometry,
Strategy const& strategy,
bool expected_result,
bool check_validity = true)
{
bool simple = bg::is_simple(geometry, strategy);
bool valid = ! check_validity || bg::is_valid(geometry, strategy);
BOOST_CHECK_MESSAGE( valid == true,
"Expected valid geometry, "
<< " wkt: " << bg::wkt(geometry) );
BOOST_CHECK_MESSAGE( simple == expected_result,
"Expected: " << expected_result
<< " detected: " << simple
<< " wkt: " << bg::wkt(geometry) );
}
template <typename CSTag, typename Geometry>
void test_simple(Geometry const& geometry, bool expected_result,
bool check_validity = true)
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "=======" << std::endl;
#endif
bool simple = bg::is_simple(geometry);
bool valid = ! check_validity || bg::is_valid(geometry);
BOOST_CHECK_MESSAGE( valid == true,
"Expected valid geometry, "
<< " wkt: " << bg::wkt(geometry) );
BOOST_CHECK_MESSAGE( simple == expected_result,
"Expected: " << expected_result
<< " detected: " << simple
<< " wkt: " << bg::wkt(geometry) );
typedef typename bg::strategy::intersection::services::default_strategy
<
CSTag
>::type strategy_type;
test_simple_s(geometry, strategy_type(), expected_result, check_validity);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "Geometry: ";
pretty_print_geometry<Geometry>::apply(std::cout, geometry);
std::cout << std::endl;
std::cout << std::boolalpha;
std::cout << "is simple: " << simple << std::endl;
std::cout << "expected result: " << expected_result << std::endl;
std::cout << "=======" << std::endl;
std::cout << std::endl << std::endl;
std::cout << std::noboolalpha;
#endif
}
template <typename Geometry>
void test_simple(Geometry const& geometry,
bool expected_result,
bool check_validity = true)
{
typedef typename bg::cs_tag<Geometry>::type cs_tag;
test_simple<cs_tag>(geometry, expected_result, check_validity);
}
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
void test_simple(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& variant_geometry,
bool expected_result,
bool check_validity = true)
{
typedef typename bg::cs_tag<T0>::type cs_tag;
test_simple<cs_tag>(variant_geometry, expected_result, check_validity);
}

View File

@ -325,6 +325,30 @@ struct validity_tester_areal
}; };
template <bool AllowDuplicates>
struct validity_tester_geo_areal
{
template <typename Geometry>
static inline bool apply(Geometry const& geometry)
{
bg::is_valid_default_policy<AllowDuplicates> visitor;
bg::strategy::intersection::geographic_segments<> s;
return bg::is_valid(geometry, visitor, s);
}
template <typename Geometry>
static inline std::string reason(Geometry const& geometry)
{
std::ostringstream oss;
bg::failing_reason_policy<AllowDuplicates> visitor(oss);
bg::strategy::intersection::geographic_segments<> s;
bg::is_valid(geometry, visitor, s);
return oss.str();
}
};
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------