Merge branch 'develop' of https://github.com/boostorg/geometry into feature/setops

Conflicts:
	include/boost/geometry/algorithms/detail/relate/less.hpp
This commit is contained in:
Menelaos Karavelas
2014-04-01 04:05:50 +03:00
44 changed files with 3167 additions and 625 deletions

View File

@@ -1,79 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014 Oracle and/or its affiliates.
// 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)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GROUP_DIM_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GROUP_DIM_HPP
#include <boost/type_traits/is_base_of.hpp>
#include <boost/geometry/core/tag.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail {
template <typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type,
bool IsPoint = boost::is_base_of<pointlike_tag, Tag>::value,
bool IsLinear = boost::is_base_of<linear_tag, Tag>::value,
bool IsAreal = boost::is_base_of<areal_tag, Tag>::value>
struct group_tag
: not_implemented<Tag>
{};
template <typename Geometry, typename Tag>
struct group_tag<Geometry, Tag, true, false, false>
{
typedef pointlike_tag type;
};
template <typename Geometry, typename Tag>
struct group_tag<Geometry, Tag, false, true, false>
{
typedef linear_tag type;
};
template <typename Geometry, typename Tag>
struct group_tag<Geometry, Tag, false, false, true>
{
typedef areal_tag type;
};
template <typename Geometry,
typename GroupTag = typename group_tag<Geometry>::type>
struct group_dim
: not_implemented<GroupTag>
{};
template <typename Geometry>
struct group_dim<Geometry, pointlike_tag>
{
static const int value = 0;
};
template <typename Geometry>
struct group_dim<Geometry, linear_tag>
{
static const int value = 1;
};
template <typename Geometry>
struct group_dim<Geometry, areal_tag>
{
static const int value = 2;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GROUP_DIM_HPP

View File

@@ -52,9 +52,8 @@ struct get_turn_without_info
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
// TODO: should this always be std::size_t or replace with template parameter?
std::size_t /*p_segments_count*/,
std::size_t /*q_segments_count*/,
bool /*is_p_first*/, bool /*is_p_last*/,
bool /*is_q_first*/, bool /*is_q_last*/,
TurnInfo const& ,
RescalePolicy const& rescale_policy,
OutputIterator out)

View File

@@ -975,9 +975,8 @@ struct get_turn_info
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
// TODO: should this always be std::size_t or replace with template parameter?
std::size_t /*p_segments_count*/,
std::size_t /*q_segments_count*/,
bool /*is_p_first*/, bool /*is_p_last*/,
bool /*is_q_first*/, bool /*is_q_last*/,
TurnInfo const& tp_model,
RescalePolicy const& , // TODO: this will be used. rescale_policy,
OutputIterator out)

View File

@@ -130,9 +130,8 @@ struct get_turn_info_for_endpoint
>
static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
// TODO: should this always be std::size_t or replace with template parameter?
std::size_t p_segments_count,
std::size_t q_segments_count,
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
IntersectionResult const& result,
method_type method,
@@ -147,11 +146,6 @@ struct get_turn_info_for_endpoint
int segment_index1 = tp_model.operations[1].seg_id.segment_index;
BOOST_ASSERT(segment_index0 >= 0 && segment_index1 >= 0);
bool is_p_first = segment_index0 == 0;
bool is_q_first = segment_index1 == 0;
bool is_p_last = static_cast<std::size_t>(segment_index0) + 1 == p_segments_count;
bool is_q_last = static_cast<std::size_t>(segment_index1) + 1 == q_segments_count;
if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last )
return false;
@@ -418,14 +412,13 @@ struct get_turn_info_for_endpoint
geometry::convert(i2, i2_conv);
side_calculator<Point1, Point2> side_calc(i2_conv, i1, j1, i2, j2, k2);
TurnInfo tp = tp_model;
equal<TurnInfo>::apply(i2_conv, i1, j1, i2, j2, k2,
tp, result.template get<0>(), result.template get<1>(), side_calc);
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);
// TODO: must the above be calculated?
// wouldn't it be enough to check if segments are collinear?
if ( tp.both(operation_continue) )
if ( operations_both(operations, operation_continue) )
{
// THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE!
bool opposite = result.template get<1>().opposite;
@@ -435,7 +428,7 @@ struct get_turn_info_for_endpoint
}
else
{
BOOST_ASSERT(tp.combination(operation_intersection, operation_union));
BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union));
//op1 = operation_union;
//op2 = operation_union;
}
@@ -466,14 +459,13 @@ struct get_turn_info_for_endpoint
side_calculator<Point1, Point2> side_calc(i2_conv, j1, i1, i2, j2, k2);
TurnInfo tp = tp_model;
equal<TurnInfo>::apply(i2_conv, j1, i1, i2, j2, k2,
tp, result.template get<0>(), result.template get<1>(), side_calc);
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);
// TODO: must the above be calculated?
// wouldn't it be enough to check if segments are collinear?
if ( tp.both(operation_continue) )
if ( operations_both(operations, operation_continue) )
{
// THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE!
bool second_going_out = result.template get<0>().count > 1;
@@ -483,7 +475,7 @@ struct get_turn_info_for_endpoint
}
else
{
BOOST_ASSERT(tp.combination(operation_intersection, operation_union));
BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union));
//op1 = operation_blocked;
//op2 = operation_union;
}
@@ -558,6 +550,66 @@ struct get_turn_info_for_endpoint
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
template <typename SidePolicy>
static inline std::pair<operation_type, operation_type> operations_of_equal(SidePolicy const& side)
{
int const side_pk_q2 = side.pk_wrt_q2();
int const side_pk_p = side.pk_wrt_p1();
int const side_qk_p = side.qk_wrt_p1();
// If pk is collinear with qj-qk, they continue collinearly.
// This can be on either side of p1 (== q1), or collinear
// The second condition checks if they do not continue
// oppositely
if ( side_pk_q2 == 0 && side_pk_p == side_qk_p )
{
return std::make_pair(operation_continue, operation_continue);
}
// If they turn to same side (not opposite sides)
if ( ! base_turn_handler::opposite(side_pk_p, side_qk_p) )
{
int const side_pk_q2 = side.pk_wrt_q2();
// If pk is left of q2 or collinear: p: union, q: intersection
if ( side_pk_q2 != -1 )
{
return std::make_pair(operation_union, operation_intersection);
}
else
{
return std::make_pair(operation_intersection, operation_union);
}
}
else
{
// They turn opposite sides. If p turns left (or collinear),
// p: union, q: intersection
if ( side_pk_p != -1 )
{
return std::make_pair(operation_union, operation_intersection);
}
else
{
return std::make_pair(operation_intersection, operation_union);
}
}
}
static inline bool operations_both(
std::pair<operation_type, operation_type> const& operations,
operation_type const op)
{
return operations.first == op && operations.second == op;
}
static inline bool operations_combination(
std::pair<operation_type, operation_type> const& operations,
operation_type const op1, operation_type const op2)
{
return ( operations.first == op1 && operations.second == op2 )
|| ( operations.first == op2 && operations.second == op1 );
}
};
}} // namespace detail::overlay

View File

@@ -17,6 +17,9 @@
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp>
// TEMP, for spikes detector
//#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
@@ -36,9 +39,8 @@ struct get_turn_info_linear_areal
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
// TODO: should this always be std::size_t or replace with template parameter?
std::size_t p_segments_count,
std::size_t q_segments_count,
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
RescalePolicy const& , // TODO: this will be used. rescale_policy,
OutputIterator out)
@@ -74,7 +76,8 @@ struct get_turn_info_linear_areal
case 'f' : // collinear, "from"
case 's' : // starts from the middle
get_turn_info_for_endpoint<true, true>(
pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_none, out);
break;
@@ -84,7 +87,8 @@ struct get_turn_info_linear_areal
case 'm' :
{
if ( get_turn_info_for_endpoint<false, true>(
pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_touch_interior, out) )
{
// do nothing
@@ -139,7 +143,8 @@ struct get_turn_info_linear_areal
{
// Both touch (both arrive there)
if ( get_turn_info_for_endpoint<false, true>(
pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_touch, out) )
{
// do nothing
@@ -164,7 +169,8 @@ struct get_turn_info_linear_areal
case 'e':
{
if ( get_turn_info_for_endpoint<true, true>(
pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_equal, out) )
{
// do nothing
@@ -183,6 +189,14 @@ struct get_turn_info_linear_areal
replacer_of_method_and_operations_ec<false> replacer(method_touch);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TODO: This isn't correct handling, hence commented out
/*spike_detector<Point1, Point2> spike_detect(side_calc);
if ( tp.operations[0].operation == operation_union
&& spike_detect.is_spike_p())
{
tp.operations[0].operation = operation_continue;
}*/
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
@@ -202,7 +216,8 @@ struct get_turn_info_linear_areal
{
// Collinear
if ( get_turn_info_for_endpoint<true, true>(
pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_collinear, out) )
{
// do nothing
@@ -219,6 +234,13 @@ struct get_turn_info_linear_areal
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(), side_calc);
spike_detector<Point1, Point2> spike_detect(side_calc);
if ( tp.operations[0].operation == operation_union
&& spike_detect.is_spike_p())
{
tp.operations[0].operation = operation_continue;
}
replacer_of_method_and_operations_ec<false> replacer(method_touch);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
}
@@ -288,12 +310,18 @@ struct get_turn_info_linear_areal
// Assuming G1 is always Linear
if ( op0 == operation_blocked )
{
op0 = operation_continue;
}
if ( op1 == operation_blocked )
{
op1 = operation_continue;
}
else if ( op1 == operation_intersection )
{
op1 = operation_union;
}
}
template <bool IsFront>
@@ -318,12 +346,18 @@ struct get_turn_info_linear_areal
// Assuming G1 is always Linear
if ( op0 == operation_blocked )
{
op0 = operation_continue;
}
if ( op1 == operation_blocked )
{
op1 = operation_continue;
}
else if ( op1 == operation_intersection )
{
op1 = operation_union;
}
}
private:
@@ -347,9 +381,8 @@ struct get_turn_info_linear_areal
static inline bool get_turn_info_for_endpoint(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
// TODO: should this always be std::size_t or replace with template parameter?
std::size_t p_segments_count,
std::size_t q_segments_count,
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
IntersectionResult const& result,
method_type method,
@@ -367,11 +400,6 @@ struct get_turn_info_linear_areal
const int segment_index1 = tp_model.operations[1].seg_id.segment_index;
BOOST_ASSERT(segment_index0 >= 0 && segment_index1 >= 0);
const bool is_p_first = segment_index0 == 0;
const bool is_q_first = segment_index1 == 0; // not used
const bool is_p_last = static_cast<std::size_t>(segment_index0) + 1 == p_segments_count;
const bool is_q_last = static_cast<std::size_t>(segment_index1) + 1 == q_segments_count; // not used
if ( !is_p_first && !is_p_last )
return false;
@@ -430,8 +458,11 @@ struct get_turn_info_linear_areal
{
side_calculator<Point1, Point2> side_calc(qi_conv, pi, pj, qi, qj, qk);
equal<TurnInfo>::apply(qi_conv, pi, pj, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(), side_calc);
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
tp.operations[0].operation = operations.first;
tp.operations[1].operation = operations.second;
replaced_method = method_touch;
}
@@ -443,9 +474,11 @@ struct get_turn_info_linear_areal
side_calculator<Point1, Point2> side_calc(qi_conv, pi, pj, qi, pi_conv, qj);
// Collinear, but similar thus handled as equal
equal<TurnInfo>::apply(qi_conv, pi, pj, qi, pi_conv, qj,
tp, result.template get<0>(), result.template get<1>(), side_calc);
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
tp.operations[0].operation = operations.first;
tp.operations[1].operation = operations.second;
}
replacer_of_method_and_operations_ec<true> replacer(replaced_method);
@@ -491,8 +524,11 @@ struct get_turn_info_linear_areal
geometry::convert(qi, qi_conv);
side_calculator<Point1, Point2> side_calc(qi_conv, pj, pi, qi, qj, qk);
equal<TurnInfo>::apply(qi_conv, pj, pi, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(), side_calc);
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
tp.operations[0].operation = operations.first;
tp.operations[1].operation = operations.second;
replacer_of_method_and_operations_ec<false> replacer(method_none);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);

View File

@@ -22,6 +22,62 @@ namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay {
template <typename Point1,
typename Point2,
typename SideCalc = side_calculator<Point1, Point2> >
class spike_detector
{
public:
explicit spike_detector(SideCalc const& side_calc)
: m_side_calc(side_calc)
{}
inline bool is_spike_p() const
{
if ( m_side_calc.pk_wrt_p1() == 0 )
{
int const qk_p1 = m_side_calc.qk_wrt_p1();
int const qk_p2 = m_side_calc.qk_wrt_p2();
if ( qk_p1 == -qk_p2 )
{
if ( qk_p1 == 0 )
{
// TODO check additional things
}
return true;
}
}
return false;
}
inline bool is_spike_q() const
{
if ( m_side_calc.qk_wrt_q1() == 0 )
{
int const pk_q1 = m_side_calc.pk_wrt_q1();
int const pk_q2 = m_side_calc.pk_wrt_q2();
if ( pk_q1 == -pk_q2 )
{
if ( pk_q1 == 0 )
{
// TODO check additional things
}
return true;
}
}
return false;
}
private:
SideCalc const& m_side_calc;
};
template<typename AssignPolicy>
struct get_turn_info_linear_linear
{
@@ -36,9 +92,8 @@ struct get_turn_info_linear_linear
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
// TODO: should this always be std::size_t or replace with template parameter?
std::size_t p_segments_count,
std::size_t q_segments_count,
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
RescalePolicy const& , // TODO: this will be used. rescale_policy,
OutputIterator out)
@@ -74,8 +129,9 @@ struct get_turn_info_linear_linear
case 'f' : // collinear, "from"
case 's' : // starts from the middle
get_turn_info_for_endpoint<AssignPolicy, true, true>
::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
tp_model, result, method_none, out);
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_none, out);
break;
case 'd' : // disjoint: never do anything
@@ -84,8 +140,9 @@ struct get_turn_info_linear_linear
case 'm' :
{
if ( get_turn_info_for_endpoint<AssignPolicy, false, true>
::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
tp_model, result, method_touch_interior, out) )
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_touch_interior, out) )
{
// do nothing
}
@@ -143,7 +200,8 @@ struct get_turn_info_linear_linear
{
// Both touch (both arrive there)
if ( get_turn_info_for_endpoint<AssignPolicy, false, true>
::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_touch, out) )
{
// do nothing
@@ -172,7 +230,8 @@ struct get_turn_info_linear_linear
case 'e':
{
if ( get_turn_info_for_endpoint<AssignPolicy, true, true>
::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_equal, out) )
{
// do nothing
@@ -191,6 +250,19 @@ struct get_turn_info_linear_linear
replacer_of_method_and_operations_ec replacer(method_touch);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TODO: This isn't correct handling, hence commented out
/*spike_detector<Point1, Point2> spike_detect(side_calc);
if ( tp.operations[0].operation == operation_union
&& spike_detect.is_spike_p())
{
tp.operations[0].operation = operation_continue;
}
if ( tp.operations[1].operation == operation_union
&& spike_detect.is_spike_q())
{
tp.operations[1].operation = operation_continue;
}*/
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
@@ -211,7 +283,8 @@ struct get_turn_info_linear_linear
{
// Collinear
if ( get_turn_info_for_endpoint<AssignPolicy, true, true>
::apply(pi, pj, pk, qi, qj, qk, p_segments_count, q_segments_count,
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, method_collinear, out) )
{
// do nothing
@@ -236,6 +309,19 @@ struct get_turn_info_linear_linear
replacer_of_method_and_operations_ec replacer(method_touch);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TODO: This isn't correct handling, hence commented out
/*spike_detector<Point1, Point2> spike_detect(side_calc);
if ( tp.operations[0].operation == operation_union
&& spike_detect.is_spike_p())
{
tp.operations[0].operation = operation_continue;
}
if ( tp.operations[1].operation == operation_union
&& spike_detect.is_spike_q())
{
tp.operations[1].operation = operation_continue;
}*/
}
else
{
@@ -244,6 +330,11 @@ struct get_turn_info_linear_linear
replacer_of_method_and_operations_ec replacer(method_touch_interior);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TEST
//spike_detector<Point1, Point2> spike_detect(side_calc);
//spike_detect.is_spike_p();
//spike_detect.is_spike_q();
}
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
@@ -305,14 +396,22 @@ struct get_turn_info_linear_linear
else
{
if ( op0 == operation_continue || op0 == operation_blocked )
{
op0 = operation_intersection;
}
else if ( op0 == operation_intersection )
{
op0 = operation_union;
}
if ( op1 == operation_continue || op1 == operation_blocked )
{
op1 = operation_intersection;
}
else if ( op1 == operation_intersection )
{
op1 = operation_union;
}
}
}
@@ -330,14 +429,22 @@ struct get_turn_info_linear_linear
BOOST_ASSERT(op0 != operation_blocked || op1 != operation_blocked );
if ( op0 == operation_blocked )
{
op0 = operation_intersection;
}
else if ( op0 == operation_intersection )
{
op0 = operation_union;
}
if ( op1 == operation_blocked )
{
op1 = operation_intersection;
}
else if ( op1 == operation_intersection )
{
op1 = operation_union;
}
if ( op0 == operation_intersection || op0 == operation_union
|| op1 == operation_intersection || op1 == operation_union )
@@ -353,13 +460,15 @@ struct get_turn_info_linear_linear
static inline void replace_operations_i(operation_type & op0, operation_type & op1)
{
if ( op0 == operation_intersection )
{
op0 = operation_union;
}
if ( op1 == operation_intersection )
{
op1 = operation_union;
}
}
};
}} // namespace detail::overlay

