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
[[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]]]
[[intersects(Segment)] [intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]]
[[[$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)]]
[[[$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.

View File

@ -25,6 +25,7 @@
[*Improvements]
* 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
[*Solved issues]
@ -43,6 +44,7 @@
* 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 error in disjoint for geographic Segment/Box
* Fix handling of non-cartesian geometries in various algorithms
[/=================]
[heading Boost 1.64]

View File

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

View File

@ -494,7 +494,7 @@ struct buffered_piece_collection
for (typename occupation_map_type::iterator it = occupation_map.begin();
it != occupation_map.end(); ++it)
{
it->second.get_left_turns(it->first, m_turns);
it->second.get_left_turns(it->first, m_turns, m_side_strategy);
}
}

View File

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

View File

@ -2,10 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2017.
// 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 Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -17,14 +18,22 @@
#include <boost/geometry/core/access.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
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// TODO: remove
template <std::size_t Index, typename Point1, typename 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)
// 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)
@ -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
template <typename Point1, typename Point2>
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)
// 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;
return direction_code_impl<Point1>::apply(segment_a, segment_b, p);
}
@ -73,7 +250,6 @@ inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
#endif //DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP

View File

@ -5,6 +5,11 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// 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 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>
static inline bool extend(CirclingIterator& it,
std::size_t n,
@ -214,10 +213,11 @@ struct extreme_points_on_ring
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,
Extremes const& extremes,
Intruders& intruders)
Intruders& intruders,
SideStrategy const& strategy)
{
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)
{
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 last_side = side_strategy::apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;
int const first_side = strategy.apply(*right, extremes.front(), *(extremes.begin() + 1)) * 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 (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,
Extremes const& extremes,
Intruders& intruders)
Intruders& intruders,
SideStrategy const& strategy)
{
std::size_t const n = boost::size(ring);
if (n >= 3)
@ -275,12 +276,12 @@ struct extreme_points_on_ring
geometry::ever_circling_range_iterator<Ring const> right(ring);
++right;
get_intruders(ring, left, right, extremes, intruders);
get_intruders(ring, left, right, extremes, intruders, strategy);
}
}
template <typename Iterator>
static inline bool right_turn(Ring const& ring, Iterator it)
template <typename Iterator, typename SideStrategy>
static inline bool right_turn(Ring const& ring, Iterator it, SideStrategy const& strategy)
{
typename std::iterator_traits<Iterator>::difference_type const index
= 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 first_side = side_strategy::apply(*(right - 1), *right, *left) * factor;
int const last_side = side_strategy::apply(*left, *(left + 1), *right) * factor;
int const first_side = strategy.apply(*(right - 1), *right, *left) * 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;
@ -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
template <typename Extremes, typename Intruders>
static inline bool apply(Ring const& ring, Extremes& extremes, Intruders& intruders)
template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Ring const& ring,
Extremes& extremes,
Intruders& intruders,
SideStrategy const& strategy)
{
std::size_t const n = boost::size(ring);
if (n < 3)
@ -321,7 +325,7 @@ struct extreme_points_on_ring
compare<Dimension> smaller;
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;
}
@ -365,7 +369,7 @@ struct extreme_points_on_ring
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;
}
@ -403,8 +407,9 @@ struct extreme_points<Ring, Dimension, ring_tag>
template<typename Polygon, std::size_t Dimension>
struct extreme_points<Polygon, Dimension, polygon_tag>
{
template <typename Extremes, typename Intruders>
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders)
template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders,
SideStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef detail::extreme_points::extreme_points_on_ring
@ -412,7 +417,8 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
ring_type, Dimension
> 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;
}
@ -423,7 +429,7 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
for (typename detail::interior_iterator<Polygon const>::type
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;
@ -433,8 +439,9 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
template<typename Box>
struct extreme_points<Box, 1, box_tag>
{
template <typename Extremes, typename Intruders>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
SideStrategy const& )
{
extremes.resize(4);
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
@ -446,8 +453,9 @@ struct extreme_points<Box, 1, box_tag>
template<typename Box>
struct extreme_points<Box, 0, box_tag>
{
template <typename Extremes, typename Intruders>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
SideStrategy const& )
{
extremes.resize(4);
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>
struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
{
template <typename Extremes, typename Intruders>
static inline bool apply(MultiPolygon const& multi, Extremes& extremes, Intruders& intruders)
template <typename Extremes, typename Intruders, typename SideStrategy>
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.
// 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,
Dimension,
polygon_tag
>::apply(*boost::begin(multi), extremes, intruders);
>::apply(*boost::begin(multi), extremes, intruders, strategy);
}
return false;
@ -489,8 +498,18 @@ struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
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.
*/
template <std::size_t Edge, typename Geometry, typename Extremes, typename Intruders>
inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders)
template
<
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>();
@ -509,7 +528,11 @@ inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intrude
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.
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// 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
{
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_strategy(strategy)
{}
template <typename Angle>
@ -89,8 +91,7 @@ struct angle_less
return quadrant_p < quadrant_q;
}
// Same quadrant, check if p is located left of q
int const side = side_strategy_type::apply(m_origin, q.point,
p.point);
int const side = m_strategy.apply(m_origin, q.point, p.point);
if (side != 0)
{
return side == 1;
@ -114,19 +115,17 @@ struct angle_less
private:
Point m_origin;
SideStrategy m_strategy;
};
template <typename Point>
template <typename Point, typename SideStrategy>
struct angle_equal_to
{
typedef Point vector_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type side_strategy_type;
inline angle_equal_to(Point const& origin)
inline angle_equal_to(Point const& origin, SideStrategy const& strategy)
: m_origin(origin)
, m_strategy(strategy)
{}
template <typename Angle>
@ -143,13 +142,13 @@ struct angle_equal_to
return false;
}
// Same quadrant, check if p/q are collinear
int const side = side_strategy_type::apply(m_origin, q.point,
p.point);
int const side = m_strategy.apply(m_origin, q.point, p.point);
return side == 0;
}
private:
Point m_origin;
SideStrategy m_strategy;
};
template <typename AngleCollection, typename Turns>
@ -193,13 +192,14 @@ inline void get_left_turns(AngleCollection const& sorted_angles,
//! Returns the number of clusters
template <typename Point, typename AngleCollection>
inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin)
template <typename Point, typename AngleCollection, typename SideStrategy>
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
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();
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>
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;
return ! boost::empty(linestring)
@ -247,7 +249,7 @@ struct is_simple_linestring
&& ! detail::is_valid::has_spikes
<
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,
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);
}
};
@ -267,23 +272,44 @@ struct is_simple_linestring<Linestring, true>
template <typename 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>
static inline bool apply(MultiLinestring const& multilinestring,
Strategy const& strategy)
{
typedef per_linestring<Strategy> per_ls;
// check each of the linestrings for simplicity
// but do not compute self-intersections yet; these will be
// computed for the entire multilinestring
if ( ! detail::check_iterator_range
<
is_simple_linestring
<
typename boost::range_value<MultiLinestring>::type,
false // do not compute self-intersections
>,
per_ls, // do not compute self-intersections
true // allow empty multilinestring
>::apply(boost::begin(multilinestring),
boost::end(multilinestring))
boost::end(multilinestring),
per_ls(strategy))
)
{
return false;

View File

@ -1,8 +1,9 @@
// 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 Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@ -91,8 +92,9 @@ struct has_spikes
return std::find_if(second, last, not_equal(*first));
}
template <typename VisitPolicy>
static inline bool apply(Range const& range, VisitPolicy& visitor)
template <typename VisitPolicy, typename SideStrategy>
static inline bool apply(Range const& range, VisitPolicy& visitor,
SideStrategy const& strategy)
{
boost::ignore_unused(visitor);
@ -124,9 +126,8 @@ struct has_spikes
while (next != boost::end(view))
{
if ( geometry::detail::point_is_spike_or_equal(*prev,
*next,
*cur) )
if ( geometry::detail::point_is_spike_or_equal(*prev, *next, *cur,
strategy) )
{
return
! visitor.template apply<failure_spikes>(is_linear, *cur);
@ -146,7 +147,7 @@ struct has_spikes
boost::rend(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
! visitor.template apply<failure_spikes>(is_linear, *cur);

View File

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

View File

@ -198,7 +198,7 @@ struct is_valid_ring
return
is_topologically_closed<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
|| has_valid_self_turns<Ring>::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.
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@ -99,12 +104,18 @@ public :
}
}
template <typename RobustPoint, typename Turns>
inline void get_left_turns(RobustPoint const& origin, Turns& turns)
template <typename RobustPoint, typename Turns, typename SideStrategy>
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
std::sort(m_angles.begin(), m_angles.end(),
detail::left_turns::angle_less<typename AngleInfo::point_type>(origin));
std::sort(m_angles.begin(), m_angles.end(), angle_less(origin, strategy));
// Group same-angled elements
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.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// 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,
SideStrategy const& strategy,
RobustPolicy const& robust_policy)
{
#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,
*(boost::end(range) - 3),
*(boost::end(range) - 2),
strategy,
robust_policy))
{
// 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,
SideStrategy const& strategy,
RobustPolicy const& robust_policy)
{
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
// 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);
if (BOOST_GEOMETRY_CONDITION(closed))

View File

@ -2,8 +2,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2017.
// 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 Adam Wulkiewicz, on behalf of Oracle
@ -57,12 +57,14 @@ struct copy_segments_ring
<
typename Ring,
typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(Ring const& ring,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@ -109,7 +111,7 @@ struct copy_segments_ring
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:
// 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,
Point const& point,
SideStrategy const& strategy,
RobustPolicy const& robust_policy,
boost::true_type const&)
{
detail::overlay::append_no_dups_or_spikes(current_output, point,
strategy,
robust_policy);
}
// 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,
Point const& point,
SideStrategy const&,
RobustPolicy const&,
boost::false_type const&)
{
@ -144,12 +149,14 @@ public:
<
typename LineString,
typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(LineString const& ls,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@ -170,7 +177,7 @@ public:
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>());
}
}
@ -183,12 +190,14 @@ struct copy_segments_polygon
<
typename Polygon,
typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(Polygon const& polygon,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@ -199,6 +208,7 @@ struct copy_segments_polygon
? geometry::exterior_ring(polygon)
: range::at(geometry::interior_rings(polygon), seg_id.ring_index),
seg_id, to_index,
strategy,
robust_policy,
current_output
);
@ -213,12 +223,14 @@ struct copy_segments_box
<
typename Box,
typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(Box const& box,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@ -239,7 +251,7 @@ struct copy_segments_box
for (signed_size_type i = 0; i < count; i++, index++)
{
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 SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
static inline void apply(MultiGeometry const& multi_geometry,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@ -272,6 +286,7 @@ struct copy_segments_multi
// Call the single-version
Policy::apply(range::at(multi_geometry, seg_id.multi_index),
seg_id, to_index,
strategy,
robust_policy,
current_output);
}
@ -341,12 +356,14 @@ template
bool Reverse,
typename Geometry,
typename SegmentIdentifier,
typename SideStrategy,
typename RobustPolicy,
typename RangeOut
>
inline void copy_segments(Geometry const& geometry,
SegmentIdentifier const& seg_id,
signed_size_type to_index,
SideStrategy const& strategy,
RobustPolicy const& robust_policy,
RangeOut& range_out)
{
@ -356,7 +373,7 @@ inline void copy_segments(Geometry const& geometry,
<
typename tag<Geometry>::type,
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.
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@ -59,7 +64,7 @@ template
typename Turns,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
typename Strategy
typename SideStrategy
>
inline void enrich_sort(Operations& operations,
Turns const& turns,
@ -67,7 +72,7 @@ inline void enrich_sort(Operations& operations,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
Strategy const& /*strategy*/)
SideStrategy const& strategy)
{
std::sort(boost::begin(operations),
boost::end(operations),
@ -77,8 +82,9 @@ inline void enrich_sort(Operations& operations,
typename boost::range_value<Operations>::type,
Geometry1, Geometry2,
RobustPolicy,
SideStrategy,
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 Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy side strategy type
\tparam SideStrategy side strategy type
\param turns container containing intersection points
\param clusters container containing clusters
\param geometry1 \param_geometry
@ -291,13 +297,13 @@ template
typename Clusters,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
typename Strategy
typename SideStrategy
>
inline void enrich_intersection_points(Turns& turns,
Clusters& clusters,
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
Strategy const& strategy)
SideStrategy const& strategy)
{
static const detail::overlay::operation_type target_operation
= detail::overlay::operation_from_overlay<OverlayType>::value;
@ -420,7 +426,8 @@ inline void enrich_intersection_points(Turns& turns,
Reverse1,
Reverse2,
OverlayType
>(clusters, turns, target_operation, geometry1, geometry2);
>(clusters, turns, target_operation,
geometry1, geometry2, strategy);
detail::overlay::cleanup_clusters(turns, clusters);
}

View File

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

View File

@ -2,12 +2,14 @@
// 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.
// 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
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
@ -183,7 +185,8 @@ protected:
typename TurnIterator,
typename TurnOperationIterator,
typename SegmentIdentifier,
typename OutputIterator
typename OutputIterator,
typename SideStrategy
>
static inline OutputIterator
process_turn(TurnIterator it,
@ -193,7 +196,8 @@ protected:
Linestring const& linestring,
LinestringOut& current_piece,
SegmentIdentifier& current_segment_id,
OutputIterator oit)
OutputIterator oit,
SideStrategy const& strategy)
{
// We don't rescale linear/linear
detail::no_rescale_policy robust_policy;
@ -208,7 +212,7 @@ protected:
action::enter(current_piece, linestring,
current_segment_id,
op_it->seg_id.segment_index,
it->point, *op_it, robust_policy, oit);
it->point, *op_it, strategy, robust_policy, oit);
}
++enter_count;
}
@ -223,7 +227,7 @@ protected:
action::leave(current_piece, linestring,
current_segment_id,
op_it->seg_id.segment_index,
it->point, *op_it, robust_policy, oit);
it->point, *op_it, strategy, robust_policy, oit);
}
}
else if ( FollowIsolatedPoints
@ -249,14 +253,16 @@ protected:
template
<
typename SegmentIdentifier,
typename OutputIterator
typename OutputIterator,
typename SideStrategy
>
static inline OutputIterator
process_end(bool entered,
Linestring const& linestring,
SegmentIdentifier const& current_segment_id,
LinestringOut& current_piece,
OutputIterator oit)
OutputIterator oit,
SideStrategy const& strategy)
{
if ( action::is_entered(entered) )
{
@ -269,6 +275,7 @@ protected:
>::apply(linestring,
current_segment_id,
static_cast<signed_size_type>(boost::size(linestring) - 1),
strategy,
robust_policy,
current_piece);
}
@ -283,11 +290,12 @@ protected:
}
public:
template <typename TurnIterator, typename OutputIterator>
template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
static inline OutputIterator
apply(Linestring const& linestring, Linear const&,
TurnIterator first, TurnIterator beyond,
OutputIterator oit)
OutputIterator oit,
SideStrategy const& strategy)
{
// Iterate through all intersection points (they are
// ordered along the each line)
@ -304,7 +312,8 @@ public:
entered, enter_count,
linestring,
current_piece, current_segment_id,
oit);
oit,
strategy);
}
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
@ -318,7 +327,8 @@ public:
return process_end(entered, linestring,
current_segment_id, current_piece,
oit);
oit,
strategy);
}
};
@ -413,11 +423,12 @@ protected:
};
public:
template <typename TurnIterator, typename OutputIterator>
template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
static inline OutputIterator
apply(MultiLinestring const& multilinestring, Linear const& linear,
TurnIterator first, TurnIterator beyond,
OutputIterator oit)
OutputIterator oit,
SideStrategy const& strategy)
{
BOOST_GEOMETRY_ASSERT( first != beyond );
@ -447,7 +458,7 @@ public:
has_other_multi_id(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;
linestring_iterator ls_next = ls_beyond;

View File

@ -2,6 +2,11 @@
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// 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.
Therefore, it is useful that using sides we are able to discover this.
*/
template <typename Point1>
struct get_relative_order
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point1>::type
>::type strategy;
template <typename Point>
template <typename Point, typename SideStrategy>
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_tj_u = strategy::apply(ti, tj, uj);
int const side_ti_u = strategy.apply(ti, tj, ui);
int const side_tj_u = strategy.apply(ti, tj, uj);
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
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(
Point1 const& pi, Point1 const& pj,
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_si_p = strategy::apply(pi, pj, si);
int const side_ri_p = strategy.apply(pi, pj, ri);
int const side_si_p = strategy.apply(pi, pj, si);
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
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;
#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)
{
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;

View File

@ -233,7 +233,7 @@ public :
// section 2: [--------------]
// section 1: |----|---|---|---|---|
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)
{
ever_circling_iterator<range1_iterator> nd_next1(
@ -251,7 +251,7 @@ public :
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)
{
bool skip = same_source;
@ -359,7 +359,7 @@ private :
// skips to the begin-point, we loose the index or have to recalculate it)
// So we mimic it here
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,
typename boost::range_iterator<Range const>::type& it,
typename boost::range_iterator<Range const>::type& prev,
@ -373,7 +373,7 @@ private :
// Mimic section-iterator:
// Skip to point such that section interects other box
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++)
{}
// 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.
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@ -728,11 +733,13 @@ template
typename Turns,
typename Clusters,
typename Geometry1,
typename Geometry2
typename Geometry2,
typename SideStrategy
>
inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
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 turn_type::point_type point_type;
@ -742,7 +749,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
// right side
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;
for (typename Clusters::iterator mit = clusters.begin();
@ -755,7 +762,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
continue;
}
sbs_type sbs;
sbs_type sbs(strategy);
point_type turn_point; // should be all the same for all turns in cluster
bool first = true;

View File

@ -2,6 +2,11 @@
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@ -60,6 +65,7 @@ template
typename Indexed,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
typename SideStrategy,
bool Reverse1, bool Reverse2
>
struct less_by_segment_ratio
@ -68,12 +74,14 @@ struct less_by_segment_ratio
, operation_type for_operation
, Geometry1 const& geometry1
, Geometry2 const& geometry2
, RobustPolicy const& robust_policy)
, RobustPolicy const& robust_policy
, SideStrategy const& strategy)
: m_turns(turns)
, m_for_operation(for_operation)
, m_geometry1(geometry1)
, m_geometry2(geometry2)
, m_robust_policy(robust_policy)
, m_strategy(strategy)
{
}
@ -84,6 +92,7 @@ private :
Geometry1 const& m_geometry1;
Geometry2 const& m_geometry2;
RobustPolicy const& m_robust_policy;
SideStrategy const& m_strategy;
typedef typename geometry::point_type<Geometry1>::type point_type;
@ -108,13 +117,8 @@ private :
*right.other_seg_id,
si, sj);
typedef typename strategy::side::services::default_strategy
<
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);
int const side_rj_p = m_strategy.apply(pi, pj, rj);
int const side_sj_p = m_strategy.apply(pi, pj, sj);
// Put the one turning left (1; right == -1) as last
if (side_rj_p != side_sj_p)
@ -122,8 +126,8 @@ private :
return side_rj_p < side_sj_p;
}
int const side_sj_r = strategy::apply(ri, rj, sj);
int const side_rj_s = strategy::apply(si, sj, rj);
int const side_sj_r = m_strategy.apply(ri, rj, sj);
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 right: this is not relevant, but take also here most left

