Merge branch 'develop' into fix/read_wkt

This commit is contained in:
Adam Wulkiewicz 2014-11-03 19:55:39 +01:00
commit ae9c2953d0
213 changed files with 6082 additions and 3329 deletions

View File

@ -113,6 +113,7 @@ Boost.Geometry contains contributions by:
* Federico Fern\u00E1ndez (preliminary version of R-tree spatial index)
* Karsten Ahnert (patch for cross-track distance)
* Mats Taraldsvik (documentation: adapting a legacy model)
* Matt Amos (fixes for point_on_surface)
* Samuel Debionne (variant support for distance, assign, crosses, intersection, ...)
[include imports.qbk]

View File

@ -22,18 +22,31 @@
[*Improvements]
* The support of parameters convertible to value_type in rtree insert(), remove() and count() functions
* Support for counterclockwise input/output in algorithm buffer
* Support for open-geometry input in algorithm buffer (open output not yet supported)
* Support for degenerate input (point-like linestrings, polygons) in algorithm buffer
[*Solved tickets]
* [@https://svn.boost.org/trac/boost/ticket/8402 8402] Implicit casts warnings
* [@https://svn.boost.org/trac/boost/ticket/8402 8402] Implicit conversion warnings
* [@https://svn.boost.org/trac/boost/ticket/9354 9354] Bug in winding strategy affecting within() and covered_by() for non-cartesian coordinate systems
* [@https://svn.boost.org/trac/boost/ticket/10177 10177] Missing include
* [@https://svn.boost.org/trac/boost/ticket/10345 10345] Distance fails to compile for some coordinate types
* [@https://svn.boost.org/trac/boost/ticket/10398 10398] Wrong neighbour check in buffer, calculating turns
* [@https://svn.boost.org/trac/boost/ticket/10421 10421] Invalid Point-Box distance for spherical CS
* [@https://svn.boost.org/trac/boost/ticket/10615 10615] Rtree constructor feature request
* [@https://svn.boost.org/trac/boost/ticket/10643 10643] Invalid point_on_surface() result for big coordinates
* [@https://svn.boost.org/trac/boost/ticket/10668 10668] Implicit conversion warnings (duplicated 8402)
[*Bugfixes]
* Several fixes of bugs in algorithm buffer
* Bug in point_on_surface() for CCW Polygons (extreme_points()) and numerical issue (thanks to Matt Amos)
* Bug in disjoint() for A/A fixed by replacement of point_on_surface() with point_on_border() (thanks to Matt Amos)
* The result of convex_hull(), duplicated Point in open output, too small number of Points for 1- and 2-Point input
* Imprecision for big coordinates in centroid(), fixed by Points translation (related with ticket 10643)
* for_each_segment() not taking into account the last segment of open Geometry
[/=================]
[heading Boost 1.56]
[/=================]
@ -41,7 +54,7 @@
[*Additional functionality]
* New algorithm buffer for inflating/deflating geometries (buffer itself already existed but that was only to enlarge a box)
* New algorithm remove_spikes, algorithm to remove spikes from a ring, polygon or multi_polygon.
* New algorithm remove_spikes, algorithm to remove spikes from a ring, polygon or multi_polygon
* New algorithm point_on_surface, generating a point lying on the surface (interior) of the polygon
* New algorithm is_simple, returning true if a geometry is simple according to the OGC standard
* New algorithm is_valid, returning true if a geometry is valid according to the OGC standard

View File

@ -5,6 +5,11 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -19,7 +24,6 @@
#include <cstddef>
#include <boost/range.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
@ -36,6 +40,7 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@ -50,6 +55,8 @@
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/multi/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
namespace boost { namespace geometry
{
@ -188,17 +195,19 @@ inline bool range_ok(Range const& range, Point& centroid)
return true;
}
/*!
\brief Calculate the centroid of a ring.
\brief Calculate the centroid of a Ring or a Linestring.
*/
template <closure_selector Closure>
struct centroid_range_state
{
template<typename Ring, typename Strategy>
template<typename Ring, typename PointTransformer, typename Strategy>
static inline void apply(Ring const& ring,
Strategy const& strategy, typename Strategy::state_type& state)
PointTransformer const& transformer,
Strategy const& strategy,
typename Strategy::state_type& state)
{
typedef typename geometry::point_type<Ring const>::type point_type;
typedef typename closeable_view<Ring const, Closure>::type view_type;
typedef typename boost::range_iterator<view_type const>::type iterator_type;
@ -207,11 +216,19 @@ struct centroid_range_state
iterator_type it = boost::begin(view);
iterator_type end = boost::end(view);
for (iterator_type previous = it++;
it != end;
++previous, ++it)
typename PointTransformer::result_type
previous_pt = transformer.apply(*it);
for ( ++it ; it != end ; ++it)
{
strategy.apply(*previous, *it, state);
typename PointTransformer::result_type
pt = transformer.apply(*it);
strategy.apply(static_cast<point_type const&>(previous_pt),
static_cast<point_type const&>(pt),
state);
previous_pt = pt;
}
}
};
@ -221,13 +238,20 @@ struct centroid_range
{
template<typename Range, typename Point, typename Strategy>
static inline void apply(Range const& range, Point& centroid,
Strategy const& strategy)
Strategy const& strategy)
{
if (range_ok(range, centroid))
{
// prepare translation transformer
translating_transformer<Range> transformer(*boost::begin(range));
typename Strategy::state_type state;
centroid_range_state<Closure>::apply(range, strategy, state);
centroid_range_state<Closure>::apply(range, transformer,
strategy, state);
strategy.result(state, centroid);
// translate the result back
transformer.apply_reverse(centroid);
}
}
};
@ -240,14 +264,16 @@ struct centroid_range
*/
struct centroid_polygon_state
{
template<typename Polygon, typename Strategy>
template<typename Polygon, typename PointTransformer, typename Strategy>
static inline void apply(Polygon const& poly,
Strategy const& strategy, typename Strategy::state_type& state)
PointTransformer const& transformer,
Strategy const& strategy,
typename Strategy::state_type& state)
{
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);
per_ring::apply(exterior_ring(poly), transformer, strategy, state);
typename interior_return_type<Polygon const>::type
rings = interior_rings(poly);
@ -255,7 +281,7 @@ struct centroid_polygon_state
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
per_ring::apply(*it, strategy, state);
per_ring::apply(*it, transformer, strategy, state);
}
}
};
@ -268,9 +294,16 @@ struct centroid_polygon
{
if (range_ok(exterior_ring(poly), centroid))
{
// prepare translation transformer
translating_transformer<Polygon>
transformer(*boost::begin(exterior_ring(poly)));
typename Strategy::state_type state;
centroid_polygon_state::apply(poly, strategy, state);
centroid_polygon_state::apply(poly, transformer, strategy, state);
strategy.result(state, centroid);
// translate the result back
transformer.apply_reverse(centroid);
}
}
};
@ -282,11 +315,14 @@ struct centroid_polygon
*/
struct centroid_multi_point_state
{
template <typename Point, typename Strategy>
template <typename Point, typename PointTransformer, typename Strategy>
static inline void apply(Point const& point,
Strategy const& strategy, typename Strategy::state_type& state)
PointTransformer const& transformer,
Strategy const& strategy,
typename Strategy::state_type& state)
{
strategy.apply(point, state);
strategy.apply(static_cast<Point const&>(transformer.apply(point)),
state);
}
};
@ -303,8 +339,9 @@ template <typename Policy>
struct centroid_multi
{
template <typename Multi, typename Point, typename Strategy>
static inline void apply(Multi const& multi, Point& centroid,
Strategy const& strategy)
static inline void apply(Multi const& multi,
Point& centroid,
Strategy const& strategy)
{
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
// If there is nothing in any of the ranges, it is not possible
@ -315,6 +352,9 @@ struct centroid_multi
}
#endif
// prepare translation transformer
translating_transformer<Multi> transformer(multi);
typename Strategy::state_type state;
for (typename boost::range_iterator<Multi const>::type
@ -322,9 +362,12 @@ struct centroid_multi
it != boost::end(multi);
++it)
{
Policy::apply(*it, strategy, state);
Policy::apply(*it, transformer, strategy, state);
}
Strategy::result(state, centroid);
// translate the result back
transformer.apply_reverse(centroid);
}
};

View File

@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -21,6 +26,7 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@ -44,7 +50,7 @@ namespace boost { namespace geometry
namespace detail { namespace convex_hull
{
template <order_selector Order>
template <order_selector Order, closure_selector Closure>
struct hull_insert
{
@ -57,7 +63,7 @@ struct hull_insert
typename Strategy::state_type state;
strategy.apply(geometry, state);
strategy.result(state, out, Order == clockwise);
strategy.result(state, out, Order == clockwise, Closure != open);
return out;
}
};
@ -70,7 +76,8 @@ struct hull_to_geometry
{
hull_insert
<
geometry::point_order<OutputGeometry>::value
geometry::point_order<OutputGeometry>::value,
geometry::closure<OutputGeometry>::value
>::apply(geometry,
std::back_inserter(
// Handle linestring, ring and polygon the same:
@ -124,9 +131,9 @@ struct convex_hull<Box, box_tag>
template <order_selector Order>
template <order_selector Order, closure_selector Closure>
struct convex_hull_insert
: detail::convex_hull::hull_insert<Order>
: detail::convex_hull::hull_insert<Order, Closure>
{};
@ -171,7 +178,8 @@ struct convex_hull_insert
BOOST_CONCEPT_ASSERT( (geometry::concept::ConvexHullStrategy<Strategy>) );
return dispatch::convex_hull_insert<
geometry::point_order<Geometry>::value
geometry::point_order<Geometry>::value,
geometry::closure<Geometry>::value
>::apply(geometry, out, strategy);
}
@ -189,7 +197,7 @@ struct convex_hull_insert
}
};
}; // namespace resolve_strategy
} // namespace resolve_strategy
namespace resolve_variant {

View File

@ -12,10 +12,12 @@
#include <cstddef>
#include <iterator>
#include <boost/core/ignore_unused.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@ -29,6 +31,8 @@
#include <boost/geometry/algorithms/simplify.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
#if defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)
#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>
#endif
@ -87,6 +91,13 @@ inline void simplify_input(Range const& range,
geometry::simplify(range, simplified, max_distance, strategy);
#endif
if (boost::size(simplified) == 2
&& geometry::equals(geometry::range::front(simplified),
geometry::range::back(simplified)))
{
traits::resize<Range>::apply(simplified, 1);
}
}
@ -202,7 +213,7 @@ struct buffer_range
typename EndStrategy,
typename RobustPolicy
>
static inline void iterate(Collection& collection,
static inline bool iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@ -215,6 +226,8 @@ struct buffer_range
output_point_type& last_p1,
output_point_type& last_p2)
{
boost::ignore_unused(side_strategy);
typedef typename std::iterator_traits
<
Iterator
@ -246,6 +259,7 @@ struct buffer_range
* pup: penultimate_point
*/
bool result = false;
bool first = true;
Iterator it = begin;
@ -259,14 +273,21 @@ struct buffer_range
{
robust_point_type robust_input;
geometry::recalculate(robust_input, *it, robust_policy);
// Check on equality - however, if input is simplified, this is highly
// unlikely (though possible by rescaling)
// Check on equality - however, if input is simplified, this is
// unlikely (though possible by rescaling or for degenerated pointlike polygons)
if (! detail::equals::equals_point_point(previous_robust_input, robust_input))
{
generated_side.clear();
side_strategy.apply(*prev, *it, side,
distance_strategy, generated_side);
if (generated_side.empty())
{
break;
}
result = true;
if (! first)
{
add_join(collection,
@ -295,6 +316,7 @@ struct buffer_range
}
previous_robust_input = robust_input;
}
return result;
}
};
@ -345,6 +367,26 @@ struct visit_pieces_default_policy
{}
};
template
<
typename OutputPointType,
typename Point,
typename Collection,
typename DistanceStrategy,
typename PointStrategy
>
inline void buffer_point(Point const& point, Collection& collection,
DistanceStrategy const& distance_strategy,
PointStrategy const& point_strategy)
{
collection.start_new_ring();
std::vector<OutputPointType> range_out;
point_strategy.apply(point, distance_strategy, range_out);
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
collection.finish_ring();
}
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
@ -389,13 +431,10 @@ struct buffer_inserter<point_tag, Point, RingOutput>
PointStrategy const& point_strategy,
RobustPolicy const& )
{
typedef typename point_type<RingOutput>::type output_point_type;
collection.start_new_ring();
std::vector<output_point_type> range_out;
point_strategy.apply(point, distance_strategy, range_out);
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
collection.finish_ring();
detail::buffer::buffer_point
<
typename point_type<RingOutput>::type
>(point, collection, distance_strategy, point_strategy);
}
};
@ -419,7 +458,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typename EndStrategy,
typename RobustPolicy
>
static inline void iterate(Collection& collection,
static inline bool iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@ -432,21 +471,25 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typedef detail::buffer::buffer_range<RingOutput> buffer_range;
buffer_range::iterate(collection, begin, end,
bool result = buffer_range::iterate(collection, begin, end,
side,
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1, first_p2, last_p1, last_p2);
// Generate closing join
buffer_range::add_join(collection,
*(end - 2),
*(end - 1), last_p1, last_p2,
*(begin + 1), first_p1, first_p2,
side,
distance_strategy, join_strategy, end_strategy,
robust_policy);
if (result)
{
buffer_range::add_join(collection,
*(end - 2),
*(end - 1), last_p1, last_p2,
*(begin + 1), first_p1, first_p2,
side,
distance_strategy, join_strategy, end_strategy,
robust_policy);
}
// Buffer is closed automatically by last closing corner
return result;
}
template
@ -465,30 +508,48 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& ,
PointStrategy const& point_strategy,
RobustPolicy const& robust_policy)
{
if (boost::size(ring) > 3)
{
RingOutput simplified;
detail::buffer::simplify_input(ring, distance, simplified);
RingInput simplified;
detail::buffer::simplify_input(ring, distance, simplified);
bool has_output = false;
std::size_t n = boost::size(simplified);
std::size_t const min_points = core_detail::closure::minimum_ring_size
<
geometry::closure<RingInput>::value
>::value;
if (n >= min_points)
{
detail::normalized_view<RingInput const> view(simplified);
if (distance.negative())
{
// Walk backwards (rings will be reversed afterwards)
// It might be that this will be changed later.
// TODO: decide this.
iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
has_output = iterate(collection, boost::rbegin(view), boost::rend(view),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy);
}
else
{
iterate(collection, boost::begin(simplified), boost::end(simplified),
has_output = iterate(collection, boost::begin(view), boost::end(view),
strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy);
}
}
if (! has_output && n >= 1)
{
// Use point_strategy to buffer degenerated ring
detail::buffer::buffer_point<output_point_type>
(
geometry::range::front(simplified),
collection, distance, point_strategy
);
}
}
};
@ -505,19 +566,6 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typedef typename point_type<output_ring_type>::type output_point_type;
typedef typename point_type<Linestring>::type input_point_type;
template <typename DistanceStrategy, typename SideStrategy>
static inline output_point_type first_perpendicular_point(
input_point_type const& p1, input_point_type const& p2,
DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy)
{
std::vector<output_point_type> generated_side;
side_strategy.apply(p1, p2,
strategy::buffer::buffer_side_right,
distance_strategy, generated_side);
return generated_side.front();
}
template
<
typename Collection,
@ -528,7 +576,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename EndStrategy,
typename RobustPolicy
>
static inline void iterate(Collection& collection,
static inline bool iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@ -545,10 +593,23 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
// other side of the linestring. If it is the second pass (right),
// we have it already from the first phase (left).
// But for the first pass, we have to generate it
output_point_type reverse_p1
= side == strategy::buffer::buffer_side_right
? first_p1
: first_perpendicular_point(ultimate_point, penultimate_point, distance_strategy, side_strategy);
output_point_type reverse_p1;
if (side == strategy::buffer::buffer_side_right)
{
reverse_p1 = first_p1;
}
else
{
std::vector<output_point_type> generated_side;
side_strategy.apply(ultimate_point, penultimate_point,
strategy::buffer::buffer_side_right,
distance_strategy, generated_side);
if (generated_side.empty())
{
return false;
}
reverse_p1 = generated_side.front();
}
output_point_type first_p2, last_p1, last_p2;
@ -560,6 +621,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
std::vector<output_point_type> range_out;
end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);
collection.add_endcap(end_strategy, range_out, ultimate_point);
return true;
}
template
@ -577,30 +639,41 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& ,
PointStrategy const& point_strategy,
RobustPolicy const& robust_policy)
{
if (boost::size(linestring) > 1)
{
Linestring simplified;
detail::buffer::simplify_input(linestring, distance, simplified);
Linestring simplified;
detail::buffer::simplify_input(linestring, distance, simplified);
bool has_output = false;
std::size_t n = boost::size(simplified);
if (n > 1)
{
collection.start_new_ring();
output_point_type first_p1;
iterate(collection, boost::begin(simplified), boost::end(simplified),
has_output = iterate(collection,
boost::begin(simplified), boost::end(simplified),
strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
if (has_output)
{
iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
}
collection.finish_ring();
}
else
if (! has_output && n >= 1)
{
// Use point_strategy to buffer degenerated linestring
detail::buffer::buffer_point<output_point_type>
(
geometry::range::front(simplified),
collection, distance, point_strategy
);
}
}
};
@ -769,6 +842,8 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
VisitPiecesPolicy& visit_pieces_policy
)
{
boost::ignore_unused(visit_pieces_policy);
typedef detail::buffer::buffered_piece_collection
<
typename geometry::ring_type<GeometryOutput>::type,
@ -800,7 +875,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.get_turns();
if (areal)
{
collection.check_remaining_points(distance_strategy.factor());
collection.check_remaining_points(distance_strategy);
}
// Visit the piece collection. This does nothing (by default), but
@ -814,7 +889,16 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.enrich();
collection.traverse();
if (distance_strategy.negative() && areal)
// Reverse all offsetted rings / traversed rings if:
// - they were generated on the negative side (deflate) of polygons
// - the output is counter clockwise
// and avoid reversing twice
bool reverse = distance_strategy.negative() && areal;
if (geometry::point_order<GeometryOutput>::value == counterclockwise)
{
reverse = ! reverse;
}
if (reverse)
{
collection.reverse();
}

View File

@ -35,7 +35,7 @@ namespace detail { namespace buffer
enum intersection_location_type
{
location_ok, inside_buffer, inside_original
location_ok, inside_buffer, location_discard
};
class backtrack_for_buffer

View File

@ -12,8 +12,9 @@
#include <algorithm>
#include <cstddef>
#include <set>
#include <boost/range.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
@ -117,6 +118,8 @@ struct buffered_piece_collection
point_type,
RobustPolicy
>::type robust_point_type;
// Robust ring/polygon type, always clockwise
typedef geometry::model::ring<robust_point_type> robust_ring_type;
typedef geometry::model::polygon<robust_point_type> robust_polygon_type;
@ -392,32 +395,60 @@ struct buffered_piece_collection
// will never start a new ring from this type of points.
it->selectable_start = false;
}
}
}
inline void check_remaining_points(int factor)
template <typename DistanceStrategy>
inline void check_point_in_original(buffer_turn_info_type& turn,
DistanceStrategy const& distance_strategy)
{
// TODO: use partition
strategy::within::winding<robust_point_type> winding;
for (std::size_t i = 0; i < robust_polygons.size(); i++)
{
int const code = detail::within::point_in_geometry(turn.robust_point,
robust_polygons[i], winding);
switch (code)
{
case 0 :
// On border of original: always discard
turn.location = location_discard;
return;
case 1 :
// Inside original
if (distance_strategy.negative())
{
// For deflate: it is inside the (multi)polygon
// OK, no action, we can return
}
else
{
// For inflate: it is inside, discard
turn.location = location_discard;
}
return;
}
}
if (distance_strategy.negative())
{
// For deflate: it was not found in one of the polygons, discard
turn.location = location_discard;
}
}
template <typename DistanceStrategy>
inline void check_remaining_points(DistanceStrategy const& distance_strategy)
{
// TODO: partition: this one is, together with the overlay, quadratic
for (typename boost::range_iterator<turn_vector_type>::type it =
boost::begin(m_turns); it != boost::end(m_turns); ++it)
{
if (it->location == location_ok)
{
int code = -1;
for (std::size_t i = 0; i < robust_polygons.size(); i++)
{
if (geometry::covered_by(it->robust_point, robust_polygons[i]))
{
code = 1;
break;
}
}
if (code * factor == 1)
{
it->location = inside_original;
}
check_point_in_original(*it, distance_strategy);
}
}
}
@ -571,7 +602,11 @@ struct buffered_piece_collection
inline void finish_ring(bool is_interior = false)
{
BOOST_ASSERT(m_first_piece_index != -1);
if (m_first_piece_index == -1)
{
return;
}
if (m_first_piece_index < static_cast<int>(boost::size(m_pieces)))
{
// If piece was added
@ -628,6 +663,7 @@ struct buffered_piece_collection
std::size_t const n = boost::size(offsetted_rings.back());
pc.first_seg_id.segment_index = decrease_segment_index_by_one ? n - 1 : n;
pc.last_segment_index = pc.first_seg_id.segment_index;
m_pieces.push_back(pc);
return m_pieces.back();
@ -724,10 +760,7 @@ struct buffered_piece_collection
template <typename Range>
inline void add_range_to_piece(piece& pc, Range const& range, bool add_front)
{
if (boost::size(range) == 0u)
{
return;
}
BOOST_ASSERT(boost::size(range) != 0u);
typename Range::const_iterator it = boost::begin(range);
@ -750,7 +783,11 @@ struct buffered_piece_collection
inline void add_piece(strategy::buffer::piece_type type, Range const& range, bool decrease_segment_index_by_one)
{
piece& pc = create_piece(type, decrease_segment_index_by_one);
add_range_to_piece(pc, range, offsetted_rings.back().empty());
if (boost::size(range) > 0u)
{
add_range_to_piece(pc, range, offsetted_rings.back().empty());
}
finish_piece(pc);
}
@ -770,9 +807,9 @@ struct buffered_piece_collection
{
piece& pc = create_piece(type, true);
add_range_to_piece(pc, range, offsetted_rings.back().empty());
if (boost::size(range) > 0)
if (boost::size(range) > 0u)
{
add_range_to_piece(pc, range, offsetted_rings.back().empty());
finish_piece(pc, range.back(), p, range.front());
}
else
@ -784,6 +821,8 @@ struct buffered_piece_collection
template <typename EndcapStrategy, typename Range>
inline void add_endcap(EndcapStrategy const& strategy, Range const& range, point_type const& end_point)
{
boost::ignore_unused(strategy);
if (range.empty())
{
return;

View File

@ -0,0 +1,119 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP
#include <cstddef>
#include <boost/core/addressof.hpp>
#include <boost/core/ref.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace centroid
{
// NOTE: There is no need to translate in other coordinate systems than
// cartesian. But if it was needed then one should translate using
// CS-specific technique, e.g. in spherical/geographic a translation
// vector should contain coordinates being multiplies of 2PI or 360 deg.
template <typename Geometry,
typename CastedTag = typename tag_cast
<
typename tag<Geometry>::type,
areal_tag
>::type,
typename CSTag = typename cs_tag<Geometry>::type>
struct translating_transformer
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef boost::reference_wrapper<point_type const> result_type;
explicit translating_transformer(Geometry const&) {}
explicit translating_transformer(point_type const&) {}
result_type apply(point_type const& pt) const
{
return result_type(pt);
}
template <typename ResPt>
void apply_reverse(ResPt &) const {}
};
// Specialization for Areal Geometries in cartesian CS
template <typename Geometry>
struct translating_transformer<Geometry, areal_tag, cartesian_tag>
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef point_type result_type;
explicit translating_transformer(Geometry const& geom)
: m_origin(NULL)
{
geometry::point_iterator<Geometry const>
pt_it = geometry::points_begin(geom);
if ( pt_it != geometry::points_end(geom) )
{
m_origin = boost::addressof(*pt_it);
}
}
explicit translating_transformer(point_type const& origin)
: m_origin(boost::addressof(origin))
{}
result_type apply(point_type const& pt) const
{
point_type res = pt;
if ( m_origin )
geometry::subtract_point(res, *m_origin);
return res;
}
template <typename ResPt>
void apply_reverse(ResPt & res_pt) const
{
if ( m_origin )
geometry::add_point(res_pt, *m_origin);
}
const point_type * m_origin;
};
}} // namespace detail::centroid
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP

View File

@ -0,0 +1,146 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
#include <iterator>
#include <boost/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace closest_feature
{
// returns the range iterator the realizes the closest
// distance between the geometry and the element of the range
class geometry_to_range
{
private:
template
<
typename Geometry,
typename RangeIterator,
typename Strategy,
typename Distance
>
static inline void apply(Geometry const& geometry,
RangeIterator first,
RangeIterator last,
Strategy const& strategy,
RangeIterator& it_min,
Distance& dist_min)
{
BOOST_ASSERT( first != last );
Distance const zero = Distance(0);
// start with first distance
it_min = first;
dist_min = dispatch::distance
<
Geometry,
typename std::iterator_traits<RangeIterator>::value_type,
Strategy
>::apply(geometry, *it_min, strategy);
// check if other elements in the range are closer
for (RangeIterator it = ++first; it != last; ++it)
{
Distance dist = dispatch::distance
<
Geometry,
typename std::iterator_traits<RangeIterator>::value_type,
Strategy
>::apply(geometry, *it, strategy);
if (geometry::math::equals(dist, zero))
{
dist_min = dist;
it_min = it;
return;
}
else if (dist < dist_min)
{
dist_min = dist;
it_min = it;
}
}
}
public:
template
<
typename Geometry,
typename RangeIterator,
typename Strategy,
typename Distance
>
static inline RangeIterator apply(Geometry const& geometry,
RangeIterator first,
RangeIterator last,
Strategy const& strategy,
Distance& dist_min)
{
RangeIterator it_min;
apply(geometry, first, last, strategy, it_min, dist_min);
return it_min;
}
template
<
typename Geometry,
typename RangeIterator,
typename Strategy
>
static inline RangeIterator apply(Geometry const& geometry,
RangeIterator first,
RangeIterator last,
Strategy const& strategy)
{
typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry>::type,
typename point_type
<
typename std::iterator_traits
<
RangeIterator
>::value_type
>::type
>::type dist_min;
return apply(geometry, first, last, strategy, dist_min);
}
};
}} // namespace detail::closest_feature
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP

View File

@ -0,0 +1,250 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP
#include <utility>
#include <boost/assert.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace closest_feature
{
// returns the segment (pair of iterators) that realizes the closest
// distance of the point to the range
template
<
typename Point,
typename Range,
closure_selector Closure,
typename Strategy
>
class point_to_point_range
{
protected:
typedef typename boost::range_iterator<Range const>::type iterator_type;
template <typename Distance>
static inline void apply(Point const& point,
iterator_type first,
iterator_type last,
Strategy const& strategy,
iterator_type& it_min1,
iterator_type& it_min2,
Distance& dist_min)
{
BOOST_ASSERT( first != last );
Distance const zero = Distance(0);
iterator_type it = first;
iterator_type prev = it++;
if (it == last)
{
it_min1 = it_min2 = first;
dist_min = strategy.apply(point, *first, *first);
return;
}
// start with first segment distance
dist_min = strategy.apply(point, *prev, *it);
iterator_type prev_min_dist = prev;
// check if other segments are closer
for (++prev, ++it; it != last; ++prev, ++it)
{
Distance dist = strategy.apply(point, *prev, *it);
if (geometry::math::equals(dist, zero))
{
dist_min = zero;
it_min1 = prev;
it_min2 = it;
return;
}
else if (dist < dist_min)
{
dist_min = dist;
prev_min_dist = prev;
}
}
it_min1 = it_min2 = prev_min_dist;
++it_min2;
}
public:
typedef typename std::pair<iterator_type, iterator_type> return_type;
template <typename Distance>
static inline return_type apply(Point const& point,
iterator_type first,
iterator_type last,
Strategy const& strategy,
Distance& dist_min)
{
iterator_type it_min1, it_min2;
apply(point, first, last, strategy, it_min1, it_min2, dist_min);
return std::make_pair(it_min1, it_min2);
}
static inline return_type apply(Point const& point,
iterator_type first,
iterator_type last,
Strategy const& strategy)
{
typename strategy::distance::services::return_type
<
Strategy,
Point,
typename boost::range_value<Range>::type
>::type dist_min;
return apply(point, first, last, strategy, dist_min);
}
template <typename Distance>
static inline return_type apply(Point const& point,
Range const& range,
Strategy const& strategy,
Distance& dist_min)
{
return apply(point,
boost::begin(range),
boost::end(range),
strategy,
dist_min);
}
static inline return_type apply(Point const& point,
Range const& range,
Strategy const& strategy)
{
return apply(point, boost::begin(range), boost::end(range), strategy);
}
};
// specialization for open ranges
template <typename Point, typename Range, typename Strategy>
class point_to_point_range<Point, Range, open, Strategy>
: point_to_point_range<Point, Range, closed, Strategy>
{
private:
typedef point_to_point_range<Point, Range, closed, Strategy> base_type;
typedef typename base_type::iterator_type iterator_type;
template <typename Distance>
static inline void apply(Point const& point,
iterator_type first,
iterator_type last,
Strategy const& strategy,
iterator_type& it_min1,
iterator_type& it_min2,
Distance& dist_min)
{
BOOST_ASSERT( first != last );
base_type::apply(point, first, last, strategy,
it_min1, it_min2, dist_min);
iterator_type it_back = --last;
Distance const zero = Distance(0);
Distance dist = strategy.apply(point, *it_back, *first);
if (geometry::math::equals(dist, zero))
{
dist_min = zero;
it_min1 = it_back;
it_min2 = first;
}
else if (dist < dist_min)
{
dist_min = dist;
it_min1 = it_back;
it_min2 = first;
}
}
public:
typedef typename std::pair<iterator_type, iterator_type> return_type;
template <typename Distance>
static inline return_type apply(Point const& point,
iterator_type first,
iterator_type last,
Strategy const& strategy,
Distance& dist_min)
{
iterator_type it_min1, it_min2;
apply(point, first, last, strategy, it_min1, it_min2, dist_min);
return std::make_pair(it_min1, it_min2);
}
static inline return_type apply(Point const& point,
iterator_type first,
iterator_type last,
Strategy const& strategy)
{
typedef typename strategy::distance::services::return_type
<
Strategy,
Point,
typename boost::range_value<Range>::type
>::type distance_return_type;
distance_return_type dist_min;
return apply(point, first, last, strategy, dist_min);
}
template <typename Distance>
static inline return_type apply(Point const& point,
Range const& range,
Strategy const& strategy,
Distance& dist_min)
{
return apply(point,
boost::begin(range),
boost::end(range),
strategy,
dist_min);
}
static inline return_type apply(Point const& point,
Range const& range,
Strategy const& strategy)
{
return apply(point, boost::begin(range), boost::end(range), strategy);
}
};
}} // namespace detail::closest_feature
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP

View File

@ -0,0 +1,196 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP
#include <cstddef>
#include <iterator>
#include <utility>
#include <boost/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace closest_feature
{
// returns a pair of a objects where the first is an object of the
// r-tree range and the second an object of the query range that
// realizes the closest feature of the two ranges
class range_to_range_rtree
{
private:
template
<
typename RTreeRangeIterator,
typename QueryRangeIterator,
typename Strategy,
typename RTreeValueType,
typename Distance
>
static inline void apply(RTreeRangeIterator rtree_first,
RTreeRangeIterator rtree_last,
QueryRangeIterator queries_first,
QueryRangeIterator queries_last,
Strategy const& strategy,
RTreeValueType& rtree_min,
QueryRangeIterator& qit_min,
Distance& dist_min)
{
typedef index::rtree<RTreeValueType, index::linear<8> > rtree_type;
BOOST_ASSERT( rtree_first != rtree_last );
BOOST_ASSERT( queries_first != queries_last );
Distance const zero = Distance(0);
// create -- packing algorithm
rtree_type rt(rtree_first, rtree_last);
RTreeValueType t_v;
bool first = true;
for (QueryRangeIterator qit = queries_first;
qit != queries_last; ++qit, first = false)
{
std::size_t n = rt.query(index::nearest(*qit, 1), &t_v);
BOOST_ASSERT( n > 0 );
// n above is unused outside BOOST_ASSERT, hence the call
// to boost::ignore_unused below
//
// however, t_v (initialized by the call to rt.query(...))
// is used below, which is why we cannot put the call to
// rt.query(...) inside BOOST_ASSERT
boost::ignore_unused(n);
Distance dist = dispatch::distance
<
RTreeValueType,
typename std::iterator_traits
<
QueryRangeIterator
>::value_type,
Strategy
>::apply(t_v, *qit, strategy);
if (first || dist < dist_min)
{
dist_min = dist;
rtree_min = t_v;
qit_min = qit;
if ( math::equals(dist_min, zero) )
{
return;
}
}
}
}
public:
template <typename RTreeRangeIterator, typename QueryRangeIterator>
struct return_type
{
typedef std::pair
<
typename std::iterator_traits<RTreeRangeIterator>::value_type,
QueryRangeIterator
> type;
};
template
<
typename RTreeRangeIterator,
typename QueryRangeIterator,
typename Strategy,
typename Distance
>
static inline typename return_type
<
RTreeRangeIterator, QueryRangeIterator
>::type apply(RTreeRangeIterator rtree_first,
RTreeRangeIterator rtree_last,
QueryRangeIterator queries_first,
QueryRangeIterator queries_last,
Strategy const& strategy,
Distance& dist_min)
{
typedef typename std::iterator_traits
<
RTreeRangeIterator
>::value_type rtree_value_type;
rtree_value_type rtree_min;
QueryRangeIterator qit_min;
apply(rtree_first, rtree_last, queries_first, queries_last,
strategy, rtree_min, qit_min, dist_min);
return std::make_pair(rtree_min, qit_min);
}
template
<
typename RTreeRangeIterator,
typename QueryRangeIterator,
typename Strategy
>
static inline typename return_type
<
RTreeRangeIterator, QueryRangeIterator
>::type apply(RTreeRangeIterator rtree_first,
RTreeRangeIterator rtree_last,
QueryRangeIterator queries_first,
QueryRangeIterator queries_last,
Strategy const& strategy)
{
typedef typename std::iterator_traits
<
RTreeRangeIterator
>::value_type rtree_value_type;
typename strategy::distance::services::return_type
<
Strategy,
typename point_type<rtree_value_type>::type,
typename point_type
<
typename std::iterator_traits
<
QueryRangeIterator
>::value_type
>::type
>::type dist_min;
return apply(rtree_first, rtree_last, queries_first, queries_last,
strategy, dist_min);
}
};
}} // namespace detail::closest_feature
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP

View File

@ -0,0 +1,56 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/// Calculate course (bearing) between two points.
template <typename ReturnType, typename Point1, typename Point2>
inline ReturnType course(Point1 const& p1, Point2 const& p2)
{
// http://williams.best.vwh.net/avform.htm#Crs
ReturnType dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
ReturnType cos_p2lat = cos(get_as_radian<1>(p2));
// An optimization which should kick in often for Boxes
//if ( math::equals(dlon, ReturnType(0)) )
//if ( get<0>(p1) == get<0>(p2) )
//{
// return - sin(get_as_radian<1>(p1)) * cos_p2lat);
//}
// "An alternative formula, not requiring the pre-computation of d"
// In the formula below dlon is used as "d"
return atan2(sin(dlon) * cos_p2lat,
cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
- sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP

View File

@ -23,9 +23,9 @@
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/point_on_surface.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
@ -42,21 +42,21 @@ namespace detail { namespace disjoint
template<typename Geometry>
struct check_each_ring_for_within
{
bool has_within;
bool not_disjoint;
Geometry const& m_geometry;
inline check_each_ring_for_within(Geometry const& g)
: has_within(false)
: not_disjoint(false)
, m_geometry(g)
{}
template <typename Range>
inline void apply(Range const& range)
{
if ( geometry::within(geometry::return_point_on_surface(range), m_geometry) )
{
has_within = true;
}
typename point_type<Range>::type pt;
not_disjoint = not_disjoint
|| ( geometry::point_on_border(pt, range)
&& geometry::covered_by(pt, m_geometry) );
}
};
@ -68,7 +68,7 @@ inline bool rings_containing(FirstGeometry const& geometry1,
{
check_each_ring_for_within<FirstGeometry> checker(geometry1);
geometry::detail::for_each_range(geometry2, checker);
return checker.has_within;
return checker.not_disjoint;
}
@ -87,8 +87,8 @@ struct general_areal
// If there is no intersection of segments, they might located
// inside each other
// We check that using a point on the surface, and see if that is inside
// the other geometry. And vice versa.
// We check that using a point on the border (external boundary),
// and see if that is contained in the other geometry. And vice versa.
if ( rings_containing(geometry1, geometry2)
|| rings_containing(geometry2, geometry1) )

View File

@ -20,8 +20,6 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP
#include <utility>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
@ -35,8 +33,7 @@
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/single_to_multi.hpp>
#include <boost/geometry/algorithms/detail/distance/multi_to_multi.hpp>
#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>
namespace boost { namespace geometry
@ -106,7 +103,10 @@ struct distance
>
{
static inline typename return_type<Strategy, Point, typename point_type<Linestring>::type>::type
static inline typename strategy::distance::services::return_type
<
Strategy, Point, typename point_type<Linestring>::type
>::type
apply(Point const& point,
Linestring const& linestring,
Strategy const&)
@ -151,15 +151,12 @@ struct distance
Strategy
>::type ps_strategy_type;
std::pair<return_type, bool>
dc = detail::distance::point_to_ring
return detail::distance::point_to_ring
<
Point, Ring,
geometry::closure<Ring>::value,
ps_strategy_type
>::apply(point, ring, ps_strategy_type());
return dc.second ? return_type(0) : dc.first;
}
};
@ -179,8 +176,8 @@ struct distance
>::type return_type;
static inline return_type apply(Point const& point,
Polygon const& polygon,
Strategy const&)
Polygon const& polygon,
Strategy const&)
{
typedef typename detail::distance::default_ps_strategy
<
@ -189,25 +186,19 @@ struct distance
Strategy
>::type ps_strategy_type;
std::pair<return_type, bool>
dc = detail::distance::point_to_polygon
return detail::distance::point_to_polygon
<
Point, Polygon,
Point,
Polygon,
geometry::closure<Polygon>::value,
ps_strategy_type
>::apply(point, polygon, ps_strategy_type());
return dc.second ? return_type(0) : dc.first;
}
};
namespace splitted_dispatch
{
template
<
typename Point,
@ -215,11 +206,11 @@ template
typename MultiGeometryTag,
typename Strategy
>
struct distance_single_to_multi
struct distance
<
Point, MultiGeometry, Strategy,
point_tag, MultiGeometryTag,
strategy_tag_distance_point_point
strategy_tag_distance_point_point, false
>
{
typedef typename strategy::distance::services::return_type
@ -238,11 +229,11 @@ struct distance_single_to_multi
Strategy
>::type ps_strategy_type;
return distance_single_to_multi
return distance
<
Point, MultiGeometry, ps_strategy_type,
point_tag, MultiGeometryTag,
strategy_tag_distance_point_segment
strategy_tag_distance_point_segment, false
>::apply(point, multigeometry, ps_strategy_type());
}
};
@ -255,11 +246,11 @@ template
typename GeometryTag,
typename Strategy
>
struct distance_single_to_multi
struct distance
<
Geometry, MultiPoint, Strategy,
GeometryTag, multi_point_tag,
strategy_tag_distance_point_point
strategy_tag_distance_point_point, false
>
{
typedef typename strategy::distance::services::return_type
@ -280,11 +271,11 @@ struct distance_single_to_multi
Strategy
>::type ps_strategy_type;
return distance_single_to_multi
return distance
<
Geometry, MultiPoint, ps_strategy_type,
GeometryTag, multi_point_tag,
strategy_tag_distance_point_segment
strategy_tag_distance_point_segment, false
>::apply(geometry, multipoint, ps_strategy_type());
}
};
@ -297,11 +288,11 @@ template
typename MultiGeometryTag,
typename Strategy
>
struct distance_multi_to_multi
struct distance
<
MultiPoint, MultiGeometry, Strategy,
multi_point_tag, MultiGeometryTag,
strategy_tag_distance_point_point
strategy_tag_distance_point_point, false
>
{
typedef typename strategy::distance::services::return_type
@ -322,19 +313,16 @@ struct distance_multi_to_multi
Strategy
>::type ps_strategy_type;
return distance_multi_to_multi
return distance
<
MultiPoint, MultiGeometry, ps_strategy_type,
multi_point_tag, MultiGeometryTag,
strategy_tag_distance_point_segment
strategy_tag_distance_point_segment, false
>::apply(multipoint, multigeometry, ps_strategy_type());
}
};
} // namespace splitted_dispatch
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@ -10,6 +10,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
@ -42,7 +44,7 @@ struct distance
>::type
apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
boost::ignore_unused(strategy);
return strategy.apply(box1, box2);
}
};