View File

@@ -54,7 +54,6 @@
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp>
#include <boost/geometry/algorithms/detail/group_dim.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
@@ -287,8 +286,13 @@ public :
std::size_t const size_before = boost::size(turns);
bool const is_1_first = sec1.is_non_duplicate_first && index1 == sec1.begin_index;
bool const is_1_last = sec1.is_non_duplicate_last && index1+1 >= sec1.end_index;
bool const is_2_first = sec2.is_non_duplicate_first && index2 == sec2.begin_index;
bool const is_2_last = sec2.is_non_duplicate_last && index2+1 >= sec2.end_index;
TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2,
sec1.range_count - 1, sec2.range_count - 1,
is_1_first, is_1_last, is_2_first, is_2_last,
ti, rescale_policy, std::back_inserter(turns));
if (InterruptPolicy::enabled)
@@ -598,7 +602,9 @@ struct get_turns_cs
get_turns_with_box(seg_id, source_id2,
*prev, *it, *next,
bp[0], bp[1], bp[2], bp[3],
segments_count1,
// NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes
index == 0,
unsigned(index) == segments_count1,
rescale_policy,
turns, interrupt_policy);
// Future performance enhancement:
@@ -639,7 +645,8 @@ private:
box_point_type const& bp1,
box_point_type const& bp2,
box_point_type const& bp3,
std::size_t segments_count1,
bool const is_range_first,
bool const is_range_last,
RescalePolicy const& rescale_policy,
// Output
Turns& turns,
@@ -658,22 +665,26 @@ private:
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 0);
TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2,
segments_count1, 4,
is_range_first, is_range_last,
true, false,
ti, rescale_policy, std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1);
TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3,
segments_count1, 4,
is_range_first, is_range_last,
false, false,
ti, rescale_policy, std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2);
TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0,
segments_count1, 4,
is_range_first, is_range_last,
false, false,
ti, rescale_policy, std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);
TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1,
segments_count1, 4,
is_range_first, is_range_last,
false, true,
ti, rescale_policy, std::back_inserter(turns));
if (InterruptPolicy::enabled)
@@ -738,9 +749,15 @@ struct get_turns_polygon_cs
// GET_TURN_INFO_TYPE
template <typename Geometry>
struct topological_tag_base
{
typedef typename tag_cast<typename tag<Geometry>::type, pointlike_tag, linear_tag, areal_tag>::type type;
};
template <typename Geometry1, typename Geometry2, typename AssignPolicy,
typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,
typename TagBase1 = typename group_tag<Geometry1>::type, typename TagBase2 = typename group_tag<Geometry2>::type>
typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>
struct get_turn_info_type
: overlay::get_turn_info<AssignPolicy>
{};
@@ -757,7 +774,7 @@ struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear
template <typename Geometry1, typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,
typename TagBase1 = typename group_tag<Geometry1>::type, typename TagBase2 = typename group_tag<Geometry2>::type>
typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>
struct turn_operation_type
{
typedef overlay::turn_operation type;

View File

@@ -1,78 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
// 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)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RANGE_HELPERS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RANGE_HELPERS_HPP
#include <boost/range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace range {
template <typename Range>
inline typename boost::range_value<Range>::type const&
at(Range const& rng, typename boost::range_size<Range>::type i)
{
BOOST_ASSERT(i < boost::size(rng));
return *(boost::begin(rng) + i);
}
template <typename Range>
inline typename boost::range_value<Range>::type &
at(Range & rng, typename boost::range_size<Range>::type i)
{
BOOST_ASSERT(i < boost::size(rng));
return *(boost::begin(rng) + i);
}
template <typename Range>
inline typename boost::range_value<Range>::type const&
front(Range const& rng)
{
BOOST_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
template <typename Range>
inline typename boost::range_value<Range>::type &
front(Range & rng)
{
BOOST_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
template <typename Range>
inline typename boost::range_value<Range>::type const&
back(Range const& rng)
{
BOOST_ASSERT(!boost::empty(rng));
return *(--boost::end(rng));
}
template <typename Range>
inline typename boost::range_value<Range>::type &
back(Range & rng)
{
BOOST_ASSERT(!boost::empty(rng));
return *(--boost::end(rng));
}
}} // namespace detail::range
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RANGE_HELPERS_HPP

View File

@@ -11,8 +11,10 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/range_helpers.hpp>
namespace boost { namespace geometry
{
@@ -112,14 +114,14 @@ public:
if ( BoundaryQuery == boundary_back )
{
if ( sid.segment_index + 2 != geometry::num_points(sub_geometry::get(geometry, sid)) )
if ( sid.segment_index + 2 != geometry::num_points(sub_range(geometry, sid)) )
return false;
}
if ( BoundaryQuery == boundary_any )
{
if ( sid.segment_index != 0
&& sid.segment_index + 2 != geometry::num_points(sub_geometry::get(geometry, sid)) )
&& sid.segment_index + 2 != geometry::num_points(sub_range(geometry, sid)) )
return false;
}

View File

@@ -18,47 +18,37 @@
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate {
#ifndef DOXYGEN_NO_DISPATCH
namespace detail_dispatch { namespace relate {
// TODO: should this be integrated with geometry::less?
// TODO: Integrate it with geometry::less?
template
<
typename Point1,
typename Point2,
std::size_t I = 0,
std::size_t D1 = geometry::dimension<Point1>::value,
std::size_t D2 = geometry::dimension<Point2>::value
>
struct less_dispatch
: not_implemented<Point1, Point2>
{};
template<typename Point1, typename Point2, std::size_t I, std::size_t D>
struct less_dispatch<Point1, Point2, I, D, D>
template <typename Point1,
typename Point2,
std::size_t I = 0,
std::size_t D = geometry::dimension<Point1>::value>
struct less
{
static inline bool apply(Point1 const& l, Point2 const& r)
static inline bool apply(Point1 const& left, Point2 const& right)
{
typename geometry::coordinate_type<Point1>::type
cl = geometry::get<I>(l);
cleft = geometry::get<I>(left);
typename geometry::coordinate_type<Point2>::type
cr = geometry::get<I>(r);
cright = geometry::get<I>(right);
if ( geometry::math::equals(cl, cr) )
if ( geometry::math::equals(cleft, cright) )
{
return less_dispatch<Point1, Point2, I + 1, D, D>::apply(l, r);
return less<Point1, Point2, I + 1, D>::apply(left, right);
}
else
{
return cl < cr;
return cleft < cright;
}
}
};
template <typename Point1, typename Point2, std::size_t D>
struct less_dispatch<Point1, Point2, D, D, D>
struct less<Point1, Point2, D, D>
{
static inline bool apply(Point1 const&, Point2 const&)
{
@@ -66,12 +56,19 @@ struct less_dispatch<Point1, Point2, D, D, D>
}
};
}} // namespace detail_dispatch::relate
#endif
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate {
struct less
{
template <typename Point1, typename Point2>
inline bool operator()(Point1 const& point1, Point2 const& point2) const
{
return less_dispatch<Point1, Point2>::apply(point1, point2);
return detail_dispatch::relate::less<Point1, Point2>::apply(point1, point2);
}
};

View File

@@ -14,9 +14,10 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP
#include <boost/geometry/algorithms/detail/group_dim.hpp>
#include <boost/geometry/algorithms/detail/sub_geometry.hpp>
#include <boost/geometry/algorithms/detail/range_helpers.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/turns.hpp>
@@ -185,8 +186,8 @@ template <typename Geometry1, typename Geometry2, bool TransposeResult = false>
struct linear_areal
{
// check Linear / Areal
BOOST_STATIC_ASSERT(detail::group_dim<Geometry1>::value == 1
&& detail::group_dim<Geometry2>::value == 2);
BOOST_STATIC_ASSERT(topological_dimension<Geometry1>::value == 1
&& topological_dimension<Geometry2>::value == 2);
static const bool interruption_enabled = true;
@@ -607,6 +608,7 @@ struct linear_areal
&& !fake_enter_detected
&& it->operations[op_id].position != overlay::position_front )
{
// TODO: calculate_from_inside() is only needed if the current Linestring is not closed
bool from_inside = first_in_range
&& calculate_from_inside(geometry,
other_geometry,
@@ -621,7 +623,7 @@ struct linear_areal
if ( first_in_range )
{
bool front_b = is_endpoint_on_boundary<boundary_front>(
range::front(sub_geometry::get(geometry, seg_id)),
range::front(sub_range(geometry, seg_id)),
boundary_checker);
// if there is a boundary on the first point
@@ -692,6 +694,7 @@ struct linear_areal
// TODO: very similar code is used in the handling of intersection
if ( it->operations[op_id].position != overlay::position_front )
{
// TODO: calculate_from_inside() is only needed if the current Linestring is not closed
bool first_from_inside = first_in_range
&& calculate_from_inside(geometry,
other_geometry,
@@ -712,7 +715,7 @@ struct linear_areal
if ( first_in_range && ( !this_b || op_blocked ) )
{
bool front_b = is_endpoint_on_boundary<boundary_front>(
range::front(sub_geometry::get(geometry, seg_id)),
range::front(sub_range(geometry, seg_id)),
boundary_checker);
// if there is a boundary on the first point
@@ -758,7 +761,7 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
bool prev_back_b = is_endpoint_on_boundary<boundary_back>(
range::back(sub_geometry::get(geometry, prev_seg_id)),
range::back(sub_range(geometry, prev_seg_id)),
boundary_checker);
// if there is a boundary on the last point
@@ -779,7 +782,7 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
bool prev_back_b = is_endpoint_on_boundary<boundary_back>(
range::back(sub_geometry::get(geometry, prev_seg_id)),
range::back(sub_range(geometry, prev_seg_id)),
boundary_checker);
// if there is a boundary on the last point
@@ -832,10 +835,10 @@ struct linear_areal
reverse2 ? iterate_reverse : iterate_forward
>::type range2_view;
typedef typename sub_geometry::result_type<Geometry1 const>::type range1_ref;
typedef typename sub_range_return_type<Geometry1 const>::type range1_ref;
range1_ref range1 = sub_geometry::get(geometry1, turn.operations[op_id].seg_id);
range2_cview const cview(sub_geometry::get(geometry2, turn.operations[other_op_id].seg_id));
range1_ref range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
range2_cview const cview(sub_range(geometry2, turn.operations[other_op_id].seg_id));
range2_view const range2(cview);
std::size_t s1 = boost::size(range1);
@@ -855,18 +858,23 @@ struct linear_areal
geometry::convert(qi, qi_conv);
bool is_ip_qj = equals::equals_point_point(turn.point, qj);
// TODO: test this!
BOOST_ASSERT(!equals::equals_point_point(turn.point, pi));
BOOST_ASSERT(!equals::equals_point_point(turn.point, qi));
// BOOST_ASSERT(!equals::equals_point_point(turn.point, pi));
// BOOST_ASSERT(!equals::equals_point_point(turn.point, qi));
point1_type new_pj;
geometry::convert(turn.point, new_pj);
if ( is_ip_qj )
{
std::size_t q_seg_jk = (q_seg_ij + 1) % seg_count2;
BOOST_ASSERT(q_seg_jk + 1 < s2);
point2_type const& qk = range::at(range2, q_seg_jk + 1);
// Will this sequence of point be always correct?
overlay::side_calculator<point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, qj, qk);
// TODO: the following function should return immediately, however the worst case complexity is O(N)
// It would be good to replace it with some O(1) mechanism
typename boost::range_iterator<range2_view>::type
qk_it = find_next_non_duplicated(boost::begin(range2),
boost::begin(range2) + q_seg_jk,
boost::end(range2));
// Will this sequence of points be always correct?
overlay::side_calculator<point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it);
return calculate_from_inside_sides(side_calc);
}
@@ -881,6 +889,29 @@ struct linear_areal
}
}
template <typename It>
static inline It find_next_non_duplicated(It first, It current, It last)
{
BOOST_ASSERT( current != last );
It it = current;
for ( ++it ; it != last ; ++it )
{
if ( !equals::equals_point_point(*current, *it) )
return it;
}
// if not found start from the beginning
for ( it = first ; it != current ; ++it )
{
if ( !equals::equals_point_point(*current, *it) )
return it;
}
return current;
}
// calculate inside or outside based on side_calc
// this is simplified version of a check from equal<>
template <typename SideCalc>

View File

@@ -14,8 +14,9 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP
#include <boost/geometry/algorithms/detail/sub_geometry.hpp>
#include <boost/geometry/algorithms/detail/range_helpers.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/turns.hpp>
@@ -454,7 +455,7 @@ struct linear_linear
if ( first_in_range )
{
bool front_b = is_endpoint_on_boundary<boundary_front>(
range::front(sub_geometry::get(geometry, seg_id)),
range::front(sub_range(geometry, seg_id)),
boundary_checker);
// if there is a boundary on the first point
@@ -529,7 +530,7 @@ struct linear_linear
if ( first_in_range )
{
bool front_b = is_endpoint_on_boundary<boundary_front>(
range::front(sub_geometry::get(geometry, seg_id)),
range::front(sub_range(geometry, seg_id)),
boundary_checker);
// if there is a boundary on the first point
@@ -557,25 +558,33 @@ struct linear_linear
{
// it's also the boundary of the other geometry
if ( other_b )
{
update<boundary, boundary, '0', transpose_result>(res);
}
else
{
update<boundary, interior, '0', transpose_result>(res);
}
}
// if current IP is not on boundary of the geometry
else
{
// it's also the boundary of the other geometry
if ( other_b )
{
update<interior, boundary, '0', transpose_result>(res);
}
else
{
update<interior, interior, '0', transpose_result>(res);
}
}
// first IP on the last segment point - this means that the first point is outside
if ( first_in_range && ( !this_b || op_blocked ) && was_outside /*&& !is_collinear*/ )
{
bool front_b = is_endpoint_on_boundary<boundary_front>(
range::front(sub_geometry::get(geometry, seg_id)),
range::front(sub_range(geometry, seg_id)),
boundary_checker);
// if there is a boundary on the first point
@@ -611,7 +620,7 @@ struct linear_linear
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
bool prev_back_b = is_endpoint_on_boundary<boundary_back>(
range::back(sub_geometry::get(geometry, prev_seg_id)),
range::back(sub_range(geometry, prev_seg_id)),
boundary_checker);
// if there is a boundary on the last point

View File

@@ -15,8 +15,15 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
#include <boost/tuple/tuple.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
// TEMP - move this header to geometry/detail
#include <boost/geometry/index/detail/tuples.hpp>
@@ -796,8 +803,8 @@ typedef static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> static_mask_dis
// TOUCHES - NOT P/P
template <typename Geometry1,
typename Geometry2,
std::size_t Dim1 = detail::group_dim<Geometry1>::value,
std::size_t Dim2 = detail::group_dim<Geometry2>::value>
std::size_t Dim1 = topological_dimension<Geometry1>::value,
std::size_t Dim2 = topological_dimension<Geometry2>::value>
struct static_mask_touches_type
{
typedef boost::mpl::vector<
@@ -829,8 +836,8 @@ typedef boost::mpl::vector<
// dim(G1) < dim(G2) - P/L P/A L/A
template <typename Geometry1,
typename Geometry2,
std::size_t Dim1 = detail::group_dim<Geometry1>::value,
std::size_t Dim2 = detail::group_dim<Geometry2>::value,
std::size_t Dim1 = topological_dimension<Geometry1>::value,
std::size_t Dim2 = topological_dimension<Geometry2>::value,
bool D1LessD2 = (Dim1 < Dim2)
>
struct static_mask_crosses_type
@@ -866,8 +873,8 @@ struct static_mask_crosses_type<Geometry1, Geometry2, 1, 1, D1LessD2>
// dim(G1) != dim(G2) - NOT P/P, L/L, A/A
template <typename Geometry1,
typename Geometry2,
std::size_t Dim1 = detail::group_dim<Geometry1>::value,
std::size_t Dim2 = detail::group_dim<Geometry2>::value
std::size_t Dim1 = topological_dimension<Geometry1>::value,
std::size_t Dim2 = topological_dimension<Geometry2>::value
>
struct static_mask_overlaps_type
: not_implemented<typename geometry::tag<Geometry1>::type,

View File

@@ -11,8 +11,9 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/range_helpers.hpp>
namespace boost { namespace geometry {

View File

@@ -4,6 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -11,6 +14,8 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
@@ -72,6 +77,9 @@ struct section
bool duplicate;
int non_duplicate_index;
bool is_non_duplicate_first;
bool is_non_duplicate_last;
inline section()
: id(-1)
, begin_index(-1)
@@ -80,6 +88,8 @@ struct section
, range_count(0)
, duplicate(false)
, non_duplicate_index(-1)
, is_non_duplicate_first(false)
, is_non_duplicate_last(false)
{
assign_inverse(bounding_box);
for (std::size_t i = 0; i < DimensionCount; i++)
@@ -251,13 +261,11 @@ struct sectionalize_part
typename Sections
>
static inline void apply(Sections& sections,
typename boost::range_value<Sections>::type& section,
int& index, int& ndi,
Range const& range,
RescalePolicy const& rescale_policy,
bool make_rescaled_boxes,
ring_identifier ring_id,
std::size_t max_count)
Range const& range,
RescalePolicy const& rescale_policy,
bool make_rescaled_boxes,
ring_identifier ring_id,
std::size_t max_count)
{
boost::ignore_unused_variable_warning(rescale_policy);
boost::ignore_unused_variable_warning(make_rescaled_boxes);
@@ -267,19 +275,20 @@ struct sectionalize_part
typedef typename boost::range_iterator<Range const>::type iterator_type;
if (int(boost::size(range)) <= index)
if ( boost::empty(range) )
{
return;
}
if (index == 0)
{
ndi = 0;
}
int index = 0;
int ndi = 0; // non duplicate index
section_type section;
bool mark_first_non_duplicated = true;
std::size_t last_non_duplicate_index = 0;
iterator_type it = boost::begin(range);
it += index;
for(iterator_type previous = it++;
it != boost::end(range);
++previous, ++it, index++)
@@ -329,6 +338,11 @@ struct sectionalize_part
)
)
{
if ( !section.duplicate )
{
last_non_duplicate_index = sections.size();
}
sections.push_back(section);
section = section_type();
}
@@ -341,6 +355,12 @@ struct sectionalize_part
section.non_duplicate_index = ndi;
section.range_count = boost::size(range);
if ( mark_first_non_duplicated && !duplicate )
{
section.is_non_duplicate_first = true;
mark_first_non_duplicated = false;
}
copy_loop
<
int, 0, DimensionCount
@@ -356,6 +376,23 @@ struct sectionalize_part
ndi++;
}
}
// Add last section if applicable
if (section.count > 0)
{
if ( !section.duplicate )
{
last_non_duplicate_index = sections.size();
}
sections.push_back(section);
}
if ( last_non_duplicate_index < sections.size()
&& !sections[last_non_duplicate_index].duplicate )
{
sections[last_non_duplicate_index].is_non_duplicate_last = true;
}
}
};
@@ -375,10 +412,11 @@ struct sectionalize_range
typename Sections
>
static inline void apply(Range const& range,
RescalePolicy const& rescale_policy,
bool make_rescaled_boxes,
Sections& sections,
ring_identifier ring_id, std::size_t max_count)
RescalePolicy const& rescale_policy,
bool make_rescaled_boxes,
Sections& sections,
ring_identifier ring_id,
std::size_t max_count)
{
typedef typename closeable_view<Range const, Closure>::type cview_type;
typedef typename reversible_view
@@ -403,20 +441,8 @@ struct sectionalize_range
return;
}
int index = 0;
int ndi = 0; // non duplicate index
typedef typename boost::range_value<Sections>::type section_type;
section_type section;
sectionalize_part<Point, DimensionCount>
::apply(sections, section, index, ndi, view, rescale_policy, make_rescaled_boxes, ring_id, max_count);
// Add last section if applicable
if (section.count > 0)
{
sections.push_back(section);
}
::apply(sections, view, rescale_policy, make_rescaled_boxes, ring_id, max_count);
}
};

View File

@@ -1,131 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
// 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)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_GEOMETRY_HPP
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace sub_geometry {
// TODO: later implement Geometry-specialized index_type
// polygons/multi_polygons also need ring_index member
struct index_type
{
index_type() : multi_index(-1) {}
int multi_index;
inline bool operator<(index_type const& i) const
{
return multi_index < i.multi_index;
}
inline bool operator==(index_type const& i) const
{
return multi_index == i.multi_index;
}
};
}} // namespace detail::sub_geometry
namespace detail_dispatch { namespace sub_geometry {
// TODO: later remove IsMulti and move to multi directory
template <typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type,
bool IsMulti = boost::is_base_of<multi_tag, Tag>::value>
struct get : not_implemented<Tag>
{};
template <typename Geometry, typename Tag>
struct get<Geometry, Tag, false>
{
typedef Geometry & result_type;
template <typename Id> static inline
result_type apply(Geometry & geometry, Id const&)
{
return geometry;
}
};
template <typename Geometry>
struct get<Geometry, polygon_tag, false>
{
typedef typename geometry::ring_type<Geometry>::type & result_type;
template <typename Id> static inline
result_type apply(Geometry & geometry, Id const& id)
{
if ( id.ring_index < 0 )
{
return geometry::exterior_ring(geometry);
}
else
{
std::size_t ri = static_cast<std::size_t>(id.ring_index);
BOOST_ASSERT( ri < boost::size(geometry::interior_rings(geometry)) );
return *(boost::begin(geometry::interior_rings(geometry)) + ri);
}
}
};
template <typename Geometry, typename Tag>
struct get<Geometry, Tag, true>
{
typedef typename boost::range_value<Geometry>::type value_type;
typedef typename boost::mpl::if_c
<
boost::is_const<Geometry>::value,
typename boost::add_const<value_type>::type,
value_type
>::type sub_type;
typedef detail_dispatch::sub_geometry::get<sub_type> get_type;
typedef typename get_type::result_type result_type;
template <typename Id> static inline
result_type apply(Geometry & geometry, Id const& id)
{
BOOST_ASSERT(0 <= id.multi_index);
return get_type::apply(*(boost::begin(geometry) + id.multi_index), id);
}
};
}} // namespace detail_dispatch::sub_geometry
namespace detail { namespace sub_geometry {
template <typename Geometry>
struct result_type
{
typedef typename detail_dispatch::sub_geometry::get<Geometry>::result_type type;
};
// This function also works for geometry::segment_identifier
template <typename Geometry, typename Id> inline
typename detail_dispatch::sub_geometry::get<Geometry>::result_type
get(Geometry & geometry, Id const& id)
{
return detail_dispatch::sub_geometry::get<Geometry>::apply(geometry, id);
};
}} // namespace detail::sub_geometry
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_GEOMETRY_HPP

View File

@@ -0,0 +1,113 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
// 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)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace detail_dispatch {
template <typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type,
bool IsMulti = boost::is_base_of<multi_tag, Tag>::value>
struct sub_range : not_implemented<Tag>
{};
template <typename Geometry, typename Tag>
struct sub_range<Geometry, Tag, false>
{
typedef Geometry & return_type;
template <typename Id> static inline
return_type apply(Geometry & geometry, Id const&)
{
return geometry;
}
};
template <typename Geometry>
struct sub_range<Geometry, polygon_tag, false>
{
typedef typename geometry::ring_type<Geometry>::type & return_type;
template <typename Id> static inline
return_type apply(Geometry & geometry, Id const& id)
{
if ( id.ring_index < 0 )
{
return geometry::exterior_ring(geometry);
}
else
{
std::size_t ri = static_cast<std::size_t>(id.ring_index);
return range::at(geometry::interior_rings(geometry), ri);
}
}
};
template <typename Geometry, typename Tag>
struct sub_range<Geometry, Tag, true>
{
typedef typename boost::range_value<Geometry>::type value_type;
typedef typename boost::mpl::if_c
<
boost::is_const<Geometry>::value,
typename boost::add_const<value_type>::type,
value_type
>::type sub_type;
typedef detail_dispatch::sub_range<sub_type> sub_sub_range;
// TODO: shouldn't it be return_type?
typedef typename sub_sub_range::return_type return_type;
template <typename Id> static inline
return_type apply(Geometry & geometry, Id const& id)
{
BOOST_ASSERT(0 <= id.multi_index);
return sub_sub_range::apply(range::at(geometry, id.multi_index), id);
}
};
} // namespace detail_dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace detail {
template <typename Geometry>
struct sub_range_return_type
{
typedef typename detail_dispatch::sub_range<Geometry>::return_type type;
};
// This function also works for geometry::segment_identifier
template <typename Geometry, typename Id> inline
typename sub_range_return_type<Geometry>::type
sub_range(Geometry & geometry, Id const& id)
{
return detail_dispatch::sub_range<Geometry>::apply(geometry, id);
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP

View File

@@ -28,7 +28,7 @@
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_geometries.hpp>
#include <boost/geometry/algorithms/detail/sub_geometry.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
@@ -207,8 +207,8 @@ struct linear_areal_interrupt_policy
template <typename Turn>
inline bool is_turn_on_last_point(Turn const& turn)
{
typename sub_geometry::result_type<Linear const>::type
g = sub_geometry::get(linear, turn.operations[0].seg_id);
typename sub_range_return_type<Linear const>::type
g = sub_range(linear, turn.operations[0].seg_id);
std::size_t s = boost::size(g);

View File

@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -14,6 +14,8 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
@@ -61,81 +63,21 @@ namespace boost { namespace geometry
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
// currently works only for linestrings
template <typename Geometry1, typename Geometry2>
struct linear_linear
struct use_point_in_geometry
{
template <typename Strategy>
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;
}
};
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)
{
// TODO within() should return FALSE if a length(geometry1) == 0 and is contained entirely within a boundary,
// also if geometry2 has length(geometry2) == 0, it should be considered as a point.
// TODO: currently only for linestrings
std::size_t s1 = boost::size(geometry1);
std::size_t s2 = boost::size(geometry2);
if ( s1 == 0 || s2 == 0 || s2 == 1 )
return false;
if ( s1 == 1 && s2 == 1 ) // within(Pt, Pt)
return false;
if ( s1 == 1 )
return point_in_geometry(*boost::begin(geometry1), geometry2) > 0;
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef detail::overlay::turn_info<point1_type> turn_info;
typedef detail::overlay::get_turn_info
<
detail::overlay::assign_null_policy
> policy_type;
std::deque<turn_info> turns;
detail::get_turns::no_interrupt_policy policy;
boost::geometry::get_turns
<
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, // should be false
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, // should be false
detail::overlay::assign_null_policy
>(geometry1, geometry2, detail::no_rescale_policy(), turns, policy);
return analyse_turns(turns.begin(), turns.end())
// TODO: currently only for linestrings
&& point_in_geometry(*boost::begin(geometry1), geometry2) >= 0
&& point_in_geometry(*(boost::end(geometry1) - 1), geometry2) >= 0;
}
template <typename TurnIt>
static inline bool analyse_turns(TurnIt first, TurnIt last)
{
bool has_turns = false;
for ( TurnIt it = first ; it != last ; ++it )
{
switch ( it->method )
{
case overlay::method_crosses:
return false;
case overlay::method_touch:
case overlay::method_touch_interior:
if ( it->both(overlay::operation_continue)
|| it->both(overlay::operation_blocked) )
{
has_turns = true;
}
else
return false;
case overlay::method_equal:
case overlay::method_collinear:
has_turns = true;
break;
case overlay::method_none :
case overlay::method_disjoint :
case overlay::method_error :
break;
}
}
return has_turns;
return Strategy::apply(geometry1, geometry2);
}
};
@@ -180,48 +122,73 @@ struct within<Box1, Box2, box_tag, box_tag>
}
};
// P/A
template <typename Point, typename Ring>
struct within<Point, Ring, point_tag, ring_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy)
{
return detail::within::point_in_geometry(point, ring, strategy) == 1;
}
};
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename Polygon>
struct within<Point, Polygon, point_tag, polygon_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy)
{
return detail::within::point_in_geometry(point, polygon, strategy) == 1;
}
};
: public detail::within::use_point_in_geometry
{};
// P/L
template <typename Point, typename Linestring>
struct within<Point, Linestring, point_tag, linestring_tag>
{
template <typename Strategy> static inline
bool apply(Point const& point, Linestring const& linestring, Strategy const& strategy)
{
return detail::within::point_in_geometry(point, linestring, strategy) == 1;
}
};
: public detail::within::use_point_in_geometry
{};
// L/L
template <typename Linestring1, typename Linestring2>
struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>
{
template <typename Strategy> static inline
bool apply(Linestring1 const& linestring1, Linestring2 const& linestring2, Strategy const& strategy)
{
return detail::within::linear_linear<Linestring1, Linestring2>
::apply(linestring1, linestring2, strategy);
}
};
: public detail::within::use_relate
{};
template <typename Linestring, typename MultiLinestring>
struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Linestring>
struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
: public detail::within::use_relate
{};
// L/A
template <typename Linestring, typename Ring>
struct within<Linestring, Ring, linestring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Ring>
struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename Polygon>
struct within<Linestring, Polygon, linestring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Polygon>
struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename MultiPolygon>
struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename MultiPolygon>
struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@@ -0,0 +1,109 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
namespace boost { namespace geometry
{
template <typename Iterator1, typename Iterator2, typename Value>
struct concatenate_iterator
: public boost::iterator_facade
<
concatenate_iterator<Iterator1, Iterator2, Value>,
Value,
boost::forward_traversal_tag
>
{
private:
Iterator1 m_it1, m_end1;
Iterator2 m_it2;
struct enabler {};
public:
typedef Iterator1 first_iterator_type;
typedef Iterator2 second_iterator_type;
// default constructor
concatenate_iterator() {}
// for begin
concatenate_iterator(Iterator1 it1, Iterator1 end1,
Iterator2 it2)
: m_it1(it1), m_end1(end1), m_it2(it2)
{}
// for end
concatenate_iterator(Iterator1 end1, Iterator2 end2)
: m_it1(end1), m_end1(end1), m_it2(end2)
{}
template <typename OtherIt1, typename OtherIt2, typename OtherValue>
concatenate_iterator
(concatenate_iterator<OtherIt1, OtherIt2, OtherValue> const& other,
typename boost::enable_if_c
<
boost::is_convertible<OtherIt1, Iterator1>::value
&& boost::is_convertible<OtherIt2, Iterator2>::value,
enabler
>::type = enabler())
: m_it1(other.m_it1), m_end1(other.m_end1), m_it2(other.m_it2)
{}
private:
friend class boost::iterator_core_access;
template <typename It1, typename It2, typename V>
friend class concatenate_iterator;
Value& dereference() const
{
if ( m_it1 == m_end1 )
{
return *m_it2;
}
return *m_it1;
}
bool equal(concatenate_iterator const& other) const
{
return m_it1 == other.m_it1 && m_it2 == other.m_it2;
}
void increment()
{
if ( m_it1 == m_end1 )
{
++m_it2;
}
else
{
++m_it1;
}
}
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP

View File

@@ -0,0 +1,47 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// dispatch for points_begin
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct points_begin
: not_implemented<Geometry>
{};
// dispatch for points_end
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct points_end
: not_implemented<Geometry>
{};
} // namespace core_dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP

View File

@@ -0,0 +1,37 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP
#define BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct point_iterator_type
: not_implemented<Geometry>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_TYPE_HPP

View File

@@ -0,0 +1,208 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
namespace boost { namespace geometry
{
template
<
typename OuterIterator,
typename InnerIterator,
typename Value,
typename AccessInnerBegin,
typename AccessInnerEnd
>
struct flatten_iterator
: public boost::iterator_facade
<
flatten_iterator
<
OuterIterator,
InnerIterator,
Value,
AccessInnerBegin,
AccessInnerEnd>,
Value,
boost::forward_traversal_tag
>
{
private:
OuterIterator m_outer_it, m_outer_end;
InnerIterator m_inner_it;
struct enabler {};
public:
typedef OuterIterator outer_iterator_type;
typedef InnerIterator inner_iterator_type;
// default constructor
flatten_iterator() {}
// for begin
flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)
: m_outer_it(outer_it), m_outer_end(outer_end)
{
advance_through_empty();
}
// for end
flatten_iterator(OuterIterator outer_end)
: m_outer_it(outer_end), m_outer_end(outer_end)
{}
template
<
typename OtherOuterIterator, typename OtherInnerIterator,
typename OtherValue,
typename OtherAccessInnerBegin, typename OtherAccessInnerEnd
>
flatten_iterator(flatten_iterator
<
OtherOuterIterator,
OtherInnerIterator,
OtherValue,
OtherAccessInnerBegin,
OtherAccessInnerEnd
> const& other,
typename boost::enable_if
<
boost::is_convertible<OtherValue*, Value*>,
enabler
>::type = enabler())
: m_outer_it(other.m_outer_it),
m_outer_end(other.m_outer_end),
m_inner_it(other.m_inner_it)
{}
template
<
typename OtherOuterIterator,
typename OtherInnerIterator,
typename OtherValue,
typename OtherAccessInnerBegin,
typename OtherAccessInnerEnd
>
flatten_iterator operator=(flatten_iterator
<
OtherOuterIterator,
OtherInnerIterator,
OtherValue,
OtherAccessInnerBegin,
OtherAccessInnerEnd
> const& other)
{
m_outer_it = other.m_outer_it;
m_outer_end = other.m_outer_end;
m_inner_it = other.m_inner_it;
return *this;
}
private:
friend class boost::iterator_core_access;
template
<
typename Outer,
typename Inner,
typename V,
typename InnerBegin,
typename InnerEnd
>
friend class flatten_iterator;
static inline bool empty(OuterIterator outer_it)
{
return
AccessInnerBegin::apply(*outer_it) == AccessInnerEnd::apply(*outer_it);
}
inline void advance_through_empty()
{
while ( m_outer_it != m_outer_end && empty(m_outer_it) )
{
++m_outer_it;
}
if ( m_outer_it != m_outer_end )
{
m_inner_it = AccessInnerBegin::apply(*m_outer_it);
}
}
Value& dereference() const
{
BOOST_ASSERT( m_outer_it != m_outer_end );
BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
return *m_inner_it;
}
template
<
typename OtherOuterIterator,
typename OtherInnerIterator,
typename OtherValue,
typename OtherAccessInnerBegin,
typename OtherAccessInnerEnd
>
inline bool equal(flatten_iterator
<
OtherOuterIterator,
OtherInnerIterator,
OtherValue,
OtherAccessInnerBegin,
OtherAccessInnerEnd
> const& other) const
{
if ( this->m_outer_it != other.m_outer_it )
{
return false;
}
if ( this->m_outer_it == m_outer_end )
{
return true;
}
return this->m_inner_it == other.m_inner_it;
}
inline void increment()
{
BOOST_ASSERT( m_outer_it != m_outer_end );
BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
++m_inner_it;
if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
{
++m_outer_it;
advance_through_empty();
}
}
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP

View File

@@ -0,0 +1,278 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
#include <boost/utility/enable_if.hpp>
#include <boost/geometry/iterators/dispatch/point_iterator.hpp>
#include <boost/geometry/iterators/point_iterator_type.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// specializations for points_begin
template <typename Linestring>
struct points_begin<Linestring, linestring_tag>
{
static inline typename point_iterator_type<Linestring>::type
apply(Linestring& linestring)
{
return boost::begin(linestring);
}
};
template <typename Ring>
struct points_begin<Ring, ring_tag>
{
static inline typename point_iterator_type<Ring>::type
apply(Ring& ring)
{
return boost::begin(ring);
}
};
template <typename Polygon>
struct points_begin<Polygon, polygon_tag>
{
typedef typename point_iterator_type<Polygon>::type return_type;
static inline return_type apply(Polygon& polygon)
{
typedef typename return_type::second_iterator_type flatten_iterator;
return return_type
(boost::begin(geometry::exterior_ring(polygon)),
boost::end(geometry::exterior_ring(polygon)),
flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
boost::end(geometry::interior_rings(polygon))
)
);
}
};
template <typename MultiPoint>
struct points_begin<MultiPoint, multi_point_tag>
{
static inline typename point_iterator_type<MultiPoint>::type
apply(MultiPoint& multipoint)
{
return boost::begin(multipoint);
}
};
template <typename MultiLinestring>
struct points_begin<MultiLinestring, multi_linestring_tag>
{
static inline typename point_iterator_type<MultiLinestring>::type
apply(MultiLinestring& multilinestring)
{
return typename point_iterator_type
<
MultiLinestring
>::type(boost::begin(multilinestring), boost::end(multilinestring));
}
};
template <typename MultiPolygon>
struct points_begin<MultiPolygon, multi_polygon_tag>
{
static inline typename point_iterator_type<MultiPolygon>::type
apply(MultiPolygon& multipolygon)
{
return typename point_iterator_type
<
MultiPolygon
>::type(boost::begin(multipolygon), boost::end(multipolygon));
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// specializations for points_end
template <typename Linestring>
struct points_end<Linestring, linestring_tag>
{
static inline typename point_iterator_type<Linestring>::type
apply(Linestring& linestring)
{
return boost::end(linestring);
}
};
template <typename Ring>
struct points_end<Ring, ring_tag>
{
static inline typename point_iterator_type<Ring>::type
apply(Ring& ring)
{
return boost::end(ring);
}
};
template <typename Polygon>
struct points_end<Polygon, polygon_tag>
{
typedef typename point_iterator_type<Polygon>::type return_type;
static inline return_type apply(Polygon& polygon)
{
typedef typename return_type::second_iterator_type flatten_iterator;
return return_type
(boost::end(geometry::exterior_ring(polygon)),
flatten_iterator( boost::end(geometry::interior_rings(polygon)) )
);
}
};
template <typename MultiPoint>
struct points_end<MultiPoint, multi_point_tag>
{
static inline typename point_iterator_type<MultiPoint>::type
apply(MultiPoint& multipoint)
{
return boost::end(multipoint);
}
};
template <typename MultiLinestring>
struct points_end<MultiLinestring, multi_linestring_tag>
{
static inline typename point_iterator_type<MultiLinestring>::type
apply(MultiLinestring& multilinestring)
{
return typename point_iterator_type
<
MultiLinestring
>::type(boost::end(multilinestring));
}
};
template <typename MultiPolygon>
struct points_end<MultiPolygon, multi_polygon_tag>
{
static inline typename point_iterator_type<MultiPolygon>::type
apply(MultiPolygon& multipolygon)
{
return typename point_iterator_type
<
MultiPolygon
>::type(boost::end(multipolygon));
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
// MK:: need to add doc here
template <typename Geometry>
class point_iterator
: public dispatch::point_iterator_type<Geometry>::type
{
private:
typedef typename dispatch::point_iterator_type<Geometry>::type base;
base* base_ptr()
{
return this;
}
base const* base_ptr() const
{
return this;
}
template <typename G1, typename G2>
struct is_convertible
: boost::is_convertible
<
typename dispatch::point_iterator_type<G1>::type,
typename dispatch::point_iterator_type<G2>::type
>
{};
struct enabler {};
template <typename OtherGeometry> friend class point_iterator;
template <typename G> friend inline point_iterator<G> points_begin(G&);
template <typename G> friend inline point_iterator<G> points_end(G&);
point_iterator(base const& base_it) : base(base_it) {}
public:
point_iterator() {}
template <typename OtherGeometry>
point_iterator(point_iterator<OtherGeometry> const& other,
typename boost::enable_if
<
is_convertible<OtherGeometry, Geometry>,
enabler
>::type = enabler())
: base(*other.base_ptr())
{}
};
// MK:: need to add doc here
template <typename Geometry>
inline point_iterator<Geometry>
points_begin(Geometry& geometry)
{
return dispatch::points_begin<Geometry>::apply(geometry);
}
// MK:: need to add doc here
template <typename Geometry>
inline point_iterator<Geometry>
points_end(Geometry& geometry)
{
return dispatch::points_end<Geometry>::apply(geometry);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP

View File

@@ -0,0 +1,203 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP
#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP
#include <boost/geometry/iterators/dispatch/point_iterator_type.hpp>
#include <boost/geometry/iterators/dispatch/point_iterator.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/multi/core/tags.hpp>
#include <boost/geometry/iterators/flatten_iterator.hpp>
#include <boost/geometry/iterators/concatenate_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail_dispatch
{
template <typename Geometry>
struct point_iterator_value_type
{
typedef typename boost::mpl::if_c
<
!boost::is_const<Geometry>::type::value,
typename geometry::point_type<Geometry>::type,
typename geometry::point_type<Geometry>::type const
>::type type;
};
template
<
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct point_iterator_inner_range_type
{
typedef typename boost::mpl::if_c
<
!boost::is_const<Geometry>::type::value,
typename boost::range_value<Geometry>::type,
typename boost::range_value<Geometry>::type const
>::type type;
};
template <typename Polygon>
struct point_iterator_inner_range_type<Polygon, polygon_tag>
{
typedef typename boost::mpl::if_c
<
!boost::is_const<Polygon>::type::value,
typename geometry::ring_type<Polygon>::type,
typename geometry::ring_type<Polygon>::type const
>::type type;
};
} // namespace detail_dispatch
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linestring>
struct point_iterator_type<Linestring, linestring_tag>
{
typedef typename boost::range_iterator<Linestring>::type type;
};
template <typename Ring>
struct point_iterator_type<Ring, ring_tag>
{
typedef typename boost::range_iterator<Ring>::type type;
};
template <typename Polygon>
class point_iterator_type<Polygon, polygon_tag>
{
private:
typedef typename detail_dispatch::point_iterator_inner_range_type
<
Polygon
>::type InnerRange;
public:
typedef concatenate_iterator
<
typename boost::range_iterator<InnerRange>::type,
flatten_iterator
<
typename boost::range_iterator
<
typename geometry::interior_type<Polygon>::type
>::type,
typename dispatch::point_iterator_type
<
InnerRange
>::type,
typename detail_dispatch::point_iterator_value_type
<
Polygon
>::type,
dispatch::points_begin<InnerRange>,
dispatch::points_end<InnerRange>
>,
typename detail_dispatch::point_iterator_value_type<Polygon>::type
> type;
};
template <typename MultiPoint>
struct point_iterator_type<MultiPoint, multi_point_tag>
{
typedef typename boost::range_iterator<MultiPoint>::type type;
};
template <typename MultiLinestring>
class point_iterator_type<MultiLinestring, multi_linestring_tag>
{
private:
typedef typename detail_dispatch::point_iterator_inner_range_type
<
MultiLinestring
>::type InnerRange;
public:
typedef flatten_iterator
<
typename boost::range_iterator<MultiLinestring>::type,
typename dispatch::point_iterator_type<InnerRange>::type,
typename detail_dispatch::point_iterator_value_type
<
MultiLinestring
>::type,
dispatch::points_begin<InnerRange>,
dispatch::points_end<InnerRange>
> type;
};
template <typename MultiPolygon>
class point_iterator_type<MultiPolygon, multi_polygon_tag>
{
private:
typedef typename detail_dispatch::point_iterator_inner_range_type
<
MultiPolygon
>::type InnerRange;
public:
typedef flatten_iterator
<
typename boost::range_iterator<MultiPolygon>::type,
typename dispatch::point_iterator_type<InnerRange>::type,
typename detail_dispatch::point_iterator_value_type
<
MultiPolygon
>::type,
dispatch::points_begin<InnerRange>,
dispatch::points_end<InnerRange>
> type;
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_TYPE_HPP

View File

@@ -81,7 +81,8 @@ struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point,
MultiPolygon const& multi_polygon, Strategy const& strategy)
MultiPolygon const& multi_polygon,
Strategy const& strategy)
{
return detail::within::geometry_multi_within_code
<
@@ -101,12 +102,25 @@ struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point,
MultiLinestring const& multi_linestring, Strategy const& strategy)
MultiLinestring const& multi_linestring,
Strategy const& strategy)
{
return detail::within::point_in_geometry(point, multi_linestring, strategy) == 1;
}
};
template <typename Point, typename MultiPoint>
struct within<Point, MultiPoint, point_tag, multi_point_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point,
MultiPoint const& multi_point,
Strategy const& strategy)
{
return detail::within::point_in_geometry(point, multi_point, strategy) == 1;
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@@ -21,6 +21,7 @@
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
@@ -28,37 +29,6 @@ namespace boost { namespace geometry
namespace policies { namespace relate
{
template <typename Result, bool IsInteger = std::numeric_limits<Result>::is_integer>
struct round_dispatch
{
template <typename T>
static inline Result apply(T const& v)
{
return v < 0 ?
boost::numeric_cast<Result>(ceil(v - 0.5f)) :
boost::numeric_cast<Result>(floor(v + 0.5f));
}
};
template <typename Result>
struct round_dispatch<Result, false>
{
template <typename T>
static inline Result apply(T const& v)
{
return boost::numeric_cast<Result>(v);
}
};
template <typename Result, typename T>
inline Result round(T const& v)
{
// NOTE: boost::round() could be used instead but it throws in some situations
//BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_integer);
return round_dispatch<Result>::apply(v);
}
template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
struct segments_intersection_points
{
@@ -89,9 +59,9 @@ struct segments_intersection_points
return_type result;
result.count = 1;
set<0>(result.intersections[0],
round<return_coordinate_type>(R(s1x) + r * R(dx1)));
geometry::math::round<return_coordinate_type>(R(s1x) + r * R(dx1)));
set<1>(result.intersections[0],
round<return_coordinate_type>(R(s1y) + r * R(dy1)));
geometry::math::round<return_coordinate_type>(R(s1y) + r * R(dy1)));
return result;
}

View File

@@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013.
// Modifications copyright (c) 2013, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -13,6 +13,8 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
@@ -198,23 +200,30 @@ struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag,
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used
template <typename Point, typename Geometry>
struct default_strategy<point_tag, linestring_tag, point_tag, linestring_tag, cartesian_tag, cartesian_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry>
struct default_strategy<point_tag, linestring_tag, point_tag, linestring_tag, spherical_tag, spherical_tag, Point, Geometry>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
// TODO: later move it to multi/strategies/agnostic
template <typename Point, typename Geometry>
struct default_strategy<point_tag, multi_linestring_tag, point_tag, multi_linestring_tag, cartesian_tag, cartesian_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Linestring1, typename Linestring2>
struct default_strategy<linestring_tag, linestring_tag, linestring_tag, linestring_tag, cartesian_tag, cartesian_tag, Linestring1, Linestring2>
template <typename Point, typename Geometry>
struct default_strategy<point_tag, multi_linestring_tag, point_tag, multi_linestring_tag, spherical_tag, spherical_tag, Point, Geometry>
{
typedef strategy::within::winding<typename geometry::point_type<Linestring1>::type, typename geometry::point_type<Linestring2>::type> type;
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
} // namespace services
@@ -243,19 +252,32 @@ struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag,
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used
template <typename Point, typename Geometry>
struct default_strategy<point_tag, linestring_tag, point_tag, linestring_tag, cartesian_tag, cartesian_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
// TODO: later move it to multi/strategies/agnostic
template <typename Point, typename Geometry>
struct default_strategy<point_tag, linestring_tag, point_tag, linestring_tag, spherical_tag, spherical_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry>
struct default_strategy<point_tag, multi_linestring_tag, point_tag, multi_linestring_tag, cartesian_tag, cartesian_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry>
struct default_strategy<point_tag, multi_linestring_tag, point_tag, multi_linestring_tag, spherical_tag, spherical_tag, Point, Geometry>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
}}} // namespace strategy::covered_by::services
#endif

View File

@@ -0,0 +1,207 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014 Oracle and/or its affiliates.
// 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)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
#include <boost/geometry/algorithms/detail/relate/relate.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace relate
{
template <typename StaticMask>
struct relate
{
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return detail::relate::relate<StaticMask>(geometry1, geometry2);
}
};
} // namespace relate
namespace within
{
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
// P/L
//template <typename Point, typename Linestring, typename AnyCS1, typename AnyCS2>
//struct default_strategy<point_tag, linestring_tag, point_tag, linestring_tag, AnyCS1, AnyCS2, Point, Linestring>
//{
// typedef strategy::relate::relate<detail::relate::static_mask_within> type;
//};
//
//template <typename Point, typename MultiLinestring, typename AnyCS1, typename AnyCS2>
//struct default_strategy<point_tag, multi_linestring_tag, point_tag, multi_linestring_tag, AnyCS1, AnyCS2, Point, MultiLinestring>
//{
// typedef strategy::relate::relate<detail::relate::static_mask_within> type;
//};
// L/L
template <typename Linestring1, typename Linestring2, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, linestring_tag, linestring_tag, linestring_tag, AnyCS1, AnyCS2, Linestring1, Linestring2>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
template <typename Linestring, typename MultiLinestring, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, multi_linestring_tag, linestring_tag, multi_linestring_tag, AnyCS1, AnyCS2, Linestring, MultiLinestring>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
template <typename MultiLinestring, typename Linestring, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, linestring_tag, multi_linestring_tag, linestring_tag, AnyCS1, AnyCS2, MultiLinestring, Linestring>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
// L/A
template <typename Linestring, typename Ring, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, ring_tag, linestring_tag, areal_tag, AnyCS1, AnyCS2, Linestring, Ring>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
template <typename MultiLinestring, typename Ring, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, ring_tag, multi_linestring_tag, areal_tag, AnyCS1, AnyCS2, MultiLinestring, Ring>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
template <typename Linestring, typename Polygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, polygon_tag, linestring_tag, areal_tag, AnyCS1, AnyCS2, Linestring, Polygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
template <typename MultiLinestring, typename Polygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, polygon_tag, multi_linestring_tag, areal_tag, AnyCS1, AnyCS2, MultiLinestring, Polygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
template <typename Linestring, typename MultiPolygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, multi_polygon_tag, linestring_tag, areal_tag, AnyCS1, AnyCS2, Linestring, MultiPolygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
template <typename MultiLinestring, typename MultiPolygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, multi_polygon_tag, multi_linestring_tag, areal_tag, AnyCS1, AnyCS2, MultiLinestring, MultiPolygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_within> type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
// P/L
//template <typename Point, typename Linestring, typename AnyCS1, typename AnyCS2>
//struct default_strategy<point_tag, linestring_tag, point_tag, linestring_tag, AnyCS1, AnyCS2, Point, Linestring>
//{
// typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
//};
//
//template <typename Point, typename MultiLinestring, typename AnyCS1, typename AnyCS2>
//struct default_strategy<point_tag, multi_linestring_tag, point_tag, multi_linestring_tag, AnyCS1, AnyCS2, Point, MultiLinestring>
//{
// typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
//};
// L/L
template <typename Linestring1, typename Linestring2, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, linestring_tag, linestring_tag, linestring_tag, AnyCS1, AnyCS2, Linestring1, Linestring2>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
template <typename Linestring, typename MultiLinestring, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, multi_linestring_tag, linestring_tag, multi_linestring_tag, AnyCS1, AnyCS2, Linestring, MultiLinestring>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
template <typename MultiLinestring, typename Linestring, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, linestring_tag, multi_linestring_tag, linestring_tag, AnyCS1, AnyCS2, MultiLinestring, Linestring>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
// L/A
template <typename Linestring, typename Ring, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, ring_tag, linestring_tag, areal_tag, AnyCS1, AnyCS2, Linestring, Ring>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
template <typename MultiLinestring, typename Ring, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, ring_tag, multi_linestring_tag, areal_tag, AnyCS1, AnyCS2, MultiLinestring, Ring>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
template <typename Linestring, typename Polygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, polygon_tag, linestring_tag, areal_tag, AnyCS1, AnyCS2, Linestring, Polygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
template <typename MultiLinestring, typename Polygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, polygon_tag, multi_linestring_tag, areal_tag, AnyCS1, AnyCS2, MultiLinestring, Polygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
template <typename Linestring, typename MultiPolygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<linestring_tag, multi_polygon_tag, linestring_tag, areal_tag, AnyCS1, AnyCS2, Linestring, MultiPolygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
template <typename MultiLinestring, typename MultiPolygon, typename AnyCS1, typename AnyCS2>
struct default_strategy<multi_linestring_tag, multi_polygon_tag, multi_linestring_tag, areal_tag, AnyCS1, AnyCS2, MultiLinestring, MultiPolygon>
{
typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP

View File

@@ -55,6 +55,8 @@
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
#include <boost/geometry/strategies/agnostic/relate.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>

View File

@@ -111,6 +111,29 @@ struct relaxed_epsilon
}
};
// ItoF ItoI FtoF
template <typename Result, typename Source,
bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
struct round
{
static inline Result apply(Source const& v)
{
return boost::numeric_cast<Result>(v);
}
};
// FtoI
template <typename Result, typename Source>
struct round<Result, Source, true, false>
{
static inline Result apply(Source const& v)
{
return v < 0
? boost::numeric_cast<Result>(ceil(v - 0.5f))
: boost::numeric_cast<Result>(floor(v + 0.5f));
}
};
} // namespace detail
#endif
@@ -239,6 +262,19 @@ static inline int sign(T const& value)
return value > zero ? 1 : value < zero ? -1 : 0;
}
/*!
\brief Short utility to calculate the rounded value of a number.
\ingroup utility
\note If the source T is NOT an integral type and Result is an integral type
the value is rounded towards the closest integral value. Otherwise it's
just casted.
*/
template <typename Result, typename T>
inline Result round(T const& v)
{
// NOTE: boost::round() could be used instead but it throws in some situations
return detail::round<Result, T>::apply(v);
}
} // namespace math