View File

@ -194,13 +194,15 @@ protected:
typename Turns,
typename LinearGeometry1,
typename LinearGeometry2,
typename OutputIterator
typename OutputIterator,
typename IntersectionStrategy
>
static inline OutputIterator
sort_and_follow_turns(Turns& turns,
LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2,
OutputIterator oit)
OutputIterator oit,
IntersectionStrategy const& strategy)
{
// remove turns that have no added value
turns::filter_continue_turns
@ -228,7 +230,7 @@ protected:
FollowIsolatedPoints,
!EnableFilterContinueTurns || OverlayType == overlay_intersection
>::apply(linear1, linear2, boost::begin(turns), boost::end(turns),
oit);
oit, strategy.get_side_strategy());
}
public:
@ -277,7 +279,7 @@ public:
OverlayType,
EnableFollowIsolatedPoints
&& 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.
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// 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/direction_code.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/strategies/side.hpp>
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
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type side;
less_by_side(const Point& p1, const Point& p2)
less_by_side(const Point& p1, const Point& p2, SideStrategy const& strategy)
: m_p1(p1)
, m_p2(p2)
, m_strategy(strategy)
{}
template <typename T>
@ -125,8 +125,8 @@ struct less_by_side
LessOnSame on_same;
Compare compare;
int const side_first = side::apply(m_p1, m_p2, first.point);
int const side_second = side::apply(m_p1, m_p2, second.point);
int const side_first = m_strategy.apply(m_p1, m_p2, first.point);
int const side_second = m_strategy.apply(m_p1, m_p2, second.point);
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)
// 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)
{
@ -184,6 +184,7 @@ struct less_by_side
private :
Point m_p1, m_p2;
SideStrategy const& m_strategy;
};
// Sorts vectors in counter clockwise order (by default)
@ -193,6 +194,7 @@ template
bool Reverse2,
overlay_type OverlayType,
typename Point,
typename SideStrategy,
typename Compare
>
struct side_sorter
@ -223,9 +225,10 @@ private :
};
public :
side_sorter()
side_sorter(SideStrategy const& strategy)
: m_origin_count(0)
, m_origin_segment_distance(0)
, m_strategy(strategy)
{}
template <typename Operation, typename Geometry1, typename Geometry2>
@ -309,8 +312,8 @@ public :
// to give colinear points
// Sort by side and assign rank
less_by_side<Point, less_by_index, Compare> less_unique(m_origin, turn_point);
less_by_side<Point, less_false, Compare> less_non_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, 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);
@ -425,6 +428,7 @@ public :
Point m_origin;
std::size_t m_origin_count;
int m_origin_segment_distance;
SideStrategy m_strategy;
private :