View File

@ -95,10 +95,7 @@ struct default_strategy<Pointlike, Box, pointlike_tag, box_tag, false>
<
point_tag, box_tag,
typename point_type<Pointlike>::type,
typename point_type<Box>::type,
cartesian_tag,
cartesian_tag,
void
typename point_type<Box>::type
>
{};
@ -109,10 +106,7 @@ struct default_strategy<Box1, Box2, box_tag, box_tag, false>
<
box_tag, box_tag,
typename point_type<Box1>::type,
typename point_type<Box2>::type,
cartesian_tag,
cartesian_tag,
void
typename point_type<Box2>::type
>
{};

View File

@ -1,395 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_GEOMETRY_RTREE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_GEOMETRY_RTREE_HPP
#include <cstddef>
#include <algorithm>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/range.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/geometry/iterators/has_one_element.hpp>
#include <boost/geometry/algorithms/for_each.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template
<
typename RTreePoint,
typename Geometry,
typename Strategy
>
class point_range_to_geometry_rtree
{
private:
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy,
RTreePoint,
typename point_type<Geometry>::type
>::type comparable_return_type;
typedef index::rtree<RTreePoint, index::linear<8> > r_tree;
// functor to evaluate minimum comparable distance
struct minimum_comparable_distance_evaluator
{
r_tree const& m_r_tree;
comparable_strategy const& m_cstrategy;
bool m_first;
comparable_return_type m_min_cd;
minimum_comparable_distance_evaluator
(r_tree const& r_tree, comparable_strategy const& cstrategy)
: m_r_tree(r_tree)
, m_cstrategy(cstrategy)
, m_first(true)
, m_min_cd()
{}
template <typename QueryGeometry>
inline void operator()(QueryGeometry const& query_geometry)
{
typename r_tree::value_type t_v;
std::size_t n =
m_r_tree.query(index::nearest(query_geometry, 1), &t_v);
BOOST_ASSERT( n > 0 );
// n above is unused outside BOOST_ASSERT, hence the call
// to boost::ignore_unused below
//
// however, t_v (initialized by the call to m_r_tree.query(...))
// is used below, which is why we cannot put the call to
// m_r_tree.query(...) inside BOOST_ASSERT
boost::ignore_unused(n);
comparable_return_type cd = dispatch::distance
<
typename r_tree::value_type,
QueryGeometry,
comparable_strategy
>::apply(t_v, query_geometry, m_cstrategy);
if ( m_first || cd < m_min_cd )
{
m_first = false;
m_min_cd = cd;
}
}
};
// class to choose between for_each_point and for_each_segment
template <typename G, typename Tag = typename tag<G>::type>
struct for_each_selector
{
typedef dispatch::for_each_segment<G> type;
};
template <typename MultiPoint>
struct for_each_selector<MultiPoint, multi_point_tag>
{
typedef dispatch::for_each_point<MultiPoint> type;
};
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
RTreePoint,
typename point_type<Geometry>::type
>::type return_type;
template <typename PointIterator>
static inline return_type apply(PointIterator points_first,
PointIterator points_beyond,
Geometry const& geometry,
Strategy const& strategy)
{
BOOST_ASSERT( points_first != points_beyond );
if ( geometry::has_one_element(points_first, points_beyond) )
{
return dispatch::distance
<
typename std::iterator_traits<PointIterator>::value_type,
Geometry,
Strategy
>::apply(*points_first, geometry, strategy);
}
// create -- packing algorithm
r_tree rt(points_first, points_beyond);
minimum_comparable_distance_evaluator
functor(rt,
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy));
for_each_selector<Geometry>::type::apply(geometry, functor);
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, RTreePoint, Geometry
>::apply(functor.m_min_cd);
}
};
template
<
typename Geometry1,
typename Geometry2,
typename Strategy
>
class geometry_to_geometry_rtree
{
// the following works with linear geometries seen as ranges of points
//
// we compute the r-tree for the points of one range and then,
// compute nearest points for the segments of the other,
// ... and ...
// vice versa.
private:
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type comparable_return_type;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type return_type;
static inline return_type apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
bool check_intersection = true)
{
typedef geometry::point_iterator<Geometry1 const> const_point_iterator1;
typedef geometry::point_iterator<Geometry2 const> const_point_iterator2;
const_point_iterator1 first1 = points_begin(geometry1);
const_point_iterator1 beyond1 = points_end(geometry1);
const_point_iterator2 first2 = points_begin(geometry2);
const_point_iterator2 beyond2 = points_end(geometry2);
if ( geometry::has_one_element(first1, beyond1) )
{
return dispatch::distance
<
typename point_type<Geometry1>::type,
Geometry2,
Strategy
>::apply(*first1, geometry2, strategy);
}
if ( geometry::has_one_element(first2, beyond2) )
{
return dispatch::distance
<
typename point_type<Geometry2>::type,
Geometry1,
Strategy
>::apply(*first2, geometry1, strategy);
}
if ( check_intersection && geometry::intersects(geometry1, geometry2) )
{
return return_type(0);
}
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
comparable_return_type cdist1 = point_range_to_geometry_rtree
<
typename point_type<Geometry1>::type,
Geometry2,
comparable_strategy
>::apply(first1, beyond1, geometry2, cstrategy);
comparable_return_type cdist2 = point_range_to_geometry_rtree
<
typename point_type<Geometry2>::type,
Geometry1,
comparable_strategy
>::apply(first2, beyond2, geometry1, cstrategy);
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Geometry1, Geometry2
>::apply( (std::min)(cdist1, cdist2) );
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linestring1, typename Linestring2, typename Strategy>
struct distance
<
Linestring1, Linestring2, Strategy,
linestring_tag, linestring_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::geometry_to_geometry_rtree
<
Linestring1, Linestring2, Strategy
>
{};
template <typename Linestring, typename Polygon, typename Strategy>
struct distance
<
Linestring, Polygon, Strategy,
linestring_tag, polygon_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::geometry_to_geometry_rtree
<
Linestring, Polygon, Strategy
>
{};
template <typename Linestring, typename Ring, typename Strategy>
struct distance
<
Linestring, Ring, Strategy,
linestring_tag, ring_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::geometry_to_geometry_rtree
<
Linestring, Ring, Strategy
>
{};
template <typename Polygon1, typename Polygon2, typename Strategy>
struct distance
<
Polygon1, Polygon2, Strategy,
polygon_tag, polygon_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::geometry_to_geometry_rtree
<
Polygon1, Polygon2, Strategy
>
{};
template <typename Polygon, typename Ring, typename Strategy>
struct distance
<
Polygon, Ring, Strategy,
polygon_tag, ring_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::geometry_to_geometry_rtree
<
Polygon, Ring, Strategy
>
{};
template <typename Ring1, typename Ring2, typename Strategy>
struct distance
<
Ring1, Ring2, Strategy,
ring_tag, ring_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::geometry_to_geometry_rtree
<
Ring1, Ring2, Strategy
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_GEOMETRY_RTREE_HPP

View File

@ -0,0 +1,462 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP
#include <iterator>
#include <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
// closure of segment or box point range
template
<
typename SegmentOrBox,
typename Tag = typename tag<SegmentOrBox>::type
>
struct segment_or_box_point_range_closure
: not_implemented<SegmentOrBox>
{};
template <typename Segment>
struct segment_or_box_point_range_closure<Segment, segment_tag>
{
static const closure_selector value = closed;
};
template <typename Box>
struct segment_or_box_point_range_closure<Box, box_tag>
{
static const closure_selector value = open;
};
template
<
typename Geometry,
typename SegmentOrBox,
typename Strategy,
typename Tag = typename tag<Geometry>::type
>
class geometry_to_segment_or_box
{
private:
typedef typename point_type<SegmentOrBox>::type segment_or_box_point;
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef detail::closest_feature::point_to_point_range
<
typename point_type<Geometry>::type,
std::vector<segment_or_box_point>,
segment_or_box_point_range_closure<SegmentOrBox>::value,
comparable_strategy
> point_to_point_range;
typedef detail::closest_feature::geometry_to_range geometry_to_range;
typedef typename strategy::distance::services::return_type
<
comparable_strategy,
typename point_type<Geometry>::type,
segment_or_box_point
>::type comparable_return_type;
// assign the new minimum value for an iterator of the point range
// of a segment or a box
template
<
typename SegOrBox,
typename SegOrBoxTag = typename tag<SegOrBox>::type
>
struct assign_new_min_iterator
: not_implemented<SegOrBox>
{};
template <typename Segment>
struct assign_new_min_iterator<Segment, segment_tag>
{
template <typename Iterator>
static inline void apply(Iterator&, Iterator)
{
}
};
template <typename Box>
struct assign_new_min_iterator<Box, box_tag>
{
template <typename Iterator>
static inline void apply(Iterator& it_min, Iterator it)
{
it_min = it;
}
};
// assign the points of a segment or a box to a range
template
<
typename SegOrBox,
typename PointRange,
typename SegOrBoxTag = typename tag<SegOrBox>::type
>
struct assign_segment_or_box_points
{};
template <typename Segment, typename PointRange>
struct assign_segment_or_box_points<Segment, PointRange, segment_tag>
{
static inline void apply(Segment const& segment, PointRange& range)
{
detail::assign_point_from_index<0>(segment, range[0]);
detail::assign_point_from_index<1>(segment, range[1]);
}
};
template <typename Box, typename PointRange>
struct assign_segment_or_box_points<Box, PointRange, box_tag>
{
static inline void apply(Box const& box, PointRange& range)
{
detail::assign_box_corners_oriented<true>(box, range);
}
};
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry>::type,
segment_or_box_point
>::type return_type;
static inline return_type apply(Geometry const& geometry,
SegmentOrBox const& segment_or_box,
Strategy const& strategy,
bool check_intersection = true)
{
typedef geometry::point_iterator<Geometry const> point_iterator_type;
typedef geometry::segment_iterator
<
Geometry const
> segment_iterator_type;
typedef typename std::vector
<
segment_or_box_point
>::const_iterator seg_or_box_iterator_type;
typedef assign_new_min_iterator<SegmentOrBox> assign_new_value;
if (check_intersection
&& geometry::intersects(geometry, segment_or_box))
{
return 0;
}
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
// get all points of the segment or the box
std::vector<segment_or_box_point>
seg_or_box_points(geometry::num_points(segment_or_box));
assign_segment_or_box_points
<
SegmentOrBox,
std::vector<segment_or_box_point>
>::apply(segment_or_box, seg_or_box_points);
// consider all distances of the points in the geometry to the
// segment or box
comparable_return_type cd_min1;
point_iterator_type pit_min;
seg_or_box_iterator_type it_min1 = seg_or_box_points.begin();
seg_or_box_iterator_type it_min2 = ++seg_or_box_points.begin();
bool first = true;
for (point_iterator_type pit = points_begin(geometry);
pit != points_end(geometry); ++pit, first = false)
{
comparable_return_type cd;
std::pair
<
seg_or_box_iterator_type, seg_or_box_iterator_type
> it_pair
= point_to_point_range::apply(*pit,
seg_or_box_points.begin(),
seg_or_box_points.end(),
cstrategy,
cd);
if (first || cd < cd_min1)
{
cd_min1 = cd;
pit_min = pit;
assign_new_value::apply(it_min1, it_pair.first);
assign_new_value::apply(it_min2, it_pair.second);
}
}
// consider all distances of the points in the segment or box to the
// segments of the geometry
comparable_return_type cd_min2;
segment_iterator_type sit_min;
typename std::vector<segment_or_box_point>::const_iterator it_min;
first = true;
for (typename std::vector<segment_or_box_point>::const_iterator it
= seg_or_box_points.begin();
it != seg_or_box_points.end(); ++it, first = false)
{
comparable_return_type cd;
segment_iterator_type sit
= geometry_to_range::apply(*it,
segments_begin(geometry),
segments_end(geometry),
cstrategy,
cd);
if (first || cd < cd_min2)
{
cd_min2 = cd;
it_min = it;
sit_min = sit;
}
}
if (is_comparable<Strategy>::value)
{
return (std::min)(cd_min1, cd_min2);
}
if (cd_min1 < cd_min2)
{
return strategy.apply(*pit_min, *it_min1, *it_min2);
}
else
{
return dispatch::distance
<
segment_or_box_point,
typename std::iterator_traits
<
segment_iterator_type
>::value_type,
Strategy
>::apply(*it_min, *sit_min, strategy);
}
}
static inline return_type
apply(SegmentOrBox const& segment_or_box, Geometry const& geometry,
Strategy const& strategy, bool check_intersection = true)
{
return apply(geometry, segment_or_box, strategy, check_intersection);
}
};
template <typename MultiPoint, typename SegmentOrBox, typename Strategy>
class geometry_to_segment_or_box
<
MultiPoint, SegmentOrBox, Strategy, multi_point_tag
>
{
private:
typedef detail::closest_feature::geometry_to_range base_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
typedef detail::closest_feature::geometry_to_range geometry_to_range;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<SegmentOrBox>::type,
typename point_type<MultiPoint>::type
>::type return_type;
static inline return_type apply(MultiPoint const& multipoint,
SegmentOrBox const& segment_or_box,
Strategy const& strategy)
{
namespace sds = strategy::distance::services;
typename sds::return_type
<
typename sds::comparable_type<Strategy>::type,
typename point_type<SegmentOrBox>::type,
typename point_type<MultiPoint>::type
>::type cd_min;
iterator_type it_min
= geometry_to_range::apply(segment_or_box,
boost::begin(multipoint),
boost::end(multipoint),
sds::get_comparable
<
Strategy
>::apply(strategy),
cd_min);
return
is_comparable<Strategy>::value
?
cd_min
:
dispatch::distance
<
typename point_type<MultiPoint>::type,
SegmentOrBox,
Strategy
>::apply(*it_min, segment_or_box, strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Segment, typename Strategy>
struct distance
<
Linear, Segment, Strategy, linear_tag, segment_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Linear, Segment, Strategy>
{};
template <typename Areal, typename Segment, typename Strategy>
struct distance
<
Areal, Segment, Strategy, areal_tag, segment_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>
{};
template <typename Segment, typename Areal, typename Strategy>
struct distance
<
Segment, Areal, Strategy, segment_tag, areal_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>
{};
template <typename Linear, typename Box, typename Strategy>
struct distance
<
Linear, Box, Strategy, linear_tag, box_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box
<
Linear, Box, Strategy
>
{};
template <typename Areal, typename Box, typename Strategy>
struct distance
<
Areal, Box, Strategy, areal_tag, box_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Areal, Box, Strategy>
{};
template <typename MultiPoint, typename Segment, typename Strategy>
struct distance
<
MultiPoint, Segment, Strategy,
multi_point_tag, segment_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box
<
MultiPoint, Segment, Strategy
>
{};
template <typename MultiPoint, typename Box, typename Strategy>
struct distance
<
MultiPoint, Box, Strategy,
multi_point_tag, box_tag,
strategy_tag_distance_point_box, false
> : detail::distance::geometry_to_segment_or_box
<
MultiPoint, Box, Strategy
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP

View File

@ -22,17 +22,14 @@
// the implementation details
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/algorithms/detail/distance/polygon_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/box_to_box.hpp>
#include <boost/geometry/algorithms/detail/distance/single_to_multi.hpp>
#include <boost/geometry/algorithms/detail/distance/multi_to_multi.hpp>
#include <boost/geometry/algorithms/detail/distance/multipoint_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp>
#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/algorithms/detail/distance/box_to_box.hpp>
#include <boost/geometry/algorithms/detail/distance/backward_compatibility.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP

View File

@ -0,0 +1,45 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP
#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/strategies/distance.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
// metafunction to determine is a strategy is comparable or not
template <typename Strategy>
struct is_comparable
: boost::is_same
<
Strategy,
typename strategy::distance::services::comparable_type
<
Strategy
>::type
>
{};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP

View File

@ -0,0 +1,70 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP
#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
// class to choose between point_iterator and segment_iterator
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct iterator_selector
{
typedef geometry::segment_iterator<Geometry> iterator_type;
static inline iterator_type begin(Geometry& geometry)
{
return segments_begin(geometry);
}
static inline iterator_type end(Geometry& geometry)
{
return segments_end(geometry);
}
};
template <typename MultiPoint>
struct iterator_selector<MultiPoint, multi_point_tag>
{
typedef geometry::point_iterator<MultiPoint> iterator_type;
static inline iterator_type begin(MultiPoint& multipoint)
{
return points_begin(multipoint);
}
static inline iterator_type end(MultiPoint& multipoint)
{
return points_end(multipoint);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP

View File

@ -0,0 +1,147 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Linear, typename Areal, typename Strategy>
struct linear_to_areal
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Linear>::type,
typename point_type<Areal>::type
>::type return_type;
static inline return_type apply(Linear const& linear,
Areal const& areal,
Strategy const& strategy)
{
if ( geometry::intersects(linear, areal) )
{
return 0;
}
return linear_to_linear
<
Linear, Areal, Strategy
>::apply(linear, areal, strategy, false);
}
static inline return_type apply(Areal const& areal,
Linear const& linear,
Strategy const& strategy)
{
return apply(linear, areal, strategy);
}
};
template <typename Areal1, typename Areal2, typename Strategy>
struct areal_to_areal
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Areal1>::type,
typename point_type<Areal2>::type
>::type return_type;
static inline return_type apply(Areal1 const& areal1,
Areal2 const& areal2,
Strategy const& strategy)
{
if ( geometry::intersects(areal1, areal2) )
{
return 0;
}
return linear_to_linear
<
Areal1, Areal2, Strategy
>::apply(areal1, areal2, strategy, false);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Areal, typename Strategy>
struct distance
<
Linear, Areal, Strategy,
linear_tag, areal_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
<
Linear, Areal, Strategy
>
{};
template <typename Areal, typename Linear, typename Strategy>
struct distance
<
Areal, Linear, Strategy,
areal_tag, linear_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
<
Linear, Areal, Strategy
>
{};
template <typename Areal1, typename Areal2, typename Strategy>
struct distance
<
Areal1, Areal2, Strategy,
areal_tag, areal_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::areal_to_areal
<
Areal1, Areal2, Strategy
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP

View File

@ -0,0 +1,123 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/num_segments.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Linear1, typename Linear2, typename Strategy>
struct linear_to_linear
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Linear1>::type,
typename point_type<Linear2>::type
>::type return_type;
static inline return_type apply(Linear1 const& linear1,
Linear2 const& linear2,
Strategy const& strategy,
bool = false)
{
if (geometry::num_points(linear1) == 1)
{
return dispatch::distance
<
typename point_type<Linear1>::type,
Linear2,
Strategy
>::apply(*points_begin(linear1), linear2, strategy);
}
if (geometry::num_points(linear2) == 1)
{
return dispatch::distance
<
typename point_type<Linear2>::type,
Linear1,
Strategy
>::apply(*points_begin(linear2), linear1, strategy);
}
if (geometry::num_segments(linear2) < geometry::num_segments(linear1))
{
return point_or_segment_range_to_geometry_rtree
<
geometry::segment_iterator<Linear2 const>,
Linear1,
Strategy
>::apply(geometry::segments_begin(linear2),
geometry::segments_end(linear2),
linear1,
strategy);
}
return point_or_segment_range_to_geometry_rtree
<
geometry::segment_iterator<Linear1 const>,
Linear2,
Strategy
>::apply(geometry::segments_begin(linear1),
geometry::segments_end(linear1),
linear2,
strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear1, typename Linear2, typename Strategy>
struct distance
<
Linear1, Linear2, Strategy,
linear_tag, linear_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::linear_to_linear
<
Linear1, Linear2, Strategy
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP

View File

@ -1,256 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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_DETAIL_DISTANCE_MULTI_TO_MULTI_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTI_TO_MULTI_HPP
#include <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/single_to_multi.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Multi1, typename Multi2, typename Strategy>
class distance_multi_to_multi_generic
{
private:
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy,
typename point_type<Multi1>::type,
typename point_type<Multi2>::type
>::type comparable_return_type;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Multi1>::type,
typename point_type<Multi2>::type
>::type return_type;
static inline return_type apply(Multi1 const& multi1,
Multi2 const& multi2, Strategy const& strategy)
{
comparable_return_type min_cdist = comparable_return_type();
bool first = true;
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
for(typename range_iterator<Multi1 const>::type it = boost::begin(multi1);
it != boost::end(multi1);
++it, first = false)
{
comparable_return_type cdist =
dispatch::splitted_dispatch::distance_single_to_multi
<
typename range_value<Multi1>::type,
Multi2,
comparable_strategy,
typename tag<typename range_value<Multi1>::type>::type,
typename tag<Multi2>::type,
typename strategy::distance::services::tag
<
comparable_strategy
>::type
>::apply(*it, multi2, cstrategy);
if (first || cdist < min_cdist)
{
min_cdist = cdist;
if ( geometry::math::equals(min_cdist, 0) )
{
break;
}
}
}
return strategy::distance::services::comparable_to_regular
<
comparable_strategy,
Strategy,
Multi1,
Multi2
>::apply(min_cdist);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
namespace splitted_dispatch
{
template
<
typename MultiGeometry1,
typename MultiGeometry2,
typename Strategy,
typename Tag1,
typename Tag2,
typename StrategyTag
>
struct distance_multi_to_multi
: not_implemented<MultiGeometry1, MultiGeometry2>
{};
template
<
typename MultiPoint,
typename MultiPolygon,
typename Strategy
>
struct distance_multi_to_multi
<
MultiPoint, MultiPolygon, Strategy,
multi_point_tag, multi_polygon_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_multi_to_multi_generic
<
MultiPoint, MultiPolygon, Strategy
>
{};
template
<
typename MultiLinestring1,
typename MultiLinestring2,
typename Strategy
>
struct distance_multi_to_multi
<
MultiLinestring1, MultiLinestring2, Strategy,
multi_linestring_tag, multi_linestring_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
MultiLinestring1, MultiLinestring2, Strategy
>
{};
template
<
typename MultiLinestring,
typename MultiPolygon,
typename Strategy
>
struct distance_multi_to_multi
<
MultiLinestring, MultiPolygon, Strategy,
multi_linestring_tag, multi_polygon_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
MultiLinestring, MultiPolygon, Strategy
>
{};
template <typename MultiPolygon1, typename MultiPolygon2, typename Strategy>
struct distance_multi_to_multi
<
MultiPolygon1, MultiPolygon2, Strategy,
multi_polygon_tag, multi_polygon_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
MultiPolygon1, MultiPolygon2, Strategy
>
{};
} // namespace splitted_dispatch
template
<
typename MultiGeometry1,
typename MultiGeometry2,
typename Strategy,
typename StrategyTag
>
struct distance
<
MultiGeometry1, MultiGeometry2, Strategy, multi_tag, multi_tag,
StrategyTag, false
> : splitted_dispatch::distance_multi_to_multi
<
MultiGeometry1, MultiGeometry2, Strategy,
typename geometry::tag<MultiGeometry1>::type,
typename geometry::tag<MultiGeometry2>::type,
StrategyTag
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTI_TO_MULTI_HPP

View File

@ -0,0 +1,240 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP
#include <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
struct multipoint_to_multipoint
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiPoint1>::type,
typename point_type<MultiPoint2>::type
>::type return_type;
static inline return_type apply(MultiPoint1 const& multipoint1,
MultiPoint2 const& multipoint2,
Strategy const& strategy)
{
if (boost::size(multipoint2) < boost::size(multipoint1))
{
return point_or_segment_range_to_geometry_rtree
<
typename boost::range_iterator<MultiPoint2 const>::type,
MultiPoint1,
Strategy
>::apply(boost::begin(multipoint2),
boost::end(multipoint2),
multipoint1,
strategy);
}
return point_or_segment_range_to_geometry_rtree
<
typename boost::range_iterator<MultiPoint1 const>::type,
MultiPoint2,
Strategy
>::apply(boost::begin(multipoint1),
boost::end(multipoint1),
multipoint2,
strategy);
}
};
template <typename MultiPoint, typename Linear, typename Strategy>
struct multipoint_to_linear
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiPoint>::type,
typename point_type<Linear>::type
>::type return_type;
static inline return_type apply(MultiPoint const& multipoint,
Linear const& linear,
Strategy const& strategy)
{
return detail::distance::point_or_segment_range_to_geometry_rtree
<
typename boost::range_iterator<MultiPoint const>::type,
Linear,
Strategy
>::apply(boost::begin(multipoint),
boost::end(multipoint),
linear,
strategy);
}
static inline return_type apply(Linear const& linear,
MultiPoint const& multipoint,
Strategy const& strategy)
{
return apply(multipoint, linear, strategy);
}
};
template <typename MultiPoint, typename Areal, typename Strategy>
class multipoint_to_areal
{
private:
struct within_areal
{
within_areal(Areal const& areal)
: m_areal(areal)
{}
template <typename Point>
inline bool apply(Point const& point) const
{
return geometry::within(point, m_areal);
}
Areal const& m_areal;
};
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiPoint>::type,
typename point_type<Areal>::type
>::type return_type;
static inline return_type apply(MultiPoint const& multipoint,
Areal const& areal,
Strategy const& strategy)
{
within_areal predicate(areal);
if (check_iterator_range
<
within_areal, false
>::apply(boost::begin(multipoint),
boost::end(multipoint),
predicate))
{
return 0;
}
return detail::distance::point_or_segment_range_to_geometry_rtree
<
typename boost::range_iterator<MultiPoint const>::type,
Areal,
Strategy
>::apply(boost::begin(multipoint),
boost::end(multipoint),
areal,
strategy);
}
static inline return_type apply(Areal const& areal,
MultiPoint const& multipoint,
Strategy const& strategy)
{
return apply(multipoint, areal, strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
struct distance
<
MultiPoint1, MultiPoint2, Strategy,
multi_point_tag, multi_point_tag,
strategy_tag_distance_point_point, false
> : detail::distance::multipoint_to_multipoint
<
MultiPoint1, MultiPoint2, Strategy
>
{};
template <typename MultiPoint, typename Linear, typename Strategy>
struct distance
<
MultiPoint, Linear, Strategy, multi_point_tag, linear_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
{};
template <typename Linear, typename MultiPoint, typename Strategy>
struct distance
<
Linear, MultiPoint, Strategy, linear_tag, multi_point_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
{};
template <typename MultiPoint, typename Areal, typename Strategy>
struct distance
<
MultiPoint, Areal, Strategy, multi_point_tag, areal_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
{};
template <typename Areal, typename MultiPoint, typename Strategy>
struct distance
<
Areal, MultiPoint, Strategy, areal_tag, multi_point_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP

View File

@ -1,183 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_RANGE_HPP
#include <boost/range.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/single_to_multi.hpp>
#include <boost/geometry/algorithms/detail/distance/multi_to_multi.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
struct multipoint_to_multipoint
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiPoint1>::type,
typename point_type<MultiPoint2>::type
>::type return_type;
static inline return_type apply(MultiPoint1 const& multipoint1,
MultiPoint2 const& multipoint2,
Strategy const& strategy)
{
if ( boost::size(multipoint1) > boost::size(multipoint2) )
{
return multipoint_to_multipoint
<
MultiPoint2, MultiPoint1, Strategy
>::apply(multipoint2, multipoint1, strategy);
}
return point_range_to_geometry_rtree
<
typename point_type<MultiPoint1>::type,
MultiPoint2,
Strategy
>::apply(points_begin(multipoint1), points_end(multipoint1),
multipoint2, strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
namespace splitted_dispatch
{
// specializations of distance_single_to_multi for various geometry combinations
template<typename Linestring, typename MultiPoint, typename Strategy>
struct distance_single_to_multi
<
Linestring, MultiPoint, Strategy,
linestring_tag, multi_point_tag,
strategy_tag_distance_point_segment
>
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Linestring>::type,
typename point_type<MultiPoint>::type
>::type return_type;
static inline return_type apply(Linestring const& linestring,
MultiPoint const& multipoint,
Strategy const& strategy)
{
return detail::distance::point_range_to_geometry_rtree
<
typename point_type<MultiPoint>::type,
Linestring,
Strategy
>::apply(geometry::points_begin(multipoint),
geometry::points_end(multipoint),
linestring, strategy);
}
};
// specializations of distance_multi_to_multi for various geometry combinations
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
struct distance_multi_to_multi
<
MultiPoint1, MultiPoint2, Strategy,
multi_point_tag, multi_point_tag,
strategy_tag_distance_point_point
> : detail::distance::multipoint_to_multipoint
<
MultiPoint1, MultiPoint2, Strategy
>
{};
template
<
typename MultiPoint,
typename MultiLinestring,
typename Strategy
>
struct distance_multi_to_multi
<
MultiPoint, MultiLinestring, Strategy,
multi_point_tag, multi_linestring_tag,
strategy_tag_distance_point_segment
>
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiPoint>::type,
typename point_type<MultiLinestring>::type
>::type return_type;
static inline return_type apply(MultiPoint const& multipoint,
MultiLinestring const& multilinestring,
Strategy const& strategy)
{
return detail::distance::point_range_to_geometry_rtree
<
typename point_type<MultiPoint>::type,
MultiLinestring,
Strategy
>::apply(geometry::points_begin(multipoint),
geometry::points_end(multipoint),
multilinestring, strategy);
}
};
} // namespace splitted_dispatch
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_ALTERNATE_HPP

View File

@ -20,33 +20,35 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
#include <utility>
#include <iterator>
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/interior_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
namespace boost { namespace geometry
{
@ -63,7 +65,7 @@ struct point_to_point
typename strategy::distance::services::return_type<Strategy, P1, P2>::type
apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
boost::ignore_unused(strategy);
return strategy.apply(p1, p2);
}
};
@ -84,12 +86,10 @@ private:
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
typedef detail::closest_feature::point_to_point_range
<
comparable_strategy,
Point,
typename boost::range_value<Range>::type
>::type comparable_return_type;
Point, Range, Closure, comparable_strategy
> point_to_point_range;
public:
typedef typename strategy::distance::services::return_type
@ -102,68 +102,42 @@ public:
static inline return_type apply(Point const& point, Range const& range,
Strategy const& strategy)
{
comparable_strategy c_strategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
comparable_return_type const zero = comparable_return_type(0);
return_type const zero = return_type(0);
if (boost::size(range) == 0)
{
return zero;
}
typedef typename closeable_view<Range const, Closure>::type view_type;
namespace sds = strategy::distance::services;
view_type view(range);
// line of one point: return point distance
typedef typename boost::range_iterator<view_type const>::type iterator_type;
iterator_type it = boost::begin(view);
iterator_type prev = it++;
if (it == boost::end(view))
{
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Point,
typename boost::range_value<Range>::type
>::apply( c_strategy.apply(point,
*boost::begin(view),
*boost::begin(view)) );
}
// start with first segment distance
comparable_return_type cd = c_strategy.apply(point, *prev, *it);
// check if other segments are closer
for (++prev, ++it; it != boost::end(view); ++prev, ++it)
{
comparable_return_type cds = c_strategy.apply(point, *prev, *it);
if (geometry::math::equals(cds, zero))
{
return strategy::distance::services::comparable_to_regular
<
comparable_strategy,
Strategy,
Point,
typename boost::range_value<Range>::type
>::apply(zero);
}
else if (cds < cd)
{
cd = cds;
}
}
return strategy::distance::services::comparable_to_regular
typename sds::return_type
<
comparable_strategy,
Strategy,
Point,
typename boost::range_value<Range>::type
>::apply(cd);
typename point_type<Range>::type
>::type cd_min;
std::pair
<
typename boost::range_iterator<Range const>::type,
typename boost::range_iterator<Range const>::type
> it_pair
= point_to_point_range::apply(point,
boost::begin(range),
boost::end(range),
sds::get_comparable
<
Strategy
>::apply(strategy),
cd_min);
return
is_comparable<Strategy>::value
?
cd_min
:
strategy.apply(point, *it_pair.first, *it_pair.second);
}
};
@ -177,35 +151,28 @@ template
>
struct point_to_ring
{
typedef std::pair
typedef typename strategy::distance::services::return_type
<
typename strategy::distance::services::return_type
<
Strategy, Point, typename point_type<Ring>::type
>::type,
bool
> distance_containment;
Strategy, Point, typename point_type<Ring>::type
>::type return_type;
static inline distance_containment apply(Point const& point,
Ring const& ring,
Strategy const& strategy)
static inline return_type apply(Point const& point,
Ring const& ring,
Strategy const& strategy)
{
return distance_containment
(
point_to_range
<
Point,
Ring,
Closure,
Strategy
>::apply(point, ring, strategy),
geometry::within(point, ring)
);
if (geometry::within(point, ring))
{
return return_type(0);
}
return point_to_range
<
Point, Ring, closure<Ring>::value, Strategy
>::apply(point, ring, strategy);
}
};
template
<
typename Point,
@ -215,79 +182,163 @@ template
>
class point_to_polygon
{
private:
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy, Point, typename point_type<Polygon>::type
>::type comparable_return_type;
typedef std::pair
<
comparable_return_type, bool
> comparable_distance_containment;
public:
typedef typename strategy::distance::services::return_type
<
Strategy, Point, typename point_type<Polygon>::type
>::type return_type;
typedef std::pair<return_type, bool> distance_containment;
static inline distance_containment apply(Point const& point,
Polygon const& polygon,
Strategy const& strategy)
private:
typedef point_to_range
<
Point, typename ring_type<Polygon>::type, Closure, Strategy
> per_ring;
struct distance_to_interior_rings
{
comparable_strategy c_strategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
// Check distance to all rings
typedef point_to_ring
<
Point,
typename ring_type<Polygon>::type,
Closure,
comparable_strategy
> per_ring;
comparable_distance_containment dc =
per_ring::apply(point, exterior_ring(polygon), c_strategy);
typename interior_return_type<Polygon const>::type rings
= interior_rings(polygon);
for (typename boost::range_iterator
<
typename interior_type<Polygon const>::type const
>::type it = boost::begin(rings);
it != boost::end(rings); ++it)
template <typename InteriorRingIterator>
static inline return_type apply(Point const& point,
InteriorRingIterator first,
InteriorRingIterator last,
Strategy const& strategy)
{
comparable_distance_containment dcr =
per_ring::apply(point, *it, c_strategy);
if (dcr.first < dc.first)
for (InteriorRingIterator it = first; it != last; ++it)
{
dc.first = dcr.first;
}
// If it was inside, and also inside inner ring,
// turn off the inside-flag, it is outside the polygon
if (dc.second && dcr.second)
{
dc.second = false;
if (geometry::within(point, *it))
{
// the point is inside a polygon hole, so its distance
// to the polygon its distance to the polygon's
// hole boundary
return per_ring::apply(point, *it, strategy);
}
}
return 0;
}
return_type rd = strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Point, Polygon
>::apply(dc.first);
template <typename InteriorRings>
static inline return_type apply(Point const& point,
InteriorRings const& interior_rings,
Strategy const& strategy)
{
return apply(point,
boost::begin(interior_rings),
boost::end(interior_rings),
strategy);
}
};
return std::make_pair(rd, dc.second);
public:
static inline return_type apply(Point const& point,
Polygon const& polygon,
Strategy const& strategy)
{
if (!geometry::covered_by(point, exterior_ring(polygon)))
{
// the point is outside the exterior ring, so its distance
// to the polygon is its distance to the polygon's exterior ring
return per_ring::apply(point, exterior_ring(polygon), strategy);
}
// Check interior rings
return distance_to_interior_rings::apply(point,
interior_rings(polygon),
strategy);
}
};
template
<
typename Point,
typename MultiGeometry,
typename Strategy,
bool CheckCoveredBy = boost::is_same
<
typename tag<MultiGeometry>::type, multi_polygon_tag
>::value
>
class point_to_multigeometry
{
private:
typedef detail::closest_feature::geometry_to_range geometry_to_range;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
Point,
typename point_type<MultiGeometry>::type
>::type return_type;
static inline return_type apply(Point const& point,
MultiGeometry const& multigeometry,
Strategy const& strategy)
{
typedef iterator_selector<MultiGeometry const> selector_type;
namespace sds = strategy::distance::services;
typename sds::return_type
<
typename sds::comparable_type<Strategy>::type,
Point,
typename point_type<MultiGeometry>::type
>::type cd;
typename selector_type::iterator_type it_min
= geometry_to_range::apply(point,
selector_type::begin(multigeometry),
selector_type::end(multigeometry),
sds::get_comparable
<
Strategy
>::apply(strategy),
cd);
return
is_comparable<Strategy>::value
?
cd
:
dispatch::distance
<
Point,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type,
Strategy
>::apply(point, *it_min, strategy);
}
};
// this is called only for multipolygons, hence the change in the
// template parameter name MultiGeometry to MultiPolygon
template <typename Point, typename MultiPolygon, typename Strategy>
struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
{
typedef typename strategy::distance::services::return_type
<
Strategy,
Point,
typename point_type<MultiPolygon>::type
>::type return_type;
static inline return_type apply(Point const& point,
MultiPolygon const& multipolygon,
Strategy const& strategy)
{
if (geometry::covered_by(point, multipolygon))
{
return 0;
}
return point_to_multigeometry
<
Point, MultiPolygon, Strategy, false
>::apply(point, multipolygon, strategy);
}
};
@ -307,111 +358,73 @@ namespace dispatch
template <typename P1, typename P2, typename Strategy>
struct distance
<
P1, P2, Strategy,
point_tag, point_tag, strategy_tag_distance_point_point,
false
>
: detail::distance::point_to_point<P1, P2, Strategy>
P1, P2, Strategy, point_tag, point_tag,
strategy_tag_distance_point_point, false
> : detail::distance::point_to_point<P1, P2, Strategy>
{};
// Point-line version 2, where point-segment strategy is specified
template <typename Point, typename Linestring, typename Strategy>
struct distance
<
Point, Linestring, Strategy,
point_tag, linestring_tag, strategy_tag_distance_point_segment,
false
> : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
<
Point, Linestring, Strategy, point_tag, linestring_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
{};
// Point-ring , where point-segment strategy is specified
template <typename Point, typename Ring, typename Strategy>
struct distance
<
Point, Ring, Strategy,
point_tag, ring_tag, strategy_tag_distance_point_segment,
false
>
{
typedef typename strategy::distance::services::return_type
<
Point, Ring, Strategy, point_tag, ring_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_ring
<
Strategy, Point, typename point_type<Ring>::type
>::type return_type;
static inline return_type apply(Point const& point,
Ring const& ring,
Strategy const& strategy)
{
std::pair<return_type, bool>
dc = detail::distance::point_to_ring
<
Point, Ring,
geometry::closure<Ring>::value,
Strategy
>::apply(point, ring, strategy);
return dc.second ? return_type(0) : dc.first;
}
};
Point, Ring, closure<Ring>::value, Strategy
>
{};
// Point-polygon , where point-segment strategy is specified
template <typename Point, typename Polygon, typename Strategy>
struct distance
<
Point, Polygon, Strategy, point_tag, polygon_tag,
strategy_tag_distance_point_segment, false
>
{
typedef typename strategy::distance::services::return_type
<
Point, Polygon, Strategy, point_tag, polygon_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_polygon
<
Strategy, Point, typename point_type<Polygon>::type
>::type return_type;
static inline return_type apply(Point const& point,
Polygon const& polygon,
Strategy const& strategy)
{
std::pair<return_type, bool>
dc = detail::distance::point_to_polygon
<
Point, Polygon,
geometry::closure<Polygon>::value,
Strategy
>::apply(point, polygon, strategy);
return dc.second ? return_type(0) : dc.first;
}
};
Point, Polygon, closure<Polygon>::value, Strategy
>
{};
// Point-segment version 2, with point-segment strategy
template <typename Point, typename Segment, typename Strategy>
struct distance
<
Point, Segment, Strategy,
point_tag, segment_tag, strategy_tag_distance_point_segment,
false
>
<
Point, Segment, Strategy, point_tag, segment_tag,
strategy_tag_distance_point_segment, false
>
{
static inline typename return_type<Strategy, Point, typename point_type<Segment>::type>::type
apply(Point const& point,
Segment const& segment,
Strategy const& strategy)
static inline typename strategy::distance::services::return_type
<
Strategy, Point, typename point_type<Segment>::type
>::type apply(Point const& point,
Segment const& segment,
Strategy const& strategy)
{
typename point_type<Segment>::type p[2];
geometry::detail::assign_point_from_index<0>(segment, p[0]);
geometry::detail::assign_point_from_index<1>(segment, p[1]);
boost::ignore_unused_variable_warning(strategy);
boost::ignore_unused(strategy);
return strategy.apply(point, p[0], p[1]);
}
};
template <typename Point, typename Box, typename Strategy>
struct distance
<
@ -425,12 +438,75 @@ struct distance
>::type
apply(Point const& point, Box const& box, Strategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
boost::ignore_unused(strategy);
return strategy.apply(point, box);
}
};
template<typename Point, typename MultiPoint, typename Strategy>
struct distance
<
Point, MultiPoint, Strategy, point_tag, multi_point_tag,
strategy_tag_distance_point_point, false
> : detail::distance::point_to_multigeometry
<
Point, MultiPoint, Strategy
>
{};
template<typename Point, typename MultiLinestring, typename Strategy>
struct distance
<
Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_multigeometry
<
Point, MultiLinestring, Strategy
>
{};
template<typename Point, typename MultiPolygon, typename Strategy>
struct distance
<
Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_multigeometry
<
Point, MultiPolygon, Strategy
>
{};
template <typename Point, typename Linear, typename Strategy>
struct distance
<
Point, Linear, Strategy, point_tag, linear_tag,
strategy_tag_distance_point_segment, false
> : distance
<
Point, Linear, Strategy,
point_tag, typename tag<Linear>::type,
strategy_tag_distance_point_segment, false
>
{};
template <typename Point, typename Areal, typename Strategy>
struct distance
<
Point, Areal, Strategy, point_tag, areal_tag,
strategy_tag_distance_point_segment, false
> : distance
<
Point, Areal, Strategy,
point_tag, typename tag<Areal>::type,
strategy_tag_distance_point_segment, false
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@ -1,160 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POLYGON_TO_SEGMENT_OR_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POLYGON_TO_SEGMENT_OR_BOX_HPP
#include <boost/range.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_segment_or_box.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Polygon, typename SegmentOrBox, typename Strategy>
class polygon_to_segment_or_box
{
private:
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy,
typename point_type<Polygon>::type,
typename point_type<SegmentOrBox>::type
>::type comparable_return_type;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Polygon>::type,
typename point_type<SegmentOrBox>::type
>::type return_type;
static inline return_type apply(Polygon const& polygon,
SegmentOrBox const& segment_or_box,
Strategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type e_ring;
typedef typename geometry::interior_type<Polygon>::type i_rings;
typedef typename range_value<i_rings>::type i_ring;
if ( geometry::intersects(polygon, segment_or_box) )
{
return 0;
}
e_ring const& ext_ring = geometry::exterior_ring<Polygon>(polygon);
i_rings const& int_rings = geometry::interior_rings<Polygon>(polygon);
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
comparable_return_type cd_min = range_to_segment_or_box
<
e_ring, SegmentOrBox, comparable_strategy
>::apply(ext_ring, segment_or_box, cstrategy, false);
typedef typename boost::range_iterator<i_rings const>::type iterator_type;
for (iterator_type it = boost::begin(int_rings);
it != boost::end(int_rings); ++it)
{
comparable_return_type cd = range_to_segment_or_box
<
i_ring, SegmentOrBox, comparable_strategy
>::apply(*it, segment_or_box, cstrategy, false);
if ( cd < cd_min )
{
cd_min = cd;
}
}
return strategy::distance::services::comparable_to_regular
<
comparable_strategy,
Strategy,
Polygon,
SegmentOrBox
>::apply(cd_min);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DETAIL
namespace dispatch
{
template <typename Polygon, typename Segment, typename Strategy>
struct distance
<
Polygon, Segment, Strategy, polygon_tag, segment_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::polygon_to_segment_or_box<Polygon, Segment, Strategy>
{};
template <typename Polygon, typename Box, typename Strategy>
struct distance
<
Polygon, Box, Strategy, polygon_tag, box_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::polygon_to_segment_or_box<Polygon, Box, Strategy>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POLYGON_TO_SEGMENT_OR_BOX_HPP

View File

@ -0,0 +1,131 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP
#include <iterator>
#include <utility>
#include <boost/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/iterators/has_one_element.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template
<
typename PointOrSegmentIterator,
typename Geometry,
typename Strategy
>
class point_or_segment_range_to_geometry_rtree
{
private:
typedef typename std::iterator_traits
<
PointOrSegmentIterator
>::value_type point_or_segment_type;
typedef iterator_selector<Geometry const> selector_type;
typedef detail::closest_feature::range_to_range_rtree range_to_range;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<point_or_segment_type>::type,
typename point_type<Geometry>::type
>::type return_type;
static inline return_type apply(PointOrSegmentIterator first,
PointOrSegmentIterator last,
Geometry const& geometry,
Strategy const& strategy)
{
namespace sds = strategy::distance::services;
BOOST_ASSERT( first != last );
if ( geometry::has_one_element(first, last) )
{
return dispatch::distance
<
point_or_segment_type, Geometry, Strategy
>::apply(*first, geometry, strategy);
}
typename sds::return_type
<
typename sds::comparable_type<Strategy>::type,
typename point_type<point_or_segment_type>::type,
typename point_type<Geometry>::type
>::type cd_min;
std::pair
<
point_or_segment_type,
typename selector_type::iterator_type
> closest_features
= range_to_range::apply(first,
last,
selector_type::begin(geometry),
selector_type::end(geometry),
sds::get_comparable
<
Strategy
>::apply(strategy),
cd_min);
return
is_comparable<Strategy>::value
?
cd_min
:
dispatch::distance
<
point_or_segment_type,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type,
Strategy
>::apply(closest_features.first,
*closest_features.second,
strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP

View File

@ -1,333 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_SEGMENT_OR_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_SEGMENT_OR_BOX_HPP
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template
<
typename Range,
typename SegmentOrBox,
typename Strategy
>
class range_to_segment_or_box
{
private:
typedef typename point_type<SegmentOrBox>::type segment_or_box_point;
typedef typename point_type<Range>::type range_point;
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy, range_point, segment_or_box_point
>::type comparable_return_type;
typedef typename strategy::distance::services::tag
<
comparable_strategy
>::type comparable_strategy_tag;
typedef dispatch::distance
<
segment_or_box_point, Range, comparable_strategy,
point_tag, typename tag<Range>::type,
comparable_strategy_tag, false
> comparable_point_to_range;
// compute distance of a point to a segment or a box
template
<
typename Point,
typename SegOrBoxPoints,
typename ComparableStrategy,
typename Tag
>
struct comparable_distance_point_to_segment_or_box
{};
template
<
typename Point,
typename SegmentPoints,
typename ComparableStrategy
>
struct comparable_distance_point_to_segment_or_box
<
Point, SegmentPoints, ComparableStrategy, segment_tag
>
{
static inline
comparable_return_type apply(Point const& point,
SegmentPoints const& segment_points,
ComparableStrategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
return strategy.apply(point, segment_points[0], segment_points[1]);
}
};
template
<
typename Point,
typename BoxPoints,
typename ComparableStrategy
>
struct comparable_distance_point_to_segment_or_box
<
Point, BoxPoints, ComparableStrategy, box_tag
>
{
static inline
comparable_return_type apply(Point const& point,
BoxPoints const& box_points,
ComparableStrategy const& strategy)
{
return point_to_range
<
Point, BoxPoints, open, ComparableStrategy
>::apply(point, box_points, strategy);
}
};
// assign the points of a segment or a box to a range
template
<
typename SegOrBox,
typename PointRange,
typename Tag = typename tag<SegOrBox>::type
>
struct assign_segment_or_box_points
{};
template <typename Segment, typename PointRange>
struct assign_segment_or_box_points<Segment, PointRange, segment_tag>
{
static inline void apply(Segment const& segment, PointRange& range)
{
detail::assign_point_from_index<0>(segment, range[0]);
detail::assign_point_from_index<1>(segment, range[1]);
}
};
template <typename Box, typename PointRange>
struct assign_segment_or_box_points<Box, PointRange, box_tag>
{
static inline void apply(Box const& box, PointRange& range)
{
detail::assign_box_corners_oriented<true>(box, range);
}
};
public:
typedef typename strategy::distance::services::return_type
<
Strategy, range_point, segment_or_box_point
>::type return_type;
static inline return_type
apply(Range const& range, SegmentOrBox const& segment_or_box,
Strategy const& strategy, bool check_intersection = true)
{
if ( check_intersection && geometry::intersects(range, segment_or_box) )
{
return 0;
}
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
// get all points of the segment or the box
std::vector<segment_or_box_point>
segment_or_box_points(geometry::num_points(segment_or_box));
assign_segment_or_box_points
<
SegmentOrBox,
std::vector<segment_or_box_point>
>::apply(segment_or_box, segment_or_box_points);
// consider all distances from each endpoint of the segment or box
// to the range
typename std::vector<segment_or_box_point>::const_iterator it
= segment_or_box_points.begin();
comparable_return_type cd_min =
comparable_point_to_range::apply(*it, range, cstrategy);
for (++it; it != segment_or_box_points.end(); ++it)
{
comparable_return_type cd =
comparable_point_to_range::apply(*it, range, cstrategy);
if ( cd < cd_min )
{
cd_min = cd;
}
}
// consider all distances of the points in the range to the
// segment or box
typedef typename range_iterator<Range const>::type iterator_type;
for (iterator_type it = boost::begin(range); it != boost::end(range); ++it)
{
comparable_return_type cd =
comparable_distance_point_to_segment_or_box
<
typename point_type<Range>::type,
std::vector<segment_or_box_point>,
comparable_strategy,
typename tag<SegmentOrBox>::type
>::apply(*it, segment_or_box_points, cstrategy);
if ( cd < cd_min )
{
cd_min = cd;
}
}
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy,
range_point, segment_or_box_point
>::apply(cd_min);
}
static inline return_type
apply(SegmentOrBox const& segment_or_box, Range const& range,
Strategy const& strategy, bool check_intersection = true)
{
return apply(range, segment_or_box, strategy, check_intersection);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linestring, typename Segment, typename Strategy>
struct distance
<
Linestring, Segment, Strategy, linestring_tag, segment_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::range_to_segment_or_box
<
Linestring, Segment, Strategy
>
{};
template <typename Segment, typename Ring, typename Strategy>
struct distance
<
Segment, Ring, Strategy, segment_tag, ring_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::range_to_segment_or_box
<
Ring, Segment, Strategy
>
{};
template <typename Linestring, typename Box, typename Strategy>
struct distance
<
Linestring, Box, Strategy, linestring_tag, box_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::range_to_segment_or_box
<
Linestring, Box, Strategy
>
{};
template <typename Ring, typename Box, typename Strategy>
struct distance
<
Ring, Box, Strategy, ring_tag, box_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::range_to_segment_or_box
<
Ring, Box, Strategy
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_SEGMENT_OR_BOX_HPP

View File

@ -10,6 +10,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
#include <cstddef>
#include <functional>
#include <vector>
@ -20,6 +22,7 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
@ -28,7 +31,6 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/policies/compare.hpp>
@ -40,7 +42,7 @@
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@ -73,16 +75,19 @@ private:
Strategy
>::type comparable_strategy;
typedef detail::closest_feature::point_to_point_range
<
segment_point,
std::vector<box_point>,
open,
comparable_strategy
> point_to_point_range;
typedef typename strategy::distance::services::return_type
<
comparable_strategy, segment_point, box_point
>::type comparable_return_type;
typedef point_to_range
<
segment_point, std::vector<box_point>, open, comparable_strategy
> point_to_box_boundary;
public:
typedef typename strategy::distance::services::return_type
<
@ -94,7 +99,7 @@ public:
Strategy const& strategy,
bool check_intersection = true)
{
if ( check_intersection && geometry::intersects(segment, box) )
if (check_intersection && geometry::intersects(segment, box))
{
return 0;
}
@ -104,7 +109,6 @@ public:
<
Strategy
>::apply(strategy);
boost::ignore_unused(cstrategy);
// get segment points
segment_point p[2];
@ -120,13 +124,49 @@ public:
{
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
}
cd[4] = point_to_box_boundary::apply(p[0], box_points, cstrategy);
cd[5] = point_to_box_boundary::apply(p[1], box_points, cstrategy);
return strategy::distance::services::comparable_to_regular
std::pair
<
comparable_strategy, Strategy, Segment, Box
>::apply( *std::min_element(cd, cd + 6) );
typename std::vector<box_point>::const_iterator,
typename std::vector<box_point>::const_iterator
> bit_min[2];
bit_min[0] = point_to_point_range::apply(p[0],
box_points.begin(),
box_points.end(),
cstrategy,
cd[4]);
bit_min[1] = point_to_point_range::apply(p[1],
box_points.begin(),
box_points.end(),
cstrategy,
cd[5]);
unsigned int imin = 0;
for (unsigned int i = 1; i < 6; ++i)
{
if (cd[i] < cd[imin])
{
imin = i;
}
}
if (is_comparable<Strategy>::value)
{
return cd[imin];
}
if (imin < 4)
{
return strategy.apply(box_points[imin], p[0], p[1]);
}
else
{
unsigned int bimin = imin - 4;
return strategy.apply(p[bimin],
*bit_min[bimin].first,
*bit_min[bimin].second);
}
}
};
@ -153,12 +193,14 @@ private:
comparable_strategy, segment_point, box_point
>::type comparable_return_type;
typedef typename detail::distance::default_strategy
<
segment_point, Box
>::type point_box_strategy;
typedef typename strategy::distance::services::comparable_type
<
typename detail::distance::default_strategy
<
segment_point, Box
>::type
point_box_strategy
>::type point_box_comparable_strategy;
public:
@ -172,7 +214,7 @@ public:
Strategy const& strategy,
bool check_intersection = true)
{
if ( check_intersection && geometry::intersects(segment, box) )
if (check_intersection && geometry::intersects(segment, box))
{
return 0;
}
@ -204,10 +246,28 @@ public:
cd[4] = pb_cstrategy.apply(p[0], box);
cd[5] = pb_cstrategy.apply(p[1], box);
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Segment, Box
>::apply( *std::min_element(cd, cd + 6) );
unsigned int imin = 0;
for (unsigned int i = 1; i < 6; ++i)
{
if (cd[i] < cd[imin])
{
imin = i;
}
}
if (is_comparable<Strategy>::value)
{
return cd[imin];
}
if (imin < 4)
{
strategy.apply(box_points[imin], p[0], p[1]);
}
else
{
return point_box_strategy().apply(p[imin - 4], box);
}
}
};
@ -294,19 +354,22 @@ private:
LessEqual less_equal;
if ( less_equal(geometry::get<1>(top_right), geometry::get<1>(p0)) )
if (less_equal(geometry::get<1>(top_right), geometry::get<1>(p0)))
{
// closest box point is the top-right corner
return cast::apply(pp_strategy.apply(p0, top_right));
}
else if ( less_equal(geometry::get<1>(bottom_right),
geometry::get<1>(p0)) )
else if (less_equal(geometry::get<1>(bottom_right),
geometry::get<1>(p0)))
{
// distance is realized between p0 and right-most
// segment of box
ReturnType diff = cast::apply(geometry::get<0>(p0))
- cast::apply(geometry::get<0>(bottom_right));
return diff * diff;
return strategy::distance::services::result_from_distance
<
PSStrategy, BoxPoint, SegmentPoint
>::apply(ps_strategy, math::abs(diff));
}
else
{
@ -338,11 +401,14 @@ private:
// p0 is above the upper segment of the box
// (and inside its band)
if ( less_equal(geometry::get<0>(top_left), geometry::get<0>(p0)) )
if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p0)))
{
ReturnType diff = cast::apply(geometry::get<1>(p0))
- cast::apply(geometry::get<1>(top_left));
return diff * diff;
return strategy::distance::services::result_from_distance
<
PSStrategy, SegmentPoint, BoxPoint
>::apply(ps_strategy, math::abs(diff));
}
// p0 is to the left of the box, but p1 is above the box
@ -367,7 +433,7 @@ private:
ReturnType& result)
{
// p0 lies to the right of the box
if ( geometry::get<0>(p0) >= geometry::get<0>(top_right) )
if (geometry::get<0>(p0) >= geometry::get<0>(top_right))
{
result = right_of_box
<
@ -378,7 +444,7 @@ private:
}
// p1 lies to the left of the box
if ( geometry::get<0>(p1) <= geometry::get<0>(bottom_left) )
if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left))
{
result = right_of_box
<
@ -406,7 +472,7 @@ private:
ReturnType& result)
{
// the segment lies below the box
if ( geometry::get<1>(p1) < geometry::get<1>(bottom_left) )
if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
{
result = above_of_box
<
@ -416,7 +482,7 @@ private:
}
// the segment lies above the box
if ( geometry::get<1>(p0) > geometry::get<1>(top_right) )
if (geometry::get<1>(p0) > geometry::get<1>(top_right))
{
result = above_of_box
<
@ -457,7 +523,7 @@ private:
ReturnType t_max1 = cast::apply(geometry::get<1>(top_right1))
- cast::apply(geometry::get<1>(p0));
if ( diff1 < 0 )
if (diff1 < 0)
{
diff1 = -diff1;
t_min1 = -t_min1;
@ -465,14 +531,14 @@ private:
}
// t_min0 > t_max1
if ( t_min0 * diff1 > t_max1 * diff0 )
if (t_min0 * diff1 > t_max1 * diff0)
{
result = cast::apply(ps_strategy.apply(corner1, p0, p1));
return true;
}
// t_max0 < t_min1
if ( t_max0 * diff1 < t_min1 * diff0 )
if (t_max0 * diff1 < t_min1 * diff0)
{
result = cast::apply(ps_strategy.apply(corner2, p0, p1));
return true;
@ -503,31 +569,31 @@ private:
ReturnType result(0);
if ( check_right_left_of_box
<
less_equal
>::apply(p0, p1,
top_left, top_right, bottom_left, bottom_right,
pp_strategy, ps_strategy, result) )
if (check_right_left_of_box
<
less_equal
>::apply(p0, p1,
top_left, top_right, bottom_left, bottom_right,
pp_strategy, ps_strategy, result))
{
return result;
}
if ( check_above_below_of_box
<
less_equal
>::apply(p0, p1,
top_left, top_right, bottom_left, bottom_right,
ps_strategy, result) )
if (check_above_below_of_box
<
less_equal
>::apply(p0, p1,
top_left, top_right, bottom_left, bottom_right,
ps_strategy, result))
{
return result;
}
if ( check_generic_position::apply(p0, p1,
bottom_left, top_right,
bottom_left, top_right,
top_left, bottom_right,
ps_strategy, result) )
if (check_generic_position::apply(p0, p1,
bottom_left, top_right,
bottom_left, top_right,
top_left, bottom_right,
ps_strategy, result))
{
return result;
}
@ -555,31 +621,31 @@ private:
ReturnType result(0);
if ( check_right_left_of_box
<
greater_equal
>::apply(p0, p1,
bottom_left, bottom_right, top_left, top_right,
pp_strategy, ps_strategy, result) )
if (check_right_left_of_box
<
greater_equal
>::apply(p0, p1,
bottom_left, bottom_right, top_left, top_right,
pp_strategy, ps_strategy, result))
{
return result;
}
if ( check_above_below_of_box
<
greater_equal
>::apply(p1, p0,
top_right, top_left, bottom_right, bottom_left,
ps_strategy, result) )
if (check_above_below_of_box
<
greater_equal
>::apply(p1, p0,
top_right, top_left, bottom_right, bottom_left,
ps_strategy, result))
{
return result;
}
if ( check_generic_position::apply(p0, p1,
bottom_left, top_right,
top_right, bottom_left,
bottom_left, top_right,
ps_strategy, result) )
if (check_generic_position::apply(p0, p1,
bottom_left, top_right,
top_right, bottom_left,
bottom_left, top_right,
ps_strategy, result))
{
return result;
}
@ -600,8 +666,8 @@ public:
{
BOOST_ASSERT( geometry::less<SegmentPoint>()(p0, p1) );
if ( geometry::get<0>(p0) < geometry::get<0>(p1)
&& geometry::get<1>(p0) > geometry::get<1>(p1) )
if (geometry::get<0>(p0) < geometry::get<0>(p1)
&& geometry::get<1>(p0) > geometry::get<1>(p1))
{
return negative_slope_segment(p0, p1,
top_left, top_right,
@ -675,7 +741,7 @@ public:
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
if ( geometry::equals(p[0], p[1]) )
if (geometry::equals(p[0], p[1]))
{
typedef typename boost::mpl::if_
<
@ -709,53 +775,34 @@ public:
detail::assign_box_corners(box, bottom_left, bottom_right,
top_left, top_right);
pp_comparable_strategy c_pp_strategy =
strategy::distance::services::get_comparable
<
PPStrategy
>::apply(pp_strategy);
ps_comparable_strategy c_ps_strategy =
strategy::distance::services::get_comparable
<
PSStrategy
>::apply(ps_strategy);
comparable_return_type cd;
if ( geometry::less<segment_point>()(p[0], p[1]) )
if (geometry::less<segment_point>()(p[0], p[1]))
{
cd = segment_to_box_2D
return segment_to_box_2D
<
return_type,
segment_point,
box_point,
pp_comparable_strategy,
ps_comparable_strategy
PPStrategy,
PSStrategy
>::apply(p[0], p[1],
top_left, top_right, bottom_left, bottom_right,
c_pp_strategy,
c_ps_strategy);
pp_strategy,
ps_strategy);
}
else
{
cd = segment_to_box_2D
return segment_to_box_2D
<
return_type,
segment_point,
box_point,
pp_comparable_strategy,
ps_comparable_strategy
PPStrategy,
PSStrategy
>::apply(p[1], p[0],
top_left, top_right, bottom_left, bottom_right,
c_pp_strategy,
c_ps_strategy);
pp_strategy,
ps_strategy);
}
return strategy::distance::services::comparable_to_regular
<
ps_comparable_strategy, PSStrategy, Segment, Box
>::apply( cd );
}
};
@ -790,12 +837,32 @@ struct distance
{
assert_dimension_equal<Segment, Box>();
typedef typename detail::distance::default_strategy
typedef typename boost::mpl::if_
<
typename point_type<Segment>::type,
typename point_type<Box>::type
boost::is_same
<
typename strategy::distance::services::comparable_type
<
Strategy
>::type,
Strategy
>,
typename strategy::distance::services::comparable_type
<
typename detail::distance::default_strategy
<
typename point_type<Segment>::type,
typename point_type<Box>::type
>::type
>::type,
typename detail::distance::default_strategy
<
typename point_type<Segment>::type,
typename point_type<Box>::type
>::type
>::type pp_strategy_type;
return detail::distance::segment_to_box
<
Segment,

View File

@ -11,17 +11,21 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP
#include <algorithm>
#include <iterator>
#include <boost/core/addressof.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@ -64,7 +68,7 @@ public:
apply(Segment1 const& segment1, Segment2 const& segment2,
Strategy const& strategy)
{
if ( geometry::intersects(segment1, segment2) )
if (geometry::intersects(segment1, segment2))
{
return 0;
}
@ -89,10 +93,25 @@ public:
d[2] = cstrategy.apply(p[0], q[0], q[1]);
d[3] = cstrategy.apply(p[1], q[0], q[1]);
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Segment1, Segment2
>::apply( *std::min_element(d, d + 4) );
std::size_t imin = std::distance(boost::addressof(d[0]),
std::min_element(d, d + 4));
if (is_comparable<Strategy>::value)
{
return d[imin];
}
switch (imin)
{
case 0:
return strategy.apply(q[0], p[0], p[1]);
case 1:
return strategy.apply(q[1], p[0], p[1]);
case 2:
return strategy.apply(p[0], q[0], q[1]);
default:
return strategy.apply(p[1], q[0], q[1]);
}
}
};

View File

@ -1,526 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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_DETAIL_DISTANCE_SINGLE_TO_MULTI_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SINGLE_TO_MULTI_HPP
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/geometry_id.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/for_each.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template<typename Geometry, typename MultiGeometry, typename Strategy>
class distance_single_to_multi_generic
{
private:
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy,
typename point_type<Geometry>::type,
typename point_type<MultiGeometry>::type
>::type comparable_return_type;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry>::type,
typename point_type<MultiGeometry>::type
>::type return_type;
static inline return_type apply(Geometry const& geometry,
MultiGeometry const& multi,
Strategy const& strategy)
{
comparable_return_type min_cdist = comparable_return_type();
bool first = true;
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
for (typename range_iterator<MultiGeometry const>::type it = boost::begin(multi);
it != boost::end(multi);
++it, first = false)
{
comparable_return_type cdist = dispatch::distance
<
Geometry,
typename range_value<MultiGeometry>::type,
comparable_strategy
>::apply(geometry, *it, cstrategy);
if (first || cdist < min_cdist)
{
min_cdist = cdist;
if ( geometry::math::equals(min_cdist, 0) )
{
break;
}
}
}
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Geometry, MultiGeometry
>::apply(min_cdist);
}
};
template <typename MultiGeometry, typename Geometry, typename Strategy>
struct distance_multi_to_single_generic
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiGeometry>::type,
typename point_type<Geometry>::type
>::type return_type;
static inline return_type apply(MultiGeometry const& multi,
Geometry const& geometry,
Strategy const& strategy)
{
return distance_single_to_multi_generic
<
Geometry, MultiGeometry, Strategy
>::apply(geometry, multi, strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
namespace splitted_dispatch
{
template
<
typename Geometry,
typename MultiGeometry,
typename Strategy,
typename GeometryTag,
typename MultiGeometryTag,
typename StrategyTag
>
struct distance_single_to_multi
: not_implemented<Geometry, MultiGeometry>
{};
template<typename Point, typename MultiPoint, typename Strategy>
struct distance_single_to_multi
<
Point, MultiPoint, Strategy,
point_tag, multi_point_tag,
strategy_tag_distance_point_point
> : detail::distance::distance_single_to_multi_generic
<
Point, MultiPoint, Strategy
>
{};
template<typename Point, typename MultiLinestring, typename Strategy>
struct distance_single_to_multi
<
Point, MultiLinestring, Strategy,
point_tag, multi_linestring_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_single_to_multi_generic
<
Point, MultiLinestring, Strategy
>
{};
template<typename Point, typename MultiPolygon, typename Strategy>
struct distance_single_to_multi
<
Point, MultiPolygon, Strategy,
point_tag, multi_polygon_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_single_to_multi_generic
<
Point, MultiPolygon, Strategy
>
{};
template<typename Linestring, typename MultiLinestring, typename Strategy>
struct distance_single_to_multi
<
Linestring, MultiLinestring, Strategy,
linestring_tag, multi_linestring_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
Linestring, MultiLinestring, Strategy
>
{};
template <typename Linestring, typename MultiPolygon, typename Strategy>
struct distance_single_to_multi
<
Linestring, MultiPolygon, Strategy,
linestring_tag, multi_polygon_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
Linestring, MultiPolygon, Strategy
>
{};
template <typename Polygon, typename MultiPoint, typename Strategy>
struct distance_single_to_multi
<
Polygon, MultiPoint, Strategy,
polygon_tag, multi_point_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_single_to_multi_generic
<
Polygon, MultiPoint, Strategy
>
{};
template <typename Polygon, typename MultiLinestring, typename Strategy>
struct distance_single_to_multi
<
Polygon, MultiLinestring, Strategy,
polygon_tag, multi_linestring_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
Polygon, MultiLinestring, Strategy
>
{};
template <typename Polygon, typename MultiPolygon, typename Strategy>
struct distance_single_to_multi
<
Polygon, MultiPolygon, Strategy,
polygon_tag, multi_polygon_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
Polygon, MultiPolygon, Strategy
>
{};
template <typename MultiLinestring, typename Ring, typename Strategy>
struct distance_single_to_multi
<
MultiLinestring, Ring, Strategy,
multi_linestring_tag, ring_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
MultiLinestring, Ring, Strategy
>
{};
template <typename MultiPolygon, typename Ring, typename Strategy>
struct distance_single_to_multi
<
MultiPolygon, Ring, Strategy,
multi_polygon_tag, ring_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
MultiPolygon, Ring, Strategy
>
{};
template
<
typename MultiGeometry,
typename Geometry,
typename Strategy,
typename MultiGeometryTag,
typename GeometryTag,
typename StrategyTag
>
struct distance_multi_to_single
: not_implemented<MultiGeometry, Geometry>
{};
template
<
typename MultiPoint,
typename Segment,
typename Strategy
>
struct distance_multi_to_single
<
MultiPoint, Segment, Strategy,
multi_point_tag, segment_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_multi_to_single_generic
<
MultiPoint, Segment, Strategy
>
{};
template
<
typename MultiPoint,
typename Ring,
typename Strategy
>
struct distance_multi_to_single
<
MultiPoint, Ring, Strategy,
multi_point_tag, ring_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_multi_to_single_generic
<
MultiPoint, Ring, Strategy
>
{};
template
<
typename MultiPoint,
typename Box,
typename Strategy
>
struct distance_multi_to_single
<
MultiPoint, Box, Strategy,
multi_point_tag, box_tag,
strategy_tag_distance_point_box
> : detail::distance::distance_multi_to_single_generic
<
MultiPoint, Box, Strategy
>
{};
template <typename MultiLinestring, typename Segment, typename Strategy>
struct distance_multi_to_single
<
MultiLinestring, Segment, Strategy,
multi_linestring_tag, segment_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_multi_to_single_generic
<
MultiLinestring, Segment, Strategy
>
{};
template <typename MultiLinestring, typename Ring, typename Strategy>
struct distance_multi_to_single
<
MultiLinestring, Ring, Strategy,
multi_linestring_tag, ring_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
MultiLinestring, Ring, Strategy
>
{};
template <typename MultiLinestring, typename Box, typename Strategy>
struct distance_multi_to_single
<
MultiLinestring, Box, Strategy,
multi_linestring_tag, box_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_multi_to_single_generic
<
MultiLinestring, Box, Strategy
>
{};
template <typename MultiPolygon, typename Segment, typename Strategy>
struct distance_multi_to_single
<
MultiPolygon, Segment, Strategy,
multi_polygon_tag, segment_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_multi_to_single_generic
<
MultiPolygon, Segment, Strategy
>
{};
template <typename MultiPolygon, typename Ring, typename Strategy>
struct distance_multi_to_single
<
MultiPolygon, Ring, Strategy,
multi_polygon_tag, ring_tag,
strategy_tag_distance_point_segment
> : detail::distance::geometry_to_geometry_rtree
<
MultiPolygon, Ring, Strategy
>
{};
template <typename MultiPolygon, typename Box, typename Strategy>
struct distance_multi_to_single
<
MultiPolygon, Box, Strategy,
multi_polygon_tag, box_tag,
strategy_tag_distance_point_segment
> : detail::distance::distance_multi_to_single_generic
<
MultiPolygon, Box, Strategy
>
{};
} // namespace splitted_dispatch
template
<
typename Geometry,
typename MultiGeometry,
typename Strategy,
typename GeometryTag,
typename StrategyTag
>
struct distance
<
Geometry, MultiGeometry, Strategy, GeometryTag, multi_tag,
StrategyTag, false
> : splitted_dispatch::distance_single_to_multi
<
Geometry, MultiGeometry, Strategy,
GeometryTag, typename tag<MultiGeometry>::type,
StrategyTag
>
{};
template
<
typename MultiGeometry,
typename Geometry,
typename Strategy,
typename GeometryTag,
typename StrategyTag
>
struct distance
<
MultiGeometry, Geometry, Strategy, multi_tag, GeometryTag,
StrategyTag, false
> : splitted_dispatch::distance_multi_to_single
<
MultiGeometry, Geometry, Strategy,
typename tag<MultiGeometry>::type, GeometryTag,
StrategyTag
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SINGLE_TO_MULTI_HPP

View File

@ -228,7 +228,7 @@ struct less
template <typename Turn>
static inline bool use_fraction(Turn const& left, Turn const& right)
{
static const LessOp less_op;
static LessOp less_op;
return left.operations[OpId].fraction < right.operations[OpId].fraction
|| ( left.operations[OpId].fraction == right.operations[OpId].fraction

View File

@ -103,7 +103,7 @@ typename sub_range_return_type<Geometry>::type
sub_range(Geometry & geometry, Id const& id)
{
return detail_dispatch::sub_range<Geometry>::apply(geometry, id);
};
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL

View File

@ -24,6 +24,10 @@
// So decided that at least for Boost 1.49 this is commented for
// scalar results, except distance.
#if defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)
#include <boost/core/ignore_unused.hpp>
#endif
namespace boost { namespace geometry
{
@ -39,6 +43,8 @@ inline void throw_on_empty_input(Geometry const& geometry)
{
throw empty_input_exception();
}
#else
boost::ignore_unused(geometry);
#endif
}

View File

@ -22,7 +22,9 @@
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@ -36,16 +38,33 @@ namespace dispatch
{
using strategy::distance::services::return_type;
template
<
typename Geometry1, typename Geometry2,
typename Strategy = typename detail::distance::default_strategy<Geometry1, Geometry2>::type,
typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
typename StrategyTag = typename strategy::distance::services::tag<Strategy>::type,
typename Strategy = typename detail::distance::default_strategy
<
Geometry1, Geometry2
>::type,
typename Tag1 = typename tag_cast
<
typename tag<Geometry1>::type,
segment_tag,
box_tag,
linear_tag,
areal_tag
>::type,
typename Tag2 = typename tag_cast
<
typename tag<Geometry2>::type,
segment_tag,
box_tag,
linear_tag,
areal_tag
>::type,
typename StrategyTag = typename strategy::distance::services::tag
<
Strategy
>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct distance: not_implemented<Tag1, Tag2>
@ -53,8 +72,6 @@ struct distance: not_implemented<Tag1, Tag2>
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@ -16,6 +16,7 @@
#include <cstddef>
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
@ -52,6 +53,8 @@ struct simplify_range_insert
static inline void apply(Range const& range, OutputIterator out,
Distance const& max_distance, Strategy const& strategy)
{
boost::ignore_unused(strategy);
if (boost::size(range) <= 2 || max_distance < 0)
{
std::copy(boost::begin(range), boost::end(range), out);

View File

@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -16,7 +21,8 @@
#include <cstddef>
#include <boost/type_traits.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
@ -45,6 +51,35 @@ struct degree {};
struct radian {};
#ifndef DOXYGEN_NO_DETAIL
namespace core_detail
{
template <typename DegreeOrRadian>
struct coordinate_system_units
{
BOOST_MPL_ASSERT_MSG
((false),
COORDINATE_SYSTEM_UNITS_MUST_BE_DEGREES_OR_RADIANS,
(types<DegreeOrRadian>));
};
template <>
struct coordinate_system_units<geometry::degree>
{
typedef geometry::degree units;
};
template <>
struct coordinate_system_units<geometry::radian>
{
typedef geometry::radian units;
};
} // namespace core_detail
#endif // DOXYGEN_NO_DETAIL
namespace cs
{
@ -73,7 +108,10 @@ known as lat,long or lo,la or phi,lambda
template<typename DegreeOrRadian>
struct geographic
{
typedef DegreeOrRadian units;
typedef typename core_detail::coordinate_system_units
<
DegreeOrRadian
>::units units;
};
@ -99,7 +137,10 @@ struct geographic
template<typename DegreeOrRadian>
struct spherical
{
typedef DegreeOrRadian units;
typedef typename core_detail::coordinate_system_units
<
DegreeOrRadian
>::units units;
};
@ -116,7 +157,10 @@ struct spherical
template<typename DegreeOrRadian>
struct spherical_equatorial
{
typedef DegreeOrRadian units;
typedef typename core_detail::coordinate_system_units
<
DegreeOrRadian
>::units units;
};
@ -131,7 +175,10 @@ struct spherical_equatorial
template<typename DegreeOrRadian>
struct polar
{
typedef DegreeOrRadian units;
typedef typename core_detail::coordinate_system_units
<
DegreeOrRadian
>::units units;
};

View File

@ -29,9 +29,9 @@ namespace dispatch
{
template <typename Geometry>
struct num_points<nsphere_tag, Geometry>
: detail::num_points::other_count<1>
template <typename Geometry, bool AddForOpen>
struct num_points<Geometry, AddForOpen, nsphere_tag>
: detail::counting::other_count<1>
{};

View File

@ -61,9 +61,9 @@ private:
Translator const& m_tr;
};
template <typename Parameters, typename Box, size_t AxisIndex>
struct choose_split_axis_and_index_for_axis<Parameters, Box, AxisIndex, nsphere_tag>
: choose_split_axis_and_index_for_axis<Parameters, Box, AxisIndex, box_tag>
template <typename Box, size_t AxisIndex>
struct choose_split_axis_and_index_for_axis<Box, AxisIndex, nsphere_tag>
: choose_split_axis_and_index_for_axis<Box, AxisIndex, box_tag>
{};

View File

@ -150,7 +150,7 @@ public :
}
}
void resize(std::size_t new_size)
void resize(std::size_t /*new_size*/)
{
if (m_do_hole)
{

View File

@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -17,6 +22,7 @@
#include <cstddef>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@ -24,7 +30,6 @@
namespace boost { namespace geometry { namespace concept
{
@ -46,6 +51,9 @@ The point concept is defined as following:
with two functions:
- \b get to get a coordinate value
- \b set to set a coordinate value (this one is not checked for ConstPoint)
- for non-Cartesian coordinate systems, the coordinate system's units
must either be boost::geometry::degree or boost::geometry::radian
\par Example:
@ -90,8 +98,12 @@ class Point
typedef typename coordinate_type<Geometry>::type ctype;
typedef typename coordinate_system<Geometry>::type csystem;
enum { ccount = dimension<Geometry>::value };
// The following enum is used to fully instantiate the coordinate
// system class; this is needed in order to check the units passed
// to it for non-Cartesian coordinate systems.
enum { cs_check = sizeof(csystem) };
enum { ccount = dimension<Geometry>::value };
template <typename P, std::size_t Dimension, std::size_t DimensionCount>
struct dimension_checker
@ -139,8 +151,12 @@ class ConstPoint
typedef typename coordinate_type<Geometry>::type ctype;
typedef typename coordinate_system<Geometry>::type csystem;
enum { ccount = dimension<Geometry>::value };
// The following enum is used to fully instantiate the coordinate
// system class; this is needed in order to check the units passed
// to it for non-Cartesian coordinate systems.
enum { cs_check = sizeof(csystem) };
enum { ccount = dimension<Geometry>::value };
template <typename P, std::size_t Dimension, std::size_t DimensionCount>
struct dimension_checker
@ -149,7 +165,7 @@ class ConstPoint
{
const P* p = 0;
ctype coord(geometry::get<Dimension>(*p));
boost::ignore_unused_variable_warning(coord);
boost::ignore_unused(coord);
dimension_checker<P, Dimension+1, DimensionCount>::apply();
}
};

View File

@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -64,6 +69,12 @@ template
>
class point
{
private:
// The following enum is used to fully instantiate the
// CoordinateSystem class and check the correctness of the units
// passed for non-Cartesian coordinate systems.
enum { cs_check = sizeof(CoordinateSystem) };
public:
/// @brief Default constructor, no initialization

View File

@ -299,7 +299,7 @@ inline void pick_seeds(Elements const& elements,
separation_type separation = 0;
impl::apply(elements, parameters, tr, separation, seed1, seed2);
};
}
} // namespace linear

View File

@ -96,13 +96,13 @@ public:
typename OtherValue,
typename OtherReference
>
concatenate_iterator operator=(concatenate_iterator
<
OtherIt1,
OtherIt2,
OtherValue,
OtherReference
> const& other)
concatenate_iterator & operator=(concatenate_iterator
<
OtherIt1,
OtherIt2,
OtherValue,
OtherReference
> const& other)
{
static const bool are_conv
= boost::is_convertible<OtherIt1, Iterator1>::value

View File

@ -149,12 +149,12 @@ public:
typename OtherValue,
typename OtherReference
>
range_segment_iterator operator=(range_segment_iterator
<
OtherRange,
OtherValue,
OtherReference
> const& other)
range_segment_iterator & operator=(range_segment_iterator
<
OtherRange,
OtherValue,
OtherReference
> const& other)
{
typedef typename range_segment_iterator
<

View File

@ -72,6 +72,16 @@ public:
: m_outer_it(outer_end), m_outer_end(outer_end)
{}
flatten_iterator & operator=(flatten_iterator const& other)
{
m_outer_it = other.m_outer_it;
m_outer_end = other.m_outer_end;
// avoid assigning an iterator having singular value
if ( other.m_outer_it != other.m_outer_end )
m_inner_it = other.m_inner_it;
return *this;
}
template
<
typename OtherOuterIterator, typename OtherInnerIterator,
@ -116,15 +126,15 @@ public:
typename OtherAccessInnerEnd,
typename OtherReference
>
flatten_iterator operator=(flatten_iterator
<
OtherOuterIterator,
OtherInnerIterator,
OtherValue,
OtherAccessInnerBegin,
OtherAccessInnerEnd,
OtherReference
> const& other)
flatten_iterator & operator=(flatten_iterator
<
OtherOuterIterator,
OtherInnerIterator,
OtherValue,
OtherAccessInnerBegin,
OtherAccessInnerEnd,
OtherReference
> const& other)
{
static const bool are_conv
= boost::is_convertible
@ -142,7 +152,9 @@ public:
m_outer_it = other.m_outer_it;
m_outer_end = other.m_outer_end;
m_inner_it = other.m_inner_it;
// avoid assigning an iterator having singular value
if ( other.m_outer_it != other.m_outer_end )
m_inner_it = other.m_inner_it;
return *this;
}

View File

@ -289,6 +289,32 @@ public:
NOT_CONVERTIBLE,
(point_iterator<OtherGeometry>));
}
inline point_iterator& operator++() // prefix
{
base::operator++();
return *this;
}
inline point_iterator& operator--() // prefix
{
base::operator--();
return *this;
}
inline point_iterator operator++(int) // postfix
{
point_iterator copy(*this);
base::operator++();
return copy;
}
inline point_iterator operator--(int) // postfix
{
point_iterator copy(*this);
base::operator--();
return copy;
}
};

View File

@ -272,6 +272,16 @@ private:
inline segment_iterator(base const& base_it) : base(base_it) {}
public:
// The following typedef is needed for this iterator to be
// bidirectional.
// Normally we would not have to define this. However, due to the
// fact that the value type of the iterator is not a reference,
// the iterator_facade framework (used to define the base class of
// this iterator) degrades automatically the iterator's category
// to input iterator. With the following typedef we recover the
// correct iterator category.
typedef std::bidirectional_iterator_tag iterator_category;
inline segment_iterator() {}
template <typename OtherGeometry>
@ -291,6 +301,32 @@ public:
NOT_CONVERTIBLE,
(segment_iterator<OtherGeometry>));
}
inline segment_iterator& operator++() // prefix
{
base::operator++();
return *this;
}
inline segment_iterator& operator--() // prefix
{
base::operator--();
return *this;
}
inline segment_iterator operator++(int) // postfix
{
segment_iterator copy(*this);
base::operator++();
return copy;
}
inline segment_iterator operator--(int) // postfix
{
segment_iterator copy(*this);
base::operator--();
return copy;
}
};

View File

@ -9,6 +9,8 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
@ -62,10 +64,10 @@ public :
return negative() ? math::abs(result) : result;
}
//! Returns 1 (used internally)
//! Used internally, returns -1 for deflate, 1 for inflate
inline int factor() const
{
return m_left < 0 ? -1 : 1;
return negative() ? -1 : 1;
}
//! Returns true if both distances are negative
@ -79,6 +81,8 @@ public :
inline NumericType max_distance(JoinStrategy const& join_strategy,
EndStrategy const& end_strategy) const
{
boost::ignore_unused(join_strategy, end_strategy);
NumericType const left = geometry::math::abs(m_left);
NumericType const right = geometry::math::abs(m_right);
NumericType const dist = (std::max)(left, right);

View File

@ -56,13 +56,13 @@ public :
inline NumericType apply(Point const& , Point const& ,
buffer_side_selector ) const
{
return m_distance;
return negative() ? geometry::math::abs(m_distance) : m_distance;
}
//! Returns 1 (used internally)
//! Used internally, returns -1 for deflate, 1 for inflate
inline int factor() const
{
return 1;
return negative() ? -1 : 1;
}
//! Returns true if distance is negative

View File

@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -282,17 +287,17 @@ public:
template <typename OutputIterator>
inline void result(partitions const& state,
OutputIterator out, bool clockwise) const
OutputIterator out,
bool clockwise,
bool closed) const
{
if (clockwise)
{
output_range<iterate_forward>(state.m_upper_hull, out, false);
output_range<iterate_reverse>(state.m_lower_hull, out, true);
output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
}
else
{
output_range<iterate_forward>(state.m_lower_hull, out, false);
output_range<iterate_reverse>(state.m_upper_hull, out, true);
output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
}
}
@ -343,28 +348,28 @@ private:
}
template <iterate_direction Direction, typename OutputIterator>
static inline void output_range(container_type const& range,
OutputIterator out, bool skip_first)
template <typename OutputIterator>
static inline void output_ranges(container_type const& first, container_type const& second,
OutputIterator out, bool closed)
{
typedef typename reversible_view<container_type const, Direction>::type view_type;
view_type view(range);
bool first = true;
for (typename boost::range_iterator<view_type const>::type it = boost::begin(view);
it != boost::end(view); ++it)
std::copy(boost::begin(first), boost::end(first), out);
BOOST_ASSERT(closed ? !boost::empty(second) : boost::size(second) > 1);
std::copy(++boost::rbegin(second), // skip the first Point
closed ? boost::rend(second) : --boost::rend(second), // skip the last Point if open
out);
typedef typename boost::range_size<container_type>::type size_type;
size_type const count = boost::size(first) + boost::size(second) - 1;
// count describes a closed case but comparison with min size of closed
// gives the result compatible also with open
// here core_detail::closure::minimum_ring_size<closed> could be used
if ( count < 4 )
{
if (first && skip_first)
{
first = false;
}
else
{
*out = *it;
++out;
}
// there should be only one missing
*out++ = *boost::begin(first);
}
}
};
}} // namespace strategy::convex_hull

View File

@ -69,34 +69,30 @@ private :
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
PromotedType dx1 = get<0>(perp1) - get<0>(vertex);
PromotedType dy1 = get<1>(perp1) - get<1>(vertex);
PromotedType dx2 = get<0>(perp2) - get<0>(vertex);
PromotedType dy2 = get<1>(perp2) - get<1>(vertex);
PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
BOOST_ASSERT(buffer_distance != 0);
dx1 /= buffer_distance;
dy1 /= buffer_distance;
dx2 /= buffer_distance;
dy2 /= buffer_distance;
PromotedType angle_diff = acos(dx1 * dx2 + dy1 * dy2);
PromotedType two = 2.0;
PromotedType steps = m_points_per_circle;
int n = boost::numeric_cast<int>(steps * angle_diff
/ (two * geometry::math::pi<PromotedType>()));
if (n <= 1)
{
return;
}
PromotedType const two = 2.0;
PromotedType const two_pi = two * geometry::math::pi<PromotedType>();
PromotedType const angle1 = atan2(dy1, dx1);
PromotedType diff = angle_diff / PromotedType(n);
PromotedType a = angle1 - diff;
PromotedType angle2 = atan2(dy2, dx2);
while (angle2 > angle1)
{
angle2 -= two_pi;
}
// Divide the angle into an integer amount of steps to make it
// visually correct also for a low number of points / circle
int const n = static_cast<int>
(
m_points_per_circle * (angle1 - angle2) / two_pi
);
PromotedType const diff = (angle1 - angle2) / static_cast<PromotedType>(n);
PromotedType a = angle1 - diff;
for (int i = 0; i < n - 1; i++, a -= diff)
{
Point p;

View File

@ -9,8 +9,6 @@
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
@ -69,14 +67,19 @@ public :
// Generate a block along (left or right of) the segment
// Simulate a vector d (dx,dy)
coordinate_type dx = get<0>(input_p2) - get<0>(input_p1);
coordinate_type dy = get<1>(input_p2) - get<1>(input_p1);
coordinate_type const dx = get<0>(input_p2) - get<0>(input_p1);
coordinate_type const dy = get<1>(input_p2) - get<1>(input_p1);
// For normalization [0,1] (=dot product d.d, sqrt)
promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);
// Because coordinates are not equal, length should not be zero
BOOST_ASSERT((! geometry::math::equals(length, 0)));
if (geometry::math::equals(length, 0))
{
// Coordinates are simplified and therefore most often not equal.
// But if simplify is skipped, or for lines with two
// equal points, length is 0 and we cannot generate output.
return;
}
// Generate the normalized perpendicular p, to the left (ccw)
promoted_type const px = -dy / length;

View File

@ -1,107 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_COMPARABLE_TO_REGULAR_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_COMPARABLE_TO_REGULAR_HPP
#include <cmath>
#include <boost/geometry/strategies/distance_comparable_to_regular.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
<
typename ComparableStrategy,
typename Strategy,
typename Geometry1,
typename Geometry2
>
struct comparable_to_regular
<
ComparableStrategy, Strategy,
Geometry1, Geometry2,
cartesian_tag, cartesian_tag
>
{
typedef typename return_type
<
Strategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type calculation_type;
typedef typename return_type
<
ComparableStrategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type comparable_calculation_type;
static inline calculation_type apply(comparable_calculation_type const& cd)
{
return math::sqrt( boost::numeric_cast<calculation_type>(cd) );
}
};
template <typename ComparableStrategy, typename Geometry1, typename Geometry2>
struct comparable_to_regular
<
ComparableStrategy,
ComparableStrategy,
Geometry1,
Geometry2,
cartesian_tag,
cartesian_tag
>
{
typedef typename return_type
<
ComparableStrategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type comparable_calculation_type;
static inline comparable_calculation_type
apply(comparable_calculation_type const& cd)
{
return cd;
}
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_COMPARABLE_TO_REGULAR_HPP

View File

@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -56,7 +61,7 @@ class ConvexHullStrategy
str->apply(*sp, *st);
// 5) must implement a method result, with an output iterator
str->result(*st, std::back_inserter(*v), true);
str->result(*st, std::back_inserter(*v), true, true);
}
};

View File

@ -1,53 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_COMPARABLE_TO_REGULAR_HPP
#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_COMPARABLE_TO_REGULAR_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
<
typename ComparableStrategy,
typename Strategy,
typename Geometry1,
typename Geometry2,
typename CsTag1 = typename cs_tag<Geometry1>::type,
typename CsTag2 = typename cs_tag<Geometry2>::type
>
struct comparable_to_regular
: geometry::not_implemented<CsTag1, CsTag2>
{};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_COMPARABLE_TO_REGULAR_HPP

View File

@ -90,7 +90,7 @@ struct de9im
static inline char as_char(int v)
{
return v >= 0 && v < 10 ? ('0' + char(v)) : '-';
return v >= 0 && v < 10 ? static_cast<char>('0' + v) : '-';
}
#if defined(HAVE_MATRIX_AS_STRING)

View File

@ -19,6 +19,7 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/algorithms/detail/course.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
@ -117,10 +118,10 @@ public :
return_type d2 = m_strategy.apply(sp2, p);
return_type crs_AD = course(sp1, p);
return_type crs_AB = course(sp1, sp2);
return_type crs_AD = geometry::detail::course<return_type>(sp1, p);
return_type crs_AB = geometry::detail::course<return_type>(sp1, sp2);
return_type crs_BA = crs_AB - geometry::math::pi<return_type>();
return_type crs_BD = course(sp2, p);
return_type crs_BD = geometry::detail::course<return_type>(sp2, p);
return_type d_crs1 = crs_AD - crs_AB;
return_type d_crs2 = crs_BD - crs_BA;
@ -165,24 +166,6 @@ public :
private :
Strategy m_strategy;
/// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
template <typename Point1, typename Point2>
inline typename return_type<Point1, Point2>::type
course(Point1 const& p1, Point2 const& p2) const
{
typedef typename return_type<Point1, Point2>::type return_type;
// http://williams.best.vwh.net/avform.htm#Crs
return_type dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
return_type cos_p2lat = cos(get_as_radian<1>(p2));
// "An alternative formula, not requiring the pre-computation of d"
return atan2(sin(dlon) * cos_p2lat,
cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
- sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
}
};

View File

@ -0,0 +1,287 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
template
<
typename CalculationType = void,
typename Strategy = haversine<double, CalculationType>
>
class cross_track_point_box
{
public:
template <typename Point, typename Box>
struct return_type
: promote_floating_point
<
typename select_calculation_type
<
Point,
typename point_type<Box>::type,
CalculationType
>::type
>
{};
inline cross_track_point_box()
{}
explicit inline cross_track_point_box(typename Strategy::radius_type const& r)
: m_pp_strategy(r)
{}
inline cross_track_point_box(Strategy const& s)
: m_pp_strategy(s)
{}
template <typename Point, typename Box>
inline typename return_type<Point, Box>::type
apply(Point const& point, Box const& box) const
{
#if !defined(BOOST_MSVC)
BOOST_CONCEPT_ASSERT
(
(concept::PointDistanceStrategy
<
Strategy, Point,
typename point_type<Box>::type
>)
);
#endif
typedef typename return_type<Point, Box>::type return_type;
typedef typename point_type<Box>::type box_point_t;
// Create (counterclockwise) array of points, the fifth one closes it
// If every point is on the LEFT side (=1) or ON the border (=0)
// the distance should be equal to 0.
// TODO: This strategy as well as other cross-track strategies
// and therefore e.g. spherical within(Point, Box) may not work
// properly for a Box degenerated to a Segment or Point
boost::array<box_point_t, 5> bp;
geometry::detail::assign_box_corners_oriented<true>(box, bp);
bp[4] = bp[0];
for (int i = 1; i < 5; i++)
{
box_point_t const& p1 = bp[i - 1];
box_point_t const& p2 = bp[i];
return_type const crs_AD = geometry::detail::course<return_type>(p1, point);
return_type const crs_AB = geometry::detail::course<return_type>(p1, p2);
return_type const d_crs1 = crs_AD - crs_AB;
return_type const sin_d_crs1 = sin(d_crs1);
// this constant sin() is here to be consistent with the side strategy
return_type const sigXTD = asin(sin(0.001) * sin_d_crs1);
// If the point is on the right side of the edge
if ( sigXTD > 0 )
{
return_type const crs_BA = crs_AB - geometry::math::pi<return_type>();
return_type const crs_BD = geometry::detail::course<return_type>(p2, point);
return_type const d_crs2 = crs_BD - crs_BA;
return_type const projection1 = cos( d_crs1 );
return_type const projection2 = cos( d_crs2 );
if(projection1 > 0.0 && projection2 > 0.0)
{
return_type const d1 = m_pp_strategy.apply(p1, point);
return_type const
XTD = radius()
* geometry::math::abs(
asin( sin( d1 / radius() ) * sin_d_crs1 )
);
return return_type(XTD);
}
else
{
// OPTIMIZATION
// Return d1 if projection1 <= 0 and d2 if projection2 <= 0
// if both == 0 then return d1 or d2
// both shouldn't be < 0
return_type const d1 = m_pp_strategy.apply(p1, point);
return_type const d2 = m_pp_strategy.apply(p2, point);
return return_type((std::min)( d1 , d2 ));
}
}
}
// Return 0 if the point isn't on the right side of any segment
return return_type(0);
}
inline typename Strategy::radius_type radius() const
{ return m_pp_strategy.radius(); }
private :
Strategy m_pp_strategy;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<cross_track_point_box<CalculationType, Strategy> >
{
typedef strategy_tag_distance_point_box type;
};
template <typename CalculationType, typename Strategy, typename P, typename Box>
struct return_type<cross_track_point_box<CalculationType, Strategy>, P, Box>
: cross_track_point_box<CalculationType, Strategy>::template return_type<P, Box>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<cross_track_point_box<CalculationType, Strategy> >
{
// There is no shortcut, so the strategy itself is its comparable type
typedef cross_track_point_box<CalculationType, Strategy> type;
};
template
<
typename CalculationType,
typename Strategy
>
struct get_comparable<cross_track_point_box<CalculationType, Strategy> >
{
typedef typename comparable_type
<
cross_track_point_box<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(
cross_track_point_box<CalculationType, Strategy> const& strategy)
{
return cross_track_point_box<CalculationType, Strategy>(strategy.radius());
}
};
template
<
typename CalculationType,
typename Strategy,
typename P, typename Box
>
struct result_from_distance
<
cross_track_point_box<CalculationType, Strategy>,
P,
Box
>
{
private :
typedef typename cross_track_point_box
<
CalculationType, Strategy
>::template return_type<P, Box> return_type;
public :
template <typename T>
static inline return_type apply(
cross_track_point_box<CalculationType, Strategy> const& ,
T const& distance)
{
return distance;
}
};
template <typename Point, typename Box, typename Strategy>
struct default_strategy
<
point_tag, box_tag, Point, Box,
spherical_equatorial_tag, spherical_equatorial_tag,
Strategy
>
{
typedef cross_track_point_box
<
void,
typename boost::mpl::if_
<
boost::is_void<Strategy>,
typename default_strategy
<
point_tag, point_tag,
Point, typename point_type<Box>::type,
spherical_equatorial_tag, spherical_equatorial_tag
>::type,
Strategy
>::type
> type;
};
template <typename Box, typename Point, typename Strategy>
struct default_strategy
<
box_tag, point_tag, Box, Point,
spherical_equatorial_tag, spherical_equatorial_tag,
Strategy
>
{
typedef typename default_strategy
<
point_tag, box_tag, Point, Box,
spherical_equatorial_tag, spherical_equatorial_tag,
Strategy
>::type type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP

View File

@ -17,6 +17,8 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/algorithms/detail/course.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
@ -31,29 +33,6 @@ namespace boost { namespace geometry
namespace strategy { namespace side
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
template <typename Point>
static inline double course(Point const& p1, Point const& p2)
{
// http://williams.best.vwh.net/avform.htm#Crs
double dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
double cos_p2lat = cos(get_as_radian<1>(p2));
// "An alternative formula, not requiring the pre-computation of d"
return atan2(sin(dlon) * cos_p2lat,
cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
- sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
}
}
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Check at which side of a Great Circle segment a point lies
left of segment (> 0), right of segment (< 0), on segment (0)
@ -86,8 +65,8 @@ public :
boost::ignore_unused<coordinate_type>();
double d1 = 0.001; // m_strategy.apply(sp1, p);
double crs_AD = detail::course(p1, p);
double crs_AB = detail::course(p1, p2);
double crs_AD = geometry::detail::course<double>(p1, p);
double crs_AB = geometry::detail::course<double>(p1, p2);
double XTD = asin(sin(d1) * sin(crs_AD - crs_AB));
return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1;

View File

@ -55,11 +55,11 @@
#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/cartesian/distance_comparable_to_regular.hpp>
#include <boost/geometry/strategies/spherical/area_huiller.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp>
#include <boost/geometry/strategies/spherical/compare_circular.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>

View File

@ -29,4 +29,3 @@ build-project policies ;
build-project io ;
build-project util ;
build-project views ;
build-project multi ;

View File

@ -8,6 +8,7 @@
# Modifications copyright (c) 2014, Oracle and/or its affiliates.
#
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -24,66 +25,45 @@ test-suite boost-geometry-algorithms
[ run convex_hull.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run correct.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run convert.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run covered_by.cpp ]
[ run crosses.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run difference.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <toolset>msvc:<cxxflags>/bigobj ]
[ run difference_linear_linear.cpp ]
[ run difference_pl_pl.cpp ]
[ run disjoint.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run disjoint_coverage.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run distance.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run distance_areal_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run distance_linear_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run distance_linear_linear.cpp ]
[ run distance_pointlike_areal.cpp ]
[ run distance_pointlike_linear.cpp ]
[ run distance_pointlike_pointlike.cpp ]
[ run envelope.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run equals.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run expand.cpp ]
[ run for_each.cpp ]
[ run intersection.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <toolset>msvc:<cxxflags>/bigobj ]
[ run intersection_linear_linear.cpp ]
[ run intersection_pl_pl.cpp ]
[ run intersects.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run is_simple.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run is_valid.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run length.cpp ]
[ run make.cpp ]
[ run multi_area.cpp ]
[ run multi_centroid.cpp ]
[ run multi_convert.cpp ]
[ run multi_convex_hull.cpp ]
[ run multi_correct.cpp ]
[ run multi_envelope.cpp ]
[ run multi_for_each.cpp ]
[ run multi_length.cpp ]
[ run multi_num_geometries.cpp ]
[ run multi_num_interior_rings.cpp ]
[ run multi_num_points.cpp ]
[ run multi_perimeter.cpp ]
[ run multi_reverse.cpp ]
[ run multi_simplify.cpp ]
[ run multi_transform.cpp ]
[ run multi_unique.cpp ]
[ run num_geometries.cpp ]
[ run num_interior_rings.cpp ]
[ run num_points.cpp ]
[ run num_segments.cpp ]
[ run overlaps.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run perimeter.cpp ]
[ run point_on_surface.cpp ]
[ run relate_areal_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run relate_linear_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run relate_linear_linear.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run relate_pointlike_xxx.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run remove_spikes.cpp ]
[ run reverse.cpp ]
[ run simplify.cpp ]
[ run sym_difference_linear_linear.cpp ]
[ run touches.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run transform.cpp ]
[ run union.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <toolset>msvc:<cxxflags>/bigobj ]
[ run union_linear_linear.cpp ]
[ run union_pl_pl.cpp ]
[ run unique.cpp ]
[ run within.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run within_areal_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run within_linear_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run within_linear_linear.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run within_pointlike_xxx.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
;
build-project overlay
;
build-project buffer
;
build-project detail
;
build-project buffer ;
build-project detail ;
build-project distance ;
build-project overlay ;
build-project relational_operations ;
build-project set_operations ;

View File

@ -27,6 +27,12 @@ static std::string const overlapping = "LINESTRING(0 0,4 5,7 4,10 6, 10 2,2 2)";
static std::string const curve = "LINESTRING(2 7,3 5,5 4,7 5,8 7)";
static std::string const tripod = "LINESTRING(5 0,5 5,1 8,5 5,9 8)"; // with spike
static std::string const degenerate0 = "LINESTRING()";
static std::string const degenerate1 = "LINESTRING(5 5)";
static std::string const degenerate2 = "LINESTRING(5 5,5 5)";
static std::string const degenerate3 = "LINESTRING(5 5,5 5,5 5)";
static std::string const degenerate4 = "LINESTRING(5 5,5 5,4 4,5 5,5 5)";
static std::string const for_collinear = "LINESTRING(2 0,0 0,0 4,6 4,6 0,4 0)";
static std::string const for_collinear2 = "LINESTRING(2 1,2 0,0 0,0 4,6 4,6 0,4 0,4 1)";
@ -42,11 +48,11 @@ static std::string const aimes171 = "LINESTRING(-2.393161 52.265087,-2.393002 52
static std::string const aimes181 = "LINESTRING(-2.320686 52.43505,-2.320678 52.435016,-2.320697 52.434978,-2.3207 52.434977,-2.320741 52.434964,-2.320807 52.434964,-2.320847 52.434986,-2.320903 52.435022)";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::linestring<P> linestring;
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
bg::strategy::buffer::join_miter join_miter;
bg::strategy::buffer::join_round join_round(100);
@ -133,6 +139,13 @@ void test_all()
test_one<linestring, polygon>("field_sprayer1", field_sprayer1, join_round, end_round, 718.761877, 16.5, 6.5);
test_one<linestring, polygon>("field_sprayer1", field_sprayer1, join_miter, end_round, 718.939628, 16.5, 6.5);
test_one<linestring, polygon>("degenerate0", degenerate0, join_round, end_round, 0.0, 3.0);
test_one<linestring, polygon>("degenerate1", degenerate1, join_round, end_round, 28.25, 3.0);
test_one<linestring, polygon>("degenerate2", degenerate2, join_round, end_round, 28.2503, 3.0);
test_one<linestring, polygon>("degenerate3", degenerate3, join_round, end_round, 28.2503, 3.0);
test_one<linestring, polygon>("degenerate4", degenerate4, join_round, end_round, 36.7410, 3.0);
test_one<linestring, polygon>("degenerate4", degenerate4, join_round, end_flat, 8.4853, 3.0);
double tolerance = 1.0e-10;
test_one<linestring, polygon>("aimes120", aimes120, join_miter, end_flat, 1.62669948622351512e-08, 0.000018, 0.000018, false, tolerance);
@ -165,7 +178,8 @@ void test_all()
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
//test_all<bg::model::point<tt, 2, bg::cs::cartesian> >();
return 0;
}

View File

@ -15,13 +15,19 @@ static std::string const simplex = "MULTILINESTRING((0 0,4 5),(5 4,10 0))";
static std::string const two_bends = "MULTILINESTRING((0 0,4 5,7 4,10 6),(1 5,5 9,8 6))";
static std::string const turn_inside = "MULTILINESTRING((0 0,4 5,7 4,10 6),(1 5,5 9,8 6),(0 4,-2 6))";
static std::string const degenerate0 = "MULTILINESTRING()";
static std::string const degenerate1 = "MULTILINESTRING((5 5))";
static std::string const degenerate2 = "MULTILINESTRING((5 5),(9 9))";
static std::string const degenerate3 = "MULTILINESTRING((5 5),(9 9),(4 10))";
static std::string const degenerate4 = "MULTILINESTRING((5 5,5 5),(9 9,9 9,10 10,9 9,9 9,9 9),(4 10,4 10,3 11,4 12,3 11,4 10,4 10))";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::linestring<P> linestring;
typedef bg::model::multi_linestring<linestring> multi_linestring_type;
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
bg::strategy::buffer::join_miter join_miter;
bg::strategy::buffer::join_round join_round(100);
@ -49,13 +55,20 @@ void test_all()
test_one<multi_linestring_type, polygon>("two_bends", two_bends, join_round_by_divide, end_flat, 64.6217, 1.5, 1.5);
test_one<multi_linestring_type, polygon>("two_bends", two_bends, join_miter, end_flat, 65.1834, 1.5, 1.5);
test_one<multi_linestring_type, polygon>("two_bends", two_bends, join_miter, end_round, 75.2917, 1.5, 1.5);
test_one<multi_linestring_type, polygon>("degenerate0", degenerate0, join_round, end_round, 0.0, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate1", degenerate1, join_round, end_round, 28.2503, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate2", degenerate2, join_round, end_round, 56.0457, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate3", degenerate3, join_round, end_round, 80.4531, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate4", degenerate4, join_round, end_round, 104.3142, 3.0, 3.0);
}
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
return 0;
}

View File

@ -21,12 +21,10 @@ static std::string const multipoint_a = "MULTIPOINT((39 44),(38 37),(41 29),(15
static std::string const multipoint_b = "MULTIPOINT((5 56),(98 67),(20 7),(58 60),(10 4),(75 68),(61 68),(75 62),(92 26),(74 6),(67 54),(20 43),(63 30),(45 7))";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
//std::cout << typeid(bg::coordinate_type<P>::type).name() << std::endl;
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
typedef bg::model::multi_point<P> multi_point_type;
bg::strategy::buffer::join_miter join_miter;
@ -185,9 +183,8 @@ void test_growth(int n, int distance_count)
int test_main(int, char* [])
{
//std::cout << std::setprecision(6);
//test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
#ifdef BOOST_GEOMETRY_BUFFER_TEST_GROWTH

View File

@ -24,6 +24,13 @@ static std::string const wrapped
static std::string const triangles
= "MULTIPOLYGON(((0 4,3 0,-2.5 -1,0 4)),((3 8,5.5 13,8 8,3 8)),((11 4,13.5 -1,8 0,11 4)))";
static std::string const degenerate0
= "MULTIPOLYGON()";
static std::string const degenerate1
= "MULTIPOLYGON(((5 5,5 5,5 5,5 5)),((6 6,6 6,6 6,6 6)))";
static std::string const degenerate2
= "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0),(5 5,5 5,5 5,5 5)),((11 5,11 5,11 5,11 5)))";
// From robustness tests (rt)
// Case with duplicate points (due to chained boxes) (round)
@ -260,10 +267,10 @@ static std::string const rt_u12
static std::string const rt_u13
= "MULTIPOLYGON(((6 4,6 5,7 5,6 4)),((3 2,3 3,4 3,3 2)),((7 8,7 9,8 9,8 8,7 8)),((4 9,4 10,5 10,4 9)),((7 7,7 8,8 7,7 7)),((2 6,2 7,3 7,2 6)),((0 1,1 2,1 1,0 1)),((3 1,4 2,4 1,3 1)),((2 5,2 6,3 6,2 5)),((3 5,4 4,3 4,2 4,3 5)),((4 1,5 2,5 1,4 1)),((2 0,2 1,3 1,2 0)),((5 7,5 8,6 7,5 7)),((0 2,0 3,1 3,0 2)),((9 8,9 9,10 9,10 8,9 8)),((7 5,7 6,8 5,7 5)),((5 6,5 7,6 6,5 6)),((0 6,0 7,1 7,1 6,0 6)),((5 0,5 1,6 1,5 0)),((8 7,8 8,9 8,8 7)),((4.5 4.5,5 4,4 4,4 5,5 5,4.5 4.5)),((6 2,5 2,5 3,6 3,7 3,8 2,7 2,6 2)),((8 6,8 7,9 7,9 6,9 5,8 5,8 6)),((8 1,9 0,8 0,7 0,8 1)))";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::polygon<P> polygon_type;
typedef bg::model::polygon<P, Clockwise> polygon_type;
typedef bg::model::multi_polygon<polygon_type> multi_polygon_type;
bg::strategy::buffer::join_miter join_miter;
@ -285,6 +292,11 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("multi_simplex_50", simplex, join_round, end_flat, 174.46, 5.0);
test_one<multi_polygon_type, polygon_type>("multi_simplex_50", simplex, join_miter, end_flat, 298.797, 5.0);
test_one<multi_polygon_type, polygon_type>("multi_simplex_01", simplex, join_round, end_flat, 9.7514, -0.1);
test_one<multi_polygon_type, polygon_type>("multi_simplex_05", simplex, join_round, end_flat, 3.2019, -0.5);
test_one<multi_polygon_type, polygon_type>("multi_simplex_10", simplex, join_round, end_flat, 0.2012, -1.0);
test_one<multi_polygon_type, polygon_type>("multi_simplex_12", simplex, join_round, end_flat, 0.0, -1.2);
test_one<multi_polygon_type, polygon_type>("zonethru_05", zonethru, join_round, end_flat, 67.4627, 0.5);
test_one<multi_polygon_type, polygon_type>("zonethru_05", zonethru, join_miter, end_flat, 68.0000, 0.5);
test_one<multi_polygon_type, polygon_type>("zonethru_10", zonethru, join_round, end_flat, 93.8508, 1.0);
@ -298,6 +310,10 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("wrapped_15", wrapped, join_round, end_flat, 167.066, 1.5);
test_one<multi_polygon_type, polygon_type>("wrapped_15", wrapped, join_miter, end_flat, 169.000, 1.5);
test_one<multi_polygon_type, polygon_type>("degenerate0", degenerate0, join_round, end_flat, 0.0, 1.0);
test_one<multi_polygon_type, polygon_type>("degenerate1", degenerate1, join_round, end_flat, 5.708, 1.0);
test_one<multi_polygon_type, polygon_type>("degenerate2", degenerate2, join_round, end_flat, 133.0166, 0.75);
test_one<multi_polygon_type, polygon_type>("rt_a", rt_a, join_round, end_flat, 34.5381, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_a", rt_a, join_miter, end_flat, 36, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_b", rt_b, join_round, end_flat, 31.4186, 1.0);
@ -364,11 +380,13 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("rt_q1", rt_q1, join_miter, end_flat, 27, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_q2", rt_q2, join_miter, end_flat, 26.4853, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_q2", rt_q2, join_miter, end_flat, 0.9697, -0.25);
test_one<multi_polygon_type, polygon_type>("rt_r", rt_r, join_miter, end_flat, 21.0761, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_s1", rt_s1, join_miter, end_flat, 20.4853, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_s2", rt_s2, join_miter, end_flat, 24.6495, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_t", rt_t, join_miter, end_flat, 15.6569, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_t", rt_t, join_miter, end_flat, 0.1679, -0.25);
test_one<multi_polygon_type, polygon_type>("rt_u1", rt_u1, join_round, end_flat, 33.2032, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u2", rt_u2, join_round, end_flat, 138.8001, 1.0);
@ -384,8 +402,13 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("rt_u8", rt_u8, join_miter, end_flat, 70.9142, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u9", rt_u9, join_miter, end_flat, 59.3063, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u10", rt_u10, join_miter, end_flat, 144.0858, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u10_50", rt_u10, join_miter, end_flat, 0.2145, -0.50);
test_one<multi_polygon_type, polygon_type>("rt_u10_25", rt_u10, join_miter, end_flat, 9.6682, -0.25);
test_one<multi_polygon_type, polygon_type>("rt_u11", rt_u11, join_miter, end_flat, 131.3995, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u11_50", rt_u11, join_miter, end_flat, 0.04289, -0.50);
test_one<multi_polygon_type, polygon_type>("rt_u11_25", rt_u11, join_miter, end_flat, 10.1449, -0.25);
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
test_one<multi_polygon_type, polygon_type>("rt_u12", rt_u12, join_miter, end_flat, 999, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_u13", rt_u13, join_miter, end_flat, 115.4853, 1.0);
@ -394,7 +417,8 @@ void test_all()
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
//test_all<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >();
return 0;

View File

@ -7,29 +7,15 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//#define BOOST_GEOMETRY_DEBUG_WITH_MAPPER
//#define BOOST_GEOMETRY_DEBUG_ASSEMBLE
//#define BOOST_GEOMETRY_DEBUG_IDENTIFIER
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/buffer.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <test_buffer.hpp>
static std::string const simplex = "POINT(5 5)";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
bg::strategy::buffer::join_miter join_miter;
bg::strategy::buffer::end_flat end_flat;
@ -44,8 +30,7 @@ void test_all()
int test_main(int, char* [])
{
//std::cout << std::setprecision(6);
//test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
return 0;
}

View File

@ -14,6 +14,8 @@ static std::string const simplex
= "POLYGON ((0 0,1 5,6 1,0 0))";
static std::string const concave_simplex
= "POLYGON ((0 0,3 5,3 3,5 3,0 0))";
static std::string const square_simplex
= "POLYGON ((0 0,0 1,1 1,1 0,0 0))";
static std::string const spike_simplex
= "POLYGON ((0 0,1 5,3 3,5 5,3 3,5 1,0 0))";
static std::string const chained_box
@ -63,6 +65,21 @@ static std::string const bowl
static std::string const triangle
= "POLYGON((4 5,5 4,4 4,3 4,3 5,3 6,4 5))";
// Triangle which caused acos in join_round to fail with larger side strategy
static std::string const sharp_triangle
= "POLYGON((2 0,3 8,4 0,2 0))";
static std::string const degenerate0
= "POLYGON(())";
static std::string const degenerate1
= "POLYGON((5 5))";
static std::string const degenerate2
= "POLYGON((5 5,5 5,5 5,5 5))";
static std::string const degenerate3
= "POLYGON((0 0,0 10,10 10,10 0,0 0),(5 5,5 5,5 5,5 5))";
// Real-life examples
static std::string const county1
= "POLYGON((-111.700 41.200 ,-111.681388 41.181739 ,-111.682453 41.181506 ,-111.684052 41.180804 ,-111.685295 41.180538 ,-111.686318 41.180776 ,-111.687517 41.181416 ,-111.688982 41.181520 ,-111.690670 41.181523 ,-111.692135 41.181460 ,-111.693646 41.182034 ,-111.695156 41.182204 ,-111.696489 41.182274 ,-111.697775 41.182075 ,-111.698974 41.181539 ,-111.700485 41.182348 ,-111.701374 41.182955 ,-111.700 41.200))";
@ -98,11 +115,64 @@ static std::string const ticket_10398_4
static std::string const ticket_10412
= "POLYGON((897747.8 6270564.3,897764.3 6270569.7,897776.5 6270529.5,897768.1 6270527.1,897767.6 6270529.4,897756.3 6270525.8,897745.8 6270522.3,897752 6270502.9,897749.7 6270502,897750.7 6270499.1,897751.8 6270498.6,897752.3 6270499.3,897754.6 6270497.9,897755.8 6270500.2,897766.8 6270494.1,897765.6 6270491.5,897768.3 6270490.5,897770.9 6270491.5,897770.2 6270494.6,897780.1 6270497.5,897781 6270494.6,897786.8 6270496.6,897790.8 6270482.5,897785.3 6270480.7,897785.9 6270478.2,897768.9 6270473.2,897768.1 6270475.8,897766.1 6270475.2,897758.7 6270479.2,897753.2 6270481.8,897751.9 6270479,897746.5 6270481.9,897748 6270484.6,897745.2 6270486.1,897743.9 6270483.3,897741.4 6270484.7,897742.6 6270487.3,897739.4 6270488.9,897738.3 6270486.3,897735.6 6270487.8,897733.1 6270496.8,897731.2 6270502.7,897732.4 6270503.2,897731.5 6270506.1,897730.3 6270505.7,897725.8 6270520.2,897726.8 6270520.7,897726 6270523,897728 6270523.7,897726.3 6270529.6,897742.8 6270534.5,897741.2 6270539.9,897751.4 6270543.4,897750.7 6270546.4,897753.2 6270547.2,897747.8 6270564.3))";
// CCW Polygons not working in 1.56
static std::string const mysql_report_2014_10_24
= "POLYGON((0 0, 0 8, 8 8, 8 10, -10 10, -10 0, 0 0))";
static std::string const mysql_report_2014_10_28_1
= "POLYGON((0 0,10 10,0 8,0 0))";
static std::string const mysql_report_2014_10_28_2
= "POLYGON((1 1,10 10,0 8,1 1))";
static std::string const mysql_report_2014_10_28_3
= "POLYGON((2 2,8 2,8 8,2 8,2 2))";
template <typename P>
class buffer_custom_side_strategy
{
public :
template
<
typename Point,
typename OutputRange,
typename DistanceStrategy
>
static inline void apply(
Point const& input_p1, Point const& input_p2,
bg::strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance,
OutputRange& output_range)
{
// Generate a block along (left or right of) the segment
double const dx = bg::get<0>(input_p2) - bg::get<0>(input_p1);
double const dy = bg::get<1>(input_p2) - bg::get<1>(input_p1);
// For normalization [0,1] (=dot product d.d, sqrt)
double const length = bg::math::sqrt(dx * dx + dy * dy);
if (bg::math::equals(length, 0))
{
return;
}
// Generate the perpendicular p, to the left (ccw), and use an adapted distance
double const d = 1.1 * distance.apply(input_p1, input_p2, side);
double const px = d * -dy / length;
double const py = d * dx / length;
output_range.resize(2);
bg::set<0>(output_range.front(), bg::get<0>(input_p1) + px);
bg::set<1>(output_range.front(), bg::get<1>(input_p1) + py);
bg::set<0>(output_range.back(), bg::get<0>(input_p2) + px);
bg::set<1>(output_range.back(), bg::get<1>(input_p2) + py);
}
};
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::polygon<P> polygon_type;
typedef bg::model::polygon<P, Clockwise, true> polygon_type;
bg::strategy::buffer::join_miter join_miter(10.0);
bg::strategy::buffer::join_round join_round(100);
@ -112,9 +182,23 @@ void test_all()
test_one<polygon_type, polygon_type>("simplex", simplex, join_round, end_flat, 47.9408, 1.5);
test_one<polygon_type, polygon_type>("simplex", simplex, join_miter, end_flat, 52.8733, 1.5);
test_one<polygon_type, polygon_type>("simplex", simplex, join_round, end_flat, 7.04043, -0.5);
test_one<polygon_type, polygon_type>("simplex", simplex, join_miter, end_flat, 7.04043, -0.5);
test_one<polygon_type, polygon_type>("square_simplex", square_simplex, join_round, end_flat, 14.0639, 1.5);
test_one<polygon_type, polygon_type>("square_simplex", square_simplex, join_miter, end_flat, 16.0000, 1.5);
test_one<polygon_type, polygon_type>("square_simplex01", square_simplex, join_miter, end_flat, 0.6400, -0.1);
test_one<polygon_type, polygon_type>("square_simplex04", square_simplex, join_miter, end_flat, 0.0400, -0.4);
test_one<polygon_type, polygon_type>("square_simplex05", square_simplex, join_miter, end_flat, 0.0, -0.5);
test_one<polygon_type, polygon_type>("square_simplex06", square_simplex, join_miter, end_flat, 0.0, -0.6);
test_one<polygon_type, polygon_type>("concave_simplex", concave_simplex, join_round, end_flat, 14.5616, 0.5);
test_one<polygon_type, polygon_type>("concave_simplex", concave_simplex, join_miter, end_flat, 16.3861, 0.5);
test_one<polygon_type, polygon_type>("concave_simplex", concave_simplex, join_round, end_flat, 0.777987, -0.5);
test_one<polygon_type, polygon_type>("concave_simplex", concave_simplex, join_miter, end_flat, 0.724208, -0.5);
test_one<polygon_type, polygon_type>("spike_simplex15", spike_simplex, join_round, end_round, 50.3633, 1.5);
test_one<polygon_type, polygon_type>("spike_simplex15", spike_simplex, join_miter, end_flat, 51.5509, 1.5);
@ -154,13 +238,13 @@ void test_all()
test_one<polygon_type, polygon_type>("indentation12", indentation, join_miter, end_flat, 46.3541, 1.2);
test_one<polygon_type, polygon_type>("indentation12", indentation, join_round, end_flat, 45.0537, 1.2);
// TODO: fix, the buffered pieces are currently counterclockwise, that should be reversed
//test_one<polygon_type, polygon_type>("indentation4_neg", indentation, join_miter, end_flat, 6.99098413022335, -0.4);
//test_one<polygon_type, polygon_type>("indentation4_neg", indentation, join_round, end_flat, 7.25523322189147, -0.4);
//test_one<polygon_type, polygon_type>("indentation8_neg", indentation, join_miter, end_flat, 1.36941992048731, -0.8);
//test_one<polygon_type, polygon_type>("indentation8_neg", indentation, join_round, end_flat, 1.37375487490664, -0.8);
//test_one<polygon_type, polygon_type>("indentation12_neg", indentation, join_miter, end_flat, 0, -1.2);
//test_one<polygon_type, polygon_type>("indentation12_neg", indentation, join_round, end_flat, 0, -1.2);
// Indentation - deflated
test_one<polygon_type, polygon_type>("indentation4", indentation, join_miter, end_flat, 6.99098413022335, -0.4);
test_one<polygon_type, polygon_type>("indentation4", indentation, join_round, end_flat, 7.25523322189147, -0.4);
test_one<polygon_type, polygon_type>("indentation8", indentation, join_miter, end_flat, 1.36941992048731, -0.8);
test_one<polygon_type, polygon_type>("indentation8", indentation, join_round, end_flat, 1.37375487490664, -0.8);
test_one<polygon_type, polygon_type>("indentation12", indentation, join_miter, end_flat, 0, -1.2);
test_one<polygon_type, polygon_type>("indentation12", indentation, join_round, end_flat, 0, -1.2);
test_one<polygon_type, polygon_type>("donut_simplex6", donut_simplex, join_miter, end_flat, 53.648, 0.6);
test_one<polygon_type, polygon_type>("donut_simplex6", donut_simplex, join_round, end_flat, 52.820, 0.6);
@ -175,11 +259,20 @@ void test_all()
test_one<polygon_type, polygon_type>("donut_simplex16", donut_simplex, join_miter, end_flat, 93.777, 1.6);
test_one<polygon_type, polygon_type>("donut_simplex16", donut_simplex, join_round, end_flat, 87.933, 1.6);
test_one<polygon_type, polygon_type>("donut_simplex3", donut_simplex, join_miter, end_flat, 19.7636, -0.3);
test_one<polygon_type, polygon_type>("donut_simplex3", donut_simplex, join_round, end_flat, 19.8861, -0.3);
test_one<polygon_type, polygon_type>("donut_simplex6", donut_simplex, join_miter, end_flat, 12.8920, -0.6);
test_one<polygon_type, polygon_type>("donut_simplex6", donut_simplex, join_round, end_flat, 12.9157, -0.6);
test_one<polygon_type, polygon_type>("donut_diamond1", donut_diamond, join_miter, end_flat, 280.0, 1.0);
test_one<polygon_type, polygon_type>("donut_diamond4", donut_diamond, join_miter, end_flat, 529.0, 4.0);
test_one<polygon_type, polygon_type>("donut_diamond5", donut_diamond, join_miter, end_flat, 625.0, 5.0);
test_one<polygon_type, polygon_type>("donut_diamond6", donut_diamond, join_miter, end_flat, 729.0, 6.0);
test_one<polygon_type, polygon_type>("donut_diamond1", donut_diamond, join_miter, end_flat, 122.0417, -1.0);
test_one<polygon_type, polygon_type>("donut_diamond2", donut_diamond, join_miter, end_flat, 56.3750, -2.0);
test_one<polygon_type, polygon_type>("donut_diamond3", donut_diamond, join_miter, end_flat, 17.7084, -3.0);
test_one<polygon_type, polygon_type>("arrow4", arrow, join_miter, end_flat, 28.265, 0.4);
test_one<polygon_type, polygon_type>("arrow4", arrow, join_round, end_flat, 27.039, 0.4);
test_one<polygon_type, polygon_type>("arrow5", arrow, join_miter, end_flat, 31.500, 0.5);
@ -210,6 +303,11 @@ void test_all()
test_one<polygon_type, polygon_type>("fork_c1", fork_c, join_miter, end_flat, 152, 1);
test_one<polygon_type, polygon_type>("triangle", triangle, join_miter, end_flat, 14.6569, 1.0);
test_one<polygon_type, polygon_type>("degenerate0", degenerate0, join_round, end_round, 0.0, 1.0);
test_one<polygon_type, polygon_type>("degenerate1", degenerate1, join_round, end_round, 3.1389, 1.0);
test_one<polygon_type, polygon_type>("degenerate2", degenerate2, join_round, end_round, 3.1389, 1.0);
test_one<polygon_type, polygon_type>("degenerate3", degenerate3, join_round, end_round, 143.1395, 1.0);
test_one<polygon_type, polygon_type>("gammagate2", gammagate, join_miter, end_flat, 130, 2);
test_one<polygon_type, polygon_type>("flower1", flower, join_miter, end_flat, 67.614, 0.1);
@ -234,6 +332,9 @@ void test_all()
test_one<polygon_type, polygon_type>("flower55", flower, join_round, end_flat, 96.580, 0.55);
test_one<polygon_type, polygon_type>("flower60", flower, join_round, end_flat, 99.408, 0.60);
// Flower - deflated
test_one<polygon_type, polygon_type>("flower60", flower, join_round, end_flat, 19.3210, -0.60);
// Saw
{
// SQL Server:
@ -288,6 +389,8 @@ void test_all()
}
test_one<polygon_type, polygon_type>("county1", county1, join_round, end_flat, 0.00114092, 0.01);
test_one<polygon_type, polygon_type>("county1", county1, join_miter, end_flat, 0.00132859, 0.01);
test_one<polygon_type, polygon_type>("county1", county1, join_round, end_flat, 0.00114092, -0.01);
test_one<polygon_type, polygon_type>("county1", county1, join_miter, end_flat, 0.00132859, -0.01);
test_one<polygon_type, polygon_type>("parcel1_10", parcel1, join_round, end_flat, 7571.39121246337891, 10.0);
test_one<polygon_type, polygon_type>("parcel1_10", parcel1, join_miter, end_flat, 8207.45314788818359, 10.0);
@ -310,23 +413,20 @@ void test_all()
test_one<polygon_type, polygon_type>("parcel3_30", parcel3, join_round, end_flat, 45261.4196014404297, 30.0);
test_one<polygon_type, polygon_type>("parcel3_30", parcel3, join_miter, end_flat, 45567.3875694274902, 30.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 155.6188, 5.0);
test_one<polygon_type, polygon_type>("parcel3_bend_5", parcel3_bend, join_round, end_flat, 155.6188, 5.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 458.4187, 10.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 917.9747, 15.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 1534.4795, 20.0);
// These cases differ a bit based on point order (TODO: find out / describe why)
test_one<polygon_type, polygon_type>("parcel3_bend_15", parcel3_bend, join_round, end_flat, Clockwise ? 917.9747 : 917.996, 15.0);
test_one<polygon_type, polygon_type>("parcel3_bend_20", parcel3_bend, join_round, end_flat, Clockwise ? 1534.4795 : 1534.508, 20.0);
// Negative buffers making polygons smaller
test_one<polygon_type, polygon_type>("simplex", simplex, join_round, end_flat, 7.04043, -0.5);
test_one<polygon_type, polygon_type>("simplex", simplex, join_miter, end_flat, 7.04043, -0.5);
test_one<polygon_type, polygon_type>("concave_simplex", concave_simplex, join_round, end_flat, 0.777987, -0.5);
test_one<polygon_type, polygon_type>("concave_simplex", concave_simplex, join_miter, end_flat, 0.724208, -0.5);
test_one<polygon_type, polygon_type>("donut_simplex3", donut_simplex, join_miter, end_flat, 19.7636, -0.3);
test_one<polygon_type, polygon_type>("donut_simplex3", donut_simplex, join_round, end_flat, 19.8861, -0.3);
test_one<polygon_type, polygon_type>("donut_simplex6", donut_simplex, join_miter, end_flat, 12.8920, -0.6);
test_one<polygon_type, polygon_type>("donut_simplex6", donut_simplex, join_round, end_flat, 12.9157, -0.6);
// Parcel - deflated
test_one<polygon_type, polygon_type>("parcel1_10", parcel1, join_round, end_flat, 1571.9024, -10.0);
test_one<polygon_type, polygon_type>("parcel1_10", parcel1, join_miter, end_flat, 1473.7325, -10.0);
test_one<polygon_type, polygon_type>("parcel1_20", parcel1, join_round, end_flat, 209.3579, -20.0);
test_one<polygon_type, polygon_type>("parcel1_20", parcel1, join_miter, end_flat, 188.4224, -20.0);
// Tickets
test_one<polygon_type, polygon_type>("ticket_10398_1_5", ticket_10398_1, join_miter, end_flat, 494.7192, 0.5, -999, false);
test_one<polygon_type, polygon_type>("ticket_10398_1_25", ticket_10398_1, join_miter, end_flat, 697.7798, 2.5, -999, false);
test_one<polygon_type, polygon_type>("ticket_10398_1_84", ticket_10398_1, join_miter, end_flat, 1470.8096, 8.4, -999, false);
@ -344,8 +444,67 @@ void test_all()
test_one<polygon_type, polygon_type>("ticket_10398_4_91", ticket_10398_4, join_miter, end_flat, 819.1406, 9.1, -999, false);
test_one<polygon_type, polygon_type>("ticket_10412", ticket_10412, join_miter, end_flat, 3109.6616, 1.5, -999, false);
// Tickets - deflated
test_one<polygon_type, polygon_type>("ticket_10398_1_5", ticket_10398_1, join_miter, end_flat, 404.3936, -0.5);
test_one<polygon_type, polygon_type>("ticket_10398_1_25", ticket_10398_1, join_miter, end_flat, 246.7329, -2.5);
{
bg::strategy::buffer::join_round join_round32(32);
bg::strategy::buffer::end_round end_round32(32);
test_one<polygon_type, polygon_type>("mysql_report_2014_10_24", mysql_report_2014_10_24,
join_round32, end_round32, 174.902, 1.0);
test_one<polygon_type, polygon_type>("mysql_report_2014_10_28_1", mysql_report_2014_10_28_1,
join_round32, end_round32, 75.46, 1.0);
test_one<polygon_type, polygon_type>("mysql_report_2014_10_28_2", mysql_report_2014_10_28_2,
join_round32, end_round32, 69.117, 1.0);
test_one<polygon_type, polygon_type>("mysql_report_2014_10_28_3", mysql_report_2014_10_28_3,
join_round32, end_round32, 63.121, 1.0);
}
{
bg::strategy::buffer::join_round join_round12(12);
buffer_custom_side_strategy side_strategy;
bg::strategy::buffer::point_circle point_strategy;
bg::strategy::buffer::distance_symmetric
<
typename bg::coordinate_type<P>::type
> distance_strategy(1.0);
test_with_custom_strategies<polygon_type, polygon_type>("sharp_triangle",
sharp_triangle,
join_round12, end_flat, distance_strategy, side_strategy, point_strategy,
31.0721);
}
}
template
<
typename InputPoint,
typename OutputPoint,
bool InputClockwise,
bool OutputClockwise,
bool InputClosed,
bool OutputClosed
>
void test_mixed()
{
typedef bg::model::polygon<InputPoint, InputClockwise, InputClosed> input_polygon_type;
typedef bg::model::polygon<OutputPoint, OutputClockwise, OutputClosed> output_polygon_type;
bg::strategy::buffer::join_round join_round(12);
bg::strategy::buffer::end_flat end_flat;
std::ostringstream name;
name << "mixed_" << std::boolalpha
<< InputClockwise << "_" << OutputClockwise
<< "_" << InputClosed << "_" << OutputClosed;
test_one<input_polygon_type, output_polygon_type>(name.str(),
simplex, join_round, end_flat, 47.4831, 1.5);
}
#ifdef HAVE_TTMATH
#include <ttmath_stub.hpp>
@ -353,8 +512,28 @@ void test_all()
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
//test_all<bg::model::point<tt, 2, bg::cs::cartesian> >();
typedef bg::model::point<double, 2, bg::cs::cartesian> dpoint;
test_all<true, dpoint>();
test_all<false, dpoint>();
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
test_mixed<dpoint, dpoint, false, false, true, true>();
test_mixed<dpoint, dpoint, false, true, true, true>();
test_mixed<dpoint, dpoint, true, false, true, true>();
test_mixed<dpoint, dpoint, true, true, true, true>();
test_mixed<dpoint, dpoint, false, false, false, true>();
test_mixed<dpoint, dpoint, false, true, false, true>();
test_mixed<dpoint, dpoint, true, false, false, true>();
test_mixed<dpoint, dpoint, true, true, false, true>();
#ifdef HAVE_TTMATH
test_all<bg::model::point<tt, 2, bg::cs::cartesian> >();
#endif
#endif
return 0;
}

View File

@ -128,7 +128,7 @@ struct svg_visitor
color = 'r';
is_good = false;
break;
case bgdb::inside_original :
case bgdb::location_discard :
fill = "fill:rgb(0,0,255);";
color = 'b';
is_good = false;
@ -285,6 +285,9 @@ struct svg_visitor
template <typename PieceCollection>
inline void apply(PieceCollection const& collection, int phase)
{
// Comment next return if you want to see pieces, turns, etc.
return;
if(phase == 0)
{
map_pieces(collection.m_pieces, collection.offsetted_rings, true, true);
@ -362,12 +365,18 @@ template
typename GeometryOut,
typename JoinStrategy,
typename EndStrategy,
typename DistanceStrategy,
typename SideStrategy,
typename PointStrategy,
typename Geometry
>
void test_buffer(std::string const& caseid, Geometry const& geometry,
JoinStrategy const& join_strategy, EndStrategy const& end_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy,
PointStrategy const& point_strategy,
bool check_self_intersections, double expected_area,
double distance_left, double distance_right,
double tolerance,
std::size_t* self_ip_count)
{
@ -387,11 +396,6 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
: ""
;
if (distance_right < -998)
{
distance_right = distance_left;
}
bg::model::box<point_type> envelope;
bg::envelope(geometry, envelope);
@ -411,7 +415,8 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
<< string_from_type<coordinate_type>::name()
<< "_" << join_name
<< (end_name.empty() ? "" : "_") << end_name
<< (distance_left < 0 && distance_right < 0 ? "_deflate" : "")
<< (distance_strategy.negative() ? "_deflate" : "")
<< (bg::point_order<GeometryOut>::value == bg::counterclockwise ? "_ccw" : "")
// << "_" << point_buffer_count
;
@ -426,10 +431,15 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
mapper_type mapper(svg, 1000, 1000);
{
double d = std::abs(distance_left) + std::abs(distance_right);
bg::model::box<point_type> box = envelope;
bg::buffer(box, box, d * (join_name == "miter" ? 2.0 : 1.1));
if (distance_strategy.negative())
{
bg::buffer(box, box, 1.0);
}
else
{
bg::buffer(box, box, 1.1 * distance_strategy.max_distance(join_strategy, end_strategy));
}
mapper.add(box);
}
@ -438,19 +448,6 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
bg::detail::buffer::visit_pieces_default_policy visitor;
#endif
bg::strategy::buffer::distance_asymmetric
<
coordinate_type
>
distance_strategy(distance_left, distance_right);
bg::strategy::buffer::side_straight side_strategy;
// For (multi)points a buffer with 88 points is used for testing.
// More points will give a more precise result - expected area should be
// adapted then
bg::strategy::buffer::point_circle circle_strategy(88);
typedef typename bg::point_type<Geometry>::type point_type;
typedef typename bg::rescale_policy_type<point_type>::type
rescale_policy_type;
@ -469,7 +466,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
side_strategy,
join_strategy,
end_strategy,
circle_strategy,
point_strategy,
rescale_policy,
visitor);
@ -524,16 +521,24 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
// Map input geometry in green
if (areal)
{
mapper.map(geometry, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,128,0);stroke-width:2");
mapper.map(geometry, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,64,0);stroke-width:2");
}
else
{
mapper.map(geometry, "opacity:0.5;stroke:rgb(0,128,0);stroke-width:10");
}
// Map buffer in yellow (inflate) and with orange-dots (deflate)
BOOST_FOREACH(GeometryOut const& polygon, buffered)
{
mapper.map(polygon, "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3");
if (distance_strategy.negative())
{
mapper.map(polygon, "opacity:0.4;fill:rgb(255,255,192);stroke:rgb(255,128,0);stroke-width:3");
}
else
{
mapper.map(polygon, "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3");
}
post_map(polygon, mapper, rescale_policy);
}
#endif
@ -595,10 +600,39 @@ void test_one(std::string const& caseid, std::string const& wkt,
<< std::endl;
#endif
bg::strategy::buffer::side_straight side_strategy;
bg::strategy::buffer::point_circle circle_strategy(88);
bg::strategy::buffer::distance_asymmetric
<
typename bg::coordinate_type<Geometry>::type
> distance_strategy(distance_left,
distance_right > -998 ? distance_right : distance_left);
test_buffer<GeometryOut>
(caseid, g, join_strategy, end_strategy,
(caseid, g,
join_strategy, end_strategy,
distance_strategy, side_strategy, circle_strategy,
check_self_intersections, expected_area,
distance_left, distance_right, tolerance, NULL);
tolerance, NULL);
// Also test symmetric distance strategy if right-distance is not specified
if (bg::math::equals(distance_right, -999))
{
bg::strategy::buffer::distance_symmetric
<
typename bg::coordinate_type<Geometry>::type
> sym_distance_strategy(distance_left);
test_buffer<GeometryOut>
(caseid + "_sym", g,
join_strategy, end_strategy,
sym_distance_strategy, side_strategy, circle_strategy,
check_self_intersections, expected_area,
tolerance, NULL);
}
}
// Version (currently for the Aimes test) counting self-ip's instead of checking
@ -621,10 +655,52 @@ void test_one(std::string const& caseid, std::string const& wkt,
bg::read_wkt(wkt, g);
bg::correct(g);
test_buffer<GeometryOut>(caseid, g, join_strategy, end_strategy,
bg::strategy::buffer::distance_asymmetric
<
typename bg::coordinate_type<Geometry>::type
> distance_strategy(distance_left,
distance_right > -998 ? distance_right : distance_left);
bg::strategy::buffer::point_circle circle_strategy(88);
bg::strategy::buffer::side_straight side_strategy;
test_buffer<GeometryOut>(caseid, g,
join_strategy, end_strategy,
distance_strategy, side_strategy, circle_strategy,
false, expected_area,
distance_left, distance_right, tolerance, &self_ip_count);
tolerance, &self_ip_count);
}
template
<
typename Geometry,
typename GeometryOut,
typename JoinStrategy,
typename EndStrategy,
typename DistanceStrategy,
typename SideStrategy,
typename PointStrategy
>
void test_with_custom_strategies(std::string const& caseid,
std::string const& wkt,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy,
PointStrategy const& point_strategy,
double expected_area)
{
namespace bg = boost::geometry;
Geometry g;
bg::read_wkt(wkt, g);
bg::correct(g);
test_buffer<GeometryOut>
(caseid, g,
join_strategy, end_strategy,
distance_strategy, side_strategy, point_strategy,
true, expected_area, 0.01, NULL);
}
#endif

View File

@ -5,6 +5,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -129,6 +134,34 @@ void test_large_integers()
BOOST_CHECK_EQUAL(bg::get<1>(int_centroid), bg::get<1>(double_centroid_as_int));
}
//#include <to_svg.hpp>
void test_large_doubles()
{
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
point pt_far, pt_near;
bg::model::polygon<point> poly_far, poly_near;
// related to ticket #10643
bg::read_wkt("POLYGON((1074699.93 703064.65, 1074703.90 703064.58, 1074704.53 703061.40, 1074702.10 703054.62, 1074699.93 703064.65))", poly_far);
bg::read_wkt("POLYGON((699.93 64.65, 703.90 64.58, 704.53 61.40, 702.10 54.62, 699.93 64.65))", poly_near);
bg::centroid(poly_far, pt_far);
bg::centroid(poly_near, pt_near);
BOOST_CHECK(bg::within(pt_far, poly_far));
BOOST_CHECK(bg::within(pt_near, poly_near));
point pt_near_moved;
bg::set<0>(pt_near_moved, bg::get<0>(pt_near) + 1074000.0);
bg::set<1>(pt_near_moved, bg::get<1>(pt_near) + 703000.0);
//geom_to_svg(poly_far, pt_far, "far.svg");
//geom_to_svg(poly_near, pt_near, "near.svg");
double d = bg::distance(pt_far, pt_near_moved);
BOOST_CHECK(d < 0.1);
}
int test_main(int, char* [])
{
@ -149,6 +182,9 @@ int test_main(int, char* [])
// The test currently fails in release mode. TODO: fix this
test_large_integers();
#endif
test_large_doubles();
test_exceptions<bg::model::d2::point_xy<double> >();
return 0;

View File

@ -24,7 +24,7 @@
template <int DimensionCount, bool Reverse, typename Geometry>
void test_sectionalize(std::string const caseid, Geometry const& geometry, std::size_t section_count)
void test_sectionalize(std::string const /*caseid*/, Geometry const& geometry, std::size_t section_count)
{
typedef typename bg::point_type<Geometry>::type point;
typedef bg::model::box<point> box;

View File

@ -0,0 +1,27 @@
# Boost.Geometry (aka GGL, Generic Geometry Library)
#
# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
#
# This file was modified by Oracle on 2014.
# Modifications copyright (c) 2014, Oracle and/or its affiliates.
#
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
test-suite boost-geometry-algorithms-distance
:
[ run distance.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run distance_areal_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run distance_linear_areal.cpp : : : <toolset>msvc:<cxxflags>/bigobj ]
[ run distance_linear_linear.cpp ]
[ run distance_pointlike_areal.cpp ]
[ run distance_pointlike_linear.cpp ]
[ run distance_pointlike_pointlike.cpp ]
[ run distance_se_pl_pl.cpp ]
;

View File

@ -16,7 +16,7 @@
#include <string>
#include <sstream>
#include <algorithms/test_distance.hpp>
#include "test_distance.hpp"
#include <boost/mpl/if.hpp>
#include <boost/array.hpp>

View File

@ -0,0 +1,229 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#include <iostream>
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_distance_spherical_equatorial_pl_pl
#endif
#include <boost/range.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include "test_distance_se_common.hpp"
typedef bg::cs::spherical_equatorial<bg::degree> cs_type;
typedef bg::model::point<double, 2, cs_type> point_type;
typedef bg::model::multi_point<point_type> multi_point_type;
namespace services = bg::strategy::distance::services;
typedef bg::default_distance_result<point_type>::type return_type;
typedef bg::strategy::distance::haversine<double> point_point_strategy;
//===========================================================================
inline bg::default_distance_result<point_type>::type
distance_from_wkt(std::string const& wkt1, std::string const& wkt2)
{
point_type p1, p2;
bg::read_wkt(wkt1, p1);
bg::read_wkt(wkt2, p2);
return bg::distance(p1, p2);
}
inline bg::default_comparable_distance_result<point_type>::type
comparable_distance_from_wkt(std::string const& wkt1, std::string const& wkt2)
{
point_type p1, p2;
bg::read_wkt(wkt1, p1);
bg::read_wkt(wkt2, p2);
return bg::comparable_distance(p1, p2);
}
//===========================================================================
template <typename Strategy>
void test_distance_point_point(Strategy const& strategy)
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "point/point distance tests" << std::endl;
#endif
typedef test_distance_of_geometries<point_type, point_type> tester;
tester::apply("POINT(10 10)",
"POINT(0 0)",
0.24619691677893202,
0.0150768448035229,
strategy);
tester::apply("POINT(10 10)",
"POINT(10 10)",
0, 0, strategy);
// antipodal points
tester::apply("POINT(0 10)",
"POINT(180 -10)",
180.0 * bg::math::d2r, 1.0, strategy);
}
//===========================================================================
template <typename Strategy>
void test_distance_point_multipoint(Strategy const& strategy)
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "point/multipoint distance tests" << std::endl;
#endif
typedef test_distance_of_geometries<point_type, multi_point_type> tester;
tester::apply("POINT(10 10)",
"MULTIPOINT(10 10,20 10,20 20,10 20)",
0, 0, strategy);
tester::apply("POINT(10 10)",
"MULTIPOINT(20 20,20 30,30 20,30 30)",
distance_from_wkt("POINT(10 10)", "POINT(20 20)"),
comparable_distance_from_wkt("POINT(10 10)", "POINT(20 20)"),
strategy);
tester::apply("POINT(3 0)",
"MULTIPOINT(20 20,20 40,40 20,40 40)",
distance_from_wkt("POINT(3 0)", "POINT(20 20)"),
comparable_distance_from_wkt("POINT(3 0)", "POINT(20 20)"),
strategy);
// almost antipodal points
tester::apply("POINT(179 2)",
"MULTIPOINT(3 3,4 3,4 4,3 4)",
distance_from_wkt("POINT(179 2)", "POINT(4 4)"),
comparable_distance_from_wkt("POINT(179 2)", "POINT(4 4)"),
strategy);
// minimum distance across the dateline
tester::apply("POINT(355 5)",
"MULTIPOINT(10 10,20 10,20 20,10 20)",
distance_from_wkt("POINT(355 5)", "POINT(10 10)"),
comparable_distance_from_wkt("POINT(355 5)", "POINT(10 10)"),
strategy);
}
//===========================================================================
template <typename Strategy>
void test_distance_multipoint_multipoint(Strategy const& strategy)
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "multipoint/multipoint distance tests" << std::endl;
#endif
typedef test_distance_of_geometries
<
multi_point_type, multi_point_type
> tester;
tester::apply("MULTIPOINT(10 10,11 10,10 11,11 11)",
"MULTIPOINT(11 11,12 11,12 12,11 12)",
0, 0, strategy);
tester::apply("MULTIPOINT(10 10,11 10,10 11,11 11)",
"MULTIPOINT(12 12,12 13,13 12,13 13)",
distance_from_wkt("POINT(11 11)", "POINT(12 12)"),
comparable_distance_from_wkt("POINT(11 11)", "POINT(12 12)"),
strategy);
// example with many points in each multi-point so that the r-tree
// does some splitting.
tester::apply("MULTIPOINT(1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 8,1 9,1 10,\
2 1,2 2,2 3,2 4,2 5,2 6,2 7,2 8,2 9,2 10,\
3 1,3 2,3 3,3 4,3 5,3 6,3 7,3 8,3 9,3 10,\
10 1,10 10)",
"MULTIPOINT(11 11,11 12,11 13,11 14,11 15,\
11 16,11 17,11 18,11 19,11 20,\
12 11,12 12,12 13,12 24,12 15,\
12 16,12 17,12 18,12 29,12 20,\
13 11,13 12,13 13,13 24,13 15,\
13 16,13 17,13 18,13 29,13 20,\
20 11,20 20)",
distance_from_wkt("POINT(10 10)", "POINT(11 11)"),
comparable_distance_from_wkt("POINT(10 10)", "POINT(11 11)"),
strategy);
}
//===========================================================================
template <typename Point, typename Strategy>
void test_more_empty_input_pointlike_pointlike(Strategy const& strategy)
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl;
std::cout << "testing on empty inputs... " << std::flush;
#endif
bg::model::multi_point<Point> multipoint_empty;
Point point = from_wkt<Point>("POINT(0 0)");
// 1st geometry is empty
test_empty_input(multipoint_empty, point, strategy);
// 2nd geometry is empty
test_empty_input(point, multipoint_empty, strategy);
// both geometries are empty
test_empty_input(multipoint_empty, multipoint_empty, strategy);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "done!" << std::endl;
#endif
}
//===========================================================================
BOOST_AUTO_TEST_CASE( test_all_point_point )
{
test_distance_point_point(point_point_strategy());
test_distance_point_point(point_point_strategy(earth_radius_km));
test_distance_point_point(point_point_strategy(earth_radius_miles));
}
BOOST_AUTO_TEST_CASE( test_all_point_multipoint )
{
test_distance_point_multipoint(point_point_strategy());
test_distance_point_multipoint(point_point_strategy(earth_radius_km));
test_distance_point_multipoint(point_point_strategy(earth_radius_miles));
}
BOOST_AUTO_TEST_CASE( test_all_multipoint_multipoint )
{
test_distance_multipoint_multipoint(point_point_strategy());
test_distance_multipoint_multipoint(point_point_strategy(earth_radius_km));
test_distance_multipoint_multipoint(point_point_strategy(earth_radius_miles));
}
BOOST_AUTO_TEST_CASE( test_all_empty_input_pointlike_pointlike )
{
test_more_empty_input_pointlike_pointlike
<
point_type
>(point_point_strategy());
test_more_empty_input_pointlike_pointlike
<
point_type
>(point_point_strategy(earth_radius_km));
test_more_empty_input_pointlike_pointlike
<
point_type
>(point_point_strategy(earth_radius_miles));
}

View File

@ -39,8 +39,7 @@
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include "from_wkt.hpp"
#include <from_wkt.hpp>
#include <string_from_type.hpp>

View File

@ -0,0 +1,573 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP
#define BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP
#include <iostream>
#include <string>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/multi/geometries/multi_point.hpp>
#include <boost/geometry/multi/geometries/multi_linestring.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
#include <boost/geometry/io/wkt/write.hpp>
#include <boost/geometry/multi/io/wkt/write.hpp>
#include <boost/geometry/io/dsv/write.hpp>
#include <boost/geometry/multi/io/dsv/write.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <from_wkt.hpp>
#include <string_from_type.hpp>
#ifndef BOOST_GEOMETRY_TEST_DISTANCE_HPP
namespace bg = ::boost::geometry;
static const double earth_radius_km = 6371.0;
static const double earth_radius_miles = 3959.0;
// function copied from BG's test_distance.hpp
template <typename Geometry1, typename Geometry2>
void test_empty_input(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
try
{
bg::distance(geometry1, geometry2);
}
catch(bg::empty_input_exception const& )
{
return;
}
BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
}
#endif // BOOST_GEOMETRY_TEST_DISTANCE_HPP
//========================================================================
template
<
typename PointLike1,
typename PointLike2,
typename Strategy,
typename Tag1 = typename bg::tag<PointLike1>::type,
typename Tag2 = typename bg::tag<PointLike2>::type
>
struct distance_brute_force
{};
template
<
typename PointLike1,
typename PointLike2,
typename Strategy
>
struct distance_brute_force
<
PointLike1, PointLike2, Strategy,
bg::point_tag, bg::point_tag
>
{
typedef typename bg::distance_result
<
PointLike1, PointLike2, Strategy
>::type distance_type;
static inline distance_type apply(PointLike1 const& p1,
PointLike2 const& p2,
Strategy const& strategy)
{
return bg::distance(p1, p2, strategy);
}
};
template
<
typename PointLike1,
typename PointLike2,
typename Strategy
>
struct distance_brute_force
<
PointLike1, PointLike2, Strategy,
bg::point_tag, bg::multi_point_tag
>
{
typedef typename bg::distance_result
<
PointLike1, PointLike2, Strategy
>::type distance_type;
static inline distance_type apply(PointLike1 const& p,
PointLike2 const& mp,
Strategy const& strategy)
{
typedef typename boost::range_iterator<PointLike2 const>::type iterator;
bool first = true;
distance_type d_min;
for (iterator it = boost::begin(mp); it != boost::end(mp);
++it, first = false)
{
distance_type d = bg::distance(p, *it, strategy);
if ( first || d < d_min )
{
d_min = d;
}
}
return d_min;
}
};
template
<
typename PointLike1,
typename PointLike2,
typename Strategy
>
struct distance_brute_force
<
PointLike1, PointLike2, Strategy,
bg::multi_point_tag, bg::multi_point_tag
>
{
typedef typename bg::distance_result
<
PointLike1, PointLike2, Strategy
>::type distance_type;
static inline distance_type apply(PointLike1 const& mp1,
PointLike2 const& mp2,
Strategy const& strategy)
{
typedef typename boost::range_iterator
<
PointLike1 const
>::type iterator1;
typedef typename boost::range_iterator
<
PointLike2 const
>::type iterator2;
bool first = true;
distance_type d_min;
for (iterator1 it1 = boost::begin(mp1); it1 != boost::end(mp1); ++it1)
{
for (iterator2 it2 = boost::begin(mp2); it2 != boost::end(mp2);
++it2, first = false)
{
distance_type d = bg::distance(*it1, *it2, strategy);
if ( first || d < d_min )
{
d_min = d;
}
}
}
return d_min;
}
};
//========================================================================
#ifdef BOOST_GEOMETRY_TEST_DEBUG
// pretty print geometry -- START
template <typename Geometry, typename GeometryTag>
struct pretty_print_geometry_dispatch
{
template <typename Stream>
static inline Stream& apply(Geometry const& geometry, Stream& os)
{
os << bg::wkt(geometry);
return os;
}
};
template <typename Geometry>
struct pretty_print_geometry_dispatch<Geometry, bg::segment_tag>
{
template <typename Stream>
static inline Stream& apply(Geometry const& geometry, Stream& os)
{
os << "SEGMENT" << bg::dsv(geometry);
return os;
}
};
template <typename Geometry>
struct pretty_print_geometry_dispatch<Geometry, bg::box_tag>
{
template <typename Stream>
static inline Stream& apply(Geometry const& geometry, Stream& os)
{
os << "BOX" << bg::dsv(geometry);
return os;
}
};
template <typename Geometry>
struct pretty_print_geometry
{
template <typename Stream>
static inline Stream& apply(Geometry const& geometry, Stream& os)
{
return pretty_print_geometry_dispatch
<
Geometry, typename bg::tag<Geometry>::type
>::apply(geometry, os);
}
};
// pretty print geometry -- END
#endif // BOOST_GEOMETRY_TEST_DEBUG
//========================================================================
template <typename T>
struct check_equal
{
static inline void apply(T const& value1, T const& value2)
{
BOOST_CHECK( value1 == value2 );
}
};
template <>
struct check_equal<double>
{
static inline void apply(double value1, double value2)
{
BOOST_CHECK_CLOSE( value1, value2, 0.0001 );
}
};
//========================================================================
template
<
typename Geometry1, typename Geometry2,
int id1 = bg::geometry_id<Geometry1>::value,
int id2 = bg::geometry_id<Geometry2>::value
>
struct test_distance_of_geometries
: public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
{};
template <typename Geometry1, typename Geometry2>
struct test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
{
template
<
typename DistanceType,
typename ComparableDistanceType,
typename Strategy
>
static inline
void apply(std::string const& wkt1,
std::string const& wkt2,
DistanceType const& expected_distance,
ComparableDistanceType const& expected_comparable_distance,
Strategy const& strategy,
bool test_reversed = true)
{
Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
apply(geometry1, geometry2,
expected_distance, expected_comparable_distance,
strategy, test_reversed);
}
template
<
typename DistanceType,
typename ComparableDistanceType,
typename Strategy
>
static inline
void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
DistanceType const& expected_distance,
ComparableDistanceType const& expected_comparable_distance,
Strategy const& strategy,
bool test_reversed = true)
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
typedef pretty_print_geometry<Geometry1> PPG1;
typedef pretty_print_geometry<Geometry2> PPG2;
PPG1::apply(geometry1, std::cout);
std::cout << " - ";
PPG2::apply(geometry2, std::cout);
std::cout << std::endl;
#endif
typedef typename bg::default_distance_result
<
Geometry1, Geometry2
>::type default_distance_result;
typedef typename bg::strategy::distance::services::return_type
<
Strategy, Geometry1, Geometry2
>::type distance_result_from_strategy;
static const bool same_regular = boost::is_same
<
default_distance_result,
distance_result_from_strategy
>::type::value;
BOOST_CHECK( same_regular );
typedef typename bg::default_comparable_distance_result
<
Geometry1, Geometry2
>::type default_comparable_distance_result;
typedef typename bg::strategy::distance::services::return_type
<
typename bg::strategy::distance::services::comparable_type
<
Strategy
>::type,
Geometry1,
Geometry2
>::type comparable_distance_result_from_strategy;
static const bool same_comparable = boost::is_same
<
default_comparable_distance_result,
comparable_distance_result_from_strategy
>::type::value;
BOOST_CHECK( same_comparable );
// check distance with default strategy
default_distance_result dist_def = bg::distance(geometry1, geometry2);
check_equal
<
default_distance_result
>::apply(dist_def, expected_distance);
// check distance with passed strategy
distance_result_from_strategy dist =
bg::distance(geometry1, geometry2, strategy);
check_equal
<
default_distance_result
>::apply(dist, expected_distance * strategy.radius());
// check against the comparable distance computed in a
// brute-force manner
default_distance_result dist_brute_force = distance_brute_force
<
Geometry1, Geometry2, Strategy
>::apply(geometry1, geometry2, strategy);
check_equal
<
default_distance_result
>::apply(dist_brute_force, expected_distance * strategy.radius());
// check comparable distance with default strategy
default_comparable_distance_result cdist_def =
bg::comparable_distance(geometry1, geometry2);
check_equal
<
default_comparable_distance_result
>::apply(cdist_def, expected_comparable_distance);
// check comparable distance with passed strategy
comparable_distance_result_from_strategy cdist =
bg::comparable_distance(geometry1, geometry2, strategy);
check_equal
<
default_comparable_distance_result
>::apply(cdist, expected_comparable_distance);
// check against the comparable distance computed in a
// brute-force manner
default_comparable_distance_result cdist_brute_force
= distance_brute_force
<
Geometry1,
Geometry2,
typename bg::strategy::distance::services::comparable_type
<
Strategy
>::type
>::apply(geometry1,
geometry2,
bg::strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy));
check_equal
<
default_comparable_distance_result
>::apply(cdist_brute_force, expected_comparable_distance);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name()
<< string_from_type<typename bg::coordinate_type<Geometry2>::type>::name()
<< " -> "
<< string_from_type<default_distance_result>::name()
<< string_from_type<default_comparable_distance_result>::name()
<< std::endl;
std::cout << "expected distance (default strategy) = "
<< expected_distance << " ; "
<< "expected distance (passed strategy) = "
<< (expected_distance * strategy.radius()) << " ; "
<< "expected comp. distance = "
<< expected_comparable_distance
<< std::endl;
std::cout << "distance (default strategy) = " << dist_def << " ; "
<< "distance (passed strategy) = " << dist << " ; "
<< "comp. distance (default strategy) = "
<< cdist_def << " ; "
<< "comp. distance (passed strategy) = "
<< cdist << std::endl;
if ( !test_reversed )
{
std::cout << std::endl;
}
#endif
if ( test_reversed )
{
// check distance with default strategy
dist_def = bg::distance(geometry2, geometry1);
check_equal
<
default_distance_result
>::apply(dist_def, expected_distance);
// check distance with given strategy
dist = bg::distance(geometry2, geometry1, strategy);
check_equal
<
default_distance_result
>::apply(dist, expected_distance * strategy.radius());
// check comparable distance with default strategy
cdist_def = bg::comparable_distance(geometry2, geometry1);
check_equal
<
default_comparable_distance_result
>::apply(cdist_def, expected_comparable_distance);
// check comparable distance with given strategy
cdist = bg::comparable_distance(geometry2, geometry1, strategy);
check_equal
<
default_comparable_distance_result
>::apply(cdist, expected_comparable_distance);
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << "expected distance (default strategy) = "
<< expected_distance << " ; "
<< "expected distance (passed strategy) = "
<< (expected_distance * strategy.radius()) << " ; "
<< "expected comp. distance = "
<< expected_comparable_distance
<< std::endl;
std::cout << "distance[reversed args] (def. startegy) = "
<< dist_def << " ; "
<< "distance[reversed args] (passed startegy) = "
<< dist << " ; "
<< "comp. distance[reversed args] (def. strategy) = "
<< cdist_def << " ; "
<< "comp. distance[reversed args] (passed strategy) = "
<< cdist << std::endl;
std::cout << std::endl;
#endif
}
}
};
//========================================================================
template <typename Geometry1, typename Geometry2, typename Strategy>
void test_empty_input(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
try
{
bg::distance(geometry1, geometry2, strategy);
}
catch(bg::empty_input_exception const& )
{
return;
}
BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
try
{
bg::distance(geometry2, geometry1, strategy);
}
catch(bg::empty_input_exception const& )
{
return;
}
BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
}
#endif // BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP

View File

@ -36,7 +36,7 @@
#include <boost/geometry/algorithms/is_valid.hpp>
#include <boost/geometry/algorithms/is_simple.hpp>
#include "from_wkt.hpp"
#include <from_wkt.hpp>
#ifdef BOOST_GEOMETRY_TEST_DEBUG
#include "pretty_print_geometry.hpp"

View File

@ -16,7 +16,7 @@
#include <boost/test/included/unit_test.hpp>
#include "from_wkt.hpp"
#include <from_wkt.hpp>
#include "test_is_valid.hpp"

View File

@ -5,6 +5,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -52,11 +57,11 @@ void test_all()
test_geometry<mp>("MULTIPOINT((0 0),(5 0),(1 1),(4 1))", -1, 5, 4.0);
test_geometry<mp>("MULTIPOINT((0 1),(5 1),(1 0),(4 0))", -1, 5, 4.0);
// All points in vertical line (this delivers an empty polygon with 2 points and a closing point)
test_geometry<mp>("MULTIPOINT((1 0),(5 0),(3 0),(4 0),(2 0))", -1, 3, 0.0);
// All points in vertical line (this delivers an empty polygon with 3 points and closing point for closed)
test_geometry<mp>("MULTIPOINT((1 0),(5 0),(3 0),(4 0),(2 0))", -1, 4, 0.0);
// One point only
test_geometry<mp>("MULTIPOINT((1 0))", -1, 3, 0.0);
test_geometry<mp>("MULTIPOINT((1 0))", -1, 4, 0.0);
// Problem of 6019, reproduced by the convex hull robustness test:
test_geometry<mp>("MULTIPOINT((2 9),(1 3),(9 4),(1 1),(1 0),(7 9),(2 5),(3 7),(3 6),(2 4))",

Some files were not shown because too many files have changed in this diff Show More