View File

@@ -0,0 +1,110 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
// 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)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
#define BOOST_GEOMETRY_UTIL_RANGE_HPP
#include <boost/concept_check.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/size.hpp>
namespace boost { namespace geometry { namespace range {
// NOTE: For SinglePassRanges at could iterate over all elements until the i-th element is met.
/*!
\brief Short utility to conveniently return an element of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_value<RandomAccessRange const>::type const&
at(RandomAccessRange const& rng,
typename boost::range_size<RandomAccessRange const>::type i)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange const> ));
BOOST_ASSERT(i < boost::size(rng));
return *(boost::begin(rng) + i);
}
/*!
\brief Short utility to conveniently return an element of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_value<RandomAccessRange>::type &
at(RandomAccessRange & rng,
typename boost::range_size<RandomAccessRange>::type i)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));
BOOST_ASSERT(i < boost::size(rng));
return *(boost::begin(rng) + i);
}
/*!
\brief Short utility to conveniently return the front element of a Range.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_value<Range>::type const&
front(Range const& rng)
{
BOOST_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
/*!
\brief Short utility to conveniently return the front element of a Range.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_value<Range>::type &
front(Range & rng)
{
BOOST_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
// NOTE: For SinglePassRanges back() could iterate over all elements until the last element is met.
/*!
\brief Short utility to conveniently return the back element of a BidirectionalRange.
\ingroup utility
*/
template <typename BidirectionalRange>
inline typename boost::range_value<BidirectionalRange>::type const&
back(BidirectionalRange const& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));
BOOST_ASSERT(!boost::empty(rng));
return *(--boost::end(rng));
}
/*!
\brief Short utility to conveniently return the back element of a BidirectionalRange.
\ingroup utility
*/
template <typename BidirectionalRange>
inline typename boost::range_value<BidirectionalRange>::type &
back(BidirectionalRange & rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange> ));
BOOST_ASSERT(!boost::empty(rng));
return *(--boost::end(rng));
}
}}} // namespace boost::geometry::range
#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP

View File

@@ -61,13 +61,11 @@ void test_sectionalize_part()
bg::detail::no_rescale_policy rescale_policy;
bg::ring_identifier ring_id;
int index = 0;
int ndi = 0;
sectionalize_part::apply(sections, section, index, ndi, geometry, rescale_policy, false, ring_id, 10);
sectionalize_part::apply(sections, geometry, rescale_policy, false, ring_id, 10);
// There should not yet be anything generated, because it is only ONE point
geometry.push_back(bg::make<point_type>(2, 2));
sectionalize_part::apply(sections, section, index, ndi, geometry, rescale_policy, false, ring_id, 10);
sectionalize_part::apply(sections, geometry, rescale_policy, false, ring_id, 10);
}

View File

@@ -198,6 +198,14 @@ void test_areal()
ggl_list_20131119_james[0], ggl_list_20131119_james[1],
1, 4, 6.6125873045, 0.1);
#if 0
// TODO: fix this testcase, it should give 0 but instead it gives one of the input polygons
// Mailed to the Boost.Geometry list on 2014/03/21 by 7415963@gmail.com
test_one<Polygon, Polygon, Polygon>("ggl_list_20140321_7415963",
ggl_list_20140321_7415963[0], ggl_list_20140321_7415963[1],
0, 0, 0, 0.1);
#endif
test_one<Polygon, Polygon, Polygon>("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1],
1, 4, 0.00029437899183903937, 0.01);