View File

@ -2,6 +2,11 @@
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@ -94,6 +99,7 @@ template
typename Turns,
typename Clusters,
typename RobustPolicy,
typename SideStrategy,
typename Visitor
>
struct traversal
@ -108,17 +114,19 @@ struct traversal
typedef sort_by_side::side_sorter
<
Reverse1, Reverse2, OverlayType,
point_type, side_compare_type
point_type, SideStrategy, side_compare_type
> sbs_type;
inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2,
Turns& turns, Clusters const& clusters,
RobustPolicy const& robust_policy, Visitor& visitor)
RobustPolicy const& robust_policy, SideStrategy const& strategy,
Visitor& visitor)
: m_geometry1(geometry1)
, m_geometry2(geometry2)
, m_turns(turns)
, m_clusters(clusters)
, m_robust_policy(robust_policy)
, m_strategy(strategy)
, m_visitor(visitor)
{
}
@ -579,7 +587,7 @@ struct traversal
cluster_info const& cinfo = mit->second;
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();
sit != ids.end(); ++sit)
@ -625,7 +633,7 @@ struct traversal
turn_type const& current_turn,
segment_identifier const& previous_seg_id)
{
sbs_type sbs;
sbs_type sbs(m_strategy);
// Add this turn to the sort-by-side sorter
for (int i = 0; i < 2; i++)
@ -817,6 +825,7 @@ private :
Turns& m_turns;
Clusters const& m_clusters;
RobustPolicy const& m_robust_policy;
SideStrategy m_strategy;
Visitor& m_visitor;
};

