Updated Boost libraries

This commit is contained in:
Sergii Pylypenko
2013-06-26 17:31:21 +03:00
parent cb4611925f
commit d62c91a533
2623 changed files with 177210 additions and 61224 deletions
@@ -18,6 +18,8 @@
#include <boost/mpl/if.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
@@ -26,6 +28,7 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/geometries/variant.hpp>
#include <boost/geometry/algorithms/detail/calculate_null.hpp>
#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
@@ -49,41 +52,33 @@ namespace boost { namespace geometry
namespace detail { namespace area
{
template<typename Box, typename Strategy>
struct box_area
{
typedef typename coordinate_type<Box>::type return_type;
static inline return_type apply(Box const& box, Strategy const&)
template <typename Box, typename Strategy>
static inline typename coordinate_type<Box>::type
apply(Box const& box, Strategy const&)
{
// Currently only works for 2D Cartesian boxes
assert_dimension<Box, 2>();
return_type const dx = get<max_corner, 0>(box)
- get<min_corner, 0>(box);
return_type const dy = get<max_corner, 1>(box)
- get<min_corner, 1>(box);
return dx * dy;
return (get<max_corner, 0>(box) - get<min_corner, 0>(box))
* (get<max_corner, 1>(box) - get<min_corner, 1>(box));
}
};
template
<
typename Ring,
iterate_direction Direction,
closure_selector Closure,
typename Strategy
closure_selector Closure
>
struct ring_area
{
BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) );
typedef typename Strategy::return_type type;
static inline type apply(Ring const& ring, Strategy const& strategy)
template <typename Ring, typename Strategy>
static inline typename Strategy::return_type
apply(Ring const& ring, Strategy const& strategy)
{
BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) );
assert_dimension<Ring, 2>();
// Ignore warning (because using static method sometimes) on strategy
@@ -92,10 +87,10 @@ struct ring_area
// An open ring has at least three points,
// A closed ring has at least four points,
// if not, there is no (zero) area
if (boost::size(ring)
if (int(boost::size(ring))
< core_detail::closure::minimum_ring_size<Closure>::value)
{
return type();
return typename Strategy::return_type();
}
typedef typename reversible_view<Ring const, Direction>::type rview_type;
@@ -136,71 +131,75 @@ namespace dispatch
template
<
typename Geometry,
typename Strategy = typename strategy::area::services::default_strategy
<
typename cs_tag
<
typename point_type<Geometry>::type
>::type,
typename point_type<Geometry>::type
>::type,
typename Tag = typename tag<Geometry>::type
>
struct area
: detail::calculate_null
<
typename Strategy::return_type,
Geometry,
Strategy
> {};
struct area : detail::calculate_null
{
template <typename Strategy>
static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)
{
return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);
}
};
template
<
typename Geometry,
typename Strategy
>
struct area<Geometry, Strategy, box_tag>
: detail::area::box_area<Geometry, Strategy>
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, void>
{
template <typename Strategy>
struct visitor: boost::static_visitor<typename Strategy::return_type>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
typename Strategy::return_type operator()(Geometry const& geometry) const
{
return dispatch::area<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Variant, typename Strategy>
static inline typename Strategy::return_type
apply(Variant const& variant_geometry, Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), variant_geometry);
}
};
template <typename Geometry>
struct area<Geometry, box_tag> : detail::area::box_area
{};
template
<
typename Ring,
typename Strategy
>
struct area<Ring, Strategy, ring_tag>
template <typename Ring>
struct area<Ring, ring_tag>
: detail::area::ring_area
<
Ring,
order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::value,
Strategy
geometry::closure<Ring>::value
>
{};
template
<
typename Polygon,
typename Strategy
>
struct area<Polygon, Strategy, polygon_tag>
: detail::calculate_polygon_sum
<
template <typename Polygon>
struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
{
template <typename Strategy>
static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy)
{
return calculate_polygon_sum::apply<
typename Strategy::return_type,
Polygon,
Strategy,
detail::area::ring_area
<
typename ring_type<Polygon const>::type,
order_as_direction<geometry::point_order<Polygon>::value>::value,
geometry::closure<Polygon>::value,
Strategy
geometry::closure<Polygon>::value
>
>
{};
>(polygon, strategy);
}
};
} // namespace dispatch
@@ -243,10 +242,7 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr
// detail::throw_on_empty_input(geometry);
return dispatch::area
<
Geometry
>::apply(geometry, strategy_type());
return dispatch::area<Geometry>::apply(geometry, strategy_type());
}
/*!
@@ -281,11 +277,7 @@ inline typename Strategy::return_type area(
// detail::throw_on_empty_input(geometry);
return dispatch::area
<
Geometry,
Strategy
>::apply(geometry, strategy);
return dispatch::area<Geometry>::apply(geometry, strategy);
}
@@ -20,6 +20,7 @@
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/disjoint.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -75,15 +76,23 @@ inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
namespace dispatch
{
template <typename TagIn, typename TagOut, typename Input, typename T, typename Output>
struct buffer {};
template
<
typename Input,
typename Output,
typename TagIn = typename tag<Input>::type,
typename TagOut = typename tag<Output>::type
>
struct buffer: not_implemented<TagIn, TagOut>
{};
template <typename BoxIn, typename T, typename BoxOut>
struct buffer<box_tag, box_tag, BoxIn, T, BoxOut>
template <typename BoxIn, typename BoxOut>
struct buffer<BoxIn, BoxOut, box_tag, box_tag>
{
static inline void apply(BoxIn const& box_in, T const& distance,
T const& , BoxIn& box_out)
template <typename Distance>
static inline void apply(BoxIn const& box_in, Distance const& distance,
Distance const& , BoxIn& box_out)
{
detail::buffer::buffer_box(box_in, distance, box_out);
}
@@ -122,10 +131,7 @@ inline void buffer(Input const& geometry_in, Output& geometry_out,
dispatch::buffer
<
typename tag<Input>::type,
typename tag<Output>::type,
Input,
Distance,
Output
>::apply(geometry_in, distance, chord_length, geometry_out);
}
@@ -152,10 +158,7 @@ Output return_buffer(Input const& geometry, T const& distance, T const& chord_le
dispatch::buffer
<
typename tag<Input>::type,
typename tag<Output>::type,
Input,
T,
Output
>::apply(geometry, distance, chord_length, geometry_out);
@@ -30,6 +30,7 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/concepts/centroid_concept.hpp>
@@ -77,9 +78,9 @@ public:
namespace detail { namespace centroid
{
template<typename Point, typename PointCentroid, typename Strategy>
struct centroid_point
{
template<typename Point, typename PointCentroid, typename Strategy>
static inline void apply(Point const& point, PointCentroid& centroid,
Strategy const&)
{
@@ -127,9 +128,9 @@ struct centroid_box_calculator<Box, Point, DimensionCount, DimensionCount>
};
template<typename Box, typename Point, typename Strategy>
struct centroid_box
{
template<typename Box, typename Point, typename Strategy>
static inline void apply(Box const& box, Point& centroid,
Strategy const&)
{
@@ -173,9 +174,10 @@ inline bool range_ok(Range const& range, Point& centroid)
/*!
\brief Calculate the centroid of a ring.
*/
template<typename Ring, closure_selector Closure, typename Strategy>
template <closure_selector Closure>
struct centroid_range_state
{
template<typename Ring, typename Strategy>
static inline void apply(Ring const& ring,
Strategy const& strategy, typename Strategy::state_type& state)
{
@@ -196,21 +198,17 @@ struct centroid_range_state
}
};
template<typename Range, typename Point, closure_selector Closure, typename Strategy>
template <closure_selector Closure>
struct centroid_range
{
template<typename Range, typename Point, typename Strategy>
static inline void apply(Range const& range, Point& centroid,
Strategy const& strategy)
{
if (range_ok(range, centroid))
{
typename Strategy::state_type state;
centroid_range_state
<
Range,
Closure,
Strategy
>::apply(range, strategy, state);
centroid_range_state<Closure>::apply(range, strategy, state);
strategy.result(state, centroid);
}
}
@@ -222,20 +220,14 @@ struct centroid_range
\note Because outer ring is clockwise, inners are counter clockwise,
triangle approach is OK and works for polygons with rings.
*/
template<typename Polygon, typename Strategy>
struct centroid_polygon_state
{
typedef typename ring_type<Polygon>::type ring_type;
template<typename Polygon, typename Strategy>
static inline void apply(Polygon const& poly,
Strategy const& strategy, typename Strategy::state_type& state)
{
typedef centroid_range_state
<
ring_type,
geometry::closure<ring_type>::value,
Strategy
> per_ring;
typedef typename ring_type<Polygon>::type ring_type;
typedef centroid_range_state<geometry::closure<ring_type>::value> per_ring;
per_ring::apply(exterior_ring(poly), strategy, state);
@@ -248,20 +240,16 @@ struct centroid_polygon_state
}
};
template<typename Polygon, typename Point, typename Strategy>
struct centroid_polygon
{
template<typename Polygon, typename Point, typename Strategy>
static inline void apply(Polygon const& poly, Point& centroid,
Strategy const& strategy)
{
if (range_ok(exterior_ring(poly), centroid))
{
typename Strategy::state_type state;
centroid_polygon_state
<
Polygon,
Strategy
>::apply(poly, strategy, state);
centroid_polygon_state::apply(poly, strategy, state);
strategy.result(state, centroid);
}
}
@@ -278,58 +266,35 @@ namespace dispatch
template
<
typename Tag,
typename Geometry,
typename Point,
typename Strategy
typename Tag = typename tag<Geometry>::type
>
struct centroid {};
template
<
typename Geometry,
typename Point,
typename Strategy
>
struct centroid<point_tag, Geometry, Point, Strategy>
: detail::centroid::centroid_point<Geometry, Point, Strategy>
struct centroid: not_implemented<Tag>
{};
template
<
typename Box,
typename Point,
typename Strategy
>
struct centroid<box_tag, Box, Point, Strategy>
: detail::centroid::centroid_box<Box, Point, Strategy>
template <typename Geometry>
struct centroid<Geometry, point_tag>
: detail::centroid::centroid_point
{};
template <typename Ring, typename Point, typename Strategy>
struct centroid<ring_tag, Ring, Point, Strategy>
: detail::centroid::centroid_range
<
Ring,
Point,
geometry::closure<Ring>::value,
Strategy
>
template <typename Box>
struct centroid<Box, box_tag>
: detail::centroid::centroid_box
{};
template <typename Linestring, typename Point, typename Strategy>
struct centroid<linestring_tag, Linestring, Point, Strategy>
: detail::centroid::centroid_range
<
Linestring,
Point,
closed,
Strategy
>
template <typename Ring>
struct centroid<Ring, ring_tag>
: detail::centroid::centroid_range<geometry::closure<Ring>::value>
{};
template <typename Linestring>
struct centroid<Linestring, linestring_tag>
: detail::centroid::centroid_range<closed>
{};
template <typename Polygon, typename Point, typename Strategy>
struct centroid<polygon_tag, Polygon, Point, Strategy>
: detail::centroid::centroid_polygon<Polygon, Point, Strategy>
template <typename Polygon>
struct centroid<Polygon, polygon_tag>
: detail::centroid::centroid_polygon
{};
} // namespace dispatch
@@ -365,13 +330,7 @@ inline void centroid(Geometry const& geometry, Point& c,
// Call dispatch apply method. That one returns true if centroid
// should be taken from state.
dispatch::centroid
<
typename tag<Geometry>::type,
Geometry,
Point,
Strategy
>::apply(geometry, c, strategy);
dispatch::centroid<Geometry>::apply(geometry, c, strategy);
}
@@ -40,18 +40,13 @@ namespace boost { namespace geometry
namespace detail { namespace convex_hull
{
template
<
typename Geometry,
order_selector Order,
typename Strategy
>
template <order_selector Order>
struct hull_insert
{
// Member template function (to avoid inconvenient declaration
// of output-iterator-type, from hull_to_geometry)
template <typename OutputIterator>
template <typename Geometry, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry const& geometry,
OutputIterator out, Strategy const& strategy)
{
@@ -63,22 +58,15 @@ struct hull_insert
}
};
template
<
typename Geometry,
typename Strategy
>
struct hull_to_geometry
{
template <typename OutputGeometry>
template <typename Geometry, typename OutputGeometry, typename Strategy>
static inline void apply(Geometry const& geometry, OutputGeometry& out,
Strategy const& strategy)
{
hull_insert
<
Geometry,
geometry::point_order<OutputGeometry>::value,
Strategy
geometry::point_order<OutputGeometry>::value
>::apply(geometry,
std::back_inserter(
// Handle linestring, ring and polygon the same:
@@ -113,21 +101,16 @@ namespace dispatch
template
<
typename Geometry,
typename Strategy = typename detail::convex_hull::default_strategy<Geometry>::type,
typename Tag = typename tag<Geometry>::type
>
struct convex_hull
: detail::convex_hull::hull_to_geometry<Geometry, Strategy>
: detail::convex_hull::hull_to_geometry
{};
template
<
typename Box,
typename Strategy
>
struct convex_hull<Box, Strategy, box_tag>
template <typename Box>
struct convex_hull<Box, box_tag>
{
template <typename OutputGeometry>
template <typename OutputGeometry, typename Strategy>
static inline void apply(Box const& box, OutputGeometry& out,
Strategy const& )
{
@@ -149,13 +132,9 @@ struct convex_hull<Box, Strategy, box_tag>
template
<
order_selector Order,
typename Geometry, typename Strategy
>
template <order_selector Order>
struct convex_hull_insert
: detail::convex_hull::hull_insert<Geometry, Order, Strategy>
: detail::convex_hull::hull_insert<Order>
{};
@@ -181,11 +160,7 @@ inline void convex_hull(Geometry const& geometry,
return;
}
dispatch::convex_hull
<
Geometry,
Strategy
>::apply(geometry, out, strategy);
dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
}
@@ -232,8 +207,7 @@ inline OutputIterator convex_hull_insert(Geometry const& geometry,
return dispatch::convex_hull_insert
<
geometry::point_order<Geometry>::value,
Geometry, Strategy
geometry::point_order<Geometry>::value
>::apply(geometry, out, strategy);
}
@@ -119,10 +119,8 @@ struct correct_ring
typedef detail::area::ring_area
<
Ring,
order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::value,
strategy_type
geometry::closure<Ring>::value
> ring_area_type;
@@ -21,9 +21,9 @@ namespace boost { namespace geometry
namespace detail
{
template<typename ReturnType, typename Geometry, typename Strategy>
struct calculate_null
{
template<typename ReturnType, typename Geometry, typename Strategy>
static inline ReturnType apply(Geometry const& , Strategy const&)
{
return ReturnType();
@@ -26,16 +26,9 @@ namespace detail
{
template
<
typename ReturnType,
typename Polygon,
typename Strategy,
typename Policy
>
class calculate_polygon_sum
{
template <typename Rings>
template <typename ReturnType, typename Policy, typename Rings, typename Strategy>
static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
{
ReturnType sum = ReturnType();
@@ -47,10 +40,11 @@ class calculate_polygon_sum
}
public :
template <typename ReturnType, typename Policy, typename Polygon, typename Strategy>
static inline ReturnType apply(Polygon const& poly, Strategy const& strategy)
{
return Policy::apply(exterior_ring(poly), strategy)
+ sum_interior_rings(interior_rings(poly), strategy)
+ sum_interior_rings<ReturnType, Policy>(interior_rings(poly), strategy)
;
}
};
@@ -26,6 +26,7 @@
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/util/math.hpp>
@@ -165,6 +166,19 @@ struct box_box<Box1, Box2, DimensionCount, DimensionCount>
};
template
<
typename Geometry1, typename Geometry2
>
struct reverse_covered_by
{
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return ! geometry::covered_by(geometry1, geometry2);
}
};
/*!
\brief Internal utility function to detect of boxes are disjoint
@@ -22,6 +22,7 @@
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/util/add_const_if_c.hpp>
#include <boost/geometry/views/box_view.hpp>
namespace boost { namespace geometry
@@ -0,0 +1,371 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// TODO: move this to /util/
template <typename T>
static inline std::pair<T, T> ordered_pair(T const& first, T const& second)
{
return first < second ? std::make_pair(first, second) : std::make_pair(second, first);
}
template <typename AngleInfo>
inline void debug_left_turn(AngleInfo const& ai, AngleInfo const& previous)
{
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
std::cout << "Angle: " << (ai.incoming ? "i" : "o")
<< " " << si(ai.seg_id)
<< " " << (math::r2d * (ai.angle) )
<< " turn: " << ai.turn_index << "[" << ai.operation_index << "]"
;
if (ai.turn_index != previous.turn_index
|| ai.operation_index != previous.operation_index)
{
std::cout << " diff: " << math::r2d * math::abs(previous.angle - ai.angle);
}
std::cout << std::endl;
#endif
}
template <typename AngleInfo>
inline void debug_left_turn(std::string const& caption, AngleInfo const& ai, AngleInfo const& previous,
int code = -99, int code2 = -99, int code3 = -99, int code4 = -99)
{
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
std::cout << " " << caption
<< " turn: " << ai.turn_index << "[" << ai.operation_index << "]"
<< " " << si(ai.seg_id)
<< " " << (ai.incoming ? "i" : "o")
<< " " << (math::r2d * (ai.angle) )
<< " turn: " << previous.turn_index << "[" << previous.operation_index << "]"
<< " " << si(previous.seg_id)
<< " " << (previous.incoming ? "i" : "o")
<< " " << (math::r2d * (previous.angle) )
;
if (code != -99)
{
std::cout << " code: " << code << " , " << code2 << " , " << code3 << " , " << code4;
}
std::cout << std::endl;
#endif
}
template <typename Operation>
inline bool include_operation(Operation const& op,
segment_identifier const& outgoing_seg_id,
segment_identifier const& incoming_seg_id)
{
return op.seg_id == outgoing_seg_id
&& op.other_id == incoming_seg_id
&& (op.operation == detail::overlay::operation_union
||op.operation == detail::overlay::operation_continue)
;
}
template <typename Turn>
inline bool process_include(segment_identifier const& outgoing_seg_id, segment_identifier const& incoming_seg_id,
int turn_index, Turn& turn,
std::set<int>& keep_indices, int priority)
{
bool result = false;
for (int i = 0; i < 2; i++)
{
if (include_operation(turn.operations[i], outgoing_seg_id, incoming_seg_id))
{
turn.operations[i].include_in_occupation_map = true;
if (priority > turn.priority)
{
turn.priority = priority;
}
keep_indices.insert(turn_index);
result = true;
}
}
return result;
}
template <typename AngleInfo, typename Turns, typename TurnSegmentIndices>
inline bool include_left_turn_of_all(
AngleInfo const& outgoing, AngleInfo const& incoming,
Turns& turns, TurnSegmentIndices const& turn_segment_indices,
std::set<int>& keep_indices, int priority)
{
segment_identifier const& outgoing_seg_id = turns[outgoing.turn_index].operations[outgoing.operation_index].seg_id;
segment_identifier const& incoming_seg_id = turns[incoming.turn_index].operations[incoming.operation_index].seg_id;
if (outgoing.turn_index == incoming.turn_index)
{
return process_include(outgoing_seg_id, incoming_seg_id, outgoing.turn_index, turns[outgoing.turn_index], keep_indices, priority);
}
bool result = false;
std::pair<segment_identifier, segment_identifier> pair = ordered_pair(outgoing_seg_id, incoming_seg_id);
typename boost::range_iterator<TurnSegmentIndices const>::type it = turn_segment_indices.find(pair);
if (it != turn_segment_indices.end())
{
for (std::set<int>::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit)
{
if (process_include(outgoing_seg_id, incoming_seg_id, *sit, turns[*sit], keep_indices, priority))
{
result = true;
}
}
}
return result;
}
template <std::size_t Index, typename Turn>
inline bool corresponds(Turn const& turn, segment_identifier const& seg_id)
{
return turn.operations[Index].operation == detail::overlay::operation_union
&& turn.operations[Index].seg_id == seg_id;
}
template <typename Turns, typename TurnSegmentIndices>
inline bool prefer_by_other(Turns const& turns,
TurnSegmentIndices const& turn_segment_indices,
std::set<int>& indices)
{
std::map<segment_identifier, int> map;
for (std::set<int>::const_iterator sit = indices.begin();
sit != indices.end();
++sit)
{
map[turns[*sit].operations[0].seg_id]++;
map[turns[*sit].operations[1].seg_id]++;
}
std::set<segment_identifier> segment_occuring_once;
for (std::map<segment_identifier, int>::const_iterator mit = map.begin();
mit != map.end();++mit)
{
if (mit->second == 1)
{
segment_occuring_once.insert(mit->first);
}
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_PREFER
std::cout << si(mit->first) << " " << mit->second << std::endl;
#endif
}
if (segment_occuring_once.size() == 2)
{
// Try to find within all turns a turn with these two segments
std::set<segment_identifier>::const_iterator soo_it = segment_occuring_once.begin();
segment_identifier front = *soo_it;
soo_it++;
segment_identifier back = *soo_it;
std::pair<segment_identifier, segment_identifier> pair = ordered_pair(front, back);
typename boost::range_iterator<TurnSegmentIndices const>::type it = turn_segment_indices.find(pair);
if (it != turn_segment_indices.end())
{
// debug_turns_by_indices("Found", it->second);
// Check which is the union/continue
segment_identifier good;
for (std::set<int>::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit)
{
if (turns[*sit].operations[0].operation == detail::overlay::operation_union)
{
good = turns[*sit].operations[0].seg_id;
}
else if (turns[*sit].operations[1].operation == detail::overlay::operation_union)
{
good = turns[*sit].operations[1].seg_id;
}
}
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_PREFER
std::cout << "Good: " << si(good) << std::endl;
#endif
// Find in indexes-to-keep this segment with the union. Discard the other one
std::set<int> ok_indices;
for (std::set<int>::const_iterator sit = indices.begin(); sit != indices.end(); ++sit)
{
if (corresponds<0>(turns[*sit], good) || corresponds<1>(turns[*sit], good))
{
ok_indices.insert(*sit);
}
}
if (ok_indices.size() > 0 && ok_indices.size() < indices.size())
{
indices = ok_indices;
std::cout << "^";
return true;
}
}
}
return false;
}
template <typename Turns>
inline void prefer_by_priority(Turns const& turns, std::set<int>& indices)
{
// Find max prio
int min_prio = 1024, max_prio = 0;
for (std::set<int>::const_iterator sit = indices.begin(); sit != indices.end(); ++sit)
{
if (turns[*sit].priority > max_prio)
{
max_prio = turns[*sit].priority;
}
if (turns[*sit].priority < min_prio)
{
min_prio = turns[*sit].priority;
}
}
if (min_prio == max_prio)
{
return;
}
// Only keep indices with high prio
std::set<int> ok_indices;
for (std::set<int>::const_iterator sit = indices.begin(); sit != indices.end(); ++sit)
{
if (turns[*sit].priority >= max_prio)
{
ok_indices.insert(*sit);
}
}
if (ok_indices.size() > 0 && ok_indices.size() < indices.size())
{
indices = ok_indices;
std::cout << "%";
}
}
template <typename AngleInfo, typename Angles, typename Turns, typename TurnSegmentIndices>
inline void calculate_left_turns(Angles const& angles,
Turns& turns, TurnSegmentIndices const& turn_segment_indices,
std::set<int>& keep_indices)
{
bool debug_indicate_size = false;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<typename AngleInfo::point_type>::type
>::type side_strategy;
std::size_t i = 0;
std::size_t n = boost::size(angles);
typedef geometry::ever_circling_range_iterator<Angles const> circling_iterator;
circling_iterator cit(angles);
debug_left_turn(*cit, *cit);
for(circling_iterator prev = cit++; i < n; prev = cit++, i++)
{
debug_left_turn(*cit, *prev);
bool const include = ! geometry::math::equals(prev->angle, cit->angle)
&& ! prev->incoming
&& cit->incoming;
if (include)
{
// Go back to possibly include more same left outgoing angles:
// Because we check on side too we can take a large "epsilon"
circling_iterator back = prev - 1;
typename AngleInfo::angle_type eps = 0.00001;
int b = 1;
for(std::size_t d = 0;
math::abs(prev->angle - back->angle) < eps
&& ! back->incoming
&& d < n;
d++)
{
--back;
++b;
}
// Same but forward to possibly include more incoming angles
int f = 1;
circling_iterator forward = cit + 1;
for(std::size_t d = 0;
math::abs(cit->angle - forward->angle) < eps
&& forward->incoming
&& d < n;
d++)
{
++forward;
++f;
}
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
std::cout << "HANDLE " << b << "/" << f << " ANGLES" << std::endl;
#endif
for(circling_iterator bit = prev; bit != back; --bit)
{
int code = side_strategy::apply(bit->direction_point, prev->intersection_point, prev->direction_point);
int code2 = side_strategy::apply(prev->direction_point, bit->intersection_point, bit->direction_point);
for(circling_iterator fit = cit; fit != forward; ++fit)
{
int code3 = side_strategy::apply(fit->direction_point, cit->intersection_point, cit->direction_point);
int code4 = side_strategy::apply(cit->direction_point, fit->intersection_point, fit->direction_point);
int priority = 2;
if (code == -1 && code2 == 1)
{
// This segment is lying right of the other one.
// Cannot ignore it (because of robustness, see a.o. #rt_p21 from unit test).
// But if we find more we can prefer later by priority
// (a.o. necessary for #rt_o2 from unit test)
priority = 1;
}
bool included = include_left_turn_of_all(*bit, *fit, turns, turn_segment_indices, keep_indices, priority);
debug_left_turn(included ? "KEEP" : "SKIP", *fit, *bit, code, code2, code3, code4);
}
}
}
}
if (debug_indicate_size)
{
std::cout << " size=" << keep_indices.size();
}
if (keep_indices.size() >= 2)
{
prefer_by_other(turns, turn_segment_indices, keep_indices);
}
if (keep_indices.size() >= 2)
{
prefer_by_priority(turns, keep_indices);
}
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
@@ -0,0 +1,329 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
#if ! defined(NDEBUG)
// #define BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
#endif
#include <algorithm>
#include <boost/range.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/iterators/closing_iterator.hpp>
#include <boost/geometry/algorithms/detail/get_left_turns.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename P>
class relaxed_less
{
typedef typename geometry::coordinate_type<P>::type coordinate_type;
coordinate_type epsilon;
public :
inline relaxed_less()
{
// TODO: adapt for ttmath, and maybe build the map in another way
// (e.g. exact constellations of segment-id's), maybe adaptive.
epsilon = std::numeric_limits<double>::epsilon() * 100.0;
}
inline bool operator()(P const& a, P const& b) const
{
coordinate_type const dx = math::abs(geometry::get<0>(a) - geometry::get<0>(b));
coordinate_type const dy = math::abs(geometry::get<1>(a) - geometry::get<1>(b));
if (dx < epsilon && dy < epsilon)
{
return false;
}
if (dx < epsilon)
{
return geometry::get<1>(a) < geometry::get<1>(b);
}
return geometry::get<0>(a) < geometry::get<0>(b);
}
inline bool equals(P const& a, P const& b) const
{
typedef typename geometry::coordinate_type<P>::type coordinate_type;
coordinate_type const dx = math::abs(geometry::get<0>(a) - geometry::get<0>(b));
coordinate_type const dy = math::abs(geometry::get<1>(a) - geometry::get<1>(b));
return dx < epsilon && dy < epsilon;
};
};
template <typename T, typename P1, typename P2>
inline T calculate_angle(P1 const& from_point, P2 const& to_point)
{
typedef P1 vector_type;
vector_type v = from_point;
geometry::subtract_point(v, to_point);
return atan2(geometry::get<1>(v), geometry::get<0>(v));
}
template <typename Iterator, typename Vector>
inline Iterator advance_circular(Iterator it, Vector const& vector, segment_identifier& seg_id, bool forward = true)
{
int const increment = forward ? 1 : -1;
if (it == boost::begin(vector) && increment < 0)
{
it = boost::end(vector);
seg_id.segment_index = boost::size(vector);
}
it += increment;
seg_id.segment_index += increment;
if (it == boost::end(vector))
{
seg_id.segment_index = 0;
it = boost::begin(vector);
}
return it;
}
template <typename Point, typename T>
struct angle_info
{
typedef T angle_type;
typedef Point point_type;
segment_identifier seg_id;
int turn_index;
int operation_index;
Point intersection_point;
Point direction_point;
T angle;
bool incoming;
};
template <typename AngleInfo>
class occupation_info
{
typedef std::vector<AngleInfo> collection_type;
struct angle_sort
{
inline bool operator()(AngleInfo const& left, AngleInfo const& right) const
{
// In this case we can compare even double using equals
// return geometry::math::equals(left.angle, right.angle)
return left.angle == right.angle
? int(left.incoming) < int(right.incoming)
: left.angle < right.angle
;
}
};
public :
collection_type angles;
private :
bool m_occupied;
bool m_calculated;
inline bool is_occupied()
{
if (boost::size(angles) <= 1)
{
return false;
}
std::sort(angles.begin(), angles.end(), angle_sort());
typedef geometry::closing_iterator<collection_type const> closing_iterator;
closing_iterator vit(angles);
closing_iterator end(angles, true);
closing_iterator prev = vit++;
for( ; vit != end; prev = vit++)
{
if (! geometry::math::equals(prev->angle, vit->angle)
&& ! prev->incoming
&& vit->incoming)
{
return false;
}
}
return true;
}
public :
inline occupation_info()
: m_occupied(false)
, m_calculated(false)
{}
template <typename PointC, typename Point1, typename Point2>
inline void add(PointC const& map_point, Point1 const& direction_point, Point2 const& intersection_point,
int turn_index, int operation_index,
segment_identifier const& seg_id, bool incoming)
{
//std::cout << "-> adding angle " << geometry::wkt(direction_point) << " .. " << geometry::wkt(intersection_point) << " " << int(incoming) << std::endl;
if (geometry::equals(direction_point, intersection_point))
{
//std::cout << "EQUAL! Skipping" << std::endl;
return;
}
AngleInfo info;
info.incoming = incoming;
info.angle = calculate_angle<typename AngleInfo::angle_type>(direction_point, map_point);
info.seg_id = seg_id;
info.turn_index = turn_index;
info.operation_index = operation_index;
info.intersection_point = intersection_point;
info.direction_point = direction_point;
angles.push_back(info);
m_calculated = false;
}
inline bool occupied()
{
if (! m_calculated)
{
m_occupied = is_occupied();
m_calculated = true;
}
return m_occupied;
}
template <typename Turns, typename TurnSegmentIndices>
inline void get_left_turns(
Turns& turns, TurnSegmentIndices const& turn_segment_indices,
std::set<int>& keep_indices)
{
std::sort(angles.begin(), angles.end(), angle_sort());
calculate_left_turns<AngleInfo>(angles, turns, turn_segment_indices, keep_indices);
}
};
template <typename Point, typename Ring, typename Info>
inline void add_incoming_and_outgoing_angles(Point const& map_point, Point const& intersection_point,
Ring const& ring,
int turn_index,
int operation_index,
segment_identifier seg_id,
Info& info)
{
typedef typename boost::range_iterator
<
Ring const
>::type iterator_type;
int const n = boost::size(ring);
if (seg_id.segment_index >= n || seg_id.segment_index < 0)
{
return;
}
segment_identifier real_seg_id = seg_id;
iterator_type it = boost::begin(ring) + seg_id.segment_index;
// TODO: if we use turn-info ("to", "middle"), we know if to advance without resorting to equals
relaxed_less<Point> comparator;
if (comparator.equals(intersection_point, *it))
{
// It should be equal only once. But otherwise we skip it (in "add")
it = advance_circular(it, ring, seg_id, false);
}
info.add(map_point, *it, intersection_point, turn_index, operation_index, real_seg_id, true);
if (comparator.equals(intersection_point, *it))
{
it = advance_circular(it, ring, real_seg_id);
}
else
{
// Don't upgrade the ID
it = advance_circular(it, ring, seg_id);
}
for (int defensive_check = 0;
comparator.equals(intersection_point, *it) && defensive_check < n;
defensive_check++)
{
it = advance_circular(it, ring, real_seg_id);
}
info.add(map_point, *it, intersection_point, turn_index, operation_index, real_seg_id, false);
}
// Map in two senses of the word: it is a std::map where the key is a point.
// Per point an "occupation_info" record is kept
// Used for the buffer (but will also be used for intersections/unions having complex self-tangencies)
template <typename Point, typename OccupationInfo>
class occupation_map
{
public :
typedef std::map<Point, OccupationInfo, relaxed_less<Point> > map_type;
map_type map;
std::set<int> turn_indices;
inline OccupationInfo& find_or_insert(Point const& point, Point& mapped_point)
{
typename map_type::iterator it = map.find(point);
if (it == boost::end(map))
{
std::pair<typename map_type::iterator, bool> pair
= map.insert(std::make_pair(point, OccupationInfo()));
it = pair.first;
}
mapped_point = it->first;
return it->second;
}
inline bool contains(Point const& point) const
{
typename map_type::const_iterator it = map.find(point);
return it != boost::end(map);
}
inline bool contains_turn_index(int index) const
{
return turn_indices.count(index) > 0;
}
inline void insert_turn_index(int index)
{
turn_indices.insert(index);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
@@ -9,6 +9,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
@@ -73,6 +75,21 @@ inline OutputIterator add_rings(SelectionMap const& map,
OutputIterator out)
{
typedef typename SelectionMap::const_iterator iterator;
typedef typename SelectionMap::mapped_type property_type;
typedef typename property_type::area_type area_type;
area_type const zero = 0;
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
<
geometry::closure
<
typename boost::range_value
<
RingCollection const
>::type
>::value
>::value;
for (iterator it = boost::begin(map);
it != boost::end(map);
@@ -99,7 +116,15 @@ inline OutputIterator add_rings(SelectionMap const& map,
*child_it, mit->second.reversed, true);
}
}
*out++ = result;
// Only add rings if they satisfy minimal requirements.
// This cannot be done earlier (during traversal), not
// everything is figured out yet (sum of positive/negative rings)
if (geometry::num_points(result) >= min_num_points
&& math::larger(geometry::area(result), zero))
{
*out++ = result;
}
}
}
return out;
@@ -130,7 +130,7 @@ struct assign_visitor
return;
}
if (outer.real_area > 0)
if (math::larger(outer.real_area, 0))
{
if (inner.real_area < 0 || m_check_for_orientation)
{
@@ -317,13 +317,14 @@ template
>
inline void assign_parents(Geometry const& geometry,
RingCollection const& collection,
RingMap& ring_map)
RingMap& ring_map,
bool check_for_orientation)
{
// Call it with an empty geometry
// (ring_map should be empty for source_id==1)
Geometry empty;
assign_parents(geometry, empty, collection, ring_map, true);
assign_parents(geometry, empty, collection, ring_map, check_for_orientation);
}
@@ -32,9 +32,18 @@ struct calculate_distance_policy
{
static bool const include_no_turn = false;
static bool const include_degenerate = false;
static bool const include_opposite = false;
template <typename Point1, typename Point2, typename Info>
static inline void apply(Info& info, Point1 const& p1, Point2 const& p2)
template
<
typename Info,
typename Point1,
typename Point2,
typename IntersectionInfo,
typename DirInfo
>
static inline void apply(Info& info, Point1 const& p1, Point2 const& p2,
IntersectionInfo const&, DirInfo const&)
{
info.operations[0].enriched.distance
= geometry::comparable_distance(info.point, p1);
@@ -77,12 +77,23 @@ struct convert_ring<polygon_tag>
}
else
{
interior_rings(destination).resize(
interior_rings(destination).size() + 1);
geometry::convert(source, interior_rings(destination).back());
if (reverse)
// Avoid adding interior rings which are invalid
// because of its number of points:
std::size_t const min_num_points
= core_detail::closure::minimum_ring_size
<
geometry::closure<Destination>::value
>::value;
if (geometry::num_points(source) >= min_num_points)
{
boost::reverse(interior_rings(destination).back());
interior_rings(destination).resize(
interior_rings(destination).size() + 1);
geometry::convert(source, interior_rings(destination).back());
if (reverse)
{
boost::reverse(interior_rings(destination).back());
}
}
}
}
@@ -55,14 +55,14 @@ struct copy_segment_point_range
if (second)
{
index++;
if (index >= boost::size(range))
if (index >= int(boost::size(range)))
{
index = 0;
}
}
// Exception?
if (index >= boost::size(range))
if (index >= int(boost::size(range)))
{
return false;
}
@@ -78,7 +78,7 @@ struct copy_segments_ring
int const from_index = seg_id.segment_index + 1;
// Sanity check
BOOST_ASSERT(from_index < boost::size(view));
BOOST_ASSERT(from_index < int(boost::size(view)));
ec_iterator it(boost::begin(view), boost::end(view),
boost::begin(view) + from_index);
@@ -89,7 +89,7 @@ struct copy_segments_ring
typedef typename boost::range_difference<Ring>::type size_type;
size_type const count = from_index <= to_index
? to_index - from_index + 1
: boost::size(view) - from_index + to_index + 1;
: int(boost::size(view)) - from_index + to_index + 1;
for (size_type i = 0; i < count; ++i, ++it)
{
@@ -117,7 +117,7 @@ struct copy_segments_linestring
int const from_index = seg_id.segment_index + 1;
// Sanity check
if (from_index > to_index || from_index < 0 || to_index >= boost::size(ls))
if (from_index > to_index || from_index < 0 || to_index >= int(boost::size(ls)))
{
return;
}
@@ -28,6 +28,7 @@ inline char method_char(detail::overlay::method_type const& method)
case method_touch_interior : return 'm';
case method_collinear : return 'c';
case method_equal : return 'e';
case method_error : return '!';
default : return '?';
}
}
@@ -42,6 +43,7 @@ inline char operation_char(detail::overlay::operation_type const& operation)
case operation_intersection : return 'i';
case operation_blocked : return 'x';
case operation_continue : return 'c';
case operation_opposite : return 'o';
default : return '?';
}
}
@@ -279,12 +279,12 @@ class follow
{
// In case of turn point at the same location, we want to have continue/blocked LAST
// because that should be followed (intersection) or skipped (difference).
// By chance the enumeration is ordered like that but we keep the safe way here.
inline int operation_order(Turn const& turn) const
{
operation_type const& operation = turn.operations[0].operation;
switch(operation)
{
case operation_opposite : return 0;
case operation_none : return 0;
case operation_union : return 1;
case operation_intersection : return 2;
@@ -83,7 +83,7 @@ struct get_ring<polygon_tag>
BOOST_ASSERT
(
id.ring_index >= -1
&& id.ring_index < boost::size(interior_rings(polygon))
&& id.ring_index < int(boost::size(interior_rings(polygon)))
);
return id.ring_index < 0
? exterior_ring(polygon)
@@ -250,9 +250,15 @@ struct touch : public base_turn_handler
int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
int const side_pk_p = SideStrategy::apply(pi, pj, pk);
int const side_qk_q = SideStrategy::apply(qi, qj, qk);
bool const both_continue = side_pk_p == 0 && side_qk_q == 0;
bool const robustness_issue_in_continue = both_continue && side_pk_q2 != 0;
bool const q_turns_left = side_qk_q == 1;
bool const block_q = side_qk_p1 == 0
&& ! same(side_qi_p1, side_qk_q);
&& ! same(side_qi_p1, side_qk_q)
&& ! robustness_issue_in_continue
;
// If Pk at same side as Qi/Qk
// (the "or" is for collinear case)
@@ -278,7 +284,7 @@ struct touch : public base_turn_handler
if (side_pk_q1 == 0)
{
ti.operations[0].operation = operation_blocked;
// Q turns right -> union (both independant),
// Q turns right -> union (both independent),
// Q turns left -> intersection
ti.operations[1].operation = block_q ? operation_blocked
: q_turns_left ? operation_intersection
@@ -463,6 +469,45 @@ struct equal : public base_turn_handler
};
template
<
typename TurnInfo,
typename AssignPolicy
>
struct equal_opposite : public base_turn_handler
{
template
<
typename Point1,
typename Point2,
typename OutputIterator,
typename IntersectionInfo,
typename DirInfo
>
static inline void apply(Point1 const& pi, Point2 const& qi,
/* by value: */ TurnInfo tp,
OutputIterator& out,
IntersectionInfo const& intersection_info,
DirInfo const& dir_info)
{
// For equal-opposite segments, normally don't do anything.
if (AssignPolicy::include_opposite)
{
tp.method = method_equal;
for (int i = 0; i < 2; i++)
{
tp.operations[i].operation = operation_opposite;
}
for (unsigned int i = 0; i < intersection_info.count; i++)
{
geometry::convert(intersection_info.intersections[i], tp.point);
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
*out++ = tp;
}
}
}
};
template
<
typename TurnInfo,
@@ -494,6 +539,13 @@ struct collinear : public base_turn_handler
- if P arrives and P turns right: intersection for P
- if Q arrives and Q turns left: union for Q (=intersection for P)
- if Q arrives and Q turns right: intersection for Q (=union for P)
ROBUSTNESS: p and q are collinear, so you would expect
that side qk//p1 == pk//q1. But that is not always the case
in near-epsilon ranges. Then decision logic is different.
If p arrives, q is further, so the angle qk//p1 is (normally)
more precise than pk//p1
*/
template
<
@@ -516,12 +568,18 @@ struct collinear : public base_turn_handler
// Should not be 0, this is checked before
BOOST_ASSERT(arrival != 0);
int const side_p = SideStrategy::apply(pi, pj, pk);
int const side_q = SideStrategy::apply(qi, qj, qk);
// If p arrives, use p, else use q
int const side_p_or_q = arrival == 1
? SideStrategy::apply(pi, pj, pk)
: SideStrategy::apply(qi, qj, qk)
? side_p
: side_q
;
int const side_pk = SideStrategy::apply(qi, qj, pk);
int const side_qk = SideStrategy::apply(pi, pj, qk);
// See comments above,
// resulting in a strange sort of mathematic rule here:
// The arrival-info multiplied by the relevant side
@@ -529,7 +587,15 @@ struct collinear : public base_turn_handler
int const product = arrival * side_p_or_q;
if(product == 0)
// Robustness: side_p is supposed to be equal to side_pk (because p/q are collinear)
// and side_q to side_qk
bool const robustness_issue = side_pk != side_p || side_qk != side_q;
if (robustness_issue)
{
handle_robustness(ti, arrival, side_p, side_q, side_pk, side_qk);
}
else if(product == 0)
{
both(ti, operation_continue);
}
@@ -538,6 +604,38 @@ struct collinear : public base_turn_handler
ui_else_iu(product == 1, ti);
}
}
static inline void handle_robustness(TurnInfo& ti, int arrival,
int side_p, int side_q, int side_pk, int side_qk)
{
// We take the longer one, i.e. if q arrives in p (arrival == -1),
// then p exceeds q and we should take p for a union...
bool use_p_for_union = arrival == -1;
// ... unless one of the sides consistently directs to the other side
int const consistent_side_p = side_p == side_pk ? side_p : 0;
int const consistent_side_q = side_q == side_qk ? side_q : 0;
if (arrival == -1 && (consistent_side_p == -1 || consistent_side_q == 1))
{
use_p_for_union = false;
}
if (arrival == 1 && (consistent_side_p == 1 || consistent_side_q == -1))
{
use_p_for_union = true;
}
//std::cout << "ROBUSTNESS -> Collinear "
// << " arr: " << arrival
// << " dir: " << side_p << " " << side_q
// << " rev: " << side_pk << " " << side_qk
// << " cst: " << cside_p << " " << cside_q
// << std::boolalpha << " " << use_p_for_union
// << std::endl;
ui_else_iu(use_p_for_union, ti);
}
};
template
@@ -583,6 +681,7 @@ private :
TurnInfo& tp, IntersectionInfo const& intersection_info)
{
int const side_rk_r = SideStrategy::apply(ri, rj, rk);
operation_type blocked = operation_blocked;
switch(side_rk_r)
{
@@ -596,15 +695,24 @@ private :
break;
case 0 :
// No turn on opposite collinear: block, do not traverse
// But this "xx" is ignored here, it is useless to include
// two operation blocked, so the whole point does not need
// But this "xx" is usually ignored, it is useless to include
// two operations blocked, so the whole point does not need
// to be generated.
// So return false to indicate nothing is to be done.
return false;
if (AssignPolicy::include_opposite)
{
tp.operations[Index].operation = operation_opposite;
blocked = operation_opposite;
}
else
{
return false;
}
break;
}
// The other direction is always blocked when collinear opposite
tp.operations[1 - Index].operation = operation_blocked;
tp.operations[1 - Index].operation = blocked;
// If P arrives within Q, set info on P (which is done above, index=0),
// this turn-info belongs to the second intersection point, index=1
@@ -633,32 +741,45 @@ public:
IntersectionInfo const& intersection_info,
DirInfo const& dir_info)
{
/*
std::cout << "arrivals: "
<< dir_info.arrival[0]
<< "/" << dir_info.arrival[1]
<< std::endl;
*/
TurnInfo tp = tp_model;
tp.method = method_collinear;
// If P arrives within Q, there is a turn dependant on P
// If P arrives within Q, there is a turn dependent on P
if (dir_info.arrival[0] == 1
&& set_tp<0>(pi, pj, pk, tp, intersection_info))
{
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
*out++ = tp;
}
// If Q arrives within P, there is a turn dependant on Q
// If Q arrives within P, there is a turn dependent on Q
if (dir_info.arrival[1] == 1
&& set_tp<1>(qi, qj, qk, tp, intersection_info))
{
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
*out++ = tp;
}
if (AssignPolicy::include_opposite)
{
// Handle cases not yet handled above
if ((dir_info.arrival[1] == -1 && dir_info.arrival[0] == 0)
|| (dir_info.arrival[0] == -1 && dir_info.arrival[1] == 0))
{
for (int i = 0; i < 2; i++)
{
tp.operations[i].operation = operation_opposite;
}
for (unsigned int i = 0; i < intersection_info.count; i++)
{
geometry::convert(intersection_info.intersections[i], tp.point);
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
*out++ = tp;
}
}
}
}
};
@@ -722,9 +843,17 @@ struct assign_null_policy
{
static bool const include_no_turn = false;
static bool const include_degenerate = false;
static bool const include_opposite = false;
template <typename Point1, typename Point2, typename Info>
static inline void apply(Info& , Point1 const& , Point2 const& )
template
<
typename Info,
typename Point1,
typename Point2,
typename IntersectionInfo,
typename DirInfo
>
static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&, DirInfo const&)
{}
};
@@ -763,8 +892,9 @@ struct get_turn_info
typedef typename si::segment_intersection_strategy_type strategy;
// Intersect pi-pj with qi-qj
// The points pk and qk are only used do determine more information
// about the turn.
template <typename OutputIterator>
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
@@ -796,7 +926,7 @@ struct get_turn_info
{
only_convert<TurnInfo>::apply(tp,
result.template get<0>());
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
break;
@@ -824,7 +954,7 @@ struct get_turn_info
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, result.template get<0>(), result.template get<1>());
}
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
break;
@@ -838,7 +968,7 @@ struct get_turn_info
policy::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
break;
@@ -853,7 +983,7 @@ struct get_turn_info
policy::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
break;
@@ -871,10 +1001,18 @@ struct get_turn_info
policy::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
// If they ARE opposite, don't do anything.
else
{
equal_opposite
<
TurnInfo,
AssignPolicy
>::apply(pi, qi,
tp, out, result.template get<0>(), result.template get<1>());
}
}
break;
case 'c' :
@@ -906,7 +1044,7 @@ struct get_turn_info
tp, result.template get<0>(), result.template get<1>());
}
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
else
@@ -927,7 +1065,7 @@ struct get_turn_info
if (AssignPolicy::include_degenerate)
{
only_convert<TurnInfo>::apply(tp, result.template get<0>());
AssignPolicy::apply(tp, pi, qi);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
*out++ = tp;
}
}
@@ -495,7 +495,7 @@ struct get_turns_cs
int source_id1, Range const& range,
int source_id2, Box const& box,
Turns& turns,
InterruptPolicy& ,
InterruptPolicy& interrupt_policy,
int multi_index = -1, int ring_index = -1)
{
if (boost::size(range) <= 1)
@@ -557,7 +557,7 @@ struct get_turns_cs
get_turns_with_box(seg_id, source_id2,
*prev, *it, *next,
bp[0], bp[1], bp[2], bp[3],
turns);
turns, interrupt_policy);
// Future performance enhancement:
// return if told by the interrupt policy
}
@@ -596,7 +596,8 @@ private:
box_point_type const& bp2,
box_point_type const& bp3,
// Output
Turns& turns)
Turns& turns,
InterruptPolicy& interrupt_policy)
{
// Depending on code some relations can be left out
@@ -622,6 +623,12 @@ private:
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);
TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1,
ti, std::back_inserter(turns));
if (InterruptPolicy::enabled)
{
interrupt_policy.apply(turns);
}
}
};
@@ -252,6 +252,32 @@ private :
: order == 1;
}
inline bool consider_ix_ix(Indexed const& left, Indexed const& right
, std::string const& // header
) const
{
// Take first intersection, then blocked.
if (left.subject.operation == operation_intersection
&& right.subject.operation == operation_blocked)
{
return true;
}
else if (left.subject.operation == operation_blocked
&& right.subject.operation == operation_intersection)
{
return false;
}
// Default case, should not occur
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
std::cout << "ix/ix unhandled" << std::endl;
#endif
//debug_consider(0, left, right, header, false, "-> return", ret);
return left.index < right.index;
}
inline bool consider_iu_iu(Indexed const& left, Indexed const& right,
std::string const& header) const
@@ -446,6 +472,11 @@ public :
{
return consider_iu_iu(left, right, "iu/iu");
}
else if (m_turn_points[left.index].combination(operation_intersection, operation_blocked)
&& m_turn_points[right.index].combination(operation_intersection, operation_blocked))
{
return consider_ix_ix(left, right, "ix/ix");
}
else if (m_turn_points[left.index].both(operation_intersection)
&& m_turn_points[right.index].both(operation_intersection))
{
@@ -493,7 +524,7 @@ public :
<< "/" << operation_char(m_turn_points[right.index].operations[0].operation)
<< operation_char(m_turn_points[right.index].operations[1].operation)
<< " " << " Take " << left.index << " < " << right.index
<< std::cout;
<< std::endl;
#endif
return default_order;
@@ -41,14 +41,14 @@ namespace boost { namespace geometry
namespace detail { namespace intersection
{
template
<
typename Segment1, typename Segment2,
typename OutputIterator, typename PointOut,
typename Strategy
>
template <typename PointOut>
struct intersection_segment_segment_point
{
template
<
typename Segment1, typename Segment2,
typename OutputIterator, typename Strategy
>
static inline OutputIterator apply(Segment1 const& segment1,
Segment2 const& segment2, OutputIterator out,
Strategy const& )
@@ -77,14 +77,14 @@ struct intersection_segment_segment_point
}
};
template
<
typename Linestring1, typename Linestring2,
typename OutputIterator, typename PointOut,
typename Strategy
>
template <typename PointOut>
struct intersection_linestring_linestring_point
{
template
<
typename Linestring1, typename Linestring2,
typename OutputIterator, typename Strategy
>
static inline OutputIterator apply(Linestring1 const& linestring1,
Linestring2 const& linestring2, OutputIterator out,
Strategy const& )
@@ -112,22 +112,12 @@ struct intersection_linestring_linestring_point
*/
template
<
typename LineString, typename Areal,
bool ReverseAreal,
typename OutputIterator, typename LineStringOut,
overlay_type OverlayType,
typename Strategy
typename LineStringOut,
overlay_type OverlayType
>
struct intersection_of_linestring_with_areal
{
typedef detail::overlay::follow
<
LineStringOut,
LineString,
Areal,
OverlayType
> follower;
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
template <typename Turn, typename Operation>
static inline void debug_follow(Turn const& turn, Operation op,
@@ -145,6 +135,11 @@ struct intersection_of_linestring_with_areal
}
#endif
template
<
typename LineString, typename Areal,
typename OutputIterator, typename Strategy
>
static inline OutputIterator apply(LineString const& linestring, Areal const& areal,
OutputIterator out,
Strategy const& )
@@ -154,6 +149,14 @@ struct intersection_of_linestring_with_areal
return out;
}
typedef detail::overlay::follow
<
LineStringOut,
LineString,
Areal,
OverlayType
> follower;
typedef typename point_type<LineStringOut>::type point_type;
typedef detail::overlay::traversal_turn_info<point_type> turn_info;
@@ -220,18 +223,22 @@ namespace dispatch
template
<
// tag dispatching:
typename TagIn1, typename TagIn2, typename TagOut,
// orientation
// metafunction finetuning helpers:
bool Areal1, bool Areal2, bool ArealOut,
// real types
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
// orientation
bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
// tag dispatching:
typename TagIn1 = typename geometry::tag<Geometry1>::type,
typename TagIn2 = typename geometry::tag<Geometry2>::type,
typename TagOut = typename geometry::tag<GeometryOut>::type,
// metafunction finetuning helpers:
bool Areal1 = geometry::is_areal<Geometry1>::value,
bool Areal2 = geometry::is_areal<Geometry2>::value,
bool ArealOut = geometry::is_areal<GeometryOut>::value
>
struct intersection_insert
{
@@ -245,122 +252,103 @@ struct intersection_insert
template
<
typename TagIn1, typename TagIn2, typename TagOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut,
typename TagIn1, typename TagIn2, typename TagOut
>
struct intersection_insert
<
TagIn1, TagIn2, TagOut,
true, true, true,
Geometry1, Geometry2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
GeometryOut,
OverlayType,
Strategy
Reverse1, Reverse2, ReverseOut,
TagIn1, TagIn2, TagOut,
true, true, true
> : detail::overlay::overlay
<Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, OutputIterator, GeometryOut, OverlayType, Strategy>
<Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
{};
// Any areal type with box:
template
<
typename TagIn, typename TagOut,
typename Geometry, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut,
typename TagIn, typename TagOut
>
struct intersection_insert
<
TagIn, box_tag, TagOut,
true, true, true,
Geometry, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
GeometryOut,
OverlayType,
Strategy
Reverse1, Reverse2, ReverseOut,
TagIn, box_tag, TagOut,
true, true, true
> : detail::overlay::overlay
<Geometry, Box, Reverse1, Reverse2, ReverseOut, OutputIterator, GeometryOut, OverlayType, Strategy>
<Geometry, Box, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
{};
template
<
typename Segment1, typename Segment2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut
>
struct intersection_insert
<
segment_tag, segment_tag, point_tag,
false, false, false,
Segment1, Segment2,
GeometryOut,
OverlayType,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
OverlayType, Strategy
> : detail::intersection::intersection_segment_segment_point
<
Segment1, Segment2,
OutputIterator, GeometryOut,
Strategy
>
segment_tag, segment_tag, point_tag,
false, false, false
> : detail::intersection::intersection_segment_segment_point<GeometryOut>
{};
template
<
typename Linestring1, typename Linestring2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut
>
struct intersection_insert
<
linestring_tag, linestring_tag, point_tag,
false, false, false,
Linestring1, Linestring2,
GeometryOut,
OverlayType,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
OverlayType, Strategy
> : detail::intersection::intersection_linestring_linestring_point
<
Linestring1, Linestring2,
OutputIterator, GeometryOut,
Strategy
>
linestring_tag, linestring_tag, point_tag,
false, false, false
> : detail::intersection::intersection_linestring_linestring_point<GeometryOut>
{};
template
<
typename Linestring, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut
>
struct intersection_insert
<
linestring_tag, box_tag, linestring_tag,
false, true, false,
Linestring, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
GeometryOut,
OverlayType,
Strategy
Reverse1, Reverse2, ReverseOut,
linestring_tag, box_tag, linestring_tag,
false, true, false
>
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Linestring const& linestring,
Box const& box, OutputIterator out, Strategy const& )
{
@@ -375,27 +363,23 @@ struct intersection_insert
template
<
typename Linestring, typename Polygon,
bool ReverseLinestring, bool ReversePolygon, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool ReverseLinestring, bool ReversePolygon, bool ReverseOut
>
struct intersection_insert
<
linestring_tag, polygon_tag, linestring_tag,
false, true, false,
Linestring, Polygon,
ReverseLinestring, ReversePolygon, ReverseOut,
OutputIterator, GeometryOut,
GeometryOut,
OverlayType,
Strategy
ReverseLinestring, ReversePolygon, ReverseOut,
linestring_tag, polygon_tag, linestring_tag,
false, true, false
> : detail::intersection::intersection_of_linestring_with_areal
<
Linestring, Polygon,
ReversePolygon,
OutputIterator, GeometryOut,
OverlayType,
Strategy
GeometryOut,
OverlayType
>
{};
@@ -403,49 +387,44 @@ struct intersection_insert
template
<
typename Linestring, typename Ring,
bool ReverseLinestring, bool ReverseRing, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool ReverseLinestring, bool ReverseRing, bool ReverseOut
>
struct intersection_insert
<
linestring_tag, ring_tag, linestring_tag,
false, true, false,
Linestring, Ring,
ReverseLinestring, ReverseRing, ReverseOut,
OutputIterator, GeometryOut,
GeometryOut,
OverlayType,
Strategy
ReverseLinestring, ReverseRing, ReverseOut,
linestring_tag, ring_tag, linestring_tag,
false, true, false
> : detail::intersection::intersection_of_linestring_with_areal
<
Linestring, Ring,
ReverseRing,
OutputIterator, GeometryOut,
OverlayType,
Strategy
GeometryOut,
OverlayType
>
{};
template
<
typename Segment, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut
>
struct intersection_insert
<
segment_tag, box_tag, linestring_tag,
false, true, false,
Segment, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
GeometryOut,
OverlayType,
Strategy
Reverse1, Reverse2, ReverseOut,
segment_tag, box_tag, linestring_tag,
false, true, false
>
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Segment const& segment,
Box const& box, OutputIterator out, Strategy const& )
{
@@ -460,25 +439,24 @@ struct intersection_insert
template
<
typename Tag1, typename Tag2,
bool Areal1, bool Areal2,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename PointOut,
typename PointOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut,
typename Tag1, typename Tag2,
bool Areal1, bool Areal2
>
struct intersection_insert
<
Tag1, Tag2, point_tag,
Areal1, Areal2, false,
Geometry1, Geometry2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, PointOut,
PointOut,
OverlayType,
Strategy
Reverse1, Reverse2, ReverseOut,
Tag1, Tag2, point_tag,
Areal1, Areal2, false
>
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, OutputIterator out, Strategy const& )
{
@@ -504,29 +482,22 @@ struct intersection_insert
template
<
typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
bool Areal1, bool Areal2, bool ArealOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Geometry1, typename Geometry2, typename GeometryOut,
overlay_type OverlayType,
typename Strategy
bool Reverse1, bool Reverse2, bool ReverseOut
>
struct intersection_insert_reversed
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry1 const& g1,
Geometry2 const& g2, OutputIterator out,
Strategy const& strategy)
{
return intersection_insert
<
GeometryTag2, GeometryTag1, GeometryTag3,
Areal2, Areal1, ArealOut,
Geometry2, Geometry1,
Reverse2, Reverse1, ReverseOut,
OutputIterator, GeometryOut,
Geometry2, Geometry1, GeometryOut,
OverlayType,
Strategy
Reverse2, Reverse1, ReverseOut
>::apply(g2, g1, out, strategy);
}
};
@@ -561,35 +532,20 @@ inline OutputIterator insert(Geometry1 const& geometry1,
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
geometry::dispatch::intersection_insert_reversed
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
GeometryOut,
OverlayType,
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value,
overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
OutputIterator, GeometryOut,
OverlayType,
Strategy
overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
>,
geometry::dispatch::intersection_insert
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
OutputIterator, GeometryOut,
GeometryOut,
OverlayType,
Strategy
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value
>
>::type::apply(geometry1, geometry2, out, strategy);
}
@@ -134,12 +134,12 @@ template
<
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
overlay_type Direction,
typename Strategy
typename GeometryOut,
overlay_type Direction
>
struct overlay
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(
Geometry1 const& geometry1, Geometry2 const& geometry2,
OutputIterator out,
@@ -233,7 +233,7 @@ std::cout << "traverse" << std::endl;
std::cout << "map_turns: " << timer.elapsed() << std::endl;
#endif
typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;
typedef ring_properties<typename geometry::point_type<GeometryOut>::type> properties;
std::map<ring_identifier, properties> selected;
select_rings<Direction>(geometry1, geometry2, map, selected, ! turn_points.empty());
@@ -17,7 +17,9 @@
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -233,6 +235,7 @@ public :
detail::overlay::operation_type operation,
Turns& turns, Rings& rings)
{
typedef typename boost::range_value<Rings>::type ring_type;
typedef typename boost::range_iterator<Turns>::type turn_iterator;
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename boost::range_iterator
@@ -240,6 +243,12 @@ public :
typename turn_type::container_type
>::type turn_operation_iterator_type;
std::size_t const min_num_points
= core_detail::closure::minimum_ring_size
<
geometry::closure<ring_type>::value
>::value;
std::size_t size_at_start = boost::size(rings);
typename Backtrack::state_type state;
@@ -267,7 +276,7 @@ public :
{
set_visited_for_continue(*it, *iit);
typename boost::range_value<Rings>::type current_output;
ring_type current_output;
detail::overlay::append_no_duplicates(current_output,
it->point, true);
@@ -376,7 +385,10 @@ public :
{
iit->visited.set_finished();
detail::overlay::debug_traverse(*current, *iit, "->Finished");
rings.push_back(current_output);
if (geometry::num_points(current_output) >= min_num_points)
{
rings.push_back(current_output);
}
}
}
}
@@ -28,7 +28,8 @@ enum operation_type
operation_union,
operation_intersection,
operation_blocked,
operation_continue
operation_continue,
operation_opposite
};
@@ -102,6 +103,12 @@ struct turn_info
{
return has12(type, type);
}
inline bool has(operation_type type) const
{
return this->operations[0].operation == type
|| this->operations[1].operation == type;
}
inline bool combination(operation_type type1, operation_type type2) const
{
@@ -114,10 +121,13 @@ struct turn_info
{
return both(operation_blocked);
}
inline bool opposite() const
{
return both(operation_opposite);
}
inline bool any_blocked() const
{
return this->operations[0].operation == operation_blocked
|| this->operations[1].operation == operation_blocked;
return has(operation_blocked);
}
@@ -153,12 +153,12 @@ class partition_one_collection
static inline void next_level(Box const& box,
InputCollection const& collection,
index_vector_type const& input,
int level, int min_elements,
int level, std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
if (boost::size(input) > 0)
{
if (boost::size(input) > min_elements && level < 100)
if (std::size_t(boost::size(input)) > min_elements && level < 100)
{
sub_divide::apply(box, collection, input, level + 1,
min_elements, policy, box_policy);
@@ -176,7 +176,7 @@ public :
InputCollection const& collection,
index_vector_type const& input,
int level,
int min_elements,
std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
box_policy.apply(box, level);
@@ -230,13 +230,13 @@ class partition_two_collections
index_vector_type const& input1,
InputCollection const& collection2,
index_vector_type const& input2,
int level, int min_elements,
int level, std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
if (boost::size(input1) > 0 && boost::size(input2) > 0)
{
if (boost::size(input1) > min_elements
&& boost::size(input2) > min_elements
if (std::size_t(boost::size(input1)) > min_elements
&& std::size_t(boost::size(input2)) > min_elements
&& level < 100)
{
sub_divide::apply(box, collection1, input1, collection2,
@@ -257,7 +257,7 @@ public :
InputCollection const& collection1, index_vector_type const& input1,
InputCollection const& collection2, index_vector_type const& input2,
int level,
int min_elements,
std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
box_policy.apply(box, level);
@@ -335,11 +335,11 @@ public :
template <typename InputCollection, typename VisitPolicy>
static inline void apply(InputCollection const& collection,
VisitPolicy& visitor,
int min_elements = 16,
std::size_t min_elements = 16,
VisitBoxPolicy box_visitor = visit_no_policy()
)
{
if (boost::size(collection) > min_elements)
if (std::size_t(boost::size(collection)) > min_elements)
{
index_vector_type index_vector;
Box total;
@@ -377,12 +377,12 @@ public :
static inline void apply(InputCollection const& collection1,
InputCollection const& collection2,
VisitPolicy& visitor,
int min_elements = 16,
std::size_t min_elements = 16,
VisitBoxPolicy box_visitor = visit_no_policy()
)
{
if (boost::size(collection1) > min_elements
&& boost::size(collection2) > min_elements)
if (std::size_t(boost::size(collection1)) > min_elements
&& std::size_t(boost::size(collection2)) > min_elements)
{
index_vector_type index_vector1, index_vector2;
Box total;
@@ -25,6 +25,7 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint.hpp>
@@ -50,7 +51,8 @@ struct get_point
template<typename Point, std::size_t Dimension, std::size_t DimensionCount>
struct midpoint_helper
{
static inline bool apply(Point& p, Point const& p1, Point const& p2)
template <typename InputPoint>
static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2)
{
typename coordinate_type<Point>::type const two = 2;
set<Dimension>(p,
@@ -63,7 +65,8 @@ struct midpoint_helper
template <typename Point, std::size_t DimensionCount>
struct midpoint_helper<Point, DimensionCount, DimensionCount>
{
static inline bool apply(Point& , Point const& , Point const& )
template <typename InputPoint>
static inline bool apply(Point& , InputPoint const& , InputPoint const& )
{
return true;
}
@@ -102,7 +105,7 @@ struct point_on_range
if (n > 0)
{
point = *boost::begin(range);
geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point);
return true;
}
return false;
@@ -254,7 +254,7 @@ struct sectionalize_part
Range const& range,
ring_identifier ring_id)
{
if (boost::size(range) <= index)
if (int(boost::size(range)) <= index)
{
return;
}
@@ -56,19 +56,11 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
return geometry::dispatch::intersection_insert
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
OutputIterator, GeometryOut,
GeometryOut,
overlay_difference,
Strategy
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
>::apply(geometry1, geometry2, out, strategy);
}
@@ -27,6 +27,7 @@
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/algorithms/detail/disjoint.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/within.hpp>
@@ -44,15 +45,57 @@ namespace boost { namespace geometry
namespace detail { namespace disjoint
{
template<typename Geometry>
struct check_each_ring_for_within
{
bool has_within;
Geometry const& m_geometry;
inline check_each_ring_for_within(Geometry const& g)
: has_within(false)
, m_geometry(g)
{}
template <typename Range>
inline void apply(Range const& range)
{
typename geometry::point_type<Range>::type p;
geometry::point_on_border(p, range);
if (geometry::within(p, m_geometry))
{
has_within = true;
}
}
};
template <typename FirstGeometry, typename SecondGeometry>
inline bool rings_containing(FirstGeometry const& geometry1,
SecondGeometry const& geometry2)
{
check_each_ring_for_within<FirstGeometry> checker(geometry1);
geometry::detail::for_each_range(geometry2, checker);
return checker.has_within;
}
struct assign_disjoint_policy
{
// We want to include all points:
static bool const include_no_turn = true;
static bool const include_degenerate = true;
static bool const include_opposite = true;
// We don't assign extra info:
template <typename Point1, typename Point2, typename Info>
static inline void apply(Info& , Point1 const& , Point2 const& )
template
<
typename Info,
typename Point1,
typename Point2,
typename IntersectionInfo,
typename DirInfo
>
static inline void apply(Info& , Point1 const& , Point2 const&,
IntersectionInfo const&, DirInfo const&)
{}
};
@@ -107,8 +150,6 @@ struct disjoint_segment
}
};
template <typename Geometry1, typename Geometry2>
struct general_areal
{
@@ -119,20 +160,10 @@ struct general_areal
return false;
}
typedef typename geometry::point_type<Geometry1>::type point_type;
// If there is no intersection of segments, they might located
// inside each other
point_type p1;
geometry::point_on_border(p1, geometry1);
if (geometry::within(p1, geometry2))
{
return false;
}
typename geometry::point_type<Geometry1>::type p2;
geometry::point_on_border(p2, geometry2);
if (geometry::within(p2, geometry1))
if (rings_containing(geometry1, geometry2)
|| rings_containing(geometry2, geometry1))
{
return false;
}
@@ -153,68 +184,82 @@ namespace dispatch
template
<
typename GeometryTag1, typename GeometryTag2,
typename Geometry1, typename Geometry2,
std::size_t DimensionCount
std::size_t DimensionCount = dimension<Geometry1>::type::value,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct disjoint
: detail::disjoint::general_areal<Geometry1, Geometry2>
{};
template <typename Point1, typename Point2, std::size_t DimensionCount>
struct disjoint<point_tag, point_tag, Point1, Point2, DimensionCount>
: detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct disjoint<box_tag, box_tag, Box1, Box2, DimensionCount>
: detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
{};
template <typename Point, typename Box, std::size_t DimensionCount>
struct disjoint<point_tag, box_tag, Point, Box, DimensionCount>
: detail::disjoint::point_box<Point, Box, 0, DimensionCount>
{};
template <typename Linestring1, typename Linestring2>
struct disjoint<linestring_tag, linestring_tag, Linestring1, Linestring2, 2>
: detail::disjoint::disjoint_linear<Linestring1, Linestring2>
{};
template <typename Linestring1, typename Linestring2>
struct disjoint<segment_tag, segment_tag, Linestring1, Linestring2, 2>
: detail::disjoint::disjoint_segment<Linestring1, Linestring2>
{};
template <typename Linestring, typename Segment>
struct disjoint<linestring_tag, segment_tag, Linestring, Segment, 2>
: detail::disjoint::disjoint_linear<Linestring, Segment>
{};
// If reversal is needed, perform it
template
<
typename GeometryTag1, typename GeometryTag2,
typename Geometry1, typename Geometry2,
std::size_t DimensionCount
std::size_t DimensionCount,
typename Tag1, typename Tag2
>
struct disjoint_reversed
struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true>
: disjoint<Geometry2, Geometry1, DimensionCount, Tag2, Tag1, false>
{
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
{
return disjoint
<
GeometryTag2, GeometryTag1,
Geometry2, Geometry1,
DimensionCount
DimensionCount,
Tag2, Tag1
>::apply(g2, g1);
}
};
template <typename Point1, typename Point2, std::size_t DimensionCount, bool Reverse>
struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, Reverse>
: detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, Reverse>
: detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
{};
template <typename Point, typename Box, std::size_t DimensionCount, bool Reverse>
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, Reverse>
: detail::disjoint::point_box<Point, Box, 0, DimensionCount>
{};
template <typename Point, typename Ring, std::size_t DimensionCount, bool Reverse>
struct disjoint<Point, Ring, DimensionCount, point_tag, ring_tag, Reverse>
: detail::disjoint::reverse_covered_by<Point, Ring>
{};
template <typename Point, typename Polygon, std::size_t DimensionCount, bool Reverse>
struct disjoint<Point, Polygon, DimensionCount, point_tag, polygon_tag, Reverse>
: detail::disjoint::reverse_covered_by<Point, Polygon>
{};
template <typename Linestring1, typename Linestring2, bool Reverse>
struct disjoint<Linestring1, Linestring2, 2, linestring_tag, linestring_tag, Reverse>
: detail::disjoint::disjoint_linear<Linestring1, Linestring2>
{};
template <typename Linestring1, typename Linestring2, bool Reverse>
struct disjoint<Linestring1, Linestring2, 2, segment_tag, segment_tag, Reverse>
: detail::disjoint::disjoint_segment<Linestring1, Linestring2>
{};
template <typename Linestring, typename Segment, bool Reverse>
struct disjoint<Linestring, Segment, 2, linestring_tag, segment_tag, Reverse>
: detail::disjoint::disjoint_linear<Linestring, Segment>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
@@ -241,26 +286,7 @@ inline bool disjoint(Geometry1 const& geometry1,
Geometry2 const
>();
return boost::mpl::if_c
<
reverse_dispatch<Geometry1, Geometry2>::type::value,
dispatch::disjoint_reversed
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
Geometry1,
Geometry2,
dimension<Geometry1>::type::value
>,
dispatch::disjoint
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
Geometry1,
Geometry2,
dimension<Geometry1>::type::value
>
>::type::apply(geometry1, geometry2);
return dispatch::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
}
@@ -130,7 +130,7 @@ struct point_to_range
// check if other segments are closer
for (++prev, ++it; it != boost::end(view); ++prev, ++it)
{
return_type const ds = ps_strategy.apply(point, *prev, *it);
return_type const ds = eps_strategy.apply(point, *prev, *it);
if (geometry::math::equals(ds, zero))
{
return ds;
@@ -369,7 +369,10 @@ struct distance
<
segment_tag,
Point,
typename point_type<Linestring>::type
typename point_type<Linestring>::type,
typename cs_tag<Point>::type,
typename cs_tag<typename point_type<Linestring>::type>::type,
Strategy
>::type ps_strategy_type;
return detail::distance::point_to_range
@@ -14,13 +14,13 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -35,9 +35,9 @@ namespace detail { namespace envelope
/// Calculate envelope of an 2D or 3D segment
template<typename Geometry, typename Box>
struct envelope_expand_one
{
template<typename Geometry, typename Box>
static inline void apply(Geometry const& geometry, Box& mbr)
{
assign_inverse(mbr);
@@ -63,10 +63,10 @@ inline void envelope_range_additional(Range const& range, Box& mbr)
/// Generic range dispatching struct
template <typename Range, typename Box>
struct envelope_range
{
/// Calculate envelope of range using a strategy
template <typename Range, typename Box>
static inline void apply(Range const& range, Box& mbr)
{
assign_inverse(mbr);
@@ -82,122 +82,54 @@ namespace dispatch
{
// Note, the strategy is for future use (less/greater -> compare spherical
// using other methods), defaults are OK for now.
// However, they are already in the template methods
template
<
typename Tag1, typename Tag2,
typename Geometry, typename Box,
typename StrategyLess, typename StrategyGreater
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct envelope
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (types<Geometry>)
);
};
struct envelope: not_implemented<Tag>
{};
template
<
typename Point, typename Box,
typename StrategyLess, typename StrategyGreater
>
struct envelope
<
point_tag, box_tag,
Point, Box,
StrategyLess, StrategyGreater
>
: detail::envelope::envelope_expand_one<Point, Box>
template <typename Point>
struct envelope<Point, point_tag>
: detail::envelope::envelope_expand_one
{};
template
<
typename BoxIn, typename BoxOut,
typename StrategyLess, typename StrategyGreater
>
struct envelope
<
box_tag, box_tag,
BoxIn, BoxOut,
StrategyLess, StrategyGreater
>
: detail::envelope::envelope_expand_one<BoxIn, BoxOut>
template <typename Box>
struct envelope<Box, box_tag>
: detail::envelope::envelope_expand_one
{};
template
<
typename Segment, typename Box,
typename StrategyLess, typename StrategyGreater
>
struct envelope
<
segment_tag, box_tag,
Segment, Box,
StrategyLess, StrategyGreater
>
: detail::envelope::envelope_expand_one<Segment, Box>
template <typename Segment>
struct envelope<Segment, segment_tag>
: detail::envelope::envelope_expand_one
{};
template
<
typename Linestring, typename Box,
typename StrategyLess, typename StrategyGreater
>
struct envelope
<
linestring_tag, box_tag,
Linestring, Box,
StrategyLess, StrategyGreater
>
: detail::envelope::envelope_range<Linestring, Box>
template <typename Linestring>
struct envelope<Linestring, linestring_tag>
: detail::envelope::envelope_range
{};
template
<
typename Ring, typename Box,
typename StrategyLess, typename StrategyGreater
>
struct envelope
<
ring_tag, box_tag,
Ring, Box,
StrategyLess, StrategyGreater
>
: detail::envelope::envelope_range<Ring, Box>
template <typename Ring>
struct envelope<Ring, ring_tag>
: detail::envelope::envelope_range
{};
template
<
typename Polygon, typename Box,
typename StrategyLess, typename StrategyGreater
>
struct envelope
<
polygon_tag, box_tag,
Polygon, Box,
StrategyLess, StrategyGreater
>
template <typename Polygon>
struct envelope<Polygon, polygon_tag>
: detail::envelope::envelope_range
{
template <typename Box>
static inline void apply(Polygon const& poly, Box& mbr)
{
// For polygon, inspecting outer ring is sufficient
detail::envelope::envelope_range
<
typename ring_type<Polygon>::type,
Box
>::apply(exterior_ring(poly), mbr);
detail::envelope::envelope_range::apply(exterior_ring(poly), mbr);
}
};
@@ -228,12 +160,7 @@ inline void envelope(Geometry const& geometry, Box& mbr)
concept::check<Geometry const>();
concept::check<Box>();
dispatch::envelope
<
typename tag<Geometry>::type, typename tag<Box>::type,
Geometry, Box,
void, void
>::apply(geometry, mbr);
dispatch::envelope<Geometry>::apply(geometry, mbr);
}
@@ -259,12 +186,7 @@ inline Box return_envelope(Geometry const& geometry)
concept::check<Box>();
Box mbr;
dispatch::envelope
<
typename tag<Geometry>::type, typename tag<Box>::type,
Geometry, Box,
void, void
>::apply(geometry, mbr);
dispatch::envelope<Geometry>::apply(geometry, mbr);
return mbr;
}
@@ -18,8 +18,6 @@
#include <cstddef>
#include <vector>
#include <boost/mpl/if.hpp>
#include <boost/static_assert.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/access.hpp>
@@ -30,6 +28,7 @@
#include <boost/geometry/algorithms/detail/disjoint.hpp>
#include <boost/geometry/algorithms/detail/not.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
// For trivial checks
#include <boost/geometry/algorithms/area.hpp>
@@ -51,13 +50,12 @@ namespace detail { namespace equals
template
<
typename Box1,
typename Box2,
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
@@ -65,13 +63,14 @@ struct box_box
{
return false;
}
return box_box<Box1, Box2, Dimension + 1, DimensionCount>::apply(box1, box2);
return box_box<Dimension + 1, DimensionCount>::apply(box1, box2);
}
};
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct box_box<Box1, Box2, DimensionCount, DimensionCount>
template <std::size_t DimensionCount>
struct box_box<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& , Box2 const& )
{
return true;
@@ -103,9 +102,10 @@ struct length_check
};
template <typename Geometry1, typename Geometry2, typename TrivialCheck>
template <typename TrivialCheck>
struct equals_by_collection
{
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
if (! TrivialCheck::apply(geometry1, geometry2))
@@ -152,17 +152,42 @@ namespace dispatch
template
<
typename Tag1, typename Tag2,
typename Geometry1,
typename Geometry2,
std::size_t DimensionCount
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
std::size_t DimensionCount = dimension<Geometry1>::type::value,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct equals
struct equals: not_implemented<Tag1, Tag2>
{};
template <typename P1, typename P2, std::size_t DimensionCount>
struct equals<point_tag, point_tag, P1, P2, DimensionCount>
// If reversal is needed, perform it
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
std::size_t DimensionCount
>
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
{
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
{
return equals
<
Geometry2, Geometry1,
Tag2, Tag1,
DimensionCount,
false
>::apply(g2, g1);
}
};
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
: geometry::detail::not_
<
P1,
@@ -172,93 +197,48 @@ struct equals<point_tag, point_tag, P1, P2, DimensionCount>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct equals<box_tag, box_tag, Box1, Box2, DimensionCount>
: detail::equals::box_box<Box1, Box2, 0, DimensionCount>
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
: detail::equals::box_box<0, DimensionCount>
{};
template <typename Ring1, typename Ring2>
struct equals<ring_tag, ring_tag, Ring1, Ring2, 2>
: detail::equals::equals_by_collection
<
Ring1, Ring2,
detail::equals::area_check
>
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Polygon1, typename Polygon2>
struct equals<polygon_tag, polygon_tag, Polygon1, Polygon2, 2>
: detail::equals::equals_by_collection
<
Polygon1, Polygon2,
detail::equals::area_check
>
template <typename Polygon1, typename Polygon2, bool Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename LineString1, typename LineString2>
struct equals<linestring_tag, linestring_tag, LineString1, LineString2, 2>
: detail::equals::equals_by_collection
<
LineString1, LineString2,
detail::equals::length_check
>
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::length_check>
{};
template <typename Polygon, typename Ring>
struct equals<polygon_tag, ring_tag, Polygon, Ring, 2>
: detail::equals::equals_by_collection
<
Polygon, Ring,
detail::equals::area_check
>
template <typename Polygon, typename Ring, bool Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Ring, typename Box>
struct equals<ring_tag, box_tag, Ring, Box, 2>
: detail::equals::equals_by_collection
<
Ring, Box,
detail::equals::area_check
>
template <typename Ring, typename Box, bool Reverse>
struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Polygon, typename Box>
struct equals<polygon_tag, box_tag, Polygon, Box, 2>
: detail::equals::equals_by_collection
<
Polygon, Box,
detail::equals::area_check
>
template <typename Polygon, typename Box, bool Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template
<
typename Tag1, typename Tag2,
typename Geometry1,
typename Geometry2,
std::size_t DimensionCount
>
struct equals_reversed
{
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
{
return equals
<
Tag2, Tag1,
Geometry2, Geometry1,
DimensionCount
>::apply(g2, g1);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
@@ -289,26 +269,7 @@ inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
Geometry2 const
>();
return boost::mpl::if_c
<
reverse_dispatch<Geometry1, Geometry2>::type::value,
dispatch::equals_reversed
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
Geometry1,
Geometry2,
dimension<Geometry1>::type::value
>,
dispatch::equals
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
Geometry1,
Geometry2,
dimension<Geometry1>::type::value
>
>::type::apply(geometry1, geometry2);
return dispatch::equals<Geometry1, Geometry2>::apply(geometry1, geometry2);
}
@@ -19,6 +19,7 @@
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -38,26 +39,26 @@ namespace detail { namespace expand
template
<
typename Box, typename Point,
typename StrategyLess, typename StrategyGreater,
std::size_t Dimension, std::size_t DimensionCount
>
struct point_loop
{
typedef typename strategy::compare::detail::select_strategy
<
StrategyLess, 1, Point, Dimension
>::type less_type;
typedef typename strategy::compare::detail::select_strategy
<
StrategyGreater, -1, Point, Dimension
>::type greater_type;
typedef typename select_coordinate_type<Point, Box>::type coordinate_type;
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& source)
{
typedef typename strategy::compare::detail::select_strategy
<
StrategyLess, 1, Point, Dimension
>::type less_type;
typedef typename strategy::compare::detail::select_strategy
<
StrategyGreater, -1, Point, Dimension
>::type greater_type;
typedef typename select_coordinate_type<Point, Box>::type coordinate_type;
less_type less;
greater_type greater;
@@ -75,7 +76,6 @@ struct point_loop
point_loop
<
Box, Point,
StrategyLess, StrategyGreater,
Dimension + 1, DimensionCount
>::apply(box, source);
@@ -85,49 +85,47 @@ struct point_loop
template
<
typename Box, typename Point,
typename StrategyLess, typename StrategyGreater,
std::size_t DimensionCount
>
struct point_loop
<
Box, Point,
StrategyLess, StrategyGreater,
DimensionCount, DimensionCount
>
{
template <typename Box, typename Point>
static inline void apply(Box&, Point const&) {}
};
template
<
typename Box, typename Geometry,
typename StrategyLess, typename StrategyGreater,
std::size_t Index,
std::size_t Dimension, std::size_t DimensionCount
>
struct indexed_loop
{
typedef typename strategy::compare::detail::select_strategy
<
StrategyLess, 1, Box, Dimension
>::type less_type;
typedef typename strategy::compare::detail::select_strategy
<
StrategyGreater, -1, Box, Dimension
>::type greater_type;
typedef typename select_coordinate_type
<
Box,
Geometry
>::type coordinate_type;
template <typename Box, typename Geometry>
static inline void apply(Box& box, Geometry const& source)
{
typedef typename strategy::compare::detail::select_strategy
<
StrategyLess, 1, Box, Dimension
>::type less_type;
typedef typename strategy::compare::detail::select_strategy
<
StrategyGreater, -1, Box, Dimension
>::type greater_type;
typedef typename select_coordinate_type
<
Box,
Geometry
>::type coordinate_type;
less_type less;
greater_type greater;
@@ -145,7 +143,6 @@ struct indexed_loop
indexed_loop
<
Box, Geometry,
StrategyLess, StrategyGreater,
Index, Dimension + 1, DimensionCount
>::apply(box, source);
@@ -155,17 +152,16 @@ struct indexed_loop
template
<
typename Box, typename Geometry,
typename StrategyLess, typename StrategyGreater,
std::size_t Index, std::size_t DimensionCount
>
struct indexed_loop
<
Box, Geometry,
StrategyLess, StrategyGreater,
Index, DimensionCount, DimensionCount
>
{
template <typename Box, typename Geometry>
static inline void apply(Box&, Geometry const&) {}
};
@@ -174,23 +170,21 @@ struct indexed_loop
// Changes a box such that the other box is also contained by the box
template
<
typename Box, typename Geometry,
typename StrategyLess, typename StrategyGreater
>
struct expand_indexed
{
template <typename Box, typename Geometry>
static inline void apply(Box& box, Geometry const& geometry)
{
indexed_loop
<
Box, Geometry,
StrategyLess, StrategyGreater,
0, 0, dimension<Geometry>::type::value
>::apply(box, geometry);
indexed_loop
<
Box, Geometry,
StrategyLess, StrategyGreater,
1, 0, dimension<Geometry>::type::value
>::apply(box, geometry);
@@ -206,11 +200,13 @@ namespace dispatch
template
<
typename Tag,
typename BoxOut, typename Geometry,
typename StrategyLess, typename StrategyGreater
typename GeometryOut, typename Geometry,
typename StrategyLess = strategy::compare::default_strategy,
typename StrategyGreater = strategy::compare::default_strategy,
typename TagOut = typename tag<GeometryOut>::type,
typename Tag = typename tag<Geometry>::type
>
struct expand
struct expand: not_implemented<TagOut, Tag>
{};
@@ -220,10 +216,9 @@ template
typename BoxOut, typename Point,
typename StrategyLess, typename StrategyGreater
>
struct expand<point_tag, BoxOut, Point, StrategyLess, StrategyGreater>
struct expand<BoxOut, Point, StrategyLess, StrategyGreater, box_tag, point_tag>
: detail::expand::point_loop
<
BoxOut, Point,
StrategyLess, StrategyGreater,
0, dimension<Point>::type::value
>
@@ -236,9 +231,8 @@ template
typename BoxOut, typename BoxIn,
typename StrategyLess, typename StrategyGreater
>
struct expand<box_tag, BoxOut, BoxIn, StrategyLess, StrategyGreater>
: detail::expand::expand_indexed
<BoxOut, BoxIn, StrategyLess, StrategyGreater>
struct expand<BoxOut, BoxIn, StrategyLess, StrategyGreater, box_tag, box_tag>
: detail::expand::expand_indexed<StrategyLess, StrategyGreater>
{};
template
@@ -246,9 +240,8 @@ template
typename Box, typename Segment,
typename StrategyLess, typename StrategyGreater
>
struct expand<segment_tag, Box, Segment, StrategyLess, StrategyGreater>
: detail::expand::expand_indexed
<Box, Segment, StrategyLess, StrategyGreater>
struct expand<Box, Segment, StrategyLess, StrategyGreater, box_tag, segment_tag>
: detail::expand::expand_indexed<StrategyLess, StrategyGreater>
{};
@@ -279,13 +272,7 @@ inline void expand(Box& box, Geometry const& geometry,
{
concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
dispatch::expand
<
typename tag<Geometry>::type,
Box,
Geometry,
StrategyLess, StrategyGreater
>::apply(box, geometry);
dispatch::expand<Box, Geometry>::apply(box, geometry);
}
***/
@@ -305,13 +292,7 @@ inline void expand(Box& box, Geometry const& geometry)
{
concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
dispatch::expand
<
typename tag<Geometry>::type,
Box, Geometry,
strategy::compare::default_strategy,
strategy::compare::default_strategy
>::apply(box, geometry);
dispatch::expand<Box, Geometry>::apply(box, geometry);
}
}} // namespace boost::geometry
@@ -18,8 +18,10 @@
#include <algorithm>
#include <boost/range.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag_cast.hpp>
@@ -39,53 +41,55 @@ namespace detail { namespace for_each
{
template <typename Point, typename Functor, bool IsConst>
struct fe_point_per_point
{
static inline Functor apply(
typename add_const_if_c<IsConst, Point>::type& point, Functor f)
template <typename Point, typename Functor>
static inline void apply(Point& point, Functor& f)
{
f(point);
return f;
}
};
template <typename Point, typename Functor, bool IsConst>
struct fe_point_per_segment
{
static inline Functor apply(
typename add_const_if_c<IsConst, Point>::type& , Functor f)
template <typename Point, typename Functor>
static inline void apply(Point& , Functor& f)
{
// TODO: if non-const, we should extract the points from the segment
// and call the functor on those two points
return f;
}
};
template <typename Range, typename Functor, bool IsConst>
struct fe_range_per_point
{
static inline Functor apply(
typename add_const_if_c<IsConst, Range>::type& range,
Functor f)
template <typename Range, typename Functor>
static inline void apply(Range& range, Functor& f)
{
return (std::for_each(boost::begin(range), boost::end(range), f));
// The previous implementation called the std library:
// return (std::for_each(boost::begin(range), boost::end(range), f));
// But that is not accepted for capturing lambda's.
// It needs to do it like that to return the state of Functor f (f is passed by value in std::for_each).
// So we now loop manually.
for (typename boost::range_iterator<Range>::type it = boost::begin(range); it != boost::end(range); ++it)
{
f(*it);
}
}
};
template <typename Range, typename Functor, bool IsConst>
struct fe_range_per_segment
{
static inline Functor apply(
typename add_const_if_c<IsConst, Range>::type& range,
Functor f)
template <typename Range, typename Functor>
static inline void apply(Range& range, Functor& f)
{
typedef typename add_const_if_c
<
IsConst,
is_const<Range>::value,
typename point_type<Range>::type
>::type point_type;
@@ -97,65 +101,41 @@ struct fe_range_per_segment
f(s);
previous = it++;
}
return f;
}
};
template <typename Polygon, typename Functor, bool IsConst>
struct fe_polygon_per_point
{
typedef typename add_const_if_c<IsConst, Polygon>::type poly_type;
static inline Functor apply(poly_type& poly, Functor f)
template <typename Polygon, typename Functor>
static inline void apply(Polygon& poly, Functor& f)
{
typedef fe_range_per_point
<
typename ring_type<Polygon>::type,
Functor,
IsConst
> per_ring;
fe_range_per_point::apply(exterior_ring(poly), f);
f = per_ring::apply(exterior_ring(poly), f);
typename interior_return_type<poly_type>::type rings
typename interior_return_type<Polygon>::type rings
= interior_rings(poly);
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
{
f = per_ring::apply(*it, f);
fe_range_per_point::apply(*it, f);
}
return f;
}
};
template <typename Polygon, typename Functor, bool IsConst>
struct fe_polygon_per_segment
{
typedef typename add_const_if_c<IsConst, Polygon>::type poly_type;
static inline Functor apply(poly_type& poly, Functor f)
template <typename Polygon, typename Functor>
static inline void apply(Polygon& poly, Functor& f)
{
typedef fe_range_per_segment
<
typename ring_type<Polygon>::type,
Functor,
IsConst
> per_ring;
fe_range_per_segment::apply(exterior_ring(poly), f);
f = per_ring::apply(exterior_ring(poly), f);
typename interior_return_type<poly_type>::type rings
typename interior_return_type<Polygon>::type rings
= interior_rings(poly);
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
{
f = per_ring::apply(*it, f);
fe_range_per_segment::apply(*it, f);
}
return f;
}
};
@@ -171,68 +151,66 @@ namespace dispatch
template
<
typename Tag,
typename Geometry,
typename Functor,
bool IsConst
typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
>
struct for_each_point {};
template <typename Point, typename Functor, bool IsConst>
struct for_each_point<point_tag, Point, Functor, IsConst>
: detail::for_each::fe_point_per_point<Point, Functor, IsConst>
struct for_each_point: not_implemented<Tag>
{};
template <typename Linestring, typename Functor, bool IsConst>
struct for_each_point<linestring_tag, Linestring, Functor, IsConst>
: detail::for_each::fe_range_per_point<Linestring, Functor, IsConst>
template <typename Point>
struct for_each_point<Point, point_tag>
: detail::for_each::fe_point_per_point
{};
template <typename Ring, typename Functor, bool IsConst>
struct for_each_point<ring_tag, Ring, Functor, IsConst>
: detail::for_each::fe_range_per_point<Ring, Functor, IsConst>
template <typename Linestring>
struct for_each_point<Linestring, linestring_tag>
: detail::for_each::fe_range_per_point
{};
template <typename Polygon, typename Functor, bool IsConst>
struct for_each_point<polygon_tag, Polygon, Functor, IsConst>
: detail::for_each::fe_polygon_per_point<Polygon, Functor, IsConst>
template <typename Ring>
struct for_each_point<Ring, ring_tag>
: detail::for_each::fe_range_per_point
{};
template <typename Polygon>
struct for_each_point<Polygon, polygon_tag>
: detail::for_each::fe_polygon_per_point
{};
template
<
typename Tag,
typename Geometry,
typename Functor,
bool IsConst
typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
>
struct for_each_segment {};
struct for_each_segment: not_implemented<Tag>
{};
template <typename Point, typename Functor, bool IsConst>
struct for_each_segment<point_tag, Point, Functor, IsConst>
: detail::for_each::fe_point_per_segment<Point, Functor, IsConst>
template <typename Point>
struct for_each_segment<Point, point_tag>
: detail::for_each::fe_point_per_segment
{};
template <typename Linestring, typename Functor, bool IsConst>
struct for_each_segment<linestring_tag, Linestring, Functor, IsConst>
: detail::for_each::fe_range_per_segment<Linestring, Functor, IsConst>
template <typename Linestring>
struct for_each_segment<Linestring, linestring_tag>
: detail::for_each::fe_range_per_segment
{};
template <typename Ring, typename Functor, bool IsConst>
struct for_each_segment<ring_tag, Ring, Functor, IsConst>
: detail::for_each::fe_range_per_segment<Ring, Functor, IsConst>
template <typename Ring>
struct for_each_segment<Ring, ring_tag>
: detail::for_each::fe_range_per_segment
{};
template <typename Polygon, typename Functor, bool IsConst>
struct for_each_segment<polygon_tag, Polygon, Functor, IsConst>
: detail::for_each::fe_polygon_per_segment<Polygon, Functor, IsConst>
template <typename Polygon>
struct for_each_segment<Polygon, polygon_tag>
: detail::for_each::fe_polygon_per_segment
{};
@@ -240,35 +218,6 @@ struct for_each_segment<polygon_tag, Polygon, Functor, IsConst>
#endif // DOXYGEN_NO_DISPATCH
/*!
\brief \brf_for_each{point}
\details \det_for_each{point}
\ingroup for_each
\param geometry \param_geometry
\param f \par_for_each_f{const point}
\tparam Geometry \tparam_geometry
\tparam Functor \tparam_functor
\qbk{distinguish,const version}
\qbk{[include reference/algorithms/for_each_point.qbk]}
\qbk{[heading Example]}
\qbk{[for_each_point_const] [for_each_point_const_output]}
*/
template<typename Geometry, typename Functor>
inline Functor for_each_point(Geometry const& geometry, Functor f)
{
concept::check<Geometry const>();
return dispatch::for_each_point
<
typename tag_cast<typename tag<Geometry>::type, multi_tag>::type,
Geometry,
Functor,
true
>::apply(geometry, f);
}
/*!
\brief \brf_for_each{point}
\details \det_for_each{point}
@@ -281,48 +230,15 @@ inline Functor for_each_point(Geometry const& geometry, Functor f)
\qbk{[include reference/algorithms/for_each_point.qbk]}
\qbk{[heading Example]}
\qbk{[for_each_point] [for_each_point_output]}
\qbk{[for_each_point_const] [for_each_point_const_output]}
*/
template<typename Geometry, typename Functor>
inline Functor for_each_point(Geometry& geometry, Functor f)
{
concept::check<Geometry>();
return dispatch::for_each_point
<
typename tag_cast<typename tag<Geometry>::type, multi_tag>::type,
Geometry,
Functor,
false
>::apply(geometry, f);
}
/*!
\brief \brf_for_each{segment}
\details \det_for_each{segment}
\ingroup for_each
\param geometry \param_geometry
\param f \par_for_each_f{const segment}
\tparam Geometry \tparam_geometry
\tparam Functor \tparam_functor
\qbk{distinguish,const version}
\qbk{[include reference/algorithms/for_each_segment.qbk]}
\qbk{[heading Example]}
\qbk{[for_each_segment_const] [for_each_segment_const_output]}
*/
template<typename Geometry, typename Functor>
inline Functor for_each_segment(Geometry const& geometry, Functor f)
{
concept::check<Geometry const>();
return dispatch::for_each_segment
<
typename tag_cast<typename tag<Geometry>::type, multi_tag>::type,
Geometry,
Functor,
true
>::apply(geometry, f);
dispatch::for_each_point<Geometry>::apply(geometry, f);
return f;
}
@@ -336,19 +252,16 @@ inline Functor for_each_segment(Geometry const& geometry, Functor f)
\tparam Functor \tparam_functor
\qbk{[include reference/algorithms/for_each_segment.qbk]}
\qbk{[heading Example]}
\qbk{[for_each_segment_const] [for_each_segment_const_output]}
*/
template<typename Geometry, typename Functor>
inline Functor for_each_segment(Geometry& geometry, Functor f)
{
concept::check<Geometry>();
return dispatch::for_each_segment
<
typename tag_cast<typename tag<Geometry>::type, multi_tag>::type,
Geometry,
Functor,
false
>::apply(geometry, f);
dispatch::for_each_segment<Geometry>::apply(geometry, f);
return f;
}
@@ -22,15 +22,14 @@ namespace boost { namespace geometry
namespace detail { namespace intersection
{
template
<
typename Box1, typename Box2,
typename BoxOut,
typename Strategy,
std::size_t Dimension, std::size_t DimensionCount
>
template <std::size_t Dimension, std::size_t DimensionCount>
struct intersection_box_box
{
template
<
typename Box1, typename Box2, typename BoxOut,
typename Strategy
>
static inline bool apply(Box1 const& box1,
Box2 const& box2, BoxOut& box_out,
Strategy const& strategy)
@@ -50,23 +49,19 @@ struct intersection_box_box
set<min_corner, Dimension>(box_out, min1 < min2 ? min2 : min1);
set<max_corner, Dimension>(box_out, max1 > max2 ? max2 : max1);
return intersection_box_box
<
Box1, Box2, BoxOut, Strategy,
Dimension + 1, DimensionCount
>::apply(box1, box2, box_out, strategy);
return intersection_box_box<Dimension + 1, DimensionCount>
::apply(box1, box2, box_out, strategy);
}
};
template
<
typename Box1, typename Box2,
typename BoxOut,
typename Strategy,
std::size_t DimensionCount
>
struct intersection_box_box<Box1, Box2, BoxOut, Strategy, DimensionCount, DimensionCount>
template <std::size_t DimensionCount>
struct intersection_box_box<DimensionCount, DimensionCount>
{
template
<
typename Box1, typename Box2, typename BoxOut,
typename Strategy
>
static inline bool apply(Box1 const&, Box2 const&, BoxOut&, Strategy const&)
{
return true;
@@ -86,15 +81,14 @@ namespace dispatch
// By default, all is forwarded to the intersection_insert-dispatcher
template
<
typename Tag1, typename Tag2, typename TagOut,
typename Geometry1, typename Geometry2,
typename GeometryOut,
typename Strategy
typename Tag1 = typename geometry::tag<Geometry1>::type,
typename Tag2 = typename geometry::tag<Geometry2>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct intersection
{
typedef std::back_insert_iterator<GeometryOut> output_iterator;
template <typename GeometryOut, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out,
@@ -104,17 +98,8 @@ struct intersection
intersection_insert
<
Tag1, Tag2, typename geometry::tag<OneOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<OneOut>::value,
Geometry1, Geometry2,
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value, false>::value,
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, false>::value,
detail::overlay::do_reverse<geometry::point_order<OneOut>::value>::value,
output_iterator, OneOut,
overlay_intersection,
Strategy
Geometry1, Geometry2, OneOut,
overlay_intersection
>::apply(geometry1, geometry2, std::back_inserter(geometry_out), strategy);
return true;
@@ -123,50 +108,50 @@ struct intersection
};
// If reversal is needed, perform it
template
<
typename Box1, typename Box2,
typename BoxOut,
typename Strategy
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2
>
struct intersection
<
box_tag, box_tag, box_tag,
Box1, Box2, BoxOut,
Strategy
> : public detail::intersection::intersection_box_box
<
Box1, Box2, BoxOut,
Strategy,
0, geometry::dimension<Box1>::value
>
{};
template
<
typename Tag1, typename Tag2, typename TagOut,
typename Geometry1, typename Geometry2,
typename GeometryOut,
typename Strategy
Geometry1, Geometry2,
Tag1, Tag2,
true
>
struct intersection_reversed
: intersection<Geometry2, Geometry1, Tag2, Tag1, false>
{
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
template <typename GeometryOut, typename Strategy>
static inline bool apply(
Geometry1 const& g1,
Geometry2 const& g2,
GeometryOut& out,
Strategy const& strategy)
{
return intersection
<
Tag2, Tag1, TagOut,
Geometry2, Geometry1,
GeometryOut, Strategy
>::apply(geometry2, geometry1, geometry_out, strategy);
return intersection<
Geometry2, Geometry1,
Tag2, Tag1,
false
>::apply(g2, g1, out, strategy);
}
};
template
<
typename Box1, typename Box2, bool Reverse
>
struct intersection
<
Box1, Box2,
box_tag, box_tag,
Reverse
> : public detail::intersection::intersection_box_box
<
0, geometry::dimension<Box1>::value
>
{};
} // namespace dispatch
@@ -210,24 +195,10 @@ inline bool intersection(Geometry1 const& geometry1,
> strategy;
return boost::mpl::if_c
<
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
dispatch::intersection_reversed
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
Geometry1, Geometry2, GeometryOut, strategy
>,
dispatch::intersection
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
Geometry1, Geometry2, GeometryOut, strategy
>
>::type::apply(geometry1, geometry2, geometry_out, strategy());
return dispatch::intersection<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, geometry_out, strategy());
}
@@ -43,9 +43,10 @@ namespace detail { namespace length
{
template<typename Segment, typename Strategy>
template<typename Segment>
struct segment_length
{
template <typename Strategy>
static inline typename default_length_result<Segment>::type apply(
Segment const& segment, Strategy const& strategy)
{
@@ -63,11 +64,12 @@ struct segment_length
\note for_each could be used here, now that point_type is changed by boost
range iterator
*/
template<typename Range, typename Strategy, closure_selector Closure>
template<typename Range, closure_selector Closure>
struct range_length
{
typedef typename default_length_result<Range>::type return_type;
template <typename Strategy>
static inline return_type apply(
Range const& range, Strategy const& strategy)
{
@@ -106,28 +108,31 @@ namespace dispatch
{
template <typename Tag, typename Geometry, typename Strategy>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct length : detail::calculate_null
<
typename default_length_result<Geometry>::type,
Geometry,
Strategy
>
{};
{
typedef typename default_length_result<Geometry>::type return_type;
template <typename Strategy>
static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
{
return calculate_null::apply<return_type>(geometry, strategy);
}
};
template <typename Geometry, typename Strategy>
struct length<linestring_tag, Geometry, Strategy>
: detail::length::range_length<Geometry, Strategy, closed>
template <typename Geometry>
struct length<Geometry, linestring_tag>
: detail::length::range_length<Geometry, closed>
{};
// RING: length is currently 0; it might be argued that it is the "perimeter"
template <typename Geometry, typename Strategy>
struct length<segment_tag, Geometry, Strategy>
: detail::length::segment_length<Geometry, Strategy>
template <typename Geometry>
struct length<Geometry, segment_tag>
: detail::length::segment_length<Geometry>
{};
@@ -159,12 +164,7 @@ inline typename default_length_result<Geometry>::type length(
point_tag, typename point_type<Geometry>::type
>::type strategy_type;
return dispatch::length
<
typename tag<Geometry>::type,
Geometry,
strategy_type
>::apply(geometry, strategy_type());
return dispatch::length<Geometry>::apply(geometry, strategy_type());
}
@@ -190,12 +190,7 @@ inline typename default_length_result<Geometry>::type length(
// detail::throw_on_empty_input(geometry);
return dispatch::length
<
typename tag<Geometry>::type,
Geometry,
Strategy
>::apply(geometry, strategy);
return dispatch::length<Geometry>::apply(geometry, strategy);
}
@@ -17,7 +17,7 @@
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -35,19 +35,22 @@ namespace dispatch
{
template <typename Tag, typename Geometry>
struct num_geometries
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (types<Geometry>)
);
};
template
<
typename Geometry,
typename Tag = typename tag_cast
<
typename tag<Geometry>::type,
single_tag,
multi_tag
>::type
>
struct num_geometries: not_implemented<Tag>
{};
template <typename Geometry>
struct num_geometries<single_tag, Geometry>
struct num_geometries<Geometry, single_tag>
{
static inline std::size_t apply(Geometry const&)
{
@@ -76,16 +79,7 @@ inline std::size_t num_geometries(Geometry const& geometry)
{
concept::check<Geometry const>();
return dispatch::num_geometries
<
typename tag_cast
<
typename tag<Geometry>::type,
single_tag,
multi_tag
>::type,
Geometry
>::apply(geometry);
return dispatch::num_geometries<Geometry>::apply(geometry);
}
@@ -32,7 +32,7 @@ namespace dispatch
{
template <typename Tag, typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct num_interior_rings
{
static inline std::size_t apply(Geometry const& )
@@ -44,7 +44,7 @@ struct num_interior_rings
template <typename Polygon>
struct num_interior_rings<polygon_tag, Polygon>
struct num_interior_rings<Polygon, polygon_tag>
{
static inline std::size_t apply(Polygon const& polygon)
{
@@ -74,11 +74,7 @@ struct num_interior_rings<polygon_tag, Polygon>
template <typename Geometry>
inline std::size_t num_interior_rings(Geometry const& geometry)
{
return dispatch::num_interior_rings
<
typename tag<Geometry>::type,
Geometry
>::apply(geometry);
return dispatch::num_interior_rings<Geometry>::apply(geometry);
}
@@ -16,7 +16,6 @@
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/typeof/typeof.hpp>
@@ -27,6 +26,7 @@
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -38,9 +38,9 @@ namespace detail { namespace num_points
{
template <typename Range>
struct range_count
{
template <typename Range>
static inline std::size_t apply(Range const& range, bool add_for_open)
{
std::size_t n = boost::size(range);
@@ -60,30 +60,31 @@ struct range_count
}
};
template <typename Geometry, std::size_t D>
template <std::size_t D>
struct other_count
{
template <typename Geometry>
static inline std::size_t apply(Geometry const&, bool)
{
return D;
}
};
template <typename Polygon>
struct polygon_count
struct polygon_count: private range_count
{
template <typename Polygon>
static inline std::size_t apply(Polygon const& poly, bool add_for_open)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
std::size_t n = range_count<ring_type>::apply(
std::size_t n = range_count::apply(
exterior_ring(poly), add_for_open);
typename interior_return_type<Polygon const>::type rings
= interior_rings(poly);
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
{
n += range_count<ring_type>::apply(*it, add_for_open);
n += range_count::apply(*it, add_for_open);
}
return n;
@@ -98,44 +99,42 @@ struct polygon_count
namespace dispatch
{
template <typename GeometryTag, typename Geometry>
struct num_points
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (types<Geometry>)
);
};
template <typename Geometry>
struct num_points<point_tag, Geometry>
: detail::num_points::other_count<Geometry, 1>
template
<
typename Geometry,
typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
>
struct num_points: not_implemented<Tag>
{};
template <typename Geometry>
struct num_points<box_tag, Geometry>
: detail::num_points::other_count<Geometry, 4>
struct num_points<Geometry, point_tag>
: detail::num_points::other_count<1>
{};
template <typename Geometry>
struct num_points<segment_tag, Geometry>
: detail::num_points::other_count<Geometry, 2>
struct num_points<Geometry, box_tag>
: detail::num_points::other_count<4>
{};
template <typename Geometry>
struct num_points<linestring_tag, Geometry>
: detail::num_points::range_count<Geometry>
struct num_points<Geometry, segment_tag>
: detail::num_points::other_count<2>
{};
template <typename Geometry>
struct num_points<ring_tag, Geometry>
: detail::num_points::range_count<Geometry>
struct num_points<Geometry, linestring_tag>
: detail::num_points::range_count
{};
template <typename Geometry>
struct num_points<polygon_tag, Geometry>
: detail::num_points::polygon_count<Geometry>
struct num_points<Geometry, ring_tag>
: detail::num_points::range_count
{};
template <typename Geometry>
struct num_points<Geometry, polygon_tag>
: detail::num_points::polygon_count
{};
} // namespace dispatch
@@ -158,11 +157,7 @@ inline std::size_t num_points(Geometry const& geometry, bool add_for_open = fals
{
concept::check<Geometry const>();
return dispatch::num_points
<
typename tag_cast<typename tag<Geometry>::type, multi_tag>::type,
Geometry
>::apply(geometry, add_for_open);
return dispatch::num_points<Geometry>::apply(geometry, add_for_open);
}
}} // namespace boost::geometry
@@ -17,10 +17,10 @@
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
namespace boost { namespace geometry
@@ -32,13 +32,12 @@ namespace detail { namespace overlaps
template
<
typename Box1,
typename Box2,
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box_loop
{
template <typename Box1, typename Box2>
static inline void apply(Box1 const& b1, Box2 const& b2,
bool& overlaps, bool& one_in_two, bool& two_in_one)
{
@@ -84,8 +83,6 @@ struct box_box_loop
box_box_loop
<
Box1,
Box2,
Dimension + 1,
DimensionCount
>::apply(b1, b2, overlaps, one_in_two, two_in_one);
@@ -94,24 +91,19 @@ struct box_box_loop
template
<
typename Box1,
typename Box2,
std::size_t DimensionCount
>
struct box_box_loop<Box1, Box2, DimensionCount, DimensionCount>
struct box_box_loop<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2>
static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
{
}
};
template
<
typename Box1,
typename Box2
>
struct box_box
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& b1, Box2 const& b2)
{
bool overlaps = true;
@@ -119,8 +111,6 @@ struct box_box
bool within2 = true;
box_box_loop
<
Box1,
Box2,
0,
dimension<Box1>::type::value
>::apply(b1, b2, overlaps, within1, within2);
@@ -148,24 +138,18 @@ namespace dispatch
template
<
typename Tag1,
typename Tag2,
typename Geometry1,
typename Geometry2
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct overlaps
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (types<Geometry1, Geometry2>)
);
};
struct overlaps: not_implemented<Tag1, Tag2>
{};
template <typename Box1, typename Box2>
struct overlaps<box_tag, box_tag, Box1, Box2>
: detail::overlaps::box_box<Box1, Box2>
struct overlaps<Box1, Box2, box_tag, box_tag>
: detail::overlaps::box_box
{};
@@ -190,8 +174,6 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
return dispatch::overlaps
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
Geometry1,
Geometry2
>::apply(geometry1, geometry2);
@@ -33,40 +33,43 @@ namespace dispatch
{
// Default perimeter is 0.0, specializations implement calculated values
template <typename Tag, typename Geometry, typename Strategy>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct perimeter : detail::calculate_null
<
typename default_length_result<Geometry>::type,
Geometry,
Strategy
>
{};
{
typedef typename default_length_result<Geometry>::type return_type;
template <typename Geometry, typename Strategy>
struct perimeter<ring_tag, Geometry, Strategy>
template <typename Strategy>
static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
{
return calculate_null::apply<return_type>(geometry, strategy);
}
};
template <typename Geometry>
struct perimeter<Geometry, ring_tag>
: detail::length::range_length
<
Geometry,
Strategy,
closure<Geometry>::value
>
{};
template <typename Polygon, typename Strategy>
struct perimeter<polygon_tag, Polygon, Strategy>
: detail::calculate_polygon_sum
<
typename default_length_result<Polygon>::type,
Polygon,
Strategy,
detail::length::range_length
template <typename Polygon>
struct perimeter<Polygon, polygon_tag> : detail::calculate_polygon_sum
{
typedef typename default_length_result<Polygon>::type return_type;
typedef detail::length::range_length
<
typename ring_type<Polygon>::type,
Strategy,
closure<Polygon>::value
>
>
{};
> policy;
template <typename Strategy>
static inline return_type apply(Polygon const& polygon, Strategy const& strategy)
{
return calculate_polygon_sum::apply<return_type, policy>(polygon, strategy);
}
};
// box,n-sphere: to be implemented
@@ -100,12 +103,7 @@ inline typename default_length_result<Geometry>::type perimeter(
// detail::throw_on_empty_input(geometry);
return dispatch::perimeter
<
typename tag<Geometry>::type,
Geometry,
strategy_type
>::apply(geometry, strategy_type());
return dispatch::perimeter<Geometry>::apply(geometry, strategy_type());
}
/*!
@@ -130,12 +128,7 @@ inline typename default_length_result<Geometry>::type perimeter(
// detail::throw_on_empty_input(geometry);
return dispatch::perimeter
<
typename tag<Geometry>::type,
Geometry,
Strategy
>::apply(geometry, strategy);
return dispatch::perimeter<Geometry>::apply(geometry, strategy);
}
}} // namespace boost::geometry
@@ -32,9 +32,9 @@ namespace detail { namespace reverse
{
template <typename Range>
struct range_reverse
{
template <typename Range>
static inline void apply(Range& range)
{
std::reverse(boost::begin(range), boost::end(range));
@@ -42,21 +42,20 @@ struct range_reverse
};
template <typename Polygon>
struct polygon_reverse
struct polygon_reverse: private range_reverse
{
template <typename Polygon>
static inline void apply(Polygon& polygon)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef range_reverse<ring_type> per_range;
per_range::apply(exterior_ring(polygon));
range_reverse::apply(exterior_ring(polygon));
typename interior_return_type<Polygon>::type rings
= interior_rings(polygon);
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
{
per_range::apply(*it);
range_reverse::apply(*it);
}
}
};
@@ -71,11 +70,7 @@ namespace dispatch
{
template
<
typename Tag,
typename Geometry
>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct reverse
{
static inline void apply(Geometry&)
@@ -84,20 +79,20 @@ struct reverse
template <typename Ring>
struct reverse<ring_tag, Ring>
: detail::reverse::range_reverse<Ring>
struct reverse<Ring, ring_tag>
: detail::reverse::range_reverse
{};
template <typename LineString>
struct reverse<linestring_tag, LineString>
: detail::reverse::range_reverse<LineString>
struct reverse<LineString, linestring_tag>
: detail::reverse::range_reverse
{};
template <typename Polygon>
struct reverse<polygon_tag, Polygon>
: detail::reverse::polygon_reverse<Polygon>
struct reverse<Polygon, polygon_tag>
: detail::reverse::polygon_reverse
{};
@@ -121,11 +116,7 @@ inline void reverse(Geometry& geometry)
{
concept::check<Geometry>();
dispatch::reverse
<
typename tag<Geometry>::type,
Geometry
>::apply(geometry);
dispatch::reverse<Geometry>::apply(geometry);
}
}} // namespace boost::geometry
@@ -33,6 +33,7 @@
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
@@ -43,12 +44,11 @@ namespace boost { namespace geometry
namespace detail { namespace simplify
{
template<typename Range, typename Strategy>
struct simplify_range_insert
{
template <typename OutputIterator, typename Distance>
template<typename Range, typename Strategy, typename OutputIterator, typename Distance>
static inline void apply(Range const& range, OutputIterator out,
Distance const& max_distance, Strategy const& strategy)
Distance const& max_distance, Strategy const& strategy)
{
if (boost::size(range) <= 2 || max_distance < 0)
{
@@ -62,12 +62,11 @@ struct simplify_range_insert
};
template<typename Range, typename Strategy>
struct simplify_copy
{
template <typename Distance>
template <typename Range, typename Strategy, typename Distance>
static inline void apply(Range const& range, Range& out,
Distance const& , Strategy const& )
Distance const& , Strategy const& )
{
std::copy
(
@@ -77,10 +76,10 @@ struct simplify_copy
};
template<typename Range, typename Strategy, std::size_t Minimum>
template<std::size_t Minimum>
struct simplify_range
{
template <typename Distance>
template <typename Range, typename Strategy, typename Distance>
static inline void apply(Range const& range, Range& out,
Distance const& max_distance, Strategy const& strategy)
{
@@ -101,14 +100,11 @@ struct simplify_range
if (boost::size(range) <= int(Minimum) || max_distance < 0.0)
{
simplify_copy<Range, Strategy>::apply
(
range, out, max_distance, strategy
);
simplify_copy::apply(range, out, max_distance, strategy);
}
else
{
simplify_range_insert<Range, Strategy>::apply
simplify_range_insert::apply
(
range, std::back_inserter(out), max_distance, strategy
);
@@ -116,10 +112,9 @@ struct simplify_range
}
};
template<typename Polygon, typename Strategy>
struct simplify_polygon
{
template <typename Distance>
template <typename Polygon, typename Strategy, typename Distance>
static inline void apply(Polygon const& poly_in, Polygon& poly_out,
Distance const& max_distance, Strategy const& strategy)
{
@@ -133,9 +128,9 @@ struct simplify_polygon
// Note that if there are inner rings, and distance is too large,
// they might intersect with the outer ring in the output,
// while it didn't in the input.
simplify_range<ring_type, Strategy, Minimum>::apply(exterior_ring(poly_in),
exterior_ring(poly_out),
max_distance, strategy);
simplify_range<Minimum>::apply(exterior_ring(poly_in),
exterior_ring(poly_out),
max_distance, strategy);
traits::resize
<
@@ -154,8 +149,7 @@ struct simplify_polygon
it_in != boost::end(rings_in);
++it_in, ++it_out)
{
simplify_range<ring_type, Strategy, Minimum>::apply(*it_in,
*it_out, max_distance, strategy);
simplify_range<Minimum>::apply(*it_in, *it_out, max_distance, strategy);
}
}
};
@@ -169,15 +163,18 @@ struct simplify_polygon
namespace dispatch
{
template <typename Tag, typename Geometry, typename Strategy>
struct simplify
{
};
template
<
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct simplify: not_implemented<Tag>
{};
template <typename Point, typename Strategy>
struct simplify<point_tag, Point, Strategy>
template <typename Point>
struct simplify<Point, point_tag>
{
template <typename Distance>
template <typename Distance, typename Strategy>
static inline void apply(Point const& point, Point& out,
Distance const& , Strategy const& )
{
@@ -186,22 +183,15 @@ struct simplify<point_tag, Point, Strategy>
};
template <typename Linestring, typename Strategy>
struct simplify<linestring_tag, Linestring, Strategy>
: detail::simplify::simplify_range
<
Linestring,
Strategy,
2
>
template <typename Linestring>
struct simplify<Linestring, linestring_tag>
: detail::simplify::simplify_range<2>
{};
template <typename Ring, typename Strategy>
struct simplify<ring_tag, Ring, Strategy>
template <typename Ring>
struct simplify<Ring, ring_tag>
: detail::simplify::simplify_range
<
Ring,
Strategy,
core_detail::closure::minimum_ring_size
<
geometry::closure<Ring>::value
@@ -209,38 +199,29 @@ struct simplify<ring_tag, Ring, Strategy>
>
{};
template <typename Polygon, typename Strategy>
struct simplify<polygon_tag, Polygon, Strategy>
template <typename Polygon>
struct simplify<Polygon, polygon_tag>
: detail::simplify::simplify_polygon
<
Polygon,
Strategy
>
{};
template <typename Tag, typename Geometry, typename Strategy>
struct simplify_insert
{
};
template <typename Linestring, typename Strategy>
struct simplify_insert<linestring_tag, Linestring, Strategy>
: detail::simplify::simplify_range_insert
<
Linestring,
Strategy
>
template
<
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct simplify_insert: not_implemented<Tag>
{};
template <typename Ring, typename Strategy>
struct simplify_insert<ring_tag, Ring, Strategy>
template <typename Linestring>
struct simplify_insert<Linestring, linestring_tag>
: detail::simplify::simplify_range_insert
{};
template <typename Ring>
struct simplify_insert<Ring, ring_tag>
: detail::simplify::simplify_range_insert
<
Ring,
Strategy
>
{};
@@ -275,12 +256,7 @@ inline void simplify(Geometry const& geometry, Geometry& out,
geometry::clear(out);
dispatch::simplify
<
typename tag<Geometry>::type,
Geometry,
Strategy
>::apply(geometry, out, max_distance, strategy);
dispatch::simplify<Geometry>::apply(geometry, out, max_distance, strategy);
}
@@ -348,12 +324,7 @@ inline void simplify_insert(Geometry const& geometry, OutputIterator out,
concept::check<Geometry const>();
BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) );
dispatch::simplify_insert
<
typename tag<Geometry>::type,
Geometry,
Strategy
>::apply(geometry, out, max_distance, strategy);
dispatch::simplify_insert<Geometry>::apply(geometry, out, max_distance, strategy);
}
/*!
@@ -387,12 +358,7 @@ inline void simplify_insert(Geometry const& geometry, OutputIterator out,
point_type, ds_strategy_type
> strategy_type;
dispatch::simplify_insert
<
typename tag<Geometry>::type,
Geometry,
strategy_type
>::apply(geometry, out, max_distance, strategy_type());
dispatch::simplify_insert<Geometry>::apply(geometry, out, max_distance, strategy_type());
}
}} // namespace detail::simplify
@@ -59,35 +59,20 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
out = geometry::dispatch::intersection_insert
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
OutputIterator, GeometryOut,
GeometryOut,
overlay_difference,
Strategy
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
>::apply(geometry1, geometry2, out, strategy);
out = geometry::dispatch::intersection_insert
<
typename geometry::tag<Geometry2>::type,
typename geometry::tag<Geometry1>::type,
typename geometry::tag<GeometryOut>::type,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<GeometryOut>::value,
Geometry2, Geometry1,
GeometryOut,
overlay_difference,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value, true>::value,
geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
OutputIterator, GeometryOut,
overlay_difference,
Strategy
geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
>::apply(geometry2, geometry1, out, strategy);
return out;
}
@@ -0,0 +1,181 @@
// 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.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// 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)
#ifndef BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
#include <deque>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_geometries.hpp>
namespace boost { namespace geometry
{
namespace detail { namespace touches
{
template <typename Turn>
inline bool ok_for_touch(Turn const& turn)
{
return turn.both(detail::overlay::operation_union)
|| turn.both(detail::overlay::operation_blocked)
|| turn.combination(detail::overlay::operation_union, detail::overlay::operation_blocked)
;
}
template <typename Turns>
inline bool has_only_turns(Turns const& turns)
{
bool has_touch = false;
typedef typename boost::range_iterator<Turns const>::type iterator_type;
for (iterator_type it = boost::begin(turns); it != boost::end(turns); ++it)
{
if (it->has(detail::overlay::operation_intersection))
{
return false;
}
switch(it->method)
{
case detail::overlay::method_crosses:
return false;
case detail::overlay::method_equal:
// Segment spatially equal means: at the right side
// the polygon internally overlaps. So return false.
return false;
case detail::overlay::method_touch:
case detail::overlay::method_touch_interior:
case detail::overlay::method_collinear:
if (ok_for_touch(*it))
{
has_touch = true;
}
else
{
return false;
}
break;
case detail::overlay::method_none :
case detail::overlay::method_disjoint :
case detail::overlay::method_error :
break;
}
}
return has_touch;
}
}}
/*!
\brief \brief_check{has at least one touching point (self-tangency)}
\note This function can be called for one geometry (self-tangency) and
also for two geometries (touch)
\ingroup touches
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_check{is self-touching}
\qbk{distinguish,one geometry}
\qbk{[def __one_parameter__]}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry>
inline bool touches(Geometry const& geometry)
{
concept::check<Geometry const>();
typedef detail::overlay::turn_info
<
typename geometry::point_type<Geometry>::type
> turn_info;
typedef detail::overlay::get_turn_info
<
typename point_type<Geometry>::type,
typename point_type<Geometry>::type,
turn_info,
detail::overlay::assign_null_policy
> policy_type;
std::deque<turn_info> turns;
detail::self_get_turn_points::no_interrupt_policy policy;
detail::self_get_turn_points::get_turns
<
Geometry,
std::deque<turn_info>,
policy_type,
detail::self_get_turn_points::no_interrupt_policy
>::apply(geometry, turns, policy);
return detail::touches::has_only_turns(turns);
}
/*!
\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
\ingroup touches
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{touch each other}
\qbk{distinguish,two geometries}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
typedef detail::overlay::turn_info
<
typename geometry::point_type<Geometry1>::type
> turn_info;
typedef detail::overlay::get_turn_info
<
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
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
<
false, false,
detail::overlay::assign_null_policy
>(geometry1, geometry2, turns, policy);
return detail::touches::has_only_turns(turns)
&& ! geometry::detail::disjoint::rings_containing(geometry1, geometry2)
&& ! geometry::detail::disjoint::rings_containing(geometry2, geometry1)
;
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
@@ -41,9 +41,9 @@ namespace boost { namespace geometry
namespace detail { namespace transform
{
template <typename Point1, typename Point2, typename Strategy>
struct transform_point
{
template <typename Point1, typename Point2, typename Strategy>
static inline bool apply(Point1 const& p1, Point2& p2,
Strategy const& strategy)
{
@@ -52,9 +52,9 @@ struct transform_point
};
template <typename Box1, typename Box2, typename Strategy>
struct transform_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& b1, Box2& b2,
Strategy const& strategy)
{
@@ -91,9 +91,9 @@ struct transform_box
}
};
template <typename Geometry1, typename Geometry2, typename Strategy>
struct transform_box_or_segment
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& source, Geometry2& target,
Strategy const& strategy)
{
@@ -133,12 +133,7 @@ inline bool transform_range_out(Range const& range,
it != boost::end(range);
++it)
{
if (! transform_point
<
typename point_type<Range>::type,
PointOut,
Strategy
>::apply(*it, point_out, strategy))
if (! transform_point::apply(*it, point_out, strategy))
{
return false;
}
@@ -148,9 +143,9 @@ inline bool transform_range_out(Range const& range,
}
template <typename Polygon1, typename Polygon2, typename Strategy>
struct transform_polygon
{
template <typename Polygon1, typename Polygon2, typename Strategy>
static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,
Strategy const& strategy)
{
@@ -211,9 +206,9 @@ struct select_strategy
>::type type;
};
template <typename Range1, typename Range2, typename Strategy>
struct transform_range
{
template <typename Range1, typename Range2, typename Strategy>
static inline bool apply(Range1 const& range1,
Range2& range2, Strategy const& strategy)
{
@@ -236,50 +231,50 @@ namespace dispatch
template
<
typename Tag1, typename Tag2,
typename Geometry1, typename Geometry2,
typename Strategy
typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type
>
struct transform {};
template <typename Point1, typename Point2, typename Strategy>
struct transform<point_tag, point_tag, Point1, Point2, Strategy>
: detail::transform::transform_point<Point1, Point2, Strategy>
template <typename Point1, typename Point2>
struct transform<Point1, Point2, point_tag, point_tag>
: detail::transform::transform_point
{
};
template <typename Linestring1, typename Linestring2, typename Strategy>
template <typename Linestring1, typename Linestring2>
struct transform
<
linestring_tag, linestring_tag,
Linestring1, Linestring2, Strategy
Linestring1, Linestring2,
linestring_tag, linestring_tag
>
: detail::transform::transform_range<Linestring1, Linestring2, Strategy>
: detail::transform::transform_range
{
};
template <typename Range1, typename Range2, typename Strategy>
struct transform<ring_tag, ring_tag, Range1, Range2, Strategy>
: detail::transform::transform_range<Range1, Range2, Strategy>
template <typename Range1, typename Range2>
struct transform<Range1, Range2, ring_tag, ring_tag>
: detail::transform::transform_range
{
};
template <typename Polygon1, typename Polygon2, typename Strategy>
struct transform<polygon_tag, polygon_tag, Polygon1, Polygon2, Strategy>
: detail::transform::transform_polygon<Polygon1, Polygon2, Strategy>
template <typename Polygon1, typename Polygon2>
struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>
: detail::transform::transform_polygon
{
};
template <typename Box1, typename Box2, typename Strategy>
struct transform<box_tag, box_tag, Box1, Box2, Strategy>
: detail::transform::transform_box<Box1, Box2, Strategy>
template <typename Box1, typename Box2>
struct transform<Box1, Box2, box_tag, box_tag>
: detail::transform::transform_box
{
};
template <typename Segment1, typename Segment2, typename Strategy>
struct transform<segment_tag, segment_tag, Segment1, Segment2, Strategy>
: detail::transform::transform_box_or_segment<Segment1, Segment2, Strategy>
template <typename Segment1, typename Segment2>
struct transform<Segment1, Segment2, segment_tag, segment_tag>
: detail::transform::transform_box_or_segment
{
};
@@ -310,14 +305,7 @@ inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
concept::check<Geometry1 const>();
concept::check<Geometry2>();
typedef dispatch::transform
<
typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
Geometry1,
Geometry2,
Strategy
> transform_type;
typedef dispatch::transform<Geometry1, Geometry2> transform_type;
return transform_type::apply(geometry1, geometry2, strategy);
}
@@ -10,14 +10,13 @@
#define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
#include <boost/mpl/if.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/geometry/core/is_areal.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
@@ -30,78 +29,70 @@ namespace dispatch
template
<
// tag dispatching:
typename TagIn1, typename TagIn2, typename TagOut,
// metafunction finetuning helpers:
bool Areal1, bool Areal2, bool ArealOut,
// real types
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Strategy
typename Geometry1, typename Geometry2, typename GeometryOut,
typename TagIn1 = typename tag<Geometry1>::type,
typename TagIn2 = typename tag<Geometry2>::type,
typename TagOut = typename tag<GeometryOut>::type,
bool Areal1 = geometry::is_areal<Geometry1>::value,
bool Areal2 = geometry::is_areal<Geometry2>::value,
bool ArealOut = geometry::is_areal<GeometryOut>::value,
bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct union_insert
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES
, (types<Geometry1, Geometry2, GeometryOut>)
);
};
template
<
typename TagIn1, typename TagIn2, typename TagOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Strategy
>
struct union_insert
<
TagIn1, TagIn2, TagOut,
true, true, true,
Geometry1, Geometry2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::overlay::overlay
<Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, OutputIterator, GeometryOut, overlay_union, Strategy>
struct union_insert: not_implemented<TagIn1, TagIn2, TagOut>
{};
// If reversal is needed, perform it first
template
<
typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
bool Areal1, bool Areal2, bool ArealOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
typename Geometry1, typename Geometry2, typename GeometryOut,
typename TagIn1, typename TagIn2, typename TagOut,
bool Reverse1, bool Reverse2, bool ReverseOut
>
struct union_insert_reversed
struct union_insert
<
Geometry1, Geometry2, GeometryOut,
TagIn1, TagIn2, TagOut,
true, true, true,
Reverse1, Reverse2, ReverseOut,
true
>: union_insert<Geometry2, Geometry1, GeometryOut>
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry1 const& g1,
Geometry2 const& g2, OutputIterator out,
Strategy const& strategy)
{
return union_insert
<
GeometryTag2, GeometryTag1, GeometryTag3,
Areal2, Areal1, ArealOut,
Geometry2, Geometry1,
Reverse2, Reverse1, ReverseOut,
OutputIterator, GeometryOut,
Strategy
Geometry2, Geometry1, GeometryOut
>::apply(g2, g1, out, strategy);
}
};
template
<
typename Geometry1, typename Geometry2, typename GeometryOut,
typename TagIn1, typename TagIn2, typename TagOut,
bool Reverse1, bool Reverse2, bool ReverseOut
>
struct union_insert
<
Geometry1, Geometry2, GeometryOut,
TagIn1, TagIn2, TagOut,
true, true, true,
Reverse1, Reverse2, ReverseOut,
false
> : detail::overlay::overlay
<Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, overlay_union>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
@@ -121,40 +112,10 @@ inline OutputIterator insert(Geometry1 const& geometry1,
OutputIterator out,
Strategy const& strategy)
{
return boost::mpl::if_c
<
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
dispatch::union_insert_reversed
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
OutputIterator, GeometryOut,
Strategy
>,
dispatch::union_insert
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
OutputIterator, GeometryOut,
Strategy
>
>::type::apply(geometry1, geometry2, out, strategy);
return dispatch::union_insert
<
Geometry1, Geometry2, GeometryOut
>::apply(geometry1, geometry2, out, strategy);
}
/*!
@@ -34,9 +34,9 @@ namespace detail { namespace unique
{
template <typename Range, typename ComparePolicy>
struct range_unique
{
template <typename Range, typename ComparePolicy>
static inline void apply(Range& range, ComparePolicy const& policy)
{
typename boost::range_iterator<Range>::type it
@@ -52,21 +52,20 @@ struct range_unique
};
template <typename Polygon, typename ComparePolicy>
struct polygon_unique
{
template <typename Polygon, typename ComparePolicy>
static inline void apply(Polygon& polygon, ComparePolicy const& policy)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef range_unique<ring_type, ComparePolicy> per_range;
per_range::apply(exterior_ring(polygon), policy);
range_unique::apply(exterior_ring(polygon), policy);
typename interior_return_type<Polygon>::type rings
= interior_rings(polygon);
for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
{
per_range::apply(*it, policy);
range_unique::apply(*it, policy);
}
}
};
@@ -85,32 +84,32 @@ namespace dispatch
template
<
typename Tag,
typename Geometry,
typename ComparePolicy
typename Tag = typename tag<Geometry>::type
>
struct unique
{
template <typename ComparePolicy>
static inline void apply(Geometry&, ComparePolicy const& )
{}
};
template <typename Ring, typename ComparePolicy>
struct unique<ring_tag, Ring, ComparePolicy>
: detail::unique::range_unique<Ring, ComparePolicy>
template <typename Ring>
struct unique<Ring, ring_tag>
: detail::unique::range_unique
{};
template <typename LineString, typename ComparePolicy>
struct unique<linestring_tag, LineString, ComparePolicy>
: detail::unique::range_unique<LineString, ComparePolicy>
template <typename LineString>
struct unique<LineString, linestring_tag>
: detail::unique::range_unique
{};
template <typename Polygon, typename ComparePolicy>
struct unique<polygon_tag, Polygon, ComparePolicy>
: detail::unique::polygon_unique<Polygon, ComparePolicy>
template <typename Polygon>
struct unique<Polygon, polygon_tag>
: detail::unique::polygon_unique
{};
@@ -139,12 +138,7 @@ inline void unique(Geometry& geometry)
> policy;
dispatch::unique
<
typename tag<Geometry>::type,
Geometry,
policy
>::apply(geometry, policy());
dispatch::unique<Geometry>::apply(geometry, policy());
}
}} // namespace boost::geometry
@@ -65,7 +65,7 @@ struct point_in_ring
static inline int apply(Point const& point, Ring const& ring,
Strategy const& strategy)
{
if (boost::size(ring)
if (int(boost::size(ring))
< core_detail::closure::minimum_ring_size<Closure>::value)
{
return -1;