View File

@@ -20,6 +20,7 @@ test-suite boost-geometry-algorithms-overlay
[ run get_turn_info.cpp ]
[ run get_turns.cpp ]
[ run get_turns_linear_linear.cpp ]
[ run get_turns_linear_areal.cpp ]
[ run relative_order.cpp ]
[ run select_rings.cpp ]
[ run self_intersection_points.cpp ]

View File

@@ -51,7 +51,7 @@ void test_with_point(std::string const& caseid,
<
bg::detail::overlay::assign_null_policy
>::apply(pi, pj, pk, qi, qj, qk,
10, 10, // dummy max numbers of segments
false, false, false, false, // dummy parameters
model, bg::detail::no_rescale_policy(), std::back_inserter(info));

View File

@@ -538,6 +538,12 @@ static std::string ggl_list_20131119_james[2] =
};
static std::string ggl_list_20140321_7415963[2] =
{
"POLYGON((-6.0 3.2500000000000013, -9.0 3.2500000000000022, -9.0 6.5, -6.0 6.5, -6.0 3.2500000000000013))",
"POLYGON((-3.0 0.0, -6.0 0.0, -6.0 3.2500000000000013, -3.0 3.2500000000000009, -3.0 0.0))",
};
// GEOS "TestOverlay" test.
// Note that the first one WAS invalid and is made valid using SQL Server 2008 Spatial MakeValid() function
static std::string geos_1_test_overlay[2] =