View File

@ -50,9 +50,13 @@ template
>
struct traversal_ring_creator
{
typedef traversal<Reverse1, Reverse2, OverlayType,
Geometry1, Geometry2, Turns, Clusters, RobustPolicy, Visitor>
traversal_type;
typedef traversal
<
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 turn_type::turn_operation_type turn_operation_type;
@ -65,7 +69,9 @@ struct traversal_ring_creator
Clusters const& clusters,
IntersectionStrategy const& intersection_strategy,
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_geometry2(geometry2)
, m_turns(turns)
@ -106,12 +112,14 @@ struct traversal_ring_creator
{
geometry::copy_segments<Reverse1>(m_geometry1,
previous_op.seg_id, to_vertex_index,
m_intersection_strategy.get_side_strategy(),
m_robust_policy, current_ring);
}
else
{
geometry::copy_segments<Reverse2>(m_geometry2,
previous_op.seg_id, to_vertex_index,
m_intersection_strategy.get_side_strategy(),
m_robust_policy, current_ring);
}
}
@ -155,6 +163,7 @@ struct traversal_ring_creator
turn_type& current_turn = m_turns[turn_index];
turn_operation_type& op = current_turn.operations[op_index];
detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point,
m_intersection_strategy.get_side_strategy(),
m_robust_policy);
// 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];
detail::overlay::append_no_dups_or_spikes(ring, start_turn.point,
m_intersection_strategy.get_side_strategy(),
m_robust_policy);
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)
{
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);
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) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2017.
// 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 Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -19,11 +20,13 @@
#include <boost/geometry/algorithms/detail/direction_code.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/strategies/side.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
@ -32,6 +35,26 @@ namespace boost { namespace geometry
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.
// the specified two other points (segment_a, segment_b)
//
@ -42,33 +65,29 @@ namespace detail
// So specify last point first, then (a,b)
// The segment's orientation does matter: if lp is to the right of b
// no spike is reported
template <typename Point1, typename Point2, typename Point3>
static inline bool point_is_spike_or_equal(Point1 const& last_point,
Point2 const& segment_a,
Point3 const& segment_b)
template
<
typename Point1, typename Point2, typename Point3,
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
<
typename cs_tag<Point1>::type
>::type side_strategy;
int const side = side_strategy::apply(last_point, segment_a, segment_b);
int const side = strategy.apply(segment_a, segment_b, last_point);
if (side == 0)
{
// Last point is collinear w.r.t previous segment.
// Check if it 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 it 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;
#ifdef BOOST_GEOMETRY_ENABLE_POINT_IS_SPIKE_OR_EQUAL_TEST
bool r1 = collinear_point_is_spike_or_equal(last_point, segment_a, segment_b);
bool r2 = direction_code(segment_a, segment_b, last_point) < 1;
if (r1 != r2)
std::cout << "spike detection failure with: " << r1 << " " << r2 << std::endl;
return r2;
#else
return direction_code(segment_a, segment_b, last_point) < 1;
#endif
}
return false;
}
@ -78,14 +97,16 @@ template
typename Point1,
typename Point2,
typename Point3,
typename SideStrategy,
typename RobustPolicy
>
static inline bool point_is_spike_or_equal(Point1 const& last_point,
Point2 const& segment_a,
Point3 const& segment_b,
SideStrategy const& strategy,
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;
}
@ -111,7 +132,8 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point,
(
last_point_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.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2017.
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -27,6 +27,74 @@ namespace boost { namespace geometry
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
<
std::size_t Dimension,
@ -34,14 +102,15 @@ template
typename RobustBox,
typename RobustPolicy
>
static inline bool preceding(int dir, Point const& point,
RobustBox const& robust_box,
static inline bool preceding(int dir,
Point const& point,
RobustBox const& point_robust_box,
RobustBox const& other_robust_box,
RobustPolicy const& robust_policy)
{
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
geometry::recalculate(robust_point, point, robust_policy);
return (dir == 1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box))
|| (dir == -1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box));
return preceding_check<Dimension, Point>::apply(dir, robust_point, point_robust_box, other_robust_box);
}
template
@ -51,14 +120,13 @@ template
typename RobustBox,
typename RobustPolicy
>
static inline bool exceeding(int dir, Point const& point,
RobustBox const& robust_box,
static inline bool exceeding(int dir,
Point const& point,
RobustBox const& point_robust_box,
RobustBox const& other_robust_box,
RobustPolicy const& robust_policy)
{
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
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));
return preceding<Dimension>(-dir, point, point_robust_box, other_robust_box, robust_policy);
}

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2015.
// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
// 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 Menelaos Karavelas, on behalf of Oracle
@ -136,11 +136,21 @@ struct sections : std::vector<section<Box, DimensionCount> >
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
<
typename Point,
typename DimensionVector,
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
{
@ -161,21 +171,67 @@ struct get_direction_loop
get_direction_loop
<
Point,
DimensionVector,
Index + 1,
Count
Count,
CastedCSTag
>::apply(seg, directions);
}
};
template <typename DimensionVector, std::size_t Count>
struct get_direction_loop<DimensionVector, Count, Count>
template
<
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>
static inline void apply(Segment const&, int [Count])
{}
};
//! Copy one static array to another
template <typename T, std::size_t Index, std::size_t Count>
struct copy_loop
@ -410,7 +466,7 @@ struct sectionalize_part
int direction_classes[dimension_count] = {0};
get_direction_loop
<
DimensionVector, 0, dimension_count
Point, DimensionVector, 0, dimension_count
>::apply(robust_segment, direction_classes);
// if "dir" == 0 for all point-dimensions, it is duplicate.
@ -929,7 +985,10 @@ inline void sectionalize(Geometry const& geometry,
typename cs_tag<Geometry>::type
>::type envelope_strategy_type;
sectionalize<Reverse, DimensionVector>(geometry, robust_policy, sections,
boost::geometry::sectionalize
<
Reverse, DimensionVector
>(geometry, robust_policy, sections,
envelope_strategy_type(),
source_index, max_count);
}

View File

@ -2,6 +2,11 @@
// 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@ -10,17 +15,23 @@
#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/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.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/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
namespace boost { namespace geometry
{
@ -31,15 +42,9 @@ namespace detail { namespace is_convex
struct ring_is_convex
{
template <typename Ring>
static inline bool apply(Ring const& ring)
template <typename Ring, typename SideStrategy>
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);
if (boost::size(ring) < core_detail::closure::minimum_ring_size
<
@ -86,7 +91,7 @@ struct ring_is_convex
// iterator
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)
{
// Next is on the left side of clockwise ring:
@ -129,7 +134,8 @@ struct is_convex : not_implemented<Tag>
template <typename Box>
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)
return true;
@ -144,13 +150,71 @@ struct is_convex<Box, ring_tag> : detail::is_convex::ring_is_convex
} // namespace 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
template<typename 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) 2013 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// 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/strategies/cartesian/centroid_bashein_detmer.hpp>
#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry
@ -241,8 +242,9 @@ inline void replace_extremes_for_self_tangencies(Extremes& extremes, Intruders&
extremes = triangle;
}
template <int Dimension, typename Geometry, typename Point>
inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
template <int Dimension, typename Geometry, typename Point, typename SideStrategy>
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::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;
intruders_type intruders;
geometry::extreme_points<Dimension>(geometry, extremes, intruders);
geometry::extreme_points<Dimension>(geometry, extremes, intruders, strategy);
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
\param geometry Geometry to take point from
\param point Point to assign
\param strategy side strategy
*/
template <typename Geometry, typename Point>
inline void point_on_surface(Geometry const& geometry, Point & point)
template <typename Geometry, typename Point, typename SideStrategy>
inline void point_on_surface(Geometry const& geometry, Point & point,
SideStrategy const& strategy)
{
concepts::check<Point>();
concepts::check<Geometry const>();
// 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
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
\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) 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,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@ -34,6 +39,8 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/condition.hpp>
@ -59,20 +66,13 @@ namespace detail { namespace remove_spikes
{
template <typename Range>
struct range_remove_spikes
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Range>::type
>::type side_strategy;
typedef typename coordinate_type<Range>::type coordinate_type;
template <typename Range, typename SideStrategy>
static inline void apply(Range& range, SideStrategy const& strategy)
{
typedef typename point_type<Range>::type point_type;
static inline void apply(Range& range)
{
std::size_t n = boost::size(range);
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);
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)
cleaned.erase(cleaned.end() - 2);
@ -110,13 +113,21 @@ struct range_remove_spikes
found = false;
// Check for spike in first point
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();
found = true;
}
// 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();
found = true;
@ -144,15 +155,13 @@ struct range_remove_spikes
};
template <typename Polygon>
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<ring_type> per_range;
per_range::apply(exterior_ring(polygon));
typedef range_remove_spikes per_range;
per_range::apply(exterior_ring(polygon), strategy);
typename interior_return_type<Polygon>::type
rings = interior_rings(polygon);
@ -160,23 +169,24 @@ struct polygon_remove_spikes
for (typename detail::interior_iterator<Polygon>::type
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
{
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
it = boost::begin(multi);
it != boost::end(multi);
++it)
{
SingleVersion::apply(*it);
SingleVersion::apply(*it, strategy);
}
}
};
@ -199,21 +209,22 @@ template
>
struct remove_spikes
{
static inline void apply(Geometry&)
template <typename SideStrategy>
static inline void apply(Geometry&, SideStrategy const&)
{}
};
template <typename Ring>
struct remove_spikes<Ring, ring_tag>
: detail::remove_spikes::range_remove_spikes<Ring>
: detail::remove_spikes::range_remove_spikes
{};
template <typename Polygon>
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>
: detail::remove_spikes::multi_remove_spikes
<
MultiPolygon,
detail::remove_spikes::polygon_remove_spikes
<
typename boost::range_value<MultiPolygon>::type
>
>
{};
@ -239,28 +246,46 @@ namespace resolve_variant {
template <typename Geometry>
struct remove_spikes
{
static void apply(Geometry& geometry)
template <typename Strategy>
static void apply(Geometry& geometry, Strategy const& strategy)
{
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)>
struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<void>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy) : m_strategy(strategy) {}
template <typename Geometry>
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>
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_ep2; // squared 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)
: m_spheroid(spheroid)
@ -92,12 +92,27 @@ protected :
* (CT(2.0) - CT(formula::flattening<CT>(spheroid))))
, m_ep2(m_e2 / (CT(1.0) - m_e2))
, m_ep(math::sqrt(m_ep2))
, m_c2((m_a2 / CT(2.0)) +
((math::sqr(get_radius<2>(spheroid)) * boost::math::atanh(math::sqrt(m_e2)))
/ (CT(2.0) * math::sqrt(m_e2))))
, m_c2(authalic_radius(spheroid, m_a2, 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
{
CT m_excess_sum;

View File

@ -4,7 +4,7 @@
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
# 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.
#
# 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_empty.cpp : : : : algorithms_is_empty ]
[ 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_failure.cpp : : : : algorithms_is_valid_failure ]
[ run is_valid_geo.cpp : : : : algorithms_is_valid_geo ]
[ run make.cpp : : : : algorithms_make ]
[ run maximum_gap.cpp : : : : algorithms_maximum_gap ]
[ 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,
// 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* [])

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_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>
void test_all()
{
@ -78,6 +80,18 @@ void test_all()
mysql_report_2015_02_25_1, join, end_flat,
distance_strategy(6051788), side_strategy,
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>

View File

@ -13,36 +13,7 @@
#define BOOST_TEST_MODULE test_is_simple
#endif
#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
#include "test_is_simple.hpp"
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;
//----------------------------------------------------------------------------
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 )
{
#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>
#endif
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
template <typename P, typename T>
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 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);

View File

@ -49,12 +49,14 @@ template
typename Turns,
typename Clusters,
typename Geometry1,
typename Geometry2
typename Geometry2,
typename SideStrategy
>
std::vector<std::size_t> test_gather_cluster_properties(std::string const& case_id,
Clusters& clusters, Turns& turns,
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::detail::overlay;
@ -69,7 +71,7 @@ std::vector<std::size_t> test_gather_cluster_properties(std::string const& case_
// right side
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;
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;
}
sbs_type sbs;
sbs_type sbs(strategy);
point_type turn_point; // should be all the same for all turns in cluster
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
return test_gather_cluster_properties<Reverse1, Reverse2, OverlayType>(case_id,
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
// right side
typedef typename Strategy::side_strategy_type side_strategy;
typedef bg::detail::overlay::sort_by_side::side_sorter
<
false, false, overlay_union,
point_type, std::less<int>
point_type, side_strategy, std::less<int>
> sbs_type;
sbs_type sbs;
sbs_type sbs(strategy.get_side_strategy());
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
{
BOOST_CHECK_MESSAGE(right_count[rank] == ranked_point.count_right,
BOOST_CHECK_MESSAGE(right_count[rank] == int(ranked_point.count_right),
" caseid=" << case_id
<< " ranks: conflict in right_count=" << ranked_point.count_right
<< " vs " << right_count[rank]);

View File

@ -398,9 +398,9 @@ void test_areal()
// Robustness issues, followed out buffer-robustness-tests, test them also reverse
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
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],
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],
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],

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();
}
};
//----------------------------------------------------------------------------