mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-12 05:51:47 +00:00
Merge branch 'develop' into feature/intvalid
This commit is contained in:
commit
0591aa63ea
@ -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.
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 :
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 ]
|
||||
|
@ -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* [])
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
59
test/algorithms/is_simple_geo.cpp
Normal file
59
test/algorithms/is_simple_geo.cpp
Normal 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);
|
||||
}
|
38
test/algorithms/is_valid_geo.cpp
Normal file
38
test/algorithms/is_valid_geo.cpp
Normal 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);
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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],
|
||||
|
121
test/algorithms/test_is_simple.hpp
Normal file
121
test/algorithms/test_is_simple.hpp
Normal 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);
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user