View File

@@ -152,8 +152,8 @@ struct expected_pusher
typedef std::vector<std::string>::iterator iterator;
typedef std::vector<std::string>::const_iterator const_iterator;
//iterator begin() { return vec.begin(); }
//iterator end() { return vec.end(); }
iterator begin() { return vec.begin(); }
iterator end() { return vec.end(); }
const_iterator begin() const { return vec.begin(); }
const_iterator end() const { return vec.end(); }

View File

@@ -40,7 +40,7 @@
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
//TEST
#include <to_svg.hpp>
//#include <to_svg.hpp>
namespace bgdr = bg::detail::relate;
@@ -75,8 +75,8 @@ void check_geometry(Geometry1 const& geometry1,
std::string expected_tr = transposed(expected);
bool ok = boost::equal(res_str, expected_tr);
BOOST_CHECK_MESSAGE(ok,
"relate: " << wkt1
<< " and " << wkt2
"relate: " << wkt2
<< " and " << wkt1
<< " -> Expected: " << expected_tr
<< " detected: " << res_str);
}
@@ -251,9 +251,14 @@ void test_linestring_linestring()
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,1 1,5 3)", "LINESTRING(6 3,3 3,0 0)", "1F100F102");
test_geometry<ls, ls>("LINESTRING(5 3,1 1,3 3,2 2,0 0)", "LINESTRING(6 3,3 3,0 0)", "1F100F102");
// spike
test_geometry<ls, ls>("LINESTRING(0 0,10 0)",
// spikes
// FOR NOW DISABLED
/*test_geometry<ls, ls>("LINESTRING(0 0,10 0)",
"LINESTRING(1 0,9 0,2 0)", "101FF0FF2");
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,3 3,6 3)", "1FF00F102");
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", "1FF00F102");*/
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,4 4)", "LINESTRING(0 0,1 1,4 4)", "1FFF0FFF2");
// loop i/i i/i u/u u/u
test_geometry<ls, ls>("LINESTRING(0 0,10 0)",
@@ -313,6 +318,10 @@ void test_linestring_linestring()
test_geometry<ls, ls>("LINESTRING(1 0,5 0,7 0,8 1)", "LINESTRING(0 0,10 0,10 10,4 -1)",
"1F10F0102");
// duplicated points
test_geometry<ls, ls>("LINESTRING(1 1, 2 2, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", "1FF0FF102");
test_geometry<ls, ls>("LINESTRING(1 1, 1 1, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", "1FF0FF102");
// linear ring
test_geometry<ls, ls>("LINESTRING(0 0,10 0)", "LINESTRING(5 0,9 0,5 5,1 0,5 0)", "1F1FF01F2");
test_geometry<ls, ls>("LINESTRING(0 0,5 0,10 0)", "LINESTRING(5 0,9 0,5 5,1 0,5 0)", "1F1FF01F2");
@@ -426,8 +435,28 @@ void test_linestring_polygon()
// IB1 IE
test_geometry<ls, poly>("LINESTRING(10 10,10 5,15 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "F11F00212");
// II IB0 IE
test_geometry<ls, poly>("LINESTRING(5 5,10 5,15 10)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212");
// duplicated points
{
// II IB0 IE
test_geometry<ls, poly>("LINESTRING(5 5,10 5,15 10)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212");
test_geometry<ls, poly>("LINESTRING(5 5,5 5,5 5,10 5,10 5,10 5,15 10,15 10,15 10)",
"POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))",
"1010F0212");
test_geometry<ls, poly>("LINESTRING(5 5,5 5,5 5,10 0,10 0,10 0,15 10,15 10,15 10)",
"POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))",
"1010F0212");
// IE IB0 II
test_geometry<ls, poly>("LINESTRING(15 10,15 10,15 10,10 5,10 5,10 5,5 5,5 5,5 5)",
"POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))",
"1010F0212");
test_geometry<ls, poly>("LINESTRING(15 10,15 10,15 10,10 0,10 0,10 0,5 5,5 5,5 5)",
"POLYGON((0 0,0 0,0 0,0 10,0 10,0 10,10 10,10 10,10 10,10 0,10 0,10 0,0 0,0 0,0 0))",
"1010F0212");
// TEST
//test_geometry<ls, poly>("LINESTRING(5 5,5 5,5 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212");
test_geometry<ls, poly>("LINESTRING(5 5,5 5,5 5,15 5,15 5,15 5)", "POLYGON((0 0,0 10,10 10,10 0,0 0))", "1010F0212");
}
// non-simple polygon with hole
test_geometry<ls, poly>("LINESTRING(9 1,10 5,9 9)",

View File

@@ -29,8 +29,6 @@ void test_linestring_linestring()
test_geometry<ls, ls>("LINESTRING(1 1, 2 2, 3 2)", "LINESTRING(4 2, 2 2, 0 0)", true);
test_geometry<ls, ls>("LINESTRING(3 2, 2 2, 1 1)", "LINESTRING(4 2, 2 2, 0 0)", true);
test_geometry<ls, ls>("LINESTRING(1 1, 2 2, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true);
test_geometry<ls, ls>("LINESTRING(1 1, 2 2, 3 3)", "LINESTRING(0 0, 2 2, 4 2)", false);
test_geometry<ls, ls>("LINESTRING(1 1, 2 2, 3 2, 3 3)", "LINESTRING(0 0, 2 2, 4 2)", false);
test_geometry<ls, ls>("LINESTRING(1 1, 2 2, 3 1)", "LINESTRING(0 0, 2 2, 4 2)", false);
@@ -41,14 +39,30 @@ void test_linestring_linestring()
test_geometry<ls, ls>("LINESTRING(1 0, 1 1, 2 2, 3 2)", "LINESTRING(0 0, 2 2, 4 2)", false);
test_geometry<ls, ls>("LINESTRING(1 0, 0 0, 2 2, 3 2)", "LINESTRING(0 0, 2 2, 4 2)", false);
test_geometry<ls, ls>("LINESTRING(0 0)", "LINESTRING(0 0)", false);
test_geometry<ls, ls>("LINESTRING(1 1)", "LINESTRING(0 0, 2 2)", true);
test_geometry<ls, ls>("LINESTRING(0 0)", "LINESTRING(0 0, 2 2)", false);
test_geometry<ls, ls>("LINESTRING(0 0, 1 1)", "LINESTRING(0 0)", false);
// duplicated points
test_geometry<ls, ls>("LINESTRING(1 1, 2 2, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true);
test_geometry<ls, ls>("LINESTRING(1 1, 1 1, 2 2)", "LINESTRING(0 0, 2 2, 4 2)", true);
test_geometry<ls, ls>("LINESTRING(0 0, 0 0, 0 0, 1 1, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 2 2, 3 3)",
"LINESTRING(0 0, 2 2, 4 4)", true);
// invalid linestrings
// test_geometry<ls, ls>("LINESTRING(0 0)", "LINESTRING(0 0)", false);
// test_geometry<ls, ls>("LINESTRING(1 1)", "LINESTRING(0 0, 2 2)", true);
// test_geometry<ls, ls>("LINESTRING(0 0)", "LINESTRING(0 0, 2 2)", false);
// test_geometry<ls, ls>("LINESTRING(0 0, 1 1)", "LINESTRING(0 0)", false);
// spikes
// FOR NOW DISABLED
/*test_geometry<ls, ls>("LINESTRING(0 0,5 0,3 0,6 0)", "LINESTRING(0 0,6 0)", true);
test_geometry<ls, ls>("LINESTRING(0 0,5 0,3 0,6 0)", "LINESTRING(0 0,6 0)", true);
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,3 3,6 3)", true);
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,1 1,5 3)", "LINESTRING(0 0,3 3,6 3)", false);
test_geometry<ls, ls>("LINESTRING(0 0,3 3,6 3)", "LINESTRING(0 0,2 2,3 3,1 1)", false);
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,1 1)", "LINESTRING(0 0,4 4,6 3)", true);
test_geometry<ls, ls>("LINESTRING(0 0,4 4,6 3)", "LINESTRING(0 0,2 2,3 3,1 1)", false);
test_geometry<ls, ls>("LINESTRING(0 0,2 2,3 3,1 1,5 3)", "LINESTRING(0 0,3 3,6 3)", false);*/
}
template <typename P>

View File

@@ -1,8 +1,13 @@
# Boost.Geometry (aka GGL, Generic Geometry Library)
#
# Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
#
# This file was modified by Oracle on 2014.
# Modifications copyright (c) 2014, Oracle and/or its affiliates.
#
# Contributed and/or modified by Menelaos Karavelas, 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
@@ -12,4 +17,7 @@ test-suite boost-geometry-iterators
:
[ run closing_iterator.cpp ]
[ run ever_circling_iterator.cpp ]
[ run point_iterator.cpp ]
[ run concatenate_iterator.cpp ]
[ run flatten_iterator.cpp ]
;

View File

@@ -0,0 +1,260 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, 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_concatenate_iterator
#endif
#include <boost/test/included/unit_test.hpp>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <list>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/list.hpp>
#include <boost/geometry/iterators/concatenate_iterator.hpp>
using namespace boost::assign;
template <typename Iterator>
std::ostream& print_container(std::ostream& os,
Iterator begin, Iterator end,
std::string const& header)
{
std::cout << header;
for (Iterator it = begin; it != end; ++it)
{
os << " " << *it;
}
return os;
}
template <typename T>
struct is_odd
{
inline bool operator()(T const& t) const
{
return t % 2 != 0;
}
};
struct test_concatenate_iterator
{
template <typename Container1, typename Container2>
static inline void apply(Container1& c1, Container2& c2,
std::string const& case_id)
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "case id: " << case_id << std::endl;
#endif
typedef typename Container1::const_iterator const_iterator1;
typedef typename Container2::const_iterator const_iterator2;
typedef typename Container1::iterator iterator1;
typedef typename Container2::iterator iterator2;
typedef boost::geometry::concatenate_iterator
<
const_iterator1, const_iterator2,
typename Container1::value_type const
> const_concat_iterator;
typedef boost::geometry::concatenate_iterator
<
iterator1, iterator2, typename Container1::value_type
> concat_iterator;
concat_iterator begin(c1.begin(), c1.end(), c2.begin());
concat_iterator end(c1.end(), c2.end());
const_concat_iterator const_begin(begin);
const_concat_iterator const_end(end);
const_begin = begin;
const_end = end;
std::size_t size(0);
for (const_concat_iterator it = const_begin; it != const_end; ++it)
{
++size;
}
BOOST_CHECK( c1.size() + c2.size() == size );
size = 0;
for (concat_iterator it = begin; it != end; ++it)
{
++size;
}
BOOST_CHECK( c1.size() + c2.size() == size );
#ifdef GEOMETRY_TEST_DEBUG
print_container(std::cout, c1.begin(), c1.end(), "first :")
<< std::endl;
print_container(std::cout, c2.begin(), c2.end(), "second :")
<< std::endl;
print_container(std::cout, begin, end, "combined:")
<< std::endl;
if ( begin != end )
{
std::cout << "min element: "
<< *std::min_element(begin, end)
<< std::endl;
std::cout << "max element: "
<< *std::max_element(const_begin, const_end)
<< std::endl;
}
#endif
{
const_iterator1 it1 = c1.begin();
const_iterator2 it2 = c2.begin();
for (const_concat_iterator it = const_begin; it != const_end; ++it)
{
if ( it1 != c1.end() )
{
BOOST_CHECK( *it == *it1 );
++it1;
}
else
{
BOOST_CHECK( *it == *it2 );
++it2;
}
}
}
typedef typename std::iterator_traits
<
concat_iterator
>::value_type value_type;
if ( c1.size() != 0 )
{
concat_iterator it_max = std::max_element(begin, end);
const_concat_iterator const_it_max =
std::max_element(const_begin, const_end);
BOOST_CHECK( it_max == const_it_max );
value_type old_value = *const_begin;
value_type new_value = *it_max + 1;
*begin = *it_max + 1;
BOOST_CHECK( *c1.begin() == new_value );
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "modified element of 1st container:" << std::endl;
print_container(std::cout, c1.begin(), c1.end(), "first :")
<< std::endl;
print_container(std::cout, begin, end, "combined:")
<< std::endl;
#endif
*begin = old_value;
BOOST_CHECK( *c1.begin() == old_value );
}
if ( c2.size() != 0 )
{
concat_iterator begin2 = begin;
std::size_t counter(0);
while ( counter != c1.size() )
{
++counter;
begin2++;
}
concat_iterator it_max = std::max_element(begin, end);
const_concat_iterator const_it_max =
std::max_element(const_begin, const_end);
BOOST_CHECK( it_max == const_it_max );
value_type old_value = *begin2;
value_type new_value = *it_max + 1;
*begin2 = *it_max + 1;
BOOST_CHECK( *c2.begin() == new_value );
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "modified element of 2nd container:" << std::endl;
print_container(std::cout, c2.begin(), c2.end(), "second :")
<< std::endl;
print_container(std::cout, begin, end, "combined:")
<< std::endl;
#endif
*begin2 = old_value;
BOOST_CHECK( *c2.begin() == old_value );
}
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "odd elements removed:" << std::endl;
print_container(std::cout, begin, end, "before:")
<< std::endl;
#endif
concat_iterator new_end =
std::remove_if(begin, end, is_odd<value_type>());
for (const_concat_iterator it = const_begin; it != new_end; ++it)
{
BOOST_CHECK( !is_odd<value_type>()(*it) );
}
#ifdef GEOMETRY_TEST_DEBUG
print_container(std::cout, begin, new_end, "after :")
<< std::endl;
#endif
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "====================" << std::endl << std::endl;
#endif
}
};
BOOST_AUTO_TEST_CASE( test_concatenate_iterator_all )
{
{
std::vector<int> v;
std::list<int> l;
test_concatenate_iterator::apply(v, l, "empty_both");
}
{
std::vector<int> v;
std::list<int> l;
l += 10,11,12,13,14,15,16,17,18,19,20;
test_concatenate_iterator::apply(v, l, "empty_first");
}
{
std::vector<int> v;
v += 0,1,2,3,4,5,6;
std::list<int> l;
test_concatenate_iterator::apply(v, l, "empty_second");
}
{
std::vector<int> v;
v += 0,1,2,3,4,5,6;
std::list<int> l;
l += 10,11,12,13,14,15,16,17,18,19,20;
test_concatenate_iterator::apply(l, v, "non_empty");
}
}

View File

@@ -0,0 +1,430 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, 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_flatten_iterator
#endif
#include <boost/test/included/unit_test.hpp>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <list>
#include <boost/mpl/if.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/list.hpp>
#include <boost/assign/std/set.hpp>
#include <boost/geometry/iterators/flatten_iterator.hpp>
using namespace boost::assign;
template <typename Iterator>
std::ostream& print_container(std::ostream& os,
Iterator begin, Iterator end,
std::string const& header)
{
std::cout << header;
for (Iterator it = begin; it != end; ++it)
{
os << " " << *it;
}
return os;
}
template <typename Iterator>
std::ostream& print_nested_container(std::ostream& os,
Iterator begin, Iterator end,
std::string const& header)
{
std::cout << header;
for (Iterator outer = begin; outer != end; ++outer)
{
os << " (";
for (BOOST_AUTO_TPL(inner, outer->begin());
inner != outer->end(); ++inner)
{
if ( inner != outer->begin() )
{
os << " ";
}
os << *inner;
}
os << ") ";
}
return os;
}
template <typename T>
struct is_odd
{
inline bool operator()(T const& t) const
{
return t % 2 != 0;
}
};
template <typename T>
struct is_even
{
inline bool operator()(T const& t) const
{
return !is_odd<T>()(t);
}
};
template <typename InnerContainer>
struct access_begin
{
typedef typename boost::mpl::if_
<
typename boost::is_const<InnerContainer>::type,
typename InnerContainer::const_iterator,
typename InnerContainer::iterator
>::type return_type;
static inline return_type apply(InnerContainer& inner)
{
return inner.begin();
}
};
template <typename InnerContainer>
struct access_end
{
typedef typename boost::mpl::if_
<
typename boost::is_const<InnerContainer>::type,
typename InnerContainer::const_iterator,
typename InnerContainer::iterator
>::type return_type;
static inline return_type apply(InnerContainer& inner)
{
return inner.end();
}
};
template <typename NestedContainer>
std::size_t number_of_elements(NestedContainer const& c)
{
std::size_t num_elements(0);
for (typename NestedContainer::const_iterator outer = c.begin();
outer != c.end(); ++outer)
{
num_elements += outer->size();
}
return num_elements;
}
struct test_flatten_iterator
{
template <typename NestedContainer>
static inline void apply(NestedContainer& c,
std::string const& case_id,
std::string const& container_id)
{
#ifdef GEOMETRY_TEST_DEBUG
std::stringstream sstream;
sstream << case_id << " " << "[" << container_id << "]";
std::cout << "case id: " << sstream.str() << std::endl;
#endif
typedef typename NestedContainer::const_iterator const_outer_iterator;
typedef typename NestedContainer::iterator outer_iterator;
typedef typename NestedContainer::value_type inner_container;
typedef typename inner_container::const_iterator const_inner_iterator;
typedef typename inner_container::iterator inner_iterator;
typedef boost::geometry::flatten_iterator
<
const_outer_iterator,
const_inner_iterator,
typename inner_container::value_type const,
access_begin<inner_container const>,
access_end<inner_container const>
> const_flatten_iterator;
typedef boost::geometry::flatten_iterator
<
outer_iterator,
inner_iterator,
typename inner_container::value_type,
access_begin<inner_container>,
access_end<inner_container>
> flatten_iterator;
flatten_iterator begin(c.begin(), c.end());
flatten_iterator end(c.end());
const_flatten_iterator const_begin(begin);
const_flatten_iterator const_end(end);
const_begin = begin;
const_end = end;
std::size_t size(0);
for (const_flatten_iterator it = const_begin; it != const_end; ++it)
{
++size;
}
BOOST_CHECK( number_of_elements(c) == size );
size = 0;
for (flatten_iterator it = begin; it != end; ++it)
{
++size;
}
BOOST_CHECK( number_of_elements(c) == size );
#ifdef GEOMETRY_TEST_DEBUG
print_nested_container(std::cout, c.begin(), c.end(), "nested :")
<< std::endl;
print_container(std::cout, begin, end, "flattened :")
<< std::endl;
if ( begin != end )
{
std::cout << "min element: "
<< *std::min_element(begin, end)
<< std::endl;
std::cout << "max element: "
<< *std::max_element(const_begin, const_end)
<< std::endl;
}
#endif
{
const_flatten_iterator it = begin;
const_outer_iterator outer_begin = c.begin();
const_outer_iterator outer_end = c.end();
for (const_outer_iterator outer = outer_begin;
outer != outer_end; ++outer)
{
const_inner_iterator inner_begin = outer->begin();
const_inner_iterator inner_end = outer->end();
for (const_inner_iterator inner = inner_begin;
inner != inner_end; ++inner, it++)
// it++, instead of ++it, on purpose here
{
BOOST_CHECK( *it == *inner );
}
}
}
typedef typename std::iterator_traits
<
flatten_iterator
>::value_type value_type;
if ( begin != end )
{
flatten_iterator it_max = std::max_element(begin, end);
const_flatten_iterator const_it_max =
std::max_element(const_begin, const_end);
BOOST_CHECK( it_max == const_it_max );
BOOST_CHECK( *it_max == *const_it_max );
value_type old_value = *const_begin;
value_type new_value = *it_max + 1;
*begin = *it_max + 1;
const_outer_iterator outer = c.begin();
while ( outer->begin() == outer->end() )
{
++outer;
}
const_inner_iterator inner = outer->begin();
BOOST_CHECK( *inner == new_value );
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "modified 1st element of 1st non-empty "
<< "inner container:" << std::endl;
print_nested_container(std::cout, c.begin(), c.end(), "nested :")
<< std::endl;
print_container(std::cout, begin, end, "flattened:")
<< std::endl;
#endif
*begin = old_value;
BOOST_CHECK( *inner == old_value );
}
if ( begin != end )
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "odd elements removed:" << std::endl;
print_nested_container(std::cout, c.begin(), c.end(),
"nested before:")
<< std::endl;
print_container(std::cout, begin, end,
"flattended before:")
<< std::endl;
#endif
typename std::iterator_traits<flatten_iterator>::difference_type
num_even = std::count_if(begin, end, is_even<int>());
flatten_iterator new_end =
std::remove_if(begin, end, is_odd<value_type>());
std::size_t new_size(0);
for (const_flatten_iterator it = const_begin; it != new_end; ++it)
{
++new_size;
BOOST_CHECK( !is_odd<value_type>()(*it) );
}
BOOST_CHECK( new_size == static_cast<std::size_t>(num_even) );
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
print_nested_container(std::cout, c.begin(), c.end(),
"nested after (all elements) :")
<< std::endl;
print_container(std::cout, begin, new_end, "flattened after :")
<< std::endl;
#endif
}
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "====================" << std::endl << std::endl;
#endif
}
};
// the actual test cases -- START
template <int CaseNumber>
struct test_case_per_container;
template<>
struct test_case_per_container<0>
{
template <typename NestedContainer>
static inline void apply(std::string const& case_id,
std::string const& container_id)
{
NestedContainer c;
test_flatten_iterator::apply(c, case_id, container_id);
}
};
template<>
struct test_case_per_container<1>
{
template <typename NestedContainer>
static inline void apply(std::string const& case_id,
std::string const& container_id)
{
NestedContainer c;
for (int i = 0; i < 5; ++i)
{
c += typename NestedContainer::value_type();
}
test_flatten_iterator::apply(c, case_id, container_id);
}
};
template<>
struct test_case_per_container<2>
{
template <typename NestedContainer>
static inline void apply(std::string const& case_id,
std::string const& container_id)
{
NestedContainer c;
typename NestedContainer::value_type ic[4];
ic[0] += 5,4,3,2,1;
ic[1] += 6,7,8;
ic[2] += 9;
ic[3] += 9,8,7,6,5;
c += ic[0],ic[1],ic[2],ic[3];
test_flatten_iterator::apply(c, case_id, container_id);
}
};
template<>
struct test_case_per_container<3>
{
template <typename NestedContainer>
static inline void apply(std::string const& case_id,
std::string const& container_id)
{
NestedContainer c;
typename NestedContainer::value_type ic[20];
ic[2] += 5,4,3,2,1;
ic[3] += 6,7,8;
ic[8] += 9;
ic[9] += 9,8,7,6,5;
ic[14] += 4,3,2,1;
for (std::size_t i = 0; i < 20; ++i)
{
c += ic[i];
}
test_flatten_iterator::apply(c, case_id, container_id);
}
};
// the actual test cases -- END
template <int CaseNumber>
inline void test_case_all_containers(std::string const& case_id)
{
typedef typename std::vector<std::vector<int> > VV;
typedef typename std::vector<std::list<int> > VL;
typedef typename std::list<std::vector<int> > LV;
typedef typename std::list<std::list<int> > LL;
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
#endif
test_case_per_container<CaseNumber>::template apply<VV>(case_id, "VV");
test_case_per_container<CaseNumber>::template apply<VL>(case_id, "VL");
test_case_per_container<CaseNumber>::template apply<LV>(case_id, "LV");
test_case_per_container<CaseNumber>::template apply<LL>(case_id, "LL");
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "********************************************************"
<< std::endl << std::endl;
#endif
}
BOOST_AUTO_TEST_CASE( test_flatten_iterator_all )
{
test_case_all_containers<0>("empty");
test_case_all_containers<1>("case1");
test_case_all_containers<2>("case2");
test_case_all_containers<3>("case3");
}

View File

@@ -0,0 +1,468 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#include <iostream>
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_point_iterator
#endif
#include <boost/test/included/unit_test.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
#include <boost/geometry/multi/geometries/multi_geometries.hpp>
#include <boost/geometry/multi/geometries/register/multi_point.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/io/wkt/read.hpp>
#include <boost/geometry/io/wkt/write.hpp>
#include <boost/geometry/io/dsv/write.hpp>
#include <boost/geometry/multi/io/dsv/write.hpp>
#include <boost/geometry/multi/io/wkt/write.hpp>
#include <boost/geometry/multi/io/wkt/read.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
namespace bg = ::boost::geometry;
namespace ba = ::boost::assign;
typedef bg::model::point<double, 2, bg::cs::cartesian> point_type;
typedef bg::model::point<double, 3, bg::cs::cartesian> point_type_3d;
typedef bg::model::linestring<point_type> linestring_type;
typedef bg::model::polygon<point_type, false, false> polygon_type; //ccw, open
// multi geometries
typedef bg::model::multi_point<point_type> multi_point_type;
typedef bg::model::multi_point<point_type_3d> multi_point_type_3d;
typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
typedef bg::model::multi_polygon<polygon_type> multi_polygon_type;
typedef boost::tuple<double, double> tuple_point_type;
typedef boost::tuple<double, double, double> tuple_point_type_3d;
typedef std::vector<tuple_point_type> tuple_multi_point_type;
typedef std::vector<tuple_point_type_3d> tuple_multi_point_type_3d;
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type)
BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type_3d)
template <typename Geometry>
Geometry from_wkt(std::string const& wkt)
{
Geometry geometry;
boost::geometry::read_wkt(wkt, geometry);
return geometry;
}
struct equals
{
template <typename Iterator>
static inline std::size_t number_of_elements(Iterator begin,
Iterator end)
{
std::size_t num_elems(0);
for (Iterator it = begin; it != end; ++it)
{
++num_elems;
}
return num_elems;
}
template <typename Iterator1, typename Iterator2>
static inline bool apply(Iterator1 begin1, Iterator1 end1,
Iterator2 begin2, Iterator2 end2)
{
std::size_t num_points1 = number_of_elements(begin1, end1);
std::size_t num_points2 = number_of_elements(begin2, end2);
if ( num_points1 != num_points2 )
{
return false;
}
Iterator1 it1 = begin1;
Iterator2 it2 = begin2;
for (; it1 != end1; ++it1, ++it2)
{
if ( !bg::equals(*it1, *it2) )
{
return false;
}
}
return true;
}
};
struct test_assignment
{
template <typename Iterator, typename ConstIterator, typename Value>
static inline void apply(Iterator it, ConstIterator cit,
Value const& value1, Value const& value2)
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "== before assignment ==" << std::endl;
std::cout << "value1: " << bg::wkt(value1) << std::endl;
std::cout << "value2: " << bg::wkt(value2) << std::endl;
std::cout << "*it : " << bg::wkt(*it) << std::endl;
std::cout << "*cit : " << bg::wkt(*cit) << std::endl;
#endif
BOOST_CHECK( bg::equals(*it, value1) );
BOOST_CHECK( !bg::equals(*it, value2) );
BOOST_CHECK( bg::equals(*cit, value1) );
BOOST_CHECK( !bg::equals(*cit, value2) );
*it = value2;
BOOST_CHECK( bg::equals(*it, value2) );
BOOST_CHECK( !bg::equals(*it, value1) );
BOOST_CHECK( bg::equals(*cit, value2) );
BOOST_CHECK( !bg::equals(*cit, value1) );
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "== after 1st assignment ==" << std::endl;
std::cout << "value1: " << bg::wkt(value1) << std::endl;
std::cout << "value2: " << bg::wkt(value2) << std::endl;
std::cout << "*it : " << bg::wkt(*it) << std::endl;
std::cout << "*cit : " << bg::wkt(*cit) << std::endl;
#endif
*it = value1;
BOOST_CHECK( bg::equals(*it, value1) );
BOOST_CHECK( !bg::equals(*it, value2) );
BOOST_CHECK( bg::equals(*cit, value1) );
BOOST_CHECK( !bg::equals(*cit, value2) );
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "== after 2nd assignment ==" << std::endl;
std::cout << "value1: " << bg::wkt(value1) << std::endl;
std::cout << "value2: " << bg::wkt(value2) << std::endl;
std::cout << "*it : " << bg::wkt(*it) << std::endl;
std::cout << "*cit : " << bg::wkt(*cit) << std::endl;
std::cout << std::endl;
#endif
}
};
template <typename Geometry, typename PointRange>
struct test_point_iterator_of_geometry
{
template <typename G>
static inline void base_test(G& geometry,
PointRange const& point_range,
std::string const& header)
{
typedef bg::point_iterator<G> point_iterator;
typedef bg::point_iterator<G const> const_point_iterator;
point_iterator begin = bg::points_begin(geometry);
point_iterator end = bg::points_end(geometry);
BOOST_CHECK( equals::apply(begin, end,
bg::points_begin(point_range),
bg::points_end(point_range))
);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << header << " geometry: " << bg::wkt(geometry) << std::endl;
std::cout << "point range: (";
for (point_iterator pit = begin; pit != end; ++pit)
{
std::cout << " " << bg::dsv(*pit);
}
std::cout << " )" << std::endl;
typedef bg::point_iterator<PointRange const> point_range_iterator;
point_range_iterator rng_begin = bg::points_begin(point_range);
point_range_iterator rng_end = bg::points_end(point_range);
std::cout << "expected point range: (";
for (point_range_iterator pit = rng_begin; pit != rng_end; ++pit)
{
std::cout << " " << bg::dsv(*pit);
}
std::cout << " )" << std::endl;
#endif
}
static inline void apply(Geometry geometry, PointRange const& point_range)
{
base_test<Geometry>(geometry, point_range, "non-const");
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl;
#endif
base_test<Geometry const>(geometry, point_range, "const");
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
#endif
// testing construction of const and non-const iterator
typedef bg::point_iterator<Geometry> point_iterator;
typedef bg::point_iterator<Geometry const> const_point_iterator;
point_iterator begin = bg::points_begin(geometry);
point_iterator end = bg::points_end(geometry);
const_point_iterator const_begin = bg::points_begin(geometry);
const_point_iterator const_end = bg::points_end(geometry);
// testing assignment of non-const to const iterator
const_begin = begin;
const_end = end;
// testing dereferencing/assignment
if ( begin != end )
{
typedef typename bg::point_type<Geometry>::type point;
point p = *begin;
point q = bg::make_zero<point>();
test_assignment::apply(begin, const_begin, p, q);
*begin = q;
test_assignment::apply(begin, const_begin, q, p);
*begin = p;
}
}
};
//======================================================================
//======================================================================
BOOST_AUTO_TEST_CASE( test_linestring_point_iterator )
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "*** LINESTRING ***" << std::endl;
#endif
typedef tuple_multi_point_type TMP;
typedef linestring_type L;
typedef test_point_iterator_of_geometry<L, TMP> tester;
tester::apply(from_wkt<L>("LINESTRING()"),
TMP()
);
tester::apply(from_wkt<L>("LINESTRING(3 3,4 4,5 5)"),
ba::tuple_list_of(3,3)(4,4)(5,5)
);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl << std::endl;
#endif
}
//======================================================================
//======================================================================
BOOST_AUTO_TEST_CASE( test_polygon_point_iterator )
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "*** POLYGON ***" << std::endl;
#endif
typedef tuple_multi_point_type TMP;
typedef polygon_type P;
typedef test_point_iterator_of_geometry<P, TMP> tester;
tester::apply(from_wkt<P>("POLYGON()"),
TMP()
);
tester::apply(from_wkt<P>("POLYGON(())"),
TMP()
);
tester::apply(from_wkt<P>("POLYGON((1 1,9 1,9 9,1 9),(5 5,6 5,6 6,5 6))"),
ba::tuple_list_of(1,1)(9,1)(9,9)(1,9)(5,5)(6,5)(6,6)(5,6)
);
tester::apply(from_wkt<P>("POLYGON((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),())"),
ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)
);
tester::apply(from_wkt<P>("POLYGON((),(3 3,4 4,5 5),(),(),(6 6,7 7,8 8),(),(),(9 9),())"),
ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)
);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
#endif
}
//======================================================================
//======================================================================
BOOST_AUTO_TEST_CASE( test_multipoint_point_iterator )
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "*** MULTIPOINT ***" << std::endl;
#endif
typedef tuple_multi_point_type TMP;
typedef multi_point_type MP;
typedef test_point_iterator_of_geometry<MP, TMP> tester;
tester::apply(from_wkt<MP>("MULTIPOINT()"),
TMP()
);
tester::apply(from_wkt<MP>("MULTIPOINT(3 3,4 4,5 5)"),
ba::tuple_list_of(3,3)(4,4)(5,5)
);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl << std::endl;
#endif
}
//======================================================================
//======================================================================
BOOST_AUTO_TEST_CASE( test_multipoint_3d_point_iterator )
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "*** MULTIPOINT 3D ***" << std::endl;
#endif
typedef tuple_multi_point_type_3d TMP;
typedef multi_point_type_3d MP;
typedef test_point_iterator_of_geometry<MP, TMP> tester;
tester::apply(from_wkt<MP>("MULTIPOINT()"),
TMP()
);
tester::apply(from_wkt<MP>("MULTIPOINT(3 3 3,4 4 4,5 5 5)"),
ba::tuple_list_of(3,3,3)(4,4,4)(5,5,5)
);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl << std::endl;
#endif
}
//======================================================================
//======================================================================
BOOST_AUTO_TEST_CASE( test_multilinestring_point_iterator )
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "*** MULTILINESTRING ***" << std::endl;
#endif
typedef tuple_multi_point_type TMP;
typedef multi_linestring_type ML;
typedef test_point_iterator_of_geometry<ML, TMP> tester;
tester::apply(from_wkt<ML>("MULTILINESTRING()"),
TMP()
);
tester::apply(from_wkt<ML>("MULTILINESTRING(())"),
TMP()
);
tester::apply(from_wkt<ML>("MULTILINESTRING((),(),())"),
TMP()
);
tester::apply(from_wkt<ML>("MULTILINESTRING((1 1,2 2,3 3),(3 3,4 4,5 5),(6 6))"),
ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6)
);
tester::apply(from_wkt<ML>("MULTILINESTRING((),(),(1 1,2 2,3 3),(),(),(3 3,4 4,5 5),(),(6 6),(),(),())"),
ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6)
);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
#endif
}
//======================================================================
//======================================================================
BOOST_AUTO_TEST_CASE( test_multipolygon_point_iterator )
{
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "*** MULTIPOLYGON ***" << std::endl;
#endif
typedef tuple_multi_point_type TMP;
typedef multi_polygon_type MPL;
typedef test_point_iterator_of_geometry<MPL, TMP> tester;
tester::apply(from_wkt<MPL>("MULTIPOLYGON()"),
TMP()
);
tester::apply(from_wkt<MPL>("MULTIPOLYGON( () )"),
TMP()
);
tester::apply(from_wkt<MPL>("MULTIPOLYGON( (()) )"),
TMP()
);
tester::apply(from_wkt<MPL>("MULTIPOLYGON( ((),()) )"),
TMP()
);
tester::apply(from_wkt<MPL>("MULTIPOLYGON(((3 3,4 4,5 5),(6 6,7 7,8 8),(9 9)),((1 1,2 2,10 10),(11 11,12 12)))"),
ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\
(1,1)(2,2)(10,10)(11,11)(12,12)
);
tester::apply(from_wkt<MPL>("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()))"),
ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\
(1,1)(2,2)(10,10)(11,11)(12,12)(13,13)
);
tester::apply(from_wkt<MPL>("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()),((),(),()))"),
ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\
(1,1)(2,2)(10,10)(11,11)(12,12)(13,13)
);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
#endif
}