summaryrefslogtreecommitdiff
path: root/boost/geometry
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:08:07 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:09:00 +0900
commitb5c87084afaef42b2d058f68091be31988a6a874 (patch)
treeadef9a65870a41181687e11d57fdf98e7629de3c /boost/geometry
parent34bd32e225e2a8a94104489b31c42e5801cc1f4a (diff)
downloadboost-b5c87084afaef42b2d058f68091be31988a6a874.tar.gz
boost-b5c87084afaef42b2d058f68091be31988a6a874.tar.bz2
boost-b5c87084afaef42b2d058f68091be31988a6a874.zip
Imported Upstream version 1.64.0upstream/1.64.0
Change-Id: Id9212edd016dd55f21172c427aa7894d1d24148b Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/geometry')
-rw-r--r--boost/geometry/algorithms/area.hpp7
-rw-r--r--boost/geometry/algorithms/buffer.hpp10
-rw-r--r--boost/geometry/algorithms/centroid.hpp7
-rw-r--r--boost/geometry/algorithms/covered_by.hpp31
-rw-r--r--boost/geometry/algorithms/crosses.hpp141
-rw-r--r--boost/geometry/algorithms/detail/azimuth.hpp25
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp57
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_policies.hpp6
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp49
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp12
-rw-r--r--boost/geometry/algorithms/detail/calculate_sum.hpp6
-rw-r--r--boost/geometry/algorithms/detail/disjoint/areal_areal.hpp74
-rw-r--r--boost/geometry/algorithms/detail/disjoint/box_box.hpp16
-rw-r--r--boost/geometry/algorithms/detail/disjoint/interface.hpp157
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_areal.hpp87
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_linear.hpp38
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp11
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp88
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp25
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_box.hpp28
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_geometry.hpp9
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_point.hpp18
-rw-r--r--boost/geometry/algorithms/detail/disjoint/segment_box.hpp242
-rw-r--r--boost/geometry/algorithms/detail/envelope/box.hpp17
-rw-r--r--boost/geometry/algorithms/detail/envelope/implementation.hpp13
-rw-r--r--boost/geometry/algorithms/detail/envelope/interface.hpp124
-rw-r--r--boost/geometry/algorithms/detail/envelope/linear.hpp28
-rw-r--r--boost/geometry/algorithms/detail/envelope/multipoint.hpp13
-rw-r--r--boost/geometry/algorithms/detail/envelope/point.hpp15
-rw-r--r--boost/geometry/algorithms/detail/envelope/range.hpp44
-rw-r--r--boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp21
-rw-r--r--boost/geometry/algorithms/detail/envelope/segment.hpp209
-rw-r--r--boost/geometry/algorithms/detail/equals/collect_vectors.hpp97
-rw-r--r--boost/geometry/algorithms/detail/expand/box.hpp17
-rw-r--r--boost/geometry/algorithms/detail/expand/indexed.hpp25
-rw-r--r--boost/geometry/algorithms/detail/expand/interface.hpp99
-rw-r--r--boost/geometry/algorithms/detail/expand/point.hpp27
-rw-r--r--boost/geometry/algorithms/detail/expand/segment.hpp42
-rw-r--r--boost/geometry/algorithms/detail/has_self_intersections.hpp23
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp279
-rw-r--r--boost/geometry/algorithms/detail/is_simple/always_simple.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_simple/areal.hpp18
-rw-r--r--boost/geometry/algorithms/detail/is_simple/interface.hpp77
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp31
-rw-r--r--boost/geometry/algorithms/detail/is_simple/multipoint.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_valid/box.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/interface.hpp163
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp33
-rw-r--r--boost/geometry/algorithms/detail/is_valid/pointlike.hpp11
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp49
-rw-r--r--boost/geometry/algorithms/detail/is_valid/ring.hpp47
-rw-r--r--boost/geometry/algorithms/detail/is_valid/segment.hpp6
-rw-r--r--boost/geometry/algorithms/detail/not.hpp13
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp40
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp49
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp31
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp21
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp139
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp59
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp32
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp130
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp63
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp11
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp42
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp42
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp11
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp5
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp499
-rw-r--r--boost/geometry/algorithms/detail/relate/areal_areal.hpp87
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation.hpp7
-rw-r--r--boost/geometry/algorithms/detail/relate/interface.hpp135
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_areal.hpp79
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_linear.hpp16
-rw-r--r--boost/geometry/algorithms/detail/relate/point_geometry.hpp16
-rw-r--r--boost/geometry/algorithms/detail/relate/point_point.hpp34
-rw-r--r--boost/geometry/algorithms/detail/relate/relate_impl.hpp5
-rw-r--r--boost/geometry/algorithms/detail/relate/result.hpp4
-rw-r--r--boost/geometry/algorithms/detail/relate/turns.hpp24
-rw-r--r--boost/geometry/algorithms/detail/relation/interface.hpp93
-rw-r--r--boost/geometry/algorithms/detail/throw_on_empty_input.hpp7
-rw-r--r--boost/geometry/algorithms/detail/within/point_in_geometry.hpp98
-rw-r--r--boost/geometry/algorithms/difference.hpp305
-rw-r--r--boost/geometry/algorithms/dispatch/disjoint.hpp27
-rw-r--r--boost/geometry/algorithms/equals.hpp319
-rw-r--r--boost/geometry/algorithms/intersects.hpp40
-rw-r--r--boost/geometry/algorithms/overlaps.hpp46
-rw-r--r--boost/geometry/algorithms/sym_difference.hpp288
-rw-r--r--boost/geometry/algorithms/touches.hpp212
-rw-r--r--boost/geometry/algorithms/union.hpp294
-rw-r--r--boost/geometry/algorithms/within.hpp37
-rw-r--r--boost/geometry/arithmetic/normalize.hpp71
-rw-r--r--boost/geometry/core/srs.hpp9
-rw-r--r--boost/geometry/formulas/andoyer_inverse.hpp27
-rw-r--r--boost/geometry/formulas/area_formulas.hpp578
-rw-r--r--boost/geometry/formulas/differential_quantities.hpp19
-rw-r--r--boost/geometry/formulas/eccentricity_sqr.hpp70
-rw-r--r--boost/geometry/formulas/flattening.hpp (renamed from boost/geometry/algorithms/detail/flattening.hpp)19
-rw-r--r--boost/geometry/formulas/geographic.hpp457
-rw-r--r--boost/geometry/formulas/gnomonic_spheroid.hpp3
-rw-r--r--boost/geometry/formulas/sjoberg_intersection.hpp1310
-rw-r--r--boost/geometry/formulas/spherical.hpp152
-rw-r--r--boost/geometry/formulas/thomas_direct.hpp5
-rw-r--r--boost/geometry/formulas/thomas_inverse.hpp5
-rw-r--r--boost/geometry/formulas/vertex_latitude.hpp148
-rw-r--r--boost/geometry/formulas/vincenty_direct.hpp5
-rw-r--r--boost/geometry/formulas/vincenty_inverse.hpp38
-rw-r--r--boost/geometry/index/detail/algorithms/nth_element.hpp62
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp12
-rw-r--r--boost/geometry/index/equal_to.hpp11
-rw-r--r--boost/geometry/index/parameters.hpp24
-rw-r--r--boost/geometry/io/wkt/read.hpp26
-rw-r--r--boost/geometry/policies/robustness/segment_ratio.hpp20
-rw-r--r--boost/geometry/strategies/agnostic/point_in_point.hpp77
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp69
-rw-r--r--boost/geometry/strategies/agnostic/relate.hpp122
-rw-r--r--boost/geometry/strategies/azimuth.hpp44
-rw-r--r--boost/geometry/strategies/cartesian/area_surveyor.hpp5
-rw-r--r--boost/geometry/strategies/cartesian/azimuth.hpp49
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp28
-rw-r--r--boost/geometry/strategies/cartesian/disjoint_segment_box.hpp320
-rw-r--r--boost/geometry/strategies/cartesian/envelope_segment.hpp71
-rw-r--r--boost/geometry/strategies/cartesian/intersection.hpp (renamed from boost/geometry/strategies/cartesian/cart_intersect.hpp)262
-rw-r--r--boost/geometry/strategies/cartesian/point_in_box.hpp28
-rw-r--r--boost/geometry/strategies/covered_by.hpp51
-rw-r--r--boost/geometry/strategies/disjoint.hpp90
-rw-r--r--boost/geometry/strategies/envelope.hpp45
-rw-r--r--boost/geometry/strategies/geographic/area.hpp216
-rw-r--r--boost/geometry/strategies/geographic/azimuth.hpp103
-rw-r--r--boost/geometry/strategies/geographic/distance.hpp195
-rw-r--r--boost/geometry/strategies/geographic/distance_andoyer.hpp90
-rw-r--r--boost/geometry/strategies/geographic/distance_thomas.hpp67
-rw-r--r--boost/geometry/strategies/geographic/distance_vincenty.hpp67
-rw-r--r--boost/geometry/strategies/geographic/envelope_segment.hpp104
-rw-r--r--boost/geometry/strategies/geographic/intersection.hpp897
-rw-r--r--boost/geometry/strategies/geographic/intersection_elliptic.hpp243
-rw-r--r--boost/geometry/strategies/geographic/mapping_ssf.hpp6
-rw-r--r--boost/geometry/strategies/geographic/parameters.hpp117
-rw-r--r--boost/geometry/strategies/geographic/side.hpp113
-rw-r--r--boost/geometry/strategies/geographic/side_andoyer.hpp25
-rw-r--r--boost/geometry/strategies/geographic/side_detail.hpp139
-rw-r--r--boost/geometry/strategies/geographic/side_thomas.hpp25
-rw-r--r--boost/geometry/strategies/geographic/side_vincenty.hpp25
-rw-r--r--boost/geometry/strategies/intersection.hpp5
-rw-r--r--boost/geometry/strategies/intersection_strategies.hpp25
-rw-r--r--boost/geometry/strategies/relate.hpp177
-rw-r--r--boost/geometry/strategies/side.hpp6
-rw-r--r--boost/geometry/strategies/spherical/area.hpp182
-rw-r--r--boost/geometry/strategies/spherical/area_huiller.hpp214
-rw-r--r--boost/geometry/strategies/spherical/azimuth.hpp87
-rw-r--r--boost/geometry/strategies/spherical/envelope_segment.hpp86
-rw-r--r--boost/geometry/strategies/spherical/intersection.hpp525
-rw-r--r--boost/geometry/strategies/strategies.hpp33
-rw-r--r--boost/geometry/strategies/transform/inverse_transformer.hpp33
-rw-r--r--boost/geometry/strategies/transform/map_transformer.hpp53
-rw-r--r--boost/geometry/strategies/transform/matrix_transformers.hpp98
-rw-r--r--boost/geometry/strategies/within.hpp51
-rw-r--r--boost/geometry/util/math.hpp15
-rw-r--r--boost/geometry/util/normalize_spheroidal_coordinates.hpp34
166 files changed, 11108 insertions, 3400 deletions
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp
index 4751d4e742..18aea24036 100644
--- a/boost/geometry/algorithms/area.hpp
+++ b/boost/geometry/algorithms/area.hpp
@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -303,7 +307,8 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr
[heading Available Strategies]
\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
-\* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)]
+\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
+[/link geometry.reference.strategies.strategy_area_geographic Geographic]
}
*/
template <typename Geometry, typename Strategy>
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
index e1d3c20e44..fd6f0fbe6a 100644
--- a/boost/geometry/algorithms/buffer.hpp
+++ b/boost/geometry/algorithms/buffer.hpp
@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -274,6 +278,11 @@ inline void buffer(GeometryIn const& geometry_in,
geometry::envelope(geometry_in, box);
geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
+ typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<GeometryIn>::type
+ >::type intersection_strategy;
+
rescale_policy_type rescale_policy
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
@@ -283,6 +292,7 @@ inline void buffer(GeometryIn const& geometry_in,
join_strategy,
end_strategy,
point_strategy,
+ intersection_strategy,
rescale_policy);
}
diff --git a/boost/geometry/algorithms/centroid.hpp b/boost/geometry/algorithms/centroid.hpp
index fc2908ab1c..6a58033f37 100644
--- a/boost/geometry/algorithms/centroid.hpp
+++ b/boost/geometry/algorithms/centroid.hpp
@@ -3,7 +3,7 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015.
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
@@ -26,6 +26,7 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
@@ -183,7 +184,7 @@ inline bool range_ok(Range const& range, Point& centroid)
else if (n <= 0)
{
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
- throw centroid_exception();
+ BOOST_THROW_EXCEPTION(centroid_exception());
#else
return false;
#endif
@@ -366,7 +367,7 @@ struct centroid_multi
// to calculate the centroid
if (geometry::is_empty(multi))
{
- throw centroid_exception();
+ BOOST_THROW_EXCEPTION(centroid_exception());
}
#endif
diff --git a/boost/geometry/algorithms/covered_by.hpp b/boost/geometry/algorithms/covered_by.hpp
index 2001d5810c..f9d9dcc486 100644
--- a/boost/geometry/algorithms/covered_by.hpp
+++ b/boost/geometry/algorithms/covered_by.hpp
@@ -4,8 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017 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.
@@ -14,8 +16,6 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
@@ -51,9 +51,13 @@ struct use_point_in_geometry
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
- return Strategy::apply(geometry1, geometry2);
+ typedef typename detail::de9im::static_mask_covered_by_type
+ <
+ Geometry1, Geometry2
+ >::type covered_by_mask;
+ return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
}
};
@@ -281,23 +285,8 @@ struct covered_by
Geometry2 const& geometry2,
default_strategy)
{
- typedef typename point_type<Geometry1>::type point_type1;
- typedef typename point_type<Geometry2>::type point_type2;
-
typedef typename strategy::covered_by::services::default_strategy
<
- typename tag<Geometry1>::type,
- typename tag<Geometry2>::type,
- typename tag<Geometry1>::type,
- typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
Geometry1,
Geometry2
>::type strategy_type;
diff --git a/boost/geometry/algorithms/crosses.hpp b/boost/geometry/algorithms/crosses.hpp
index 73d86ef529..c9e3651ab2 100644
--- a/boost/geometry/algorithms/crosses.hpp
+++ b/boost/geometry/algorithms/crosses.hpp
@@ -5,8 +5,10 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -15,8 +17,6 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
@@ -26,12 +26,12 @@
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/core/access.hpp>
-
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
namespace boost { namespace geometry
{
@@ -62,20 +62,51 @@ struct crosses
#endif // DOXYGEN_NO_DISPATCH
+namespace resolve_strategy
+{
+
+struct crosses
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct crosses
{
- static inline bool
- apply(
- const Geometry1& geometry1,
- const Geometry2& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_strategy::crosses::apply(geometry1, geometry2, strategy);
}
};
@@ -83,12 +114,15 @@ namespace resolve_variant
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
+ template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2)
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
+ , m_strategy(strategy)
{}
template <typename Geometry1>
@@ -98,15 +132,16 @@ namespace resolve_variant
<
Geometry1,
Geometry2
- >::apply(geometry1, m_geometry2);
+ >::apply(geometry1, m_geometry2, m_strategy);
}
};
- static inline bool
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
@@ -114,12 +149,15 @@ namespace resolve_variant
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct crosses<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1)
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
+ , m_strategy(strategy)
{}
template <typename Geometry2>
@@ -129,15 +167,16 @@ namespace resolve_variant
<
Geometry1,
Geometry2
- >::apply(m_geometry1, geometry2);
+ >::apply(m_geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(Geometry1 const& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -145,8 +184,15 @@ namespace resolve_variant
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
+ template <typename Strategy>
struct visitor: static_visitor<bool>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
template <typename Geometry1, typename Geometry2>
result_type operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
@@ -155,15 +201,16 @@ namespace resolve_variant
<
Geometry1,
Geometry2
- >::apply(geometry1, geometry2);
+ >::apply(geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2)
+ template <typename Strategy>
+ static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -175,6 +222,31 @@ namespace resolve_variant
\ingroup crosses
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Crosses}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{crosses}
+\return \return_check2{crosses}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/crosses.qbk]}
+*/
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool crosses(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::crosses
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+\brief \brief_check2{crosses}
+\ingroup crosses
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{crosses}
@@ -184,7 +256,10 @@ namespace resolve_variant
template <typename Geometry1, typename Geometry2>
inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_variant::crosses
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/azimuth.hpp b/boost/geometry/algorithms/detail/azimuth.hpp
index 7e0d1691ed..a5863d7d24 100644
--- a/boost/geometry/algorithms/detail/azimuth.hpp
+++ b/boost/geometry/algorithms/detail/azimuth.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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,
@@ -23,6 +24,7 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>
namespace boost { namespace geometry
@@ -69,22 +71,9 @@ struct azimuth<ReturnType, spherical_equatorial_tag>
template <typename P1, typename P2, typename Sphere>
static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)
{
- // 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));
+ return geometry::formula::spherical_azimuth<ReturnType, false>
+ ( get_as_radian<0>(p1), get_as_radian<1>(p1),
+ get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth;
}
template <typename P1, typename P2>
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
index 8447532a6c..029053dda3 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -449,13 +453,14 @@ struct buffer_inserter<point_tag, Point, RingOutput>
}
};
-
+// Not a specialization, but called from specializations of ring and of polygon.
+// Calling code starts/finishes ring before/after apply
template
<
typename RingInput,
typename RingOutput
>
-struct buffer_inserter<ring_tag, RingInput, RingOutput>
+struct buffer_inserter_ring
{
typedef typename point_type<RingOutput>::type output_point_type;
@@ -568,6 +573,43 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
template
<
+ typename RingInput,
+ typename RingOutput
+>
+struct buffer_inserter<ring_tag, RingInput, RingOutput>
+{
+ template
+ <
+ typename Collection,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename RobustPolicy
+ >
+ static inline strategy::buffer::result_code apply(RingInput const& ring,
+ Collection& collection,
+ DistanceStrategy const& distance,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy,
+ RobustPolicy const& robust_policy)
+ {
+ collection.start_new_ring();
+ strategy::buffer::result_code const code
+ = buffer_inserter_ring<RingInput, RingOutput>::apply(ring,
+ collection, distance,
+ side_strategy, join_strategy, end_strategy, point_strategy,
+ robust_policy);
+ collection.finish_ring(code);
+ return code;
+ }
+};
+
+template
+<
typename Linestring,
typename Polygon
>
@@ -709,7 +751,7 @@ private:
typedef typename ring_type<PolygonInput>::type input_ring_type;
typedef typename ring_type<PolygonOutput>::type output_ring_type;
- typedef buffer_inserter<ring_tag, input_ring_type, output_ring_type> policy;
+ typedef buffer_inserter_ring<input_ring_type, output_ring_type> policy;
template
@@ -854,6 +896,7 @@ template
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename VisitPiecesPolicy
>
@@ -863,6 +906,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
VisitPiecesPolicy& visit_pieces_policy
)
@@ -872,9 +916,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
typedef detail::buffer::buffered_piece_collection
<
typename geometry::ring_type<GeometryOutput>::type,
+ IntersectionStrategy,
RobustPolicy
> collection_type;
- collection_type collection(robust_policy);
+ collection_type collection(intersection_strategy, robust_policy);
collection_type const& const_collection = collection;
bool const areal = boost::is_same
@@ -961,6 +1006,7 @@ template
typename JoinStrategy,
typename EndStrategy,
typename PointStrategy,
+ typename IntersectionStrategy,
typename RobustPolicy
>
inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
@@ -969,13 +1015,14 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& point_strategy,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
{
detail::buffer::visit_pieces_default_policy visitor;
buffer_inserter<GeometryOutput>(geometry_input, out,
distance_strategy, side_strategy, join_strategy,
end_strategy, point_strategy,
- robust_policy, visitor);
+ intersection_strategy, robust_policy, visitor);
}
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
index c1f04f93b5..92dcdcc7b0 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -52,6 +56,7 @@ public :
typename Rings,
typename Turns,
typename Geometry,
+ typename Strategy,
typename RobustPolicy,
typename Visitor
>
@@ -63,6 +68,7 @@ public :
detail::overlay::traverse_error_type /*traverse_error*/,
Geometry const& ,
Geometry const& ,
+ Strategy const& ,
RobustPolicy const& ,
state_type& state,
Visitor& /*visitor*/
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index e7214428e6..7fbbb790bb 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016.
-// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2017.
+// Modifications copyright (c) 2016-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -117,10 +117,13 @@ enum segment_relation_code
*/
-template <typename Ring, typename RobustPolicy>
+template <typename Ring, typename IntersectionStrategy, typename RobustPolicy>
struct buffered_piece_collection
{
- typedef buffered_piece_collection<Ring, RobustPolicy> this_type;
+ typedef buffered_piece_collection
+ <
+ Ring, IntersectionStrategy, RobustPolicy
+ > this_type;
typedef typename geometry::point_type<Ring>::type point_type;
typedef typename geometry::coordinate_type<Ring>::type coordinate_type;
@@ -303,7 +306,7 @@ struct buffered_piece_collection
cluster_type m_clusters;
-
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
struct redundant_turn
@@ -314,8 +317,10 @@ struct buffered_piece_collection
}
};
- buffered_piece_collection(RobustPolicy const& robust_policy)
+ buffered_piece_collection(IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy)
: m_first_piece_index(-1)
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
{}
@@ -512,10 +517,11 @@ struct buffered_piece_collection
geometry::partition
<
robust_box_type,
- turn_get_box, turn_in_original_ovelaps_box,
- original_get_box, original_ovelaps_box,
- include_turn_policy, detail::partition::include_all_policy
- >::apply(m_turns, robust_originals, visitor);
+ include_turn_policy,
+ detail::partition::include_all_policy
+ >::apply(m_turns, robust_originals, visitor,
+ turn_get_box(), turn_in_original_ovelaps_box(),
+ original_get_box(), original_ovelaps_box());
bool const deflate = distance_strategy.negative();
@@ -767,15 +773,17 @@ struct buffered_piece_collection
piece_vector_type,
buffered_ring_collection<buffered_ring<Ring> >,
turn_vector_type,
+ IntersectionStrategy,
RobustPolicy
- > visitor(m_pieces, offsetted_rings, m_turns, m_robust_policy);
+ > visitor(m_pieces, offsetted_rings, m_turns,
+ m_intersection_strategy, m_robust_policy);
geometry::partition
<
- robust_box_type,
- detail::section::get_section_box,
- detail::section::overlaps_section_box
- >::apply(monotonic_sections, visitor);
+ robust_box_type
+ >::apply(monotonic_sections, visitor,
+ detail::section::get_section_box(),
+ detail::section::overlaps_section_box());
}
insert_rescaled_piece_turns();
@@ -795,10 +803,10 @@ struct buffered_piece_collection
geometry::partition
<
- robust_box_type,
- turn_get_box, turn_ovelaps_box,
- piece_get_box, piece_ovelaps_box
- >::apply(m_turns, m_pieces, visitor);
+ robust_box_type
+ >::apply(m_turns, m_pieces, visitor,
+ turn_get_box(), turn_ovelaps_box(),
+ piece_get_box(), piece_ovelaps_box());
}
}
@@ -1354,7 +1362,8 @@ struct buffered_piece_collection
traversed_rings.clear();
buffer_overlay_visitor visitor;
traverser::apply(offsetted_rings, offsetted_rings,
- m_robust_policy, m_turns, traversed_rings,
+ m_intersection_strategy, m_robust_policy,
+ m_turns, traversed_rings,
m_clusters, visitor);
}
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
index 3425ee6ffd..178c7bcafe 100644
--- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -62,6 +66,7 @@ template
typename Pieces,
typename Rings,
typename Turns,
+ typename IntersectionStrategy,
typename RobustPolicy
>
class piece_turn_visitor
@@ -69,6 +74,7 @@ class piece_turn_visitor
Pieces const& m_pieces;
Rings const& m_rings;
Turns& m_turns;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
template <typename Piece>
@@ -243,7 +249,9 @@ class piece_turn_visitor
turn_policy::apply(*prev1, *it1, *next1,
*prev2, *it2, *next2,
false, false, false, false,
- the_model, m_robust_policy,
+ the_model,
+ m_intersection_strategy,
+ m_robust_policy,
std::back_inserter(m_turns));
}
}
@@ -254,10 +262,12 @@ public:
piece_turn_visitor(Pieces const& pieces,
Rings const& ring_collection,
Turns& turns,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
: m_pieces(pieces)
, m_rings(ring_collection)
, m_turns(turns)
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
{}
diff --git a/boost/geometry/algorithms/detail/calculate_sum.hpp b/boost/geometry/algorithms/detail/calculate_sum.hpp
index b23e70171b..732a2f5753 100644
--- a/boost/geometry/algorithms/detail/calculate_sum.hpp
+++ b/boost/geometry/algorithms/detail/calculate_sum.hpp
@@ -8,6 +8,10 @@
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2016.
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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)
@@ -30,7 +34,7 @@ class calculate_polygon_sum
template <typename ReturnType, typename Policy, typename Rings, typename Strategy>
static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
{
- ReturnType sum = ReturnType();
+ ReturnType sum = ReturnType(0);
for (typename boost::range_iterator<Rings const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
diff --git a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
index 284858a130..664c995384 100644
--- a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -39,15 +39,45 @@ namespace detail { namespace disjoint
{
-template<typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct check_each_ring_for_within_call_covered_by
+{
+ /*!
+ \tparam Strategy point_in_geometry strategy
+ */
+ template <typename Point, typename Strategy>
+ static inline bool apply(Point const& p, Geometry const& g, Strategy const& strategy)
+ {
+ return geometry::covered_by(p, g, strategy);
+ }
+};
+
+template <typename Geometry>
+struct check_each_ring_for_within_call_covered_by<Geometry, box_tag>
+{
+ template <typename Point, typename Strategy>
+ static inline bool apply(Point const& p, Geometry const& g, Strategy const& )
+ {
+ return geometry::covered_by(p, g);
+ }
+};
+
+
+/*!
+\tparam Strategy point_in_geometry strategy
+*/
+template<typename Geometry, typename Strategy>
struct check_each_ring_for_within
{
bool not_disjoint;
Geometry const& m_geometry;
+ Strategy const& m_strategy;
- inline check_each_ring_for_within(Geometry const& g)
+ inline check_each_ring_for_within(Geometry const& g,
+ Strategy const& strategy)
: not_disjoint(false)
, m_geometry(g)
+ , m_strategy(strategy)
{}
template <typename Range>
@@ -56,17 +86,26 @@ struct check_each_ring_for_within
typename point_type<Range>::type pt;
not_disjoint = not_disjoint
|| ( geometry::point_on_border(pt, range)
- && geometry::covered_by(pt, m_geometry) );
+ && check_each_ring_for_within_call_covered_by
+ <
+ Geometry
+ >::apply(pt, m_geometry, m_strategy) );
}
};
-
-template <typename FirstGeometry, typename SecondGeometry>
+/*!
+\tparam Strategy point_in_geometry strategy
+*/
+template <typename FirstGeometry, typename SecondGeometry, typename Strategy>
inline bool rings_containing(FirstGeometry const& geometry1,
- SecondGeometry const& geometry2)
+ SecondGeometry const& geometry2,
+ Strategy const& strategy)
{
- check_each_ring_for_within<FirstGeometry> checker(geometry1);
+ check_each_ring_for_within
+ <
+ FirstGeometry, Strategy
+ > checker(geometry1, strategy);
geometry::detail::for_each_range(geometry2, checker);
return checker.not_disjoint;
}
@@ -76,10 +115,15 @@ inline bool rings_containing(FirstGeometry const& geometry1,
template <typename Geometry1, typename Geometry2>
struct general_areal
{
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ /*!
+ \tparam Strategy relate (segments intersection) strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2) )
+ if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy) )
{
return false;
}
@@ -90,8 +134,10 @@ struct general_areal
// 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) )
+ if ( rings_containing(geometry1, geometry2,
+ strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>())
+ || rings_containing(geometry2, geometry1,
+ strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>()) )
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
index 3b81755e20..f830f8161c 100644
--- a/boost/geometry/algorithms/detail/disjoint/box_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2016.
-// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -52,6 +52,12 @@ template
>
struct box_box
{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
+ {
+ return apply(box1, box2);
+ }
+
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
@@ -84,6 +90,12 @@ struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag>
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
+ {
+ return apply(box1, box2);
+ }
+
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
typedef typename geometry::select_most_precise
diff --git a/boost/geometry/algorithms/detail/disjoint/interface.hpp b/boost/geometry/algorithms/detail/disjoint/interface.hpp
index ce7fe6d45c..64898e35fe 100644
--- a/boost/geometry/algorithms/detail/disjoint/interface.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/interface.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -27,43 +27,51 @@
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry
{
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
+namespace resolve_strategy
{
-
-// If reversal is needed, perform it
-template
-<
- typename Geometry1, typename Geometry2,
- std::size_t DimensionCount,
- typename Tag1, typename Tag2
->
-struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true>
+struct disjoint
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return disjoint
+ return dispatch::disjoint
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::disjoint::services::default_strategy
<
- Geometry2, Geometry1,
- DimensionCount,
- Tag2, Tag1
- >::apply(g2, g1);
+ Geometry1, Geometry2
+ >::type strategy_type;
+
+ return dispatch::disjoint
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
}
};
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
+} // namespace resolve_strategy
namespace resolve_variant {
@@ -71,7 +79,8 @@ namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct disjoint
{
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions
<
@@ -79,88 +88,135 @@ struct disjoint
Geometry2 const
>();
- return dispatch::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct disjoint<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2): m_geometry2(geometry2) {}
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
- return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
+ return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct disjoint<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1): m_geometry1(geometry1) {}
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_strategy(strategy)
+ {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
- return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2);
+ return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
-template <
+template
+<
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
-struct disjoint<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+struct disjoint
+ <
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+ >
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
- return disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
+/*!
+\brief \brief_check2{are disjoint}
+\ingroup disjoint
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Disjoint}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{disjoint}
+\return \return_check2{are disjoint}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/disjoint.qbk]}
+*/
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool disjoint(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::disjoint
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
/*!
\brief \brief_check2{are disjoint}
@@ -177,7 +233,10 @@ template <typename Geometry1, typename Geometry2>
inline bool disjoint(Geometry1 const& geometry1,
Geometry2 const& geometry2)
{
- return resolve_variant::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_variant::disjoint
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
index 6a48b684a1..e6077d3e7f 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -61,19 +61,28 @@ template <typename Geometry1, typename Geometry2,
typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>
struct disjoint_no_intersections_policy
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ /*!
+ \tparam Strategy point_in_geometry strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
typedef typename point_type<Geometry1>::type point1_type;
point1_type p;
geometry::point_on_border(p, g1);
- return !geometry::covered_by(p, g2);
+
+ return !geometry::covered_by(p, g2, strategy);
}
};
template <typename Geometry1, typename Geometry2, typename Tag1>
struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ /*!
+ \tparam Strategy point_in_geometry strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// TODO: use partition or rtree on g2
typedef typename boost::range_iterator<Geometry1 const>::type iterator;
@@ -81,7 +90,7 @@ struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
{
typedef typename boost::range_value<Geometry1 const>::type value_type;
if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
- ::apply(*it, g2) )
+ ::apply(*it, g2, strategy) )
{
return false;
}
@@ -96,15 +105,21 @@ template<typename Geometry1, typename Geometry2,
= disjoint_no_intersections_policy<Geometry1, Geometry2> >
struct disjoint_linear_areal
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ /*!
+ \tparam Strategy relate (segments intersection) strategy
+ */
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// if there are intersections - return false
- if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2) )
+ if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2, strategy) )
{
return false;
}
- return NoIntersectionsPolicy::apply(g1, g2);
+ return NoIntersectionsPolicy
+ ::apply(g1, g2,
+ strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>());
}
};
@@ -126,16 +141,18 @@ template <typename Segment, typename Polygon>
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
{
private:
- template <typename InteriorRings>
+ template <typename InteriorRings, typename Strategy>
static inline
bool check_interior_rings(InteriorRings const& interior_rings,
- Segment const& segment)
+ Segment const& segment,
+ Strategy const& strategy)
{
typedef typename boost::range_value<InteriorRings>::type ring_type;
typedef unary_disjoint_geometry_to_query_geometry
<
Segment,
+ Strategy,
disjoint_range_segment_or_box
<
ring_type, closure<ring_type>::value, Segment
@@ -147,24 +164,27 @@ private:
unary_predicate_type
>::apply(boost::begin(interior_rings),
boost::end(interior_rings),
- unary_predicate_type(segment));
+ unary_predicate_type(segment, strategy));
}
public:
- static inline bool apply(Segment const& segment, Polygon const& polygon)
+ template <typename IntersectionStrategy>
+ static inline bool apply(Segment const& segment,
+ Polygon const& polygon,
+ IntersectionStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring;
if ( !disjoint_range_segment_or_box
<
ring, closure<Polygon>::value, Segment
- >::apply(geometry::exterior_ring(polygon), segment) )
+ >::apply(geometry::exterior_ring(polygon), segment, strategy) )
{
return false;
}
- if ( !check_interior_rings(geometry::interior_rings(polygon), segment) )
+ if ( !check_interior_rings(geometry::interior_rings(polygon), segment, strategy) )
{
return false;
}
@@ -172,7 +192,8 @@ public:
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
- return !geometry::covered_by(p, polygon);
+ return !geometry::covered_by(p, polygon,
+ strategy.template get_point_in_geometry_strategy<Segment, Polygon>());
}
};
@@ -180,13 +201,14 @@ public:
template <typename Segment, typename MultiPolygon>
struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
{
- static inline
- bool apply(Segment const& segment, MultiPolygon const& multipolygon)
+ template <typename IntersectionStrategy>
+ static inline bool apply(Segment const& segment, MultiPolygon const& multipolygon,
+ IntersectionStrategy const& strategy)
{
return multirange_constant_size_geometry
<
MultiPolygon, Segment
- >::apply(multipolygon, segment);
+ >::apply(multipolygon, segment, strategy);
}
};
@@ -194,20 +216,24 @@ struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
template <typename Segment, typename Ring>
struct disjoint_segment_areal<Segment, Ring, ring_tag>
{
- static inline bool apply(Segment const& segment, Ring const& ring)
+ template <typename IntersectionStrategy>
+ static inline bool apply(Segment const& segment,
+ Ring const& ring,
+ IntersectionStrategy const& strategy)
{
if ( !disjoint_range_segment_or_box
<
Ring, closure<Ring>::value, Segment
- >::apply(ring, segment) )
+ >::apply(ring, segment, strategy) )
{
return false;
}
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
-
- return !geometry::covered_by(p, ring);
+
+ return !geometry::covered_by(p, ring,
+ strategy.template get_point_in_geometry_strategy<Segment, Ring>());
}
};
@@ -231,14 +257,15 @@ struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false>
template <typename Areal, typename Linear>
struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
-{
- static inline
- bool apply(Areal const& areal, Linear const& linear)
+{
+ template <typename Strategy>
+ static inline bool apply(Areal const& areal, Linear const& linear,
+ Strategy const& strategy)
{
return detail::disjoint::disjoint_linear_areal
<
Linear, Areal
- >::apply(linear, areal);
+ >::apply(linear, areal, strategy);
}
};
@@ -246,12 +273,14 @@ struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
template <typename Areal, typename Segment>
struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false>
{
- static inline bool apply(Areal const& g1, Segment const& g2)
+ template <typename Strategy>
+ static inline bool apply(Areal const& g1, Segment const& g2,
+ Strategy const& strategy)
{
return detail::disjoint::disjoint_segment_areal
<
Segment, Areal
- >::apply(g2, g1);
+ >::apply(g2, g1, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
index 91f985edb8..989b8df247 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -53,7 +53,9 @@ namespace detail { namespace disjoint
template <typename Segment1, typename Segment2>
struct disjoint_segment
{
- static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)
+ template <typename Strategy>
+ static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
+ Strategy const& strategy)
{
typedef typename point_type<Segment1>::type point_type;
@@ -62,23 +64,23 @@ struct disjoint_segment
rescale_policy_type robust_policy;
typedef segment_intersection_points
- <
- point_type,
- typename segment_ratio_type
+ <
+ point_type,
+ typename segment_ratio_type
<
point_type,
rescale_policy_type
>::type
- > intersection_return_type;
+ > intersection_return_type;
- intersection_return_type is
- = strategy::intersection::relate_cartesian_segments
+ typedef policies::relate::segments_intersection_points
<
- policies::relate::segments_intersection_points
- <
- intersection_return_type
- >
- >::apply(segment1, segment2, robust_policy);
+ intersection_return_type
+ > intersection_policy;
+
+ intersection_return_type is = strategy.apply(segment1, segment2,
+ intersection_policy(),
+ robust_policy);
return is.count == 0;
}
@@ -109,8 +111,10 @@ struct assign_disjoint_policy
template <typename Geometry1, typename Geometry2>
struct disjoint_linear
{
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::no_rescale_policy rescale_policy_type;
@@ -147,7 +151,7 @@ struct disjoint_linear
Geometry1, Geometry2, assign_disjoint_policy
>
>::apply(0, geometry1, 1, geometry2,
- rescale_policy_type(), turns, interrupt_policy);
+ strategy, rescale_policy_type(), turns, interrupt_policy);
return !interrupt_policy.has_intersections;
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
index 8d82f7c911..b4c71c8f30 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
@@ -53,8 +53,10 @@ template
>
struct disjoint_range_segment_or_box
{
- static inline
- bool apply(Range const& range, SegmentOrBox const& segment_or_box)
+ template <typename Strategy>
+ static inline bool apply(Range const& range,
+ SegmentOrBox const& segment_or_box,
+ Strategy const& strategy)
{
typedef typename closeable_view<Range const, Closure>::type view_type;
@@ -85,7 +87,8 @@ struct disjoint_range_segment_or_box
<
point_type, SegmentOrBox
>::apply(geometry::range::front<view_type const>(view),
- segment_or_box);
+ segment_or_box,
+ strategy.template get_point_in_geometry_strategy<Range, SegmentOrBox>());
}
else
{
@@ -99,7 +102,7 @@ struct disjoint_range_segment_or_box
if ( !dispatch::disjoint
<
range_segment, SegmentOrBox
- >::apply(rng_segment, segment_or_box) )
+ >::apply(rng_segment, segment_or_box, strategy) )
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
index 29e438e546..7c1a93cdb7 100644
--- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -14,8 +15,10 @@
#include <vector>
#include <boost/range.hpp>
+#include <boost/mpl/assert.hpp>
#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -105,36 +108,74 @@ template <typename MultiPoint, typename Linear>
class multipoint_linear
{
private:
- // structs for partition -- start
- struct expand_box
+ struct expand_box_point
{
- template <typename Box, typename Geometry>
- static inline void apply(Box& total, Geometry const& geometry)
+ template <typename Box, typename Point>
+ static inline void apply(Box& total, Point const& point)
{
- geometry::expand(total, geometry::return_envelope<Box>(geometry));
+ geometry::expand(total, point);
}
+ };
+ // TODO: After adding non-cartesian Segment envelope to the library
+ // this policy should be modified to take envelope strategy.
+ struct expand_box_segment
+ {
+ template <typename Box, typename Segment>
+ static inline void apply(Box& total, Segment const& segment)
+ {
+ geometry::expand(total, geometry::return_envelope<Box>(segment));
+ }
};
- struct overlaps_box
+ struct overlaps_box_point
{
- template <typename Box, typename Geometry>
- static inline bool apply(Box const& box, Geometry const& geometry)
+ template <typename Box, typename Point>
+ static inline bool apply(Box const& box, Point const& point)
{
- return ! dispatch::disjoint<Geometry, Box>::apply(geometry, box);
+ // The default strategy is enough in this case
+ typedef typename strategy::disjoint::services::default_strategy
+ <
+ Point, Box
+ >::type strategy_type;
+ return ! dispatch::disjoint<Point, Box>::apply(point, box, strategy_type());
}
};
+ // TODO: After implementing disjoint Segment/Box for non-cartesian geometries
+ // this strategy should be passed here.
+ // TODO: This Segment/Box strategy should somehow be derived from Point/Segment strategy
+ // which by default is winding containing CS-specific side strategy
+ // TODO: disjoint Segment/Box will be called in this case which may take
+ // quite long in non-cartesian CS. So we should consider passing range of bounding boxes
+ // of segments after calculating them once.
+ struct overlaps_box_segment
+ {
+ template <typename Box, typename Segment>
+ static inline bool apply(Box const& box, Segment const& segment)
+ {
+ typedef typename strategy::disjoint::services::default_strategy
+ <
+ Segment, Box
+ >::type strategy_type;
+ return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type());
+ }
+ };
+
+ template <typename PtSegStrategy>
class item_visitor_type
{
public:
- item_visitor_type() : m_intersection_found(false) {}
+ item_visitor_type(PtSegStrategy const& strategy)
+ : m_intersection_found(false)
+ , m_strategy(strategy)
+ {}
template <typename Item1, typename Item2>
inline void apply(Item1 const& item1, Item2 const& item2)
{
if (! m_intersection_found
- && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2))
+ && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
{
m_intersection_found = true;
}
@@ -144,6 +185,7 @@ private:
private:
bool m_intersection_found;
+ PtSegStrategy const& m_strategy;
};
// structs for partition -- end
@@ -172,23 +214,25 @@ private:
};
public:
- static inline bool apply(MultiPoint const& multipoint, Linear const& linear)
+ template <typename Strategy>
+ static inline bool apply(MultiPoint const& multipoint, Linear const& linear, Strategy const& strategy)
{
- item_visitor_type visitor;
+ item_visitor_type<Strategy> visitor(strategy);
geometry::partition
<
- geometry::model::box<typename point_type<MultiPoint>::type>,
- expand_box,
- overlaps_box
- >::apply(multipoint, segment_range(linear), visitor);
+ geometry::model::box<typename point_type<MultiPoint>::type>
+ >::apply(multipoint, segment_range(linear), visitor,
+ expand_box_point(), overlaps_box_point(),
+ expand_box_segment(), overlaps_box_segment());
return ! visitor.intersection_found();
}
- static inline bool apply(Linear const& linear, MultiPoint const& multipoint)
+ template <typename Strategy>
+ static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy)
{
- return apply(multipoint, linear);
+ return apply(multipoint, linear, strategy);
}
};
@@ -240,8 +284,10 @@ struct disjoint
multi_point_tag, multi_point_tag, false
>
{
+ template <typename Strategy>
static inline bool apply(MultiPoint1 const& multipoint1,
- MultiPoint2 const& multipoint2)
+ MultiPoint2 const& multipoint2,
+ Strategy const& )
{
if ( boost::size(multipoint2) < boost::size(multipoint1) )
{
diff --git a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
index 78a683e46e..53fb1642af 100644
--- a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -25,34 +26,40 @@ namespace detail { namespace disjoint
{
-template <typename Geometry, typename BinaryPredicate>
+template <typename Geometry, typename Strategy, typename BinaryPredicate>
class unary_disjoint_geometry_to_query_geometry
{
public:
- unary_disjoint_geometry_to_query_geometry(Geometry const& geometry)
+ unary_disjoint_geometry_to_query_geometry(Geometry const& geometry,
+ Strategy const& strategy)
: m_geometry(geometry)
+ , m_strategy(strategy)
{}
template <typename QueryGeometry>
inline bool apply(QueryGeometry const& query_geometry) const
{
- return BinaryPredicate::apply(query_geometry, m_geometry);
+ return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy);
}
private:
Geometry const& m_geometry;
+ Strategy const& m_strategy;
};
template<typename MultiRange, typename ConstantSizeGeometry>
struct multirange_constant_size_geometry
{
+ template <typename Strategy>
static inline bool apply(MultiRange const& multirange,
- ConstantSizeGeometry const& constant_size_geometry)
+ ConstantSizeGeometry const& constant_size_geometry,
+ Strategy const& strategy)
{
typedef unary_disjoint_geometry_to_query_geometry
<
ConstantSizeGeometry,
+ Strategy,
dispatch::disjoint
<
typename boost::range_value<MultiRange>::type,
@@ -64,13 +71,15 @@ struct multirange_constant_size_geometry
<
unary_predicate_type
>::apply(boost::begin(multirange), boost::end(multirange),
- unary_predicate_type(constant_size_geometry));
+ unary_predicate_type(constant_size_geometry, strategy));
}
+ template <typename Strategy>
static inline bool apply(ConstantSizeGeometry const& constant_size_geometry,
- MultiRange const& multirange)
+ MultiRange const& multirange,
+ Strategy const& strategy)
{
- return apply(multirange, constant_size_geometry);
+ return apply(multirange, constant_size_geometry, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
index 2f1085ada9..2e6773d221 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
-// This file was modified by Oracle on 2013-2016.
-// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -28,7 +28,7 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
-#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry
{
@@ -44,13 +44,13 @@ namespace detail { namespace disjoint
template <typename Point, typename Box>
inline bool disjoint_point_box(Point const& point, Box const& box)
{
+ typedef typename strategy::disjoint::services::default_strategy
+ <
+ Point, Box
+ >::type strategy_type;
+
// ! covered_by(point, box)
- return ! strategy::within::relate_point_box_loop
- <
- strategy::within::covered_by_range,
- Point, Box,
- 0, dimension<Point>::type::value
- >::apply(point, box);
+ return ! strategy_type::apply(point, box);
}
@@ -66,15 +66,11 @@ namespace dispatch
template <typename Point, typename Box, std::size_t DimensionCount>
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
{
- static inline bool apply(Point const& point, Box const& box)
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& )
{
// ! covered_by(point, box)
- return ! strategy::within::relate_point_box_loop
- <
- strategy::within::covered_by_range,
- Point, Box,
- 0, DimensionCount
- >::apply(point, box);
+ return ! Strategy::apply(point, box);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
index 9ae43f73d0..66bd7c26ce 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
@@ -39,11 +39,12 @@ namespace detail { namespace disjoint
struct reverse_covered_by
{
- template <typename Geometry1, typename Geometry2>
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return ! geometry::covered_by(geometry1, geometry2);
+ return ! geometry::covered_by(geometry1, geometry2, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/boost/geometry/algorithms/detail/disjoint/point_point.hpp
index 7580b7287b..13ac34d718 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_point.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_point.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -59,6 +59,12 @@ namespace detail { namespace disjoint
template <std::size_t Dimension, std::size_t DimensionCount>
struct point_point_generic
{
+ template <typename Point1, typename Point2, typename Strategy>
+ static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& )
+ {
+ return apply(p1, p2);
+ }
+
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
@@ -75,7 +81,7 @@ template <std::size_t DimensionCount>
struct point_point_generic<DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
- static inline bool apply(Point1 const&, Point2 const&)
+ static inline bool apply(Point1 const&, Point2 const& )
{
return false;
}
@@ -135,6 +141,12 @@ private:
};
public:
+ template <typename Point1, typename Point2, typename Strategy>
+ static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
+ {
+ return apply(point1, point2);
+ }
+
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
index cc0c7949e3..c2741ce72c 100644
--- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -22,19 +22,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
#include <cstddef>
-#include <utility>
-#include <boost/numeric/conversion/cast.hpp>
-
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/calculation_type.hpp>
-
-#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/core/point_type.hpp>
-
-#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
@@ -47,236 +36,19 @@ namespace boost { namespace geometry
namespace detail { namespace disjoint
{
-
-template <std::size_t I>
-struct compute_tmin_tmax_per_dim
-{
- template <typename SegmentPoint, typename Box, typename RelativeDistance>
- static inline void apply(SegmentPoint const& p0,
- SegmentPoint const& p1,
- Box const& box,
- RelativeDistance& ti_min,
- RelativeDistance& ti_max,
- RelativeDistance& diff)
- {
- typedef typename coordinate_type<Box>::type box_coordinate_type;
- typedef typename coordinate_type
- <
- SegmentPoint
- >::type point_coordinate_type;
-
- RelativeDistance c_p0 = boost::numeric_cast
- <
- point_coordinate_type
- >( geometry::get<I>(p0) );
-
- RelativeDistance c_p1 = boost::numeric_cast
- <
- point_coordinate_type
- >( geometry::get<I>(p1) );
-
- RelativeDistance c_b_min = boost::numeric_cast
- <
- box_coordinate_type
- >( geometry::get<geometry::min_corner, I>(box) );
-
- RelativeDistance c_b_max = boost::numeric_cast
- <
- box_coordinate_type
- >( geometry::get<geometry::max_corner, I>(box) );
-
- if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
- {
- diff = c_p1 - c_p0;
- ti_min = c_b_min - c_p0;
- ti_max = c_b_max - c_p0;
- }
- else
- {
- diff = c_p0 - c_p1;
- ti_min = c_p0 - c_b_max;
- ti_max = c_p0 - c_b_min;
- }
- }
-};
-
-
-template
-<
- typename RelativeDistance,
- typename SegmentPoint,
- typename Box,
- std::size_t I,
- std::size_t Dimension
->
-struct disjoint_segment_box_impl
-{
- template <typename RelativeDistancePair>
- static inline bool apply(SegmentPoint const& p0,
- SegmentPoint const& p1,
- Box const& box,
- RelativeDistancePair& t_min,
- RelativeDistancePair& t_max)
- {
- RelativeDistance ti_min, ti_max, diff;
-
- compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
-
- if ( geometry::math::equals(diff, 0) )
- {
- if ( (geometry::math::equals(t_min.second, 0)
- && t_min.first > ti_max)
- ||
- (geometry::math::equals(t_max.second, 0)
- && t_max.first < ti_min)
- ||
- (math::sign(ti_min) * math::sign(ti_max) > 0) )
- {
- return true;
- }
- }
-
- RelativeDistance t_min_x_diff = t_min.first * diff;
- RelativeDistance t_max_x_diff = t_max.first * diff;
-
- if ( t_min_x_diff > ti_max * t_min.second
- || t_max_x_diff < ti_min * t_max.second )
- {
- return true;
- }
-
- if ( ti_min * t_min.second > t_min_x_diff )
- {
- t_min.first = ti_min;
- t_min.second = diff;
- }
- if ( ti_max * t_max.second < t_max_x_diff )
- {
- t_max.first = ti_max;
- t_max.second = diff;
- }
-
- if ( t_min.first > t_min.second || t_max.first < 0 )
- {
- return true;
- }
-
- return disjoint_segment_box_impl
- <
- RelativeDistance,
- SegmentPoint,
- Box,
- I + 1,
- Dimension
- >::apply(p0, p1, box, t_min, t_max);
- }
-};
-
-
-template
-<
- typename RelativeDistance,
- typename SegmentPoint,
- typename Box,
- std::size_t Dimension
->
-struct disjoint_segment_box_impl
- <
- RelativeDistance, SegmentPoint, Box, 0, Dimension
- >
-{
- static inline bool apply(SegmentPoint const& p0,
- SegmentPoint const& p1,
- Box const& box)
- {
- std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
- RelativeDistance diff;
-
- compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
- t_min.first, t_max.first, diff);
-
- if ( geometry::math::equals(diff, 0) )
- {
- if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
- if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
-
- if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
- {
- return true;
- }
- }
-
- if ( t_min.first > diff || t_max.first < 0 )
- {
- return true;
- }
-
- t_min.second = t_max.second = diff;
-
- return disjoint_segment_box_impl
- <
- RelativeDistance, SegmentPoint, Box, 1, Dimension
- >::apply(p0, p1, box, t_min, t_max);
- }
-};
-
-
-template
-<
- typename RelativeDistance,
- typename SegmentPoint,
- typename Box,
- std::size_t Dimension
->
-struct disjoint_segment_box_impl
- <
- RelativeDistance, SegmentPoint, Box, Dimension, Dimension
- >
-{
- template <typename RelativeDistancePair>
- static inline bool apply(SegmentPoint const&, SegmentPoint const&,
- Box const&,
- RelativeDistancePair&, RelativeDistancePair&)
- {
- return false;
- }
-};
-
-
-//=========================================================================
-
-
-template <typename Segment, typename Box>
struct disjoint_segment_box
-{
- static inline bool apply(Segment const& segment, Box const& box)
+{
+ template <typename Segment, typename Box, typename Strategy>
+ static inline bool apply(Segment const& segment, Box const& box, Strategy const& strategy)
{
- assert_dimension_equal<Segment, Box>();
-
- typedef typename util::calculation_type::geometric::binary
- <
- Segment, Box, void
- >::type relative_distance_type;
-
- typedef typename point_type<Segment>::type segment_point_type;
- segment_point_type p0, p1;
- geometry::detail::assign_point_from_index<0>(segment, p0);
- geometry::detail::assign_point_from_index<1>(segment, p1);
-
- return disjoint_segment_box_impl
- <
- relative_distance_type, segment_point_type, Box,
- 0, dimension<Box>::value
- >::apply(p0, p1, box);
+ return strategy.apply(segment, box);
}
};
-
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
-
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
@@ -284,7 +56,7 @@ namespace dispatch
template <typename Segment, typename Box, std::size_t DimensionCount>
struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
- : detail::disjoint::disjoint_segment_box<Segment, Box>
+ : detail::disjoint::disjoint_segment_box
{};
diff --git a/boost/geometry/algorithms/detail/envelope/box.hpp b/boost/geometry/algorithms/detail/envelope/box.hpp
index 3790262948..795f51392e 100644
--- a/boost/geometry/algorithms/detail/envelope/box.hpp
+++ b/boost/geometry/algorithms/detail/envelope/box.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -97,8 +98,10 @@ struct envelope_indexed_box_on_spheroid
struct envelope_box
{
- template<typename BoxIn, typename BoxOut>
- static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ template<typename BoxIn, typename BoxOut, typename Strategy>
+ static inline void apply(BoxIn const& box_in,
+ BoxOut& mbr,
+ Strategy const&)
{
envelope_indexed_box
<
@@ -115,8 +118,10 @@ struct envelope_box
struct envelope_box_on_spheroid
{
- template <typename BoxIn, typename BoxOut>
- static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ template <typename BoxIn, typename BoxOut, typename Strategy>
+ static inline void apply(BoxIn const& box_in,
+ BoxOut& mbr,
+ Strategy const&)
{
BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
diff --git a/boost/geometry/algorithms/detail/envelope/implementation.hpp b/boost/geometry/algorithms/detail/envelope/implementation.hpp
index c1dbf8e589..d549700791 100644
--- a/boost/geometry/algorithms/detail/envelope/implementation.hpp
+++ b/boost/geometry/algorithms/detail/envelope/implementation.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -45,8 +46,8 @@ namespace detail { namespace envelope
struct envelope_polygon
{
- template <typename Polygon, typename Box>
- static inline void apply(Polygon const& polygon, Box& mbr)
+ template <typename Polygon, typename Box, typename Strategy>
+ static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
{
typename ring_return_type<Polygon const>::type ext_ring
= exterior_ring(polygon);
@@ -57,12 +58,12 @@ struct envelope_polygon
envelope_multi_range
<
envelope_range
- >::apply(interior_rings(polygon), mbr);
+ >::apply(interior_rings(polygon), mbr, strategy);
}
else
{
// otherwise, consider only the exterior ring
- envelope_range::apply(ext_ring, mbr);
+ envelope_range::apply(ext_ring, mbr, strategy);
}
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp
index befe4e42db..8e9c35b395 100644
--- a/boost/geometry/algorithms/detail/envelope/interface.hpp
+++ b/boost/geometry/algorithms/detail/envelope/interface.hpp
@@ -4,10 +4,12 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016, 2017.
+// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// 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.
@@ -27,54 +29,124 @@
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
namespace boost { namespace geometry
{
-namespace resolve_variant
+namespace resolve_strategy
{
template <typename Geometry>
struct envelope
{
+ template <typename Box, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ Strategy const& strategy)
+ {
+ dispatch::envelope<Geometry>::apply(geometry, box, strategy);
+ }
+
template <typename Box>
- static inline void apply(Geometry const& geometry, Box& box)
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ default_strategy)
+ {
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<point_type>::type coordinate_type;
+
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ coordinate_type
+ >::type strategy_type;
+
+ dispatch::envelope<Geometry>::apply(geometry, box, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+namespace resolve_variant
+{
+
+template <typename Geometry>
+struct envelope
+{
+ template <typename Box, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ Strategy const& strategy)
{
concepts::check<Geometry const>();
concepts::check<Box>();
- dispatch::envelope<Geometry>::apply(geometry, box);
+ resolve_strategy::envelope<Geometry>::apply(geometry, box, strategy);
}
};
+
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Box>
+ template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Box& m_box;
+ Strategy const& m_strategy;
- visitor(Box& box): m_box(box) {}
+ visitor(Box& box, Strategy const& strategy)
+ : m_box(box)
+ , m_strategy(strategy)
+ {}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
- envelope<Geometry>::apply(geometry, m_box);
+ envelope<Geometry>::apply(geometry, m_box, m_strategy);
}
};
- template <typename Box>
+ template <typename Box, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Box& box)
+ Box& box,
+ Strategy const& strategy)
{
- boost::apply_visitor(visitor<Box>(box), geometry);
+ boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry);
}
};
} // namespace resolve_variant
+/*!
+\brief \brief_calc{envelope (with strategy)}
+\ingroup envelope
+\details \details_calc{envelope,\det_envelope}.
+\tparam Geometry \tparam_geometry
+\tparam Box \tparam_box
+\tparam Strategy \tparam_strategy{Envelope}
+\param geometry \param_geometry
+\param mbr \param_box \param_set{envelope}
+\param strategy \param_strategy{envelope}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[envelope] [envelope_output]
+}
+*/
+template<typename Geometry, typename Box, typename Strategy>
+inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
+{
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+}
/*!
\brief \brief_calc{envelope}
@@ -94,7 +166,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template<typename Geometry, typename Box>
inline void envelope(Geometry const& geometry, Box& mbr)
{
- resolve_variant::envelope<Geometry>::apply(geometry, mbr);
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
}
@@ -104,6 +176,32 @@ inline void envelope(Geometry const& geometry, Box& mbr)
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
\tparam Box \tparam_box
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Envelope}
+\param geometry \param_geometry
+\param strategy \param_strategy{envelope}
+\return \return_calc{envelope}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[return_envelope] [return_envelope_output]
+}
+*/
+template<typename Box, typename Geometry, typename Strategy>
+inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
+{
+ Box mbr;
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+ return mbr;
+}
+
+/*!
+\brief \brief_calc{envelope}
+\ingroup envelope
+\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
+\tparam Box \tparam_box
+\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_calc{envelope}
@@ -117,7 +215,7 @@ template<typename Box, typename Geometry>
inline Box return_envelope(Geometry const& geometry)
{
Box mbr;
- resolve_variant::envelope<Geometry>::apply(geometry, mbr);
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
return mbr;
}
diff --git a/boost/geometry/algorithms/detail/envelope/linear.hpp b/boost/geometry/algorithms/detail/envelope/linear.hpp
index 49c3cf3135..09d8a76da5 100644
--- a/boost/geometry/algorithms/detail/envelope/linear.hpp
+++ b/boost/geometry/algorithms/detail/envelope/linear.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -36,12 +37,15 @@ namespace detail { namespace envelope
struct envelope_linestring_on_spheroid
{
- template <typename Linestring, typename Box>
- static inline void apply(Linestring const& linestring, Box& mbr)
+ template <typename Linestring, typename Box, typename Strategy>
+ static inline void apply(Linestring const& linestring,
+ Box& mbr,
+ Strategy const& strategy)
{
envelope_range::apply(geometry::segments_begin(linestring),
geometry::segments_end(linestring),
- mbr);
+ mbr,
+ strategy);
}
};
@@ -65,6 +69,11 @@ struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
: detail::envelope::envelope_linestring_on_spheroid
{};
+template <typename Linestring>
+struct envelope<Linestring, linestring_tag, geographic_tag>
+ : detail::envelope::envelope_linestring_on_spheroid
+{};
+
template <typename MultiLinestring, typename CS_Tag>
struct envelope
@@ -86,6 +95,15 @@ struct envelope
>
{};
+template <typename MultiLinestring>
+struct envelope
+ <
+ MultiLinestring, multi_linestring_tag, geographic_tag
+ > : detail::envelope::envelope_multi_range_on_spheroid
+ <
+ detail::envelope::envelope_linestring_on_spheroid
+ >
+{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/boost/geometry/algorithms/detail/envelope/multipoint.hpp
index 210debfdba..efee4701c9 100644
--- a/boost/geometry/algorithms/detail/envelope/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/envelope/multipoint.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -226,8 +227,8 @@ private:
}
public:
- template <typename MultiPoint, typename Box>
- static inline void apply(MultiPoint const& multipoint, Box& mbr)
+ template <typename MultiPoint, typename Box, typename Strategy>
+ static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy)
{
typedef typename point_type<MultiPoint>::type point_type;
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
@@ -255,7 +256,7 @@ public:
return dispatch::envelope
<
typename boost::range_value<MultiPoint>::type
- >::apply(range::front(multipoint), mbr);
+ >::apply(range::front(multipoint), mbr, strategy);
}
// analyze the points and put the non-pole ones in the
@@ -329,7 +330,7 @@ public:
// compute envelope for higher coordinates
iterator_type it = boost::begin(multipoint);
- envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);
+ envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr, strategy);
for (++it; it != boost::end(multipoint); ++it)
{
@@ -338,7 +339,7 @@ public:
strategy::compare::default_strategy,
strategy::compare::default_strategy,
2, dimension<Box>::value
- >::apply(mbr, *it);
+ >::apply(mbr, *it, strategy);
}
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/point.hpp b/boost/geometry/algorithms/detail/envelope/point.hpp
index e914e7e8a0..ee0559bf5f 100644
--- a/boost/geometry/algorithms/detail/envelope/point.hpp
+++ b/boost/geometry/algorithms/detail/envelope/point.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -58,8 +59,8 @@ struct envelope_one_point
>::apply(point, box_corner);
}
- template <typename Point, typename Box>
- static inline void apply(Point const& point, Box& mbr)
+ template <typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& point, Box& mbr, Strategy const&)
{
apply<min_corner>(point, mbr);
apply<max_corner>(point, mbr);
@@ -69,8 +70,8 @@ struct envelope_one_point
struct envelope_point_on_spheroid
{
- template<typename Point, typename Box>
- static inline void apply(Point const& point, Box& mbr)
+ template<typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& point, Box& mbr, Strategy const& strategy)
{
Point normalized_point = detail::return_normalized<Point>(point);
@@ -88,7 +89,7 @@ struct envelope_point_on_spheroid
envelope_one_point
<
2, dimension<Point>::value
- >::apply(normalized_point, mbr);
+ >::apply(normalized_point, mbr, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp
index 63b518114b..b5591f61ab 100644
--- a/boost/geometry/algorithms/detail/envelope/range.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -51,8 +52,11 @@ namespace detail { namespace envelope
// implementation for simple ranges
struct envelope_range
{
- template <typename Iterator, typename Box>
- static inline void apply(Iterator first, Iterator last, Box& mbr)
+ template <typename Iterator, typename Box, typename Strategy>
+ static inline void apply(Iterator first,
+ Iterator last,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
@@ -63,20 +67,20 @@ struct envelope_range
if (it != last)
{
// initialize box with first element in range
- dispatch::envelope<value_type>::apply(*it, mbr);
+ dispatch::envelope<value_type>::apply(*it, mbr, strategy);
// consider now the remaining elements in the range (if any)
for (++it; it != last; ++it)
{
- dispatch::expand<Box, value_type>::apply(mbr, *it);
+ dispatch::expand<Box, value_type>::apply(mbr, *it, strategy);
}
}
}
- template <typename Range, typename Box>
- static inline void apply(Range const& range, Box& mbr)
+ template <typename Range, typename Box, typename Strategy>
+ static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
{
- return apply(boost::begin(range), boost::end(range), mbr);
+ return apply(boost::begin(range), boost::end(range), mbr, strategy);
}
};
@@ -85,8 +89,10 @@ struct envelope_range
template <typename EnvelopePolicy>
struct envelope_multi_range
{
- template <typename MultiRange, typename Box>
- static inline void apply(MultiRange const& multirange, Box& mbr)
+ template <typename MultiRange, typename Box, typename Strategy>
+ static inline void apply(MultiRange const& multirange,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename boost::range_iterator
<
@@ -103,14 +109,14 @@ struct envelope_multi_range
if (initialized)
{
Box helper_mbr;
- EnvelopePolicy::apply(*it, helper_mbr);
+ EnvelopePolicy::apply(*it, helper_mbr, strategy);
- dispatch::expand<Box, Box>::apply(mbr, helper_mbr);
+ dispatch::expand<Box, Box>::apply(mbr, helper_mbr, strategy);
}
else
{
// compute the initial envelope
- EnvelopePolicy::apply(*it, mbr);
+ EnvelopePolicy::apply(*it, mbr, strategy);
initialized = true;
}
}
@@ -129,8 +135,10 @@ struct envelope_multi_range
template <typename EnvelopePolicy>
struct envelope_multi_range_on_spheroid
{
- template <typename MultiRange, typename Box>
- static inline void apply(MultiRange const& multirange, Box& mbr)
+ template <typename MultiRange, typename Box, typename Strategy>
+ static inline void apply(MultiRange const& multirange,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename boost::range_iterator
<
@@ -147,7 +155,7 @@ struct envelope_multi_range_on_spheroid
if (! geometry::is_empty(*it))
{
Box helper_box;
- EnvelopePolicy::apply(*it, helper_box);
+ EnvelopePolicy::apply(*it, helper_box, strategy);
boxes.push_back(helper_box);
}
}
@@ -159,7 +167,7 @@ struct envelope_multi_range_on_spheroid
// and the MBR is simply initialized
if (! boxes.empty())
{
- envelope_range_of_boxes::apply(boxes, mbr);
+ envelope_range_of_boxes::apply(boxes, mbr, strategy);
}
else
{
diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
index 64bdb9b9cb..f61fc422de 100644
--- a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -149,8 +150,10 @@ struct envelope_range_of_longitudes
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_range_of_boxes_by_expansion
{
- template <typename RangeOfBoxes, typename Box>
- static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
+ template <typename RangeOfBoxes, typename Box, typename Strategy>
+ static inline void apply(RangeOfBoxes const& range_of_boxes,
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
@@ -196,7 +199,7 @@ struct envelope_range_of_boxes_by_expansion
min_corner,
Dimension,
DimensionCount
- >::apply(mbr, *it);
+ >::apply(mbr, *it, strategy);
detail::expand::indexed_loop
<
@@ -205,7 +208,7 @@ struct envelope_range_of_boxes_by_expansion
max_corner,
Dimension,
DimensionCount
- >::apply(mbr, *it);
+ >::apply(mbr, *it, strategy);
}
}
@@ -225,8 +228,10 @@ struct envelope_range_of_boxes
}
};
- template <typename RangeOfBoxes, typename Box>
- static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
+ template <typename RangeOfBoxes, typename Box, typename Strategy>
+ static inline void apply(RangeOfBoxes const& range_of_boxes,
+ Box& mbr,
+ Strategy const& strategy)
{
// boxes in the range are assumed to be normalized already
@@ -313,7 +318,7 @@ struct envelope_range_of_boxes
envelope_range_of_boxes_by_expansion
<
2, dimension<Box>::value
- >::apply(range_of_boxes, mbr);
+ >::apply(range_of_boxes, mbr, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp
index 6186e72a3a..7631e84883 100644
--- a/boost/geometry/algorithms/detail/envelope/segment.hpp
+++ b/boost/geometry/algorithms/detail/envelope/segment.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015, 2016.
-// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2017.
+// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -26,6 +27,7 @@
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -34,10 +36,9 @@
#include <boost/geometry/geometries/helper_geometry.hpp>
-#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/formulas/vertex_latitude.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
-#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
@@ -46,7 +47,6 @@
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
-
namespace boost { namespace geometry
{
@@ -54,63 +54,36 @@ namespace boost { namespace geometry
namespace detail { namespace envelope
{
-
-template <std::size_t Dimension, std::size_t DimensionCount>
-struct envelope_one_segment
+template <typename CalculationType, typename CS_Tag>
+struct envelope_segment_call_vertex_latitude
{
- template<typename Point, typename Box>
- static inline void apply(Point const& p1, Point const& p2, Box& mbr)
+ template <typename T1, typename T2, typename Strategy>
+ static inline CalculationType apply(T1 const& lat1,
+ T2 const& alp1,
+ Strategy const& )
{
- envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr);
- detail::expand::point_loop
- <
- strategy::compare::default_strategy,
- strategy::compare::default_strategy,
- Dimension,
- DimensionCount
- >::apply(mbr, p2);
+ return geometry::formula::vertex_latitude<CalculationType, CS_Tag>
+ ::apply(lat1, alp1);
}
};
-
-// Computes the MBR of a segment given by (lon1, lat1) and (lon2,
-// lat2), and with azimuths a1 and a2 at the two endpoints of the
-// segment.
-// It is assumed that the spherical coordinates of the segment are
-// normalized and in radians.
-// The longitudes and latitudes of the endpoints are overridden by
-// those of the box.
-class compute_mbr_of_segment
+template <typename CalculationType>
+struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
{
-private:
- // computes the azimuths of the segment with endpoints (lon1, lat1)
- // and (lon2, lat2)
- // radians
- template <typename CalculationType>
- static inline void azimuths(CalculationType const& lon1,
- CalculationType const& lat1,
- CalculationType const& lon2,
- CalculationType const& lat2,
- CalculationType& a1,
- CalculationType& a2)
+ template <typename T1, typename T2, typename Strategy>
+ static inline CalculationType apply(T1 const& lat1,
+ T2 const& alp1,
+ Strategy const& strategy)
{
- BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
-
- CalculationType dlon = lon2 - lon1;
- CalculationType sin_dlon = sin(dlon);
- CalculationType cos_dlon = cos(dlon);
- CalculationType cos_lat1 = cos(lat1);
- CalculationType cos_lat2 = cos(lat2);
- CalculationType sin_lat1 = sin(lat1);
- CalculationType sin_lat2 = sin(lat2);
-
- a1 = atan2(sin_dlon * cos_lat2,
- cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon);
-
- a2 = atan2(-sin_dlon * cos_lat1,
- cos_lat2 * sin_lat1 - sin_lat2 * cos_lat1 * cos_dlon);
- a2 += math::pi<CalculationType>();
+ return geometry::formula::vertex_latitude<CalculationType, geographic_tag>
+ ::apply(lat1, alp1, strategy.model());
}
+};
+
+template <typename CS_Tag>
+class envelope_segment_impl
+{
+private:
// degrees or radians
template <typename CalculationType>
@@ -134,8 +107,8 @@ private:
static CalculationType const pi_half = math::half_pi<CalculationType>();
return (a1 < a2)
- ? (a1 < pi_half && pi_half < a2)
- : (a1 > pi_half && pi_half > a2);
+ ? (a1 < pi_half && pi_half < a2)
+ : (a1 > pi_half && pi_half > a2);
}
// radians or degrees
@@ -151,21 +124,13 @@ private:
return math::abs(lon1 - lon2) > constants::half_period(); // > pi
}
- // radians
- template <typename CalculationType>
- static inline CalculationType max_latitude(CalculationType const& azimuth,
- CalculationType const& latitude)
- {
- // azimuth and latitude are assumed to be in radians
- return acos( math::abs(cos(latitude) * sin(azimuth)) );
- }
-
// degrees or radians
- template <typename Units, typename CalculationType>
+ template <typename Units, typename CalculationType, typename Strategy>
static inline void compute_box_corners(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
- CalculationType& lat2)
+ CalculationType& lat2,
+ Strategy const& strategy)
{
// coordinates are assumed to be in radians
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
@@ -175,13 +140,14 @@ private:
CalculationType lon2_rad = math::as_radian<Units>(lon2);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
- CalculationType a1 = 0, a2 = 0;
- azimuths(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
+ CalculationType a1, a2;
+ strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
if (lat1 > lat2)
{
std::swap(lat1, lat2);
std::swap(lat1_rad, lat2_rad);
+ std::swap(a1, a2);
}
if (math::equals(a1, a2))
@@ -192,12 +158,16 @@ private:
if (contains_pi_half(a1, a2))
{
+ CalculationType p_max = envelope_segment_call_vertex_latitude
+ <CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy);
+
CalculationType const mid_lat = lat1 + lat2;
if (mid_lat < 0)
{
// update using min latitude
- CalculationType const lat_min_rad = -max_latitude(a1, lat1_rad);
- CalculationType const lat_min = math::from_radian<Units>(lat_min_rad);
+ CalculationType const lat_min_rad = -p_max;
+ CalculationType const lat_min
+ = math::from_radian<Units>(lat_min_rad);
if (lat1 > lat_min)
{
@@ -207,8 +177,9 @@ private:
else if (mid_lat > 0)
{
// update using max latitude
- CalculationType const lat_max_rad = max_latitude(a1, lat1_rad);
- CalculationType const lat_max = math::from_radian<Units>(lat_max_rad);
+ CalculationType const lat_max_rad = p_max;
+ CalculationType const lat_max
+ = math::from_radian<Units>(lat_max_rad);
if (lat2 < lat_max)
{
@@ -218,11 +189,12 @@ private:
}
}
- template <typename Units, typename CalculationType>
+ template <typename Units, typename CalculationType, typename Strategy>
static inline void apply(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
- CalculationType& lat2)
+ CalculationType& lat2,
+ Strategy const& strategy)
{
typedef math::detail::constants_on_spheroid
<
@@ -278,16 +250,22 @@ private:
swap(lon1, lat1, lon2, lat2);
}
- compute_box_corners<Units>(lon1, lat1, lon2, lat2);
+ compute_box_corners<Units>(lon1, lat1, lon2, lat2, strategy);
}
public:
- template <typename Units, typename CalculationType, typename Box>
+ template <
+ typename Units,
+ typename CalculationType,
+ typename Box,
+ typename Strategy
+ >
static inline void apply(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
CalculationType lat2,
- Box& mbr)
+ Box& mbr,
+ Strategy const& strategy)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
@@ -298,7 +276,7 @@ public:
helper_box_type radian_mbr;
- apply<Units>(lon1, lat1, lon2, lat2);
+ apply<Units>(lon1, lat1, lon2, lat2, strategy);
geometry::set
<
@@ -324,29 +302,42 @@ public:
}
};
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct envelope_one_segment
+{
+ template<typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& p1,
+ Point const& p2,
+ Box& mbr,
+ Strategy const& strategy)
+ {
+ envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr, strategy);
+ detail::expand::point_loop
+ <
+ strategy::compare::default_strategy,
+ strategy::compare::default_strategy,
+ Dimension,
+ DimensionCount
+ >::apply(mbr, p2, strategy);
+ }
+};
+
template <std::size_t DimensionCount>
-struct envelope_segment_on_sphere
+struct envelope_segment
{
- template <typename Point, typename Box>
- static inline void apply(Point const& p1, Point const& p2, Box& mbr)
+ template <typename Point, typename Box, typename Strategy>
+ static inline void apply(Point const& p1,
+ Point const& p2,
+ Box& mbr,
+ Strategy const& strategy)
{
// first compute the envelope range for the first two coordinates
- Point p1_normalized = detail::return_normalized<Point>(p1);
- Point p2_normalized = detail::return_normalized<Point>(p2);
-
- typedef typename coordinate_system<Point>::type::units units_type;
-
- compute_mbr_of_segment::template apply<units_type>(
- geometry::get<0>(p1_normalized),
- geometry::get<1>(p1_normalized),
- geometry::get<0>(p2_normalized),
- geometry::get<1>(p2_normalized),
- mbr);
+ strategy.apply(p1, p2, mbr);
// now compute the envelope range for coordinates of
// dimension 2 and higher
- envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr);
+ envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr, strategy);
}
template <typename Segment, typename Box>
@@ -359,21 +350,6 @@ struct envelope_segment_on_sphere
}
};
-
-
-template <std::size_t DimensionCount, typename CS_Tag>
-struct envelope_segment
- : envelope_one_segment<0, DimensionCount>
-{};
-
-
-template <std::size_t DimensionCount>
-struct envelope_segment<DimensionCount, spherical_equatorial_tag>
- : envelope_segment_on_sphere<DimensionCount>
-{};
-
-
-
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
@@ -383,23 +359,24 @@ namespace dispatch
{
-template <typename Segment, typename CS_Tag>
-struct envelope<Segment, segment_tag, CS_Tag>
+template <typename Segment>
+struct envelope<Segment, segment_tag>
{
- template <typename Box>
- static inline void apply(Segment const& segment, Box& mbr)
+ template <typename Box, typename Strategy>
+ static inline void apply(Segment const& segment,
+ Box& mbr,
+ Strategy const& strategy)
{
typename point_type<Segment>::type p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
detail::envelope::envelope_segment
<
- dimension<Segment>::value, CS_Tag
- >::apply(p[0], p[1], mbr);
+ dimension<Segment>::value
+ >::apply(p[0], p[1], mbr, strategy);
}
};
-
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
index eab73ea680..9625f18426 100644
--- a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
+++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
@@ -3,7 +3,12 @@
// 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.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -20,6 +25,7 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@@ -32,21 +38,37 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/views/detail/normalized_view.hpp>
+
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
+#include <boost/geometry/strategies/spherical/ssf.hpp>
+
namespace boost { namespace geometry
{
+// TODO: dispatch only by SideStrategy instead of Geometry/CSTag?
+
// Since these vectors (though ray would be a better name) are used in the
// implementation of equals() for Areal geometries the internal representation
-// should be consistent with the default side strategy for CS because currently
-// it's used in other relops.
-
-template <
+// should be consistent with the side strategy.
+template
+<
typename T,
typename Geometry,
+ typename SideStrategy,
typename CSTag = typename cs_tag<Geometry>::type
>
struct collected_vector
+ : nyi::not_implemented_tag
+{};
+
+// compatible with side_by_triangle cartesian strategy
+template <typename T, typename Geometry, typename CT, typename CSTag>
+struct collected_vector
+ <
+ T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
+ >
{
typedef T type;
@@ -136,8 +158,13 @@ private:
//T dx_0, dy_0;
};
-template <typename T, typename Geometry>
-struct collected_vector<T, Geometry, spherical_equatorial_tag>
+// Compatible with spherical_side_formula which currently
+// is the default spherical and geographical strategy
+template <typename T, typename Geometry, typename CT, typename CSTag>
+struct collected_vector
+ <
+ T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag
+ >
{
typedef T type;
@@ -232,11 +259,27 @@ private:
vector_type next; // used for collinearity check
};
-template <typename T, typename Geometry>
-struct collected_vector<T, Geometry, spherical_polar_tag>
- : public collected_vector<T, Geometry, spherical_equatorial_tag>
+// Specialization for spherical polar
+template <typename T, typename Geometry, typename CT>
+struct collected_vector
+ <
+ T, Geometry,
+ strategy::side::spherical_side_formula<CT>,
+ spherical_polar_tag
+ >
+ : public collected_vector
+ <
+ T, Geometry,
+ strategy::side::spherical_side_formula<CT>,
+ spherical_equatorial_tag
+ >
{
- typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type;
+ typedef collected_vector
+ <
+ T, Geometry,
+ strategy::side::spherical_side_formula<CT>,
+ spherical_equatorial_tag
+ > base_type;
collected_vector() {}
@@ -265,24 +308,6 @@ private:
}
};
-// This is consistent with the currently used default geographic side
-// and intersection strategies. Spherical strategies are used by default.
-// When default strategies are changed in the future this specialization
-// should be changed too.
-template <typename T, typename Geometry>
-struct collected_vector<T, Geometry, geographic_tag>
- : public collected_vector<T, Geometry, spherical_equatorial_tag>
-{
- typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type;
-
- collected_vector() {}
-
- template <typename Point>
- collected_vector(Point const& p1, Point const& p2)
- : base_type(p1, p2)
- {}
-};
-
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace collect_vectors
@@ -297,6 +322,18 @@ struct range_collect_vectors
static inline void apply(Collection& collection, Range const& range)
{
+ typedef geometry::detail::normalized_view
+ <
+ Range const
+ > normalized_range_type;
+
+ apply_impl(collection, normalized_range_type(range));
+ }
+
+private:
+ template <typename NormalizedRange>
+ static inline void apply_impl(Collection& collection, NormalizedRange const& range)
+ {
if (boost::size(range) < 2)
{
return;
@@ -305,7 +342,7 @@ struct range_collect_vectors
typedef typename boost::range_size<Collection>::type collection_size_t;
collection_size_t c_old_size = boost::size(collection);
- typedef typename boost::range_iterator<Range const>::type iterator;
+ typedef typename boost::range_iterator<NormalizedRange const>::type iterator;
bool is_first = true;
iterator it = boost::begin(range);
diff --git a/boost/geometry/algorithms/detail/expand/box.hpp b/boost/geometry/algorithms/detail/expand/box.hpp
index 4c89e6f1d4..3edb23f5ae 100644
--- a/boost/geometry/algorithms/detail/expand/box.hpp
+++ b/boost/geometry/algorithms/detail/expand/box.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -44,16 +45,18 @@ namespace detail { namespace expand
struct box_on_spheroid
{
- template <typename BoxOut, typename BoxIn>
- static inline void apply(BoxOut& box_out, BoxIn const& box_in)
+ template <typename BoxOut, typename BoxIn, typename Strategy>
+ static inline void apply(BoxOut& box_out,
+ BoxIn const& box_in,
+ Strategy const& strategy)
{
// normalize both boxes and convert box-in to be of type of box-out
BoxOut mbrs[2];
- detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]);
- detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]);
+ detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0], strategy);
+ detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1], strategy);
// compute the envelope of the two boxes
- detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out);
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp
index bdd6eb4506..28cf0e2e4f 100644
--- a/boost/geometry/algorithms/detail/expand/indexed.hpp
+++ b/boost/geometry/algorithms/detail/expand/indexed.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -49,8 +50,8 @@ template
>
struct indexed_loop
{
- template <typename Box, typename Geometry>
- static inline void apply(Box& box, Geometry const& source)
+ template <typename Box, typename Geometry, typename Strategy>
+ static inline void apply(Box& box, Geometry const& source, Strategy const& strategy)
{
typedef typename strategy::compare::detail::select_strategy
<
@@ -87,7 +88,7 @@ struct indexed_loop
<
StrategyLess, StrategyGreater,
Index, Dimension + 1, DimensionCount
- >::apply(box, source);
+ >::apply(box, source, strategy);
}
};
@@ -103,8 +104,8 @@ struct indexed_loop
Index, DimensionCount, DimensionCount
>
{
- template <typename Box, typename Geometry>
- static inline void apply(Box&, Geometry const&) {}
+ template <typename Box, typename Geometry, typename Strategy>
+ static inline void apply(Box&, Geometry const&, Strategy const&) {}
};
@@ -117,20 +118,22 @@ template
>
struct expand_indexed
{
- template <typename Box, typename Geometry>
- static inline void apply(Box& box, Geometry const& geometry)
+ template <typename Box, typename Geometry, typename Strategy>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
{
indexed_loop
<
StrategyLess, StrategyGreater,
0, Dimension, DimensionCount
- >::apply(box, geometry);
+ >::apply(box, geometry, strategy);
indexed_loop
<
StrategyLess, StrategyGreater,
1, Dimension, DimensionCount
- >::apply(box, geometry);
+ >::apply(box, geometry, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp
index 140754af4e..5aacd8e72a 100644
--- a/boost/geometry/algorithms/detail/expand/interface.hpp
+++ b/boost/geometry/algorithms/detail/expand/interface.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -28,10 +29,50 @@
#include <boost/geometry/algorithms/dispatch/expand.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
namespace boost { namespace geometry
{
+namespace resolve_strategy
+{
+
+template <typename Geometry>
+struct expand
+{
+ template <typename Box, typename Strategy>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
+ {
+ dispatch::expand<Box, Geometry>::apply(box, geometry, strategy);
+ }
+
+ template <typename Box>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ default_strategy)
+ {
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<point_type>::type coordinate_type;
+
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ coordinate_type
+ >::type strategy_type;
+
+ dispatch::expand<Box, Geometry>::apply(box, geometry, strategy_type());
+ }
+};
+
+} //namespace resolve_strategy
+
namespace resolve_variant
{
@@ -39,40 +80,48 @@ namespace resolve_variant
template <typename Geometry>
struct expand
{
- template <typename Box>
- static inline void apply(Box& box, Geometry const& geometry)
+ template <typename Box, typename Strategy>
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
{
concepts::check<Box>();
concepts::check<Geometry const>();
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
- dispatch::expand<Box, Geometry>::apply(box, geometry);
+ resolve_strategy::expand<Geometry>::apply(box, geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Box>
+ template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Box& m_box;
+ Strategy const& m_strategy;
- visitor(Box& box) : m_box(box) {}
+ visitor(Box& box, Strategy const& strategy)
+ : m_box(box)
+ , m_strategy(strategy)
+ {}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
- return expand<Geometry>::apply(m_box, geometry);
+ return expand<Geometry>::apply(m_box, geometry, m_strategy);
}
};
- template <class Box>
+ template <class Box, typename Strategy>
static inline void
apply(Box& box,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Box>(box), geometry);
+ return boost::apply_visitor(visitor<Box, Strategy>(box, strategy),
+ geometry);
}
};
@@ -106,21 +155,43 @@ inline void expand(Box& box, Geometry const& geometry,
}
***/
+/*!
+\brief Expands (with strategy)
+\ingroup expand
+\tparam Box type of the box
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{expand}
+\param box box to be expanded using another geometry, mutable
+\param geometry \param_geometry geometry which envelope (bounding box)
+\param strategy \param_strategy{expand}
+will be added to the box
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/expand.qbk]}
+ */
+template <typename Box, typename Geometry, typename Strategy>
+inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy)
+{
+
+ resolve_variant::expand<Geometry>::apply(box, geometry, strategy);
+}
/*!
-\brief Expands a box using the bounding box (envelope) of another geometry (box, point)
+\brief Expands a box using the bounding box (envelope) of another geometry
+(box, point)
\ingroup expand
\tparam Box type of the box
\tparam Geometry \tparam_geometry
\param box box to be expanded using another geometry, mutable
-\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box
+\param geometry \param_geometry geometry which envelope (bounding box) will be
+added to the box
\qbk{[include reference/algorithms/expand.qbk]}
*/
template <typename Box, typename Geometry>
inline void expand(Box& box, Geometry const& geometry)
{
- resolve_variant::expand<Geometry>::apply(box, geometry);
+ resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/expand/point.hpp b/boost/geometry/algorithms/detail/expand/point.hpp
index 56b7f1c738..f0cbd1db02 100644
--- a/boost/geometry/algorithms/detail/expand/point.hpp
+++ b/boost/geometry/algorithms/detail/expand/point.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -59,8 +60,8 @@ template
>
struct point_loop
{
- template <typename Box, typename Point>
- static inline void apply(Box& box, Point const& source)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box& box, Point const& source, Strategy const& strategy)
{
typedef typename strategy::compare::detail::select_strategy
<
@@ -95,22 +96,24 @@ struct point_loop
point_loop
<
StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
- >::apply(box, source);
+ >::apply(box, source, strategy);
}
};
template
<
- typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount
+ typename StrategyLess,
+ typename StrategyGreater,
+ std::size_t DimensionCount
>
struct point_loop
<
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
>
{
- template <typename Box, typename Point>
- static inline void apply(Box&, Point const&) {}
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box&, Point const&, Strategy const&) {}
};
@@ -123,8 +126,10 @@ template
>
struct point_loop_on_spheroid
{
- template <typename Box, typename Point>
- static inline void apply(Box& box, Point const& point)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box& box,
+ Point const& point,
+ Strategy const& strategy)
{
typedef typename point_type<Box>::type box_point_type;
typedef typename coordinate_type<Box>::type box_coordinate_type;
@@ -224,7 +229,7 @@ struct point_loop_on_spheroid
point_loop
<
StrategyLess, StrategyGreater, 2, DimensionCount
- >::apply(box, point);
+ >::apply(box, point, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/expand/segment.hpp b/boost/geometry/algorithms/detail/expand/segment.hpp
index 041c1e175f..0570e944d4 100644
--- a/boost/geometry/algorithms/detail/expand/segment.hpp
+++ b/boost/geometry/algorithms/detail/expand/segment.hpp
@@ -5,9 +5,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016.
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
@@ -39,25 +40,29 @@ namespace boost { namespace geometry
namespace detail { namespace expand
{
-
-struct segment_on_sphere
+struct segment
{
- template <typename Box, typename Segment>
- static inline void apply(Box& box, Segment const& segment)
+ template <typename Box, typename Segment, typename Strategy>
+ static inline void apply(Box& box,
+ Segment const& segment,
+ Strategy const& strategy)
{
Box mbrs[2];
// compute the envelope of the segment
- detail::envelope::envelope_segment_on_sphere
+ typename point_type<Segment>::type p[2];
+ detail::assign_point_from_index<0>(segment, p[0]);
+ detail::assign_point_from_index<1>(segment, p[1]);
+ detail::envelope::envelope_segment
<
dimension<Segment>::value
- >::apply(segment, mbrs[0]);
+ >::apply(p[0], p[1], mbrs[0], strategy);
// normalize the box
- detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]);
+ detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1], strategy);
// compute the envelope of the two boxes
- detail::envelope::envelope_range_of_boxes::apply(mbrs, box);
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box, strategy);
}
};
@@ -69,7 +74,6 @@ struct segment_on_sphere
namespace dispatch
{
-
template
<
typename Box, typename Segment,
@@ -103,13 +107,27 @@ struct expand
StrategyLess, StrategyGreater,
box_tag, segment_tag,
spherical_equatorial_tag, spherical_equatorial_tag
- > : detail::expand::segment_on_sphere
+ > : detail::expand::segment
{};
+template
+<
+ typename Box, typename Segment,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand
+ <
+ Box, Segment,
+ StrategyLess, StrategyGreater,
+ box_tag, segment_tag,
+ geographic_tag, geographic_tag
+ > : detail::expand::segment
+{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
+
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp
index 24746ac627..9a388a4d80 100644
--- a/boost/geometry/algorithms/detail/has_self_intersections.hpp
+++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -12,6 +17,8 @@
#include <deque>
#include <boost/range.hpp>
+#include <boost/throw_exception.hpp>
+
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
@@ -59,8 +66,9 @@ namespace detail { namespace overlay
{
-template <typename Geometry, typename RobustPolicy>
+template <typename Geometry, typename Strategy, typename RobustPolicy>
inline bool has_self_intersections(Geometry const& geometry,
+ Strategy const& strategy,
RobustPolicy const& robust_policy,
bool throw_on_self_intersection = true)
{
@@ -73,7 +81,7 @@ inline bool has_self_intersections(Geometry const& geometry,
std::deque<turn_info> turns;
detail::disjoint::disjoint_interrupt_policy policy;
- geometry::self_turns<detail::overlay::assign_null_policy>(geometry, robust_policy, turns, policy);
+ geometry::self_turns<detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy);
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
bool first = true;
@@ -113,7 +121,7 @@ inline bool has_self_intersections(Geometry const& geometry,
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
if (throw_on_self_intersection)
{
- throw overlay_invalid_input_exception();
+ BOOST_THROW_EXCEPTION(overlay_invalid_input_exception());
}
#endif
return true;
@@ -132,11 +140,16 @@ inline bool has_self_intersections(Geometry const& geometry,
typedef typename geometry::rescale_policy_type<point_type>::type
rescale_policy_type;
+ typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy;
+
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
- return has_self_intersections(geometry, robust_policy,
- throw_on_self_intersection);
+ return has_self_intersections(geometry, strategy, robust_policy,
+ throw_on_self_intersection);
}
diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp
index e0955de3d8..0efc9731b5 100644
--- a/boost/geometry/algorithms/detail/intersection/interface.hpp
+++ b/boost/geometry/algorithms/detail/intersection/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,12 +15,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
-// TODO: those headers probably may be removed
-#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
@@ -51,10 +53,11 @@ struct intersection
typedef typename boost::range_value<GeometryOut>::type OneOut;
intersection_insert
- <
- Geometry1, Geometry2, OneOut,
- overlay_intersection
- >::apply(geometry1, geometry2, robust_policy, range::back_inserter(geometry_out), strategy);
+ <
+ Geometry1, Geometry2, OneOut,
+ overlay_intersection
+ >::apply(geometry1, geometry2, robust_policy,
+ range::back_inserter(geometry_out), strategy);
return true;
}
@@ -84,11 +87,12 @@ struct intersection
GeometryOut& out,
Strategy const& strategy)
{
- return intersection<
- Geometry2, Geometry1,
- Tag2, Tag1,
- false
- >::apply(g2, g1, robust_policy, out, strategy);
+ return intersection
+ <
+ Geometry2, Geometry1,
+ Tag2, Tag1,
+ false
+ >::apply(g2, g1, robust_policy, out, strategy);
}
};
@@ -96,47 +100,93 @@ struct intersection
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
-
+
+namespace resolve_strategy {
+
+struct intersection
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename GeometryOut,
+ typename Strategy
+ >
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ GeometryOut & geometry_out,
+ Strategy const& strategy)
+ {
+ return dispatch::intersection
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, robust_policy, geometry_out,
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename GeometryOut
+ >
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ GeometryOut & geometry_out,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+
+ return dispatch::intersection
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, robust_policy, geometry_out,
+ strategy_type());
+ }
+};
+
+} // resolve_strategy
+
+
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct intersection
{
- template <typename GeometryOut>
- static inline bool
- apply(
- const Geometry1& geometry1,
- const Geometry2& geometry2,
- GeometryOut& geometry_out)
+ template <typename GeometryOut, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
typedef typename geometry::rescale_overlay_policy_type
- <
- Geometry1,
- Geometry2
- >::type rescale_policy_type;
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
geometry2);
- typedef intersection_strategies
- <
- typename cs_tag<Geometry1>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<Geometry1>::type,
- rescale_policy_type
- > strategy;
-
- return dispatch::intersection
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, robust_policy, geometry_out, strategy());
+ return resolve_strategy::intersection::apply(geometry1,
+ geometry2,
+ robust_policy,
+ geometry_out,
+ strategy);
}
};
@@ -144,40 +194,43 @@ struct intersection
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
GeometryOut& m_geometry_out;
+ Strategy const& m_strategy;
visitor(Geometry2 const& geometry2,
- GeometryOut& geometry_out)
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
: m_geometry2(geometry2)
, m_geometry_out(geometry_out)
+ , m_strategy(strategy)
{}
template <typename Geometry1>
- result_type operator()(Geometry1 const& geometry1) const
+ bool operator()(Geometry1 const& geometry1) const
{
return intersection
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- GeometryOut
- >
- (geometry1, m_geometry2, m_geometry_out);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
}
};
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
static inline bool
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
- GeometryOut& geometry_out)
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1);
+ return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
+ geometry_out,
+ strategy),
+ geometry1);
}
};
@@ -185,40 +238,43 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
GeometryOut& m_geometry_out;
+ Strategy const& m_strategy;
visitor(Geometry1 const& geometry1,
- GeometryOut& geometry_out)
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
: m_geometry1(geometry1)
, m_geometry_out(geometry_out)
+ , m_strategy(strategy)
{}
template <typename Geometry2>
- result_type operator()(Geometry2 const& geometry2) const
+ bool operator()(Geometry2 const& geometry2) const
{
return intersection
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- GeometryOut
- >
- (m_geometry1, geometry2, m_geometry_out);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
}
};
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
- GeometryOut& geometry_out)
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2);
+ return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
+ geometry_out,
+ strategy),
+ geometry2);
}
};
@@ -226,38 +282,39 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
GeometryOut& m_geometry_out;
+ Strategy const& m_strategy;
- visitor(GeometryOut& geometry_out)
+ visitor(GeometryOut& geometry_out, Strategy const& strategy)
: m_geometry_out(geometry_out)
+ , m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
- result_type operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
{
return intersection
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- GeometryOut
- >
- (geometry1, geometry2, m_geometry_out);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_geometry_out, m_strategy);
}
};
- template <typename GeometryOut>
+ template <typename GeometryOut, typename Strategy>
static inline bool
- apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2,
- GeometryOut& geometry_out)
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2);
+ return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
+ strategy),
+ geometry1, geometry2);
}
};
@@ -272,32 +329,66 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIAN
\tparam Geometry2 \tparam_geometry
\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
+\tparam Strategy \tparam_strategy{Intersection}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param geometry_out The output geometry, either a multi_point, multi_polygon,
multi_linestring, or a box (for intersection of two boxes)
+\param strategy \param_strategy{intersection}
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/intersection.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename GeometryOut
+ typename GeometryOut,
+ typename Strategy
>
inline bool intersection(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut& geometry_out)
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
{
return resolve_variant::intersection
<
- Geometry1,
- Geometry2
- >::template apply
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, geometry_out, strategy);
+}
+
+
+/*!
+\brief \brief_calc2{intersection}
+\ingroup intersection
+\details \details_calc2{intersection, spatial set theoretic intersection}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
+ the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param geometry_out The output geometry, either a multi_point, multi_polygon,
+ multi_linestring, or a box (for intersection of two boxes)
+
+\qbk{[include reference/algorithms/intersection.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename GeometryOut
+>
+inline bool intersection(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out)
+{
+ return resolve_variant::intersection
<
- GeometryOut
- >
- (geometry1, geometry2, geometry_out);
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, geometry_out, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/is_simple/always_simple.hpp b/boost/geometry/algorithms/detail/is_simple/always_simple.hpp
index 91e2ef76bd..5cec5e1924 100644
--- a/boost/geometry/algorithms/detail/is_simple/always_simple.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/always_simple.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -27,7 +28,8 @@ namespace detail { namespace is_simple
template <typename Geometry>
struct always_simple
{
- static inline bool apply(Geometry const&)
+ template <typename Strategy>
+ static inline bool apply(Geometry const&, Strategy const&)
{
return true;
}
diff --git a/boost/geometry/algorithms/detail/is_simple/areal.hpp b/boost/geometry/algorithms/detail/is_simple/areal.hpp
index a2322e4831..d4d6db9bce 100644
--- a/boost/geometry/algorithms/detail/is_simple/areal.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/areal.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -37,6 +38,12 @@ namespace detail { namespace is_simple
template <typename Ring>
struct is_simple_ring
{
+ template <typename Strategy>
+ static inline bool apply(Ring const& ring, Strategy const&)
+ {
+ return apply(ring);
+ }
+
static inline bool apply(Ring const& ring)
{
simplicity_failure_policy policy;
@@ -69,6 +76,12 @@ private:
}
public:
+ template <typename Strategy>
+ static inline bool apply(Polygon const& polygon, Strategy const&)
+ {
+ return apply(polygon);
+ }
+
static inline bool apply(Polygon const& polygon)
{
return
@@ -119,7 +132,8 @@ struct is_simple<Polygon, polygon_tag>
template <typename MultiPolygon>
struct is_simple<MultiPolygon, multi_polygon_tag>
{
- static inline bool apply(MultiPolygon const& multipolygon)
+ template <typename Strategy>
+ static inline bool apply(MultiPolygon const& multipolygon, Strategy const&)
{
return
detail::check_iterator_range
diff --git a/boost/geometry/algorithms/detail/is_simple/interface.hpp b/boost/geometry/algorithms/detail/is_simple/interface.hpp
index 6d425232b0..af0127dc75 100644
--- a/boost/geometry/algorithms/detail/is_simple/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/interface.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -17,46 +18,106 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
namespace boost { namespace geometry
{
+namespace resolve_strategy
+{
+
+struct is_simple
+{
+ template <typename Geometry, typename Strategy>
+ static inline bool apply(Geometry const& geometry,
+ Strategy const& strategy)
+ {
+ return dispatch::is_simple<Geometry>::apply(geometry, strategy);
+ }
+
+ template <typename Geometry>
+ static inline bool apply(Geometry const& geometry,
+ default_strategy)
+ {
+ // NOTE: Currently the strategy is only used for Linear geometries
+ typedef typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy_type;
+
+ return dispatch::is_simple<Geometry>::apply(geometry, strategy_type());
+ }
+};
-namespace resolve_variant {
+} // namespace resolve_strategy
+
+namespace resolve_variant
+{
template <typename Geometry>
struct is_simple
{
- static inline bool apply(Geometry const& geometry)
+ template <typename Strategy>
+ static inline bool apply(Geometry const& geometry, Strategy const& strategy)
{
concepts::check<Geometry const>();
- return dispatch::is_simple<Geometry>::apply(geometry);
+
+ return resolve_strategy::is_simple::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename Strategy>
struct visitor : boost::static_visitor<bool>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
template <typename Geometry>
bool operator()(Geometry const& geometry) const
{
- return is_simple<Geometry>::apply(geometry);
+ return is_simple<Geometry>::apply(geometry, m_strategy);
}
};
+ template <typename Strategy>
static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(), geometry);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
}
};
} // namespace resolve_variant
+/*!
+\brief \brief_check{is simple}
+\ingroup is_simple
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_simple}
+\param geometry \param_geometry
+\param strategy \param_strategy{is_simple}
+\return \return_check{is simple}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/is_simple.qbk]}
+*/
+template <typename Geometry, typename Strategy>
+inline bool is_simple(Geometry const& geometry, Strategy const& strategy)
+{
+ return resolve_variant::is_simple<Geometry>::apply(geometry, strategy);
+}
+
/*!
\brief \brief_check{is simple}
@@ -70,7 +131,7 @@ struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline bool is_simple(Geometry const& geometry)
{
- return resolve_variant::is_simple<Geometry>::apply(geometry);
+ return resolve_variant::is_simple<Geometry>::apply(geometry, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index 16d7b3a803..52b9d9d1c8 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -48,6 +49,8 @@
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+
namespace boost { namespace geometry
{
@@ -186,8 +189,8 @@ private:
};
-template <typename Linear>
-inline bool has_self_intersections(Linear const& linear)
+template <typename Linear, typename Strategy>
+inline bool has_self_intersections(Linear const& linear, Strategy const& strategy)
{
typedef typename point_type<Linear>::type point_type;
@@ -218,6 +221,7 @@ inline bool has_self_intersections(Linear const& linear)
<
turn_policy
>::apply(linear,
+ strategy,
detail::no_rescale_policy(),
turns,
interrupt_policy);
@@ -243,8 +247,19 @@ struct is_simple_linestring
&& ! detail::is_valid::has_spikes
<
Linestring, closed
- >::apply(linestring, policy)
- && ! (CheckSelfIntersections && has_self_intersections(linestring));
+ >::apply(linestring, policy);
+ }
+};
+
+template <typename Linestring>
+struct is_simple_linestring<Linestring, true>
+{
+ template <typename Strategy>
+ static inline bool apply(Linestring const& linestring,
+ Strategy const& strategy)
+ {
+ return is_simple_linestring<Linestring, false>::apply(linestring)
+ && ! has_self_intersections(linestring, strategy);
}
};
@@ -252,7 +267,9 @@ struct is_simple_linestring
template <typename MultiLinestring>
struct is_simple_multilinestring
{
- static inline bool apply(MultiLinestring const& multilinestring)
+ template <typename Strategy>
+ static inline bool apply(MultiLinestring const& multilinestring,
+ Strategy const& strategy)
{
// check each of the linestrings for simplicity
// but do not compute self-intersections yet; these will be
@@ -272,7 +289,7 @@ struct is_simple_multilinestring
return false;
}
- return ! has_self_intersections(multilinestring);
+ return ! has_self_intersections(multilinestring, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
index f9f43d1cdb..61f0bc9130 100644
--- a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -38,7 +39,8 @@ namespace detail { namespace is_simple
template <typename MultiPoint>
struct is_simple_multipoint
{
- static inline bool apply(MultiPoint const& multipoint)
+ template <typename Strategy>
+ static inline bool apply(MultiPoint const& multipoint, Strategy const&)
{
if (boost::empty(multipoint))
{
diff --git a/boost/geometry/algorithms/detail/is_valid/box.hpp b/boost/geometry/algorithms/detail/is_valid/box.hpp
index 863ce625fe..69a4d4e78e 100644
--- a/boost/geometry/algorithms/detail/is_valid/box.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/box.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -71,8 +71,8 @@ struct has_valid_corners<Box, 0>
template <typename Box>
struct is_valid_box
{
- template <typename VisitPolicy>
- static inline bool apply(Box const& box, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Box const& box, VisitPolicy& visitor, Strategy const&)
{
return
! has_invalid_coordinate<Box>::apply(box, visitor)
diff --git a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
index 0a81213743..b91dc6a697 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -69,10 +70,11 @@ public:
> turn_type;
// returns true if all turns are valid
- template <typename Turns, typename VisitPolicy>
+ template <typename Turns, typename VisitPolicy, typename Strategy>
static inline bool apply(Geometry const& geometry,
Turns& turns,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
boost::ignore_unused(visitor);
@@ -85,6 +87,7 @@ public:
> interrupt_policy;
geometry::self_turns<turn_policy>(geometry,
+ strategy,
robust_policy,
turns,
interrupt_policy);
@@ -101,11 +104,11 @@ public:
}
// returns true if all turns are valid
- template <typename VisitPolicy>
- static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor, Strategy const& strategy)
{
std::vector<turn_type> turns;
- return apply(geometry, turns, visitor);
+ return apply(geometry, turns, visitor, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp
index 5a04a92824..ee013377c4 100644
--- a/boost/geometry/algorithms/detail/is_valid/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/interface.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -23,48 +24,88 @@
#include <boost/geometry/policies/is_valid/default_policy.hpp>
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
#include <boost/geometry/policies/is_valid/failure_type_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
namespace boost { namespace geometry
{
+
+namespace resolve_strategy
+{
+
+struct is_valid
+{
+ template <typename Geometry, typename VisitPolicy, typename Strategy>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
+ {
+ return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ }
+
+ template <typename Geometry, typename VisitPolicy>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& visitor,
+ default_strategy)
+ {
+ // NOTE: Currently the strategy is only used for Areal geometries
+ typedef typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy_type;
+
+ return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy_type());
+ }
+};
+} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_variant
+{
template <typename Geometry>
struct is_valid
{
- template <typename VisitPolicy>
- static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
concepts::check<Geometry const>();
- return dispatch::is_valid<Geometry>::apply(geometry, visitor);
+
+ return resolve_strategy::is_valid::apply(geometry, visitor, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
- visitor(VisitPolicy& policy) : m_policy(policy) {}
+ visitor(VisitPolicy& policy, Strategy const& strategy)
+ : m_policy(policy)
+ , m_strategy(strategy)
+ {}
template <typename Geometry>
bool operator()(Geometry const& geometry) const
{
- return is_valid<Geometry>::apply(geometry, m_policy);
+ return is_valid<Geometry>::apply(geometry, m_policy, m_strategy);
}
VisitPolicy& m_policy;
+ Strategy const& m_strategy;
};
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- VisitPolicy& policy_visitor)
+ VisitPolicy& policy_visitor,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<VisitPolicy>(policy_visitor),
+ return boost::apply_visitor(visitor<VisitPolicy, Strategy>(policy_visitor, strategy),
geometry);
}
};
@@ -73,10 +114,12 @@ struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
// Undocumented for now
-template <typename Geometry, typename VisitPolicy>
-inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
+template <typename Geometry, typename VisitPolicy, typename Strategy>
+inline bool is_valid(Geometry const& geometry,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
- return resolve_variant::is_valid<Geometry>::apply(geometry, visitor);
+ return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
@@ -84,6 +127,29 @@ inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
\brief \brief_check{is valid (in the OGC sense)}
\ingroup is_valid
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_valid}
+\param geometry \param_geometry
+\param strategy \param_strategy{is_valid}
+\return \return_check{is valid (in the OGC sense);
+furthermore, the following geometries are considered valid:
+multi-geometries with no elements,
+linear geometries containing spikes,
+areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/is_valid.qbk]}
+*/
+template <typename Geometry, typename Strategy>
+inline bool is_valid(Geometry const& geometry, Strategy const& strategy)
+{
+ is_valid_default_policy<> visitor;
+ return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+}
+
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_check{is valid (in the OGC sense);
furthermore, the following geometries are considered valid:
@@ -96,8 +162,7 @@ inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
template <typename Geometry>
inline bool is_valid(Geometry const& geometry)
{
- is_valid_default_policy<> policy_visitor;
- return geometry::is_valid(geometry, policy_visitor);
+ return is_valid(geometry, default_strategy());
}
@@ -105,6 +170,33 @@ inline bool is_valid(Geometry const& geometry)
\brief \brief_check{is valid (in the OGC sense)}
\ingroup is_valid
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_valid}
+\param geometry \param_geometry
+\param failure An enumeration value indicating that the geometry is
+ valid or not, and if not valid indicating the reason why
+\param strategy \param_strategy{is_valid}
+\return \return_check{is valid (in the OGC sense);
+ furthermore, the following geometries are considered valid:
+ multi-geometries with no elements,
+ linear geometries containing spikes,
+ areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with failure value and strategy}
+\qbk{[include reference/algorithms/is_valid_with_failure.qbk]}
+*/
+template <typename Geometry, typename Strategy>
+inline bool is_valid(Geometry const& geometry, validity_failure_type& failure, Strategy const& strategy)
+{
+ failure_type_policy<> visitor;
+ bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ failure = visitor.failure();
+ return result;
+}
+
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\param failure An enumeration value indicating that the geometry is
valid or not, and if not valid indicating the reason why
@@ -120,10 +212,7 @@ inline bool is_valid(Geometry const& geometry)
template <typename Geometry>
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)
{
- failure_type_policy<> policy_visitor;
- bool result = geometry::is_valid(geometry, policy_visitor);
- failure = policy_visitor.failure();
- return result;
+ return is_valid(geometry, failure, default_strategy());
}
@@ -131,28 +220,52 @@ inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)
\brief \brief_check{is valid (in the OGC sense)}
\ingroup is_valid
\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Is_valid}
\param geometry \param_geometry
\param message A string containing a message stating if the geometry
is valid or not, and if not valid a reason why
+\param strategy \param_strategy{is_valid}
\return \return_check{is valid (in the OGC sense);
furthermore, the following geometries are considered valid:
multi-geometries with no elements,
linear geometries containing spikes,
areal geometries with duplicate (consecutive) points}
-\qbk{distinguish,with message}
+\qbk{distinguish,with message and strategy}
\qbk{[include reference/algorithms/is_valid_with_message.qbk]}
*/
-template <typename Geometry>
-inline bool is_valid(Geometry const& geometry, std::string& message)
+template <typename Geometry, typename Strategy>
+inline bool is_valid(Geometry const& geometry, std::string& message, Strategy const& strategy)
{
std::ostringstream stream;
- failing_reason_policy<> policy_visitor(stream);
- bool result = geometry::is_valid(geometry, policy_visitor);
+ failing_reason_policy<> visitor(stream);
+ bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
message = stream.str();
return result;
}
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\param message A string containing a message stating if the geometry
+ is valid or not, and if not valid a reason why
+\return \return_check{is valid (in the OGC sense);
+ furthermore, the following geometries are considered valid:
+ multi-geometries with no elements,
+ linear geometries containing spikes,
+ areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with message}
+\qbk{[include reference/algorithms/is_valid_with_message.qbk]}
+*/
+template <typename Geometry>
+inline bool is_valid(Geometry const& geometry, std::string& message)
+{
+ return is_valid(geometry, message, default_strategy());
+}
+
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index a49e077237..6bc6b86cf8 100644
--- a/boost/geometry/algorithms/detail/is_valid/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -77,6 +77,14 @@ struct is_valid_linestring
}
return ! has_spikes<Linestring, closed>::apply(linestring, visitor);
}
+
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Linestring const& linestring,
+ VisitPolicy& visitor,
+ Strategy const&)
+ {
+ return apply(linestring, visitor);
+ }
};
@@ -142,9 +150,10 @@ private:
};
public:
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiLinestring const& multilinestring,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const&)
{
if (BOOST_GEOMETRY_CONDITION(
AllowEmptyMultiGeometries && boost::empty(multilinestring)))
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 0025445c2c..84dacc57f1 100644
--- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -43,6 +43,8 @@
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+
namespace boost { namespace geometry
{
@@ -109,10 +111,10 @@ private:
geometry::partition
<
- geometry::model::box<typename point_type<MultiPolygon>::type>,
- typename base::expand_box,
- typename base::overlaps_box
- >::apply(polygon_iterators, item_visitor);
+ geometry::model::box<typename point_type<MultiPolygon>::type>
+ >::apply(polygon_iterators, item_visitor,
+ typename base::expand_box(),
+ typename base::overlaps_box());
if (item_visitor.items_overlap)
{
@@ -235,23 +237,28 @@ private:
}
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
struct per_polygon
{
- per_polygon(VisitPolicy& policy) : m_policy(policy) {}
+ per_polygon(VisitPolicy& policy, Strategy const& strategy)
+ : m_policy(policy)
+ , m_strategy(strategy)
+ {}
template <typename Polygon>
inline bool apply(Polygon const& polygon) const
{
- return base::apply(polygon, m_policy);
+ return base::apply(polygon, m_policy, m_strategy);
}
VisitPolicy& m_policy;
+ Strategy const& m_strategy;
};
public:
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiPolygon const& multipolygon,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
typedef debug_validity_phase<MultiPolygon> debug_phase;
@@ -266,11 +273,11 @@ public:
if (! detail::check_iterator_range
<
- per_polygon<VisitPolicy>,
+ per_polygon<VisitPolicy, Strategy>,
false // do not check for empty multipolygon (done above)
>::apply(boost::begin(multipolygon),
boost::end(multipolygon),
- per_polygon<VisitPolicy>(visitor)))
+ per_polygon<VisitPolicy, Strategy>(visitor, strategy)))
{
return false;
}
@@ -283,7 +290,7 @@ public:
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns =
- ! has_valid_turns::apply(multipolygon, turns, visitor);
+ ! has_valid_turns::apply(multipolygon, turns, visitor, strategy);
debug_print_turns(turns.begin(), turns.end());
if (has_invalid_turns)
diff --git a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
index 51035f7a73..f77f7a35eb 100644
--- a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -36,8 +36,8 @@ namespace dispatch
template <typename Point>
struct is_valid<Point, point_tag>
{
- template <typename VisitPolicy>
- static inline bool apply(Point const& point, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Point const& point, VisitPolicy& visitor, Strategy const&)
{
boost::ignore_unused(visitor);
return ! detail::is_valid::has_invalid_coordinate
@@ -56,9 +56,10 @@ struct is_valid<Point, point_tag>
template <typename MultiPoint, bool AllowEmptyMultiGeometries>
struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries>
{
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiPoint const& multipoint,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const&)
{
boost::ignore_unused(multipoint, visitor);
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index bbe8e8fc39..f7e22fb8d2 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -74,10 +75,13 @@ class is_valid_polygon
protected:
typedef debug_validity_phase<Polygon> debug_phase;
- template <typename VisitPolicy>
+ template <typename VisitPolicy, typename Strategy>
struct per_ring
{
- per_ring(VisitPolicy& policy) : m_policy(policy) {}
+ per_ring(VisitPolicy& policy, Strategy const& strategy)
+ : m_policy(policy)
+ , m_strategy(strategy)
+ {}
template <typename Ring>
inline bool apply(Ring const& ring) const
@@ -85,30 +89,34 @@ protected:
return detail::is_valid::is_valid_ring
<
Ring, false, true
- >::apply(ring, m_policy);
+ >::apply(ring, m_policy, m_strategy);
}
VisitPolicy& m_policy;
+ Strategy const& m_strategy;
};
- template <typename InteriorRings, typename VisitPolicy>
+ template <typename InteriorRings, typename VisitPolicy, typename Strategy>
static bool has_valid_interior_rings(InteriorRings const& interior_rings,
- VisitPolicy& visitor)
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
return
detail::check_iterator_range
<
- per_ring<VisitPolicy>,
+ per_ring<VisitPolicy, Strategy>,
true // allow for empty interior ring range
>::apply(boost::begin(interior_rings),
boost::end(interior_rings),
- per_ring<VisitPolicy>(visitor));
+ per_ring<VisitPolicy, Strategy>(visitor, strategy));
}
struct has_valid_rings
{
- template <typename VisitPolicy>
- static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Polygon const& polygon,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
typedef typename ring_type<Polygon>::type ring_type;
@@ -119,7 +127,7 @@ protected:
<
ring_type,
false // do not check self intersections
- >::apply(exterior_ring(polygon), visitor))
+ >::apply(exterior_ring(polygon), visitor, strategy))
{
return false;
}
@@ -128,7 +136,8 @@ protected:
debug_phase::apply(2);
return has_valid_interior_rings(geometry::interior_rings(polygon),
- visitor);
+ visitor,
+ strategy);
}
};
@@ -246,10 +255,8 @@ protected:
geometry::partition
<
- geometry::model::box<typename point_type<Polygon>::type>,
- expand_box,
- overlaps_box
- >::apply(ring_iterators, item_visitor);
+ geometry::model::box<typename point_type<Polygon>::type>
+ >::apply(ring_iterators, item_visitor, expand_box(), overlaps_box());
if (item_visitor.items_overlap)
{
@@ -346,10 +353,12 @@ protected:
};
public:
- template <typename VisitPolicy>
- static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Polygon const& polygon,
+ VisitPolicy& visitor,
+ Strategy const& strategy)
{
- if (! has_valid_rings::apply(polygon, visitor))
+ if (! has_valid_rings::apply(polygon, visitor, strategy))
{
return false;
}
@@ -366,7 +375,7 @@ public:
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns
- = ! has_valid_turns::apply(polygon, turns, visitor);
+ = ! has_valid_turns::apply(polygon, turns, visitor, strategy);
debug_print_turns(turns.begin(), turns.end());
if (has_invalid_turns)
diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp
index 925c03a472..9ab68fdc48 100644
--- a/boost/geometry/algorithms/detail/is_valid/ring.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -101,26 +101,21 @@ struct ring_area_predicate<ResultType, true>
template <typename Ring, bool IsInteriorRing>
struct is_properly_oriented
{
- typedef typename point_type<Ring>::type point_type;
-
- typedef typename strategy::area::services::default_strategy
- <
- typename cs_tag<point_type>::type,
- point_type
- >::type strategy_type;
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor,
+ Strategy const& strategy)
+ {
+ boost::ignore_unused(visitor);
- typedef detail::area::ring_area
- <
- order_as_direction<geometry::point_order<Ring>::value>::value,
- geometry::closure<Ring>::value
- > ring_area_type;
+ typedef typename point_type<Ring>::type point_type;
- typedef typename default_area_result<Ring>::type area_result_type;
+ typedef detail::area::ring_area
+ <
+ order_as_direction<geometry::point_order<Ring>::value>::value,
+ geometry::closure<Ring>::value
+ > ring_area_type;
- template <typename VisitPolicy>
- static inline bool apply(Ring const& ring, VisitPolicy& visitor)
- {
- boost::ignore_unused(visitor);
+ typedef typename default_area_result<Ring>::type area_result_type;
typename ring_area_predicate
<
@@ -128,8 +123,11 @@ struct is_properly_oriented
>::type predicate;
// Check area
- area_result_type const zero = area_result_type();
- if (predicate(ring_area_type::apply(ring, strategy_type()), zero))
+ area_result_type const zero = 0;
+ area_result_type const area
+ = ring_area_type::apply(ring,
+ strategy.template get_area_strategy<point_type>());
+ if (predicate(area, zero))
{
return visitor.template apply<no_failure>();
}
@@ -150,8 +148,9 @@ template
>
struct is_valid_ring
{
- template <typename VisitPolicy>
- static inline bool apply(Ring const& ring, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor,
+ Strategy const& strategy)
{
// return invalid if any of the following condition holds:
// (a) the ring's point coordinates are not invalid (e.g., NaN)
@@ -198,8 +197,8 @@ struct is_valid_ring
&& ! has_duplicates<Ring, closure>::apply(ring, visitor)
&& ! has_spikes<Ring, closure>::apply(ring, visitor)
&& (! CheckSelfIntersections
- || has_valid_self_turns<Ring>::apply(ring, visitor))
- && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor);
+ || has_valid_self_turns<Ring>::apply(ring, visitor, strategy))
+ && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/segment.hpp b/boost/geometry/algorithms/detail/is_valid/segment.hpp
index f92f73381f..30cbf7afdb 100644
--- a/boost/geometry/algorithms/detail/is_valid/segment.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/segment.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -44,8 +44,8 @@ namespace dispatch
template <typename Segment>
struct is_valid<Segment, segment_tag>
{
- template <typename VisitPolicy>
- static inline bool apply(Segment const& segment, VisitPolicy& visitor)
+ template <typename VisitPolicy, typename Strategy>
+ static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&)
{
boost::ignore_unused(visitor);
diff --git a/boost/geometry/algorithms/detail/not.hpp b/boost/geometry/algorithms/detail/not.hpp
index 43e71e2e37..95cdfa24e6 100644
--- a/boost/geometry/algorithms/detail/not.hpp
+++ b/boost/geometry/algorithms/detail/not.hpp
@@ -4,10 +4,11 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -46,6 +47,14 @@ struct not_
{
return ! Policy::apply(geometry1, geometry2);
}
+
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return ! Policy::apply(geometry1, geometry2, strategy);
+ }
};
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index 047eb4993e..2408b4b68e 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -258,8 +262,9 @@ inline void assign_parents(Geometry1 const& geometry1,
geometry::partition
<
- box_type, ring_info_helper_get_box, ring_info_helper_ovelaps_box
- >::apply(vector, visitor);
+ box_type
+ >::apply(vector, visitor, ring_info_helper_get_box(),
+ ring_info_helper_ovelaps_box());
}
if (check_for_orientation)
diff --git a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
index a8171e1482..9beb8ad64f 100644
--- a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
+++ b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -106,19 +110,27 @@ class backtrack_check_self_intersections
public :
typedef state state_type;
- template <typename Operation, typename Rings, typename Ring, typename Turns, typename RobustPolicy, typename Visitor>
+ template
+ <
+ typename Operation,
+ typename Rings, typename Ring, typename Turns,
+ typename Strategy,
+ typename RobustPolicy,
+ typename Visitor
+ >
static inline void apply(std::size_t size_at_start,
- Rings& rings, Ring& ring,
- Turns& turns,
- typename boost::range_value<Turns>::type const& turn,
- Operation& operation,
- traverse_error_type traverse_error,
- Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- state_type& state,
- Visitor& visitor
- )
+ Rings& rings,
+ Ring& ring,
+ Turns& turns,
+ typename boost::range_value<Turns>::type const& turn,
+ Operation& operation,
+ traverse_error_type traverse_error,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy,
+ RobustPolicy const& robust_policy,
+ state_type& state,
+ Visitor& visitor)
{
visitor.visit_traverse_reject(turns, turn, operation, traverse_error);
@@ -128,8 +140,8 @@ public :
if (! state.m_checked)
{
state.m_checked = true;
- has_self_intersections(geometry1, robust_policy);
- has_self_intersections(geometry2, robust_policy);
+ has_self_intersections(geometry1, strategy, robust_policy);
+ has_self_intersections(geometry2, strategy, robust_policy);
}
// Make bad output clean
diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
index b9e48cdbfc..c249ff57ff 100644
--- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
@@ -1,5 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
@@ -15,6 +17,7 @@
#include <iterator>
#include <boost/range.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag.hpp>
@@ -307,7 +310,7 @@ public:
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
if (enter_count != 0)
{
- throw inconsistent_turns_exception();
+ BOOST_THROW_EXCEPTION(inconsistent_turns_exception());
}
#else
BOOST_GEOMETRY_ASSERT(enter_count == 0);
diff --git a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
index 99281eaecb..94667d0ed0 100644
--- a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -39,29 +44,33 @@ template
>
struct get_turn_without_info
{
- template <typename RobustPolicy, typename OutputIterator>
+ template <typename Strategy, typename RobustPolicy, typename OutputIterator>
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/,
Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/,
bool /*is_p_first*/, bool /*is_p_last*/,
bool /*is_q_first*/, bool /*is_q_last*/,
TurnInfo const& ,
+ Strategy const& strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_strategies
- <
- typename cs_tag<typename TurnInfo::point_type>::type,
- Point1,
- Point2,
- typename TurnInfo::point_type,
- RobustPolicy
- > si;
+ typedef typename TurnInfo::point_type turn_point_type;
- typedef typename si::segment_intersection_strategy_type strategy;
+ typedef policies::relate::segments_intersection_points
+ <
+ segment_intersection_points
+ <
+ turn_point_type,
+ typename geometry::segment_ratio_type
+ <
+ turn_point_type, RobustPolicy
+ >::type
+ >
+ > policy_type;
typedef model::referring_segment<Point1 const> segment_type1;
- typedef model::referring_segment<Point1 const> segment_type2;
+ typedef model::referring_segment<Point2 const> segment_type2;
segment_type1 p1(pi, pj);
segment_type2 q1(qi, qj);
@@ -75,15 +84,14 @@ struct get_turn_without_info
geometry::recalculate(pj_rob, pj, robust_policy);
geometry::recalculate(qi_rob, qi, robust_policy);
geometry::recalculate(qj_rob, qj, robust_policy);
- typename strategy::return_type result
- = strategy::apply(p1, q1, robust_policy,
- pi_rob, pj_rob, qi_rob, qj_rob);
+ typename policy_type::return_type result
+ = strategy.apply(p1, q1, policy_type(), robust_policy,
+ pi_rob, pj_rob, qi_rob, qj_rob);
- for (std::size_t i = 0; i < result.template get<0>().count; i++)
+ for (std::size_t i = 0; i < result.count; i++)
{
-
TurnInfo tp;
- geometry::convert(result.template get<0>().intersections[i], tp.point);
+ geometry::convert(result.intersections[i], tp.point);
*out++ = tp;
}
@@ -102,12 +110,14 @@ template
typename Geometry1,
typename Geometry2,
typename RobustPolicy,
- typename Turns
+ typename Turns,
+ typename Strategy
>
inline void get_intersection_points(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- Turns& turns)
+ Turns& turns,
+ Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
@@ -142,6 +152,7 @@ inline void get_intersection_points(Geometry1 const& geometry1,
>::type::apply(
0, geometry1,
1, geometry2,
+ strategy,
robust_policy,
turns, interrupt_policy);
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index a4cce3fd32..08bc342186 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,10 +17,10 @@
#include <boost/core/ignore_unused.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
-#include <boost/geometry/strategies/intersection_strategies.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
@@ -644,7 +645,7 @@ struct collinear : public base_turn_handler
// causes currently cycling include problems
typedef typename geometry::coordinate_type<Point1>::type ctype;
ctype const dx = get<0>(a) - get<0>(b);
- ctype const dy = get<1>(b) - get<1>(b);
+ ctype const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
}
};
@@ -930,6 +931,7 @@ struct get_turn_info
typename Point1,
typename Point2,
typename TurnInfo,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -939,13 +941,19 @@ struct get_turn_info
bool /*is_p_first*/, bool /*is_p_last*/,
bool /*is_q_first*/, bool /*is_q_last*/,
TurnInfo const& tp_model,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
- inters_info;
+ typedef intersection_info
+ <
+ Point1, Point2,
+ typename TurnInfo::point_type,
+ IntersectionStrategy,
+ RobustPolicy
+ > inters_info;
- inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
+ inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy);
char const method = inters.d_info().how;
@@ -991,9 +999,12 @@ struct get_turn_info
<
typename inters_info::cs_tag,
typename inters_info::robust_point2_type,
- typename inters_info::robust_point1_type
+ typename inters_info::robust_point1_type,
+ typename inters_info::side_strategy_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
- inters.rpi(), inters.rpj(), inters.rpk());
+ inters.rpi(), inters.rpj(), inters.rpk(),
+ inters.get_side_strategy());
+
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
@@ -1093,7 +1104,7 @@ struct get_turn_info
std::cout << "TURN: Unknown method: " << method << std::endl;
#endif
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
- throw turn_info_exception(method);
+ BOOST_THROW_EXCEPTION(turn_info_exception(method));
#endif
}
break;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
index 85cdfbc02d..48716634c5 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
@@ -427,8 +427,11 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
- side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2>
- side_calc(ri2, ri1, rj1, ri2, rj2, rk2);
+ side_calculator<cs_tag,
+ RobustPoint1, RobustPoint2,
+ typename IntersectionInfo::side_strategy_type,
+ RobustPoint2>
+ side_calc(ri2, ri1, rj1, ri2, rj2, rk2, inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);
@@ -478,8 +481,10 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
- side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2>
- side_calc(ri2, rj1, ri1, ri2, rj2, rk2);
+ side_calculator<cs_tag, RobustPoint1, RobustPoint2,
+ typename IntersectionInfo::side_strategy_type,
+ RobustPoint2>
+ side_calc(ri2, rj1, ri1, ri2, rj2, rk2, inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
index 3e7da1d797..5f2cb07faf 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
@@ -37,32 +37,27 @@ struct turn_operation_linear
};
template <typename TurnPointCSTag, typename PointP, typename PointQ,
+ typename SideStrategy,
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
>
struct side_calculator
{
- // This strategy should be the same as side strategy defined in
- // intersection_strategies<> which is used in various places
- // of the library
- typedef typename strategy::side::services::default_strategy
- <
- TurnPointCSTag
- >::type side;
-
inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
- Qi const& qi, Qj const& qj, Qk const& qk)
+ Qi const& qi, Qj const& qj, Qk const& qk,
+ SideStrategy const& side_strategy)
: m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
+ , m_side_strategy(side_strategy)
{}
- inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); }
- inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); }
- inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); }
- inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); }
+ inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
+ inline int pk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_pk); }
+ inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); }
+ inline int qk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_qk); }
- inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); }
- inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); }
+ inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); }
+ inline int qk_wrt_p2() const { return m_side_strategy.apply(m_pj, m_pk, m_qk); }
Pi const& m_pi;
Pj const& m_pj;
@@ -70,6 +65,8 @@ struct side_calculator
Qi const& m_qi;
Qj const& m_qj;
Qk const& m_qk;
+
+ SideStrategy const& m_side_strategy;
};
template <typename Point1, typename Point2, typename RobustPolicy>
@@ -99,7 +96,7 @@ struct robust_points
robust_point2_type m_rqi, m_rqj, m_rqk;
};
-template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>
+template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy>
class intersection_info_base
: private robust_points<Point1, Point2, RobustPolicy>
{
@@ -114,14 +111,17 @@ public:
typedef typename cs_tag<TurnPoint>::type cs_tag;
- typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type> side_calculator_type;
+ typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+ typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type, side_strategy_type> side_calculator_type;
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
: base(pi, pj, pk, qi, qj, qk, robust_policy)
, m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk,
- base::m_rqi, base::m_rqj, base::m_rqk)
+ base::m_rqi, base::m_rqj, base::m_rqk,
+ intersection_strategy.get_side_strategy())
, m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
{}
@@ -155,8 +155,8 @@ private:
point2_type const& m_qk;
};
-template <typename Point1, typename Point2, typename TurnPoint>
-class intersection_info_base<Point1, Point2, TurnPoint, detail::no_rescale_policy>
+template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy>
+class intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, detail::no_rescale_policy>
{
public:
typedef Point1 point1_type;
@@ -167,12 +167,15 @@ public:
typedef typename cs_tag<TurnPoint>::type cs_tag;
- typedef side_calculator<cs_tag, Point1, Point2> side_calculator_type;
+ typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
+ typedef side_calculator<cs_tag, Point1, Point2, side_strategy_type> side_calculator_type;
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ IntersectionStrategy const& intersection_strategy,
no_rescale_policy const& /*robust_policy*/)
- : m_side_calc(pi, pj, pk, qi, qj, qk)
+ : m_side_calc(pi, pj, pk, qi, qj, qk,
+ intersection_strategy.get_side_strategy())
{}
inline Point1 const& pi() const { return m_side_calc.m_pi; }
@@ -203,40 +206,58 @@ template
typename Point1,
typename Point2,
typename TurnPoint,
+ typename IntersectionStrategy,
typename RobustPolicy
>
class intersection_info
- : public intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy>
+ : public intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy>
{
- typedef intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy> base;
+ typedef intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> base;
+
+public:
+ typedef segment_intersection_points
+ <
+ TurnPoint,
+ typename geometry::segment_ratio_type
+ <
+ TurnPoint, RobustPolicy
+ >::type
+ > intersection_point_type;
- typedef typename intersection_strategies
+ // NOTE: formerly defined in intersection_strategies
+ typedef policies::relate::segments_tupled
<
- typename base::cs_tag,
- Point1,
- Point2,
- TurnPoint,
- RobustPolicy
- >::segment_intersection_strategy_type strategy;
+ policies::relate::segments_intersection_points
+ <
+ intersection_point_type
+ >,
+ policies::relate::segments_direction
+ > intersection_policy_type;
+
+ typedef IntersectionStrategy intersection_strategy_type;
+ typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
-public:
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
typedef typename base::side_calculator_type side_calculator_type;
- typedef typename strategy::return_type result_type;
+ typedef typename intersection_policy_type::return_type result_type;
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
- : base(pi, pj, pk, qi, qj, qk, robust_policy)
- , m_result(strategy::apply(segment_type1(pi, pj),
- segment_type2(qi, qj),
- robust_policy,
- base::rpi(), base::rpj(),
- base::rqi(), base::rqj()))
+ : base(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy)
+ , m_result(intersection_strategy.apply(
+ segment_type1(pi, pj),
+ segment_type2(qi, qj),
+ intersection_policy_type(),
+ robust_policy,
+ base::rpi(), base::rpj(),
+ base::rqi(), base::rqj()))
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
{}
@@ -244,6 +265,16 @@ public:
inline i_info_type const& i_info() const { return m_result.template get<0>(); }
inline d_info_type const& d_info() const { return m_result.template get<1>(); }
+ inline intersection_strategy_type const& get_intersection_strategy() const
+ {
+ return m_intersection_strategy;
+ }
+
+ inline side_strategy_type get_side_strategy() const
+ {
+ return m_intersection_strategy.get_side_strategy();
+ }
+
// TODO: it's more like is_spike_ip_p
inline bool is_spike_p() const
{
@@ -307,17 +338,18 @@ private:
{
typedef model::referring_segment<Point const> seg;
- typedef intersection_strategies
- <
- typename base::cs_tag, Point, Point, Point, RobustPolicy
- > si;
-
- typedef typename si::segment_intersection_strategy_type strategy;
-
- typename strategy::return_type result
- = strategy::apply(seg(i, j), seg(j, k), m_robust_policy);
+ // no need to calcualte direction info
+ typedef policies::relate::segments_intersection_points
+ <
+ intersection_point_type
+ > policy_type;
+
+ typename policy_type::return_type const result
+ = m_intersection_strategy.apply(seg(i, j), seg(j, k),
+ policy_type(),
+ m_robust_policy);
- return result.template get<0>().count == 2;
+ return result.count == 2;
}
template <std::size_t OpId>
@@ -344,6 +376,7 @@ private:
}
result_type m_result;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
};
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
index 121728d822..46c1305cd7 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,6 +15,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP
+#include <boost/throw_exception.hpp>
+
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -41,6 +44,7 @@ struct get_turn_info_linear_areal
typename Point1,
typename Point2,
typename TurnInfo,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -50,13 +54,19 @@ struct get_turn_info_linear_areal
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
- inters_info;
+ typedef intersection_info
+ <
+ Point1, Point2,
+ typename TurnInfo::point_type,
+ IntersectionStrategy,
+ RobustPolicy
+ > inters_info;
- inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
+ inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy);
char const method = inters.d_info().how;
@@ -108,9 +118,11 @@ struct get_turn_info_linear_areal
<
typename inters_info::cs_tag,
typename inters_info::robust_point2_type,
- typename inters_info::robust_point1_type
+ typename inters_info::robust_point1_type,
+ typename inters_info::side_strategy_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
- inters.rpi(), inters.rpj(), inters.rpk());
+ inters.rpi(), inters.rpj(), inters.rpk(),
+ inters.get_side_strategy());
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
@@ -395,7 +407,7 @@ struct get_turn_info_linear_areal
std::cout << "TURN: Unknown method: " << method << std::endl;
#endif
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
- throw turn_info_exception(method);
+ BOOST_THROW_EXCEPTION(turn_info_exception(method));
#endif
}
break;
@@ -747,6 +759,9 @@ struct get_turn_info_linear_areal
}
else
{
+ typedef typename IntersectionInfo::robust_point1_type rp1_type;
+ typedef typename IntersectionInfo::robust_point2_type rp2_type;
+
method_type replaced_method = method_touch_interior;
if ( ip0.is_qj )
@@ -754,11 +769,12 @@ struct get_turn_info_linear_areal
side_calculator
<
typename IntersectionInfo::cs_tag,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point2_type
+ rp1_type, rp2_type,
+ typename IntersectionInfo::side_strategy_type,
+ rp2_type
> side_calc(inters.rqi(), inters.rpi(), inters.rpj(),
- inters.rqi(), inters.rqj(), inters.rqk());
+ inters.rqi(), inters.rqj(), inters.rqk(),
+ inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
@@ -773,16 +789,13 @@ struct get_turn_info_linear_areal
side_calculator
<
typename IntersectionInfo::cs_tag,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type,
- typename IntersectionInfo::robust_point1_type,
- typename IntersectionInfo::robust_point2_type
+ rp1_type, rp2_type,
+ typename IntersectionInfo::side_strategy_type,
+ rp2_type, rp1_type, rp1_type,
+ rp2_type, rp1_type, rp2_type
> side_calc(inters.rqi(), inters.rpi(), inters.rpj(),
- inters.rqi(), inters.rpi(), inters.rqj());
+ inters.rqi(), inters.rpi(), inters.rqj(),
+ inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
@@ -832,9 +845,11 @@ struct get_turn_info_linear_areal
typename IntersectionInfo::cs_tag,
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point2_type,
+ typename IntersectionInfo::side_strategy_type,
typename IntersectionInfo::robust_point2_type
> side_calc(inters.rqi(), inters.rpj(), inters.rpi(),
- inters.rqi(), inters.rqj(), inters.rqk());
+ inters.rqi(), inters.rqj(), inters.rqk(),
+ inters.get_side_strategy());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
index 6bb3a74bb8..58fd4bb5c7 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
@@ -1,19 +1,22 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP
+#include <boost/throw_exception.hpp>
+
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
@@ -36,6 +39,7 @@ struct get_turn_info_linear_linear
typename Point1,
typename Point2,
typename TurnInfo,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename OutputIterator
>
@@ -45,13 +49,19 @@ struct get_turn_info_linear_linear
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
+ IntersectionStrategy const& strategy,
RobustPolicy const& robust_policy,
OutputIterator out)
{
- typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
- inters_info;
+ typedef intersection_info
+ <
+ Point1, Point2,
+ typename TurnInfo::point_type,
+ IntersectionStrategy,
+ RobustPolicy
+ > inters_info;
- inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
+ inters_info inters(pi, pj, pk, qi, qj, qk, strategy, robust_policy);
char const method = inters.d_info().how;
@@ -103,9 +113,11 @@ struct get_turn_info_linear_linear
<
typename inters_info::cs_tag,
typename inters_info::robust_point2_type,
- typename inters_info::robust_point1_type
+ typename inters_info::robust_point1_type,
+ typename inters_info::side_strategy_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
- inters.rpi(), inters.rpj(), inters.rpk());
+ inters.rpi(), inters.rpj(), inters.rpk(),
+ inters.get_side_strategy());
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
@@ -463,7 +475,7 @@ struct get_turn_info_linear_linear
std::cout << "TURN: Unknown method: " << method << std::endl;
#endif
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
- throw turn_info_exception(method);
+ BOOST_THROW_EXCEPTION(turn_info_exception(method));
#endif
}
break;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
index 1eb18b74d4..4e97a84a37 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -3,15 +3,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014, 2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
@@ -45,7 +45,6 @@
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
-#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
#include <boost/geometry/strategies/intersection_strategies.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
@@ -174,11 +173,12 @@ class get_turns_in_sections
public :
// Returns true if terminated, false if interrupted
- template <typename Turns, typename RobustPolicy, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply(
int source_id1, Geometry1 const& geometry1, Section1 const& sec1,
int source_id2, Geometry2 const& geometry2, Section2 const& sec2,
bool skip_larger,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy)
@@ -295,7 +295,8 @@ public :
TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2,
is_1_first, is_1_last, is_2_first, is_2_last,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
if (InterruptPolicy::enabled)
{
@@ -381,9 +382,10 @@ template
<
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2,
- typename Turns,
typename TurnPolicy,
+ typename IntersectionStrategy,
typename RobustPolicy,
+ typename Turns,
typename InterruptPolicy
>
struct section_visitor
@@ -392,16 +394,20 @@ struct section_visitor
Geometry1 const& m_geometry1;
int m_source_id2;
Geometry2 const& m_geometry2;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_rescale_policy;
Turns& m_turns;
InterruptPolicy& m_interrupt_policy;
section_visitor(int id1, Geometry1 const& g1,
- int id2, Geometry2 const& g2,
- RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& ip)
+ int id2, Geometry2 const& g2,
+ IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& ip)
: m_source_id1(id1), m_geometry1(g1)
, m_source_id2(id2), m_geometry2(g2)
+ , m_intersection_strategy(intersection_strategy)
, m_rescale_policy(robust_policy)
, m_turns(turns)
, m_interrupt_policy(ip)
@@ -423,6 +429,7 @@ struct section_visitor
m_source_id1, m_geometry1, sec1,
m_source_id2, m_geometry2, sec2,
false,
+ m_intersection_strategy,
m_rescale_policy,
m_turns, m_interrupt_policy);
}
@@ -441,10 +448,11 @@ class get_turns_generic
{
public:
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Geometry1 const& geometry1,
int source_id2, Geometry2 const& geometry2,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy)
@@ -475,15 +483,19 @@ public:
<
Geometry1, Geometry2,
Reverse1, Reverse2,
- Turns, TurnPolicy, RobustPolicy, InterruptPolicy
- > visitor(source_id1, geometry1, source_id2, geometry2, robust_policy, turns, interrupt_policy);
+ TurnPolicy,
+ IntersectionStrategy, RobustPolicy,
+ Turns, InterruptPolicy
+ > visitor(source_id1, geometry1, source_id2, geometry2,
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy);
geometry::partition
<
- box_type,
- detail::section::get_section_box,
- detail::section::overlaps_section_box
- >::apply(sec1, sec2, visitor);
+ box_type
+ >::apply(sec1, sec2, visitor,
+ detail::section::get_section_box(),
+ detail::section::overlaps_section_box());
}
};
@@ -518,10 +530,11 @@ struct get_turns_cs
>::type iterator_type;
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Range const& range,
int source_id2, Box const& box,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
@@ -593,8 +606,10 @@ struct get_turns_cs
// NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes
index == 0,
size_type(index) == segments_count1,
+ intersection_strategy,
robust_policy,
- turns, interrupt_policy);
+ turns,
+ interrupt_policy);
// Future performance enhancement:
// return if told by the interrupt policy
}
@@ -622,7 +637,7 @@ private:
else return 0;
}
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2,
// Points from a range:
point_type const& rp0,
@@ -635,6 +650,7 @@ private:
box_point_type const& bp3,
bool const is_range_first,
bool const is_range_last,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
// Output
Turns& turns,
@@ -653,25 +669,29 @@ private:
TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2,
is_range_first, is_range_last,
true, false,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1);
TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3,
is_range_first, is_range_last,
false, false,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2);
TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0,
is_range_first, is_range_last,
false, false,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);
TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1,
is_range_first, is_range_last,
false, true,
- ti, robust_policy, std::back_inserter(turns));
+ ti, intersection_strategy, robust_policy,
+ std::back_inserter(turns));
if (InterruptPolicy::enabled)
{
@@ -691,12 +711,14 @@ template
>
struct get_turns_polygon_cs
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Polygon const& polygon,
int source_id2, Box const& box,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& interrupt_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
signed_size_type multi_index = -1)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
@@ -711,8 +733,10 @@ struct get_turns_polygon_cs
intersector_type::apply(
source_id1, geometry::exterior_ring(polygon),
source_id2, box,
+ intersection_strategy,
robust_policy,
- turns, interrupt_policy,
+ turns,
+ interrupt_policy,
multi_index, -1);
signed_size_type i = 0;
@@ -725,6 +749,7 @@ struct get_turns_polygon_cs
intersector_type::apply(
source_id1, *it,
source_id2, box,
+ intersection_strategy,
robust_policy,
turns, interrupt_policy,
multi_index, i);
@@ -742,12 +767,14 @@ template
>
struct get_turns_multi_polygon_cs
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline void apply(
int source_id1, Multi const& multi,
int source_id2, Box const& box,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& interrupt_policy)
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
{
typedef typename boost::range_iterator
<
@@ -766,7 +793,8 @@ struct get_turns_multi_polygon_cs
Reverse, ReverseBox,
TurnPolicy
>::apply(source_id1, *it, source_id2, box,
- robust_policy, turns, interrupt_policy, i);
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy, i);
}
}
};
@@ -918,13 +946,13 @@ template
>
struct get_turns_reversed
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
- static inline void apply(
- int source_id1, Geometry1 const& g1,
- int source_id2, Geometry2 const& g2,
- RobustPolicy const& robust_policy,
- Turns& turns,
- InterruptPolicy& interrupt_policy)
+ template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ static inline void apply(int source_id1, Geometry1 const& g1,
+ int source_id2, Geometry2 const& g2,
+ IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
{
get_turns
<
@@ -932,8 +960,9 @@ struct get_turns_reversed
Geometry2, Geometry1,
Reverse2, Reverse1,
TurnPolicy
- >::apply(source_id2, g2, source_id1, g1, robust_policy,
- turns, interrupt_policy);
+ >::apply(source_id2, g2, source_id1, g1,
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy);
}
};
@@ -951,6 +980,7 @@ struct get_turns_reversed
\tparam Turns type of turn-container (e.g. vector of "intersection/turn point"'s)
\param geometry1 \param_geometry
\param geometry2 \param_geometry
+\param intersection_strategy segments intersection strategy
\param robust_policy policy to handle robustness issues
\param turns container which will contain turn points
\param interrupt_policy policy determining if process is stopped
@@ -962,15 +992,17 @@ template
typename AssignPolicy,
typename Geometry1,
typename Geometry2,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
inline void get_turns(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- Turns& turns,
- InterruptPolicy& interrupt_policy)
+ Geometry2 const& geometry2,
+ IntersectionStrategy const& intersection_strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
{
concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
@@ -996,11 +1028,11 @@ inline void get_turns(Geometry1 const& geometry1,
Reverse1, Reverse2,
TurnPolicy
>
- >::type::apply(
- 0, geometry1,
- 1, geometry2,
- robust_policy,
- turns, interrupt_policy);
+ >::type::apply(0, geometry1,
+ 1, geometry2,
+ intersection_strategy,
+ robust_policy,
+ turns, interrupt_policy);
}
#if defined(_MSC_VER)
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index bb82003a23..3244480f48 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -71,7 +72,7 @@ struct intersection_segment_segment_point
Segment2 const& segment2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
@@ -106,16 +107,15 @@ struct intersection_segment_segment_point
>::type
> intersection_return_type;
- typedef strategy::intersection::relate_cartesian_segments
+ typedef policies::relate::segments_intersection_points
<
- policies::relate::segments_intersection_points
- <
- intersection_return_type
- >
- > policy;
+ intersection_return_type
+ > policy_type;
- intersection_return_type is = policy::apply(segment1, segment2,
- robust_policy, pi_rob, pj_rob, qi_rob, qj_rob);
+ intersection_return_type
+ is = strategy.apply(segment1, segment2,
+ policy_type(), robust_policy,
+ pi_rob, pj_rob, qi_rob, qj_rob);
for (std::size_t i = 0; i < is.count; i++)
{
@@ -134,13 +134,14 @@ struct intersection_linestring_linestring_point
<
typename Linestring1, typename Linestring2,
typename RobustPolicy,
- typename OutputIterator, typename Strategy
+ typename OutputIterator,
+ typename Strategy
>
static inline OutputIterator apply(Linestring1 const& linestring1,
Linestring2 const& linestring2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
@@ -151,7 +152,8 @@ struct intersection_linestring_linestring_point
> turn_info;
std::deque<turn_info> turns;
- geometry::get_intersection_points(linestring1, linestring2, robust_policy, turns);
+ geometry::get_intersection_points(linestring1, linestring2,
+ robust_policy, turns, strategy);
for (typename boost::range_iterator<std::deque<turn_info> const>::type
it = boost::begin(turns); it != boost::end(turns); ++it)
@@ -295,7 +297,7 @@ struct intersection_of_linestring_with_areal
static inline OutputIterator apply(LineString const& linestring, Areal const& areal,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& strategy)
{
if (boost::size(linestring) == 0)
{
@@ -325,7 +327,7 @@ struct intersection_of_linestring_with_areal
false,
(OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
detail::overlay::assign_null_policy
- >(linestring, areal, robust_policy, turns, policy);
+ >(linestring, areal, strategy, robust_policy, turns, policy);
if (no_crossing_turns_or_empty(turns))
{
@@ -621,7 +623,7 @@ struct intersection_insert
static inline OutputIterator apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- OutputIterator out, Strategy const& )
+ OutputIterator out, Strategy const& strategy)
{
typedef detail::overlay::turn_info
@@ -635,7 +637,7 @@ struct intersection_insert
geometry::get_turns
<
false, false, detail::overlay::assign_null_policy
- >(geometry1, geometry2, robust_policy, turns, policy);
+ >(geometry1, geometry2, strategy, robust_policy, turns, policy);
for (typename std::vector<turn_info>::const_iterator it
= turns.begin(); it != turns.end(); ++it)
{
@@ -996,7 +998,11 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- typedef typename Strategy::rescale_policy_type rescale_policy_type;
+ typedef typename geometry::rescale_policy_type
+ <
+ typename geometry::point_type<Geometry1>::type // TODO from both
+ >::type rescale_policy_type;
+
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
@@ -1037,22 +1043,13 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- typedef typename geometry::rescale_policy_type
- <
- typename geometry::point_type<Geometry1>::type // TODO from both
- >::type rescale_policy_type;
-
- typedef intersection_strategies
+ typedef typename strategy::intersection::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- rescale_policy_type
- > strategy;
-
+ typename cs_tag<GeometryOut>::type
+ >::type strategy_type;
+
return intersection_insert<GeometryOut>(geometry1, geometry2, out,
- strategy());
+ strategy_type());
}
}} // namespace detail::intersection
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index 34517f6590..a74bb33ba1 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -1,11 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP
@@ -158,11 +159,13 @@ protected:
typename Turns,
typename LinearGeometry1,
typename LinearGeometry2,
+ typename IntersectionStrategy,
typename RobustPolicy
>
static inline void compute_turns(Turns& turns,
LinearGeometry1 const& linear1,
LinearGeometry2 const& linear2,
+ IntersectionStrategy const& strategy,
RobustPolicy const& robust_policy)
{
turns.clear();
@@ -180,7 +183,7 @@ protected:
assign_policy
>,
RobustPolicy
- >::apply(turns, linear1, linear2, interrupt_policy, robust_policy);
+ >::apply(turns, linear1, linear2, interrupt_policy, strategy, robust_policy);
}
@@ -237,7 +240,7 @@ public:
Linear2 const& linear2,
RobustPolicy const& robust_policy,
OutputIterator oit,
- Strategy const& )
+ Strategy const& strategy)
{
typedef typename detail::relate::turns::get_turns
<
@@ -255,7 +258,7 @@ public:
typedef std::vector<turn_info> turns_container;
turns_container turns;
- compute_turns(turns, linear1, linear2, robust_policy);
+ compute_turns(turns, linear1, linear2, strategy, robust_policy);
if ( turns.empty() )
{
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 09c80025a0..f1af2f1949 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -3,10 +3,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -184,7 +185,7 @@ struct overlay
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& ,
+ Strategy const& strategy,
Visitor& visitor)
{
bool const is_empty1 = geometry::is_empty(geometry1);
@@ -233,7 +234,7 @@ std::cout << "get turns" << std::endl;
<
Reverse1, Reverse2,
detail::overlay::assign_null_policy
- >(geometry1, geometry2, robust_policy, turns, policy);
+ >(geometry1, geometry2, strategy, robust_policy, turns, policy);
visitor.visit_turns(1, turns);
@@ -262,6 +263,7 @@ std::cout << "traverse" << std::endl;
traverse<Reverse1, Reverse2, Geometry1, Geometry2, OverlayType>::apply
(
geometry1, geometry2,
+ strategy,
robust_policy,
turns, rings,
clusters,
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
index 156cb54867..a26f54e008 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
@@ -1,12 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2015-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
-// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
@@ -69,12 +70,12 @@ struct point_linear_point
Linear const& linear,
RobustPolicy const&,
OutputIterator oit,
- Strategy const&)
+ Strategy const& strategy)
{
action_selector_pl_l
<
PointOut, OverlayType
- >::apply(point, Policy::apply(point, linear), oit);
+ >::apply(point, Policy::apply(point, linear, strategy), oit);
return oit;
}
};
@@ -95,7 +96,7 @@ struct multipoint_segment_point
Segment const& segment,
RobustPolicy const&,
OutputIterator oit,
- Strategy const&)
+ Strategy const& strategy)
{
for (typename boost::range_iterator<MultiPoint const>::type
it = boost::begin(multipoint);
@@ -105,7 +106,7 @@ struct multipoint_segment_point
action_selector_pl_l
<
PointOut, OverlayType
- >::apply(*it, Policy::apply(*it, segment), oit);
+ >::apply(*it, Policy::apply(*it, segment, strategy), oit);
}
return oit;
@@ -145,11 +146,14 @@ private:
}
};
- template <typename OutputIterator>
+ template <typename OutputIterator, typename Strategy>
class item_visitor_type
{
public:
- item_visitor_type(OutputIterator& oit) : m_oit(oit) {}
+ item_visitor_type(OutputIterator& oit, Strategy const& strategy)
+ : m_oit(oit)
+ , m_strategy(strategy)
+ {}
template <typename Item1, typename Item2>
inline void apply(Item1 const& item1, Item2 const& item2)
@@ -157,11 +161,12 @@ private:
action_selector_pl_l
<
PointOut, overlay_intersection
- >::apply(item1, Policy::apply(item1, item2), m_oit);
+ >::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit);
}
private:
OutputIterator& m_oit;
+ Strategy const& m_strategy;
};
// structs for partition -- end
@@ -189,12 +194,13 @@ private:
Linear const& m_linear;
};
- template <typename OutputIterator>
+ template <typename OutputIterator, typename Strategy>
static inline OutputIterator get_common_points(MultiPoint const& multipoint,
Linear const& linear,
- OutputIterator oit)
+ OutputIterator oit,
+ Strategy const& strategy)
{
- item_visitor_type<OutputIterator> item_visitor(oit);
+ item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
segment_range rng(linear);
@@ -203,10 +209,9 @@ private:
geometry::model::box
<
typename boost::range_value<MultiPoint>::type
- >,
- expand_box,
- overlaps_box
- >::apply(multipoint, rng, item_visitor);
+ >
+ >::apply(multipoint, rng, item_visitor,
+ expand_box(), overlaps_box());
return oit;
}
@@ -228,7 +233,8 @@ public:
// compute the common points
get_common_points(multipoint, linear,
- std::back_inserter(common_points));
+ std::back_inserter(common_points),
+ strategy);
return multipoint_multipoint_point
<
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
index aedf22e1fb..8540ef98a0 100644
--- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -61,20 +66,25 @@ template
typename Geometry,
typename Turns,
typename TurnPolicy,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename InterruptPolicy
>
struct self_section_visitor
{
Geometry const& m_geometry;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_rescale_policy;
Turns& m_turns;
InterruptPolicy& m_interrupt_policy;
inline self_section_visitor(Geometry const& g,
- RobustPolicy const& rp,
- Turns& turns, InterruptPolicy& ip)
+ IntersectionStrategy const& is,
+ RobustPolicy const& rp,
+ Turns& turns,
+ InterruptPolicy& ip)
: m_geometry(g)
+ , m_intersection_strategy(is)
, m_rescale_policy(rp)
, m_turns(turns)
, m_interrupt_policy(ip)
@@ -97,6 +107,7 @@ struct self_section_visitor
0, m_geometry, sec1,
0, m_geometry, sec2,
false,
+ m_intersection_strategy,
m_rescale_policy,
m_turns, m_interrupt_policy);
}
@@ -116,9 +127,10 @@ struct self_section_visitor
template<typename TurnPolicy>
struct get_turns
{
- template <typename Geometry, typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename Geometry, typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply(
Geometry const& geometry,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy)
@@ -142,17 +154,17 @@ struct get_turns
self_section_visitor
<
Geometry,
- Turns, TurnPolicy, RobustPolicy, InterruptPolicy
- > visitor(geometry, robust_policy, turns, interrupt_policy);
+ Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy
+ > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy);
try
{
geometry::partition
<
- box_type,
- detail::section::get_section_box,
- detail::section::overlaps_section_box
- >::apply(sec, visitor);
+ box_type
+ >::apply(sec, visitor,
+ detail::section::get_section_box(),
+ detail::section::overlaps_section_box());
}
catch(self_ip_exception const& )
{
@@ -208,9 +220,10 @@ struct self_get_turn_points
TurnPolicy
>
{
- template <typename RobustPolicy, typename Turns, typename InterruptPolicy>
+ template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
static inline bool apply(
Box const& ,
+ Strategy const& ,
RobustPolicy const& ,
Turns& ,
InterruptPolicy& )
@@ -259,6 +272,7 @@ struct self_get_turn_points
\tparam Turns type of intersection container
(e.g. vector of "intersection/turn point"'s)
\param geometry geometry
+ \param strategy strategy to be used
\param robust_policy policy to handle robustness issues
\param turns container which will contain intersection points
\param interrupt_policy policy determining if process is stopped
@@ -268,13 +282,15 @@ template
<
typename AssignPolicy,
typename Geometry,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
inline void self_turns(Geometry const& geometry,
- RobustPolicy const& robust_policy,
- Turns& turns, InterruptPolicy& interrupt_policy)
+ IntersectionStrategy const& strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns, InterruptPolicy& interrupt_policy)
{
concepts::check<Geometry const>();
@@ -285,7 +301,7 @@ inline void self_turns(Geometry const& geometry,
typename tag<Geometry>::type,
Geometry,
turn_policy
- >::apply(geometry, robust_policy, turns, interrupt_policy);
+ >::apply(geometry, strategy, robust_policy, turns, interrupt_policy);
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp
index 5adc0fcf69..bc828920e9 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp
@@ -140,10 +140,10 @@ struct traversal
{
for (int i = 0; i < 2; i++)
{
- turn_operation_type& op = turn.operations[i];
- if (op.visited.none())
+ turn_operation_type& turn_op = turn.operations[i];
+ if (turn_op.visited.none())
{
- op.visited.set_visited();
+ turn_op.visited.set_visited();
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
index e0dfee19a8..9ab82a77c1 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -38,6 +42,7 @@ template
typename Geometry2,
typename Turns,
typename Clusters,
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Visitor,
typename Backtrack
@@ -56,12 +61,14 @@ struct traversal_ring_creator
inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2,
Turns& turns, Clusters const& clusters,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy, Visitor& visitor)
: m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor)
, m_geometry1(geometry1)
, m_geometry2(geometry2)
, m_turns(turns)
, m_clusters(clusters)
+ , m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
, m_visitor(visitor)
{
@@ -280,7 +287,8 @@ struct traversal_ring_creator
rings, ring, m_turns, start_turn,
m_turns[turn_index].operations[op_index],
traverse_error,
- m_geometry1, m_geometry2, m_robust_policy,
+ m_geometry1, m_geometry2,
+ m_intersection_strategy, m_robust_policy,
state, m_visitor);
}
}
@@ -314,6 +322,7 @@ private:
Geometry2 const& m_geometry2;
Turns& m_turns;
Clusters const& m_clusters;
+ IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
Visitor& m_visitor;
};
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
index f01e50eb03..058f6c9458 100644
--- a/boost/geometry/algorithms/detail/overlay/traverse.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -58,6 +58,7 @@ class traverse
public :
template
<
+ typename IntersectionStrategy,
typename RobustPolicy,
typename Turns,
typename Rings,
@@ -66,6 +67,7 @@ public :
>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns, Rings& rings,
Clusters& clusters,
@@ -88,10 +90,11 @@ public :
Reverse1, Reverse2, OverlayType,
Geometry1, Geometry2,
Turns, Clusters,
+ IntersectionStrategy,
RobustPolicy, Visitor,
Backtrack
> trav(geometry1, geometry2, turns, clusters,
- robust_policy, visitor);
+ intersection_strategy, robust_policy, visitor);
std::size_t finalized_ring_size = boost::size(rings);
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
index 8b19add479..12c6a54661 100644
--- a/boost/geometry/algorithms/detail/partition.hpp
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -47,13 +48,14 @@ inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
// Divide forward_range into three subsets: lower, upper and oversized
// (not-fitting)
// (lower == left or bottom, upper == right or top)
-template <typename OverlapsPolicy, typename Box, typename IteratorVector>
+template <typename Box, typename IteratorVector, typename OverlapsPolicy>
inline void divide_into_subsets(Box const& lower_box,
- Box const& upper_box,
- IteratorVector const& input,
- IteratorVector& lower,
- IteratorVector& upper,
- IteratorVector& exceeding)
+ Box const& upper_box,
+ IteratorVector const& input,
+ IteratorVector& lower,
+ IteratorVector& upper,
+ IteratorVector& exceeding,
+ OverlapsPolicy const& overlaps_policy)
{
typedef typename boost::range_iterator
<
@@ -62,8 +64,8 @@ inline void divide_into_subsets(Box const& lower_box,
for(it_type it = boost::begin(input); it != boost::end(input); ++it)
{
- bool const lower_overlapping = OverlapsPolicy::apply(lower_box, **it);
- bool const upper_overlapping = OverlapsPolicy::apply(upper_box, **it);
+ bool const lower_overlapping = overlaps_policy.apply(lower_box, **it);
+ bool const upper_overlapping = overlaps_policy.apply(upper_box, **it);
if (lower_overlapping && upper_overlapping)
{
@@ -87,23 +89,24 @@ inline void divide_into_subsets(Box const& lower_box,
template
<
- typename ExpandPolicy,
typename Box,
- typename IteratorVector
+ typename IteratorVector,
+ typename ExpandPolicy
>
-inline void expand_with_elements(Box& total, IteratorVector const& input)
+inline void expand_with_elements(Box& total, IteratorVector const& input,
+ ExpandPolicy const& expand_policy)
{
typedef typename boost::range_iterator<IteratorVector const>::type it_type;
for(it_type it = boost::begin(input); it != boost::end(input); ++it)
{
- ExpandPolicy::apply(total, **it);
+ expand_policy.apply(total, **it);
}
}
// Match forward_range with itself
-template <typename Policy, typename IteratorVector>
-inline void handle_one(IteratorVector const& input, Policy& policy)
+template <typename IteratorVector, typename VisitPolicy>
+inline void handle_one(IteratorVector const& input, VisitPolicy& visitor)
{
if (boost::size(input) == 0)
{
@@ -118,7 +121,7 @@ inline void handle_one(IteratorVector const& input, Policy& policy)
it_type it2 = it1;
for (++it2; it2 != boost::end(input); ++it2)
{
- policy.apply(**it1, **it2);
+ visitor.apply(**it1, **it2);
}
}
}
@@ -126,13 +129,13 @@ inline void handle_one(IteratorVector const& input, Policy& policy)
// Match forward range 1 with forward range 2
template
<
- typename Policy,
typename IteratorVector1,
- typename IteratorVector2
+ typename IteratorVector2,
+ typename VisitPolicy
>
inline void handle_two(IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- Policy& policy)
+ IteratorVector2 const& input2,
+ VisitPolicy& visitor)
{
typedef typename boost::range_iterator
<
@@ -157,14 +160,14 @@ inline void handle_two(IteratorVector1 const& input1,
it2 != boost::end(input2);
++it2)
{
- policy.apply(**it1, **it2);
+ visitor.apply(**it1, **it2);
}
}
}
template <typename IteratorVector>
inline bool recurse_ok(IteratorVector const& input,
- std::size_t min_elements, std::size_t level)
+ std::size_t min_elements, std::size_t level)
{
return boost::size(input) >= min_elements
&& level < 100;
@@ -172,8 +175,8 @@ inline bool recurse_ok(IteratorVector const& input,
template <typename IteratorVector1, typename IteratorVector2>
inline bool recurse_ok(IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- std::size_t min_elements, std::size_t level)
+ IteratorVector2 const& input2,
+ std::size_t min_elements, std::size_t level)
{
return boost::size(input1) >= min_elements
&& recurse_ok(input2, min_elements, level);
@@ -186,103 +189,114 @@ template
typename IteratorVector3
>
inline bool recurse_ok(IteratorVector1 const& input1,
- IteratorVector2 const& input2,
- IteratorVector3 const& input3,
- std::size_t min_elements, std::size_t level)
+ IteratorVector2 const& input2,
+ IteratorVector3 const& input3,
+ std::size_t min_elements, std::size_t level)
{
return boost::size(input1) >= min_elements
&& recurse_ok(input2, input3, min_elements, level);
}
-template
-<
- int Dimension,
- typename Box,
- typename OverlapsPolicy1,
- typename OverlapsPolicy2,
- typename ExpandPolicy1,
- typename ExpandPolicy2,
- typename VisitBoxPolicy
->
+
+template <int Dimension, typename Box>
class partition_two_ranges;
-template
-<
- int Dimension,
- typename Box,
- typename OverlapsPolicy,
- typename ExpandPolicy,
- typename VisitBoxPolicy
->
+template <int Dimension, typename Box>
class partition_one_range
{
- template <typename IteratorVector>
- static inline Box get_new_box(IteratorVector const& input)
+ template <typename IteratorVector, typename ExpandPolicy>
+ static inline Box get_new_box(IteratorVector const& input,
+ ExpandPolicy const& expand_policy)
{
Box box;
geometry::assign_inverse(box);
- expand_with_elements<ExpandPolicy>(box, input);
+ expand_with_elements(box, input, expand_policy);
return box;
}
- template <typename Policy, typename IteratorVector>
+ template
+ <
+ typename IteratorVector,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+ >
static inline void next_level(Box const& box,
- IteratorVector const& input,
- std::size_t level, std::size_t min_elements,
- Policy& policy, VisitBoxPolicy& box_policy)
+ IteratorVector const& input,
+ std::size_t level, std::size_t min_elements,
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ VisitBoxPolicy& box_policy)
{
if (recurse_ok(input, min_elements, level))
{
partition_one_range
- <
- 1 - Dimension,
- Box,
- OverlapsPolicy,
- ExpandPolicy,
- VisitBoxPolicy
- >::apply(box, input, level + 1, min_elements, policy, box_policy);
+ <
+ 1 - Dimension,
+ Box
+ >::apply(box, input, level + 1, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy);
}
else
{
- handle_one(input, policy);
+ handle_one(input, visitor);
}
}
// Function to switch to two forward ranges if there are
// geometries exceeding the separation line
- template <typename Policy, typename IteratorVector>
+ template
+ <
+ typename IteratorVector,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+ >
static inline void next_level2(Box const& box,
IteratorVector const& input1,
IteratorVector const& input2,
std::size_t level, std::size_t min_elements,
- Policy& policy, VisitBoxPolicy& box_policy)
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ VisitBoxPolicy& box_policy)
{
if (recurse_ok(input1, input2, min_elements, level))
{
partition_two_ranges
- <
- 1 - Dimension,
- Box,
- OverlapsPolicy, OverlapsPolicy,
- ExpandPolicy, ExpandPolicy,
- VisitBoxPolicy
- >::apply(box, input1, input2, level + 1, min_elements,
- policy, box_policy);
+ <
+ 1 - Dimension, Box
+ >::apply(box, input1, input2, level + 1, min_elements,
+ visitor, expand_policy, overlaps_policy,
+ expand_policy, overlaps_policy, box_policy);
}
else
{
- handle_two(input1, input2, policy);
+ handle_two(input1, input2, visitor);
}
}
public :
- template <typename Policy, typename IteratorVector>
+ template
+ <
+ typename IteratorVector,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+ >
static inline void apply(Box const& box,
- IteratorVector const& input,
- std::size_t level,
- std::size_t min_elements,
- Policy& policy, VisitBoxPolicy& box_policy)
+ IteratorVector const& input,
+ std::size_t level,
+ std::size_t min_elements,
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ VisitBoxPolicy& box_policy)
{
box_policy.apply(box, level);
@@ -290,101 +304,121 @@ public :
divide_box<Dimension>(box, lower_box, upper_box);
IteratorVector lower, upper, exceeding;
- divide_into_subsets<OverlapsPolicy>(lower_box, upper_box,
- input, lower, upper, exceeding);
+ divide_into_subsets(lower_box, upper_box,
+ input, lower, upper, exceeding,
+ overlaps_policy);
if (boost::size(exceeding) > 0)
{
// Get the box of exceeding-only
- Box exceeding_box = get_new_box(exceeding);
+ Box exceeding_box = get_new_box(exceeding, expand_policy);
// Recursively do exceeding elements only, in next dimension they
// will probably be less exceeding within the new box
next_level(exceeding_box, exceeding, level, min_elements,
- policy, box_policy);
+ visitor, expand_policy, overlaps_policy, box_policy);
// Switch to two forward ranges, combine exceeding with
// lower resp upper, but not lower/lower, upper/upper
next_level2(exceeding_box, exceeding, lower, level, min_elements,
- policy, box_policy);
+ visitor, expand_policy, overlaps_policy, box_policy);
next_level2(exceeding_box, exceeding, upper, level, min_elements,
- policy, box_policy);
+ visitor, expand_policy, overlaps_policy, box_policy);
}
// Recursively call operation both parts
- next_level(lower_box, lower, level, min_elements, policy, box_policy);
- next_level(upper_box, upper, level, min_elements, policy, box_policy);
+ next_level(lower_box, lower, level, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy);
+ next_level(upper_box, upper, level, min_elements,
+ visitor, expand_policy, overlaps_policy, box_policy);
}
};
template
<
int Dimension,
- typename Box,
- typename OverlapsPolicy1,
- typename OverlapsPolicy2,
- typename ExpandPolicy1,
- typename ExpandPolicy2,
- typename VisitBoxPolicy
+ typename Box
>
class partition_two_ranges
{
template
<
- typename Policy,
typename IteratorVector1,
- typename IteratorVector2
+ typename IteratorVector2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2,
+ typename VisitBoxPolicy
>
static inline void next_level(Box const& box,
IteratorVector1 const& input1,
IteratorVector2 const& input2,
std::size_t level, std::size_t min_elements,
- Policy& policy, VisitBoxPolicy& box_policy)
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2,
+ VisitBoxPolicy& box_policy)
{
partition_two_ranges
<
- 1 - Dimension,
- Box,
- OverlapsPolicy1,
- OverlapsPolicy2,
- ExpandPolicy1,
- ExpandPolicy2,
- VisitBoxPolicy
+ 1 - Dimension, Box
>::apply(box, input1, input2, level + 1, min_elements,
- policy, box_policy);
+ visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
- template <typename ExpandPolicy, typename IteratorVector>
- static inline Box get_new_box(IteratorVector const& input)
+ template <typename IteratorVector, typename ExpandPolicy>
+ static inline Box get_new_box(IteratorVector const& input,
+ ExpandPolicy const& expand_policy)
{
Box box;
geometry::assign_inverse(box);
- expand_with_elements<ExpandPolicy>(box, input);
+ expand_with_elements(box, input, expand_policy);
return box;
}
- template <typename IteratorVector1, typename IteratorVector2>
+ template
+ <
+ typename IteratorVector1, typename IteratorVector2,
+ typename ExpandPolicy1, typename ExpandPolicy2
+ >
static inline Box get_new_box(IteratorVector1 const& input1,
- IteratorVector2 const& input2)
+ IteratorVector2 const& input2,
+ ExpandPolicy1 const& expand_policy1,
+ ExpandPolicy2 const& expand_policy2)
{
- Box box = get_new_box<ExpandPolicy1>(input1);
- expand_with_elements<ExpandPolicy2>(box, input2);
+ Box box = get_new_box(input1, expand_policy1);
+ expand_with_elements(box, input2, expand_policy2);
return box;
}
public :
template
<
- typename Policy,
typename IteratorVector1,
- typename IteratorVector2
+ typename IteratorVector2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2,
+ typename VisitBoxPolicy
>
static inline void apply(Box const& box,
IteratorVector1 const& input1,
IteratorVector2 const& input2,
std::size_t level,
std::size_t min_elements,
- Policy& policy, VisitBoxPolicy& box_policy)
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2,
+ VisitBoxPolicy& box_policy)
{
box_policy.apply(box, level);
@@ -393,10 +427,12 @@ public :
IteratorVector1 lower1, upper1, exceeding1;
IteratorVector2 lower2, upper2, exceeding2;
- divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box,
- input1, lower1, upper1, exceeding1);
- divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box,
- input2, lower2, upper2, exceeding2);
+ divide_into_subsets(lower_box, upper_box,
+ input1, lower1, upper1, exceeding1,
+ overlaps_policy1);
+ divide_into_subsets(lower_box, upper_box,
+ input2, lower2, upper2, exceeding2,
+ overlaps_policy2);
if (boost::size(exceeding1) > 0)
{
@@ -404,13 +440,15 @@ public :
if (recurse_ok(exceeding1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding1, exceeding2);
+ Box exceeding_box = get_new_box(exceeding1, exceeding2,
+ expand_policy1, expand_policy2);
next_level(exceeding_box, exceeding1, exceeding2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(exceeding1, exceeding2, policy);
+ handle_two(exceeding1, exceeding2, visitor);
}
// All exceeding from 1 with lower and upper of 2:
@@ -419,16 +457,18 @@ public :
// the same combinations again and again)
if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
{
- Box exceeding_box = get_new_box<ExpandPolicy1>(exceeding1);
+ Box exceeding_box = get_new_box(exceeding1, expand_policy1);
next_level(exceeding_box, exceeding1, lower2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
next_level(exceeding_box, exceeding1, upper2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(exceeding1, lower2, policy);
- handle_two(exceeding1, upper2, policy);
+ handle_two(exceeding1, lower2, visitor);
+ handle_two(exceeding1, upper2, visitor);
}
}
@@ -437,36 +477,40 @@ public :
// All exceeding from 2 with lower and upper of 1:
if (recurse_ok(lower1, upper1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box<ExpandPolicy2>(exceeding2);
+ Box exceeding_box = get_new_box(exceeding2, expand_policy2);
next_level(exceeding_box, lower1, exceeding2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
next_level(exceeding_box, upper1, exceeding2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(lower1, exceeding2, policy);
- handle_two(upper1, exceeding2, policy);
+ handle_two(lower1, exceeding2, visitor);
+ handle_two(upper1, exceeding2, visitor);
}
}
if (recurse_ok(lower1, lower2, min_elements, level))
{
next_level(lower_box, lower1, lower2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(lower1, lower2, policy);
+ handle_two(lower1, lower2, visitor);
}
if (recurse_ok(upper1, upper2, min_elements, level))
{
next_level(upper_box, upper1, upper2, level,
- min_elements, policy, box_policy);
+ min_elements, visitor, expand_policy1, overlaps_policy1,
+ expand_policy2, overlaps_policy2, box_policy);
}
else
{
- handle_two(upper1, upper2, policy);
+ handle_two(upper1, upper2, visitor);
}
}
};
@@ -493,46 +537,86 @@ struct include_all_policy
template
<
typename Box,
- typename ExpandPolicy1,
- typename OverlapsPolicy1,
- typename ExpandPolicy2 = ExpandPolicy1,
- typename OverlapsPolicy2 = OverlapsPolicy1,
typename IncludePolicy1 = detail::partition::include_all_policy,
- typename IncludePolicy2 = detail::partition::include_all_policy,
- typename VisitBoxPolicy = detail::partition::visit_no_policy
+ typename IncludePolicy2 = detail::partition::include_all_policy
>
class partition
{
+ static const std::size_t default_min_elements = 16;
+
template
<
- typename ExpandPolicy,
typename IncludePolicy,
typename ForwardRange,
- typename IteratorVector
+ typename IteratorVector,
+ typename ExpandPolicy
>
static inline void expand_to_range(ForwardRange const& forward_range,
- Box& total, IteratorVector& iterator_vector)
+ Box& total,
+ IteratorVector& iterator_vector,
+ ExpandPolicy const& expand_policy)
{
- for(typename boost::range_iterator<ForwardRange const>::type it
- = boost::begin(forward_range);
+ for(typename boost::range_iterator<ForwardRange const>::type
+ it = boost::begin(forward_range);
it != boost::end(forward_range);
++it)
{
if (IncludePolicy::apply(*it))
{
- ExpandPolicy::apply(total, *it);
+ expand_policy.apply(total, *it);
iterator_vector.push_back(it);
}
}
}
-public :
- template <typename ForwardRange, typename VisitPolicy>
+public:
+ template
+ <
+ typename ForwardRange,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy
+ >
static inline void apply(ForwardRange const& forward_range,
- VisitPolicy& visitor,
- std::size_t min_elements = 16,
- VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()
- )
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy)
+ {
+ apply(forward_range, visitor, expand_policy, overlaps_policy,
+ default_min_elements, detail::partition::visit_no_policy());
+ }
+
+ template
+ <
+ typename ForwardRange,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy
+ >
+ static inline void apply(ForwardRange const& forward_range,
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ std::size_t min_elements)
+ {
+ apply(forward_range, visitor, expand_policy, overlaps_policy,
+ min_elements, detail::partition::visit_no_policy());
+ }
+
+ template
+ <
+ typename ForwardRange,
+ typename VisitPolicy,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+ >
+ static inline void apply(ForwardRange const& forward_range,
+ VisitPolicy& visitor,
+ ExpandPolicy const& expand_policy,
+ OverlapsPolicy const& overlaps_policy,
+ std::size_t min_elements,
+ VisitBoxPolicy box_visitor)
{
typedef typename boost::range_iterator
<
@@ -544,17 +628,14 @@ public :
std::vector<iterator_type> iterator_vector;
Box total;
assign_inverse(total);
- expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range,
- total, iterator_vector);
+ expand_to_range<IncludePolicy1>(forward_range, total,
+ iterator_vector, expand_policy);
detail::partition::partition_one_range
<
- 0, Box,
- OverlapsPolicy1,
- ExpandPolicy1,
- VisitBoxPolicy
+ 0, Box
>::apply(total, iterator_vector, 0, min_elements,
- visitor, box_visitor);
+ visitor, expand_policy, overlaps_policy, box_visitor);
}
else
{
@@ -575,15 +656,88 @@ public :
<
typename ForwardRange1,
typename ForwardRange2,
- typename VisitPolicy
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1
+ >
+ static inline void apply(ForwardRange1 const& forward_range1,
+ ForwardRange2 const& forward_range2,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1)
+ {
+ apply(forward_range1, forward_range2, visitor,
+ expand_policy1, overlaps_policy1, expand_policy1, overlaps_policy1,
+ default_min_elements, detail::partition::visit_no_policy());
+ }
+
+ template
+ <
+ typename ForwardRange1,
+ typename ForwardRange2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2
+ >
+ static inline void apply(ForwardRange1 const& forward_range1,
+ ForwardRange2 const& forward_range2,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2)
+ {
+ apply(forward_range1, forward_range2, visitor,
+ expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy2,
+ default_min_elements, detail::partition::visit_no_policy());
+ }
+
+ template
+ <
+ typename ForwardRange1,
+ typename ForwardRange2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2
+ >
+ static inline void apply(ForwardRange1 const& forward_range1,
+ ForwardRange2 const& forward_range2,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2,
+ std::size_t min_elements)
+ {
+ apply(forward_range1, forward_range2, visitor,
+ expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy1,
+ min_elements, detail::partition::visit_no_policy());
+ }
+
+ template
+ <
+ typename ForwardRange1,
+ typename ForwardRange2,
+ typename VisitPolicy,
+ typename ExpandPolicy1,
+ typename OverlapsPolicy1,
+ typename ExpandPolicy2,
+ typename OverlapsPolicy2,
+ typename VisitBoxPolicy
>
static inline void apply(ForwardRange1 const& forward_range1,
- ForwardRange2 const& forward_range2,
- VisitPolicy& visitor,
- std::size_t min_elements = 16,
- VisitBoxPolicy box_visitor
- = detail::partition::visit_no_policy()
- )
+ ForwardRange2 const& forward_range2,
+ VisitPolicy& visitor,
+ ExpandPolicy1 const& expand_policy1,
+ OverlapsPolicy1 const& overlaps_policy1,
+ ExpandPolicy2 const& expand_policy2,
+ OverlapsPolicy2 const& overlaps_policy2,
+ std::size_t min_elements,
+ VisitBoxPolicy box_visitor)
{
typedef typename boost::range_iterator
<
@@ -602,17 +756,18 @@ public :
std::vector<iterator_type2> iterator_vector2;
Box total;
assign_inverse(total);
- expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range1,
- total, iterator_vector1);
- expand_to_range<ExpandPolicy2, IncludePolicy2>(forward_range2,
- total, iterator_vector2);
+ expand_to_range<IncludePolicy1>(forward_range1, total,
+ iterator_vector1, expand_policy1);
+ expand_to_range<IncludePolicy2>(forward_range2, total,
+ iterator_vector2, expand_policy2);
detail::partition::partition_two_ranges
<
- 0, Box, OverlapsPolicy1, OverlapsPolicy2,
- ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy
+ 0, Box
>::apply(total, iterator_vector1, iterator_vector2,
- 0, min_elements, visitor, box_visitor);
+ 0, min_elements, visitor, expand_policy1,
+ overlaps_policy1, expand_policy2, overlaps_policy2,
+ box_visitor);
}
else
{
diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
index a74954326b..800fbb2e96 100644
--- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -40,12 +40,21 @@ namespace detail { namespace relate {
// Use the rtree in this case!
// may be used to set EI and EB for an Areal geometry for which no turns were generated
-template <typename OtherAreal, typename Result, bool TransposeResult>
+template
+<
+ typename OtherAreal,
+ typename Result,
+ typename PointInArealStrategy,
+ bool TransposeResult
+>
class no_turns_aa_pred
{
public:
- no_turns_aa_pred(OtherAreal const& other_areal, Result & res)
+ no_turns_aa_pred(OtherAreal const& other_areal,
+ Result & res,
+ PointInArealStrategy const& point_in_areal_strategy)
: m_result(res)
+ , m_point_in_areal_strategy(point_in_areal_strategy)
, m_other_areal(other_areal)
, m_flags(0)
{
@@ -68,6 +77,8 @@ public:
template <typename Areal>
bool operator()(Areal const& areal)
{
+ using detail::within::point_in_geometry;
+
// if those flags are set nothing will change
if ( m_flags == 3 )
{
@@ -87,7 +98,9 @@ public:
// check if the areal is inside the other_areal
// TODO: This is O(N)
// Run in a loop O(NM) - optimize!
- int const pig = detail::within::point_in_geometry(pt, m_other_areal);
+ int const pig = point_in_geometry(pt,
+ m_other_areal,
+ m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT( pig != 0 );
// inside
@@ -119,7 +132,9 @@ public:
// TODO: O(N)
// Optimize!
- int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal);
+ int const hpig = point_in_geometry(range::front(range_ref),
+ m_other_areal,
+ m_point_in_areal_strategy);
// hole outside
if ( hpig < 0 )
@@ -155,7 +170,9 @@ public:
// TODO: O(N)
// Optimize!
- int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal);
+ int const hpig = point_in_geometry(range::front(range_ref),
+ m_other_areal,
+ m_point_in_areal_strategy);
// hole inside
if ( hpig > 0 )
@@ -174,6 +191,7 @@ public:
private:
Result & m_result;
+ PointInArealStrategy const& m_point_in_areal_strategy;
OtherAreal const& m_other_areal;
int m_flags;
};
@@ -191,8 +209,10 @@ struct areal_areal
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
// TODO: If Areal geometry may have infinite size, change the following line:
@@ -208,16 +228,31 @@ struct areal_areal
interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);
- turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
+ turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
- no_turns_aa_pred<Geometry2, Result, false> pred1(geometry2, result);
+ typedef typename IntersectionStrategy::template point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type point_in_areal_strategy12_type;
+ point_in_areal_strategy12_type point_in_areal_strategy12
+ = intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
+ typedef typename IntersectionStrategy::template point_in_geometry_strategy
+ <
+ Geometry2, Geometry1
+ >::type point_in_areal_strategy21_type;
+ point_in_areal_strategy21_type point_in_areal_strategy21
+ = intersection_strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>();
+
+ no_turns_aa_pred<Geometry2, Result, point_in_areal_strategy12_type, false>
+ pred1(geometry2, result, point_in_areal_strategy12);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
- no_turns_aa_pred<Geometry1, Result, true> pred2(geometry1, result);
+ no_turns_aa_pred<Geometry1, Result, point_in_areal_strategy21_type, true>
+ pred2(geometry1, result, point_in_areal_strategy21);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
@@ -256,7 +291,8 @@ struct areal_areal
{
// analyse rings for which turns were not generated
// or only i/i or u/u was generated
- uncertain_rings_analyser<0, Result, Geometry1, Geometry2> rings_analyser(result, geometry1, geometry2);
+ uncertain_rings_analyser<0, Result, Geometry1, Geometry2, point_in_areal_strategy12_type>
+ rings_analyser(result, geometry1, geometry2, point_in_areal_strategy12);
analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end());
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
@@ -295,7 +331,8 @@ struct areal_areal
{
// analyse rings for which turns were not generated
// or only i/i or u/u was generated
- uncertain_rings_analyser<1, Result, Geometry2, Geometry1> rings_analyser(result, geometry2, geometry1);
+ uncertain_rings_analyser<1, Result, Geometry2, Geometry1, point_in_areal_strategy21_type>
+ rings_analyser(result, geometry2, geometry1, point_in_areal_strategy21);
analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end());
//if ( result.interrupt )
@@ -565,7 +602,14 @@ struct areal_areal
analyser.apply(res);
}
- template <std::size_t OpId, typename Result, typename Geometry, typename OtherGeometry>
+ template
+ <
+ std::size_t OpId,
+ typename Result,
+ typename Geometry,
+ typename OtherGeometry,
+ typename PointInArealStrategy
+ >
class uncertain_rings_analyser
{
static const bool transpose_result = OpId != 0;
@@ -574,10 +618,13 @@ struct areal_areal
public:
inline uncertain_rings_analyser(Result & result,
Geometry const& geom,
- OtherGeometry const& other_geom)
- : geometry(geom), other_geometry(other_geom)
+ OtherGeometry const& other_geom,
+ PointInArealStrategy const& point_in_areal_strategy)
+ : geometry(geom)
+ , other_geometry(other_geom)
, interrupt(result.interrupt) // just in case, could be false as well
, m_result(result)
+ , m_point_in_areal_strategy(point_in_areal_strategy)
, m_flags(0)
{
// check which relations must be analysed
@@ -624,7 +671,10 @@ struct areal_areal
// TODO: optimize! e.g. use spatial index
// O(N) - running it in a loop gives O(NM)
- int const pig = detail::within::point_in_geometry(range::front(range_ref), other_geometry);
+ using detail::within::point_in_geometry;
+ int const pig = point_in_geometry(range::front(range_ref),
+ other_geometry,
+ m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT(pig != 0);
if ( pig > 0 )
@@ -713,6 +763,7 @@ struct areal_areal
private:
Result & m_result;
+ PointInArealStrategy const& m_point_in_areal_strategy;
int m_flags;
};
diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp
index a6f1545ed1..3bd0f806c1 100644
--- a/boost/geometry/algorithms/detail/relate/implementation.hpp
+++ b/boost/geometry/algorithms/detail/relate/implementation.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,6 +25,9 @@
#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
namespace boost { namespace geometry {
diff --git a/boost/geometry/algorithms/detail/relate/interface.hpp b/boost/geometry/algorithms/detail/relate/interface.hpp
index 95d452931c..3575fe2bc4 100644
--- a/boost/geometry/algorithms/detail/relate/interface.hpp
+++ b/boost/geometry/algorithms/detail/relate/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -29,6 +29,7 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/relate.hpp>
namespace boost { namespace geometry {
@@ -186,18 +187,59 @@ struct result_handler_type<Geometry1, Geometry2, StaticSequence, true>
> type;
};
+
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct relate
+{
+ template <typename Geometry1, typename Geometry2, typename ResultHandler, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ ResultHandler & handler,
+ Strategy const& strategy)
+ {
+ dispatch::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, handler, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2, typename ResultHandler>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ ResultHandler & handler,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ dispatch::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, handler, strategy_type());
+ }
+};
+
+} // resolve_strategy
+
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct relate
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -210,11 +252,7 @@ struct relate
Mask
>::type handler(mask);
- dispatch::relate
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, handler);
+ resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy);
return handler.result();
}
@@ -223,60 +261,64 @@ struct relate
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Mask const& m_mask;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2, Mask const& mask)
- : m_geometry2(geometry2), m_mask(mask) {}
+ visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy)
+ : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return relate<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_mask);
+ ::apply(geometry1, m_geometry2, m_mask, m_strategy);
}
};
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Mask>(geometry2, mask), geometry1);
+ return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Mask const& m_mask;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1, Mask const& mask)
- : m_geometry1(geometry1), m_mask(mask) {}
+ visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy)
+ : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return relate<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_mask);
+ ::apply(m_geometry1, geometry2, m_mask, m_strategy);
}
};
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Mask>(geometry1, mask), geometry2);
+ return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2);
}
};
@@ -289,30 +331,32 @@ struct relate<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
- template <typename Mask>
+ template <typename Mask, typename Strategy>
struct visitor : boost::static_visitor<bool>
{
Mask const& m_mask;
+ Strategy const& m_strategy;
- visitor(Mask const& mask)
- : m_mask(mask) {}
+ visitor(Mask const& mask, Strategy const& strategy)
+ : m_mask(mask), m_strategy(strategy) {}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return relate<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_mask);
+ ::apply(geometry1, geometry2, m_mask, m_strategy);
}
};
- template <typename Mask>
+ template <typename Mask, typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Mask const& mask)
+ Mask const& mask,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Mask>(mask), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2);
}
};
@@ -324,6 +368,35 @@ struct relate<
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Mask An intersection model Mask type.
+\tparam Strategy \tparam_strategy{Relate}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param mask An intersection model mask object.
+\param strategy \param_strategy{relate}
+\return true if the relation is compatible with the mask, false otherwise.
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/relate.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Mask, typename Strategy>
+inline bool relate(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
+{
+ return resolve_variant::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, mask, strategy);
+}
+
+/*!
+\brief Checks relation between a pair of geometries defined by a mask.
+\ingroup relate
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Mask An intersection model Mask type.
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param mask An intersection model mask object.
@@ -340,7 +413,7 @@ inline bool relate(Geometry1 const& geometry1,
<
Geometry1,
Geometry2
- >::apply(geometry1, geometry2, mask);
+ >::apply(geometry1, geometry2, mask, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
index 58ba7bd1af..f1b4fdf81a 100644
--- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -46,15 +46,24 @@ namespace detail { namespace relate {
// Use the rtree in this case!
// may be used to set IE and BE for a Linear geometry for which no turns were generated
-template <typename Geometry2, typename Result, typename BoundaryChecker, bool TransposeResult>
+template
+<
+ typename Geometry2,
+ typename Result,
+ typename PointInArealStrategy,
+ typename BoundaryChecker,
+ bool TransposeResult
+>
class no_turns_la_linestring_pred
{
public:
no_turns_la_linestring_pred(Geometry2 const& geometry2,
Result & res,
+ PointInArealStrategy const& point_in_areal_strategy,
BoundaryChecker const& boundary_checker)
: m_geometry2(geometry2)
, m_result(res)
+ , m_point_in_areal_strategy(point_in_areal_strategy)
, m_boundary_checker(boundary_checker)
, m_interrupt_flags(0)
{
@@ -98,7 +107,9 @@ public:
return false;
}
- int const pig = detail::within::point_in_geometry(range::front(linestring), m_geometry2);
+ int const pig = detail::within::point_in_geometry(range::front(linestring),
+ m_geometry2,
+ m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs");
if ( pig > 0 )
@@ -138,6 +149,7 @@ public:
private:
Geometry2 const& m_geometry2;
Result & m_result;
+ PointInArealStrategy const& m_point_in_areal_strategy;
BoundaryChecker const& m_boundary_checker;
unsigned m_interrupt_flags;
};
@@ -225,8 +237,10 @@ struct linear_areal
>
{};
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
// TODO: If Areal geometry may have infinite size, change the following line:
@@ -242,7 +256,7 @@ struct linear_areal
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
- turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
+ turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@@ -251,9 +265,13 @@ struct linear_areal
<
Geometry2,
Result,
+ typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type,
boundary_checker<Geometry1>,
TransposeResult
- > pred1(geometry2, result, boundary_checker1);
+ > pred1(geometry2,
+ result,
+ intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>(),
+ boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@@ -279,7 +297,8 @@ struct linear_areal
analyse_each_turn(result, analyser,
turns.begin(), turns.end(),
geometry1, geometry2,
- boundary_checker1);
+ boundary_checker1,
+ intersection_strategy.get_side_strategy());
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
@@ -615,11 +634,13 @@ struct linear_areal
typename TurnIt,
typename Geometry,
typename OtherGeometry,
- typename BoundaryChecker>
+ typename BoundaryChecker,
+ typename SideStrategy>
void apply(Result & res, TurnIt it,
Geometry const& geometry,
OtherGeometry const& other_geometry,
- BoundaryChecker const& boundary_checker)
+ BoundaryChecker const& boundary_checker,
+ SideStrategy const& side_strategy)
{
overlay::operation_type op = it->operations[op_id].operation;
@@ -856,7 +877,8 @@ struct linear_areal
bool const from_inside = first_point
&& calculate_from_inside(geometry,
other_geometry,
- *it);
+ *it,
+ side_strategy);
if ( from_inside )
update<interior, interior, '1', TransposeResult>(res);
@@ -956,7 +978,8 @@ struct linear_areal
bool const first_from_inside = first_point
&& calculate_from_inside(geometry,
other_geometry,
- *it);
+ *it,
+ side_strategy);
if ( first_from_inside )
{
update<interior, interior, '1', TransposeResult>(res);
@@ -1144,10 +1167,11 @@ struct linear_areal
// check if the passed turn's segment of Linear geometry arrived
// from the inside or the outside of the Areal geometry
- template <typename Turn>
+ template <typename Turn, typename SideStrategy>
static inline bool calculate_from_inside(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Turn const& turn)
+ Turn const& turn,
+ SideStrategy const& side_strategy)
{
typedef typename cs_tag<typename Turn::point_type>::type cs_tag;
@@ -1194,16 +1218,18 @@ struct linear_areal
boost::end(range2));
// Will this sequence of points be always correct?
- overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it);
+ overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
+ side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy);
return calculate_from_inside_sides(side_calc);
}
else
{
- point1_type new_qj;
+ point2_type new_qj;
geometry::convert(turn.point, new_qj);
- overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, new_qj, qj);
+ overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy>
+ side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy);
return calculate_from_inside_sides(side_calc);
}
@@ -1270,13 +1296,15 @@ struct linear_areal
typename Analyser,
typename Geometry,
typename OtherGeometry,
- typename BoundaryChecker>
+ typename BoundaryChecker,
+ typename SideStrategy>
static inline void analyse_each_turn(Result & res,
Analyser & analyser,
TurnIt first, TurnIt last,
Geometry const& geometry,
OtherGeometry const& other_geometry,
- BoundaryChecker const& boundary_checker)
+ BoundaryChecker const& boundary_checker,
+ SideStrategy const& side_strategy)
{
if ( first == last )
return;
@@ -1285,7 +1313,8 @@ struct linear_areal
{
analyser.apply(res, it,
geometry, other_geometry,
- boundary_checker);
+ boundary_checker,
+ side_strategy);
if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
return;
@@ -1420,10 +1449,12 @@ struct areal_linear
static const bool interruption_enabled = linear_areal_type::interruption_enabled;
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
- linear_areal_type::apply(geometry2, geometry1, result);
+ linear_areal_type::apply(geometry2, geometry1, result, intersection_strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
index 7a3f373e03..520f2bd775 100644
--- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP
@@ -119,8 +119,10 @@ struct linear_linear
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
- template <typename Result>
- static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
+ template <typename Result, typename IntersectionStrategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ IntersectionStrategy const& intersection_strategy)
{
// The result should be FFFFFFFFF
relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
@@ -138,7 +140,7 @@ struct linear_linear
Geometry1,
Geometry2,
detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> >
- >::apply(turns, geometry1, geometry2, interrupt_policy);
+ >::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
index be08016a16..a0c6c0d49b 100644
--- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -37,10 +37,10 @@ struct point_geometry
static const bool interruption_enabled = true;
- template <typename Result>
- static inline void apply(Point const& point, Geometry const& geometry, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Point const& point, Geometry const& geometry, Result & result, Strategy const& strategy)
{
- int pig = detail::within::point_in_geometry(point, geometry);
+ int pig = detail::within::point_in_geometry(point, geometry, strategy);
if ( pig > 0 ) // within
{
@@ -95,10 +95,10 @@ struct geometry_point
static const bool interruption_enabled = true;
- template <typename Result>
- static inline void apply(Geometry const& geometry, Point const& point, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry const& geometry, Point const& point, Result & result, Strategy const& strategy)
{
- point_geometry<Point, Geometry, true>::apply(point, geometry, result);
+ point_geometry<Point, Geometry, true>::apply(point, geometry, result, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp
index e55be08225..b41d346f0b 100644
--- a/boost/geometry/algorithms/detail/relate/point_point.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_point.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP
@@ -35,8 +35,10 @@ struct point_point
{
static const bool interruption_enabled = false;
- template <typename Result>
- static inline void apply(Point1 const& point1, Point2 const& point2, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Point1 const& point1, Point2 const& point2,
+ Result & result,
+ Strategy const& /*strategy*/)
{
bool equal = detail::equals::equals_point_point(point1, point2);
if ( equal )
@@ -86,8 +88,10 @@ struct point_multipoint
{
static const bool interruption_enabled = false;
- template <typename Result>
- static inline void apply(Point const& point, MultiPoint const& multi_point, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(Point const& point, MultiPoint const& multi_point,
+ Result & result,
+ Strategy const& /*strategy*/)
{
if ( boost::empty(multi_point) )
{
@@ -122,10 +126,12 @@ struct multipoint_point
{
static const bool interruption_enabled = false;
- template <typename Result>
- static inline void apply(MultiPoint const& multi_point, Point const& point, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint const& multi_point, Point const& point,
+ Result & result,
+ Strategy const& strategy)
{
- point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result);
+ point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result, strategy);
}
};
@@ -134,8 +140,10 @@ struct multipoint_multipoint
{
static const bool interruption_enabled = true;
- template <typename Result>
- static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2, Result & result)
+ template <typename Result, typename Strategy>
+ static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2,
+ Result & result,
+ Strategy const& /*strategy*/)
{
{
// TODO: throw on empty input?
diff --git a/boost/geometry/algorithms/detail/relate/relate_impl.hpp b/boost/geometry/algorithms/detail/relate/relate_impl.hpp
index e8e422993d..2ec2361c03 100644
--- a/boost/geometry/algorithms/detail/relate/relate_impl.hpp
+++ b/boost/geometry/algorithms/detail/relate/relate_impl.hpp
@@ -57,7 +57,8 @@ struct relate_impl
implemented_tag
>::type
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
typename detail::relate::result_handler_type
<
@@ -66,7 +67,7 @@ struct relate_impl
typename StaticMaskTrait<Geometry1, Geometry2>::type
>::type handler;
- dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler);
+ dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler, strategy);
return handler.result();
}
diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp
index a92badf65b..07287dc625 100644
--- a/boost/geometry/algorithms/detail/relate/result.hpp
+++ b/boost/geometry/algorithms/detail/relate/result.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2016.
// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
@@ -24,6 +25,7 @@
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/next.hpp>
#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/integral_constant.hpp>
@@ -266,7 +268,7 @@ private:
|| ( c >= '0' && c <= '9' );
if ( !is_valid )
{
- throw geometry::invalid_input_exception();
+ BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
}
}
diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp
index 09d74dec3a..6fa05eaf21 100644
--- a/boost/geometry/algorithms/detail/relate/turns.hpp
+++ b/boost/geometry/algorithms/detail/relate/turns.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -75,28 +75,35 @@ struct get_turns
{
detail::get_turns::no_interrupt_policy interrupt_policy;
- apply(turns, geometry1, geometry2, interrupt_policy);
+ typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry1>::type
+ >::type intersection_strategy;
+
+ apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy);
}
- template <typename Turns, typename InterruptPolicy>
+ template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
static inline void apply(Turns & turns,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
- InterruptPolicy & interrupt_policy)
+ InterruptPolicy & interrupt_policy,
+ IntersectionStrategy const& intersection_strategy)
{
RobustPolicy robust_policy = geometry::get_rescale_policy
<
RobustPolicy
>(geometry1, geometry2);
- apply(turns, geometry1, geometry2, interrupt_policy, robust_policy);
+ apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy);
}
- template <typename Turns, typename InterruptPolicy>
+ template <typename Turns, typename InterruptPolicy, typename IntersectionStrategy>
static inline void apply(Turns & turns,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
InterruptPolicy & interrupt_policy,
+ IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
{
static const bool reverse1 = detail::overlay::do_reverse
@@ -119,7 +126,8 @@ struct get_turns
reverse2,
GetTurnPolicy
>::apply(0, geometry1, 1, geometry2,
- robust_policy, turns, interrupt_policy);
+ intersection_strategy, robust_policy,
+ turns, interrupt_policy);
}
};
diff --git a/boost/geometry/algorithms/detail/relation/interface.hpp b/boost/geometry/algorithms/detail/relation/interface.hpp
index e9a9474551..83d27ed72f 100644
--- a/boost/geometry/algorithms/detail/relation/interface.hpp
+++ b/boost/geometry/algorithms/detail/relation/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -35,16 +35,16 @@ struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix, false>
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
-
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct relation
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2)
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -57,11 +57,7 @@ struct relation
Matrix
>::type handler;
- dispatch::relate
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, handler);
+ resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy);
return handler.result();
}
@@ -70,56 +66,60 @@ struct relation
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
struct visitor : boost::static_visitor<Matrix>
{
Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2)
- : m_geometry2(geometry2) {}
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2), m_strategy(strategy) {}
template <typename Geometry1>
Matrix operator()(Geometry1 const& geometry1) const
{
return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, m_geometry2);
+ ::template apply<Matrix>(geometry1, m_geometry2, m_strategy);
}
};
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Matrix>(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Matrix, Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
struct visitor : boost::static_visitor<Matrix>
{
Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1)
- : m_geometry1(geometry1) {}
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1), m_strategy(strategy) {}
template <typename Geometry2>
Matrix operator()(Geometry2 const& geometry2) const
{
return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(m_geometry1, geometry2);
+ ::template apply<Matrix>(m_geometry1, geometry2, m_strategy);
}
};
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix
apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Matrix>(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Matrix, Strategy>(geometry1, strategy), geometry2);
}
};
@@ -134,24 +134,30 @@ struct relation
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
struct visitor : boost::static_visitor<Matrix>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy) {}
+
template <typename Geometry1, typename Geometry2>
Matrix operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, geometry2);
+ ::template apply<Matrix>(geometry1, geometry2, m_strategy);
}
};
- template <typename Matrix>
+ template <typename Matrix, typename Strategy>
static inline Matrix
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Matrix>(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Matrix, Strategy>(strategy), geometry1, geometry2);
}
};
@@ -163,6 +169,33 @@ struct relation
\ingroup relation
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Relation}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{relation}
+\return The DE-9IM matrix expressing the relation between geometries.
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/relation.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline de9im::matrix relation(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::relation
+ <
+ Geometry1,
+ Geometry2
+ >::template apply<de9im::matrix>(geometry1, geometry2, strategy);
+}
+
+
+/*!
+\brief Calculates the relation between a pair of geometries as defined in DE-9IM.
+\ingroup relation
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return The DE-9IM matrix expressing the relation between geometries.
@@ -177,7 +210,7 @@ inline de9im::matrix relation(Geometry1 const& geometry1,
<
Geometry1,
Geometry2
- >::template apply<de9im::matrix>(geometry1, geometry2);
+ >::template apply<de9im::matrix>(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
index 2f82e1a8bd..3d45a46d16 100644
--- a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
+++ b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
@@ -16,9 +17,13 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
+
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/throw_exception.hpp>
+
+
// BSG 2012-02-06: we use this currently only for distance.
// For other scalar results area,length,perimeter it is commented on purpose.
// Reason is that for distance there is no other choice. distance of two
@@ -46,7 +51,7 @@ inline void throw_on_empty_input(Geometry const& geometry)
#if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)
if (geometry::is_empty(geometry))
{
- throw empty_input_exception();
+ BOOST_THROW_EXCEPTION(empty_input_exception());
}
#else
boost::ignore_unused(geometry);
diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
index a73364c333..a24f4d21e2 100644
--- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
@@ -5,8 +5,10 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -15,8 +17,6 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
@@ -35,8 +35,7 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/within_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
-#include <boost/geometry/strategies/within.hpp>
-#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/relate.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
@@ -46,6 +45,7 @@ namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
+
// TODO: is this needed?
inline int check_result_type(int result)
{
@@ -83,50 +83,11 @@ int point_in_range(Point const& point, Range const& range, Strategy const& strat
template <typename Geometry, typename Point, typename Range>
inline int point_in_range(Point const& point, Range const& range)
{
- typedef typename point_type<Point>::type point_type1;
- typedef typename point_type<Geometry>::type point_type2;
-
- typedef typename strategy::within::services::default_strategy
+ typedef typename strategy::point_in_geometry::services::default_strategy
<
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
+ Point, Geometry
>::type strategy_type;
- typedef typename strategy::covered_by::services::default_strategy
- <
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
- >::type strategy_type2;
-
- static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;
- BOOST_MPL_ASSERT_MSG((same_strategies),
- DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
- (strategy_type, strategy_type2));
-
return point_in_range(point, range, strategy_type());
}
@@ -414,50 +375,11 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry, Strat
template <typename Point, typename Geometry>
inline int point_in_geometry(Point const& point, Geometry const& geometry)
{
- typedef typename point_type<Point>::type point_type1;
- typedef typename point_type<Geometry>::type point_type2;
-
- typedef typename strategy::within::services::default_strategy
+ typedef typename strategy::point_in_geometry::services::default_strategy
<
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
+ Point, Geometry
>::type strategy_type;
- typedef typename strategy::covered_by::services::default_strategy
- <
- typename tag<Point>::type,
- typename tag<Geometry>::type,
- typename tag<Point>::type,
- typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
- Point,
- Geometry
- >::type strategy_type2;
-
- static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;
- BOOST_MPL_ASSERT_MSG((same_strategies),
- DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
- (strategy_type, strategy_type2));
-
return point_in_geometry(point, geometry, strategy_type());
}
diff --git a/boost/geometry/algorithms/difference.hpp b/boost/geometry/algorithms/difference.hpp
index f7ca48cbe6..c11ceca243 100644
--- a/boost/geometry/algorithms/difference.hpp
+++ b/boost/geometry/algorithms/difference.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2017.
+// Modifications copyright (c) 2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,10 +14,16 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
-#include <algorithm>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
+
namespace boost { namespace geometry
{
@@ -49,10 +60,10 @@ template
typename Strategy
>
inline OutputIterator difference_insert(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- OutputIterator out,
- Strategy const& strategy)
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -93,25 +104,18 @@ template
typename OutputIterator
>
inline OutputIterator difference_insert(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- RobustPolicy const& robust_policy,
- OutputIterator out)
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
- concepts::check<GeometryOut>();
-
- typedef intersection_strategies
+ typedef typename strategy::relate::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- RobustPolicy
- > strategy;
+ Geometry2
+ >::type strategy_type;
return difference_insert<GeometryOut>(geometry1, geometry2,
- robust_policy, out, strategy());
+ robust_policy, out, strategy_type());
}
@@ -119,6 +123,215 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct difference
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection,
+ typename Strategy
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::difference::difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ default_strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::difference::difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection));
+ }
+};
+
+} // resolve_strategy
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct difference
+{
+ template <typename Collection, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
+ geometry2);
+
+ resolve_strategy::difference::apply(geometry1, geometry2,
+ robust_policy,
+ output_collection,
+ strategy);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry2 const& m_geometry2;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ void operator()(Geometry1 const& geometry1) const
+ {
+ difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
+ output_collection,
+ strategy),
+ geometry1);
+ }
+};
+
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry1 const& m_geometry1;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ void operator()(Geometry2 const& geometry2) const
+ {
+ difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
+ output_collection,
+ strategy),
+ geometry2);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Collection& output_collection, Strategy const& strategy)
+ : m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ void operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
+ strategy),
+ geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
/*!
\brief_calc2{difference}
@@ -127,39 +340,63 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Collection \tparam_output_collection
+\tparam Strategy \tparam_strategy{Difference}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param output_collection the output collection
+\param strategy \param_strategy{difference}
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/difference.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename Collection
+ typename Collection,
+ typename Strategy
>
inline void difference(Geometry1 const& geometry1,
- Geometry2 const& geometry2, Collection& output_collection)
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- typedef typename boost::range_value<Collection>::type geometry_out;
- concepts::check<geometry_out>();
-
- typedef typename geometry::rescale_overlay_policy_type
+ resolve_variant::difference
<
Geometry1,
Geometry2
- >::type rescale_policy_type;
+ >::apply(geometry1, geometry2, output_collection, strategy);
+}
- rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
- detail::difference::difference_insert<geometry_out>(
- geometry1, geometry2, robust_policy,
- range::back_inserter(output_collection));
+/*!
+\brief_calc2{difference}
+\ingroup difference
+\details \details_calc2{difference, spatial set theoretic difference}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection \tparam_output_collection
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+
+\qbk{[include reference/algorithms/difference.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void difference(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection)
+{
+ resolve_variant::difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, default_strategy());
}
diff --git a/boost/geometry/algorithms/dispatch/disjoint.hpp b/boost/geometry/algorithms/dispatch/disjoint.hpp
index 627bcff83c..78015f1a55 100644
--- a/boost/geometry/algorithms/dispatch/disjoint.hpp
+++ b/boost/geometry/algorithms/dispatch/disjoint.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -60,6 +60,29 @@ struct disjoint
: not_implemented<Geometry1, Geometry2>
{};
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2,
+ std::size_t DimensionCount,
+ typename Tag1, typename Tag2
+>
+struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
+ {
+ return disjoint
+ <
+ Geometry2, Geometry1,
+ DimensionCount,
+ Tag2, Tag1
+ >::apply(g2, g1, strategy);
+ }
+};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp
index d04d5c7f3a..1479ea66fa 100644
--- a/boost/geometry/algorithms/equals.hpp
+++ b/boost/geometry/algorithms/equals.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -26,6 +26,7 @@
#include <vector>
#include <boost/range.hpp>
+#include <boost/type_traits/is_base_of.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
@@ -40,7 +41,6 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
-#include <boost/geometry/algorithms/detail/not.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
// For trivial checks
@@ -70,25 +70,44 @@ template
std::size_t Dimension,
std::size_t DimensionCount
>
+struct point_point
+{
+ template <typename Point1, typename Point2, typename Strategy>
+ static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
+ {
+ return ! detail::disjoint::point_point
+ <
+ Point1, Point2,
+ Dimension, DimensionCount
+ >::apply(point1, point2, strategy);
+ }
+};
+
+
+template
+<
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
struct box_box
{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& box1, Box2 const& box2)
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
|| !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
{
return false;
}
- return box_box<Dimension + 1, DimensionCount>::apply(box1, box2);
+ return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
}
};
template <std::size_t DimensionCount>
struct box_box<DimensionCount, DimensionCount>
{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& , Box2 const& )
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
{
return true;
}
@@ -97,8 +116,8 @@ struct box_box<DimensionCount, DimensionCount>
struct segment_segment
{
- template <typename Segment1, typename Segment2>
- static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)
+ template <typename Segment1, typename Segment2, typename Strategy>
+ static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& )
{
return equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
@@ -119,55 +138,75 @@ struct segment_segment
struct area_check
{
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return geometry::math::equals(
- geometry::area(geometry1),
- geometry::area(geometry2));
+ geometry::area(geometry1,
+ strategy.template get_area_strategy<Geometry1>()),
+ geometry::area(geometry2,
+ strategy.template get_area_strategy<Geometry2>()));
}
};
struct length_check
{
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return geometry::math::equals(
- geometry::length(geometry1),
- geometry::length(geometry2));
+ geometry::length(geometry1,
+ strategy.template get_distance_strategy<Geometry1>()),
+ geometry::length(geometry2,
+ strategy.template get_distance_strategy<Geometry2>()));
}
};
+template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
+struct collected_vector
+{
+ typedef typename geometry::select_most_precise
+ <
+ typename select_coordinate_type
+ <
+ Geometry1, Geometry2
+ >::type,
+ double
+ >::type calculation_type;
+
+ typedef geometry::collected_vector
+ <
+ calculation_type,
+ Geometry1,
+ typename IntersectionStrategy::side_strategy_type
+ > type;
+};
+
template <typename TrivialCheck>
struct equals_by_collection
{
- template <typename Geometry1, typename Geometry2>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- if (! TrivialCheck::apply(geometry1, geometry2))
+ if (! TrivialCheck::apply(geometry1, geometry2, strategy))
{
return false;
}
- typedef typename geometry::select_most_precise
- <
- typename select_coordinate_type
- <
- Geometry1, Geometry2
- >::type,
- double
- >::type calculation_type;
-
- typedef geometry::collected_vector
+ typedef typename collected_vector
<
- calculation_type,
- Geometry1
- > collected_vector;
+ Geometry1, Geometry2, Strategy
+ >::type collected_vector_type;
- std::vector<collected_vector> c1, c2;
+ std::vector<collected_vector_type> c1, c2;
geometry::collect_vectors(c1, geometry1);
geometry::collect_vectors(c2, geometry2);
@@ -195,6 +234,53 @@ struct equals_by_relate
>
{};
+// If collect_vectors which is a SideStrategy-dispatched optimization
+// is implemented in a way consistent with the Intersection/Side Strategy
+// then collect_vectors is used, otherwise relate is used.
+// NOTE: the result could be coneptually different for invalid
+// geometries in different coordinate systems because collect_vectors
+// and relate treat invalid geometries differently.
+template<typename TrivialCheck>
+struct equals_by_collection_or_relate
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ typedef typename boost::is_base_of
+ <
+ nyi::not_implemented_tag,
+ typename collected_vector
+ <
+ Geometry1, Geometry2, Strategy
+ >::type
+ >::type enable_relate_type;
+
+ return apply(geometry1, geometry2, strategy, enable_relate_type());
+ }
+
+private:
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy,
+ boost::false_type /*enable_relate*/)
+ {
+ return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy,
+ boost::true_type /*enable_relate*/)
+ {
+ return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
+ }
+};
+
+
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
@@ -226,7 +312,8 @@ template
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
return equals
<
@@ -234,19 +321,30 @@ struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
Tag2, Tag1,
DimensionCount,
false
- >::apply(g2, g1);
+ >::apply(g2, g1, strategy);
}
};
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
- : geometry::detail::not_
- <
- detail::disjoint::point_point<P1, P2, 0, DimensionCount>
- >
+ : detail::equals::point_point<0, DimensionCount>
+{};
+
+template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
+struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
+ : detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
{};
+template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
+struct equals<MultiPoint, Point, multi_point_tag, point_tag, DimensionCount, Reverse>
+ : detail::equals::equals_by_relate<MultiPoint, Point>
+{};
+
+template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
+struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
+ : detail::equals::equals_by_relate<Point, MultiPoint>
+{};
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
@@ -256,19 +354,19 @@ struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon1, typename Polygon2, bool Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename Ring, bool Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
@@ -290,7 +388,6 @@ struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reve
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
- //: detail::equals::equals_by_collection<detail::equals::length_check>
: detail::equals::equals_by_relate<LineString1, LineString2>
{};
@@ -313,7 +410,7 @@ struct equals
2,
Reverse
>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
@@ -325,7 +422,7 @@ struct equals
2,
Reverse
>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename MultiPolygon, typename Ring, bool Reverse>
@@ -336,7 +433,7 @@ struct equals
2,
Reverse
>
- : detail::equals::equals_by_collection<detail::equals::area_check>
+ : detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
@@ -344,80 +441,129 @@ struct equals
#endif // DOXYGEN_NO_DISPATCH
+namespace resolve_strategy
+{
+
+struct equals
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return dispatch::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return dispatch::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct equals
{
+ template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2)
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions
- <
- Geometry1 const,
- Geometry2 const
- >();
+ <
+ Geometry1 const,
+ Geometry2 const
+ >();
- return dispatch::equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2);
+ return resolve_strategy::equals
+ ::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
+ template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2)
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
+ , m_strategy(strategy)
{}
template <typename Geometry1>
inline bool operator()(Geometry1 const& geometry1) const
{
return equals<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2);
+ ::apply(geometry1, m_geometry2, m_strategy);
}
};
+ template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2
+ Geometry2 const& geometry2,
+ Strategy const& strategy
)
{
- return boost::apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1)
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
+ , m_strategy(strategy)
{}
template <typename Geometry2>
inline bool operator()(Geometry2 const& geometry2) const
{
return equals<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2);
+ ::apply(m_geometry1, geometry2, m_strategy);
}
};
+ template <typename Strategy>
static inline bool apply(
Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy
)
{
- return boost::apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -430,24 +576,33 @@ struct equals<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
+ template <typename Strategy>
struct visitor: static_visitor<bool>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
template <typename Geometry1, typename Geometry2>
inline bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2);
+ ::apply(geometry1, geometry2, m_strategy);
}
};
+ template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy
)
{
- return boost::apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -464,18 +619,48 @@ struct equals<
\ingroup equals
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Equals}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
+\param strategy \param_strategy{equals}
\return \return_check2{are spatially equal}
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/equals.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool equals(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+\brief \brief_check{are spatially equal}
+\details \details_check12{equals, is spatially equal}. Spatially equal means
+ that the same point set is included. A box can therefore be spatially equal
+ to a ring or a polygon, or a linestring can be spatially equal to a
+ multi-linestring or a segment. This only works theoretically, not all
+ combinations are implemented yet.
+\ingroup equals
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{are spatially equal}
+
+\qbk{[include reference/algorithms/equals.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2);
+ ::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/intersects.hpp b/boost/geometry/algorithms/intersects.hpp
index 5349db76bb..12ae169f12 100644
--- a/boost/geometry/algorithms/intersects.hpp
+++ b/boost/geometry/algorithms/intersects.hpp
@@ -4,10 +4,11 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -29,6 +30,8 @@
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
+#include <boost/geometry/strategies/relate.hpp>
+
namespace boost { namespace geometry
{
@@ -52,6 +55,10 @@ inline bool intersects(Geometry const& geometry)
concepts::check<Geometry const>();
typedef typename geometry::point_type<Geometry>::type point_type;
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry, Geometry
+ >::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef detail::overlay::turn_info
@@ -67,13 +74,14 @@ inline bool intersects(Geometry const& geometry)
detail::overlay::assign_null_policy
> turn_policy;
+ strategy_type strategy;
rescale_policy_type robust_policy;
detail::disjoint::disjoint_interrupt_policy policy;
detail::self_get_turn_points::get_turns
<
turn_policy
- >::apply(geometry, robust_policy, turns, policy);
+ >::apply(geometry, strategy, robust_policy, turns, policy);
return policy.has_intersections;
}
@@ -83,6 +91,32 @@ inline bool intersects(Geometry const& geometry)
\ingroup intersects
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Intersects}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{intersects}
+\return \return_check2{intersect each other}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/intersects.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool intersects(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return ! geometry::disjoint(geometry1, geometry2, strategy);
+}
+
+
+/*!
+\brief \brief_check2{have at least one intersection}
+\ingroup intersects
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{intersect each other}
diff --git a/boost/geometry/algorithms/overlaps.hpp b/boost/geometry/algorithms/overlaps.hpp
index 32738c294c..bedf17599b 100644
--- a/boost/geometry/algorithms/overlaps.hpp
+++ b/boost/geometry/algorithms/overlaps.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014, 2015.
-// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -113,8 +113,8 @@ struct box_box_loop<DimensionCount, DimensionCount>
struct box_box
{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& b1, Box2 const& b2)
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
{
bool overlaps = true;
bool within1 = true;
@@ -137,7 +137,6 @@ struct box_box
}} // namespace detail::overlaps
#endif // DOXYGEN_NO_DETAIL
-//struct not_implemented_for_this_geometry_type : public boost::false_type {};
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
@@ -175,6 +174,35 @@ struct overlaps<Box1, Box2, box_tag, box_tag>
\ingroup overlaps
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Overlaps}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{overlaps}
+\return \return_check2{overlap}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/overlaps.qbk]}
+*/
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool overlaps(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ return dispatch::overlaps
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+\brief \brief_check2{overlap}
+\ingroup overlaps
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{overlap}
@@ -187,11 +215,17 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
return dispatch::overlaps
<
Geometry1,
Geometry2
- >::apply(geometry1, geometry2);
+ >::apply(geometry1, geometry2, strategy_type());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp
index 33f94c9321..725230cd5b 100644
--- a/boost/geometry/algorithms/sym_difference.hpp
+++ b/boost/geometry/algorithms/sym_difference.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2017.
+// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -14,13 +15,21 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
+
#include <algorithm>
#include <iterator>
#include <vector>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/union.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
@@ -276,14 +285,10 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
concepts::check<Geometry2 const>();
concepts::check<GeometryOut>();
- typedef intersection_strategies
+ typedef typename strategy::intersection::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- RobustPolicy
- > strategy_type;
+ typename cs_tag<GeometryOut>::type
+ >::type strategy_type;
return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type());
}
@@ -292,6 +297,216 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct sym_difference
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection,
+ typename Strategy
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::sym_difference::sym_difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ default_strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ detail::sym_difference::sym_difference_insert<geometry_out>(
+ geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection));
+ }
+};
+
+} // resolve_strategy
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct sym_difference
+{
+ template <typename Collection, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
+ geometry2);
+
+ resolve_strategy::sym_difference::apply(geometry1, geometry2,
+ robust_policy,
+ output_collection,
+ strategy);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry2 const& m_geometry2;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ void operator()(Geometry1 const& geometry1) const
+ {
+ sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
+ output_collection,
+ strategy),
+ geometry1);
+ }
+};
+
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct sym_difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry1 const& m_geometry1;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ void operator()(Geometry2 const& geometry2) const
+ {
+ sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
+ output_collection,
+ strategy),
+ geometry2);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Collection& output_collection, Strategy const& strategy)
+ : m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ void operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
+ strategy),
+ geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
+
/*!
\brief \brief_calc2{symmetric difference}
\ingroup sym_difference
@@ -300,39 +515,64 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
\tparam Geometry2 \tparam_geometry
\tparam Collection output collection, either a multi-geometry,
or a std::vector<Geometry> / std::deque<Geometry> etc
+\tparam Strategy \tparam_strategy{Sym_difference}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param output_collection the output collection
+\param strategy \param_strategy{sym_difference}
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/sym_difference.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename Collection
+ typename Collection,
+ typename Strategy
>
inline void sym_difference(Geometry1 const& geometry1,
- Geometry2 const& geometry2, Collection& output_collection)
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
- typedef typename boost::range_value<Collection>::type geometry_out;
- concepts::check<geometry_out>();
-
- typedef typename geometry::rescale_overlay_policy_type
+ resolve_variant::sym_difference
<
Geometry1,
Geometry2
- >::type rescale_policy_type;
+ >::apply(geometry1, geometry2, output_collection, strategy);
+}
- rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
- detail::sym_difference::sym_difference_insert<geometry_out>(
- geometry1, geometry2, robust_policy,
- range::back_inserter(output_collection));
+/*!
+\brief \brief_calc2{symmetric difference}
+\ingroup sym_difference
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection output collection, either a multi-geometry,
+ or a std::vector<Geometry> / std::deque<Geometry> etc
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+
+\qbk{[include reference/algorithms/sym_difference.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void sym_difference(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection)
+{
+ resolve_variant::sym_difference
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, default_strategy());
}
diff --git a/boost/geometry/algorithms/touches.hpp b/boost/geometry/algorithms/touches.hpp
index 6384cc2a88..49e104d258 100644
--- a/boost/geometry/algorithms/touches.hpp
+++ b/boost/geometry/algorithms/touches.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -104,8 +104,8 @@ struct box_box_loop<DimensionCount, DimensionCount>
struct box_box
{
- template <typename Box1, typename Box2>
- static inline bool apply(Box1 const& b1, Box2 const& b2)
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
{
BOOST_STATIC_ASSERT((boost::is_same
<
@@ -205,15 +205,17 @@ struct areal_interrupt_policy
}
};
-template<typename Geometry>
+template<typename Geometry, typename PointInRingStrategy>
struct check_each_ring_for_within
{
bool has_within;
Geometry const& m_geometry;
+ PointInRingStrategy const& m_strategy;
- inline check_each_ring_for_within(Geometry const& g)
+ inline check_each_ring_for_within(Geometry const& g, PointInRingStrategy const& strategy)
: has_within(false)
, m_geometry(g)
+ , m_strategy(strategy)
{}
template <typename Range>
@@ -221,18 +223,31 @@ struct check_each_ring_for_within
{
typename geometry::point_type<Range>::type p;
geometry::point_on_border(p, range);
- if ( !has_within && geometry::within(p, m_geometry) )
+ if ( !has_within && geometry::within(p, m_geometry, m_strategy) )
{
has_within = true;
}
}
};
-template <typename FirstGeometry, typename SecondGeometry>
+template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy>
inline bool rings_containing(FirstGeometry const& geometry1,
- SecondGeometry const& geometry2)
+ SecondGeometry const& geometry2,
+ IntersectionStrategy const& strategy)
{
- check_each_ring_for_within<FirstGeometry> checker(geometry1);
+ // NOTE: This strategy could be defined inside IntersectionStrategy
+ typedef typename IntersectionStrategy::template point_in_geometry_strategy
+ <
+ FirstGeometry, SecondGeometry
+ >::type point_in_ring_strategy_type;
+
+ point_in_ring_strategy_type point_in_ring_strategy
+ = strategy.template get_point_in_geometry_strategy<FirstGeometry, SecondGeometry>();
+
+ check_each_ring_for_within
+ <
+ FirstGeometry, point_in_ring_strategy_type
+ > checker(geometry1, point_in_ring_strategy);
geometry::detail::for_each_range(geometry2, checker);
return checker.has_within;
}
@@ -240,8 +255,10 @@ inline bool rings_containing(FirstGeometry const& geometry1,
template <typename Geometry1, typename Geometry2>
struct areal_areal
{
- static inline
- bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename IntersectionStrategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ IntersectionStrategy const& strategy)
{
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry1>::type point_type;
@@ -259,11 +276,11 @@ struct areal_areal
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
detail::overlay::assign_null_policy
- >(geometry1, geometry2, robust_policy, turns, policy);
+ >(geometry1, geometry2, strategy, robust_policy, turns, policy);
return policy.result()
- && ! geometry::detail::touches::rings_containing(geometry1, geometry2)
- && ! geometry::detail::touches::rings_containing(geometry2, geometry1);
+ && ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
+ && ! geometry::detail::touches::rings_containing(geometry2, geometry1, strategy);
}
};
@@ -271,10 +288,10 @@ struct areal_areal
struct use_point_in_geometry
{
- template <typename Point, typename Geometry>
- static inline bool apply(Point const& point, Geometry const& geometry)
+ template <typename Point, typename Geometry, typename Strategy>
+ static inline bool apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
{
- return detail::within::point_in_geometry(point, geometry) == 0;
+ return detail::within::point_in_geometry(point, geometry, strategy) == 0;
}
};
@@ -288,7 +305,8 @@ namespace dispatch {
template
<
- typename Geometry1, typename Geometry2,
+ typename Geometry1,
+ typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
@@ -309,18 +327,30 @@ template
struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
: touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
- return touches<Geometry2, Geometry1>::apply(g2, g1);
+ return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
}
};
// P/P
-template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>
-struct touches<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, pointlike_tag, false>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false>
{
- static inline bool apply(Geometry1 const& , Geometry2 const& )
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&)
+ {
+ return false;
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, pointlike_tag, false>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const&, Geometry2 const&, Strategy const&)
{
return false;
}
@@ -403,66 +433,115 @@ struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
#endif // DOXYGEN_NO_DISPATCH
+namespace resolve_strategy
+{
+
+struct touches
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return dispatch::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
+ {
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return dispatch::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct touches
{
- static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ template <typename Strategy>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return dispatch::touches<Geometry1, Geometry2>
- ::apply(geometry1, geometry2);
+ return resolve_strategy::touches::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2): m_geometry2(geometry2) {}
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
- return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
+ return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
+ Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1): m_geometry1(geometry1) {}
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_strategy(strategy)
+ {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
- return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2);
+ return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -471,21 +550,29 @@ template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
+ template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
- return touches<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
}
};
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
+ template <typename Strategy>
+ static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -496,6 +583,10 @@ struct self_touches
{
concepts::check<Geometry const>();
+ typedef typename strategy::relate::services::default_strategy
+ <
+ Geometry, Geometry
+ >::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry>::type point_type;
typedef detail::overlay::turn_info
@@ -511,11 +602,12 @@ struct self_touches
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
+ strategy_type strategy;
rescale_policy_type robust_policy;
detail::self_get_turn_points::get_turns
<
policy_type
- >::apply(geometry, robust_policy, turns, policy);
+ >::apply(geometry, strategy, robust_policy, turns, policy);
return policy.result();
}
@@ -578,7 +670,35 @@ inline bool touches(Geometry const& geometry)
template <typename Geometry1, typename Geometry2>
inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::touches<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ return resolve_variant::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
+}
+
+/*!
+\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
+\ingroup touches
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Touches}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{touches}
+\return \return_check2{touch each other}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/touches.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool touches(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ return resolve_variant::touches
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
diff --git a/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp
index f0e55ec981..d3a2daf66e 100644
--- a/boost/geometry/algorithms/union.hpp
+++ b/boost/geometry/algorithms/union.hpp
@@ -2,10 +2,11 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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,6 +25,8 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
@@ -214,14 +217,10 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
Geometry2
>::type rescale_policy_type;
- typedef intersection_strategies
+ typename strategy::intersection::services::default_strategy
<
- typename cs_tag<GeometryOut>::type,
- Geometry1,
- Geometry2,
- typename geometry::point_type<GeometryOut>::type,
- rescale_policy_type
- > strategy;
+ typename cs_tag<GeometryOut>::type
+ >::type strategy;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
@@ -229,7 +228,7 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
return dispatch::union_insert
<
Geometry1, Geometry2, GeometryOut
- >::apply(geometry1, geometry2, robust_policy, out, strategy());
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);
}
@@ -237,6 +236,228 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_strategy {
+
+struct union_
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection,
+ typename Strategy
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ dispatch::union_insert
+ <
+ Geometry1, Geometry2, geometry_out
+ >::apply(geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy);
+ }
+
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename Collection
+ >
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ Collection & output_collection,
+ default_strategy)
+ {
+ typedef typename boost::range_value<Collection>::type geometry_out;
+
+ typedef typename strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<geometry_out>::type
+ >::type strategy_type;
+
+ dispatch::union_insert
+ <
+ Geometry1, Geometry2, geometry_out
+ >::apply(geometry1, geometry2, robust_policy,
+ range::back_inserter(output_collection),
+ strategy_type());
+ }
+};
+
+} // resolve_strategy
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct union_
+{
+ template <typename Collection, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+ concepts::check<typename boost::range_value<Collection>::type>();
+
+ typedef typename geometry::rescale_overlay_policy_type
+ <
+ Geometry1,
+ Geometry2
+ >::type rescale_policy_type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
+ geometry2);
+
+ resolve_strategy::union_::apply(geometry1, geometry2,
+ robust_policy,
+ output_collection,
+ strategy);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry2 const& m_geometry2;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1>
+ void operator()(Geometry1 const& geometry1) const
+ {
+ union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
+ output_collection,
+ strategy),
+ geometry1);
+ }
+};
+
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct union_<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Geometry1 const& m_geometry1;
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Geometry1 const& geometry1,
+ Collection& output_collection,
+ Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry2>
+ void operator()(Geometry2 const& geometry2) const
+ {
+ union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
+ output_collection,
+ strategy),
+ geometry2);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+{
+ template <typename Collection, typename Strategy>
+ struct visitor: static_visitor<>
+ {
+ Collection& m_output_collection;
+ Strategy const& m_strategy;
+
+ visitor(Collection& output_collection, Strategy const& strategy)
+ : m_output_collection(output_collection)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ void operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, m_output_collection, m_strategy);
+ }
+ };
+
+ template <typename Collection, typename Strategy>
+ static inline void
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
+ strategy),
+ geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
/*!
@@ -247,31 +468,66 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
\tparam Geometry2 \tparam_geometry
\tparam Collection output collection, either a multi-geometry,
or a std::vector<Geometry> / std::deque<Geometry> etc
+\tparam Strategy \tparam_strategy{Union_}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param output_collection the output collection
+\param strategy \param_strategy{union_}
\note Called union_ because union is a reserved word.
+\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/union.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
- typename Collection
+ typename Collection,
+ typename Strategy
>
inline void union_(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Collection& output_collection)
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
+ resolve_variant::union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, strategy);
+}
- typedef typename boost::range_value<Collection>::type geometry_out;
- concepts::check<geometry_out>();
- detail::union_::union_insert<geometry_out>(geometry1, geometry2,
- range::back_inserter(output_collection));
+/*!
+\brief Combines two geometries which each other
+\ingroup union
+\details \details_calc2{union, spatial set theoretic union}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection output collection, either a multi-geometry,
+ or a std::vector<Geometry> / std::deque<Geometry> etc
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+\note Called union_ because union is a reserved word.
+
+\qbk{[include reference/algorithms/union.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void union_(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection)
+{
+ resolve_variant::union_
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, output_collection, default_strategy());
}
diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp
index a1e6a58f8d..ba170dd27b 100644
--- a/boost/geometry/algorithms/within.hpp
+++ b/boost/geometry/algorithms/within.hpp
@@ -4,8 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2017.
+// Modifications copyright (c) 2013-2017 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.
@@ -14,8 +16,6 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
@@ -52,6 +52,7 @@
#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
@@ -75,9 +76,13 @@ struct use_point_in_geometry
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
- return Strategy::apply(geometry1, geometry2);
+ typedef typename detail::de9im::static_mask_within_type
+ <
+ Geometry1, Geometry2
+ >::type within_mask;
+ return geometry::relate(geometry1, geometry2, within_mask(), strategy);
}
};
@@ -300,23 +305,8 @@ struct within
Geometry2 const& geometry2,
default_strategy)
{
- typedef typename point_type<Geometry1>::type point_type1;
- typedef typename point_type<Geometry2>::type point_type2;
-
typedef typename strategy::within::services::default_strategy
<
- typename tag<Geometry1>::type,
- typename tag<Geometry2>::type,
- typename tag<Geometry1>::type,
- typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
- typename tag_cast
- <
- typename cs_tag<point_type1>::type, spherical_tag
- >::type,
- typename tag_cast
- <
- typename cs_tag<point_type2>::type, spherical_tag
- >::type,
Geometry1,
Geometry2
>::type strategy_type;
@@ -517,8 +507,9 @@ inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
}
*/
template<typename Geometry1, typename Geometry2, typename Strategy>
-inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2,
- Strategy const& strategy)
+inline bool within(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return resolve_variant::within
<
diff --git a/boost/geometry/arithmetic/normalize.hpp b/boost/geometry/arithmetic/normalize.hpp
new file mode 100644
index 0000000000..7dfdbd2b03
--- /dev/null
+++ b/boost/geometry/arithmetic/normalize.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016, 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_ARITHMETIC_NORMALIZE_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_NORMALIZE_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Point>
+inline typename coordinate_type<Point>::type vec_length_sqr(Point const& pt)
+{
+ return dot_product(pt, pt);
+}
+
+template <typename Point>
+inline typename coordinate_type<Point>::type vec_length(Point const& pt)
+{
+ // NOTE: hypot() could be used instead of sqrt()
+ return math::sqrt(dot_product(pt, pt));
+}
+
+template <typename Point>
+inline bool vec_normalize(Point & pt, typename coordinate_type<Point>::type & len)
+{
+ typedef typename coordinate_type<Point>::type coord_t;
+
+ coord_t const c0 = 0;
+ len = vec_length(pt);
+
+ if (math::equals(len, c0))
+ {
+ return false;
+ }
+
+ divide_value(pt, len);
+ return true;
+}
+
+template <typename Point>
+inline bool vec_normalize(Point & pt)
+{
+ typedef typename coordinate_type<Point>::type coord_t;
+ coord_t len;
+ return vec_normalize(pt, len);
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_NORMALIZE_HPP
diff --git a/boost/geometry/core/srs.hpp b/boost/geometry/core/srs.hpp
index bf1b4e28a5..5c78b9f1fc 100644
--- a/boost/geometry/core/srs.hpp
+++ b/boost/geometry/core/srs.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -51,7 +51,7 @@ public:
spheroid()
: m_a(RadiusType(6378137.0))
- , m_b(RadiusType(6356752.314245))
+ , m_b(RadiusType(6356752.3142451793))
{}
template <std::size_t I>
@@ -126,8 +126,9 @@ public:
explicit sphere(RadiusType const& r)
: m_r(r)
{}
+
sphere()
- : m_r(RadiusType((2.0 * 6378137.0 + 6356752.314245) / 3.0))
+ : m_r(RadiusType((2.0 * 6378137.0 + 6356752.3142451793) / 3.0))
{}
template <std::size_t I>
diff --git a/boost/geometry/formulas/andoyer_inverse.hpp b/boost/geometry/formulas/andoyer_inverse.hpp
index 57b5ab5384..902fd7d8f6 100644
--- a/boost/geometry/formulas/andoyer_inverse.hpp
+++ b/boost/geometry/formulas/andoyer_inverse.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2015-2016 Oracle and/or its affiliates.
+// Copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -20,9 +20,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_inverse.hpp>
@@ -75,7 +74,7 @@ public:
CT const c0 = CT(0);
CT const c1 = CT(1);
CT const pi = math::pi<CT>();
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const dlon = lon2 - lon1;
CT const sin_dlon = sin(dlon);
@@ -97,7 +96,7 @@ public:
CT const d = acos(cos_d); // [0, pi]
CT const sin_d = sin(d); // [-1, 1]
-
+
if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
{
CT const K = math::sqr(sin_lat1-sin_lat2);
@@ -138,7 +137,14 @@ public:
CT A = c0;
CT U = c0;
- if ( ! math::equals(cos_lat2, c0) )
+ if (math::equals(cos_lat2, c0))
+ {
+ if (sin_lat2 < c0)
+ {
+ A = pi;
+ }
+ }
+ else
{
CT const tan_lat2 = sin_lat2/cos_lat2;
CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
@@ -149,7 +155,14 @@ public:
CT B = c0;
CT V = c0;
- if ( ! math::equals(cos_lat1, c0) )
+ if (math::equals(cos_lat1, c0))
+ {
+ if (sin_lat1 < c0)
+ {
+ B = pi;
+ }
+ }
+ else
{
CT const tan_lat1 = sin_lat1/cos_lat1;
CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
diff --git a/boost/geometry/formulas/area_formulas.hpp b/boost/geometry/formulas/area_formulas.hpp
new file mode 100644
index 0000000000..6a0b525e25
--- /dev/null
+++ b/boost/geometry/formulas/area_formulas.hpp
@@ -0,0 +1,578 @@
+// Boost.Geometry
+
+// Copyright (c) 2015-2016 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, 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_FORMULAS_AREA_FORMULAS_HPP
+#define BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP
+
+#include <boost/geometry/formulas/flattening.hpp>
+#include <boost/math/special_functions/hypot.hpp>
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief Formulas for computing spherical and ellipsoidal polygon area.
+ The current class computes the area of the trapezoid defined by a segment
+ the two meridians passing by the endpoints and the equator.
+\author See
+- Danielsen JS, The area under the geodesic. Surv Rev 30(232):
+61–66, 1989
+- Charles F.F Karney, Algorithms for geodesics, 2011
+https://arxiv.org/pdf/1109.4448.pdf
+*/
+
+template <
+ typename CT,
+ std::size_t SeriesOrder = 2,
+ bool ExpandEpsN = true
+>
+class area_formulas
+{
+
+public:
+
+ //TODO: move the following to a more general space to be used by other
+ // classes as well
+ /*
+ Evaluate the polynomial in x using Horner's method.
+ */
+ template <typename NT, typename IteratorType>
+ static inline NT horner_evaluate(NT x,
+ IteratorType begin,
+ IteratorType end)
+ {
+ NT result(0);
+ IteratorType it = end;
+ do
+ {
+ result = result * x + *--it;
+ }
+ while (it != begin);
+ return result;
+ }
+
+ /*
+ Clenshaw algorithm for summing trigonometric series
+ https://en.wikipedia.org/wiki/Clenshaw_algorithm
+ */
+ template <typename NT, typename IteratorType>
+ static inline NT clenshaw_sum(NT cosx,
+ IteratorType begin,
+ IteratorType end)
+ {
+ IteratorType it = end;
+ bool odd = true;
+ CT b_k, b_k1(0), b_k2(0);
+ do
+ {
+ CT c_k = odd ? *--it : NT(0);
+ b_k = c_k + NT(2) * cosx * b_k1 - b_k2;
+ b_k2 = b_k1;
+ b_k1 = b_k;
+ odd = !odd;
+ }
+ while (it != begin);
+
+ return *begin + b_k1 * cosx - b_k2;
+ }
+
+ template<typename T>
+ static inline void normalize(T& x, T& y)
+ {
+ T h = boost::math::hypot(x, y);
+ x /= h;
+ y /= h;
+ }
+
+ /*
+ Generate and evaluate the series expansion of the following integral
+
+ I4 = -integrate( (t(ep2) - t(k2*sin(sigma1)^2)) / (ep2 - k2*sin(sigma1)^2)
+ * sin(sigma1)/2, sigma1, pi/2, sigma )
+ where
+
+ t(x) = sqrt(1+1/x)*asinh(sqrt(x)) + x
+
+ valid for ep2 and k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
+ and ep2 = 4 * n / (1 - n)^2 and expand in eps and n.
+
+ The resulting sum of the series is of the form
+
+ sum(C4[l] * cos((2*l+1)*sigma), l, 0, maxpow-1) )
+
+ The above expansion is performed in Computer Algebra System Maxima.
+ The C++ code (that yields the function evaluate_coeffs_n below) is generated
+ by the following Maxima script and is based on script:
+ http://geographiclib.sourceforge.net/html/geod.mac
+
+ // Maxima script begin
+ taylordepth:5$
+ ataylor(expr,var,ord):=expand(ratdisrep(taylor(expr,var,0,ord)))$
+ jtaylor(expr,var1,var2,ord):=block([zz],expand(subst([zz=1],
+ ratdisrep(taylor(subst([var1=zz*var1,var2=zz*var2],expr),zz,0,ord)))))$
+
+ compute(maxpow):=block([int,t,intexp,area, x,ep2,k2],
+ maxpow:maxpow-1,
+ t : sqrt(1+1/x) * asinh(sqrt(x)) + x,
+ int:-(tf(ep2) - tf(k2*sin(sigma)^2)) / (ep2 - k2*sin(sigma)^2)
+ * sin(sigma)/2,
+ int:subst([tf(ep2)=subst([x=ep2],t),
+ tf(k2*sin(sigma)^2)=subst([x=k2*sin(sigma)^2],t)],
+ int),
+ int:subst([abs(sin(sigma))=sin(sigma)],int),
+ int:subst([k2=4*eps/(1-eps)^2,ep2=4*n/(1-n)^2],int),
+ intexp:jtaylor(int,n,eps,maxpow),
+ area:trigreduce(integrate(intexp,sigma)),
+ area:expand(area-subst(sigma=%pi/2,area)),
+ for i:0 thru maxpow do C4[i]:coeff(area,cos((2*i+1)*sigma)),
+ if expand(area-sum(C4[i]*cos((2*i+1)*sigma),i,0,maxpow)) # 0
+ then error("left over terms in I4"),
+ 'done)$
+
+ printcode(maxpow):=
+ block([tab2:" ",tab3:" "],
+ print(" switch (SeriesOrder) {"),
+ for nn:1 thru maxpow do block([c],
+ print(concat(tab2,"case ",string(nn-1),":")),
+ c:0,
+ for m:0 thru nn-1 do block(
+ [q:jtaylor(subst([n=n],C4[m]),n,eps,nn-1),
+ linel:1200],
+ for j:m thru nn-1 do (
+ print(concat(tab3,"coeffs_n[",c,"] = ",
+ string(horner(coeff(q,eps,j))),";")),
+ c:c+1)
+ ),
+ print(concat(tab3,"break;"))),
+ print(" }"),
+ 'done)$
+
+ maxpow:6$
+ compute(maxpow)$
+ printcode(maxpow)$
+ // Maxima script end
+
+ In the resulting code we should replace each number x by CT(x)
+ e.g. using the following scirpt:
+ sed -e 's/[0-9]\+/CT(&)/g; s/\[CT(/\[/g; s/)\]/\]/g;
+ s/case\sCT(/case /g; s/):/:/g'
+ */
+
+ static inline void evaluate_coeffs_n(CT n, CT coeffs_n[])
+ {
+
+ switch (SeriesOrder) {
+ case 0:
+ coeffs_n[0] = CT(2)/CT(3);
+ break;
+ case 1:
+ coeffs_n[0] = (CT(10)-CT(4)*n)/CT(15);
+ coeffs_n[1] = -CT(1)/CT(5);
+ coeffs_n[2] = CT(1)/CT(45);
+ break;
+ case 2:
+ coeffs_n[0] = (n*(CT(8)*n-CT(28))+CT(70))/CT(105);
+ coeffs_n[1] = (CT(16)*n-CT(7))/CT(35);
+ coeffs_n[2] = -CT(2)/CT(105);
+ coeffs_n[3] = (CT(7)-CT(16)*n)/CT(315);
+ coeffs_n[4] = -CT(2)/CT(105);
+ coeffs_n[5] = CT(4)/CT(525);
+ break;
+ case 3:
+ coeffs_n[0] = (n*(n*(CT(4)*n+CT(24))-CT(84))+CT(210))/CT(315);
+ coeffs_n[1] = ((CT(48)-CT(32)*n)*n-CT(21))/CT(105);
+ coeffs_n[2] = (-CT(32)*n-CT(6))/CT(315);
+ coeffs_n[3] = CT(11)/CT(315);
+ coeffs_n[4] = (n*(CT(32)*n-CT(48))+CT(21))/CT(945);
+ coeffs_n[5] = (CT(64)*n-CT(18))/CT(945);
+ coeffs_n[6] = -CT(1)/CT(105);
+ coeffs_n[7] = (CT(12)-CT(32)*n)/CT(1575);
+ coeffs_n[8] = -CT(8)/CT(1575);
+ coeffs_n[9] = CT(8)/CT(2205);
+ break;
+ case 4:
+ coeffs_n[0] = (n*(n*(n*(CT(16)*n+CT(44))+CT(264))-CT(924))+CT(2310))/CT(3465);
+ coeffs_n[1] = (n*(n*(CT(48)*n-CT(352))+CT(528))-CT(231))/CT(1155);
+ coeffs_n[2] = (n*(CT(1088)*n-CT(352))-CT(66))/CT(3465);
+ coeffs_n[3] = (CT(121)-CT(368)*n)/CT(3465);
+ coeffs_n[4] = CT(4)/CT(1155);
+ coeffs_n[5] = (n*((CT(352)-CT(48)*n)*n-CT(528))+CT(231))/CT(10395);
+ coeffs_n[6] = ((CT(704)-CT(896)*n)*n-CT(198))/CT(10395);
+ coeffs_n[7] = (CT(80)*n-CT(99))/CT(10395);
+ coeffs_n[8] = CT(4)/CT(1155);
+ coeffs_n[9] = (n*(CT(320)*n-CT(352))+CT(132))/CT(17325);
+ coeffs_n[10] = (CT(384)*n-CT(88))/CT(17325);
+ coeffs_n[11] = -CT(8)/CT(1925);
+ coeffs_n[12] = (CT(88)-CT(256)*n)/CT(24255);
+ coeffs_n[13] = -CT(16)/CT(8085);
+ coeffs_n[14] = CT(64)/CT(31185);
+ break;
+ case 5:
+ coeffs_n[0] = (n*(n*(n*(n*(CT(100)*n+CT(208))+CT(572))+CT(3432))-CT(12012))+CT(30030))
+ /CT(45045);
+ coeffs_n[1] = (n*(n*(n*(CT(64)*n+CT(624))-CT(4576))+CT(6864))-CT(3003))/CT(15015);
+ coeffs_n[2] = (n*((CT(14144)-CT(10656)*n)*n-CT(4576))-CT(858))/CT(45045);
+ coeffs_n[3] = ((-CT(224)*n-CT(4784))*n+CT(1573))/CT(45045);
+ coeffs_n[4] = (CT(1088)*n+CT(156))/CT(45045);
+ coeffs_n[5] = CT(97)/CT(15015);
+ coeffs_n[6] = (n*(n*((-CT(64)*n-CT(624))*n+CT(4576))-CT(6864))+CT(3003))/CT(135135);
+ coeffs_n[7] = (n*(n*(CT(5952)*n-CT(11648))+CT(9152))-CT(2574))/CT(135135);
+ coeffs_n[8] = (n*(CT(5792)*n+CT(1040))-CT(1287))/CT(135135);
+ coeffs_n[9] = (CT(468)-CT(2944)*n)/CT(135135);
+ coeffs_n[10] = CT(1)/CT(9009);
+ coeffs_n[11] = (n*((CT(4160)-CT(1440)*n)*n-CT(4576))+CT(1716))/CT(225225);
+ coeffs_n[12] = ((CT(4992)-CT(8448)*n)*n-CT(1144))/CT(225225);
+ coeffs_n[13] = (CT(1856)*n-CT(936))/CT(225225);
+ coeffs_n[14] = CT(8)/CT(10725);
+ coeffs_n[15] = (n*(CT(3584)*n-CT(3328))+CT(1144))/CT(315315);
+ coeffs_n[16] = (CT(1024)*n-CT(208))/CT(105105);
+ coeffs_n[17] = -CT(136)/CT(63063);
+ coeffs_n[18] = (CT(832)-CT(2560)*n)/CT(405405);
+ coeffs_n[19] = -CT(128)/CT(135135);
+ coeffs_n[20] = CT(128)/CT(99099);
+ break;
+ }
+ }
+
+ /*
+ Expand in k2 and ep2.
+ */
+ static inline void evaluate_coeffs_ep(CT ep, CT coeffs_n[])
+ {
+ switch (SeriesOrder) {
+ case 0:
+ coeffs_n[0] = CT(2)/CT(3);
+ break;
+ case 1:
+ coeffs_n[0] = (CT(10)-ep)/CT(15);
+ coeffs_n[1] = -CT(1)/CT(20);
+ coeffs_n[2] = CT(1)/CT(180);
+ break;
+ case 2:
+ coeffs_n[0] = (ep*(CT(4)*ep-CT(7))+CT(70))/CT(105);
+ coeffs_n[1] = (CT(4)*ep-CT(7))/CT(140);
+ coeffs_n[2] = CT(1)/CT(42);
+ coeffs_n[3] = (CT(7)-CT(4)*ep)/CT(1260);
+ coeffs_n[4] = -CT(1)/CT(252);
+ coeffs_n[5] = CT(1)/CT(2100);
+ break;
+ case 3:
+ coeffs_n[0] = (ep*((CT(12)-CT(8)*ep)*ep-CT(21))+CT(210))/CT(315);
+ coeffs_n[1] = ((CT(12)-CT(8)*ep)*ep-CT(21))/CT(420);
+ coeffs_n[2] = (CT(3)-CT(2)*ep)/CT(126);
+ coeffs_n[3] = -CT(1)/CT(72);
+ coeffs_n[4] = (ep*(CT(8)*ep-CT(12))+CT(21))/CT(3780);
+ coeffs_n[5] = (CT(2)*ep-CT(3))/CT(756);
+ coeffs_n[6] = CT(1)/CT(360);
+ coeffs_n[7] = (CT(3)-CT(2)*ep)/CT(6300);
+ coeffs_n[8] = -CT(1)/CT(1800);
+ coeffs_n[9] = CT(1)/CT(17640);
+ break;
+ case 4:
+ coeffs_n[0] = (ep*(ep*(ep*(CT(64)*ep-CT(88))+CT(132))-CT(231))+CT(2310))/CT(3465);
+ coeffs_n[1] = (ep*(ep*(CT(64)*ep-CT(88))+CT(132))-CT(231))/CT(4620);
+ coeffs_n[2] = (ep*(CT(16)*ep-CT(22))+CT(33))/CT(1386);
+ coeffs_n[3] = (CT(8)*ep-CT(11))/CT(792);
+ coeffs_n[4] = CT(1)/CT(110);
+ coeffs_n[5] = (ep*((CT(88)-CT(64)*ep)*ep-CT(132))+CT(231))/CT(41580);
+ coeffs_n[6] = ((CT(22)-CT(16)*ep)*ep-CT(33))/CT(8316);
+ coeffs_n[7] = (CT(11)-CT(8)*ep)/CT(3960);
+ coeffs_n[8] = -CT(1)/CT(495);
+ coeffs_n[9] = (ep*(CT(16)*ep-CT(22))+CT(33))/CT(69300);
+ coeffs_n[10] = (CT(8)*ep-CT(11))/CT(19800);
+ coeffs_n[11] = CT(1)/CT(1925);
+ coeffs_n[12] = (CT(11)-CT(8)*ep)/CT(194040);
+ coeffs_n[13] = -CT(1)/CT(10780);
+ coeffs_n[14] = CT(1)/CT(124740);
+ break;
+ case 5:
+ coeffs_n[0] = (ep*(ep*(ep*((CT(832)-CT(640)*ep)*ep-CT(1144))+CT(1716))-CT(3003))+CT(30030))/CT(45045);
+ coeffs_n[1] = (ep*(ep*((CT(832)-CT(640)*ep)*ep-CT(1144))+CT(1716))-CT(3003))/CT(60060);
+ coeffs_n[2] = (ep*((CT(208)-CT(160)*ep)*ep-CT(286))+CT(429))/CT(18018);
+ coeffs_n[3] = ((CT(104)-CT(80)*ep)*ep-CT(143))/CT(10296);
+ coeffs_n[4] = (CT(13)-CT(10)*ep)/CT(1430);
+ coeffs_n[5] = -CT(1)/CT(156);
+ coeffs_n[6] = (ep*(ep*(ep*(CT(640)*ep-CT(832))+CT(1144))-CT(1716))+CT(3003))/CT(540540);
+ coeffs_n[7] = (ep*(ep*(CT(160)*ep-CT(208))+CT(286))-CT(429))/CT(108108);
+ coeffs_n[8] = (ep*(CT(80)*ep-CT(104))+CT(143))/CT(51480);
+ coeffs_n[9] = (CT(10)*ep-CT(13))/CT(6435);
+ coeffs_n[10] = CT(5)/CT(3276);
+ coeffs_n[11] = (ep*((CT(208)-CT(160)*ep)*ep-CT(286))+CT(429))/CT(900900);
+ coeffs_n[12] = ((CT(104)-CT(80)*ep)*ep-CT(143))/CT(257400);
+ coeffs_n[13] = (CT(13)-CT(10)*ep)/CT(25025);
+ coeffs_n[14] = -CT(1)/CT(2184);
+ coeffs_n[15] = (ep*(CT(80)*ep-CT(104))+CT(143))/CT(2522520);
+ coeffs_n[16] = (CT(10)*ep-CT(13))/CT(140140);
+ coeffs_n[17] = CT(5)/CT(45864);
+ coeffs_n[18] = (CT(13)-CT(10)*ep)/CT(1621620);
+ coeffs_n[19] = -CT(1)/CT(58968);
+ coeffs_n[20] = CT(1)/CT(792792);
+ break;
+ }
+ }
+
+ /*
+ Given the set of coefficients coeffs1[] evaluate on var2 and return
+ the set of coefficients coeffs2[]
+ */
+ static inline void evaluate_coeffs_var2(CT var2,
+ CT coeffs1[],
+ CT coeffs2[]){
+ std::size_t begin(0), end(0);
+ for(std::size_t i = 0; i <= SeriesOrder; i++){
+ end = begin + SeriesOrder + 1 - i;
+ coeffs2[i] = ((i==0) ? CT(1) : pow(var2,int(i)))
+ * horner_evaluate(var2, coeffs1 + begin, coeffs1 + end);
+ begin = end;
+ }
+ }
+
+ /*
+ Compute the spherical excess of a geodesic (or shperical) segment
+ */
+ template <
+ bool LongSegment,
+ typename PointOfSegment
+ >
+ static inline CT spherical(PointOfSegment const& p1,
+ PointOfSegment const& p2)
+ {
+ CT excess;
+
+ if(LongSegment) // not for segments parallel to equator
+ {
+ CT cbet1 = cos(geometry::get_as_radian<1>(p1));
+ CT sbet1 = sin(geometry::get_as_radian<1>(p1));
+ CT cbet2 = cos(geometry::get_as_radian<1>(p2));
+ CT sbet2 = sin(geometry::get_as_radian<1>(p2));
+
+ CT omg12 = geometry::get_as_radian<0>(p1)
+ - geometry::get_as_radian<0>(p2);
+ CT comg12 = cos(omg12);
+ CT somg12 = sin(omg12);
+
+ CT alp1 = atan2(cbet1 * sbet2
+ - sbet1 * cbet2 * comg12,
+ cbet2 * somg12);
+
+ CT alp2 = atan2(cbet1 * sbet2 * comg12
+ - sbet1 * cbet2,
+ cbet1 * somg12);
+
+ excess = alp2 - alp1;
+
+ } else {
+
+ // Trapezoidal formula
+
+ CT tan_lat1 =
+ tan(geometry::get_as_radian<1>(p1) / 2.0);
+ CT tan_lat2 =
+ tan(geometry::get_as_radian<1>(p2) / 2.0);
+
+ excess = CT(2.0)
+ * atan(((tan_lat1 + tan_lat2) / (CT(1) + tan_lat1 * tan_lat2))
+ * tan((geometry::get_as_radian<0>(p2)
+ - geometry::get_as_radian<0>(p1)) / 2));
+ }
+
+ return excess;
+ }
+
+ struct return_type_ellipsoidal
+ {
+ return_type_ellipsoidal()
+ : spherical_term(0),
+ ellipsoidal_term(0)
+ {}
+
+ CT spherical_term;
+ CT ellipsoidal_term;
+ };
+
+ /*
+ Compute the ellipsoidal correction of a geodesic (or shperical) segment
+ */
+ template <
+ template <typename, bool, bool, bool, bool, bool> class Inverse,
+ //typename AzimuthStrategy,
+ typename PointOfSegment,
+ typename SpheroidConst
+ >
+ static inline return_type_ellipsoidal ellipsoidal(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ SpheroidConst spheroid_const)
+ {
+ return_type_ellipsoidal result;
+
+ // Azimuth Approximation
+
+ typedef Inverse<CT, false, true, true, false, false> inverse_type;
+ typedef typename inverse_type::result_type inverse_result;
+
+ inverse_result i_res = inverse_type::apply(get_as_radian<0>(p1),
+ get_as_radian<1>(p1),
+ get_as_radian<0>(p2),
+ get_as_radian<1>(p2),
+ spheroid_const.m_spheroid);
+
+ CT alp1 = i_res.azimuth;
+ CT alp2 = i_res.reverse_azimuth;
+
+ // Constants
+
+ CT const ep = spheroid_const.m_ep;
+ CT const f = formula::flattening<CT>(spheroid_const.m_spheroid);
+ CT const one_minus_f = CT(1) - f;
+ std::size_t const series_order_plus_one = SeriesOrder + 1;
+ std::size_t const series_order_plus_two = SeriesOrder + 2;
+
+ // Basic trigonometric computations
+
+ CT tan_bet1 = tan(get_as_radian<1>(p1)) * one_minus_f;
+ CT tan_bet2 = tan(get_as_radian<1>(p2)) * one_minus_f;
+ CT cos_bet1 = cos(atan(tan_bet1));
+ CT cos_bet2 = cos(atan(tan_bet2));
+ CT sin_bet1 = tan_bet1 * cos_bet1;
+ CT sin_bet2 = tan_bet2 * cos_bet2;
+ CT sin_alp1 = sin(alp1);
+ CT cos_alp1 = cos(alp1);
+ CT cos_alp2 = cos(alp2);
+ CT sin_alp0 = sin_alp1 * cos_bet1;
+
+ // Spherical term computation
+
+ CT sin_omg1 = sin_alp0 * sin_bet1;
+ CT cos_omg1 = cos_alp1 * cos_bet1;
+ CT sin_omg2 = sin_alp0 * sin_bet2;
+ CT cos_omg2 = cos_alp2 * cos_bet2;
+ CT cos_omg12 = cos_omg1 * cos_omg2 + sin_omg1 * sin_omg2;
+ CT excess;
+
+ bool meridian = get<0>(p2) - get<0>(p1) == CT(0)
+ || get<1>(p1) == CT(90) || get<1>(p1) == -CT(90)
+ || get<1>(p2) == CT(90) || get<1>(p2) == -CT(90);
+
+ if (!meridian && cos_omg12 > -CT(0.7)
+ && sin_bet2 - sin_bet1 < CT(1.75)) // short segment
+ {
+ CT sin_omg12 = cos_omg1 * sin_omg2 - sin_omg1 * cos_omg2;
+ normalize(sin_omg12, cos_omg12);
+
+ CT cos_omg12p1 = CT(1) + cos_omg12;
+ CT cos_bet1p1 = CT(1) + cos_bet1;
+ CT cos_bet2p1 = CT(1) + cos_bet2;
+ excess = CT(2) * atan2(sin_omg12 * (sin_bet1 * cos_bet2p1 + sin_bet2 * cos_bet1p1),
+ cos_omg12p1 * (sin_bet1 * sin_bet2 + cos_bet1p1 * cos_bet2p1));
+ }
+ else
+ {
+ /*
+ CT sin_alp2 = sin(alp2);
+ CT sin_alp12 = sin_alp2 * cos_alp1 - cos_alp2 * sin_alp1;
+ CT cos_alp12 = cos_alp2 * cos_alp1 + sin_alp2 * sin_alp1;
+ excess = atan2(sin_alp12, cos_alp12);
+ */
+ excess = alp2 - alp1;
+ }
+
+ result.spherical_term = excess;
+
+ // Ellipsoidal term computation (uses integral approximation)
+
+ CT cos_alp0 = math::sqrt(CT(1) - math::sqr(sin_alp0));
+ CT cos_sig1 = cos_alp1 * cos_bet1;
+ CT cos_sig2 = cos_alp2 * cos_bet2;
+ CT sin_sig1 = sin_bet1;
+ CT sin_sig2 = sin_bet2;
+
+ normalize(sin_sig1, cos_sig1);
+ normalize(sin_sig2, cos_sig2);
+
+ CT coeffs[SeriesOrder + 1];
+ const std::size_t coeffs_var_size = (series_order_plus_two
+ * series_order_plus_one) / 2;
+ CT coeffs_var[coeffs_var_size];
+
+ if(ExpandEpsN){ // expand by eps and n
+
+ CT k2 = math::sqr(ep * cos_alp0);
+ CT sqrt_k2_plus_one = math::sqrt(CT(1) + k2);
+ CT eps = (sqrt_k2_plus_one - CT(1)) / (sqrt_k2_plus_one + CT(1));
+ CT n = f / (CT(2) - f);
+
+ // Generate and evaluate the polynomials on n
+ // to get the series coefficients (that depend on eps)
+ evaluate_coeffs_n(n, coeffs_var);
+
+ // Generate and evaluate the polynomials on eps (i.e. var2 = eps)
+ // to get the final series coefficients
+ evaluate_coeffs_var2(eps, coeffs_var, coeffs);
+
+ }else{ // expand by k2 and ep
+
+ CT k2 = math::sqr(ep * cos_alp0);
+ CT ep2 = math::sqr(ep);
+
+ // Generate and evaluate the polynomials on ep2
+ evaluate_coeffs_ep(ep2, coeffs_var);
+
+ // Generate and evaluate the polynomials on k2 (i.e. var2 = k2)
+ evaluate_coeffs_var2(k2, coeffs_var, coeffs);
+
+ }
+
+ // Evaluate the trigonometric sum
+ CT I12 = clenshaw_sum(cos_sig2, coeffs, coeffs + series_order_plus_one)
+ - clenshaw_sum(cos_sig1, coeffs, coeffs + series_order_plus_one);
+
+ // The part of the ellipsodal correction that depends on
+ // point coordinates
+ result.ellipsoidal_term = cos_alp0 * sin_alp0 * I12;
+
+ return result;
+ }
+
+ // Keep track whenever a segment crosses the prime meridian
+ // First normalize to [0,360)
+ template <typename PointOfSegment, typename StateType>
+ static inline int crosses_prime_meridian(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ StateType& state)
+ {
+ CT const pi
+ = geometry::math::pi<CT>();
+ CT const two_pi
+ = geometry::math::two_pi<CT>();
+
+ CT p1_lon = get_as_radian<0>(p1)
+ - ( floor( get_as_radian<0>(p1) / two_pi )
+ * two_pi );
+ CT p2_lon = get_as_radian<0>(p2)
+ - ( floor( get_as_radian<0>(p2) / two_pi )
+ * two_pi );
+
+ CT max_lon = (std::max)(p1_lon, p2_lon);
+ CT min_lon = (std::min)(p1_lon, p2_lon);
+
+ if(max_lon > pi && min_lon < pi && max_lon - min_lon > pi)
+ {
+ state.m_crosses_prime_meridian++;
+ }
+
+ return state.m_crosses_prime_meridian;
+ }
+
+};
+
+}}} // namespace boost::geometry::formula
+
+
+#endif // BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP
diff --git a/boost/geometry/formulas/differential_quantities.hpp b/boost/geometry/formulas/differential_quantities.hpp
index 9a92f14e18..ff2ec539db 100644
--- a/boost/geometry/formulas/differential_quantities.hpp
+++ b/boost/geometry/formulas/differential_quantities.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2016 Oracle and/or its affiliates.
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -64,8 +64,8 @@ public:
CT const c1 = 1;
CT const one_minus_f = c1 - f;
- CT const sin_bet1 = one_minus_f * sin_lat1;
- CT const sin_bet2 = one_minus_f * sin_lat2;
+ CT sin_bet1 = one_minus_f * sin_lat1;
+ CT sin_bet2 = one_minus_f * sin_lat2;
// equator
if (math::equals(sin_bet1, c0) && math::equals(sin_bet2, c0))
@@ -89,14 +89,17 @@ public:
CT const e2 = f * (c2 - f);
CT const ep2 = e2 / math::sqr(one_minus_f);
- CT const cos_bet1 = cos_lat1;
- CT const cos_bet2 = cos_lat2;
-
CT const sin_alp1 = sin(azimuth);
CT const cos_alp1 = cos(azimuth);
//CT const sin_alp2 = sin(reverse_azimuth);
CT const cos_alp2 = cos(reverse_azimuth);
+ CT cos_bet1 = cos_lat1;
+ CT cos_bet2 = cos_lat2;
+
+ normalize(sin_bet1, cos_bet1);
+ normalize(sin_bet2, cos_bet2);
+
CT sin_sig1 = sin_bet1;
CT cos_sig1 = cos_alp1 * cos_bet1;
CT sin_sig2 = sin_bet2;
@@ -112,8 +115,8 @@ public:
J12_f(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, f) :
J12_ep_sqr(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, ep2) ;
- CT const dn1 = math::sqrt(c1 + e2 * math::sqr(sin_lat1));
- CT const dn2 = math::sqrt(c1 + e2 * math::sqr(sin_lat2));
+ CT const dn1 = math::sqrt(c1 + ep2 * math::sqr(sin_bet1));
+ CT const dn2 = math::sqrt(c1 + ep2 * math::sqr(sin_bet2));
if (BOOST_GEOMETRY_CONDITION(EnableReducedLength))
{
diff --git a/boost/geometry/formulas/eccentricity_sqr.hpp b/boost/geometry/formulas/eccentricity_sqr.hpp
new file mode 100644
index 0000000000..01a9beacb9
--- /dev/null
+++ b/boost/geometry/formulas/eccentricity_sqr.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry
+
+// Copyright (c) 2016 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_FORMULAS_ECCENCRICITY_SQR_HPP
+#define BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace formula_dispatch
+{
+
+template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct eccentricity_sqr
+ : not_implemented<Tag>
+{};
+
+template <typename ResultType, typename Geometry>
+struct eccentricity_sqr<ResultType, Geometry, srs_sphere_tag>
+{
+ static inline ResultType apply(Geometry const& /*geometry*/)
+ {
+ return ResultType(0);
+ }
+};
+
+template <typename ResultType, typename Geometry>
+struct eccentricity_sqr<ResultType, Geometry, srs_spheroid_tag>
+{
+ static inline ResultType apply(Geometry const& geometry)
+ {
+ // 1 - (b / a)^2
+ return ResultType(1) - math::sqr(ResultType(get_radius<2>(geometry))
+ / ResultType(get_radius<0>(geometry)));
+ }
+};
+
+} // namespace formula_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace formula
+{
+
+template <typename ResultType, typename Geometry>
+ResultType eccentricity_sqr(Geometry const& geometry)
+{
+ return formula_dispatch::eccentricity_sqr<ResultType, Geometry>::apply(geometry);
+}
+
+} // namespace formula
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP
diff --git a/boost/geometry/algorithms/detail/flattening.hpp b/boost/geometry/formulas/flattening.hpp
index 8ed5fd9a89..f94ead65b0 100644
--- a/boost/geometry/algorithms/detail/flattening.hpp
+++ b/boost/geometry/formulas/flattening.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2014 Oracle and/or its affiliates.
+// Copyright (c) 2014-2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -8,8 +8,8 @@
// 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_FLATTENING_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
+#ifndef BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
+#define BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/tag.hpp>
@@ -21,7 +21,7 @@ namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
-namespace detail_dispatch
+namespace formula_dispatch
{
template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
@@ -43,27 +43,28 @@ struct flattening<ResultType, Geometry, srs_spheroid_tag>
{
static inline ResultType apply(Geometry const& geometry)
{
+ // (a - b) / a
return ResultType(get_radius<0>(geometry) - get_radius<2>(geometry))
/ ResultType(get_radius<0>(geometry));
}
};
-} // namespace detail_dispatch
+} // namespace formula_dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DETAIL
-namespace detail
+namespace formula
{
template <typename ResultType, typename Geometry>
ResultType flattening(Geometry const& geometry)
{
- return detail_dispatch::flattening<ResultType, Geometry>::apply(geometry);
+ return formula_dispatch::flattening<ResultType, Geometry>::apply(geometry);
}
-} // namespace detail
+} // namespace formula
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
+#endif // BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
diff --git a/boost/geometry/formulas/geographic.hpp b/boost/geometry/formulas/geographic.hpp
new file mode 100644
index 0000000000..f6feb66633
--- /dev/null
+++ b/boost/geometry/formulas/geographic.hpp
@@ -0,0 +1,457 @@
+// Boost.Geometry
+
+// Copyright (c) 2016, 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_FORMULAS_GEOGRAPHIC_HPP
+#define BOOST_GEOMETRY_FORMULAS_GEOGRAPHIC_HPP
+
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/cross_product.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+#include <boost/geometry/arithmetic/normalize.hpp>
+
+#include <boost/geometry/formulas/eccentricity_sqr.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry {
+
+namespace formula {
+
+template <typename Point3d, typename PointGeo, typename Spheroid>
+inline Point3d geo_to_cart3d(PointGeo const& point_geo, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type calc_t;
+
+ calc_t const c1 = 1;
+ calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
+
+ calc_t const lon = get_as_radian<0>(point_geo);
+ calc_t const lat = get_as_radian<1>(point_geo);
+
+ Point3d res;
+
+ calc_t const sin_lat = sin(lat);
+
+ // "unit" spheroid, a = 1
+ calc_t const N = c1 / math::sqrt(c1 - e_sqr * math::sqr(sin_lat));
+ calc_t const N_cos_lat = N * cos(lat);
+
+ set<0>(res, N_cos_lat * cos(lon));
+ set<1>(res, N_cos_lat * sin(lon));
+ set<2>(res, N * (c1 - e_sqr) * sin_lat);
+
+ return res;
+}
+
+template <typename PointGeo, typename Spheroid, typename Point3d>
+inline void geo_to_cart3d(PointGeo const& point_geo, Point3d & result, Point3d & north, Point3d & east, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type calc_t;
+
+ calc_t const c1 = 1;
+ calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
+
+ calc_t const lon = get_as_radian<0>(point_geo);
+ calc_t const lat = get_as_radian<1>(point_geo);
+
+ calc_t const sin_lon = sin(lon);
+ calc_t const cos_lon = cos(lon);
+ calc_t const sin_lat = sin(lat);
+ calc_t const cos_lat = cos(lat);
+
+ // "unit" spheroid, a = 1
+ calc_t const N = c1 / math::sqrt(c1 - e_sqr * math::sqr(sin_lat));
+ calc_t const N_cos_lat = N * cos_lat;
+
+ set<0>(result, N_cos_lat * cos_lon);
+ set<1>(result, N_cos_lat * sin_lon);
+ set<2>(result, N * (c1 - e_sqr) * sin_lat);
+
+ set<0>(east, -sin_lon);
+ set<1>(east, cos_lon);
+ set<2>(east, 0);
+
+ set<0>(north, -sin_lat * cos_lon);
+ set<1>(north, -sin_lat * sin_lon);
+ set<2>(north, cos_lat);
+}
+
+template <typename PointGeo, typename Point3d, typename Spheroid>
+inline PointGeo cart3d_to_geo(Point3d const& point_3d, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<PointGeo>::type coord_t;
+ typedef typename coordinate_type<Point3d>::type calc_t;
+
+ calc_t const c1 = 1;
+ //calc_t const c2 = 2;
+ calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
+
+ calc_t const x = get<0>(point_3d);
+ calc_t const y = get<1>(point_3d);
+ calc_t const z = get<2>(point_3d);
+ calc_t const xy_l = math::sqrt(math::sqr(x) + math::sqr(y));
+
+ calc_t const lonr = atan2(y, x);
+
+ // NOTE: Alternative version
+ // http://www.iag-aig.org/attach/989c8e501d9c5b5e2736955baf2632f5/V60N2_5FT.pdf
+ // calc_t const lonr = c2 * atan2(y, x + xy_l);
+
+ calc_t const latr = atan2(z, (c1 - e_sqr) * xy_l);
+
+ // NOTE: If h is equal to 0 then there is no need to improve value of latitude
+ // because then N_i / (N_i + h_i) = 1
+ // http://www.navipedia.net/index.php/Ellipsoidal_and_Cartesian_Coordinates_Conversion
+
+ PointGeo res;
+
+ set_from_radian<0>(res, lonr);
+ set_from_radian<1>(res, latr);
+
+ coord_t lon = get<0>(res);
+ coord_t lat = get<1>(res);
+
+ math::normalize_spheroidal_coordinates
+ <
+ typename coordinate_system<PointGeo>::type::units,
+ coord_t
+ >(lon, lat);
+
+ set<0>(res, lon);
+ set<1>(res, lat);
+
+ return res;
+}
+
+template <typename Point3d, typename Spheroid>
+inline Point3d projected_to_xy(Point3d const& point_3d, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // len_xy = sqrt(x^2 + y^2)
+ // r = len_xy - |z / tan(lat)|
+ // assuming h = 0
+ // lat = atan2(z, (1 - e^2) * len_xy);
+ // |z / tan(lat)| = (1 - e^2) * len_xy
+ // r = e^2 * len_xy
+ // x_res = r * cos(lon) = e^2 * len_xy * x / len_xy = e^2 * x
+ // y_res = r * sin(lon) = e^2 * len_xy * y / len_xy = e^2 * y
+
+ coord_t const c0 = 0;
+ coord_t const e_sqr = formula::eccentricity_sqr<coord_t>(spheroid);
+
+ Point3d res;
+
+ set<0>(res, e_sqr * get<0>(point_3d));
+ set<1>(res, e_sqr * get<1>(point_3d));
+ set<2>(res, c0);
+
+ return res;
+}
+
+template <typename Point3d, typename Spheroid>
+inline Point3d projected_to_surface(Point3d const& direction, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ //coord_t const c0 = 0;
+ coord_t const c2 = 2;
+ coord_t const c4 = 4;
+
+ // calculate the point of intersection of a ray and spheroid's surface
+ // the origin is the origin of the coordinate system
+ //(x*x+y*y)/(a*a) + z*z/(b*b) = 1
+ // x = d.x * t
+ // y = d.y * t
+ // z = d.z * t
+ coord_t const dx = get<0>(direction);
+ coord_t const dy = get<1>(direction);
+ coord_t const dz = get<2>(direction);
+
+ //coord_t const a_sqr = math::sqr(get_radius<0>(spheroid));
+ //coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
+ // "unit" spheroid, a = 1
+ coord_t const a_sqr = 1;
+ coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
+
+ coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
+ coord_t const delta = c4 * param_a;
+ // delta >= 0
+ coord_t const t = math::sqrt(delta) / (c2 * param_a);
+
+ // result = direction * t
+ Point3d result = direction;
+ multiply_value(result, t);
+
+ return result;
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool projected_to_surface(Point3d const& origin, Point3d const& direction, Point3d & result1, Point3d & result2, Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t const c0 = 0;
+ coord_t const c1 = 1;
+ coord_t const c2 = 2;
+ coord_t const c4 = 4;
+
+ // calculate the point of intersection of a ray and spheroid's surface
+ //(x*x+y*y)/(a*a) + z*z/(b*b) = 1
+ // x = o.x + d.x * t
+ // y = o.y + d.y * t
+ // z = o.z + d.z * t
+ coord_t const ox = get<0>(origin);
+ coord_t const oy = get<1>(origin);
+ coord_t const oz = get<2>(origin);
+ coord_t const dx = get<0>(direction);
+ coord_t const dy = get<1>(direction);
+ coord_t const dz = get<2>(direction);
+
+ //coord_t const a_sqr = math::sqr(get_radius<0>(spheroid));
+ //coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
+ // "unit" spheroid, a = 1
+ coord_t const a_sqr = 1;
+ coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
+
+ coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
+ coord_t const param_b = c2 * ((ox*dx + oy*dy) / a_sqr + oz*dz / b_sqr);
+ coord_t const param_c = (ox*ox + oy*oy) / a_sqr + oz*oz / b_sqr - c1;
+
+ coord_t const delta = math::sqr(param_b) - c4 * param_a*param_c;
+
+ // equals() ?
+ if (delta < c0 || param_a == 0)
+ {
+ return false;
+ }
+
+ // result = origin + direction * t
+
+ coord_t const sqrt_delta = math::sqrt(delta);
+ coord_t const two_a = c2 * param_a;
+
+ coord_t const t1 = (-param_b + sqrt_delta) / two_a;
+ result1 = direction;
+ multiply_value(result1, t1);
+ add_point(result1, origin);
+
+ coord_t const t2 = (-param_b - sqrt_delta) / two_a;
+ result2 = direction;
+ multiply_value(result2, t2);
+ add_point(result2, origin);
+
+ return true;
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool great_elliptic_intersection(Point3d const& a1, Point3d const& a2,
+ Point3d const& b1, Point3d const& b2,
+ Point3d & result,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t c0 = 0;
+ coord_t c1 = 1;
+
+ Point3d n1 = cross_product(a1, a2);
+ Point3d n2 = cross_product(b1, b2);
+
+ // intersection direction
+ Point3d id = cross_product(n1, n2);
+ coord_t id_len_sqr = dot_product(id, id);
+
+ if (math::equals(id_len_sqr, c0))
+ {
+ return false;
+ }
+
+ // no need to normalize a1 and a2 because the intersection point on
+ // the opposite side of the globe is at the same distance from the origin
+ coord_t cos_a1i = dot_product(a1, id);
+ coord_t cos_a2i = dot_product(a2, id);
+ coord_t gri = math::detail::greatest(cos_a1i, cos_a2i);
+ Point3d neg_id = id;
+ multiply_value(neg_id, -c1);
+ coord_t cos_a1ni = dot_product(a1, neg_id);
+ coord_t cos_a2ni = dot_product(a2, neg_id);
+ coord_t grni = math::detail::greatest(cos_a1ni, cos_a2ni);
+
+ if (gri >= grni)
+ {
+ result = projected_to_surface(id, spheroid);
+ }
+ else
+ {
+ result = projected_to_surface(neg_id, spheroid);
+ }
+
+ return true;
+}
+
+template <typename Point3d1, typename Point3d2>
+static inline int elliptic_side_value(Point3d1 const& origin, Point3d1 const& norm, Point3d2 const& pt)
+{
+ typedef typename coordinate_type<Point3d1>::type calc_t;
+ calc_t c0 = 0;
+
+ // vector oposite to pt - origin
+ // only for the purpose of assigning origin
+ Point3d1 vec = origin;
+ subtract_point(vec, pt);
+
+ calc_t d = dot_product(norm, vec);
+
+ // since the vector is opposite the signs are opposite
+ return math::equals(d, c0) ? 0
+ : d < c0 ? 1
+ : -1; // d > 0
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool planes_spheroid_intersection(Point3d const& o1, Point3d const& n1,
+ Point3d const& o2, Point3d const& n2,
+ Point3d & ip1, Point3d & ip2,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t c0 = 0;
+ coord_t c1 = 1;
+
+ // Below
+ // n . (p - o) = 0
+ // n . p - n . o = 0
+ // n . p + d = 0
+ // n . p = h
+
+ // intersection direction
+ Point3d id = cross_product(n1, n2);
+
+ if (math::equals(dot_product(id, id), c0))
+ {
+ return false;
+ }
+
+ coord_t dot_n1_n2 = dot_product(n1, n2);
+ coord_t dot_n1_n2_sqr = math::sqr(dot_n1_n2);
+
+ coord_t h1 = dot_product(n1, o1);
+ coord_t h2 = dot_product(n2, o2);
+
+ coord_t denom = c1 - dot_n1_n2_sqr;
+ coord_t C1 = (h1 - h2 * dot_n1_n2) / denom;
+ coord_t C2 = (h2 - h1 * dot_n1_n2) / denom;
+
+ // C1 * n1 + C2 * n2
+ Point3d C1_n1 = n1;
+ multiply_value(C1_n1, C1);
+ Point3d C2_n2 = n2;
+ multiply_value(C2_n2, C2);
+ Point3d io = C1_n1;
+ add_point(io, C2_n2);
+
+ if (! projected_to_surface(io, id, ip1, ip2, spheroid))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+template <typename Point3d, typename Spheroid>
+inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
+ Point3d & v1, Point3d & v2,
+ Point3d & origin, Point3d & normal,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ Point3d xy1 = projected_to_xy(p1, spheroid);
+ Point3d xy2 = projected_to_xy(p2, spheroid);
+
+ // origin = (xy1 + xy2) / 2
+ origin = xy1;
+ add_point(origin, xy2);
+ multiply_value(origin, coord_t(0.5));
+
+ // v1 = p1 - origin
+ v1 = p1;
+ subtract_point(v1, origin);
+ // v2 = p2 - origin
+ v2 = p2;
+ subtract_point(v2, origin);
+
+ normal = cross_product(v1, v2);
+}
+
+template <typename Point3d, typename Spheroid>
+inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
+ Point3d & origin, Point3d & normal,
+ Spheroid const& spheroid)
+{
+ Point3d v1, v2;
+ experimental_elliptic_plane(p1, p2, v1, v2, origin, normal, spheroid);
+}
+
+template <typename Point3d, typename Spheroid>
+inline bool experimental_elliptic_intersection(Point3d const& a1, Point3d const& a2,
+ Point3d const& b1, Point3d const& b2,
+ Point3d & result,
+ Spheroid const& spheroid)
+{
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ coord_t c0 = 0;
+ coord_t c1 = 1;
+
+ Point3d a1v, a2v, o1, n1;
+ experimental_elliptic_plane(a1, a2, a1v, a2v, o1, n1, spheroid);
+ Point3d b1v, b2v, o2, n2;
+ experimental_elliptic_plane(b1, b2, b1v, b2v, o2, n2, spheroid);
+
+ if (! detail::vec_normalize(n1) || ! detail::vec_normalize(n2))
+ {
+ return false;
+ }
+
+ Point3d ip1_s, ip2_s;
+ if (! planes_spheroid_intersection(o1, n1, o2, n2, ip1_s, ip2_s, spheroid))
+ {
+ return false;
+ }
+
+ // NOTE: simplified test, may not work in all cases
+ coord_t dot_a1i1 = dot_product(a1, ip1_s);
+ coord_t dot_a2i1 = dot_product(a2, ip1_s);
+ coord_t gri1 = math::detail::greatest(dot_a1i1, dot_a2i1);
+ coord_t dot_a1i2 = dot_product(a1, ip2_s);
+ coord_t dot_a2i2 = dot_product(a2, ip2_s);
+ coord_t gri2 = math::detail::greatest(dot_a1i2, dot_a2i2);
+
+ result = gri1 >= gri2 ? ip1_s : ip2_s;
+
+ return true;
+}
+
+} // namespace formula
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_FORMULAS_GEOGRAPHIC_HPP
diff --git a/boost/geometry/formulas/gnomonic_spheroid.hpp b/boost/geometry/formulas/gnomonic_spheroid.hpp
index 3457397b0f..4710c6c063 100644
--- a/boost/geometry/formulas/gnomonic_spheroid.hpp
+++ b/boost/geometry/formulas/gnomonic_spheroid.hpp
@@ -14,12 +14,11 @@
#include <boost/geometry/core/radius.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/thomas_inverse.hpp>
#include <boost/geometry/formulas/vincenty_direct.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>
diff --git a/boost/geometry/formulas/sjoberg_intersection.hpp b/boost/geometry/formulas/sjoberg_intersection.hpp
index 03bd4bc97e..92f9e8e78e 100644
--- a/boost/geometry/formulas/sjoberg_intersection.hpp
+++ b/boost/geometry/formulas/sjoberg_intersection.hpp
@@ -20,19 +20,606 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
namespace boost { namespace geometry { namespace formula
{
/*!
+\brief The intersection of two great circles as proposed by Sjoberg.
+\see See
+ - [Sjoberg02] Lars E. Sjoberg, Intersections on the sphere and ellipsoid, 2002
+ http://link.springer.com/article/10.1007/s00190-001-0230-9
+*/
+template <typename CT>
+struct sjoberg_intersection_spherical_02
+{
+ // TODO: if it will be used as standalone formula
+ // support segments on equator and endpoints on poles
+
+ static inline bool apply(CT const& lon1, CT const& lat1, CT const& lon_a2, CT const& lat_a2,
+ CT const& lon2, CT const& lat2, CT const& lon_b2, CT const& lat_b2,
+ CT & lon, CT & lat)
+ {
+ CT tan_lat = 0;
+ bool res = apply_alt(lon1, lat1, lon_a2, lat_a2,
+ lon2, lat2, lon_b2, lat_b2,
+ lon, tan_lat);
+
+ if (res)
+ {
+ lat = atan(tan_lat);
+ }
+
+ return res;
+ }
+
+ static inline bool apply_alt(CT const& lon1, CT const& lat1, CT const& lon_a2, CT const& lat_a2,
+ CT const& lon2, CT const& lat2, CT const& lon_b2, CT const& lat_b2,
+ CT & lon, CT & tan_lat)
+ {
+ CT const cos_lon1 = cos(lon1);
+ CT const sin_lon1 = sin(lon1);
+ CT const cos_lon2 = cos(lon2);
+ CT const sin_lon2 = sin(lon2);
+ CT const sin_lat1 = sin(lat1);
+ CT const sin_lat2 = sin(lat2);
+ CT const cos_lat1 = cos(lat1);
+ CT const cos_lat2 = cos(lat2);
+
+ CT const tan_lat_a2 = tan(lat_a2);
+ CT const tan_lat_b2 = tan(lat_b2);
+
+ return apply(lon1, lon_a2, lon2, lon_b2,
+ sin_lon1, cos_lon1, sin_lat1, cos_lat1,
+ sin_lon2, cos_lon2, sin_lat2, cos_lat2,
+ tan_lat_a2, tan_lat_b2,
+ lon, tan_lat);
+ }
+
+private:
+ static inline bool apply(CT const& lon1, CT const& lon_a2, CT const& lon2, CT const& lon_b2,
+ CT const& sin_lon1, CT const& cos_lon1, CT const& sin_lat1, CT const& cos_lat1,
+ CT const& sin_lon2, CT const& cos_lon2, CT const& sin_lat2, CT const& cos_lat2,
+ CT const& tan_lat_a2, CT const& tan_lat_b2,
+ CT & lon, CT & tan_lat)
+ {
+ // NOTE:
+ // cos_lat_ = 0 <=> segment on equator
+ // tan_alpha_ = 0 <=> segment vertical
+
+ CT const tan_lat1 = sin_lat1 / cos_lat1; //tan(lat1);
+ CT const tan_lat2 = sin_lat2 / cos_lat2; //tan(lat2);
+
+ CT const dlon1 = lon_a2 - lon1;
+ CT const sin_dlon1 = sin(dlon1);
+ CT const dlon2 = lon_b2 - lon2;
+ CT const sin_dlon2 = sin(dlon2);
+
+ CT const c0 = 0;
+ bool const is_vertical1 = math::equals(sin_dlon1, c0);
+ bool const is_vertical2 = math::equals(sin_dlon2, c0);
+
+ CT tan_alpha1 = 0;
+ CT tan_alpha2 = 0;
+
+ if (is_vertical1 && is_vertical2)
+ {
+ // circles intersect at one of the poles or are collinear
+ return false;
+ }
+ else if (is_vertical1)
+ {
+ CT const cos_dlon2 = cos(dlon2);
+ CT const tan_alpha2_x = cos_lat2 * tan_lat_b2 - sin_lat2 * cos_dlon2;
+ tan_alpha2 = sin_dlon2 / tan_alpha2_x;
+
+ lon = lon1;
+ }
+ else if (is_vertical2)
+ {
+ CT const cos_dlon1 = cos(dlon1);
+ CT const tan_alpha1_x = cos_lat1 * tan_lat_a2 - sin_lat1 * cos_dlon1;
+ tan_alpha1 = sin_dlon1 / tan_alpha1_x;
+
+ lon = lon2;
+ }
+ else
+ {
+ CT const cos_dlon1 = cos(dlon1);
+ CT const cos_dlon2 = cos(dlon2);
+
+ CT const tan_alpha1_x = cos_lat1 * tan_lat_a2 - sin_lat1 * cos_dlon1;
+ CT const tan_alpha2_x = cos_lat2 * tan_lat_b2 - sin_lat2 * cos_dlon2;
+ tan_alpha1 = sin_dlon1 / tan_alpha1_x;
+ tan_alpha2 = sin_dlon2 / tan_alpha2_x;
+
+ CT const T1 = tan_alpha1 * cos_lat1;
+ CT const T2 = tan_alpha2 * cos_lat2;
+ CT const T1T2 = T1*T2;
+ CT const tan_lon_y = T1 * sin_lon2 - T2 * sin_lon1 + T1T2 * (tan_lat1 * cos_lon1 - tan_lat2 * cos_lon2);
+ CT const tan_lon_x = T1 * cos_lon2 - T2 * cos_lon1 - T1T2 * (tan_lat1 * sin_lon1 - tan_lat2 * sin_lon2);
+
+ lon = atan2(tan_lon_y, tan_lon_x);
+ }
+
+ // choose closer result
+ CT const pi = math::pi<CT>();
+ CT const lon_2 = lon > c0 ? lon - pi : lon + pi;
+ CT const lon_dist1 = (std::max)((std::min)(math::longitude_difference<radian>(lon1, lon),
+ math::longitude_difference<radian>(lon_a2, lon)),
+ (std::min)(math::longitude_difference<radian>(lon2, lon),
+ math::longitude_difference<radian>(lon_b2, lon)));
+ CT const lon_dist2 = (std::max)((std::min)(math::longitude_difference<radian>(lon1, lon_2),
+ math::longitude_difference<radian>(lon_a2, lon_2)),
+ (std::min)(math::longitude_difference<radian>(lon2, lon_2),
+ math::longitude_difference<radian>(lon_b2, lon_2)));
+ if (lon_dist2 < lon_dist1)
+ {
+ lon = lon_2;
+ }
+
+ CT const sin_lon = sin(lon);
+ CT const cos_lon = cos(lon);
+
+ if (math::abs(tan_alpha1) >= math::abs(tan_alpha2)) // pick less vertical segment
+ {
+ CT const sin_dlon_1 = sin_lon * cos_lon1 - cos_lon * sin_lon1;
+ CT const cos_dlon_1 = cos_lon * cos_lon1 + sin_lon * sin_lon1;
+ CT const lat_y_1 = sin_dlon_1 + tan_alpha1 * sin_lat1 * cos_dlon_1;
+ CT const lat_x_1 = tan_alpha1 * cos_lat1;
+ tan_lat = lat_y_1 / lat_x_1;
+ }
+ else
+ {
+ CT const sin_dlon_2 = sin_lon * cos_lon2 - cos_lon * sin_lon2;
+ CT const cos_dlon_2 = cos_lon * cos_lon2 + sin_lon * sin_lon2;
+ CT const lat_y_2 = sin_dlon_2 + tan_alpha2 * sin_lat2 * cos_dlon_2;
+ CT const lat_x_2 = tan_alpha2 * cos_lat2;
+ tan_lat = lat_y_2 / lat_x_2;
+ }
+
+ return true;
+ }
+};
+
+
+/*! Approximation of dLambda_j [Sjoberg07], expanded into taylor series in e^2
+ Maxima script:
+ dLI_j(c_j, sinB_j, sinB) := integrate(1 / (sqrt(1 - c_j ^ 2 - x ^ 2)*(1 + sqrt(1 - e2*(1 - x ^ 2)))), x, sinB_j, sinB);
+ dL_j(c_j, B_j, B) := -e2 * c_j * dLI_j(c_j, B_j, B);
+ S: taylor(dLI_j(c_j, sinB_j, sinB), e2, 0, 3);
+ assume(c_j < 1);
+ assume(c_j > 0);
+ L1: factor(integrate(sqrt(-x ^ 2 - c_j ^ 2 + 1) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L2: factor(integrate(((x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L3: factor(integrate(((x ^ 4 - 2 * x ^ 2 + 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+ L4: factor(integrate(((x ^ 6 - 3 * x ^ 4 + 3 * x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
+
+\see See
+ - [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007
+ http://link.springer.com/article/10.1007/s00190-007-0204-7
+*/
+template <unsigned int Order, typename CT>
+inline CT sjoberg_d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
+ CT const& Cj, CT const& sqrt_1_Cj_sqr,
+ CT const& e_sqr)
+{
+ using math::detail::bounded;
+
+ if (Order == 0)
+ {
+ return 0;
+ }
+
+ CT const c1 = 1;
+ CT const c2 = 2;
+
+ CT const asin_B = asin(bounded(sin_beta / sqrt_1_Cj_sqr, -c1, c1));
+ CT const asin_Bj = asin(sin_betaj / sqrt_1_Cj_sqr);
+ CT const L0 = (asin_B - asin_Bj) / c2;
+
+ if (Order == 1)
+ {
+ return -Cj * e_sqr * L0;
+ }
+
+ CT const c0 = 0;
+ CT const c16 = 16;
+
+ CT const X = sin_beta;
+ CT const Xj = sin_betaj;
+ CT const X_sqr = math::sqr(X);
+ CT const Xj_sqr = math::sqr(Xj);
+ CT const Cj_sqr = math::sqr(Cj);
+ CT const Cj_sqr_plus_one = Cj_sqr + c1;
+ CT const one_minus_Cj_sqr = c1 - Cj_sqr;
+ CT const sqrt_Y = math::sqrt(bounded(-X_sqr + one_minus_Cj_sqr, c0));
+ CT const sqrt_Yj = math::sqrt(-Xj_sqr + one_minus_Cj_sqr);
+ CT const L1 = (Cj_sqr_plus_one * (asin_B - asin_Bj) + X * sqrt_Y - Xj * sqrt_Yj) / c16;
+
+ if (Order == 2)
+ {
+ return -Cj * e_sqr * (L0 + e_sqr * L1);
+ }
+
+ CT const c3 = 3;
+ CT const c5 = 5;
+ CT const c128 = 128;
+
+ CT const E = Cj_sqr * (c3 * Cj_sqr + c2) + c3;
+ CT const F = X * (-c2 * X_sqr + c3 * Cj_sqr + c5);
+ CT const Fj = Xj * (-c2 * Xj_sqr + c3 * Cj_sqr + c5);
+ CT const L2 = (E * (asin_B - asin_Bj) + F * sqrt_Y - Fj * sqrt_Yj) / c128;
+
+ if (Order == 3)
+ {
+ return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * L2));
+ }
+
+ CT const c8 = 8;
+ CT const c9 = 9;
+ CT const c10 = 10;
+ CT const c15 = 15;
+ CT const c24 = 24;
+ CT const c26 = 26;
+ CT const c33 = 33;
+ CT const c6144 = 6144;
+
+ CT const G = Cj_sqr * (Cj_sqr * (Cj_sqr * c15 + c9) + c9) + c15;
+ CT const H = -c10 * Cj_sqr - c26;
+ CT const I = Cj_sqr * (Cj_sqr * c15 + c24) + c33;
+ CT const J = X_sqr * (X * (c8 * X_sqr + H)) + X * I;
+ CT const Jj = Xj_sqr * (Xj * (c8 * Xj_sqr + H)) + Xj * I;
+ CT const L3 = (G * (asin_B - asin_Bj) + J * sqrt_Y - Jj * sqrt_Yj) / c6144;
+
+ // Order 4 and higher
+ return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * (L2 + e_sqr * L3)));
+}
+
+/*!
+\brief The representation of geodesic as proposed by Sjoberg.
+\see See
+ - [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007
+ http://link.springer.com/article/10.1007/s00190-007-0204-7
+ - [Sjoberg12] Lars E. Sjoberg, Solutions to the ellipsoidal Clairaut constant
+ and the inverse geodetic problem by numerical integration, 2012
+ https://www.degruyter.com/view/j/jogs.2012.2.issue-3/v10156-011-0037-4/v10156-011-0037-4.xml
+*/
+template <typename CT, unsigned int Order>
+class sjoberg_geodesic
+{
+ sjoberg_geodesic() {}
+
+ static int sign_C(CT const& alphaj)
+ {
+ CT const c0 = 0;
+ CT const c2 = 2;
+ CT const pi = math::pi<CT>();
+ CT const pi_half = pi / c2;
+
+ return (pi_half < alphaj && alphaj < pi) || (-pi_half < alphaj && alphaj < c0) ? -1 : 1;
+ }
+
+public:
+ sjoberg_geodesic(CT const& lon, CT const& lat, CT const& alpha, CT const& f)
+ : lonj(lon)
+ , latj(lat)
+ , alphaj(alpha)
+ {
+ CT const c0 = 0;
+ CT const c1 = 1;
+ CT const c2 = 2;
+ //CT const pi = math::pi<CT>();
+ //CT const pi_half = pi / c2;
+
+ one_minus_f = c1 - f;
+ e_sqr = f * (c2 - f);
+
+ tan_latj = tan(lat);
+ tan_betaj = one_minus_f * tan_latj;
+ betaj = atan(tan_betaj);
+ sin_betaj = sin(betaj);
+
+ cos_betaj = cos(betaj);
+ sin_alphaj = sin(alphaj);
+ // Clairaut constant (lower-case in the paper)
+ Cj = sign_C(alphaj) * cos_betaj * sin_alphaj;
+ Cj_sqr = math::sqr(Cj);
+ sqrt_1_Cj_sqr = math::sqrt(c1 - Cj_sqr);
+
+ sign_lon_diff = alphaj >= 0 ? 1 : -1; // || alphaj == -pi ?
+ //sign_lon_diff = 1;
+
+ is_on_equator = math::equals(sqrt_1_Cj_sqr, c0);
+ is_Cj_zero = math::equals(Cj, c0);
+
+ t0j = c0;
+ asin_tj_t0j = c0;
+
+ if (! is_Cj_zero)
+ {
+ t0j = sqrt_1_Cj_sqr / Cj;
+ }
+
+ if (! is_on_equator)
+ {
+ //asin_tj_t0j = asin(tan_betaj / t0j);
+ asin_tj_t0j = asin(tan_betaj * Cj / sqrt_1_Cj_sqr);
+ }
+ }
+
+ struct vertex_data
+ {
+ //CT beta0j;
+ CT sin_beta0j;
+ CT dL0j;
+ CT lon0j;
+ };
+
+ vertex_data get_vertex_data() const
+ {
+ CT const c2 = 2;
+ CT const pi = math::pi<CT>();
+ CT const pi_half = pi / c2;
+
+ vertex_data res;
+
+ if (! is_Cj_zero)
+ {
+ //res.beta0j = atan(t0j);
+ //res.sin_beta0j = sin(res.beta0j);
+ res.sin_beta0j = math::sign(t0j) * sqrt_1_Cj_sqr;
+ res.dL0j = d_lambda(res.sin_beta0j);
+ res.lon0j = lonj + sign_lon_diff * (pi_half - asin_tj_t0j + res.dL0j);
+ }
+ else
+ {
+ //res.beta0j = pi_half;
+ //res.sin_beta0j = betaj >= 0 ? 1 : -1;
+ res.sin_beta0j = 1;
+ res.dL0j = 0;
+ res.lon0j = lonj;
+ }
+
+ return res;
+ }
+
+ bool is_sin_beta_ok(CT const& sin_beta) const
+ {
+ CT const c1 = 1;
+ return math::abs(sin_beta / sqrt_1_Cj_sqr) <= c1;
+ }
+
+ bool k_diff(CT const& sin_beta,
+ CT & delta_k) const
+ {
+ if (is_Cj_zero)
+ {
+ delta_k = 0;
+ return true;
+ }
+
+ // beta out of bounds and not close
+ if (! (is_sin_beta_ok(sin_beta)
+ || math::equals(math::abs(sin_beta), sqrt_1_Cj_sqr)) )
+ {
+ return false;
+ }
+
+ // NOTE: beta may be slightly out of bounds here but d_lambda handles that
+ CT const dLj = d_lambda(sin_beta);
+ delta_k = sign_lon_diff * (/*asin_t_t0j*/ - asin_tj_t0j + dLj);
+
+ return true;
+ }
+
+ bool lon_diff(CT const& sin_beta, CT const& t,
+ CT & delta_lon) const
+ {
+ using math::detail::bounded;
+ CT const c1 = 1;
+
+ if (is_Cj_zero)
+ {
+ delta_lon = 0;
+ return true;
+ }
+
+ CT delta_k = 0;
+ if (! k_diff(sin_beta, delta_k))
+ {
+ return false;
+ }
+
+ CT const t_t0j = t / t0j;
+ // NOTE: t may be slightly out of bounds here
+ CT const asin_t_t0j = asin(bounded(t_t0j, -c1, c1));
+ delta_lon = sign_lon_diff * asin_t_t0j + delta_k;
+
+ return true;
+ }
+
+ bool k_diffs(CT const& sin_beta, vertex_data const& vd,
+ CT & delta_k_before, CT & delta_k_behind,
+ bool check_sin_beta = true) const
+ {
+ CT const pi = math::pi<CT>();
+
+ if (is_Cj_zero)
+ {
+ delta_k_before = 0;
+ delta_k_behind = sign_lon_diff * pi;
+ return true;
+ }
+
+ // beta out of bounds and not close
+ if (check_sin_beta
+ && ! (is_sin_beta_ok(sin_beta)
+ || math::equals(math::abs(sin_beta), sqrt_1_Cj_sqr)) )
+ {
+ return false;
+ }
+
+ // NOTE: beta may be slightly out of bounds here but d_lambda handles that
+ CT const dLj = d_lambda(sin_beta);
+ delta_k_before = sign_lon_diff * (/*asin_t_t0j*/ - asin_tj_t0j + dLj);
+
+ // This version require no additional dLj calculation
+ delta_k_behind = sign_lon_diff * (pi /*- asin_t_t0j*/ - asin_tj_t0j + vd.dL0j + (vd.dL0j - dLj));
+
+ // [Sjoberg12]
+ //CT const dL101 = d_lambda(sin_betaj, vd.sin_beta0j);
+ // WARNING: the following call might not work if beta was OoB because only the second argument is bounded
+ //CT const dL_01 = d_lambda(sin_beta, vd.sin_beta0j);
+ //delta_k_behind = sign_lon_diff * (pi /*- asin_t_t0j*/ - asin_tj_t0j + dL101 + dL_01);
+
+ return true;
+ }
+
+ bool lon_diffs(CT const& sin_beta, CT const& t, vertex_data const& vd,
+ CT & delta_lon_before, CT & delta_lon_behind) const
+ {
+ using math::detail::bounded;
+ CT const c1 = 1;
+ CT const pi = math::pi<CT>();
+
+ if (is_Cj_zero)
+ {
+ delta_lon_before = 0;
+ delta_lon_behind = sign_lon_diff * pi;
+ return true;
+ }
+
+ CT delta_k_before = 0, delta_k_behind = 0;
+ if (! k_diffs(sin_beta, vd, delta_k_before, delta_k_behind))
+ {
+ return false;
+ }
+
+ CT const t_t0j = t / t0j;
+ // NOTE: t may be slightly out of bounds here
+ CT const asin_t_t0j = asin(bounded(t_t0j, -c1, c1));
+ CT const sign_asin_t_t0j = sign_lon_diff * asin_t_t0j;
+ delta_lon_before = sign_asin_t_t0j + delta_k_before;
+ delta_lon_behind = -sign_asin_t_t0j + delta_k_behind;
+
+ return true;
+ }
+
+ bool lon(CT const& sin_beta, CT const& t, vertex_data const& vd,
+ CT & lon_before, CT & lon_behind) const
+ {
+ using math::detail::bounded;
+ CT const c1 = 1;
+ CT const pi = math::pi<CT>();
+
+ if (is_Cj_zero)
+ {
+ lon_before = lonj;
+ lon_behind = lonj + sign_lon_diff * pi;
+ return true;
+ }
+
+ if (! (is_sin_beta_ok(sin_beta)
+ || math::equals(math::abs(sin_beta), sqrt_1_Cj_sqr)) )
+ {
+ return false;
+ }
+
+ CT const t_t0j = t / t0j;
+ CT const asin_t_t0j = asin(bounded(t_t0j, -c1, c1));
+ CT const dLj = d_lambda(sin_beta);
+ lon_before = lonj + sign_lon_diff * (asin_t_t0j - asin_tj_t0j + dLj);
+ lon_behind = vd.lon0j + (vd.lon0j - lon_before);
+
+ return true;
+ }
+
+
+ CT lon(CT const& delta_lon) const
+ {
+ return lonj + delta_lon;
+ }
+
+ CT lat(CT const& t) const
+ {
+ // t = tan(beta) = (1-f)tan(lat)
+ return atan(t / one_minus_f);
+ }
+
+ void vertex(CT & lon, CT & lat) const
+ {
+ lon = get_vertex_data().lon0j;
+ if (! is_Cj_zero)
+ {
+ lat = sjoberg_geodesic::lat(t0j);
+ }
+ else
+ {
+ CT const c2 = 2;
+ lat = math::pi<CT>() / c2;
+ }
+ }
+
+ CT lon_of_equator_intersection() const
+ {
+ CT const c0 = 0;
+ CT const dLj = d_lambda(c0);
+ CT const asin_tj_t0j = asin(Cj * tan_betaj / sqrt_1_Cj_sqr);
+ return lonj - asin_tj_t0j + dLj;
+ }
+
+ CT d_lambda(CT const& sin_beta) const
+ {
+ return sjoberg_d_lambda_e_sqr<Order>(sin_betaj, sin_beta, Cj, sqrt_1_Cj_sqr, e_sqr);
+ }
+
+ // [Sjoberg12]
+ /*CT d_lambda(CT const& sin_beta1, CT const& sin_beta2) const
+ {
+ return sjoberg_d_lambda_e_sqr<Order>(sin_beta1, sin_beta2, Cj, sqrt_1_Cj_sqr, e_sqr);
+ }*/
+
+ CT lonj;
+ CT latj;
+ CT alphaj;
+
+ CT one_minus_f;
+ CT e_sqr;
+
+ CT tan_latj;
+ CT tan_betaj;
+ CT betaj;
+ CT sin_betaj;
+ CT cos_betaj;
+ CT sin_alphaj;
+ CT Cj;
+ CT Cj_sqr;
+ CT sqrt_1_Cj_sqr;
+
+ int sign_lon_diff;
+
+ bool is_on_equator;
+ bool is_Cj_zero;
+
+ CT t0j;
+ CT asin_tj_t0j;
+};
+
+
+/*!
\brief The intersection of two geodesics as proposed by Sjoberg.
-\author See
+\see See
- [Sjoberg02] Lars E. Sjoberg, Intersections on the sphere and ellipsoid, 2002
http://link.springer.com/article/10.1007/s00190-001-0230-9
- [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007
http://link.springer.com/article/10.1007/s00190-007-0204-7
+ - [Sjoberg12] Lars E. Sjoberg, Solutions to the ellipsoidal Clairaut constant
+ and the inverse geodetic problem by numerical integration, 2012
+ https://www.degruyter.com/view/j/jogs.2012.2.issue-3/v10156-011-0037-4/v10156-011-0037-4.xml
*/
template
<
@@ -42,9 +629,14 @@ template
>
class sjoberg_intersection
{
+ typedef sjoberg_geodesic<CT, Order> geodesic_type;
typedef Inverse<CT, false, true, false, false, false> inverse_type;
typedef typename inverse_type::result_type inverse_result;
+ static bool const enable_02 = true;
+ static int const max_iterations_02 = 10;
+ static int const max_iterations_07 = 20;
+
public:
template <typename T1, typename T2, typename Spheroid>
static inline bool apply(T1 const& lona1, T1 const& lata1,
@@ -63,320 +655,562 @@ public:
CT const lon_b2 = lonb2;
CT const lat_b2 = latb2;
- CT const alpha1 = inverse_type::apply(lon_a1, lat_a1, lon_a2, lat_a2, spheroid).azimuth;
- CT const alpha2 = inverse_type::apply(lon_b1, lat_b1, lon_b2, lat_b2, spheroid).azimuth;
+ inverse_result const res1 = inverse_type::apply(lon_a1, lat_a1, lon_a2, lat_a2, spheroid);
+ inverse_result const res2 = inverse_type::apply(lon_b1, lat_b1, lon_b2, lat_b2, spheroid);
- return apply(lon_a1, lat_a1, alpha1, lon_b1, lat_b1, alpha2, lon, lat, spheroid);
+ return apply(lon_a1, lat_a1, lon_a2, lat_a2, res1.azimuth,
+ lon_b1, lat_b1, lon_b2, lat_b2, res2.azimuth,
+ lon, lat, spheroid);
}
-
+
+ // TODO: Currently may not work correctly if one of the endpoints is the pole
template <typename Spheroid>
- static inline bool apply(CT const& lon1, CT const& lat1, CT const& alpha1,
- CT const& lon2, CT const& lat2, CT const& alpha2,
+ static inline bool apply(CT const& lon_a1, CT const& lat_a1, CT const& lon_a2, CT const& lat_a2, CT const& alpha_a1,
+ CT const& lon_b1, CT const& lat_b1, CT const& lon_b2, CT const& lat_b2, CT const& alpha_b1,
CT & lon, CT & lat,
Spheroid const& spheroid)
{
// coordinates in radians
- // TODO - handle special cases like degenerated segments, equator, poles, etc.
-
CT const c0 = 0;
CT const c1 = 1;
- CT const c2 = 2;
- CT const pi = math::pi<CT>();
- CT const pi_half = pi / c2;
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const one_minus_f = c1 - f;
- CT const e_sqr = f * (c2 - f);
-
- CT const sin_alpha1 = sin(alpha1);
- CT const sin_alpha2 = sin(alpha2);
-
- CT const tan_beta1 = one_minus_f * tan(lat1);
- CT const tan_beta2 = one_minus_f * tan(lat2);
- CT const beta1 = atan(tan_beta1);
- CT const beta2 = atan(tan_beta2);
- CT const cos_beta1 = cos(beta1);
- CT const cos_beta2 = cos(beta2);
- CT const sin_beta1 = sin(beta1);
- CT const sin_beta2 = sin(beta2);
-
- // Clairaut constants (lower-case in the paper)
- int const sign_C1 = math::abs(alpha1) <= pi_half ? 1 : -1;
- int const sign_C2 = math::abs(alpha2) <= pi_half ? 1 : -1;
- // Cj = 1 if on equator
- CT const C1 = sign_C1 * cos_beta1 * sin_alpha1;
- CT const C2 = sign_C2 * cos_beta2 * sin_alpha2;
-
- CT const sqrt_1_C1_sqr = math::sqrt(c1 - math::sqr(C1));
- CT const sqrt_1_C2_sqr = math::sqrt(c1 - math::sqr(C2));
-
- // handle special case: segments on the equator
- bool const on_equator1 = math::equals(sqrt_1_C1_sqr, c0);
- bool const on_equator2 = math::equals(sqrt_1_C2_sqr, c0);
- if (on_equator1 && on_equator2)
+
+ geodesic_type geod1(lon_a1, lat_a1, alpha_a1, f);
+ geodesic_type geod2(lon_b1, lat_b1, alpha_b1, f);
+
+ // Cj = 1 if on equator <=> sqrt_1_Cj_sqr = 0
+ // Cj = 0 if vertical <=> sqrt_1_Cj_sqr = 1
+
+ if (geod1.is_on_equator && geod2.is_on_equator)
{
return false;
}
- else if (on_equator1)
+ else if (geod1.is_on_equator)
{
- CT const dL2 = d_lambda_e_sqr(sin_beta2, c0, C2, sqrt_1_C2_sqr, e_sqr);
- CT const asin_t2_t02 = asin(C2 * tan_beta2 / sqrt_1_C2_sqr);
+ lon = geod2.lon_of_equator_intersection();
lat = c0;
- lon = lon2 - asin_t2_t02 + dL2;
return true;
}
- else if (on_equator2)
+ else if (geod2.is_on_equator)
{
- CT const dL1 = d_lambda_e_sqr(sin_beta1, c0, C1, sqrt_1_C1_sqr, e_sqr);
- CT const asin_t1_t01 = asin(C1 * tan_beta1 / sqrt_1_C1_sqr);
+ lon = geod1.lon_of_equator_intersection();
lat = c0;
- lon = lon1 - asin_t1_t01 + dL1;
return true;
}
- CT const t01 = sqrt_1_C1_sqr / C1;
- CT const t02 = sqrt_1_C2_sqr / C2;
+ // (lon1 - lon2) normalized to (-180, 180]
+ CT const lon1_minus_lon2 = math::longitude_distance_signed<radian>(geod2.lonj, geod1.lonj);
- CT const asin_t1_t01 = asin(tan_beta1 / t01);
- CT const asin_t2_t02 = asin(tan_beta2 / t02);
- CT const t01_t02 = t01 * t02;
- CT const t01_t02_2 = c2 * t01_t02;
- CT const sqr_t01_sqr_t02 = math::sqr(t01) + math::sqr(t02);
+ // vertical segments
+ if (geod1.is_Cj_zero && geod2.is_Cj_zero)
+ {
+ CT const pi = math::pi<CT>();
- CT t = tan_beta1;
- int t_id = 0;
+ // the geodesics are parallel, the intersection point cannot be calculated
+ if ( math::equals(lon1_minus_lon2, c0)
+ || math::equals(lon1_minus_lon2 + (lon1_minus_lon2 < c0 ? pi : -pi), c0) )
+ {
+ return false;
+ }
- // find the initial t using simplified spherical solution
- // though not entirely since the reduced latitudes and azimuths are spheroidal
- // [Sjoberg07]
- CT const k_base = lon1 - lon2 + asin_t2_t02 - asin_t1_t01;
-
+ lon = c0;
+
+ // the geodesics intersect at one of the poles
+ CT const pi_half = pi / CT(2);
+ CT const abs_lat_a1 = math::abs(lat_a1);
+ CT const abs_lat_a2 = math::abs(lat_a2);
+ if (math::equals(abs_lat_a1, abs_lat_a2))
+ {
+ lat = pi_half;
+ }
+ else
+ {
+ // pick the pole closest to one of the points of the first segment
+ CT const& closer_lat = abs_lat_a1 > abs_lat_a2 ? lat_a1 : lat_a2;
+ lat = closer_lat >= 0 ? pi_half : -pi_half;
+ }
+
+ return true;
+ }
+
+ CT lon_sph = 0;
+
+ // Starting tan(beta)
+ CT t = 0;
+
+ /*if (geod1.is_Cj_zero)
{
- CT const K = sin(k_base);
- CT const d1 = sqr_t01_sqr_t02;
- //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K));
- CT const d2 = t01_t02_2 * cos(k_base);
- CT const D1 = math::sqrt(d1 - d2);
- CT const D2 = math::sqrt(d1 + d2);
- CT const K_t01_t02 = K * t01_t02;
-
- CT const T1 = K_t01_t02 / D1;
- CT const T2 = K_t01_t02 / D2;
- CT asin_T1_t01 = 0;
- CT asin_T1_t02 = 0;
- CT asin_T2_t01 = 0;
- CT asin_T2_t02 = 0;
-
- // test 4 possible results
- CT l1 = 0, l2 = 0, dl = 0;
- bool found = check_t<0>( T1,
- lon1, asin_T1_t01 = asin(T1 / t01), asin_t1_t01,
- lon2, asin_T1_t02 = asin(T1 / t02), asin_t2_t02,
- t, l1, l2, dl, t_id)
- || check_t<1>(-T1,
- lon1, -asin_T1_t01 , asin_t1_t01,
- lon2, -asin_T1_t02 , asin_t2_t02,
- t, l1, l2, dl, t_id)
- || check_t<2>( T2,
- lon1, asin_T2_t01 = asin(T2 / t01), asin_t1_t01,
- lon2, asin_T2_t02 = asin(T2 / t02), asin_t2_t02,
- t, l1, l2, dl, t_id)
- || check_t<3>(-T2,
- lon1, -asin_T2_t01 , asin_t1_t01,
- lon2, -asin_T2_t02 , asin_t2_t02,
- t, l1, l2, dl, t_id);
-
- boost::ignore_unused(found);
+ CT const k_base = lon1_minus_lon2 + geod2.sign_lon_diff * geod2.asin_tj_t0j;
+ t = sin(k_base) * geod2.t0j;
+ lon_sph = vertical_intersection_longitude(geod1.lonj, lon_b1, lon_b2);
}
+ else if (geod2.is_Cj_zero)
+ {
+ CT const k_base = lon1_minus_lon2 - geod1.sign_lon_diff * geod1.asin_tj_t0j;
+ t = sin(-k_base) * geod1.t0j;
+ lon_sph = vertical_intersection_longitude(geod2.lonj, lon_a1, lon_a2);
+ }
+ else*/
+ {
+ // TODO: Consider using betas instead of latitudes.
+ // Some function calls might be saved this way.
+ CT tan_lat_sph = 0;
+ sjoberg_intersection_spherical_02<CT>::apply_alt(lon_a1, lat_a1, lon_a2, lat_a2,
+ lon_b1, lat_b1, lon_b2, lat_b2,
+ lon_sph, tan_lat_sph);
+ t = one_minus_f * tan_lat_sph; // tan(beta)
+ }
+
+ // TODO: no need to calculate atan here if reduced latitudes were used
+ // instead of latitudes above, in sjoberg_intersection_spherical_02
+ CT const beta = atan(t);
+
+ if (enable_02 && newton_method(geod1, geod2, beta, t, lon1_minus_lon2, lon, lat))
+ {
+ return true;
+ }
+
+ return converge_07(geod1, geod2, beta, t, lon1_minus_lon2, lon_sph, lon, lat);
+ }
+
+private:
+ static inline bool newton_method(geodesic_type const& geod1, geodesic_type const& geod2, // in
+ CT beta, CT t, CT const& lon1_minus_lon2, // in
+ CT & lon, CT & lat) // out
+ {
+ CT const c0 = 0;
+ CT const c1 = 1;
+
+ CT const e_sqr = geod1.e_sqr;
- // [Sjoberg07]
- //int const d2_sign = t_id < 2 ? -1 : 1;
- int const t_sign = (t_id % 2) ? -1 : 1;
- // [Sjoberg02]
- CT const C1_sqr = math::sqr(C1);
- CT const C2_sqr = math::sqr(C2);
-
- CT beta = atan(t);
- CT dL1 = 0, dL2 = 0;
- CT asin_t_t01 = 0;
- CT asin_t_t02 = 0;
+ CT lon1_diff = 0;
+ CT lon2_diff = 0;
- for (int i = 0; i < 10; ++i)
+ CT abs_dbeta_last = 0;
+
+ // [Sjoberg02] converges faster than solution in [Sjoberg07]
+ // Newton-Raphson method
+ for (int i = 0; i < max_iterations_02; ++i)
{
CT const sin_beta = sin(beta);
-
- // integrals approximation
- dL1 = d_lambda_e_sqr(sin_beta1, sin_beta, C1, sqrt_1_C1_sqr, e_sqr);
- dL2 = d_lambda_e_sqr(sin_beta2, sin_beta, C2, sqrt_1_C2_sqr, e_sqr);
-
- // [Sjoberg07]
- /*CT const k = k_base + dL1 - dL2;
- CT const K = sin(k);
- CT const d1 = sqr_t01_sqr_t02;
- //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K));
- CT const d2 = t01_t02_2 * cos(k);
- CT const D = math::sqrt(d1 + d2_sign * d2);
- CT const t_new = t_sign * K * t01_t02 / D;
- CT const dt = math::abs(t_new - t);
- t = t_new;
- CT const new_beta = atan(t);
- CT const dbeta = math::abs(new_beta - beta);
- beta = new_beta;*/
-
- // [Sjoberg02] - it converges faster
- // Newton–Raphson method
- asin_t_t01 = asin(t / t01);
- asin_t_t02 = asin(t / t02);
- CT const R1 = asin_t_t01 + dL1;
- CT const R2 = asin_t_t02 + dL2;
CT const cos_beta = cos(beta);
CT const cos_beta_sqr = math::sqr(cos_beta);
CT const G = c1 - e_sqr * cos_beta_sqr;
- CT const f1 = C1 / cos_beta * math::sqrt(G / (cos_beta_sqr - C1_sqr));
- CT const f2 = C2 / cos_beta * math::sqrt(G / (cos_beta_sqr - C2_sqr));
- CT const abs_f1 = math::abs(f1);
- CT const abs_f2 = math::abs(f2);
- CT const dbeta = t_sign * (k_base - R2 + R1) / (abs_f1 + abs_f2);
-
- if (math::equals(dbeta, CT(0)))
+
+ CT f1 = 0;
+ CT f2 = 0;
+
+ if (!geod1.is_Cj_zero)
+ {
+ bool is_beta_ok = geod1.lon_diff(sin_beta, t, lon1_diff);
+
+ if (is_beta_ok)
+ {
+ CT const H = cos_beta_sqr - geod1.Cj_sqr;
+ f1 = geod1.Cj / cos_beta * math::sqrt(G / H);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (!geod2.is_Cj_zero)
+ {
+ bool is_beta_ok = geod2.lon_diff(sin_beta, t, lon2_diff);
+
+ if (is_beta_ok)
+ {
+ CT const H = cos_beta_sqr - geod2.Cj_sqr;
+ f2 = geod2.Cj / cos_beta * math::sqrt(G / H);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // NOTE: Things may go wrong if the IP is near the vertex
+ // 1. May converge into the wrong direction (from the other way around).
+ // This happens when the starting point is on the other side than the vertex
+ // 2. During converging may "jump" into the other side of the vertex.
+ // In this case sin_beta/sqrt_1_Cj_sqr and t/t0j is not in [-1, 1]
+ // 3. f1-f2 may be 0 which means that the intermediate point is on the vertex
+ // In this case it's not possible to check if this is the correct result
+
+ CT const dbeta_denom = f1 - f2;
+ //CT const dbeta_denom = math::abs(f1) + math::abs(f2);
+
+ if (math::equals(dbeta_denom, c0))
+ {
+ return false;
+ }
+
+ // The sign of dbeta is changed WRT [Sjoberg02]
+ CT const dbeta = (lon1_minus_lon2 + lon1_diff - lon2_diff) / dbeta_denom;
+
+ CT const abs_dbeta = math::abs(dbeta);
+ if (i > 0 && abs_dbeta > abs_dbeta_last)
{
+ // The algorithm is not converging
+ // The intersection may be on the other side of the vertex
+ return false;
+ }
+ abs_dbeta_last = abs_dbeta;
+
+ if (math::equals(dbeta, c0))
+ {
+ // Result found
break;
}
+ // Because the sign of dbeta is changed WRT [Sjoberg02] dbeta is subtracted here
beta = beta - dbeta;
+
t = tan(beta);
}
-
- // t = tan(beta) = (1-f)tan(lat)
- lat = atan(t / one_minus_f);
- CT const l1 = lon1 + asin_t_t01 - asin_t1_t01 + dL1;
- //CT const l2 = lon2 + asin_t_t02 - asin_t2_t02 + dL2;
- lon = l1;
+ lat = geod1.lat(t);
+ // NOTE: if Cj is 0 then the result is lonj or lonj+180
+ lon = ! geod1.is_Cj_zero
+ ? geod1.lon(lon1_diff)
+ : geod2.lon(lon2_diff);
return true;
}
-private:
- /*! Approximation of dLambda_j [Sjoberg07], expanded into taylor series in e^2
- Maxima script:
- dLI_j(c_j, sinB_j, sinB) := integrate(1 / (sqrt(1 - c_j ^ 2 - x ^ 2)*(1 + sqrt(1 - e2*(1 - x ^ 2)))), x, sinB_j, sinB);
- dL_j(c_j, B_j, B) := -e2 * c_j * dLI_j(c_j, B_j, B);
- S: taylor(dLI_j(c_j, sinB_j, sinB), e2, 0, 3);
- assume(c_j < 1);
- assume(c_j > 0);
- L1: factor(integrate(sqrt(-x ^ 2 - c_j ^ 2 + 1) / (x ^ 2 + c_j ^ 2 - 1), x));
- L2: factor(integrate(((x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
- L3: factor(integrate(((x ^ 4 - 2 * x ^ 2 + 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
- L4: factor(integrate(((x ^ 6 - 3 * x ^ 4 + 3 * x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x));
- */
- static inline CT d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
- CT const& Cj, CT const& sqrt_1_Cj_sqr,
- CT const& e_sqr)
- {
- if (Order == 0)
- {
- return 0;
- }
+ struct geodesics_type
+ {
+ geodesics_type(geodesic_type const& g1, geodesic_type const& g2)
+ : geod1(g1)
+ , geod2(g2)
+ , vertex1(geod1.get_vertex_data())
+ , vertex2(geod2.get_vertex_data())
+ {}
- CT const c2 = 2;
-
- CT const asin_B = asin(sin_beta / sqrt_1_Cj_sqr);
- CT const asin_Bj = asin(sin_betaj / sqrt_1_Cj_sqr);
- CT const L0 = (asin_B - asin_Bj) / c2;
+ geodesic_type const& geod1;
+ geodesic_type const& geod2;
+ typename geodesic_type::vertex_data vertex1;
+ typename geodesic_type::vertex_data vertex2;
+ };
- if (Order == 1)
+ struct converge_07_result
+ {
+ converge_07_result()
+ : lon1(0), lon2(0), k1_diff(0), k2_diff(0), t1(0), t2(0)
+ {}
+
+ CT lon1, lon2;
+ CT k1_diff, k2_diff;
+ CT t1, t2;
+ };
+
+ static inline bool converge_07(geodesic_type const& geod1, geodesic_type const& geod2,
+ CT beta, CT t,
+ CT const& lon1_minus_lon2, CT const& lon_sph,
+ CT & lon, CT & lat)
+ {
+ //CT const c0 = 0;
+ //CT const c1 = 1;
+ //CT const c2 = 2;
+ //CT const pi = math::pi<CT>();
+
+ geodesics_type geodesics(geod1, geod2);
+ converge_07_result result;
+
+ // calculate first pair of longitudes
+ if (!converge_07_step_one(CT(sin(beta)), t, lon1_minus_lon2, geodesics, lon_sph, result, false))
{
- return -Cj * e_sqr * L0;
+ return false;
}
- CT const c1 = 1;
- CT const c16 = 16;
+ int t_direction = 0;
- CT const X = sin_beta;
- CT const Xj = sin_betaj;
- CT const Cj_sqr = math::sqr(Cj);
- CT const Cj_sqr_plus_one = Cj_sqr + c1;
- CT const one_minus_Cj_sqr = c1 - Cj_sqr;
- CT const sqrt_Y = math::sqrt(-math::sqr(X) + one_minus_Cj_sqr);
- CT const sqrt_Yj = math::sqrt(-math::sqr(Xj) + one_minus_Cj_sqr);
- CT const L1 = (Cj_sqr_plus_one * (asin_B - asin_Bj) + X * sqrt_Y - Xj * sqrt_Yj) / c16;
+ CT lon_diff_prev = math::longitude_difference<radian>(result.lon1, result.lon2);
- if (Order == 2)
+ // [Sjoberg07]
+ for (int i = 2; i < max_iterations_07; ++i)
{
- return -Cj * e_sqr * (L0 + e_sqr * L1);
+ // pick t candidates from previous result based on dir
+ CT t_cand1 = result.t1;
+ CT t_cand2 = result.t2;
+ // if direction is 0 the closer one is the first
+ if (t_direction < 0)
+ {
+ t_cand1 = (std::min)(result.t1, result.t2);
+ t_cand2 = (std::max)(result.t1, result.t2);
+ }
+ else if (t_direction > 0)
+ {
+ t_cand1 = (std::max)(result.t1, result.t2);
+ t_cand2 = (std::min)(result.t1, result.t2);
+ }
+ else
+ {
+ t_direction = t_cand1 < t_cand2 ? -1 : 1;
+ }
+
+ CT t1 = t;
+ CT beta1 = beta;
+ // check if the further calculation is needed
+ if (converge_07_update(t1, beta1, t_cand1))
+ {
+ break;
+ }
+
+ bool try_t2 = false;
+ converge_07_result result_curr;
+ if (converge_07_step_one(CT(sin(beta1)), t1, lon1_minus_lon2, geodesics, lon_sph, result_curr))
+ {
+ CT const lon_diff1 = math::longitude_difference<radian>(result_curr.lon1, result_curr.lon2);
+ if (lon_diff_prev > lon_diff1)
+ {
+ t = t1;
+ beta = beta1;
+ lon_diff_prev = lon_diff1;
+ result = result_curr;
+ }
+ else if (t_cand1 != t_cand2)
+ {
+ try_t2 = true;
+ }
+ else
+ {
+ // the result is not fully correct but it won't be more accurate
+ break;
+ }
+ }
+ // ! converge_07_step_one
+ else
+ {
+ if (t_cand1 != t_cand2)
+ {
+ try_t2 = true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ if (try_t2)
+ {
+ CT t2 = t;
+ CT beta2 = beta;
+ // check if the further calculation is needed
+ if (converge_07_update(t2, beta2, t_cand2))
+ {
+ break;
+ }
+
+ if (! converge_07_step_one(CT(sin(beta2)), t2, lon1_minus_lon2, geodesics, lon_sph, result_curr))
+ {
+ return false;
+ }
+
+ CT const lon_diff2 = math::longitude_difference<radian>(result_curr.lon1, result_curr.lon2);
+ if (lon_diff_prev > lon_diff2)
+ {
+ t_direction *= -1;
+ t = t2;
+ beta = beta2;
+ lon_diff_prev = lon_diff2;
+ result = result_curr;
+ }
+ else
+ {
+ // the result is not fully correct but it won't be more accurate
+ break;
+ }
+ }
}
- CT const c3 = 3;
- CT const c5 = 5;
- CT const c128 = 128;
+ lat = geod1.lat(t);
+ lon = ! geod1.is_Cj_zero ? result.lon1 : result.lon2;
+ math::normalize_longitude<radian>(lon);
+
+ return true;
+ }
+
+ static inline bool converge_07_update(CT & t, CT & beta, CT const& t_new)
+ {
+ CT const c0 = 0;
+
+ CT const beta_new = atan(t_new);
+ CT const dbeta = beta_new - beta;
+ beta = beta_new;
+ t = t_new;
- CT const E = Cj_sqr * (c3 * Cj_sqr + c2) + c3;
- CT const X_sqr = math::sqr(X);
- CT const Xj_sqr = math::sqr(Xj);
- CT const F = X * (-c2 * X_sqr + c3 * Cj_sqr + c5);
- CT const Fj = Xj * (-c2 * Xj_sqr + c3 * Cj_sqr + c5);
- CT const L2 = (E * (asin_B - asin_Bj) + F * sqrt_Y - Fj * sqrt_Yj) / c128;
+ return math::equals(dbeta, c0);
+ }
- if (Order == 3)
+ static inline CT const& pick_t(CT const& t1, CT const& t2, int direction)
+ {
+ return direction < 0 ? (std::min)(t1, t2) : (std::max)(t1, t2);
+ }
+
+ static inline bool converge_07_step_one(CT const& sin_beta,
+ CT const& t,
+ CT const& lon1_minus_lon2,
+ geodesics_type const& geodesics,
+ CT const& lon_sph,
+ converge_07_result & result,
+ bool check_sin_beta = true)
+ {
+ bool ok = converge_07_one_geod(sin_beta, t, geodesics.geod1, geodesics.vertex1, lon_sph,
+ result.lon1, result.k1_diff, check_sin_beta)
+ && converge_07_one_geod(sin_beta, t, geodesics.geod2, geodesics.vertex2, lon_sph,
+ result.lon2, result.k2_diff, check_sin_beta);
+
+ if (!ok)
{
- return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * L2));
+ return false;
}
- CT const c8 = 8;
- CT const c9 = 9;
- CT const c10 = 10;
- CT const c15 = 15;
- CT const c24 = 24;
- CT const c26 = 26;
- CT const c33 = 33;
- CT const c6144 = 6144;
+ CT const k = lon1_minus_lon2 + result.k1_diff - result.k2_diff;
- CT const G = Cj_sqr * (Cj_sqr * (Cj_sqr * c15 + c9) + c9) + c15;
- CT const H = -c10 * Cj_sqr - c26;
- CT const I = Cj_sqr * (Cj_sqr * c15 + c24) + c33;
- CT const J = X_sqr * (X * (c8 * X_sqr + H)) + X * I;
- CT const Jj = Xj_sqr * (Xj * (c8 * Xj_sqr + H)) + Xj * I;
- CT const L3 = (G * (asin_B - asin_Bj) + J * sqrt_Y - Jj * sqrt_Yj) / c6144;
+ // get 2 possible ts one lesser and one greater than t
+ // t1 is the closer one
+ calc_ts(t, k, geodesics.geod1, geodesics.geod2, result.t1, result.t2);
- // Order 4 and higher
- return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * (L2 + e_sqr * L3)));
+ return true;
}
- static inline CT fj(CT const& cos_beta, CT const& cos2_beta, CT const& Cj, CT const& e_sqr)
+ static inline bool converge_07_one_geod(CT const& sin_beta, CT const& t,
+ geodesic_type const& geod,
+ typename geodesic_type::vertex_data const& vertex,
+ CT const& lon_sph,
+ CT & lon, CT & k_diff,
+ bool check_sin_beta)
{
+ using math::detail::bounded;
CT const c1 = 1;
- CT const Cj_sqr = math::sqr(Cj);
- return Cj / cos_beta * math::sqrt((c1 - e_sqr * cos2_beta) / (cos2_beta - Cj_sqr));
+
+ CT k_diff_before = 0;
+ CT k_diff_behind = 0;
+
+ bool is_beta_ok = geod.k_diffs(sin_beta, vertex, k_diff_before, k_diff_behind, check_sin_beta);
+
+ if (! is_beta_ok)
+ {
+ return false;
+ }
+
+ CT const asin_t_t0j = ! geod.is_Cj_zero ? asin(bounded(t / geod.t0j, -c1, c1)) : 0;
+ CT const sign_asin_t_t0j = geod.sign_lon_diff * asin_t_t0j;
+
+ CT const lon_before = geod.lonj + sign_asin_t_t0j + k_diff_before;
+ CT const lon_behind = geod.lonj - sign_asin_t_t0j + k_diff_behind;
+
+ CT const lon_dist_before = math::longitude_distance_signed<radian>(lon_before, lon_sph);
+ CT const lon_dist_behind = math::longitude_distance_signed<radian>(lon_behind, lon_sph);
+ if (math::abs(lon_dist_before) <= math::abs(lon_dist_behind))
+ {
+ k_diff = k_diff_before;
+ lon = lon_before;
+ }
+ else
+ {
+ k_diff = k_diff_behind;
+ lon = lon_behind;
+ }
+
+ return true;
}
- template <int TId>
- static inline bool check_t(CT const& t,
- CT const& lon_a1, CT const& asin_t_t01, CT const& asin_t1_t01,
- CT const& lon_b1, CT const& asin_t_t02, CT const& asin_t2_t02,
- CT & current_t, CT & current_lon1, CT & current_lon2, CT & current_dlon,
- int & t_id)
+ static inline void calc_ts(CT const& t, CT const& k,
+ geodesic_type const& geod1, geodesic_type const& geod2,
+ CT & t1, CT& t2)
{
- CT const lon1 = lon_a1 + asin_t_t01 - asin_t1_t01;
- CT const lon2 = lon_b1 + asin_t_t02 - asin_t2_t02;
+ CT const c1 = 1;
+ CT const c2 = 2;
- // TODO - true angle difference
- CT const dlon = math::abs(lon2 - lon1);
+ CT const K = sin(k);
- bool are_equal = math::equals(dlon, CT(0));
-
- if ((TId == 0) || are_equal || dlon < current_dlon)
+ BOOST_GEOMETRY_ASSERT(!geod1.is_Cj_zero || !geod2.is_Cj_zero);
+ if (geod1.is_Cj_zero)
+ {
+ t1 = K * geod2.t0j;
+ t2 = -t1;
+ }
+ else if (geod2.is_Cj_zero)
{
- current_t = t;
- current_lon1 = lon1;
- current_lon2 = lon2;
- current_dlon = dlon;
- t_id = TId;
+ t1 = -K * geod1.t0j;
+ t2 = -t1;
}
+ else
+ {
+ CT const A = math::sqr(geod1.t0j) + math::sqr(geod2.t0j);
+ CT const B = c2 * geod1.t0j * geod2.t0j * math::sqrt(c1 - math::sqr(K));
+
+ CT const K_t01_t02 = K * geod1.t0j * geod2.t0j;
+ CT const D1 = math::sqrt(A + B);
+ CT const D2 = math::sqrt(A - B);
+ CT const t_new1 = K_t01_t02 / D1;
+ CT const t_new2 = K_t01_t02 / D2;
+ CT const t_new3 = -t_new1;
+ CT const t_new4 = -t_new2;
- return are_equal;
+ // Pick 2 nearest t_new, one greater and one lesser than current t
+ CT const abs_t_new1 = math::abs(t_new1);
+ CT const abs_t_new2 = math::abs(t_new2);
+ CT const abs_t_max = (std::max)(abs_t_new1, abs_t_new2);
+ t1 = -abs_t_max; // lesser
+ t2 = abs_t_max; // greater
+ if (t1 < t)
+ {
+ if (t_new1 < t && t_new1 > t1)
+ t1 = t_new1;
+ if (t_new2 < t && t_new2 > t1)
+ t1 = t_new2;
+ if (t_new3 < t && t_new3 > t1)
+ t1 = t_new3;
+ if (t_new4 < t && t_new4 > t1)
+ t1 = t_new4;
+ }
+ if (t2 > t)
+ {
+ if (t_new1 > t && t_new1 < t2)
+ t2 = t_new1;
+ if (t_new2 > t && t_new2 < t2)
+ t2 = t_new2;
+ if (t_new3 > t && t_new3 < t2)
+ t2 = t_new3;
+ if (t_new4 > t && t_new4 < t2)
+ t2 = t_new4;
+ }
+ }
+
+ // the first one is the closer one
+ if (math::abs(t - t2) < math::abs(t - t1))
+ {
+ std::swap(t2, t1);
+ }
+ }
+
+ static inline CT fj(CT const& cos_beta, CT const& cos2_beta, CT const& Cj, CT const& e_sqr)
+ {
+ CT const c1 = 1;
+ CT const Cj_sqr = math::sqr(Cj);
+ return Cj / cos_beta * math::sqrt((c1 - e_sqr * cos2_beta) / (cos2_beta - Cj_sqr));
}
+
+ /*static inline CT vertical_intersection_longitude(CT const& ip_lon, CT const& seg_lon1, CT const& seg_lon2)
+ {
+ CT const c0 = 0;
+ CT const lon_2 = ip_lon > c0 ? ip_lon - pi : ip_lon + pi;
+
+ return (std::min)(math::longitude_difference<radian>(ip_lon, seg_lon1),
+ math::longitude_difference<radian>(ip_lon, seg_lon2))
+ <=
+ (std::min)(math::longitude_difference<radian>(lon_2, seg_lon1),
+ math::longitude_difference<radian>(lon_2, seg_lon2))
+ ? ip_lon : lon_2;
+ }*/
};
}}} // namespace boost::geometry::formula
diff --git a/boost/geometry/formulas/spherical.hpp b/boost/geometry/formulas/spherical.hpp
index 2195bbbe10..ff24c51a88 100644
--- a/boost/geometry/formulas/spherical.hpp
+++ b/boost/geometry/formulas/spherical.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
// Copyright (c) 2016, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, 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,
@@ -27,38 +28,67 @@ namespace boost { namespace geometry {
namespace formula {
+template <typename T>
+struct result_spherical
+{
+ result_spherical()
+ : azimuth(0)
+ , reverse_azimuth(0)
+ {}
+
+ T azimuth;
+ T reverse_azimuth;
+};
+
+template <typename T>
+static inline void sph_to_cart3d(T const& lon, T const& lat, T & x, T & y, T & z)
+{
+ T const cos_lat = cos(lat);
+ x = cos_lat * cos(lon);
+ y = cos_lat * sin(lon);
+ z = sin(lat);
+}
+
template <typename Point3d, typename PointSph>
static inline Point3d sph_to_cart3d(PointSph const& point_sph)
{
typedef typename coordinate_type<Point3d>::type calc_t;
- Point3d res;
-
- calc_t lon = get_as_radian<0>(point_sph);
- calc_t lat = get_as_radian<1>(point_sph);
+ calc_t const lon = get_as_radian<0>(point_sph);
+ calc_t const lat = get_as_radian<1>(point_sph);
+ calc_t x, y, z;
+ sph_to_cart3d(lon, lat, x, y, z);
- calc_t const cos_lat = cos(lat);
- set<0>(res, cos_lat * cos(lon));
- set<1>(res, cos_lat * sin(lon));
- set<2>(res, sin(lat));
+ Point3d res;
+ set<0>(res, x);
+ set<1>(res, y);
+ set<2>(res, z);
return res;
}
+template <typename T>
+static inline void cart3d_to_sph(T const& x, T const& y, T const& z, T & lon, T & lat)
+{
+ lon = atan2(y, x);
+ lat = asin(z);
+}
+
template <typename PointSph, typename Point3d>
static inline PointSph cart3d_to_sph(Point3d const& point_3d)
{
typedef typename coordinate_type<PointSph>::type coord_t;
typedef typename coordinate_type<Point3d>::type calc_t;
- PointSph res;
-
calc_t const x = get<0>(point_3d);
calc_t const y = get<1>(point_3d);
calc_t const z = get<2>(point_3d);
+ calc_t lonr, latr;
+ cart3d_to_sph(x, y, z, lonr, latr);
- set_from_radian<0>(res, atan2(y, x));
- set_from_radian<1>(res, asin(z));
+ PointSph res;
+ set_from_radian<0>(res, lonr);
+ set_from_radian<1>(res, latr);
coord_t lon = get<0>(res);
coord_t lat = get<1>(res);
@@ -89,6 +119,104 @@ static inline int sph_side_value(Point3d1 const& norm, Point3d2 const& pt)
: -1; // d < 0
}
+template <typename CT, bool ReverseAzimuth, typename T1, typename T2>
+static inline result_spherical<CT> spherical_azimuth(T1 const& lon1,
+ T1 const& lat1,
+ T2 const& lon2,
+ T2 const& lat2)
+{
+ typedef result_spherical<CT> result_type;
+ result_type result;
+
+ // http://williams.best.vwh.net/avform.htm#Crs
+ // https://en.wikipedia.org/wiki/Great-circle_navigation
+ CT dlon = lon2 - lon1;
+
+ // 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);
+ //}
+
+ CT const cos_dlon = cos(dlon);
+ CT const sin_dlon = sin(dlon);
+ CT const cos_lat1 = cos(lat1);
+ CT const cos_lat2 = cos(lat2);
+ CT const sin_lat1 = sin(lat1);
+ CT const sin_lat2 = sin(lat2);
+
+ {
+ // "An alternative formula, not requiring the pre-computation of d"
+ // In the formula below dlon is used as "d"
+ CT const y = sin_dlon * cos_lat2;
+ CT const x = cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon;
+ result.azimuth = atan2(y, x);
+ }
+
+ if (ReverseAzimuth)
+ {
+ CT const y = sin_dlon * cos_lat1;
+ CT const x = sin_lat2 * cos_lat1 * cos_dlon - cos_lat2 * sin_lat1;
+ result.reverse_azimuth = atan2(y, x);
+ }
+
+ return result;
+}
+
+template <typename ReturnType, typename T1, typename T2>
+inline ReturnType spherical_azimuth(T1 const& lon1, T1 const& lat1,
+ T2 const& lon2, T2 const& lat2)
+{
+ return spherical_azimuth<ReturnType, false>(lon1, lat1, lon2, lat2).azimuth;
+}
+
+template <typename T>
+inline T spherical_azimuth(T const& lon1, T const& lat1, T const& lon2, T const& lat2)
+{
+ return spherical_azimuth<T, false>(lon1, lat1, lon2, lat2).azimuth;
+}
+
+template <typename T>
+inline int azimuth_side_value(T const& azi_a1_p, T const& azi_a1_a2)
+{
+ T const pi = math::pi<T>();
+ T const two_pi = math::two_pi<T>();
+
+ // instead of the formula from XTD
+ //calc_t a_diff = asin(sin(azi_a1_p - azi_a1_a2));
+
+ T a_diff = azi_a1_p - azi_a1_a2;
+ // normalize, angle in [-pi, pi]
+ while (a_diff > pi)
+ a_diff -= two_pi;
+ while (a_diff < -pi)
+ a_diff += two_pi;
+
+ // NOTE: in general it shouldn't be required to support the pi/-pi case
+ // because in non-cartesian systems it makes sense to check the side
+ // only "between" the endpoints.
+ // However currently the winding strategy calls the side strategy
+ // for vertical segments to check if the point is "between the endpoints.
+ // This could be avoided since the side strategy is not required for that
+ // because meridian is the shortest path. So a difference of
+ // longitudes would be sufficient (of course normalized to [-pi, pi]).
+
+ // NOTE: with the above said, the pi/-pi check is temporary
+ // however in case if this was required
+ // the geodesics on ellipsoid aren't "symmetrical"
+ // therefore instead of comparing a_diff to pi and -pi
+ // one should probably use inverse azimuths and compare
+ // the difference to 0 as well
+
+ // positive azimuth is on the right side
+ return math::equals(a_diff, 0)
+ || math::equals(a_diff, pi)
+ || math::equals(a_diff, -pi) ? 0
+ : a_diff > 0 ? -1 // right
+ : 1; // left
+}
+
} // namespace formula
}} // namespace boost::geometry
diff --git a/boost/geometry/formulas/thomas_direct.hpp b/boost/geometry/formulas/thomas_direct.hpp
index f8a7f83943..f208167cf5 100644
--- a/boost/geometry/formulas/thomas_direct.hpp
+++ b/boost/geometry/formulas/thomas_direct.hpp
@@ -20,9 +20,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_direct.hpp>
@@ -82,7 +81,7 @@ public:
CT const a = CT(get_radius<0>(spheroid));
CT const b = CT(get_radius<2>(spheroid));
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const one_minus_f = c1 - f;
CT const pi = math::pi<CT>();
diff --git a/boost/geometry/formulas/thomas_inverse.hpp b/boost/geometry/formulas/thomas_inverse.hpp
index d68c9de054..0853a36980 100644
--- a/boost/geometry/formulas/thomas_inverse.hpp
+++ b/boost/geometry/formulas/thomas_inverse.hpp
@@ -20,9 +20,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_inverse.hpp>
@@ -78,7 +77,7 @@ public:
CT const c4 = 4;
CT const pi_half = math::pi<CT>() / c2;
- CT const f = detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
CT const one_minus_f = c1 - f;
// CT const tan_theta1 = one_minus_f * tan(lat1);
diff --git a/boost/geometry/formulas/vertex_latitude.hpp b/boost/geometry/formulas/vertex_latitude.hpp
new file mode 100644
index 0000000000..755067b08d
--- /dev/null
+++ b/boost/geometry/formulas/vertex_latitude.hpp
@@ -0,0 +1,148 @@
+// Boost.Geometry
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_FORMULAS_MAXIMUM_LATITUDE_HPP
+#define BOOST_GEOMETRY_FORMULAS_MAXIMUM_LATITUDE_HPP
+
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
+#include <boost/mpl/assert.hpp>
+
+namespace boost { namespace geometry { namespace formula
+{
+
+/*!
+\brief Algorithm to compute the vertex latitude of a geodesic segment. Vertex is
+a point on the geodesic that maximizes (or minimizes) the latitude.
+\author See
+ [Wood96] Wood - Vertex Latitudes on Ellipsoid Geodesics, SIAM Rev., 38(4),
+ 637–644, 1996
+*/
+
+template <typename CT>
+class vertex_latitude_on_sphere
+{
+
+public:
+ template<typename T1, typename T2>
+ static inline CT apply(T1 const& lat1,
+ T2 const& alp1)
+ {
+ return std::acos( math::abs(cos(lat1) * sin(alp1)) );
+ }
+};
+
+template <typename CT>
+class vertex_latitude_on_spheroid
+{
+
+public:
+/*
+ * formula based on paper
+ * [Wood96] Wood - Vertex Latitudes on Ellipsoid Geodesics, SIAM Rev., 38(4),
+ * 637–644, 1996
+ template <typename T1, typename T2, typename Spheroid>
+ static inline CT apply(T1 const& lat1,
+ T2 const& alp1,
+ Spheroid const& spheroid)
+ {
+ CT const f = formula::flattening<CT>(spheroid);
+
+ CT const e2 = f * (CT(2) - f);
+ CT const sin_alp1 = sin(alp1);
+ CT const sin2_lat1 = math::sqr(sin(lat1));
+ CT const cos2_lat1 = CT(1) - sin2_lat1;
+
+ CT const e2_sin2 = CT(1) - e2 * sin2_lat1;
+ CT const cos2_sin2 = cos2_lat1 * math::sqr(sin_alp1);
+ CT const vertex_lat = std::asin( math::sqrt((e2_sin2 - cos2_sin2)
+ / (e2_sin2 - e2 * cos2_sin2)));
+ return vertex_lat;
+ }
+*/
+
+ // simpler formula based on Clairaut relation for spheroids
+ template <typename T1, typename T2, typename Spheroid>
+ static inline CT apply(T1 const& lat1,
+ T2 const& alp1,
+ Spheroid const& spheroid)
+ {
+ CT const f = formula::flattening<CT>(spheroid);
+
+ CT const one_minus_f = (CT(1) - f);
+
+ //get the reduced latitude
+ CT const bet1 = atan( one_minus_f * tan(lat1) );
+
+ //apply Clairaut relation
+ CT const betv = vertex_latitude_on_sphere<CT>::apply(bet1, alp1);
+
+ //return the spheroid latitude
+ return atan( tan(betv) / one_minus_f );
+ }
+
+ /*
+ template <typename T>
+ inline static void sign_adjustment(CT lat1, CT lat2, CT vertex_lat, T& vrt_result)
+ {
+ // signbit returns a non-zero value (true) if the sign is negative;
+ // and zero (false) otherwise.
+ bool sign = std::signbit(std::abs(lat1) > std::abs(lat2) ? lat1 : lat2);
+
+ vrt_result.north = sign ? std::max(lat1, lat2) : vertex_lat;
+ vrt_result.south = sign ? vertex_lat * CT(-1) : std::min(lat1, lat2);
+ }
+
+ template <typename T>
+ inline static bool vertex_on_segment(CT alp1, CT alp2, CT lat1, CT lat2, T& vrt_result)
+ {
+ CT const half_pi = math::pi<CT>() / CT(2);
+
+ // if the segment does not contain the vertex of the geodesic
+ // then return the endpoint of max (min) latitude
+ if ((alp1 < half_pi && alp2 < half_pi)
+ || (alp1 > half_pi && alp2 > half_pi))
+ {
+ vrt_result.north = std::max(lat1, lat2);
+ vrt_result.south = std::min(lat1, lat2);
+ return false;
+ }
+ return true;
+ }
+ */
+};
+
+
+template <typename CT, typename CS_Tag>
+struct vertex_latitude
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM, (types<CS_Tag>)
+ );
+
+};
+
+template <typename CT>
+struct vertex_latitude<CT, spherical_equatorial_tag>
+ : vertex_latitude_on_sphere<CT>
+{};
+
+template <typename CT>
+struct vertex_latitude<CT, geographic_tag>
+ : vertex_latitude_on_spheroid<CT>
+{};
+
+
+}}} // namespace boost::geometry::formula
+
+#endif // BOOST_GEOMETRY_FORMULAS_MAXIMUM_LATITUDE_HPP
diff --git a/boost/geometry/formulas/vincenty_direct.hpp b/boost/geometry/formulas/vincenty_direct.hpp
index f3647ff4e6..1697e5fb63 100644
--- a/boost/geometry/formulas/vincenty_direct.hpp
+++ b/boost/geometry/formulas/vincenty_direct.hpp
@@ -23,9 +23,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_direct.hpp>
@@ -85,7 +84,7 @@ public:
CT const radius_a = CT(get_radius<0>(spheroid));
CT const radius_b = CT(get_radius<2>(spheroid));
- CT const flattening = geometry::detail::flattening<CT>(spheroid);
+ CT const flattening = formula::flattening<CT>(spheroid);
CT const sin_azimuth12 = sin(azimuth12);
CT const cos_azimuth12 = cos(azimuth12);
diff --git a/boost/geometry/formulas/vincenty_inverse.hpp b/boost/geometry/formulas/vincenty_inverse.hpp
index bbda00036b..032e16e291 100644
--- a/boost/geometry/formulas/vincenty_inverse.hpp
+++ b/boost/geometry/formulas/vincenty_inverse.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,9 +23,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
#include <boost/geometry/formulas/differential_quantities.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
#include <boost/geometry/formulas/result_inverse.hpp>
@@ -41,7 +40,7 @@ namespace boost { namespace geometry { namespace formula
\brief The solution of the inverse problem of geodesics on latlong coordinates, after Vincenty, 1975
\author See
- http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
- - http://www.icsm.gov.au/gda/gdav2.3.pdf
+ - http://www.icsm.gov.au/gda/gda-v_2.4.pdf
\author Adapted from various implementations to get it close to the original document
- http://www.movable-type.co.uk/scripts/LatLongVincenty.html
- http://exogen.case.edu/projects/geopy/source/geopy.distance.html
@@ -99,10 +98,10 @@ public:
CT const radius_a = CT(get_radius<0>(spheroid));
CT const radius_b = CT(get_radius<2>(spheroid));
- CT const flattening = geometry::detail::flattening<CT>(spheroid);
+ CT const f = formula::flattening<CT>(spheroid);
// U: reduced latitude, defined by tan U = (1-f) tan phi
- CT const one_min_f = c1 - flattening;
+ CT const one_min_f = c1 - f;
CT const tan_U1 = one_min_f * tan(lat1); // above (1)
CT const tan_U2 = one_min_f * tan(lat2); // above (1)
@@ -113,8 +112,9 @@ public:
CT const cos_U1 = c1 / temp_den_U1;
CT const cos_U2 = c1 / temp_den_U2;
// sin = tan / sqrt(1 + tan^2)
- CT const sin_U1 = tan_U1 / temp_den_U1;
- CT const sin_U2 = tan_U2 / temp_den_U2;
+ // sin = tan * cos
+ CT const sin_U1 = tan_U1 * cos_U1;
+ CT const sin_U2 = tan_U2 * cos_U2;
// calculate sin U and cos U directly
//CT const U1 = atan(tan_U1);
@@ -130,7 +130,8 @@ public:
CT sin_sigma;
CT sin_alpha;
CT cos2_alpha;
- CT cos2_sigma_m;
+ CT cos_2sigma_m;
+ CT cos2_2sigma_m;
CT sigma;
int counter = 0; // robustness
@@ -144,12 +145,13 @@ public:
CT cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)
sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)
cos2_alpha = c1 - math::sqr(sin_alpha);
- cos2_sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)
+ cos_2sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)
+ cos2_2sigma_m = math::sqr(cos_2sigma_m);
- CT C = flattening/c16 * cos2_alpha * (c4 + flattening * (c4 - c3 * cos2_alpha)); // (10)
+ CT C = f/c16 * cos2_alpha * (c4 + f * (c4 - c3 * cos2_alpha)); // (10)
sigma = atan2(sin_sigma, cos_sigma); // (16)
- lambda = L + (c1 - C) * flattening * sin_alpha *
- (sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-c1 + c2 * math::sqr(cos2_sigma_m)))); // (11)
+ lambda = L + (c1 - C) * f * sin_alpha *
+ (sigma + C * sin_sigma * (cos_2sigma_m + C * cos_sigma * (-c1 + c2 * cos2_2sigma_m))); // (11)
++counter; // robustness
@@ -182,8 +184,10 @@ public:
CT A = c1 + sqr_u/c16384 * (c4096 + sqr_u * (-c768 + sqr_u * (c320 - c175 * sqr_u))); // (3)
CT B = sqr_u/c1024 * (c256 + sqr_u * ( -c128 + sqr_u * (c74 - c47 * sqr_u))); // (4)
- CT delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/c4) * (cos(sigma)* (-c1 + c2 * cos2_sigma_m)
- - (B/c6) * cos2_sigma_m * (-c3 + c4 * math::sqr(sin_sigma)) * (-c3 + c4 * cos2_sigma_m))); // (6)
+ CT const cos_sigma = cos(sigma);
+ CT const sin2_sigma = math::sqr(sin_sigma);
+ CT delta_sigma = B * sin_sigma * (cos_2sigma_m + (B/c4) * (cos_sigma* (-c1 + c2 * cos2_2sigma_m)
+ - (B/c6) * cos_2sigma_m * (-c3 + c4 * sin2_sigma) * (-c3 + c4 * cos2_2sigma_m))); // (6)
result.distance = radius_b * A * (sigma - delta_sigma); // (19)
}
@@ -206,7 +210,7 @@ public:
typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 2> quantities;
quantities::apply(lon1, lat1, lon2, lat2,
result.azimuth, result.reverse_azimuth,
- radius_b, flattening,
+ radius_b, f,
result.reduced_length, result.geodesic_scale);
}
diff --git a/boost/geometry/index/detail/algorithms/nth_element.hpp b/boost/geometry/index/detail/algorithms/nth_element.hpp
new file mode 100644
index 0000000000..201180ae3a
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/nth_element.hpp
@@ -0,0 +1,62 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+//
+// 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_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
+
+#include <algorithm>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+// See https://svn.boost.org/trac/boost/ticket/12861
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800
+// https://gcc.gnu.org/develop.html#timeline
+// 20120920 4.7.2 - no bug
+// 20130322 4.8.0 - no bug
+// 20130411 4.7.3 - no bug
+// 20130531 4.8.1 - no bug
+// 20131016 4.8.2 - bug
+// 20140422 4.9.0 - fixed
+// 20140522 4.8.3 - fixed
+// 20140612 4.7.4 - fixed
+// 20140716 4.9.1 - fixed
+#if defined(__GLIBCXX__) && (__GLIBCXX__ == 20131016)
+
+#warning "std::nth_element replaced with std::sort, libstdc++ bug workaround.";
+
+template <typename RandomIt>
+void nth_element(RandomIt first, RandomIt , RandomIt last)
+{
+ std::sort(first, last);
+}
+
+template <typename RandomIt, typename Compare>
+void nth_element(RandomIt first, RandomIt , RandomIt last, Compare comp)
+{
+ std::sort(first, last, comp);
+}
+
+#else
+
+template <typename RandomIt>
+void nth_element(RandomIt first, RandomIt nth, RandomIt last)
+{
+ std::nth_element(first, nth, last);
+}
+
+template <typename RandomIt, typename Compare>
+void nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp)
+{
+ std::nth_element(first, nth, last, comp);
+}
+
+#endif
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
index d1491b8d47..2d3903a7b4 100644
--- a/boost/geometry/index/detail/rtree/pack_create.hpp
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -2,7 +2,7 @@
//
// R-tree initial packing
//
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,6 +13,7 @@
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
+#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
@@ -67,7 +68,7 @@ struct nth_element_and_half_boxes
{
if ( I == dim_index )
{
- std::nth_element(first, median, last, point_entries_comparer<I>());
+ index::detail::nth_element(first, median, last, point_entries_comparer<I>());
geometry::convert(box, left);
geometry::convert(box, right);
diff --git a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
index 7a96986a27..89697b5947 100644
--- a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
@@ -2,7 +2,7 @@
//
// R-tree R*-tree next node choosing algorithm implementation
//
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -17,6 +17,7 @@
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
+#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/rtree/node/node.hpp>
@@ -112,7 +113,7 @@ private:
first_n_children_count = overlap_cost_threshold;
// rearrange by content_diff
// in order to calculate nearly minimum overlap cost
- std::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
+ index::detail::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
}
// calculate minimum or nearly minimum overlap cost
diff --git a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
index 8f270537fb..187d37facd 100644
--- a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
@@ -2,7 +2,7 @@
//
// R-tree R*-tree split algorithm implementation
//
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -12,8 +12,9 @@
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
-#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/algorithms/margin.hpp>
+#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/bounded_view.hpp>
@@ -122,8 +123,9 @@ struct choose_split_axis_and_index_for_corner
// {
// typename Elements::iterator f = elements_copy.begin() + index_first;
// typename Elements::iterator l = elements_copy.begin() + index_last;
-// std::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
-// std::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
+// // NOTE: for stdlibc++ shipped with gcc 4.8.2 std::nth_element is replaced with std::sort anyway
+// index::detail::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
+// index::detail::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
// std::sort(f, l, elements_less); // MAY THROW, BASIC (copy)
// }
@@ -349,7 +351,7 @@ struct nth_element
typedef typename tag<indexable_type>::type indexable_tag;
element_axis_corner_less<element_type, Translator, indexable_tag, Corner, I> less(tr);
- std::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
+ index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
}
}
};
diff --git a/boost/geometry/index/equal_to.hpp b/boost/geometry/index/equal_to.hpp
index b0cf098f1d..6b722a89fc 100644
--- a/boost/geometry/index/equal_to.hpp
+++ b/boost/geometry/index/equal_to.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry Index
//
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -42,6 +42,15 @@ struct equals<T, void>
}
};
+template <typename T>
+struct equals<T *, void>
+{
+ inline static bool apply(const T * v1, const T * v2)
+ {
+ return v1 == v2;
+ }
+};
+
template <typename Tuple, size_t I, size_t N>
struct tuple_equals
{
diff --git a/boost/geometry/index/parameters.hpp b/boost/geometry/index/parameters.hpp
index 2b94907686..1a9469c103 100644
--- a/boost/geometry/index/parameters.hpp
+++ b/boost/geometry/index/parameters.hpp
@@ -2,7 +2,7 @@
//
// R-tree algorithms parameters
//
-// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,8 +11,14 @@
#ifndef BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
+
#include <limits>
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/index/detail/exception.hpp>
+
+
namespace boost { namespace geometry { namespace index {
namespace detail {
@@ -156,8 +162,8 @@ public:
\param max_elements Maximum number of elements in nodes.
\param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
*/
- dynamic_linear(size_t max_elements,
- size_t min_elements = detail::default_min_elements_d())
+ explicit dynamic_linear(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d())
: m_max_elements(max_elements)
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
{
@@ -185,8 +191,8 @@ public:
\param max_elements Maximum number of elements in nodes.
\param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
*/
- dynamic_quadratic(size_t max_elements,
- size_t min_elements = detail::default_min_elements_d())
+ explicit dynamic_quadratic(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d())
: m_max_elements(max_elements)
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
{
@@ -222,10 +228,10 @@ public:
nearly minimum overlap cost, otherwise all leafs are analyzed
and true minimum overlap cost is calculated. Default: 32.
*/
- dynamic_rstar(size_t max_elements,
- size_t min_elements = detail::default_min_elements_d(),
- size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
- size_t overlap_cost_threshold = 32)
+ explicit dynamic_rstar(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d(),
+ size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
+ size_t overlap_cost_threshold = 32)
: m_max_elements(max_elements)
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
, m_reinserted_elements(detail::default_rstar_reinserted_elements_d_calc(max_elements, reinserted_elements))
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp
index 148a5769dd..236690dc2c 100644
--- a/boost/geometry/io/wkt/read.hpp
+++ b/boost/geometry/io/wkt/read.hpp
@@ -3,6 +3,7 @@
// 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) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015.
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
@@ -31,6 +32,7 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
+#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
@@ -139,15 +141,15 @@ struct parsing_assigner
}
catch(boost::bad_lexical_cast const& blc)
{
- throw read_wkt_exception(blc.what(), it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception(blc.what(), it, end, wkt));
}
catch(std::exception const& e)
{
- throw read_wkt_exception(e.what(), it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception(e.what(), it, end, wkt));
}
catch(...)
{
- throw read_wkt_exception("", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("", it, end, wkt));
}
parsing_assigner<Point, Dimension + 1, DimensionCount>::apply(
@@ -175,7 +177,7 @@ inline void handle_open_parenthesis(Iterator& it,
{
if (it == end || *it != "(")
{
- throw read_wkt_exception("Expected '('", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Expected '('", it, end, wkt));
}
++it;
}
@@ -192,7 +194,7 @@ inline void handle_close_parenthesis(Iterator& it,
}
else
{
- throw read_wkt_exception("Expected ')'", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Expected ')'", it, end, wkt));
}
}
@@ -203,7 +205,7 @@ inline void check_end(Iterator& it,
{
if (it != end)
{
- throw read_wkt_exception("Too much tokens", it, end, wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Too many tokens", it, end, wkt));
}
}
@@ -529,7 +531,7 @@ inline bool initialize(tokenizer const& tokens,
if (has_z && dimension<Geometry>::type::value < 3)
{
- throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Z only allowed for 3 or more dimensions", wkt));
}
#if defined(_MSC_VER)
@@ -545,7 +547,7 @@ inline bool initialize(tokenizer const& tokens,
return true;
}
- throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt));
}
@@ -702,7 +704,7 @@ struct box_parser
}
else
{
- throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt));
}
typedef typename point_type<Box>::type point_type;
@@ -729,7 +731,7 @@ struct box_parser
}
else
{
- throw read_wkt_exception("Box should have 2,4 or 5 points", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Box should have 2,4 or 5 points", wkt));
}
geometry::detail::assign_point_to_index<min_corner>(points.front(), box);
@@ -760,7 +762,7 @@ struct segment_parser
}
else
{
- throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt));
}
typedef typename point_type<Segment>::type point_type;
@@ -776,7 +778,7 @@ struct segment_parser
}
else
{
- throw read_wkt_exception("Segment should have 2 points", wkt);
+ BOOST_THROW_EXCEPTION(read_wkt_exception("Segment should have 2 points", wkt));
}
}
diff --git a/boost/geometry/policies/robustness/segment_ratio.hpp b/boost/geometry/policies/robustness/segment_ratio.hpp
index f3dbabe70a..9b313fdfaf 100644
--- a/boost/geometry/policies/robustness/segment_ratio.hpp
+++ b/boost/geometry/policies/robustness/segment_ratio.hpp
@@ -145,11 +145,10 @@ public :
m_approximation =
m_denominator == 0 ? 0
- : boost::numeric_cast<double>
- (
- boost::numeric_cast<fp_type>(m_numerator) * scale()
- / boost::numeric_cast<fp_type>(m_denominator)
- );
+ : (
+ boost::numeric_cast<fp_type>(m_numerator) * scale()
+ / boost::numeric_cast<fp_type>(m_denominator)
+ );
}
inline bool is_zero() const { return math::equals(m_numerator, 0); }
@@ -187,7 +186,7 @@ public :
return false;
}
- static fp_type const small_part_of_scale = scale() / 100.0;
+ static fp_type const small_part_of_scale = scale() / 100;
return m_approximation < small_part_of_scale
|| m_approximation > scale() - small_part_of_scale;
}
@@ -236,7 +235,14 @@ public :
private :
- typedef typename promote_floating_point<Type>::type fp_type;
+ // NOTE: if this typedef is used then fp_type is non-fundamental type
+ // if Type is non-fundamental type
+ //typedef typename promote_floating_point<Type>::type fp_type;
+
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_float<Type>::value, Type, double
+ >::type fp_type;
Type m_numerator;
Type m_denominator;
diff --git a/boost/geometry/strategies/agnostic/point_in_point.hpp b/boost/geometry/strategies/agnostic/point_in_point.hpp
index e4f9bec4c6..c6e2b63623 100644
--- a/boost/geometry/strategies/agnostic/point_in_point.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_point.hpp
@@ -1,12 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014 Oracle and/or its affiliates.
+// Copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP
@@ -41,41 +42,12 @@ struct point_in_point
namespace services
{
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, cartesian_tag, cartesian_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, spherical_tag, spherical_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, AnyCS1, AnyCS2, Point1, Point2>
+template <typename Point, typename PointLike, typename Tag2, typename AnyCS1, typename AnyCS2>
+struct default_strategy<Point, PointLike, point_tag, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
{
- typedef strategy::within::point_in_point<Point1, Point2> type;
+ typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::type> type;
};
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, cartesian_tag, cartesian_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, spherical_tag, spherical_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, AnyCS1, AnyCS2, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
} // namespace services
@@ -85,45 +57,14 @@ struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag,
}} // namespace strategy::within
-
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, cartesian_tag, cartesian_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, spherical_tag, spherical_tag, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point1, typename Point2, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, point_tag, point_tag, point_tag, AnyCS1, AnyCS2, Point1, Point2>
-{
- typedef strategy::within::point_in_point<Point1, Point2> type;
-};
-
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, cartesian_tag, cartesian_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, spherical_tag, spherical_tag, Point, MultiPoint>
-{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
-};
-
-template <typename Point, typename MultiPoint, typename AnyCS1, typename AnyCS2>
-struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, AnyCS1, AnyCS2, Point, MultiPoint>
+template <typename Point, typename PointLike, typename Tag2, typename AnyCS1, typename AnyCS2>
+struct default_strategy<Point, PointLike, point_tag, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2>
{
- typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;
+ typedef strategy::within::point_in_point<Point, typename point_type<PointLike>::type> type;
};
}}} // namespace strategy::covered_by::services
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
index 9e2ec2c4ff..3e7e258788 100644
--- a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2016.
-// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2016, 2017.
+// Modifications copyright (c) 2013-2017 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
@@ -314,6 +314,7 @@ struct winding_calculate_count<Point, CalculationType, cartesian_tag>
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
+\tparam SideStrategy Side strategy
\tparam CalculationType \tparam_calculation
\author Barend Gehrels
\note The implementation is inspired by terralib http://www.terralib.org (LGPL)
@@ -329,6 +330,10 @@ template
<
typename Point,
typename PointOfSegment = Point,
+ typename SideStrategy = typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Point>::type
+ >::type,
typename CalculationType = void
>
class winding
@@ -339,14 +344,7 @@ class winding
PointOfSegment,
CalculationType
>::type calculation_type;
-
-
- typedef typename strategy::side::services::default_strategy
- <
- typename cs_tag<Point>::type
- >::type strategy_side_type;
-
-
+
/*! subclass to keep state */
class counter
{
@@ -371,7 +369,6 @@ class winding
};
-
static inline int check_segment(Point const& point,
PointOfSegment const& seg1, PointOfSegment const& seg2,
counter& state, bool& eq1, bool& eq2)
@@ -390,16 +387,22 @@ class winding
}
-public :
+public:
+ winding()
+ {}
+
+ explicit winding(SideStrategy const& side_strategy)
+ : m_side_strategy(side_strategy)
+ {}
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
- static inline bool apply(Point const& point,
- PointOfSegment const& s1, PointOfSegment const& s2,
- counter& state)
+ inline bool apply(Point const& point,
+ PointOfSegment const& s1, PointOfSegment const& s2,
+ counter& state) const
{
typedef typename cs_tag<Point>::type cs_t;
@@ -418,7 +421,7 @@ public :
else // count == 2 || count == -2
{
// 1 left, -1 right
- side = strategy_side_type::apply(s1, s2, point);
+ side = m_side_strategy.apply(s1, s2, point);
}
if (side == 0)
@@ -445,6 +448,9 @@ public :
{
return state.code();
}
+
+private:
+ SideStrategy m_side_strategy;
};
@@ -453,29 +459,26 @@ public :
namespace services
{
-// Register using "areal_tag" for ring, polygon, multi-polygon
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used
-
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, cartesian_tag, cartesian_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, spherical_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
};
@@ -488,34 +491,30 @@ struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, sph
}} // namespace strategy::within
-
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
-// Register using "areal_tag" for ring, polygon, multi-polygon
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-template <typename AnyTag, typename Point, typename Geometry>
-struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
+template <typename Point, typename Geometry, typename AnyTag>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
-// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used
-
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, cartesian_tag, cartesian_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
template <typename Point, typename Geometry, typename AnyTag>
-struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, spherical_tag, Point, Geometry>
+struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
};
diff --git a/boost/geometry/strategies/agnostic/relate.hpp b/boost/geometry/strategies/agnostic/relate.hpp
deleted file mode 100644
index 676207694f..0000000000
--- a/boost/geometry/strategies/agnostic/relate.hpp
+++ /dev/null
@@ -1,122 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2014-2015 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_STRATEGY_AGNOSTIC_RELATE_HPP
-#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
-
-#include <boost/geometry/algorithms/relate.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-namespace strategy { namespace relate
-{
-
-template <typename Geometry1, typename Geometry2, typename StaticMask>
-struct relate
-{
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
- {
- return geometry::relate(geometry1, geometry2, StaticMask());
- }
-};
-
-} // namespace relate
-
-namespace within
-{
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-namespace services
-{
-
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_within_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_within_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-
-} // namespace services
-
-#endif
-
-
-}} // namespace strategy::within
-
-
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-namespace strategy { namespace covered_by { namespace services
-{
-
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_covered_by_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
-struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>
-{
- typedef strategy::relate::relate
- <
- Geometry1,
- Geometry2,
- typename detail::de9im::static_mask_covered_by_type
- <
- Geometry1, Geometry2
- >::type
- > type;
-};
-
-
-}}} // namespace strategy::covered_by::services
-#endif
-
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
diff --git a/boost/geometry/strategies/azimuth.hpp b/boost/geometry/strategies/azimuth.hpp
new file mode 100644
index 0000000000..8044d3933b
--- /dev/null
+++ b/boost/geometry/strategies/azimuth.hpp
@@ -0,0 +1,44 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_HPP
+
+#include <boost/mpl/assert.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace azimuth { namespace services
+{
+
+/*!
+\brief Traits class binding a default azimuth strategy to a coordinate system
+\ingroup util
+\tparam CSTag tag of coordinate system
+\tparam CalculationType \tparam_calculation
+*/
+template <typename CSTag, typename CalculationType = void>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE
+ , (types<CSTag>)
+ );
+};
+
+}}} // namespace strategy::azimuth::services
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/cartesian/area_surveyor.hpp b/boost/geometry/strategies/cartesian/area_surveyor.hpp
index ba76f67946..b3f19b1b1e 100644
--- a/boost/geometry/strategies/cartesian/area_surveyor.hpp
+++ b/boost/geometry/strategies/cartesian/area_surveyor.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2016.
-// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016, 2017.
+// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,6 +25,7 @@
//#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
diff --git a/boost/geometry/strategies/cartesian/azimuth.hpp b/boost/geometry/strategies/cartesian/azimuth.hpp
new file mode 100644
index 0000000000..62f804e8f5
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/azimuth.hpp
@@ -0,0 +1,49 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
+
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace azimuth
+{
+
+template
+<
+ typename CalculationType = void
+>
+class cartesian
+{};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
+{
+ typedef strategy::azimuth::cartesian<CalculationType> type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace strategy::azimuth
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp
index 28a6f29336..4641aafcb1 100644
--- a/boost/geometry/strategies/cartesian/box_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/box_in_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2015, 2016.
-// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015, 2016, 2017.
+// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -238,10 +238,10 @@ namespace within { namespace services
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::box_in_box<BoxContained, BoxContaining> type;
@@ -251,10 +251,10 @@ struct default_strategy
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- spherical_tag, spherical_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::box_in_box<BoxContained, BoxContaining> type;
@@ -269,10 +269,10 @@ namespace covered_by { namespace services
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::box_in_box
@@ -286,10 +286,10 @@ struct default_strategy
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
+ BoxContained, BoxContaining,
box_tag, box_tag,
- box_tag, areal_tag,
- spherical_tag, spherical_tag,
- BoxContained, BoxContaining
+ areal_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::box_in_box
diff --git a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
new file mode 100644
index 0000000000..4270803322
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
@@ -0,0 +1,320 @@
+// Boost.Geometry
+
+// 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.
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2013-2017.
+// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// 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_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
+
+
+#include <cstddef>
+#include <utility>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/calculation_type.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+
+#include <boost/geometry/strategies/disjoint.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace disjoint
+{
+
+namespace detail
+{
+
+template <std::size_t I>
+struct compute_tmin_tmax_per_dim
+{
+ template <typename SegmentPoint, typename Box, typename RelativeDistance>
+ static inline void apply(SegmentPoint const& p0,
+ SegmentPoint const& p1,
+ Box const& box,
+ RelativeDistance& ti_min,
+ RelativeDistance& ti_max,
+ RelativeDistance& diff)
+ {
+ typedef typename coordinate_type<Box>::type box_coordinate_type;
+ typedef typename coordinate_type
+ <
+ SegmentPoint
+ >::type point_coordinate_type;
+
+ RelativeDistance c_p0 = boost::numeric_cast
+ <
+ point_coordinate_type
+ >( geometry::get<I>(p0) );
+
+ RelativeDistance c_p1 = boost::numeric_cast
+ <
+ point_coordinate_type
+ >( geometry::get<I>(p1) );
+
+ RelativeDistance c_b_min = boost::numeric_cast
+ <
+ box_coordinate_type
+ >( geometry::get<geometry::min_corner, I>(box) );
+
+ RelativeDistance c_b_max = boost::numeric_cast
+ <
+ box_coordinate_type
+ >( geometry::get<geometry::max_corner, I>(box) );
+
+ if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
+ {
+ diff = c_p1 - c_p0;
+ ti_min = c_b_min - c_p0;
+ ti_max = c_b_max - c_p0;
+ }
+ else
+ {
+ diff = c_p0 - c_p1;
+ ti_min = c_p0 - c_b_max;
+ ti_max = c_p0 - c_b_min;
+ }
+ }
+};
+
+
+template
+<
+ typename RelativeDistance,
+ typename SegmentPoint,
+ typename Box,
+ std::size_t I,
+ std::size_t Dimension
+>
+struct disjoint_segment_box_impl
+{
+ template <typename RelativeDistancePair>
+ static inline bool apply(SegmentPoint const& p0,
+ SegmentPoint const& p1,
+ Box const& box,
+ RelativeDistancePair& t_min,
+ RelativeDistancePair& t_max)
+ {
+ RelativeDistance ti_min, ti_max, diff;
+
+ compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
+
+ if ( geometry::math::equals(diff, 0) )
+ {
+ if ( (geometry::math::equals(t_min.second, 0)
+ && t_min.first > ti_max)
+ ||
+ (geometry::math::equals(t_max.second, 0)
+ && t_max.first < ti_min)
+ ||
+ (math::sign(ti_min) * math::sign(ti_max) > 0) )
+ {
+ return true;
+ }
+ }
+
+ RelativeDistance t_min_x_diff = t_min.first * diff;
+ RelativeDistance t_max_x_diff = t_max.first * diff;
+
+ if ( t_min_x_diff > ti_max * t_min.second
+ || t_max_x_diff < ti_min * t_max.second )
+ {
+ return true;
+ }
+
+ if ( ti_min * t_min.second > t_min_x_diff )
+ {
+ t_min.first = ti_min;
+ t_min.second = diff;
+ }
+ if ( ti_max * t_max.second < t_max_x_diff )
+ {
+ t_max.first = ti_max;
+ t_max.second = diff;
+ }
+
+ if ( t_min.first > t_min.second || t_max.first < 0 )
+ {
+ return true;
+ }
+
+ return disjoint_segment_box_impl
+ <
+ RelativeDistance,
+ SegmentPoint,
+ Box,
+ I + 1,
+ Dimension
+ >::apply(p0, p1, box, t_min, t_max);
+ }
+};
+
+
+template
+<
+ typename RelativeDistance,
+ typename SegmentPoint,
+ typename Box,
+ std::size_t Dimension
+>
+struct disjoint_segment_box_impl
+ <
+ RelativeDistance, SegmentPoint, Box, 0, Dimension
+ >
+{
+ static inline bool apply(SegmentPoint const& p0,
+ SegmentPoint const& p1,
+ Box const& box)
+ {
+ std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
+ RelativeDistance diff;
+
+ compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
+ t_min.first, t_max.first, diff);
+
+ if ( geometry::math::equals(diff, 0) )
+ {
+ if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
+ if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
+
+ if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
+ {
+ return true;
+ }
+ }
+
+ if ( t_min.first > diff || t_max.first < 0 )
+ {
+ return true;
+ }
+
+ t_min.second = t_max.second = diff;
+
+ return disjoint_segment_box_impl
+ <
+ RelativeDistance, SegmentPoint, Box, 1, Dimension
+ >::apply(p0, p1, box, t_min, t_max);
+ }
+};
+
+
+template
+<
+ typename RelativeDistance,
+ typename SegmentPoint,
+ typename Box,
+ std::size_t Dimension
+>
+struct disjoint_segment_box_impl
+ <
+ RelativeDistance, SegmentPoint, Box, Dimension, Dimension
+ >
+{
+ template <typename RelativeDistancePair>
+ static inline bool apply(SegmentPoint const&, SegmentPoint const&,
+ Box const&,
+ RelativeDistancePair&, RelativeDistancePair&)
+ {
+ return false;
+ }
+};
+
+} // namespace detail
+
+// NOTE: This may be temporary place for this or corresponding strategy
+// It seems to be more appropriate to implement the opposite of it
+// e.g. intersection::segment_box because in disjoint() algorithm
+// other strategies that are used are intersection and covered_by strategies.
+struct segment_box
+{
+ template <typename Segment, typename Box>
+ struct point_in_geometry_strategy
+ : services::default_strategy
+ <
+ typename point_type<Segment>::type,
+ Box
+ >
+ {};
+
+ template <typename Segment, typename Box>
+ static inline typename point_in_geometry_strategy<Segment, Box>::type
+ get_point_in_geometry_strategy()
+ {
+ typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
+
+ return strategy_type();
+ }
+
+ template <typename Segment, typename Box>
+ static inline bool apply(Segment const& segment, Box const& box)
+ {
+ assert_dimension_equal<Segment, Box>();
+
+ typedef typename util::calculation_type::geometric::binary
+ <
+ Segment, Box, void
+ >::type relative_distance_type;
+
+ typedef typename point_type<Segment>::type segment_point_type;
+ segment_point_type p0, p1;
+ geometry::detail::assign_point_from_index<0>(segment, p0);
+ geometry::detail::assign_point_from_index<1>(segment, p1);
+
+ return detail::disjoint_segment_box_impl
+ <
+ relative_distance_type, segment_point_type, Box,
+ 0, dimension<Box>::value
+ >::apply(p0, p1, box);
+ }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+namespace services
+{
+
+// Currently used in all coordinate systems
+
+template <typename Linear, typename Box, typename LinearTag>
+struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2>
+{
+ typedef disjoint::segment_box type;
+};
+
+template <typename Box, typename Linear, typename LinearTag>
+struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1>
+{
+ typedef disjoint::segment_box type;
+};
+
+
+} // namespace services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}}}} // namespace boost::geometry::strategy::disjoint
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
diff --git a/boost/geometry/strategies/cartesian/envelope_segment.hpp b/boost/geometry/strategies/cartesian/envelope_segment.hpp
new file mode 100644
index 0000000000..0ddbf12a41
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/envelope_segment.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
+
+
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+template
+<
+ typename CalculationType = void
+>
+class cartesian_segment
+{
+public :
+
+ template <typename Point1, typename Point2, typename Box>
+ inline void
+ apply(Point1 const& point1, Point2 const& point2, Box& box) const
+ {
+ geometry::detail::envelope::envelope_one_segment
+ <
+ 0,
+ dimension<Point1>::value
+ >
+ ::apply(point1,
+ point2,
+ box,
+ strategy::envelope::cartesian_segment<CalculationType>());
+ }
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
+{
+ typedef strategy::envelope::cartesian_segment<CalculationType> type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
diff --git a/boost/geometry/strategies/cartesian/cart_intersect.hpp b/boost/geometry/strategies/cartesian/intersection.hpp
index 0cb5d75457..20b6b93367 100644
--- a/boost/geometry/strategies/cartesian/cart_intersect.hpp
+++ b/boost/geometry/strategies/cartesian/intersection.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2016, 2017.
+// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -33,13 +33,16 @@
#include <boost/geometry/util/promote_integral.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
-// Temporary / will be Strategy as template parameter
-#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
+#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
-
-#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
@@ -61,10 +64,74 @@ namespace strategy { namespace intersection
/*!
\see http://mathworld.wolfram.com/Line-LineIntersection.html
*/
-template <typename Policy, typename CalculationType = void>
-struct relate_cartesian_segments
+template
+<
+ typename CalculationType = void
+>
+struct cartesian_segments
{
- typedef typename Policy::return_type return_type;
+ typedef side::side_by_triangle<CalculationType> side_strategy_type;
+
+ static inline side_strategy_type get_side_strategy()
+ {
+ return side_strategy_type();
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ struct point_in_geometry_strategy
+ {
+ typedef strategy::within::winding
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ side_strategy_type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry1, typename Geometry2>
+ static inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
+ get_point_in_geometry_strategy()
+ {
+ typedef typename point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct area_strategy
+ {
+ typedef area::surveyor
+ <
+ typename point_type<Geometry>::type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename area_strategy<Geometry>::type get_area_strategy()
+ {
+ typedef typename area_strategy<Geometry>::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct distance_strategy
+ {
+ typedef distance::pythagoras
+ <
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename distance_strategy<Geometry>::type get_distance_strategy()
+ {
+ typedef typename distance_strategy<Geometry>::type strategy_type;
+ return strategy_type();
+ }
template <typename CoordinateType, typename SegmentRatio>
struct segment_intersection_info
@@ -144,9 +211,16 @@ struct relate_cartesian_segments
// Relate segments a and b
- template <typename Segment1, typename Segment2, typename RobustPolicy>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const& robust_policy)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const& policy, RobustPolicy const& robust_policy)
{
// type them all as in Segment1 - TODO reconsider this, most precise?
typedef typename geometry::point_type<Segment1>::type point_type;
@@ -169,18 +243,25 @@ struct relate_cartesian_segments
geometry::recalculate(b0_rob, b0, robust_policy);
geometry::recalculate(b1_rob, b1, robust_policy);
- return apply(a, b, robust_policy, a0_rob, a1_rob, b0_rob, b1_rob);
+ return apply(a, b, policy, robust_policy, a0_rob, a1_rob, b0_rob, b1_rob);
}
// The main entry-routine, calculating intersections of segments a / b
// NOTE: Robust* types may be the same as Segments' point types
- template <typename Segment1, typename Segment2,
- typename RobustPolicy,
- typename RobustPoint1, typename RobustPoint2>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const& /*robust_policy*/,
- RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
- RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy,
+ typename RobustPoint1,
+ typename RobustPoint2
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const&, RobustPolicy const& /*robust_policy*/,
+ RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
+ RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
@@ -197,14 +278,9 @@ struct relate_cartesian_segments
;
}
- typedef typename select_calculation_type
- <Segment1, Segment2, CalculationType>::type coordinate_type;
-
- typedef side::side_by_triangle<coordinate_type> side;
-
side_info sides;
- sides.set<0>(side::apply(robust_b1, robust_b2, robust_a1),
- side::apply(robust_b1, robust_b2, robust_a2));
+ sides.set<0>(side_strategy_type::apply(robust_b1, robust_b2, robust_a1),
+ side_strategy_type::apply(robust_b1, robust_b2, robust_a2));
if (sides.same<0>())
{
@@ -212,8 +288,8 @@ struct relate_cartesian_segments
return Policy::disjoint();
}
- sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1),
- side::apply(robust_a1, robust_a2, robust_b2));
+ sides.set<1>(side_strategy_type::apply(robust_a1, robust_a2, robust_b1),
+ side_strategy_type::apply(robust_a1, robust_a2, robust_b2));
if (sides.same<1>())
{
@@ -230,16 +306,16 @@ struct relate_cartesian_segments
>::type robust_coordinate_type;
typedef typename segment_ratio_type
- <
- typename geometry::point_type<Segment1>::type, // TODO: most precise point?
- RobustPolicy
- >::type ratio_type;
+ <
+ typename geometry::point_type<Segment1>::type, // TODO: most precise point?
+ RobustPolicy
+ >::type ratio_type;
segment_intersection_info
- <
- coordinate_type,
- ratio_type
- > sinfo;
+ <
+ typename select_calculation_type<Segment1, Segment2, CalculationType>::type,
+ ratio_type
+ > sinfo;
sinfo.dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
sinfo.dx_b = get<1, 0>(b) - get<0, 0>(b);
@@ -303,14 +379,14 @@ struct relate_cartesian_segments
if (collinear_use_first.first)
{
- return relate_collinear<0, ratio_type>(a, b,
+ return relate_collinear<0, Policy, ratio_type>(a, b,
robust_a1, robust_a2, robust_b1, robust_b2,
a_is_point, b_is_point);
}
else
{
// Y direction contains larger segments (maybe dx is zero)
- return relate_collinear<1, ratio_type>(a, b,
+ return relate_collinear<1, Policy, ratio_type>(a, b,
robust_a1, robust_a2, robust_b1, robust_b2,
a_is_point, b_is_point);
}
@@ -358,33 +434,35 @@ private:
template
<
std::size_t Dimension,
+ typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename RobustPoint1,
typename RobustPoint2
>
- static inline return_type relate_collinear(Segment1 const& a,
- Segment2 const& b,
- RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
- RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2,
- bool a_is_point, bool b_is_point)
+ static inline typename Policy::return_type
+ relate_collinear(Segment1 const& a,
+ Segment2 const& b,
+ RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
+ RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2,
+ bool a_is_point, bool b_is_point)
{
if (a_is_point)
{
- return relate_one_degenerate<RatioType>(a,
+ return relate_one_degenerate<Policy, RatioType>(a,
get<Dimension>(robust_a1),
get<Dimension>(robust_b1), get<Dimension>(robust_b2),
true);
}
if (b_is_point)
{
- return relate_one_degenerate<RatioType>(b,
+ return relate_one_degenerate<Policy, RatioType>(b,
get<Dimension>(robust_b1),
get<Dimension>(robust_a1), get<Dimension>(robust_a2),
false);
}
- return relate_collinear<RatioType>(a, b,
+ return relate_collinear<Policy, RatioType>(a, b,
get<Dimension>(robust_a1),
get<Dimension>(robust_a2),
get<Dimension>(robust_b1),
@@ -394,17 +472,17 @@ private:
/// Relate segments known collinear
template
<
+ typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename RobustType1,
typename RobustType2
>
- static inline return_type relate_collinear(Segment1 const& a
- , Segment2 const& b
- , RobustType1 oa_1, RobustType1 oa_2
- , RobustType2 ob_1, RobustType2 ob_2
- )
+ static inline typename Policy::return_type
+ relate_collinear(Segment1 const& a, Segment2 const& b,
+ RobustType1 oa_1, RobustType1 oa_2,
+ RobustType2 ob_1, RobustType2 ob_2)
{
// Calculate the ratios where a starts in b, b starts in a
// a1--------->a2 (2..7)
@@ -496,17 +574,16 @@ private:
/// Relate segments where one is degenerate
template
<
+ typename Policy,
typename RatioType,
typename DegenerateSegment,
typename RobustType1,
typename RobustType2
>
- static inline return_type relate_one_degenerate(
- DegenerateSegment const& degenerate_segment
- , RobustType1 d
- , RobustType2 s1, RobustType2 s2
- , bool a_degenerate
- )
+ static inline typename Policy::return_type
+ relate_one_degenerate(DegenerateSegment const& degenerate_segment,
+ RobustType1 d, RobustType2 s1, RobustType2 s2,
+ bool a_degenerate)
{
// Calculate the ratios where ds starts in s
// a1--------->a2 (2..6)
@@ -546,10 +623,10 @@ private:
namespace services
{
-template <typename Policy, typename CalculationType>
-struct default_strategy<cartesian_tag, Policy, CalculationType>
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
{
- typedef relate_cartesian_segments<Policy, CalculationType> type;
+ typedef cartesian_segments<CalculationType> type;
};
} // namespace services
@@ -558,6 +635,69 @@ struct default_strategy<cartesian_tag, Policy, CalculationType>
}} // namespace strategy::intersection
+namespace strategy
+{
+
+namespace within { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+}} // within::services
+
+namespace covered_by { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
+{
+ typedef strategy::intersection::cartesian_segments<> type;
+};
+
+}} // within::services
+
+} // strategy
+
}} // namespace boost::geometry
diff --git a/boost/geometry/strategies/cartesian/point_in_box.hpp b/boost/geometry/strategies/cartesian/point_in_box.hpp
index 227a98f2ad..1c14125a6d 100644
--- a/boost/geometry/strategies/cartesian/point_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_box.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015-2016.
-// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2017.
+// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -219,10 +219,10 @@ namespace within { namespace services
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::point_in_box<Point, Box> type;
@@ -232,10 +232,10 @@ struct default_strategy
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- spherical_tag, spherical_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::point_in_box<Point, Box> type;
@@ -252,10 +252,10 @@ namespace covered_by { namespace services
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- cartesian_tag, cartesian_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ cartesian_tag, cartesian_tag
>
{
typedef within::point_in_box
@@ -269,10 +269,10 @@ struct default_strategy
template <typename Point, typename Box>
struct default_strategy
<
+ Point, Box,
point_tag, box_tag,
- point_tag, areal_tag,
- spherical_tag, spherical_tag,
- Point, Box
+ pointlike_tag, areal_tag,
+ spherical_tag, spherical_tag
>
{
typedef within::point_in_box
diff --git a/boost/geometry/strategies/covered_by.hpp b/boost/geometry/strategies/covered_by.hpp
index a5aae7703b..363e34b68f 100644
--- a/boost/geometry/strategies/covered_by.hpp
+++ b/boost/geometry/strategies/covered_by.hpp
@@ -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 2017.
+// Modifications copyright (c) 2017, 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.
@@ -16,6 +21,12 @@
#include <boost/mpl/assert.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
namespace boost { namespace geometry
{
@@ -31,23 +42,39 @@ namespace services
/*!
\brief Traits class binding a covered_by determination strategy to a coordinate system
\ingroup covered_by
-\tparam TagContained tag (possibly casted) of point-type
-\tparam TagContained tag (possibly casted) of (possibly) containing type
-\tparam CsTagContained tag of coordinate system of point-type
-\tparam CsTagContaining tag of coordinate system of (possibly) containing type
-\tparam Geometry geometry-type of input (often point, or box)
+\tparam GeometryContained geometry-type of input (possibly) contained type
\tparam GeometryContaining geometry-type of input (possibly) containing type
+\tparam TagContained casted tag of (possibly) contained type
+\tparam TagContaining casted tag of (possibly) containing type
+\tparam CsTagContained tag of coordinate system of (possibly) contained type
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type
*/
template
<
- typename TagContained,
- typename TagContaining,
- typename CastedTagContained,
- typename CastedTagContaining,
- typename CsTagContained,
- typename CsTagContaining,
typename GeometryContained,
- typename GeometryContaining
+ typename GeometryContaining,
+ typename TagContained = typename tag<GeometryContained>::type,
+ typename TagContaining = typename tag<GeometryContaining>::type,
+ typename CastedTagContained = typename tag_cast
+ <
+ typename tag<GeometryContained>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CastedTagContaining = typename tag_cast
+ <
+ typename tag<GeometryContaining>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CsTagContained = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContained>::type>::type,
+ spherical_tag
+ >::type,
+ typename CsTagContaining = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContaining>::type>::type,
+ spherical_tag
+ >::type
>
struct default_strategy
{
diff --git a/boost/geometry/strategies/disjoint.hpp b/boost/geometry/strategies/disjoint.hpp
new file mode 100644
index 0000000000..f844cd86ad
--- /dev/null
+++ b/boost/geometry/strategies/disjoint.hpp
@@ -0,0 +1,90 @@
+// Boost.Geometry
+
+// Copyright (c) 2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_DISJOINT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DISJOINT_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/relate.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy { namespace disjoint
+{
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type,
+ int TopDim1 = geometry::topological_dimension<Geometry1>::value,
+ int TopDim2 = geometry::topological_dimension<Geometry2>::value
+>
+struct default_strategy
+ : relate::services::default_strategy
+ <
+ Geometry1, Geometry2
+ >
+{};
+
+template <typename Point, typename Box>
+struct default_strategy<Point, Box, point_tag, box_tag, 0, 2>
+ : strategy::covered_by::services::default_strategy<Point, Box>
+{};
+
+template <typename Box, typename Point>
+struct default_strategy<Box, Point, box_tag, point_tag, 2, 0>
+ : strategy::covered_by::services::default_strategy<Point, Box>
+{};
+
+template <typename MultiPoint, typename Box>
+struct default_strategy<MultiPoint, Box, multi_point_tag, box_tag, 0, 2>
+ : strategy::covered_by::services::default_strategy
+ <
+ typename point_type<MultiPoint>::type,
+ Box
+ >
+{};
+
+template <typename Box, typename MultiPoint>
+struct default_strategy<Box, MultiPoint, box_tag, multi_point_tag, 2, 0>
+ : strategy::covered_by::services::default_strategy
+ <
+ typename point_type<MultiPoint>::type,
+ Box
+ >
+{};
+
+template <typename Box1, typename Box2>
+struct default_strategy<Box1, Box2, box_tag, box_tag, 2, 2>
+{
+ // dummy strategy which will be ignored
+ typedef geometry::default_strategy type;
+};
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}}}} // namespace boost::geometry::strategy::disjoint
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DISJOINT_HPP
diff --git a/boost/geometry/strategies/envelope.hpp b/boost/geometry/strategies/envelope.hpp
new file mode 100644
index 0000000000..fde9c858a6
--- /dev/null
+++ b/boost/geometry/strategies/envelope.hpp
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_ENVELOPE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_ENVELOPE_HPP
+
+#include <boost/mpl/assert.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace envelope { namespace services
+{
+
+/*!
+\brief Traits class binding a default envelope strategy to a coordinate system
+\ingroup util
+\tparam CSTag tag of coordinate system
+\tparam CalculationType \tparam_calculation
+*/
+template <typename CSTag, typename CalculationType = void>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE
+ , (types<CSTag>)
+ );
+};
+
+}}} // namespace strategy::envelope::services
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_ENVELOPE_HPP
+
diff --git a/boost/geometry/strategies/geographic/area.hpp b/boost/geometry/strategies/geographic/area.hpp
new file mode 100644
index 0000000000..e1d3b09b5a
--- /dev/null
+++ b/boost/geometry/strategies/geographic/area.hpp
@@ -0,0 +1,216 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
+
+
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/area_formulas.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+#include <boost/math/special_functions/atanh.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area
+{
+
+/*!
+\brief Geographic area calculation
+\ingroup strategies
+\details Geographic area calculation by trapezoidal rule plus integral
+ approximation that gives the ellipsoidal correction
+\tparam PointOfSegment \tparam_segment_point
+\tparam FormulaPolicy Formula used to calculate azimuths
+\tparam SeriesOrder The order of approximation of the geodesic integral
+\tparam Spheroid The spheroid model
+\tparam CalculationType \tparam_calculation
+\author See
+- Danielsen JS, The area under the geodesic. Surv Rev 30(232): 61–66, 1989
+- Charles F.F Karney, Algorithms for geodesics, 2011 https://arxiv.org/pdf/1109.4448.pdf
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
+}
+*/
+template
+<
+ typename PointOfSegment,
+ typename FormulaPolicy = strategy::andoyer,
+ std::size_t SeriesOrder = strategy::default_order<FormulaPolicy>::value,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+ // Switch between two kinds of approximation(series in eps and n v.s.series in k ^ 2 and e'^2)
+ static const bool ExpandEpsN = true;
+ // LongSegment Enables special handling of long segments
+ static const bool LongSegment = false;
+
+ //Select default types in case they are not set
+
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename coordinate_type<PointOfSegment>::type,
+ double
+ >::type,
+ CalculationType
+ >::type CT;
+
+protected :
+ struct spheroid_constants
+ {
+ Spheroid m_spheroid;
+ CT const m_a2; // squared equatorial radius
+ CT const m_e2; // squared eccentricity
+ CT const m_ep2; // squared second eccentricity
+ CT const m_ep; // second eccentricity
+ CT const m_c2; // authalic radius
+
+ inline spheroid_constants(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ , m_a2(math::sqr(get_radius<0>(spheroid)))
+ , m_e2(formula::flattening<CT>(spheroid)
+ * (CT(2.0) - CT(formula::flattening<CT>(spheroid))))
+ , m_ep2(m_e2 / (CT(1.0) - m_e2))
+ , m_ep(math::sqrt(m_ep2))
+ , m_c2((m_a2 / CT(2.0)) +
+ ((math::sqr(get_radius<2>(spheroid)) * boost::math::atanh(math::sqrt(m_e2)))
+ / (CT(2.0) * math::sqrt(m_e2))))
+ {}
+ };
+
+ struct area_sums
+ {
+ CT m_excess_sum;
+ CT m_correction_sum;
+
+ // Keep track if encircles some pole
+ std::size_t m_crosses_prime_meridian;
+
+ inline area_sums()
+ : m_excess_sum(0)
+ , m_correction_sum(0)
+ , m_crosses_prime_meridian(0)
+ {}
+ inline CT area(spheroid_constants spheroid_const) const
+ {
+ CT result;
+
+ CT sum = spheroid_const.m_c2 * m_excess_sum
+ + spheroid_const.m_e2 * spheroid_const.m_a2 * m_correction_sum;
+
+ // If encircles some pole
+ if (m_crosses_prime_meridian % 2 == 1)
+ {
+ std::size_t times_crosses_prime_meridian
+ = 1 + (m_crosses_prime_meridian / 2);
+
+ result = CT(2.0)
+ * geometry::math::pi<CT>()
+ * spheroid_const.m_c2
+ * CT(times_crosses_prime_meridian)
+ - geometry::math::abs(sum);
+
+ if (geometry::math::sign<CT>(sum) == 1)
+ {
+ result = - result;
+ }
+
+ }
+ else
+ {
+ result = sum;
+ }
+
+ return result;
+ }
+ };
+
+public :
+ typedef CT return_type;
+ typedef PointOfSegment segment_point_type;
+ typedef area_sums state_type;
+
+ explicit inline geographic(Spheroid const& spheroid = Spheroid())
+ : m_spheroid_constants(spheroid)
+ {}
+
+ inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ area_sums& state) const
+ {
+
+ if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
+ {
+
+ typedef geometry::formula::area_formulas
+ <
+ CT, SeriesOrder, ExpandEpsN
+ > area_formulas;
+
+ typename area_formulas::return_type_ellipsoidal result =
+ area_formulas::template ellipsoidal<FormulaPolicy::template inverse>
+ (p1, p2, m_spheroid_constants);
+
+ state.m_excess_sum += result.spherical_term;
+ state.m_correction_sum += result.ellipsoidal_term;
+
+ // Keep track whenever a segment crosses the prime meridian
+ geometry::formula::area_formulas<CT>
+ ::crosses_prime_meridian(p1, p2, state);
+ }
+ }
+
+ inline return_type result(area_sums const& state) const
+ {
+ return state.area(m_spheroid_constants);
+ }
+
+private:
+ spheroid_constants m_spheroid_constants;
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+
+template <typename Point>
+struct default_strategy<geographic_tag, Point>
+{
+ typedef strategy::area::geographic<Point> type;
+};
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}
+
+}} // namespace strategy::area
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
diff --git a/boost/geometry/strategies/geographic/azimuth.hpp b/boost/geometry/strategies/geographic/azimuth.hpp
new file mode 100644
index 0000000000..47f59d1033
--- /dev/null
+++ b/boost/geometry/strategies/geographic/azimuth.hpp
@@ -0,0 +1,103 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP
+
+
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/strategies/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_void.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace azimuth
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+public :
+
+ typedef Spheroid model_type;
+
+ inline geographic()
+ : m_spheroid()
+ {}
+
+ explicit inline geographic(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ inline model_type const& model() const
+ {
+ return m_spheroid;
+ }
+
+ template <typename T>
+ inline void apply(T const& lon1_rad, T const& lat1_rad,
+ T const& lon2_rad, T const& lat2_rad,
+ T& a1, T& a2) const
+ {
+ typedef typename boost::mpl::if_
+ <
+ boost::is_void<CalculationType>, T, CalculationType
+ >::type calc_t;
+
+ typedef typename FormulaPolicy::template inverse<calc_t, false, true, true, false, false> inverse_type;
+ typedef typename inverse_type::result_type inverse_result;
+ inverse_result i_res = inverse_type::apply(calc_t(lon1_rad), calc_t(lat1_rad),
+ calc_t(lon2_rad), calc_t(lat2_rad),
+ m_spheroid);
+ a1 = i_res.azimuth;
+ a2 = i_res.reverse_azimuth;
+ }
+
+private :
+ Spheroid m_spheroid;
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<geographic_tag, CalculationType>
+{
+ typedef strategy::azimuth::geographic
+ <
+ strategy::andoyer,
+ srs::spheroid<double>,
+ CalculationType
+ > type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace strategy::azimuth
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/geographic/distance.hpp b/boost/geometry/strategies/geographic/distance.hpp
new file mode 100644
index 0000000000..d3656f449c
--- /dev/null
+++ b/boost/geometry/strategies/geographic/distance.hpp
@@ -0,0 +1,195 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014-2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// 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_GEOGRAPHIC_DISTANCE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/flattening.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+public :
+ template <typename Point1, typename Point2>
+ struct calculation_type
+ : promote_floating_point
+ <
+ typename select_calculation_type
+ <
+ Point1,
+ Point2,
+ CalculationType
+ >::type
+ >
+ {};
+
+ typedef Spheroid model_type;
+
+ inline geographic()
+ : m_spheroid()
+ {}
+
+ explicit inline geographic(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point1, typename Point2>
+ inline typename calculation_type<Point1, Point2>::type
+ apply(Point1 const& point1, Point2 const& point2) const
+ {
+ return FormulaPolicy::template inverse
+ <
+ typename calculation_type<Point1, Point2>::type,
+ true, false, false, false, false
+ >::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
+ get_as_radian<0>(point2), get_as_radian<1>(point2),
+ m_spheroid).distance;
+ }
+
+ inline Spheroid const& model() const
+ {
+ return m_spheroid;
+ }
+
+private :
+ Spheroid m_spheroid;
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType
+>
+struct tag<geographic<FormulaPolicy, Spheroid, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct return_type<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>
+ : geographic<FormulaPolicy, Spheroid, CalculationType>::template calculation_type<P1, P2>
+{};
+
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType
+>
+struct comparable_type<geographic<FormulaPolicy, Spheroid, CalculationType> >
+{
+ typedef geographic<FormulaPolicy, Spheroid, CalculationType> type;
+};
+
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType
+>
+struct get_comparable<geographic<FormulaPolicy, Spheroid, CalculationType> >
+{
+ static inline geographic<FormulaPolicy, Spheroid, CalculationType>
+ apply(geographic<FormulaPolicy, Spheroid, CalculationType> const& input)
+ {
+ return input;
+ }
+};
+
+template
+<
+ typename FormulaPolicy,
+ typename Spheroid,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct result_from_distance<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>
+{
+ template <typename T>
+ static inline typename return_type<geographic<FormulaPolicy, Spheroid, CalculationType>, P1, P2>::type
+ apply(geographic<FormulaPolicy, Spheroid, CalculationType> const& , T const& value)
+ {
+ return value;
+ }
+};
+
+
+template <typename Point1, typename Point2>
+struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
+{
+ typedef strategy::distance::geographic
+ <
+ strategy::andoyer,
+ srs::spheroid
+ <
+ typename select_coordinate_type<Point1, Point2>::type
+ >
+ > type;
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
diff --git a/boost/geometry/strategies/geographic/distance_andoyer.hpp b/boost/geometry/strategies/geographic/distance_andoyer.hpp
index 1946cd1090..d732951642 100644
--- a/boost/geometry/strategies/geographic/distance_andoyer.hpp
+++ b/boost/geometry/strategies/geographic/distance_andoyer.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -11,24 +11,12 @@
// 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_GEOGRAPHIC_ANDOYER_HPP
-#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
-#include <boost/geometry/core/coordinate_type.hpp>
-#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/core/radius.hpp>
-#include <boost/geometry/core/srs.hpp>
-
-#include <boost/geometry/algorithms/detail/flattening.hpp>
-
-#include <boost/geometry/formulas/andoyer_inverse.hpp>
-
-#include <boost/geometry/strategies/distance.hpp>
-
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
namespace boost { namespace geometry
@@ -57,55 +45,28 @@ are about the same as Vincenty. In my (Barend's) testcases the results didn't di
*/
template
<
- typename Spheroid,
+ typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class andoyer
+ : public strategy::distance::geographic
+ <
+ strategy::andoyer, Spheroid, CalculationType
+ >
{
-public :
- template <typename Point1, typename Point2>
- struct calculation_type
- : promote_floating_point
- <
- typename select_calculation_type
- <
- Point1,
- Point2,
- CalculationType
- >::type
- >
- {};
-
- typedef Spheroid model_type;
+ typedef strategy::distance::geographic
+ <
+ strategy::andoyer, Spheroid, CalculationType
+ > base_type;
+public :
inline andoyer()
- : m_spheroid()
+ : base_type()
{}
explicit inline andoyer(Spheroid const& spheroid)
- : m_spheroid(spheroid)
+ : base_type(spheroid)
{}
-
- template <typename Point1, typename Point2>
- inline typename calculation_type<Point1, Point2>::type
- apply(Point1 const& point1, Point2 const& point2) const
- {
- return geometry::formula::andoyer_inverse
- <
- typename calculation_type<Point1, Point2>::type,
- true, false
- >::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
- get_as_radian<0>(point2), get_as_radian<1>(point2),
- m_spheroid).distance;
- }
-
- inline Spheroid const& model() const
- {
- return m_spheroid;
- }
-
-private :
- Spheroid m_spheroid;
};
@@ -154,19 +115,6 @@ struct result_from_distance<andoyer<Spheroid, CalculationType>, P1, P2>
};
-template <typename Point1, typename Point2>
-struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
-{
- typedef strategy::distance::andoyer
- <
- srs::spheroid
- <
- typename select_coordinate_type<Point1, Point2>::type
- >
- > type;
-};
-
-
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
@@ -177,4 +125,4 @@ struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, ge
}} // namespace boost::geometry
-#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
diff --git a/boost/geometry/strategies/geographic/distance_thomas.hpp b/boost/geometry/strategies/geographic/distance_thomas.hpp
index 39e0ecfa6f..490920c778 100644
--- a/boost/geometry/strategies/geographic/distance_thomas.hpp
+++ b/boost/geometry/strategies/geographic/distance_thomas.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015, 2016.
-// Modifications copyright (c) 2015-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2017.
+// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,15 +15,9 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_THOMAS_HPP
-#include <boost/geometry/core/coordinate_type.hpp>
-#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
-#include <boost/geometry/strategies/distance.hpp>
-
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
-
-#include <boost/geometry/formulas/thomas_inverse.hpp>
namespace boost { namespace geometry
{
@@ -45,57 +39,28 @@ namespace strategy { namespace distance
*/
template
<
- typename Spheroid,
+ typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class thomas
+ : public strategy::distance::geographic
+ <
+ strategy::thomas, Spheroid, CalculationType
+ >
{
-public :
- template <typename Point1, typename Point2>
- struct calculation_type
- : promote_floating_point
- <
- typename select_calculation_type
- <
- Point1,
- Point2,
- CalculationType
- >::type
- >
- {};
-
- typedef Spheroid model_type;
+ typedef strategy::distance::geographic
+ <
+ strategy::thomas, Spheroid, CalculationType
+ > base_type;
+public :
inline thomas()
- : m_spheroid()
+ : base_type()
{}
explicit inline thomas(Spheroid const& spheroid)
- : m_spheroid(spheroid)
+ : base_type(spheroid)
{}
-
- template <typename Point1, typename Point2>
- inline typename calculation_type<Point1, Point2>::type
- apply(Point1 const& point1, Point2 const& point2) const
- {
- return geometry::formula::thomas_inverse
- <
- typename calculation_type<Point1, Point2>::type,
- true, false
- >::apply(get_as_radian<0>(point1),
- get_as_radian<1>(point1),
- get_as_radian<0>(point2),
- get_as_radian<1>(point2),
- m_spheroid).distance;
- }
-
- inline Spheroid const& model() const
- {
- return m_spheroid;
- }
-
-private :
- Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/boost/geometry/strategies/geographic/distance_vincenty.hpp b/boost/geometry/strategies/geographic/distance_vincenty.hpp
index e79e9aeb46..41146db9ff 100644
--- a/boost/geometry/strategies/geographic/distance_vincenty.hpp
+++ b/boost/geometry/strategies/geographic/distance_vincenty.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,15 +15,9 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP
-#include <boost/geometry/core/coordinate_type.hpp>
-#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
-#include <boost/geometry/strategies/distance.hpp>
-
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
-
-#include <boost/geometry/formulas/vincenty_inverse.hpp>
namespace boost { namespace geometry
{
@@ -47,57 +41,28 @@ namespace strategy { namespace distance
*/
template
<
- typename Spheroid,
+ typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class vincenty
+ : public strategy::distance::geographic
+ <
+ strategy::vincenty, Spheroid, CalculationType
+ >
{
-public :
- template <typename Point1, typename Point2>
- struct calculation_type
- : promote_floating_point
- <
- typename select_calculation_type
- <
- Point1,
- Point2,
- CalculationType
- >::type
- >
- {};
-
- typedef Spheroid model_type;
+ typedef strategy::distance::geographic
+ <
+ strategy::vincenty, Spheroid, CalculationType
+ > base_type;
+public:
inline vincenty()
- : m_spheroid()
+ : base_type()
{}
explicit inline vincenty(Spheroid const& spheroid)
- : m_spheroid(spheroid)
+ : base_type(spheroid)
{}
-
- template <typename Point1, typename Point2>
- inline typename calculation_type<Point1, Point2>::type
- apply(Point1 const& point1, Point2 const& point2) const
- {
- return geometry::formula::vincenty_inverse
- <
- typename calculation_type<Point1, Point2>::type,
- true, false
- >::apply(get_as_radian<0>(point1),
- get_as_radian<1>(point1),
- get_as_radian<0>(point2),
- get_as_radian<1>(point2),
- m_spheroid).distance;
- }
-
- inline Spheroid const& model() const
- {
- return m_spheroid;
- }
-
-private :
- Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/boost/geometry/strategies/geographic/envelope_segment.hpp b/boost/geometry/strategies/geographic/envelope_segment.hpp
new file mode 100644
index 0000000000..3641b39428
--- /dev/null
+++ b/boost/geometry/strategies/geographic/envelope_segment.hpp
@@ -0,0 +1,104 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
+
+
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/geographic/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = geometry::srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_segment
+{
+public:
+ typedef Spheroid model_type;
+
+ inline geographic_segment()
+ : m_spheroid()
+ {}
+
+ explicit inline geographic_segment(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point1, typename Point2, typename Box>
+ inline void apply(Point1 const& point1, Point2 const& point2, Box& box) const
+ {
+ Point1 p1_normalized = detail::return_normalized<Point1>(point1);
+ Point2 p2_normalized = detail::return_normalized<Point2>(point2);
+
+ geometry::strategy::azimuth::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > azimuth_geographic(m_spheroid);
+
+ typedef typename coordinate_system<Point1>::type::units units_type;
+
+ detail::envelope::envelope_segment_impl
+ <
+ geographic_tag
+ >::template apply<units_type>(geometry::get<0>(p1_normalized),
+ geometry::get<1>(p1_normalized),
+ geometry::get<0>(p2_normalized),
+ geometry::get<1>(p2_normalized),
+ box,
+ azimuth_geographic);
+
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<geographic_tag, CalculationType>
+{
+ typedef strategy::envelope::geographic_segment
+ <
+ strategy::andoyer,
+ srs::spheroid<double>,
+ CalculationType
+ > type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
diff --git a/boost/geometry/strategies/geographic/intersection.hpp b/boost/geometry/strategies/geographic/intersection.hpp
new file mode 100644
index 0000000000..1708c274c0
--- /dev/null
+++ b/boost/geometry/strategies/geographic/intersection.hpp
@@ -0,0 +1,897 @@
+// Boost.Geometry
+
+// Copyright (c) 2016-2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/detail/assign_values.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/algorithms/detail/recalculate.hpp>
+
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/sjoberg_intersection.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>
+
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>
+
+#include <boost/geometry/strategies/geographic/area.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace intersection
+{
+
+// CONSIDER: Improvement of the robustness/accuracy/repeatability by
+// moving all segments to 0 longitude
+// picking latitudes closer to 0
+// etc.
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ unsigned int Order = strategy::default_order<FormulaPolicy>::value,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct geographic_segments
+{
+ typedef side::geographic
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > side_strategy_type;
+
+ inline side_strategy_type get_side_strategy() const
+ {
+ return side_strategy_type(m_spheroid);
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ struct point_in_geometry_strategy
+ {
+ typedef strategy::within::winding
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ side_strategy_type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry1, typename Geometry2>
+ inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
+ get_point_in_geometry_strategy() const
+ {
+ typedef typename point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+ return strategy_type(get_side_strategy());
+ }
+
+ template <typename Geometry>
+ struct area_strategy
+ {
+ typedef area::geographic
+ <
+ typename point_type<Geometry>::type,
+ FormulaPolicy,
+ Order,
+ Spheroid,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ inline typename area_strategy<Geometry>::type get_area_strategy() const
+ {
+ typedef typename area_strategy<Geometry>::type strategy_type;
+ return strategy_type(m_spheroid);
+ }
+
+ template <typename Geometry>
+ struct distance_strategy
+ {
+ typedef distance::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ inline typename distance_strategy<Geometry>::type get_distance_strategy() const
+ {
+ typedef typename distance_strategy<Geometry>::type strategy_type;
+ return strategy_type(m_spheroid);
+ }
+
+ enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
+
+ template <typename CoordinateType, typename SegmentRatio>
+ struct segment_intersection_info
+ {
+ typedef typename select_most_precise
+ <
+ CoordinateType, double
+ >::type promoted_type;
+
+ promoted_type comparable_length_a() const
+ {
+ return robust_ra.denominator();
+ }
+
+ promoted_type comparable_length_b() const
+ {
+ return robust_rb.denominator();
+ }
+
+ template <typename Point, typename Segment1, typename Segment2>
+ void assign_a(Point& point, Segment1 const& a, Segment2 const& b) const
+ {
+ assign(point, a, b);
+ }
+ template <typename Point, typename Segment1, typename Segment2>
+ void assign_b(Point& point, Segment1 const& a, Segment2 const& b) const
+ {
+ assign(point, a, b);
+ }
+
+ template <typename Point, typename Segment1, typename Segment2>
+ void assign(Point& point, Segment1 const& a, Segment2 const& b) const
+ {
+ if (ip_flag == ipi_inters)
+ {
+ // TODO: assign the rest of coordinates
+ set_from_radian<0>(point, lon);
+ set_from_radian<1>(point, lat);
+ }
+ else if (ip_flag == ipi_at_a1)
+ {
+ detail::assign_point_from_index<0>(a, point);
+ }
+ else if (ip_flag == ipi_at_a2)
+ {
+ detail::assign_point_from_index<1>(a, point);
+ }
+ else if (ip_flag == ipi_at_b1)
+ {
+ detail::assign_point_from_index<0>(b, point);
+ }
+ else // ip_flag == ipi_at_b2
+ {
+ detail::assign_point_from_index<1>(b, point);
+ }
+ }
+
+ CoordinateType lon;
+ CoordinateType lat;
+ SegmentRatio robust_ra;
+ SegmentRatio robust_rb;
+ intersection_point_flag ip_flag;
+ };
+
+ explicit geographic_segments(Spheroid const& spheroid = Spheroid())
+ : m_spheroid(spheroid)
+ {}
+
+ // Relate segments a and b
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy
+ >
+ inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
+ Policy const& policy,
+ RobustPolicy const& robust_policy) const
+ {
+ typedef typename point_type<Segment1>::type point1_t;
+ typedef typename point_type<Segment2>::type point2_t;
+ point1_t a1, a2;
+ point2_t b1, b2;
+
+ detail::assign_point_from_index<0>(a, a1);
+ detail::assign_point_from_index<1>(a, a2);
+ detail::assign_point_from_index<0>(b, b1);
+ detail::assign_point_from_index<1>(b, b2);
+
+ return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
+ }
+
+ // Relate segments a and b
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy,
+ typename Point1,
+ typename Point2
+ >
+ inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
+ Policy const&, RobustPolicy const&,
+ Point1 a1, Point1 a2, Point2 b1, Point2 b2) const
+ {
+ bool is_a_reversed = get<1>(a1) > get<1>(a2);
+ bool is_b_reversed = get<1>(b1) > get<1>(b2);
+
+ if (is_a_reversed)
+ {
+ std::swap(a1, a2);
+ }
+
+ if (is_b_reversed)
+ {
+ std::swap(b1, b2);
+ }
+
+ return apply<Policy>(a, b, a1, a2, b1, b2, is_a_reversed, is_b_reversed);
+ }
+
+private:
+ // Relate segments a and b
+ template
+ <
+ typename Policy,
+ typename Segment1,
+ typename Segment2,
+ typename Point1,
+ typename Point2
+ >
+ inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
+ Point1 const& a1, Point1 const& a2,
+ Point2 const& b1, Point2 const& b2,
+ bool is_a_reversed, bool is_b_reversed) const
+ {
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
+
+ typedef typename select_calculation_type
+ <Segment1, Segment2, CalculationType>::type calc_t;
+
+ // normalized spheroid
+ srs::spheroid<calc_t> spheroid = normalized_spheroid<calc_t>(m_spheroid);
+
+ // TODO: check only 2 first coordinates here?
+ using geometry::detail::equals::equals_point_point;
+ bool a_is_point = equals_point_point(a1, a2);
+ bool b_is_point = equals_point_point(b1, b2);
+
+ if(a_is_point && b_is_point)
+ {
+ return equals_point_point(a1, b2)
+ ? Policy::degenerate(a, true)
+ : Policy::disjoint()
+ ;
+ }
+
+ calc_t const a1_lon = get_as_radian<0>(a1);
+ calc_t const a1_lat = get_as_radian<1>(a1);
+ calc_t const a2_lon = get_as_radian<0>(a2);
+ calc_t const a2_lat = get_as_radian<1>(a2);
+ calc_t const b1_lon = get_as_radian<0>(b1);
+ calc_t const b1_lat = get_as_radian<1>(b1);
+ calc_t const b2_lon = get_as_radian<0>(b2);
+ calc_t const b2_lat = get_as_radian<1>(b2);
+
+ side_info sides;
+
+ // NOTE: potential optimization, don't calculate distance at this point
+ // this would require to reimplement inverse strategy to allow
+ // calculation of distance if needed, probably also storing intermediate
+ // results somehow inside an object.
+ typedef typename FormulaPolicy::template inverse<calc_t, true, true, false, false, false> inverse_dist_azi;
+ typedef typename inverse_dist_azi::result_type inverse_result;
+
+ // TODO: no need to call inverse formula if we know that the points are equal
+ // distance can be set to 0 in this case and azimuth may be not calculated
+ bool const is_equal_a1_b1 = equals_point_point(a1, b1);
+ bool const is_equal_a2_b1 = equals_point_point(a2, b1);
+
+ inverse_result res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
+ inverse_result res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
+ inverse_result res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
+ sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
+ is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
+ if (sides.same<0>())
+ {
+ // Both points are at the same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+
+ bool const is_equal_a1_b2 = equals_point_point(a1, b2);
+
+ inverse_result res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
+ inverse_result res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
+ inverse_result res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
+ sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
+ is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
+ if (sides.same<1>())
+ {
+ // Both points are at the same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+
+ // NOTE: at this point the segments may still be disjoint
+ // NOTE: at this point one of the segments may be degenerated
+
+ bool collinear = sides.collinear();
+
+ if (! collinear)
+ {
+ // WARNING: the side strategy doesn't have the info about the other
+ // segment so it may return results inconsistent with this intersection
+ // strategy, as it checks both segments for consistency
+
+ if (sides.get<0, 0>() == 0 && sides.get<0, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<1>(0, 0);
+ }
+ else if (sides.get<1, 0>() == 0 && sides.get<1, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<0>(0, 0);
+ }
+ }
+
+ if (collinear)
+ {
+ if (a_is_point)
+ {
+ return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, is_b_reversed);
+ }
+ else if (b_is_point)
+ {
+ return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, is_a_reversed);
+ }
+ else
+ {
+ calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2;
+ calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2;
+ // use shorter segment
+ if (res_a1_a2.distance <= res_b1_b2.distance)
+ {
+ calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, dist_a1_a2, dist_a1_b1);
+ calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, dist_a1_a2, dist_a1_b2);
+ dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
+ dist_b1_a1 = -dist_a1_b1;
+ dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
+ }
+ else
+ {
+ calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, dist_b1_b2, dist_b1_a1);
+ calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, dist_b1_b2, dist_b1_a2);
+ dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
+ dist_a1_b1 = -dist_b1_a1;
+ dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
+ }
+
+ // NOTE: this is probably not needed
+ calc_t const c0 = 0;
+ int a1_on_b = position_value(c0, dist_a1_b1, dist_a1_b2);
+ int a2_on_b = position_value(dist_a1_a2, dist_a1_b1, dist_a1_b2);
+ int b1_on_a = position_value(c0, dist_b1_a1, dist_b1_a2);
+ int b2_on_a = position_value(dist_b1_b2, dist_b1_a1, dist_b1_a2);
+
+ if ((a1_on_b < 1 && a2_on_b < 1) || (a1_on_b > 3 && a2_on_b > 3))
+ {
+ return Policy::disjoint();
+ }
+
+ if (a1_on_b == 1)
+ {
+ dist_b1_a1 = 0;
+ dist_a1_b1 = 0;
+ }
+ else if (a1_on_b == 3)
+ {
+ dist_b1_a1 = dist_b1_b2;
+ dist_a1_b2 = 0;
+ }
+
+ if (a2_on_b == 1)
+ {
+ dist_b1_a2 = 0;
+ dist_a1_b1 = dist_a1_a2;
+ }
+ else if (a2_on_b == 3)
+ {
+ dist_b1_a2 = dist_b1_b2;
+ dist_a1_b2 = dist_a1_a2;
+ }
+
+ bool opposite = ! same_direction(res_a1_a2.azimuth, res_b1_b2.azimuth);
+
+ // NOTE: If segment was reversed opposite, positions and segment ratios has to be altered
+ if (is_a_reversed)
+ {
+ // opposite
+ opposite = ! opposite;
+ // positions
+ std::swap(a1_on_b, a2_on_b);
+ b1_on_a = 4 - b1_on_a;
+ b2_on_a = 4 - b2_on_a;
+ // distances for ratios
+ std::swap(dist_b1_a1, dist_b1_a2);
+ dist_a1_b1 = dist_a1_a2 - dist_a1_b1;
+ dist_a1_b2 = dist_a1_a2 - dist_a1_b2;
+ }
+ if (is_b_reversed)
+ {
+ // opposite
+ opposite = ! opposite;
+ // positions
+ a1_on_b = 4 - a1_on_b;
+ a2_on_b = 4 - a2_on_b;
+ std::swap(b1_on_a, b2_on_a);
+ // distances for ratios
+ dist_b1_a1 = dist_b1_b2 - dist_b1_a1;
+ dist_b1_a2 = dist_b1_b2 - dist_b1_a2;
+ std::swap(dist_a1_b1, dist_a1_b2);
+ }
+
+ segment_ratio<calc_t> ra_from(dist_b1_a1, dist_b1_b2);
+ segment_ratio<calc_t> ra_to(dist_b1_a2, dist_b1_b2);
+ segment_ratio<calc_t> rb_from(dist_a1_b1, dist_a1_a2);
+ segment_ratio<calc_t> rb_to(dist_a1_b2, dist_a1_a2);
+
+ return Policy::segments_collinear(a, b, opposite,
+ a1_on_b, a2_on_b, b1_on_a, b2_on_a,
+ ra_from, ra_to, rb_from, rb_to);
+ }
+ }
+ else // crossing or touching
+ {
+ if (a_is_point || b_is_point)
+ {
+ return Policy::disjoint();
+ }
+
+ calc_t lon = 0, lat = 0;
+ intersection_point_flag ip_flag;
+ calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
+ if (calculate_ip_data(a1, a2, b1, b2,
+ a1_lon, a1_lat, a2_lon, a2_lat,
+ b1_lon, b1_lat, b2_lon, b2_lat,
+ res_a1_a2, res_a1_b1, res_a1_b2,
+ res_b1_b2, res_b1_a1, res_b1_a2,
+ sides, spheroid,
+ lon, lat,
+ dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1,
+ ip_flag))
+ {
+ // NOTE: If segment was reversed sides and segment ratios has to be altered
+ if (is_a_reversed)
+ {
+ // sides
+ sides_reverse_segment<0>(sides);
+ // distance for ratio
+ dist_a1_i1 = dist_a1_a2 - dist_a1_i1;
+ // ip flag
+ ip_flag_reverse_segment(ip_flag, ipi_at_a1, ipi_at_a2);
+ }
+ if (is_b_reversed)
+ {
+ // sides
+ sides_reverse_segment<1>(sides);
+ // distance for ratio
+ dist_b1_i1 = dist_b1_b2 - dist_b1_i1;
+ // ip flag
+ ip_flag_reverse_segment(ip_flag, ipi_at_b1, ipi_at_b2);
+ }
+
+ // intersects
+ segment_intersection_info
+ <
+ calc_t,
+ segment_ratio<calc_t>
+ > sinfo;
+
+ sinfo.lon = lon;
+ sinfo.lat = lat;
+ sinfo.robust_ra.assign(dist_a1_i1, dist_a1_a2);
+ sinfo.robust_rb.assign(dist_b1_i1, dist_b1_b2);
+ sinfo.ip_flag = ip_flag;
+
+ return Policy::segments_crosses(sides, sinfo, a, b);
+ }
+ else
+ {
+ return Policy::disjoint();
+ }
+ }
+ }
+
+ template <typename Policy, typename CalcT, typename Segment, typename Point1, typename Point2, typename ResultInverse>
+ static inline typename Policy::return_type
+ collinear_one_degenerated(Segment const& segment, bool degenerated_a,
+ Point1 const& a1, Point1 const& a2,
+ Point2 const& b1, Point2 const& b2,
+ ResultInverse const& res_a1_a2,
+ ResultInverse const& res_a1_bi,
+ bool is_other_reversed)
+ {
+ CalcT dist_1_2, dist_1_o;
+ if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_bi, dist_1_2, dist_1_o))
+ {
+ return Policy::disjoint();
+ }
+
+ // NOTE: If segment was reversed segment ratio has to be altered
+ if (is_other_reversed)
+ {
+ // distance for ratio
+ dist_1_o = dist_1_2 - dist_1_o;
+ }
+
+ return Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
+ }
+
+ // TODO: instead of checks below test bi against a1 and a2 here?
+ // in order to make this independent from is_near()
+ template <typename Point1, typename Point2, typename ResultInverse, typename CalcT>
+ static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
+ Point2 const& b1, Point2 const& b2, // in
+ ResultInverse const& res_a1_a2, // in
+ ResultInverse const& res_a1_bi, // in
+ CalcT& dist_a1_a2, CalcT& dist_a1_bi) // out
+ {
+ dist_a1_a2 = res_a1_a2.distance;
+
+ dist_a1_bi = res_a1_bi.distance;
+ if (! same_direction(res_a1_bi.azimuth, res_a1_a2.azimuth))
+ {
+ dist_a1_bi = -dist_a1_bi;
+ }
+
+ // if i1 is close to a1 and b1 or b2 is equal to a1
+ if (is_endpoint_equal(dist_a1_bi, a1, b1, b2))
+ {
+ dist_a1_bi = 0;
+ return true;
+ }
+ // or i1 is close to a2 and b1 or b2 is equal to a2
+ else if (is_endpoint_equal(dist_a1_a2 - dist_a1_bi, a2, b1, b2))
+ {
+ dist_a1_bi = dist_a1_a2;
+ return true;
+ }
+
+ // or i1 is on b
+ return segment_ratio<CalcT>(dist_a1_bi, dist_a1_a2).on_segment();
+ }
+
+ template <typename Point1, typename Point2, typename CalcT, typename ResultInverse, typename Spheroid_>
+ static inline bool calculate_ip_data(Point1 const& a1, Point1 const& a2, // in
+ Point2 const& b1, Point2 const& b2, // in
+ CalcT const& a1_lon, CalcT const& a1_lat, // in
+ CalcT const& a2_lon, CalcT const& a2_lat, // in
+ CalcT const& b1_lon, CalcT const& b1_lat, // in
+ CalcT const& b2_lon, CalcT const& b2_lat, // in
+ ResultInverse const& res_a1_a2, // in
+ ResultInverse const& res_a1_b1, // in
+ ResultInverse const& res_a1_b2, // in
+ ResultInverse const& res_b1_b2, // in
+ ResultInverse const& res_b1_a1, // in
+ ResultInverse const& res_b1_a2, // in
+ side_info const& sides, // in
+ Spheroid_ const& spheroid, // in
+ CalcT & lon, CalcT & lat, // out
+ CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out
+ CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out
+ intersection_point_flag& ip_flag) // out
+ {
+ dist_a1_a2 = res_a1_a2.distance;
+ dist_b1_b2 = res_b1_b2.distance;
+
+ // assign the IP if some endpoints overlap
+ using geometry::detail::equals::equals_point_point;
+ if (equals_point_point(a1, b1))
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_a1;
+ return true;
+ }
+ else if (equals_point_point(a1, b2))
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ dist_b1_ip = dist_b1_b2;
+ ip_flag = ipi_at_a1;
+ return true;
+ }
+ else if (equals_point_point(a2, b1))
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_a2;
+ return true;
+ }
+ else if (equals_point_point(a2, b2))
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = dist_b1_b2;
+ ip_flag = ipi_at_a2;
+ return true;
+ }
+
+ // at this point we know that the endpoints doesn't overlap
+ // check cases when an endpoint lies on the other geodesic
+ if (sides.template get<0, 0>() == 0) // a1 wrt b
+ {
+ if (res_b1_a1.distance <= res_b1_b2.distance
+ && same_direction(res_b1_a1.azimuth, res_b1_b2.azimuth))
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ dist_b1_ip = res_b1_a1.distance;
+ ip_flag = ipi_at_a1;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (sides.template get<0, 1>() == 0) // a2 wrt b
+ {
+ if (res_b1_a2.distance <= res_b1_b2.distance
+ && same_direction(res_b1_a2.azimuth, res_b1_b2.azimuth))
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = res_a1_a2.distance;
+ dist_b1_ip = res_b1_a2.distance;
+ ip_flag = ipi_at_a2;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (sides.template get<1, 0>() == 0) // b1 wrt a
+ {
+ if (res_a1_b1.distance <= res_a1_a2.distance
+ && same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth))
+ {
+ lon = b1_lon;
+ lat = b1_lat;
+ dist_a1_ip = res_a1_b1.distance;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_b1;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (sides.template get<1, 1>() == 0) // b2 wrt a
+ {
+ if (res_a1_b2.distance <= res_a1_a2.distance
+ && same_direction(res_a1_b2.azimuth, res_a1_a2.azimuth))
+ {
+ lon = b2_lon;
+ lat = b2_lat;
+ dist_a1_ip = res_a1_b2.distance;
+ dist_b1_ip = res_b1_b2.distance;
+ ip_flag = ipi_at_b2;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // At this point neither the endpoints overlaps
+ // nor any andpoint lies on the other geodesic
+ // So the endpoints should lie on the opposite sides of both geodesics
+
+ bool const ok = formula::sjoberg_intersection<CalcT, FormulaPolicy::template inverse, Order>
+ ::apply(a1_lon, a1_lat, a2_lon, a2_lat, res_a1_a2.azimuth,
+ b1_lon, b1_lat, b2_lon, b2_lat, res_b1_b2.azimuth,
+ lon, lat, spheroid);
+
+ if (! ok)
+ {
+ return false;
+ }
+
+ typedef typename FormulaPolicy::template inverse<CalcT, true, true, false, false, false> inverse_dist_azi;
+ typedef typename inverse_dist_azi::result_type inverse_result;
+
+ inverse_result const res_a1_ip = inverse_dist_azi::apply(a1_lon, a1_lat, lon, lat, spheroid);
+ dist_a1_ip = res_a1_ip.distance;
+ if (! same_direction(res_a1_ip.azimuth, res_a1_a2.azimuth))
+ {
+ dist_a1_ip = -dist_a1_ip;
+ }
+
+ bool is_on_a = segment_ratio<CalcT>(dist_a1_ip, dist_a1_a2).on_segment();
+ // NOTE: not fully consistent with equals_point_point() since radians are always used.
+ bool is_on_a1 = math::equals(lon, a1_lon) && math::equals(lat, a1_lat);
+ bool is_on_a2 = math::equals(lon, a2_lon) && math::equals(lat, a2_lat);
+
+ if (! (is_on_a || is_on_a1 || is_on_a2))
+ {
+ return false;
+ }
+
+ inverse_result const res_b1_ip = inverse_dist_azi::apply(b1_lon, b1_lat, lon, lat, spheroid);
+ dist_b1_ip = res_b1_ip.distance;
+ if (! same_direction(res_b1_ip.azimuth, res_b1_b2.azimuth))
+ {
+ dist_b1_ip = -dist_b1_ip;
+ }
+
+ bool is_on_b = segment_ratio<CalcT>(dist_b1_ip, dist_b1_b2).on_segment();
+ // NOTE: not fully consistent with equals_point_point() since radians are always used.
+ bool is_on_b1 = math::equals(lon, b1_lon) && math::equals(lat, b1_lat);
+ bool is_on_b2 = math::equals(lon, b2_lon) && math::equals(lat, b2_lat);
+
+ if (! (is_on_b || is_on_b1 || is_on_b2))
+ {
+ return false;
+ }
+
+ ip_flag = ipi_inters;
+
+ if (is_on_b1)
+ {
+ lon = b1_lon;
+ lat = b1_lat;
+ dist_b1_ip = 0;
+ ip_flag = ipi_at_b1;
+ }
+ else if (is_on_b2)
+ {
+ lon = b2_lon;
+ lat = b2_lat;
+ dist_b1_ip = res_b1_b2.distance;
+ ip_flag = ipi_at_b2;
+ }
+
+ if (is_on_a1)
+ {
+ lon = a1_lon;
+ lat = a1_lat;
+ dist_a1_ip = 0;
+ ip_flag = ipi_at_a1;
+ }
+ else if (is_on_a2)
+ {
+ lon = a2_lon;
+ lat = a2_lat;
+ dist_a1_ip = res_a1_a2.distance;
+ ip_flag = ipi_at_a2;
+ }
+
+ return true;
+ }
+
+ template <typename CalcT, typename P1, typename P2>
+ static inline bool is_endpoint_equal(CalcT const& dist,
+ P1 const& ai, P2 const& b1, P2 const& b2)
+ {
+ using geometry::detail::equals::equals_point_point;
+ return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
+ }
+
+ template <typename CalcT>
+ static inline bool is_near(CalcT const& dist)
+ {
+ // NOTE: This strongly depends on the Inverse method
+ CalcT const small_number = CalcT(boost::is_same<CalcT, float>::value ? 0.0001 : 0.00000001);
+ return math::abs(dist) <= small_number;
+ }
+
+ template <typename ProjCoord1, typename ProjCoord2>
+ static inline int position_value(ProjCoord1 const& ca1,
+ ProjCoord2 const& cb1,
+ ProjCoord2 const& cb2)
+ {
+ // S1x 0 1 2 3 4
+ // S2 |---------->
+ return math::equals(ca1, cb1) ? 1
+ : math::equals(ca1, cb2) ? 3
+ : cb1 < cb2 ?
+ ( ca1 < cb1 ? 0
+ : ca1 > cb2 ? 4
+ : 2 )
+ : ( ca1 > cb1 ? 0
+ : ca1 < cb2 ? 4
+ : 2 );
+ }
+
+ template <typename CalcT>
+ static inline bool same_direction(CalcT const& azimuth1, CalcT const& azimuth2)
+ {
+ // distance between two angles normalized to (-180, 180]
+ CalcT const angle_diff = math::longitude_distance_signed<radian>(azimuth1, azimuth2);
+ return math::abs(angle_diff) <= math::half_pi<CalcT>();
+ }
+
+ template <int Which>
+ static inline void sides_reverse_segment(side_info & sides)
+ {
+ // names assuming segment A is reversed (Which == 0)
+ int a1_wrt_b = sides.template get<Which, 0>();
+ int a2_wrt_b = sides.template get<Which, 1>();
+ std::swap(a1_wrt_b, a2_wrt_b);
+ sides.template set<Which>(a1_wrt_b, a2_wrt_b);
+ int b1_wrt_a = sides.template get<1 - Which, 0>();
+ int b2_wrt_a = sides.template get<1 - Which, 1>();
+ sides.template set<1 - Which>(-b1_wrt_a, -b2_wrt_a);
+ }
+
+ static inline void ip_flag_reverse_segment(intersection_point_flag & ip_flag,
+ intersection_point_flag const& ipi_at_p1,
+ intersection_point_flag const& ipi_at_p2)
+ {
+ ip_flag = ip_flag == ipi_at_p1 ? ipi_at_p2 :
+ ip_flag == ipi_at_p2 ? ipi_at_p1 :
+ ip_flag;
+ }
+
+ template <typename CalcT, typename SpheroidT>
+ static inline srs::spheroid<CalcT> normalized_spheroid(SpheroidT const& spheroid)
+ {
+ return srs::spheroid<CalcT>(CalcT(1),
+ CalcT(get_radius<2>(spheroid)) // b/a
+ / CalcT(get_radius<0>(spheroid)));
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+
+}} // namespace strategy::intersection
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
diff --git a/boost/geometry/strategies/geographic/intersection_elliptic.hpp b/boost/geometry/strategies/geographic/intersection_elliptic.hpp
new file mode 100644
index 0000000000..76e9940fe3
--- /dev/null
+++ b/boost/geometry/strategies/geographic/intersection_elliptic.hpp
@@ -0,0 +1,243 @@
+// Boost.Geometry
+
+// Copyright (c) 2016-2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP
+
+
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/geographic.hpp>
+
+#include <boost/geometry/strategies/spherical/intersection.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace intersection
+{
+
+template <typename Spheroid>
+struct great_elliptic_segments_calc_policy
+ : spherical_segments_calc_policy
+{
+ explicit great_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid())
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point, typename Point3d>
+ Point from_cart3d(Point3d const& point_3d) const
+ {
+ return formula::cart3d_to_geo<Point>(point_3d, m_spheroid);
+ }
+
+ template <typename Point3d, typename Point>
+ Point3d to_cart3d(Point const& point) const
+ {
+ return formula::geo_to_cart3d<Point3d>(point, m_spheroid);
+ }
+
+ // relate_xxx_calc_policy must live londer than plane because it contains
+ // Spheroid object and plane keeps the reference to that object.
+ template <typename Point3d>
+ struct plane
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // not normalized
+ plane(Point3d const& p1, Point3d const& p2)
+ : normal(cross_product(p1, p2))
+ {}
+
+ int side_value(Point3d const& pt) const
+ {
+ return formula::sph_side_value(normal, pt);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const
+ {
+ Point3d v1 = p1;
+ detail::vec_normalize(v1);
+ Point3d v2 = p2;
+ detail::vec_normalize(v2);
+
+ return dot_product(v1, v2);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
+ {
+ coord_t const c0 = 0;
+
+ Point3d v1 = p1;
+ detail::vec_normalize(v1);
+ Point3d v2 = p2;
+ detail::vec_normalize(v2);
+
+ is_forward = dot_product(normal, cross_product(v1, v2)) >= c0;
+ return dot_product(v1, v2);
+ }
+
+ Point3d normal;
+ };
+
+ template <typename Point3d>
+ plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const
+ {
+ return plane<Point3d>(p1, p2);
+ }
+
+ template <typename Point3d>
+ bool intersection_points(plane<Point3d> const& plane1,
+ plane<Point3d> const& plane2,
+ Point3d & ip1, Point3d & ip2) const
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ Point3d id = cross_product(plane1.normal, plane2.normal);
+ // NOTE: the length should be greater than 0 at this point
+ // NOTE: no need to normalize in this case
+
+ ip1 = formula::projected_to_surface(id, m_spheroid);
+
+ ip2 = ip1;
+ multiply_value(ip2, coord_t(-1));
+
+ return true;
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+template <typename Spheroid>
+struct experimental_elliptic_segments_calc_policy
+{
+ explicit experimental_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid())
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Point, typename Point3d>
+ Point from_cart3d(Point3d const& point_3d) const
+ {
+ return formula::cart3d_to_geo<Point>(point_3d, m_spheroid);
+ }
+
+ template <typename Point3d, typename Point>
+ Point3d to_cart3d(Point const& point) const
+ {
+ return formula::geo_to_cart3d<Point3d>(point, m_spheroid);
+ }
+
+ // relate_xxx_calc_policy must live londer than plane because it contains
+ // Spheroid object and plane keeps the reference to that object.
+ template <typename Point3d>
+ struct plane
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // not normalized
+ plane(Point3d const& p1, Point3d const& p2, Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {
+ formula::experimental_elliptic_plane(p1, p2, origin, normal, m_spheroid);
+ }
+
+ int side_value(Point3d const& pt) const
+ {
+ return formula::elliptic_side_value(origin, normal, pt);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const
+ {
+ Point3d const v1 = normalized_vec(p1);
+ Point3d const v2 = normalized_vec(p2);
+ return dot_product(v1, v2);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
+ {
+ coord_t const c0 = 0;
+
+ Point3d const v1 = normalized_vec(p1);
+ Point3d const v2 = normalized_vec(p2);
+
+ is_forward = dot_product(normal, cross_product(v1, v2)) >= c0;
+ return dot_product(v1, v2);
+ }
+
+ Point3d origin;
+ Point3d normal;
+
+ private:
+ Point3d normalized_vec(Point3d const& p) const
+ {
+ Point3d v = p;
+ subtract_point(v, origin);
+ detail::vec_normalize(v);
+ return v;
+ }
+
+ Spheroid const& m_spheroid;
+ };
+
+ template <typename Point3d>
+ plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const
+ {
+ return plane<Point3d>(p1, p2, m_spheroid);
+ }
+
+ template <typename Point3d>
+ bool intersection_points(plane<Point3d> const& plane1,
+ plane<Point3d> const& plane2,
+ Point3d & ip1, Point3d & ip2) const
+ {
+ return formula::planes_spheroid_intersection(plane1.origin, plane1.normal,
+ plane2.origin, plane2.normal,
+ ip1, ip2, m_spheroid);
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct great_elliptic_segments
+ : ecef_segments
+ <
+ great_elliptic_segments_calc_policy<Spheroid>,
+ CalculationType
+ >
+{};
+
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+struct experimental_elliptic_segments
+ : ecef_segments
+ <
+ experimental_elliptic_segments_calc_policy<Spheroid>,
+ CalculationType
+ >
+{};
+
+
+}} // namespace strategy::intersection
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP
diff --git a/boost/geometry/strategies/geographic/mapping_ssf.hpp b/boost/geometry/strategies/geographic/mapping_ssf.hpp
index 3beedc7809..20a0523616 100644
--- a/boost/geometry/strategies/geographic/mapping_ssf.hpp
+++ b/boost/geometry/strategies/geographic/mapping_ssf.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -136,7 +136,7 @@ public :
{}
template <typename P1, typename P2, typename P>
- inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ inline int apply(P1 const& p1, P2 const& p2, P const& p) const
{
typedef typename promote_floating_point
<
diff --git a/boost/geometry/strategies/geographic/parameters.hpp b/boost/geometry/strategies/geographic/parameters.hpp
new file mode 100644
index 0000000000..5638db50fa
--- /dev/null
+++ b/boost/geometry/strategies/geographic/parameters.hpp
@@ -0,0 +1,117 @@
+// Boost.Geometry
+
+// Copyright (c) 2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP
+
+
+#include <boost/geometry/formulas/andoyer_inverse.hpp>
+#include <boost/geometry/formulas/thomas_inverse.hpp>
+#include <boost/geometry/formulas/vincenty_inverse.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/integral_c.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy
+{
+
+struct andoyer
+{
+ template
+ <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+ >
+ struct inverse
+ : formula::andoyer_inverse
+ <
+ CT, EnableDistance,
+ EnableAzimuth, EnableReverseAzimuth,
+ EnableReducedLength, EnableGeodesicScale
+ >
+ {};
+};
+
+struct thomas
+{
+ template
+ <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+ >
+ struct inverse
+ : formula::thomas_inverse
+ <
+ CT, EnableDistance,
+ EnableAzimuth, EnableReverseAzimuth,
+ EnableReducedLength, EnableGeodesicScale
+ >
+ {};
+};
+
+struct vincenty
+{
+ template
+ <
+ typename CT,
+ bool EnableDistance,
+ bool EnableAzimuth,
+ bool EnableReverseAzimuth = false,
+ bool EnableReducedLength = false,
+ bool EnableGeodesicScale = false
+ >
+ struct inverse
+ : formula::vincenty_inverse
+ <
+ CT, EnableDistance,
+ EnableAzimuth, EnableReverseAzimuth,
+ EnableReducedLength, EnableGeodesicScale
+ >
+ {};
+};
+
+
+template <typename FormulaPolicy>
+struct default_order
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE
+ , (types<FormulaPolicy>)
+ );
+};
+
+template<>
+struct default_order<andoyer>
+ : boost::mpl::integral_c<unsigned int, 1>
+{};
+
+template<>
+struct default_order<thomas>
+ : boost::mpl::integral_c<unsigned int, 2>
+{};
+
+template<>
+struct default_order<vincenty>
+ : boost::mpl::integral_c<unsigned int, 4>
+{};
+
+}}} // namespace boost::geometry::strategy
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_PARAMETERS_HPP
diff --git a/boost/geometry/strategies/geographic/side.hpp b/boost/geometry/strategies/geographic/side.hpp
new file mode 100644
index 0000000000..0d40e4da20
--- /dev/null
+++ b/boost/geometry/strategies/geographic/side.hpp
@@ -0,0 +1,113 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014-2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// 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_GEOGRAPHIC_SIDE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/formulas/spherical.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/strategies/side.hpp>
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace side
+{
+
+
+/*!
+\brief Check at which side of a segment a point lies
+ left of segment (> 0), right of segment (< 0), on segment (0)
+\ingroup strategies
+\tparam FormulaPolicy Geodesic solution formula policy.
+\tparam Spheroid Reference model of coordinate system.
+\tparam CalculationType \tparam_calculation
+ */
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+{
+public:
+ geographic()
+ {}
+
+ explicit geographic(Spheroid const& model)
+ : m_model(model)
+ {}
+
+ template <typename P1, typename P2, typename P>
+ inline int apply(P1 const& p1, P2 const& p2, P const& p) const
+ {
+ typedef typename promote_floating_point
+ <
+ typename select_calculation_type_alt
+ <
+ CalculationType,
+ P1, P2, P
+ >::type
+ >::type calc_t;
+
+ typedef typename FormulaPolicy::template inverse
+ <calc_t, false, true, false, false, false> inverse_formula;
+
+ calc_t a1p = azimuth<calc_t, inverse_formula>(p1, p, m_model);
+ calc_t a12 = azimuth<calc_t, inverse_formula>(p1, p2, m_model);
+
+ return formula::azimuth_side_value(a1p, a12);
+ }
+
+private:
+ template <typename ResultType,
+ typename InverseFormulaType,
+ typename Point1,
+ typename Point2,
+ typename ModelT>
+ static inline ResultType azimuth(Point1 const& point1, Point2 const& point2,
+ ModelT const& model)
+ {
+ return InverseFormulaType::apply(get_as_radian<0>(point1),
+ get_as_radian<1>(point1),
+ get_as_radian<0>(point2),
+ get_as_radian<1>(point2),
+ model).azimuth;
+ }
+
+ Spheroid m_model;
+};
+
+
+}} // namespace strategy::side
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_HPP
diff --git a/boost/geometry/strategies/geographic/side_andoyer.hpp b/boost/geometry/strategies/geographic/side_andoyer.hpp
index c3e71cd1cd..204e45f6e2 100644
--- a/boost/geometry/strategies/geographic/side_andoyer.hpp
+++ b/boost/geometry/strategies/geographic/side_andoyer.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,9 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP
-#include <boost/geometry/formulas/andoyer_inverse.hpp>
-
-#include <boost/geometry/strategies/geographic/side_detail.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
namespace boost { namespace geometry
@@ -31,17 +29,24 @@ namespace strategy { namespace side
\brief Check at which side of a segment a point lies
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
-\tparam Model Reference model of coordinate system.
+\tparam Spheroid Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
*/
-template <typename Model, typename CalculationType = void>
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
class andoyer
- : public detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType>
+ : public side::geographic<strategy::andoyer, Spheroid, CalculationType>
{
- typedef detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType> base_t;
+ typedef side::geographic<strategy::andoyer, Spheroid, CalculationType> base_t;
public:
- andoyer(Model const& model = Model())
+ andoyer()
+ {}
+
+ explicit andoyer(Spheroid const& model)
: base_t(model)
{}
};
diff --git a/boost/geometry/strategies/geographic/side_detail.hpp b/boost/geometry/strategies/geographic/side_detail.hpp
deleted file mode 100644
index ce1b47c88e..0000000000
--- a/boost/geometry/strategies/geographic/side_detail.hpp
+++ /dev/null
@@ -1,139 +0,0 @@
-// Boost.Geometry
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 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_GEOGRAPHIC_SIDE_DETAIL_HPP
-#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
-
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/core/radius.hpp>
-
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
-
-#include <boost/geometry/strategies/side.hpp>
-//#include <boost/geometry/strategies/concepts/side_concept.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-
-namespace strategy { namespace side
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-
-/*!
-\brief Check at which side of a segment a point lies
- left of segment (> 0), right of segment (< 0), on segment (0)
-\ingroup strategies
-\tparam InverseFormula Geodesic inverse solution formula.
-\tparam Model Reference model of coordinate system.
-\tparam CalculationType \tparam_calculation
- */
-template <template<typename, bool, bool, bool, bool, bool> class InverseFormula,
- typename Model,
- typename CalculationType = void>
-class by_azimuth
-{
-public:
- by_azimuth(Model const& model = Model())
- : m_model(model)
- {}
-
- template <typename P1, typename P2, typename P>
- inline int apply(P1 const& p1, P2 const& p2, P const& p)
- {
- typedef typename promote_floating_point
- <
- typename select_calculation_type_alt
- <
- CalculationType,
- P1, P2, P
- >::type
- >::type calc_t;
-
- typedef InverseFormula<calc_t, false, true, false, false, false> inverse_formula;
-
- calc_t a1p = azimuth<calc_t, inverse_formula>(p1, p, m_model);
- calc_t a12 = azimuth<calc_t, inverse_formula>(p1, p2, m_model);
-
- calc_t const pi = math::pi<calc_t>();
-
- // instead of the formula from XTD
- //calc_t a_diff = asin(sin(a1p - a12));
-
- calc_t a_diff = a1p - a12;
- // normalize, angle in [-pi, pi]
- while ( a_diff > pi )
- a_diff -= calc_t(2) * pi;
- while ( a_diff < -pi )
- a_diff += calc_t(2) * pi;
-
- // NOTE: in general it shouldn't be required to support the pi/-pi case
- // because in non-cartesian systems it makes sense to check the side
- // only "between" the endpoints.
- // However currently the winding strategy calls the side strategy
- // for vertical segments to check if the point is "between the endpoints.
- // This could be avoided since the side strategy is not required for that
- // because meridian is the shortest path. So a difference of
- // longitudes would be sufficient (of course normalized to [-pi, pi]).
-
- // NOTE: with the above said, the pi/-pi check is temporary
- // however in case if this was required
- // the geodesics on ellipsoid aren't "symmetrical"
- // therefore instead of comparing a_diff to pi and -pi
- // one should probably use inverse azimuths and compare
- // the difference to 0 as well
-
- // positive azimuth is on the right side
- return math::equals(a_diff, 0)
- || math::equals(a_diff, pi)
- || math::equals(a_diff, -pi) ? 0
- : a_diff > 0 ? -1 // right
- : 1; // left
- }
-
-private:
- template <typename ResultType,
- typename InverseFormulaType,
- typename Point1,
- typename Point2,
- typename ModelT>
- static inline ResultType azimuth(Point1 const& point1, Point2 const& point2, ModelT const& model)
- {
- return InverseFormulaType::apply(get_as_radian<0>(point1),
- get_as_radian<1>(point1),
- get_as_radian<0>(point2),
- get_as_radian<1>(point2),
- model).azimuth;
- }
-
- Model m_model;
-};
-
-} // detail
-#endif // DOXYGEN_NO_DETAIL
-
-}} // namespace strategy::side
-
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
diff --git a/boost/geometry/strategies/geographic/side_thomas.hpp b/boost/geometry/strategies/geographic/side_thomas.hpp
index 96b0323307..e6f8d77b58 100644
--- a/boost/geometry/strategies/geographic/side_thomas.hpp
+++ b/boost/geometry/strategies/geographic/side_thomas.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,9 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP
-#include <boost/geometry/formulas/thomas_inverse.hpp>
-
-#include <boost/geometry/strategies/geographic/side_detail.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
namespace boost { namespace geometry
@@ -31,17 +29,24 @@ namespace strategy { namespace side
\brief Check at which side of a segment a point lies
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
-\tparam Model Reference model of coordinate system.
+\tparam Spheroid Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
*/
-template <typename Model, typename CalculationType = void>
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
class thomas
- : public detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType>
+ : public side::geographic<strategy::thomas, Spheroid, CalculationType>
{
- typedef detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType> base_t;
+ typedef side::geographic<strategy::thomas, Spheroid, CalculationType> base_t;
public:
- thomas(Model const& model = Model())
+ thomas()
+ {}
+
+ explicit thomas(Spheroid const& model)
: base_t(model)
{}
};
diff --git a/boost/geometry/strategies/geographic/side_vincenty.hpp b/boost/geometry/strategies/geographic/side_vincenty.hpp
index 103277a8bd..b2f51b0901 100644
--- a/boost/geometry/strategies/geographic/side_vincenty.hpp
+++ b/boost/geometry/strategies/geographic/side_vincenty.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2015, 2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,9 +15,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP
-#include <boost/geometry/formulas/vincenty_inverse.hpp>
-
-#include <boost/geometry/strategies/geographic/side_detail.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
namespace boost { namespace geometry
@@ -31,17 +29,24 @@ namespace strategy { namespace side
\brief Check at which side of a segment a point lies
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
-\tparam Model Reference model of coordinate system.
+\tparam Spheroid Reference model of coordinate system.
\tparam CalculationType \tparam_calculation
*/
-template <typename Model, typename CalculationType = void>
+template
+<
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
class vincenty
- : public detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType>
+ : public side::geographic<strategy::vincenty, Spheroid, CalculationType>
{
- typedef detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType> base_t;
+ typedef side::geographic<strategy::vincenty, Spheroid, CalculationType> base_t;
public:
- vincenty(Model const& model = Model())
+ vincenty()
+ {}
+
+ explicit vincenty(Spheroid const& model)
: base_t(model)
{}
};
diff --git a/boost/geometry/strategies/intersection.hpp b/boost/geometry/strategies/intersection.hpp
index f51c5cb206..e5662c9e46 100644
--- a/boost/geometry/strategies/intersection.hpp
+++ b/boost/geometry/strategies/intersection.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2016, Oracle and/or its affiliates.
+// Copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -30,10 +30,9 @@ namespace services
\brief Traits class binding a segments intersection strategy to a coordinate system
\ingroup util
\tparam CSTag tag of coordinate system of point-type
-\tparam Policy intersection policy
\tparam CalculationType \tparam_calculation
*/
-template <typename CSTag, typename Policy, typename CalculationType = void>
+template <typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
diff --git a/boost/geometry/strategies/intersection_strategies.hpp b/boost/geometry/strategies/intersection_strategies.hpp
index 0452c4692c..a173505804 100644
--- a/boost/geometry/strategies/intersection_strategies.hpp
+++ b/boost/geometry/strategies/intersection_strategies.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016.
-// Modifications copyright (c) 2016, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016, 2017.
+// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -22,10 +22,10 @@
#include <boost/geometry/policies/relate/tupled.hpp>
#include <boost/geometry/strategies/intersection.hpp>
-#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side.hpp>
-#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
+#include <boost/geometry/strategies/cartesian/intersection.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
@@ -70,17 +70,18 @@ private :
> ip_type;
public:
+ typedef policies::relate::segments_tupled
+ <
+ policies::relate::segments_intersection_points
+ <
+ ip_type
+ > ,
+ policies::relate::segments_direction
+ > intersection_policy_type;
+
typedef typename strategy::intersection::services::default_strategy
<
Tag,
- policies::relate::segments_tupled
- <
- policies::relate::segments_intersection_points
- <
- ip_type
- > ,
- policies::relate::segments_direction
- >,
CalculationType
>::type segment_intersection_strategy_type;
diff --git a/boost/geometry/strategies/relate.hpp b/boost/geometry/strategies/relate.hpp
new file mode 100644
index 0000000000..ffeed78959
--- /dev/null
+++ b/boost/geometry/strategies/relate.hpp
@@ -0,0 +1,177 @@
+// Boost.Geometry
+
+// Copyright (c) 2017, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_RELATE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy
+{
+
+namespace point_in_geometry
+{
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename Point,
+ typename Geometry,
+ typename Tag1 = typename tag<Point>::type,
+ typename Tag2 = typename tag<Geometry>::type
+>
+struct default_strategy
+ : strategy::within::services::default_strategy
+ <
+ Point,
+ Geometry
+ >
+{
+ typedef typename default_strategy::type within_strategy_type;
+
+ typedef typename strategy::covered_by::services::default_strategy
+ <
+ Point,
+ Geometry
+ >::type covered_by_strategy_type;
+
+ static const bool same_strategies = boost::is_same<within_strategy_type, covered_by_strategy_type>::value;
+ BOOST_MPL_ASSERT_MSG((same_strategies),
+ DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,
+ (within_strategy_type, covered_by_strategy_type));
+};
+
+template<typename Point, typename Geometry>
+struct default_strategy<Point, Geometry, point_tag, point_tag>
+ : strategy::within::services::default_strategy<Point, Geometry>
+{};
+
+template<typename Point, typename Geometry>
+struct default_strategy<Point, Geometry, point_tag, multi_point_tag>
+ : strategy::within::services::default_strategy<Point, Geometry>
+{};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+} // namespace point_in_geometry
+
+namespace relate
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Geometry>
+struct default_intersection_strategy
+ : strategy::intersection::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >
+{};
+
+template <typename PointLike, typename Geometry>
+struct default_point_in_geometry_strategy
+ : point_in_geometry::services::default_strategy
+ <
+ typename point_type<PointLike>::type,
+ Geometry
+ >
+{};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ int TopDim1 = geometry::topological_dimension<Geometry1>::value,
+ int TopDim2 = geometry::topological_dimension<Geometry2>::value
+>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES
+ , (types<Geometry1, Geometry2>)
+ );
+};
+
+template <typename PointLike1, typename PointLike2>
+struct default_strategy<PointLike1, PointLike2, 0, 0>
+ : detail::default_point_in_geometry_strategy<PointLike1, PointLike2>
+{};
+
+template <typename PointLike, typename Geometry, int TopDim2>
+struct default_strategy<PointLike, Geometry, 0, TopDim2>
+ : detail::default_point_in_geometry_strategy<PointLike, Geometry>
+{};
+
+template <typename Geometry, typename PointLike, int TopDim1>
+struct default_strategy<Geometry, PointLike, TopDim1, 0>
+ : detail::default_point_in_geometry_strategy<PointLike, Geometry>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 1, 1>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 1, 2>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 2, 1>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, 2, 2>
+ : detail::default_intersection_strategy<Geometry1>
+{};
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+} // namespace relate
+
+} // namespace strategy
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_HPP
diff --git a/boost/geometry/strategies/side.hpp b/boost/geometry/strategies/side.hpp
index 376f2fdf1b..9aaa2bdddc 100644
--- a/boost/geometry/strategies/side.hpp
+++ b/boost/geometry/strategies/side.hpp
@@ -30,16 +30,16 @@ namespace services
/*!
\brief Traits class binding a side determination strategy to a coordinate system
\ingroup util
-\tparam Tag tag of coordinate system of point-type
+\tparam CSTag tag of coordinate system of point-type
\tparam CalculationType \tparam_calculation
*/
-template <typename Tag, typename CalculationType = void>
+template <typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TYPE
- , (types<Tag>)
+ , (types<CSTag>)
);
};
diff --git a/boost/geometry/strategies/spherical/area.hpp b/boost/geometry/strategies/spherical/area.hpp
new file mode 100644
index 0000000000..206b734548
--- /dev/null
+++ b/boost/geometry/strategies/spherical/area.hpp
@@ -0,0 +1,182 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HPP
+
+
+#include <boost/geometry/formulas/area_formulas.hpp>
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/strategies/area.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area
+{
+
+/*!
+\brief Spherical area calculation
+\ingroup strategies
+\details Calculates area on the surface of a sphere using the trapezoidal rule
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
+}
+*/
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class spherical
+{
+ // Enables special handling of long segments
+ static const bool LongSegment = false;
+
+typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename coordinate_type<PointOfSegment>::type,
+ double
+ >::type,
+ CalculationType
+ >::type CT;
+
+protected :
+ struct excess_sum
+ {
+ CT m_sum;
+
+ // Keep track if encircles some pole
+ size_t m_crosses_prime_meridian;
+
+ inline excess_sum()
+ : m_sum(0)
+ , m_crosses_prime_meridian(0)
+ {}
+ template <typename SphereType>
+ inline CT area(SphereType sphere) const
+ {
+ CT result;
+ CT radius = geometry::get_radius<0>(sphere);
+
+ // Encircles pole
+ if(m_crosses_prime_meridian % 2 == 1)
+ {
+ size_t times_crosses_prime_meridian
+ = 1 + (m_crosses_prime_meridian / 2);
+
+ result = CT(2)
+ * geometry::math::pi<CT>()
+ * times_crosses_prime_meridian
+ - geometry::math::abs(m_sum);
+
+ if(geometry::math::sign<CT>(m_sum) == 1)
+ {
+ result = - result;
+ }
+
+ } else {
+ result = m_sum;
+ }
+
+ result *= radius * radius;
+
+ return result;
+ }
+ };
+
+public :
+ typedef CT return_type;
+ typedef PointOfSegment segment_point_type;
+ typedef excess_sum state_type;
+ typedef geometry::srs::sphere<CT> sphere_type;
+
+ // For backward compatibility reasons the radius is set to 1
+ inline spherical()
+ : m_sphere(1.0)
+ {}
+
+ template <typename T>
+ explicit inline spherical(geometry::srs::sphere<T> const& sphere)
+ : m_sphere(geometry::get_radius<0>(sphere))
+ {}
+
+ explicit inline spherical(CT const& radius)
+ : m_sphere(radius)
+ {}
+
+ inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ excess_sum& state) const
+ {
+ if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
+ {
+
+ state.m_sum += geometry::formula::area_formulas
+ <CT>::template spherical<LongSegment>(p1, p2);
+
+ // Keep track whenever a segment crosses the prime meridian
+ geometry::formula::area_formulas
+ <CT>::crosses_prime_meridian(p1, p2, state);
+
+ }
+ }
+
+ inline return_type result(excess_sum const& state) const
+ {
+ return state.area(m_sphere);
+ }
+
+private :
+ /// srs Sphere
+ sphere_type m_sphere;
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+
+template <typename Point>
+struct default_strategy<spherical_equatorial_tag, Point>
+{
+ typedef strategy::area::spherical<Point> type;
+};
+
+// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
+template <typename Point>
+struct default_strategy<spherical_polar_tag, Point>
+{
+ typedef strategy::area::spherical<Point> type;
+};
+
+} // namespace services
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::area
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HPP
diff --git a/boost/geometry/strategies/spherical/area_huiller.hpp b/boost/geometry/strategies/spherical/area_huiller.hpp
deleted file mode 100644
index 37d8d20124..0000000000
--- a/boost/geometry/strategies/spherical/area_huiller.hpp
+++ /dev/null
@@ -1,214 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, 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)
-
-#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
-#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
-
-
-
-#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
-
-#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/util/math.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-namespace strategy { namespace area
-{
-
-
-
-/*!
-\brief Area calculation by spherical excess / Huiller's formula
-\ingroup strategies
-\tparam PointOfSegment point type of segments of rings/polygons
-\tparam CalculationType \tparam_calculation
-\author Barend Gehrels. Adapted from:
-- http://webdocs.cs.ualberta.ca/~graphics/books/GraphicsGems/gemsiv/sph_poly.c
-- http://tog.acm.org/resources/GraphicsGems/gemsiv/sph_poly.c
-- http://williams.best.vwh.net/avform.htm
-\note The version in Graphics Gems IV (page 132-137) didn't account for
-polygons crossing the 0 and 180 meridians. The fix for this algorithm
-can be found in Graphics Gems V (pages 45-46). See:
-- http://kysmykseka.net/koti/wizardry/Game%20Development/Programming/Graphics%20Gems%204.pdf
-- http://kysmykseka.net/koti/wizardry/Game%20Development/Programming/Graphics%20Gems%205.pdf
-\note This version works for convex and non-convex polygons, for 180 meridian
-crossing polygons and for polygons with holes. However, some cases (especially
-180 meridian cases) must still be checked.
-\note The version which sums angles, which is often seen, doesn't handle non-convex
-polygons correctly.
-\note The version which sums longitudes, see http://hdl.handle.net/2014/40409,
-is simple and works well in most cases but not in 180 meridian crossing cases.
-This probably could be solved.
-
-\note This version is made for spherical equatorial coordinate systems
-
-\qbk{
-
-[heading Example]
-[area_with_strategy]
-[area_with_strategy_output]
-
-
-[heading See also]
-[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
-}
-
-*/
-template
-<
- typename PointOfSegment,
- typename CalculationType = void
->
-class huiller
-{
-typedef typename boost::mpl::if_c
- <
- boost::is_void<CalculationType>::type::value,
- typename select_most_precise
- <
- typename coordinate_type<PointOfSegment>::type,
- double
- >::type,
- CalculationType
- >::type calculation_type;
-
-protected :
- struct excess_sum
- {
- calculation_type sum;
-
- // Distances are calculated on unit sphere here
- strategy::distance::haversine<calculation_type> distance_over_unit_sphere;
-
-
- inline excess_sum()
- : sum(0)
- , distance_over_unit_sphere(1)
- {}
- inline calculation_type area(calculation_type radius) const
- {
- return - sum * radius * radius;
- }
- };
-
-public :
- typedef calculation_type return_type;
- typedef PointOfSegment segment_point_type;
- typedef excess_sum state_type;
-
- inline huiller(calculation_type radius = 1.0)
- : m_radius(radius)
- {}
-
- inline void apply(PointOfSegment const& p1,
- PointOfSegment const& p2,
- excess_sum& state) const
- {
- if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
- {
- calculation_type const half = 0.5;
- calculation_type const two = 2.0;
- calculation_type const four = 4.0;
- calculation_type const pi
- = geometry::math::pi<calculation_type>();
- calculation_type const two_pi
- = geometry::math::two_pi<calculation_type>();
- calculation_type const half_pi
- = geometry::math::half_pi<calculation_type>();
-
- // Distance p1 p2
- calculation_type a = state.distance_over_unit_sphere.apply(p1, p2);
-
- // Sides on unit sphere to south pole
- calculation_type b = half_pi - geometry::get_as_radian<1>(p2);
- calculation_type c = half_pi - geometry::get_as_radian<1>(p1);
-
- // Semi parameter
- calculation_type s = half * (a + b + c);
-
- // E: spherical excess, using l'Huiller's formula
- // [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2]
- calculation_type excess = four
- * atan(geometry::math::sqrt(geometry::math::abs(tan(s / two)
- * tan((s - a) / two)
- * tan((s - b) / two)
- * tan((s - c) / two))));
-
- excess = geometry::math::abs(excess);
-
- // In right direction: positive, add area. In left direction: negative, subtract area.
- // Longitude comparisons are not so obvious. If one is negative and other is positive,
- // we have to take the dateline into account.
-
- calculation_type lon_diff = geometry::get_as_radian<0>(p2)
- - geometry::get_as_radian<0>(p1);
- if (lon_diff <= 0)
- {
- lon_diff += two_pi;
- }
-
- if (lon_diff > pi)
- {
- excess = -excess;
- }
-
- state.sum += excess;
- }
- }
-
- inline return_type result(excess_sum const& state) const
- {
- return state.area(m_radius);
- }
-
-private :
- /// Radius of the sphere
- calculation_type m_radius;
-};
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-namespace services
-{
-
-
-template <typename Point>
-struct default_strategy<spherical_equatorial_tag, Point>
-{
- typedef strategy::area::huiller<Point> type;
-};
-
-// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
-/***template <typename Point>
-struct default_strategy<spherical_polar_tag, Point>
-{
- typedef strategy::area::huiller<Point> type;
-};***/
-
-} // namespace services
-
-#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-
-}} // namespace strategy::area
-
-
-
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
diff --git a/boost/geometry/strategies/spherical/azimuth.hpp b/boost/geometry/strategies/spherical/azimuth.hpp
new file mode 100644
index 0000000000..3c208fe2e2
--- /dev/null
+++ b/boost/geometry/strategies/spherical/azimuth.hpp
@@ -0,0 +1,87 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2016-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AZIMUTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AZIMUTH_HPP
+
+
+#include <boost/geometry/strategies/azimuth.hpp>
+#include <boost/geometry/formulas/spherical.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_void.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace azimuth
+{
+
+template
+<
+ typename CalculationType = void
+>
+class spherical
+{
+public :
+
+ inline spherical()
+ {}
+
+ template <typename T>
+ static inline void apply(T const& lon1_rad, T const& lat1_rad,
+ T const& lon2_rad, T const& lat2_rad,
+ T& a1, T& a2)
+ {
+ typedef typename boost::mpl::if_
+ <
+ boost::is_void<CalculationType>, T, CalculationType
+ >::type calc_t;
+
+ geometry::formula::result_spherical<calc_t>
+ result = geometry::formula::spherical_azimuth<calc_t, true>(
+ calc_t(lon1_rad), calc_t(lat1_rad),
+ calc_t(lon2_rad), calc_t(lat2_rad));
+
+ a1 = result.azimuth;
+ a2 = result.reverse_azimuth;
+ }
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<spherical_equatorial_tag, CalculationType>
+{
+ typedef strategy::azimuth::spherical<CalculationType> type;
+};
+
+/*
+template <typename CalculationType>
+struct default_strategy<spherical_polar_tag, CalculationType>
+{
+ typedef strategy::azimuth::spherical<CalculationType> type;
+};
+*/
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace strategy::azimuth
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/spherical/envelope_segment.hpp b/boost/geometry/strategies/spherical/envelope_segment.hpp
new file mode 100644
index 0000000000..98f085fe73
--- /dev/null
+++ b/boost/geometry/strategies/spherical/envelope_segment.hpp
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, 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)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP
+
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
+#include <boost/geometry/strategies/spherical/azimuth.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+template
+<
+ typename CalculationType = void
+>
+class spherical_segment
+{
+public :
+
+ inline spherical_segment()
+ {}
+
+ template <typename Point1, typename Point2, typename Box>
+ inline void
+ apply(Point1 const& point1, Point2 const& point2, Box& box) const
+ {
+ Point1 p1_normalized = detail::return_normalized<Point1>(point1);
+ Point2 p2_normalized = detail::return_normalized<Point2>(point2);
+
+ geometry::strategy::azimuth::spherical<CalculationType> azimuth_spherical;
+
+ typedef typename coordinate_system<Point1>::type::units units_type;
+
+ geometry::detail::envelope::envelope_segment_impl<spherical_equatorial_tag>
+ ::template apply<units_type>(geometry::get<0>(p1_normalized),
+ geometry::get<1>(p1_normalized),
+ geometry::get<0>(p2_normalized),
+ geometry::get<1>(p2_normalized),
+ box,
+ azimuth_spherical);
+
+ }
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<spherical_equatorial_tag, CalculationType>
+{
+ typedef strategy::envelope::spherical_segment<CalculationType> type;
+};
+
+
+template <typename CalculationType>
+struct default_strategy<spherical_polar_tag, CalculationType>
+{
+ typedef strategy::envelope::spherical_segment<CalculationType> type;
+};
+
+}
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP
+
diff --git a/boost/geometry/strategies/spherical/intersection.hpp b/boost/geometry/strategies/spherical/intersection.hpp
index 4ffc853aad..5d37583333 100644
--- a/boost/geometry/strategies/spherical/intersection.hpp
+++ b/boost/geometry/strategies/spherical/intersection.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2016, Oracle and/or its affiliates.
+// Copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -25,6 +25,7 @@
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/cross_product.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
+#include <boost/geometry/arithmetic/normalize.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
@@ -32,9 +33,16 @@
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
-#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/strategies/spherical/area.hpp>
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+#include <boost/geometry/strategies/spherical/ssf.hpp>
+#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
@@ -68,13 +76,80 @@ namespace strategy { namespace intersection
// For now, intersection points near the endpoints are checked explicitly if needed (if the IP is near the endpoint)
// to generate precise result for them. Only the crossing (i) case may suffer from lower precision.
-template <typename Policy, typename CalculationType = void>
-struct relate_spherical_segments
+template
+<
+ typename CalcPolicy,
+ typename CalculationType = void
+>
+struct ecef_segments
{
- typedef typename Policy::return_type return_type;
+ typedef side::spherical_side_formula<CalculationType> side_strategy_type;
+
+ static inline side_strategy_type get_side_strategy()
+ {
+ return side_strategy_type();
+ }
+
+ template <typename Geometry1, typename Geometry2>
+ struct point_in_geometry_strategy
+ {
+ typedef strategy::within::winding
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ side_strategy_type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry1, typename Geometry2>
+ static inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
+ get_point_in_geometry_strategy()
+ {
+ typedef typename point_in_geometry_strategy
+ <
+ Geometry1, Geometry2
+ >::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct area_strategy
+ {
+ typedef area::spherical
+ <
+ typename point_type<Geometry>::type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename area_strategy<Geometry>::type get_area_strategy()
+ {
+ typedef typename area_strategy<Geometry>::type strategy_type;
+ return strategy_type();
+ }
+
+ template <typename Geometry>
+ struct distance_strategy
+ {
+ typedef distance::haversine
+ <
+ typename coordinate_type<Geometry>::type,
+ CalculationType
+ > type;
+ };
+
+ template <typename Geometry>
+ static inline typename distance_strategy<Geometry>::type get_distance_strategy()
+ {
+ typedef typename distance_strategy<Geometry>::type strategy_type;
+ return strategy_type();
+ }
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
+ // segment_intersection_info cannot outlive relate_ecef_segments
template <typename CoordinateType, typename SegmentRatio, typename Vector3d>
struct segment_intersection_info
{
@@ -83,6 +158,10 @@ struct relate_spherical_segments
CoordinateType, double
>::type promoted_type;
+ segment_intersection_info(CalcPolicy const& calc)
+ : calc_policy(calc)
+ {}
+
promoted_type comparable_length_a() const
{
return robust_ra.denominator();
@@ -110,7 +189,7 @@ struct relate_spherical_segments
if (ip_flag == ipi_inters)
{
// TODO: assign the rest of coordinates
- point = formula::cart3d_to_sph<Point>(intersection_point);
+ point = calc_policy.template from_cart3d<Point>(intersection_point);
}
else if (ip_flag == ipi_at_a1)
{
@@ -134,12 +213,21 @@ struct relate_spherical_segments
SegmentRatio robust_ra;
SegmentRatio robust_rb;
intersection_point_flag ip_flag;
+
+ CalcPolicy const& calc_policy;
};
// Relate segments a and b
- template <typename Segment1, typename Segment2, typename RobustPolicy>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const& robust_policy)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const& policy, RobustPolicy const& robust_policy)
{
typedef typename point_type<Segment1>::type point1_t;
typedef typename point_type<Segment2>::type point2_t;
@@ -152,15 +240,30 @@ struct relate_spherical_segments
detail::assign_point_from_index<0>(b, b1);
detail::assign_point_from_index<1>(b, b2);
- return apply(a, b, robust_policy, a1, a2, b1, b2);
+ return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
}
// Relate segments a and b
- template <typename Segment1, typename Segment2, typename RobustPolicy, typename Point1, typename Point2>
- static inline return_type apply(Segment1 const& a, Segment2 const& b,
- RobustPolicy const&,
- Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2)
+ template
+ <
+ typename Segment1,
+ typename Segment2,
+ typename Policy,
+ typename RobustPolicy,
+ typename Point1,
+ typename Point2
+ >
+ static inline typename Policy::return_type
+ apply(Segment1 const& a, Segment2 const& b,
+ Policy const&, RobustPolicy const&,
+ Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2)
{
+ // For now create it using default constructor. In the future it could
+ // be stored in strategy. However then apply() wouldn't be static and
+ // all relops and setops would have to take the strategy or model.
+ // Initialize explicitly to prevent compiler errors in case of PoD type
+ CalcPolicy const calc_policy = CalcPolicy();
+
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
@@ -185,25 +288,29 @@ struct relate_spherical_segments
typedef model::point<calc_t, 3, cs::cartesian> vec3d_t;
- using namespace formula;
- vec3d_t const a1v = sph_to_cart3d<vec3d_t>(a1);
- vec3d_t const a2v = sph_to_cart3d<vec3d_t>(a2);
- vec3d_t const b1v = sph_to_cart3d<vec3d_t>(b1);
- vec3d_t const b2v = sph_to_cart3d<vec3d_t>(b2);
+ vec3d_t const a1v = calc_policy.template to_cart3d<vec3d_t>(a1);
+ vec3d_t const a2v = calc_policy.template to_cart3d<vec3d_t>(a2);
+ vec3d_t const b1v = calc_policy.template to_cart3d<vec3d_t>(b1);
+ vec3d_t const b2v = calc_policy.template to_cart3d<vec3d_t>(b2);
- vec3d_t norm1 = cross_product(a1v, a2v);
- vec3d_t norm2 = cross_product(b1v, b2v);
-
side_info sides;
- // not normalized normals, the same as in SSF
- sides.set<0>(sph_side_value(norm2, a1v), sph_side_value(norm2, a2v));
+
+ typename CalcPolicy::template plane<vec3d_t>
+ plane2 = calc_policy.get_plane(b1v, b2v);
+
+ // not normalized normals, the same as in side strategy
+ sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
if (sides.same<0>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
- // not normalized normals, the same as in SSF
- sides.set<1>(sph_side_value(norm1, b1v), sph_side_value(norm1, b2v));
+
+ typename CalcPolicy::template plane<vec3d_t>
+ plane1 = calc_policy.get_plane(a1v, a2v);
+
+ // not normalized normals, the same as in side strategy
+ sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
@@ -212,13 +319,10 @@ struct relate_spherical_segments
// NOTE: at this point the segments may still be disjoint
- bool collinear = sides.collinear();
-
- calc_t const len1 = math::sqrt(dot_product(norm1, norm1));
- calc_t const len2 = math::sqrt(dot_product(norm2, norm2));
+ calc_t len1, len2;
- // point or opposite sides of a sphere, assume point
- if (math::equals(len1, c0))
+ // point or opposite sides of a sphere/spheroid, assume point
+ if (! detail::vec_normalize(plane1.normal, len1))
{
a_is_point = true;
if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0)
@@ -226,13 +330,8 @@ struct relate_spherical_segments
sides.set<0>(0, 0);
}
}
- else
- {
- // normalize
- divide_value(norm1, len1);
- }
- if (math::equals(len2, c0))
+ if (! detail::vec_normalize(plane2.normal, len2))
{
b_is_point = true;
if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0)
@@ -240,11 +339,6 @@ struct relate_spherical_segments
sides.set<1>(0, 0);
}
}
- else
- {
- // normalize
- divide_value(norm2, len2);
- }
// check both degenerated once more
if (a_is_point && b_is_point)
@@ -255,16 +349,42 @@ struct relate_spherical_segments
;
}
+ // NOTE: at this point the segments may still be disjoint
// NOTE: at this point one of the segments may be degenerated
- // and the segments may still be disjoint
- calc_t dot_n1n2 = dot_product(norm1, norm2);
+ bool collinear = sides.collinear();
+
+ if (! collinear)
+ {
+ // NOTE: for some approximations it's possible that both points may lie
+ // on the same geodesic but still some of the sides may be != 0.
+ // This is e.g. true for long segments represented as elliptic arcs
+ // with origin different than the center of the coordinate system.
+ // So make the sides consistent
+
+ // WARNING: the side strategy doesn't have the info about the other
+ // segment so it may return results inconsistent with this intersection
+ // strategy, as it checks both segments for consistency
+
+ if (sides.get<0, 0>() == 0 && sides.get<0, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<1>(0, 0);
+ }
+ else if (sides.get<1, 0>() == 0 && sides.get<1, 1>() == 0)
+ {
+ collinear = true;
+ sides.set<0>(0, 0);
+ }
+ }
+
+ calc_t dot_n1n2 = dot_product(plane1.normal, plane2.normal);
// NOTE: this is technically not needed since theoretically above sides
// are calculated, but just in case check the normals.
// Have in mind that SSF side strategy doesn't check this.
// collinear if normals are equal or opposite: cos(a) in {-1, 1}
- if (!collinear && math::equals(math::abs(dot_n1n2), c1))
+ if (! collinear && math::equals(math::abs(dot_n1n2), c1))
{
collinear = true;
sides.set<0>(0, 0);
@@ -275,12 +395,12 @@ struct relate_spherical_segments
{
if (a_is_point)
{
- return collinear_one_degenerted<calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, norm2, a1v);
+ return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, plane2, a1v);
}
else if (b_is_point)
{
// b2 used to be consistent with (degenerated) checks above (is it needed?)
- return collinear_one_degenerted<calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, norm1, b1v);
+ return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, plane1, b1v);
}
else
{
@@ -289,16 +409,16 @@ struct relate_spherical_segments
// use shorter segment
if (len1 <= len2)
{
- calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b1v, dist_a1_a2, dist_a1_b1);
- calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b2v, dist_a1_a2, dist_a1_b2);
+ calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, dist_a1_a2, dist_a1_b1);
+ calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, dist_a1_a2, dist_a1_b2);
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
dist_b1_a1 = -dist_a1_b1;
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
}
else
{
- calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, norm2, a1v, dist_b1_b2, dist_b1_a1);
- calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, norm2, a2v, dist_b1_b2, dist_b1_a2);
+ calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, dist_b1_b2, dist_b1_a1);
+ calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, dist_b1_b2, dist_b1_a2);
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
dist_a1_b1 = -dist_b1_a1;
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
@@ -359,7 +479,8 @@ struct relate_spherical_segments
vec3d_t i1;
intersection_point_flag ip_flag;
calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
- if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v, norm1, norm2, sides,
+ if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v,
+ plane1, plane2, calc_policy, sides,
i1, dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1, ip_flag))
{
// intersects
@@ -368,7 +489,7 @@ struct relate_spherical_segments
calc_t,
segment_ratio<calc_t>,
vec3d_t
- > sinfo;
+ > sinfo(calc_policy);
sinfo.robust_ra.assign(dist_a1_i1, dist_a1_a2);
sinfo.robust_rb.assign(dist_b1_i1, dist_b1_b2);
@@ -385,30 +506,32 @@ struct relate_spherical_segments
}
private:
- template <typename CalcT, typename Segment, typename Point1, typename Point2, typename Vec3d>
- static inline return_type collinear_one_degenerted(Segment const& segment, bool degenerated_a,
- Point1 const& a1, Point1 const& a2,
- Point2 const& b1, Point2 const& b2,
- Vec3d const& v1, Vec3d const& v2, Vec3d const& norm,
- Vec3d const& vother)
+ template <typename Policy, typename CalcT, typename Segment, typename Point1, typename Point2, typename Vec3d, typename Plane>
+ static inline typename Policy::return_type
+ collinear_one_degenerated(Segment const& segment, bool degenerated_a,
+ Point1 const& a1, Point1 const& a2,
+ Point2 const& b1, Point2 const& b2,
+ Vec3d const& v1, Vec3d const& v2,
+ Plane const& plane,
+ Vec3d const& vother)
{
CalcT dist_1_2, dist_1_o;
- return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, norm, vother, dist_1_2, dist_1_o)
+ return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, plane, vother, dist_1_2, dist_1_o)
? Policy::disjoint()
: Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
}
- template <typename Point1, typename Point2, typename Vec3d, typename CalcT>
- static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2,
- Point2 const& b1, Point2 const& b2,
- Vec3d const& a1v, // in
- Vec3d const& a2v, // in
- Vec3d const& norm1, // in
- Vec3d const& b1v_or_b2v, // in
+ template <typename Point1, typename Point2, typename Vec3d, typename Plane, typename CalcT>
+ static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
+ Point2 const& b1, Point2 const& b2, // in
+ Vec3d const& a1v, // in
+ Vec3d const& a2v, // in
+ Plane const& plane1, // in
+ Vec3d const& b1v_or_b2v, // in
CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
{
// calculate dist_a1_a2 and dist_a1_i1
- calculate_dists(a1v, a2v, norm1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
+ calculate_dists(a1v, a2v, plane1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
// if i1 is close to a1 and b1 or b2 is equal to a1
if (is_endpoint_equal(dist_a1_i1, a1, b1, b2))
@@ -427,54 +550,53 @@ private:
return segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();
}
- template <typename Point1, typename Point2, typename Vec3d, typename CalcT>
+ template <typename Point1, typename Point2, typename Vec3d, typename Plane, typename CalcT>
static inline bool calculate_ip_data(Point1 const& a1, Point1 const& a2, // in
Point2 const& b1, Point2 const& b2, // in
Vec3d const& a1v, Vec3d const& a2v, // in
Vec3d const& b1v, Vec3d const& b2v, // in
- Vec3d const& norm1, Vec3d const& norm2, // in
- side_info const& sides, // in
- Vec3d & i1, // in-out
- CalcT& dist_a1_a2, CalcT& dist_a1_i1, // out
- CalcT& dist_b1_b2, CalcT& dist_b1_i1, // out
+ Plane const& plane1, // in
+ Plane const& plane2, // in
+ CalcPolicy const& calc_policy, // in
+ side_info const& sides, // in
+ Vec3d & ip, // out
+ CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out
+ CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out
intersection_point_flag& ip_flag) // out
{
- // great circles intersections
- i1 = cross_product(norm1, norm2);
- // NOTE: the length should be greater than 0 at this point
- // if the normals were not normalized and their dot product
- // not checked before this function is called the length
- // should be checked here (math::equals(len, c0))
- CalcT const len = math::sqrt(dot_product(i1, i1));
- divide_value(i1, len); // normalize i1
-
- calculate_dists(a1v, a2v, norm1, i1, dist_a1_a2, dist_a1_i1);
+ Vec3d ip1, ip2;
+ calc_policy.intersection_points(plane1, plane2, ip1, ip2);
+ calculate_dists(a1v, a2v, plane1, ip1, dist_a1_a2, dist_a1_ip);
+ ip = ip1;
+
// choose the opposite side of the globe if the distance is shorter
{
- CalcT const d = abs_distance(dist_a1_a2, dist_a1_i1);
+ CalcT const d = abs_distance(dist_a1_a2, dist_a1_ip);
if (d > CalcT(0))
{
- CalcT const dist_a1_i2 = dist_of_i2(dist_a1_i1);
+ // TODO: this should be ok not only for sphere
+ // but requires more investigation
+ CalcT const dist_a1_i2 = dist_of_i2(dist_a1_ip);
CalcT const d2 = abs_distance(dist_a1_a2, dist_a1_i2);
if (d2 < d)
{
- dist_a1_i1 = dist_a1_i2;
- multiply_value(i1, CalcT(-1)); // the opposite intersection
+ dist_a1_ip = dist_a1_i2;
+ ip = ip2;
}
}
}
bool is_on_a = false, is_near_a1 = false, is_near_a2 = false;
- if (! is_potentially_crossing(dist_a1_a2, dist_a1_i1, is_on_a, is_near_a1, is_near_a2))
+ if (! is_potentially_crossing(dist_a1_a2, dist_a1_ip, is_on_a, is_near_a1, is_near_a2))
{
return false;
}
- calculate_dists(b1v, b2v, norm2, i1, dist_b1_b2, dist_b1_i1);
+ calculate_dists(b1v, b2v, plane2, ip, dist_b1_b2, dist_b1_ip);
bool is_on_b = false, is_near_b1 = false, is_near_b2 = false;
- if (! is_potentially_crossing(dist_b1_b2, dist_b1_i1, is_on_b, is_near_b1, is_near_b2))
+ if (! is_potentially_crossing(dist_b1_b2, dist_b1_ip, is_on_b, is_near_b1, is_near_b2))
{
return false;
}
@@ -485,8 +607,8 @@ private:
{
if (is_near_b1 && equals_point_point(a1, b1))
{
- dist_a1_i1 = 0;
- dist_b1_i1 = 0;
+ dist_a1_ip = 0;
+ dist_b1_ip = 0;
//i1 = a1v;
ip_flag = ipi_at_a1;
return true;
@@ -494,8 +616,8 @@ private:
if (is_near_b2 && equals_point_point(a1, b2))
{
- dist_a1_i1 = 0;
- dist_b1_i1 = dist_b1_b2;
+ dist_a1_ip = 0;
+ dist_b1_ip = dist_b1_b2;
//i1 = a1v;
ip_flag = ipi_at_a1;
return true;
@@ -506,8 +628,8 @@ private:
{
if (is_near_b1 && equals_point_point(a2, b1))
{
- dist_a1_i1 = dist_a1_a2;
- dist_b1_i1 = 0;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = 0;
//i1 = a2v;
ip_flag = ipi_at_a2;
return true;
@@ -515,8 +637,8 @@ private:
if (is_near_b2 && equals_point_point(a2, b2))
{
- dist_a1_i1 = dist_a1_a2;
- dist_b1_i1 = dist_b1_b2;
+ dist_a1_ip = dist_a1_a2;
+ dist_b1_ip = dist_b1_b2;
//i1 = a2v;
ip_flag = ipi_at_a2;
return true;
@@ -530,7 +652,7 @@ private:
{
if (is_near_b1 && sides.template get<1, 0>() == 0) // b1 wrt a
{
- dist_b1_i1 = 0;
+ dist_b1_ip = 0;
//i1 = b1v;
ip_flag = ipi_at_b1;
return true;
@@ -538,7 +660,7 @@ private:
if (is_near_b2 && sides.template get<1, 1>() == 0) // b2 wrt a
{
- dist_b1_i1 = dist_b1_b2;
+ dist_b1_ip = dist_b1_b2;
//i1 = b2v;
ip_flag = ipi_at_b2;
return true;
@@ -549,7 +671,7 @@ private:
{
if (is_near_a1 && sides.template get<0, 0>() == 0) // a1 wrt b
{
- dist_a1_i1 = 0;
+ dist_a1_ip = 0;
//i1 = a1v;
ip_flag = ipi_at_a1;
return true;
@@ -557,7 +679,7 @@ private:
if (is_near_a2 && sides.template get<0, 1>() == 0) // a2 wrt b
{
- dist_a1_i1 = dist_a1_a2;
+ dist_a1_ip = dist_a1_a2;
//i1 = a2v;
ip_flag = ipi_at_a2;
return true;
@@ -569,24 +691,26 @@ private:
return is_on_a && is_on_b;
}
- template <typename Vec3d, typename CalcT>
- static inline void calculate_dists(Vec3d const& a1v, // in
- Vec3d const& a2v, // in
- Vec3d const& norm1, // in
- Vec3d const& i1, // in
- CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
+ template <typename Vec3d, typename Plane, typename CalcT>
+ static inline void calculate_dists(Vec3d const& a1v, // in
+ Vec3d const& a2v, // in
+ Plane const& plane1, // in
+ Vec3d const& i1, // in
+ CalcT& dist_a1_a2, // out
+ CalcT& dist_a1_i1) // out
{
- CalcT const c0 = 0;
+ //CalcT const c0 = 0;
CalcT const c1 = 1;
CalcT const c2 = 2;
CalcT const c4 = 4;
- CalcT cos_a1_a2 = dot_product(a1v, a2v);
+ CalcT cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi]
- CalcT cos_a1_i1 = dot_product(a1v, i1);
+ bool is_forward = true;
+ CalcT cos_a1_i1 = plane1.cos_angle_between(a1v, i1, is_forward);
dist_a1_i1 = -cos_a1_i1 + c1; // [0, 2] representing [0, pi]
- if (dot_product(norm1, cross_product(a1v, i1)) < c0) // left or right of a1 on a
+ if (! is_forward) // left or right of a1 on a
{
dist_a1_i1 = -dist_a1_i1; // [0, 2] -> [0, -2] representing [0, -pi]
}
@@ -666,27 +790,117 @@ private:
}
};
+struct spherical_segments_calc_policy
+{
+ template <typename Point, typename Point3d>
+ static Point from_cart3d(Point3d const& point_3d)
+ {
+ return formula::cart3d_to_sph<Point>(point_3d);
+ }
+
+ template <typename Point3d, typename Point>
+ static Point3d to_cart3d(Point const& point)
+ {
+ return formula::sph_to_cart3d<Point3d>(point);
+ }
+
+ template <typename Point3d>
+ struct plane
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ // not normalized
+ plane(Point3d const& p1, Point3d const& p2)
+ : normal(cross_product(p1, p2))
+ {}
+
+ int side_value(Point3d const& pt) const
+ {
+ return formula::sph_side_value(normal, pt);
+ }
+
+ static coord_t cos_angle_between(Point3d const& p1, Point3d const& p2)
+ {
+ return dot_product(p1, p2);
+ }
+
+ coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
+ {
+ coord_t const c0 = 0;
+ is_forward = dot_product(normal, cross_product(p1, p2)) >= c0;
+ return dot_product(p1, p2);
+ }
+
+ Point3d normal;
+ };
+
+ template <typename Point3d>
+ static plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2)
+ {
+ return plane<Point3d>(p1, p2);
+ }
+
+ template <typename Point3d>
+ static bool intersection_points(plane<Point3d> const& plane1,
+ plane<Point3d> const& plane2,
+ Point3d & ip1, Point3d & ip2)
+ {
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
+ ip1 = cross_product(plane1.normal, plane2.normal);
+ // NOTE: the length should be greater than 0 at this point
+ // if the normals were not normalized and their dot product
+ // not checked before this function is called the length
+ // should be checked here (math::equals(len, c0))
+ coord_t const len = math::sqrt(dot_product(ip1, ip1));
+ divide_value(ip1, len); // normalize i1
+
+ ip2 = ip1;
+ multiply_value(ip2, coord_t(-1));
+
+ return true;
+ }
+};
+
+
+template
+<
+ typename CalculationType = void
+>
+struct spherical_segments
+ : ecef_segments
+ <
+ spherical_segments_calc_policy,
+ CalculationType
+ >
+{};
+
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
-/*template <typename Policy, typename CalculationType>
-struct default_strategy<spherical_polar_tag, Policy, CalculationType>
+/*template <typename CalculationType>
+struct default_strategy<spherical_polar_tag, CalculationType>
{
- typedef relate_spherical_segments<Policy, CalculationType> type;
+ typedef spherical_segments<CalculationType> type;
};*/
-template <typename Policy, typename CalculationType>
-struct default_strategy<spherical_equatorial_tag, Policy, CalculationType>
+template <typename CalculationType>
+struct default_strategy<spherical_equatorial_tag, CalculationType>
{
- typedef relate_spherical_segments<Policy, CalculationType> type;
+ typedef spherical_segments<CalculationType> type;
};
-template <typename Policy, typename CalculationType>
-struct default_strategy<geographic_tag, Policy, CalculationType>
+template <typename CalculationType>
+struct default_strategy<geographic_tag, CalculationType>
{
- typedef relate_spherical_segments<Policy, CalculationType> type;
+ // NOTE: Spherical strategy returns the same result as the geographic one
+ // representing segments as great elliptic arcs. If the elliptic arcs are
+ // not great elliptic arcs (the origin not in the center of the coordinate
+ // system) then there may be problems with consistency of the side and
+ // intersection strategies.
+ typedef spherical_segments<CalculationType> type;
};
} // namespace services
@@ -695,6 +909,71 @@ struct default_strategy<geographic_tag, Policy, CalculationType>
}} // namespace strategy::intersection
+
+namespace strategy
+{
+
+namespace within { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+}} // within::services
+
+namespace covered_by { namespace services
+{
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
+struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, spherical_tag, spherical_tag>
+{
+ typedef strategy::intersection::spherical_segments<> type;
+};
+
+}} // within::services
+
+} // strategy
+
+
}} // namespace boost::geometry
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
index 342485cc4c..f3c6787a4b 100644
--- a/boost/geometry/strategies/strategies.hpp
+++ b/boost/geometry/strategies/strategies.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2016.
-// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2017.
+// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -23,18 +24,24 @@
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/strategies/azimuth.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_strategies.hpp> // for backward compatibility
+#include <boost/geometry/strategies/relate.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/transform.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
+#include <boost/geometry/strategies/cartesian/azimuth.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/cartesian/buffer_end_flat.hpp>
#include <boost/geometry/strategies/cartesian/buffer_end_round.hpp>
@@ -47,30 +54,42 @@
#include <boost/geometry/strategies/cartesian/centroid_average.hpp>
#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
#include <boost/geometry/strategies/cartesian/centroid_weighted_length.hpp>
+#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>
+#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
+#include <boost/geometry/strategies/cartesian/intersection.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#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/spherical/area_huiller.hpp>
+#include <boost/geometry/strategies/spherical/area.hpp>
+#include <boost/geometry/strategies/spherical/azimuth.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/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
+#include <boost/geometry/strategies/geographic/area.hpp>
+#include <boost/geometry/strategies/geographic/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/distance_andoyer.hpp>
#include <boost/geometry/strategies/geographic/distance_thomas.hpp>
#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
-//#include <boost/geometry/strategies/geographic/side_andoyer.hpp>
-//#include <boost/geometry/strategies/geographic/side_thomas.hpp>
-//#include <boost/geometry/strategies/geographic/side_vincenty.hpp>
+#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/intersection.hpp>
+//#include <boost/geometry/strategies/geographic/intersection_elliptic.hpp>
+#include <boost/geometry/strategies/geographic/side.hpp>
+#include <boost/geometry/strategies/geographic/side_andoyer.hpp>
+#include <boost/geometry/strategies/geographic/side_thomas.hpp>
+#include <boost/geometry/strategies/geographic/side_vincenty.hpp>
#include <boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp>
#include <boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp>
@@ -80,8 +99,6 @@
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
-#include <boost/geometry/strategies/agnostic/relate.hpp>
-
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
diff --git a/boost/geometry/strategies/transform/inverse_transformer.hpp b/boost/geometry/strategies/transform/inverse_transformer.hpp
index e64a46e4a8..5213bce47a 100644
--- a/boost/geometry/strategies/transform/inverse_transformer.hpp
+++ b/boost/geometry/strategies/transform/inverse_transformer.hpp
@@ -14,15 +14,8 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
-// Remove the ublas checking, otherwise the inverse might fail
-// (while nothing seems to be wrong)
-#ifdef BOOST_UBLAS_TYPE_CHECK
-#undef BOOST_UBLAS_TYPE_CHECK
-#endif
-#define BOOST_UBLAS_TYPE_CHECK 0
-
-#include <boost/numeric/ublas/lu.hpp>
-#include <boost/numeric/ublas/io.hpp>
+#include <boost/qvm/mat.hpp>
+#include <boost/qvm/mat_operations.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
@@ -44,31 +37,13 @@ template
std::size_t Dimension2
>
class inverse_transformer
- : public ublas_transformer<CalculationType, Dimension1, Dimension2>
+ : public matrix_transformer<CalculationType, Dimension1, Dimension2>
{
public :
template <typename Transformer>
inline inverse_transformer(Transformer const& input)
{
- typedef boost::numeric::ublas::matrix<CalculationType> matrix_type;
-
- // create a working copy of the input
- matrix_type copy(input.matrix());
-
- // create a permutation matrix for the LU-factorization
- typedef boost::numeric::ublas::permutation_matrix<> permutation_matrix;
- permutation_matrix pm(copy.size1());
-
- // perform LU-factorization
- int res = boost::numeric::ublas::lu_factorize<matrix_type>(copy, pm);
- if( res == 0 )
- {
- // create identity matrix
- this->m_matrix.assign(boost::numeric::ublas::identity_matrix<CalculationType>(copy.size1()));
-
- // backsubstitute to get the inverse
- boost::numeric::ublas::lu_substitute(copy, pm, this->m_matrix);
- }
+ this->m_matrix = boost::qvm::inverse(input.matrix());
}
};
diff --git a/boost/geometry/strategies/transform/map_transformer.hpp b/boost/geometry/strategies/transform/map_transformer.hpp
index 1109e814b9..01ea6168c5 100644
--- a/boost/geometry/strategies/transform/map_transformer.hpp
+++ b/boost/geometry/strategies/transform/map_transformer.hpp
@@ -46,9 +46,10 @@ template
bool SameScale = true
>
class map_transformer
- : public ublas_transformer<CalculationType, Dimension1, Dimension2>
+ : public matrix_transformer<CalculationType, Dimension1, Dimension2>
{
- typedef boost::numeric::ublas::matrix<CalculationType> M;
+ typedef boost::qvm::mat<CalculationType, Dimension1 + 1, Dimension2 + 1> M;
+ typedef boost::qvm::mat<CalculationType, 3, 3> matrix33;
public :
template <typename B, typename D>
@@ -76,26 +77,26 @@ private :
{
// Translate to a coordinate system centered on world coordinates (-wx, -wy)
- M t1(3,3);
- t1(0,0) = 1; t1(0,1) = 0; t1(0,2) = -wx;
- t1(1,0) = 0; t1(1,1) = 1; t1(1,2) = -wy;
- t1(2,0) = 0; t1(2,1) = 0; t1(2,2) = 1;
+ matrix33 t1;
+ qvm::A<0,0>(t1) = 1; qvm::A<0,1>(t1) = 0; qvm::A<0,2>(t1) = -wx;
+ qvm::A<1,0>(t1) = 0; qvm::A<1,1>(t1) = 1; qvm::A<1,2>(t1) = -wy;
+ qvm::A<2,0>(t1) = 0; qvm::A<2,1>(t1) = 0; qvm::A<2,2>(t1) = 1;
// Scale the map
- M s(3,3);
- s(0,0) = scalex; s(0,1) = 0; s(0,2) = 0;
- s(1,0) = 0; s(1,1) = scaley; s(1,2) = 0;
- s(2,0) = 0; s(2,1) = 0; s(2,2) = 1;
+ matrix33 s;
+ qvm::A<0,0>(s) = scalex; qvm::A<0,1>(s) = 0; qvm::A<0,2>(s) = 0;
+ qvm::A<1,0>(s) = 0; qvm::A<1,1>(s) = scaley; qvm::A<1,2>(s) = 0;
+ qvm::A<2,0>(s) = 0; qvm::A<2,1>(s) = 0; qvm::A<2,2>(s) = 1;
// Translate to a coordinate system centered on the specified pixels (+px, +py)
- M t2(3, 3);
- t2(0,0) = 1; t2(0,1) = 0; t2(0,2) = px;
- t2(1,0) = 0; t2(1,1) = 1; t2(1,2) = py;
- t2(2,0) = 0; t2(2,1) = 0; t2(2,2) = 1;
+ matrix33 t2;
+ qvm::A<0,0>(t2) = 1; qvm::A<0,1>(t2) = 0; qvm::A<0,2>(t2) = px;
+ qvm::A<1,0>(t2) = 0; qvm::A<1,1>(t2) = 1; qvm::A<1,2>(t2) = py;
+ qvm::A<2,0>(t2) = 0; qvm::A<2,1>(t2) = 0; qvm::A<2,2>(t2) = 1;
// Calculate combination matrix in two steps
- this->m_matrix = boost::numeric::ublas::prod(s, t1);
- this->m_matrix = boost::numeric::ublas::prod(t2, this->m_matrix);
+ this->m_matrix = s * t1;
+ this->m_matrix = t2 * this->m_matrix;
}
@@ -140,20 +141,20 @@ private :
if (Mirror)
{
// Mirror in y-direction
- M m(3,3);
- m(0,0) = 1; m(0,1) = 0; m(0,2) = 0;
- m(1,0) = 0; m(1,1) = -1; m(1,2) = 0;
- m(2,0) = 0; m(2,1) = 0; m(2,2) = 1;
+ matrix33 m;
+ qvm::A<0,0>(m) = 1; qvm::A<0,1>(m) = 0; qvm::A<0,2>(m) = 0;
+ qvm::A<1,0>(m) = 0; qvm::A<1,1>(m) = -1; qvm::A<1,2>(m) = 0;
+ qvm::A<2,0>(m) = 0; qvm::A<2,1>(m) = 0; qvm::A<2,2>(m) = 1;
// Translate in y-direction such that it fits again
- M y(3, 3);
- y(0,0) = 1; y(0,1) = 0; y(0,2) = 0;
- y(1,0) = 0; y(1,1) = 1; y(1,2) = height;
- y(2,0) = 0; y(2,1) = 0; y(2,2) = 1;
+ matrix33 y;
+ qvm::A<0,0>(y) = 1; qvm::A<0,1>(y) = 0; qvm::A<0,2>(y) = 0;
+ qvm::A<1,0>(y) = 0; qvm::A<1,1>(y) = 1; qvm::A<1,2>(y) = height;
+ qvm::A<2,0>(y) = 0; qvm::A<2,1>(y) = 0; qvm::A<2,2>(y) = 1;
// Calculate combination matrix in two steps
- this->m_matrix = boost::numeric::ublas::prod(m, this->m_matrix);
- this->m_matrix = boost::numeric::ublas::prod(y, this->m_matrix);
+ this->m_matrix = m * this->m_matrix;
+ this->m_matrix = y * this->m_matrix;
}
}
};
diff --git a/boost/geometry/strategies/transform/matrix_transformers.hpp b/boost/geometry/strategies/transform/matrix_transformers.hpp
index d891263a7d..e0ac6496f3 100644
--- a/boost/geometry/strategies/transform/matrix_transformers.hpp
+++ b/boost/geometry/strategies/transform/matrix_transformers.hpp
@@ -22,27 +22,9 @@
#include <cstddef>
-// Remove the ublas checking, otherwise the inverse might fail
-// (while nothing seems to be wrong)
-#ifdef BOOST_UBLAS_TYPE_CHECK
-#undef BOOST_UBLAS_TYPE_CHECK
-#endif
-#define BOOST_UBLAS_TYPE_CHECK 0
-
-#include <boost/numeric/conversion/cast.hpp>
-
-#if defined(__clang__)
-// Avoid warning about unused UBLAS function: boost_numeric_ublas_abs
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-#endif
-
-#include <boost/numeric/ublas/vector.hpp>
-#include <boost/numeric/ublas/matrix.hpp>
-
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
+#include <boost/qvm/mat.hpp>
+#include <boost/qvm/mat_access.hpp>
+#include <boost/qvm/mat_operations.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -75,38 +57,37 @@ template
std::size_t Dimension1,
std::size_t Dimension2
>
-class ublas_transformer
+class matrix_transformer
{
};
template <typename CalculationType>
-class ublas_transformer<CalculationType, 2, 2>
+class matrix_transformer<CalculationType, 2, 2>
{
protected :
typedef CalculationType ct;
- typedef boost::numeric::ublas::matrix<ct> matrix_type;
+ typedef boost::qvm::mat<ct, 3, 3> matrix_type;
matrix_type m_matrix;
public :
- inline ublas_transformer(
+ inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
- : m_matrix(3, 3)
{
- m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2;
- m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2;
- m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2;
+ qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2;
+ qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2;
+ qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2;
}
- inline ublas_transformer(matrix_type const& matrix)
+ inline matrix_transformer(matrix_type const& matrix)
: m_matrix(matrix)
{}
- inline ublas_transformer() : m_matrix(3, 3) {}
+ inline matrix_transformer() {}
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
@@ -117,8 +98,8 @@ public :
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
- ct p2x = c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + m_matrix(0,2);
- ct p2y = c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + m_matrix(1,2);
+ ct p2x = c1 * qvm::A<0,0>(m_matrix) + c2 * qvm::A<0,1>(m_matrix) + qvm::A<0,2>(m_matrix);
+ ct p2y = c1 * qvm::A<1,0>(m_matrix) + c2 * qvm::A<1,1>(m_matrix) + qvm::A<1,2>(m_matrix);
typedef typename geometry::coordinate_type<P2>::type ct2;
set<0>(p2, boost::numeric_cast<ct2>(p2x));
@@ -133,51 +114,50 @@ public :
// It IS possible to go from 3 to 2 coordinates
template <typename CalculationType>
-class ublas_transformer<CalculationType, 3, 2> : public ublas_transformer<CalculationType, 2, 2>
+class matrix_transformer<CalculationType, 3, 2> : public matrix_transformer<CalculationType, 2, 2>
{
typedef CalculationType ct;
public :
- inline ublas_transformer(
+ inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
m_0_0, m_0_1, m_0_2,
m_1_0, m_1_1, m_1_2,
m_2_0, m_2_1, m_2_2)
{}
- inline ublas_transformer()
- : ublas_transformer<CalculationType, 2, 2>()
+ inline matrix_transformer()
+ : matrix_transformer<CalculationType, 2, 2>()
{}
};
template <typename CalculationType>
-class ublas_transformer<CalculationType, 3, 3>
+class matrix_transformer<CalculationType, 3, 3>
{
protected :
typedef CalculationType ct;
- typedef boost::numeric::ublas::matrix<ct> matrix_type;
+ typedef boost::qvm::mat<ct, 4, 4> matrix_type;
matrix_type m_matrix;
public :
- inline ublas_transformer(
+ inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
)
- : m_matrix(4, 4)
{
- m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2; m_matrix(0,3) = m_0_3;
- m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2; m_matrix(1,3) = m_1_3;
- m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2; m_matrix(2,3) = m_2_3;
- m_matrix(3,0) = m_3_0; m_matrix(3,1) = m_3_1; m_matrix(3,2) = m_3_2; m_matrix(3,3) = m_3_3;
+ qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2; qvm::A<0,3>(m_matrix) = m_0_3;
+ qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2; qvm::A<1,3>(m_matrix) = m_1_3;
+ qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2; qvm::A<2,3>(m_matrix) = m_2_3;
+ qvm::A<3,0>(m_matrix) = m_3_0; qvm::A<3,1>(m_matrix) = m_3_1; qvm::A<3,2>(m_matrix) = m_3_2; qvm::A<3,3>(m_matrix) = m_3_3;
}
- inline ublas_transformer() : m_matrix(4, 4) {}
+ inline matrix_transformer() {}
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
@@ -222,7 +202,7 @@ class translate_transformer
template<typename CalculationType>
-class translate_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>
+class translate_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
{
public :
// To have translate transformers compatible for 2/3 dimensions, the
@@ -230,7 +210,7 @@ public :
inline translate_transformer(CalculationType const& translate_x,
CalculationType const& translate_y,
CalculationType const& = 0)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
1, 0, translate_x,
0, 1, translate_y,
0, 0, 1)
@@ -239,13 +219,13 @@ public :
template <typename CalculationType>
-class translate_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>
+class translate_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
{
public :
inline translate_transformer(CalculationType const& translate_x,
CalculationType const& translate_y,
CalculationType const& translate_z)
- : ublas_transformer<CalculationType, 3, 3>(
+ : matrix_transformer<CalculationType, 3, 3>(
1, 0, 0, translate_x,
0, 1, 0, translate_y,
0, 0, 1, translate_z,
@@ -275,14 +255,14 @@ class scale_transformer
template <typename CalculationType>
-class scale_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>
+class scale_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
{
public :
inline scale_transformer(CalculationType const& scale_x,
CalculationType const& scale_y,
CalculationType const& = 0)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
scale_x, 0, 0,
0, scale_y, 0,
0, 0, 1)
@@ -290,7 +270,7 @@ public :
inline scale_transformer(CalculationType const& scale)
- : ublas_transformer<CalculationType, 2, 2>(
+ : matrix_transformer<CalculationType, 2, 2>(
scale, 0, 0,
0, scale, 0,
0, 0, 1)
@@ -299,13 +279,13 @@ public :
template <typename CalculationType>
-class scale_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>
+class scale_transformer<CalculationType, 3, 3> : public matrix_transformer<CalculationType, 3, 3>
{
public :
inline scale_transformer(CalculationType const& scale_x,
CalculationType const& scale_y,
CalculationType const& scale_z)
- : ublas_transformer<CalculationType, 3, 3>(
+ : matrix_transformer<CalculationType, 3, 3>(
scale_x, 0, 0, 0,
0, scale_y, 0, 0,
0, 0, scale_z, 0,
@@ -314,7 +294,7 @@ public :
inline scale_transformer(CalculationType const& scale)
- : ublas_transformer<CalculationType, 3, 3>(
+ : matrix_transformer<CalculationType, 3, 3>(
scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, scale, 0,
@@ -363,11 +343,11 @@ template
std::size_t Dimension2
>
class rad_rotate_transformer
- : public ublas_transformer<CalculationType, Dimension1, Dimension2>
+ : public matrix_transformer<CalculationType, Dimension1, Dimension2>
{
public :
inline rad_rotate_transformer(CalculationType const& angle)
- : ublas_transformer<CalculationType, Dimension1, Dimension2>(
+ : matrix_transformer<CalculationType, Dimension1, Dimension2>(
cos(angle), sin(angle), 0,
-sin(angle), cos(angle), 0,
0, 0, 1)
diff --git a/boost/geometry/strategies/within.hpp b/boost/geometry/strategies/within.hpp
index d625bc40e6..28a3283db0 100644
--- a/boost/geometry/strategies/within.hpp
+++ b/boost/geometry/strategies/within.hpp
@@ -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 2017.
+// Modifications copyright (c) 2017, 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.
@@ -16,6 +21,12 @@
#include <boost/mpl/assert.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
namespace boost { namespace geometry
{
@@ -30,23 +41,39 @@ namespace services
/*!
\brief Traits class binding a within determination strategy to a coordinate system
\ingroup within
-\tparam TagContained tag (possibly casted) of point-type
-\tparam TagContained tag (possibly casted) of (possibly) containing type
-\tparam CsTagContained tag of coordinate system of point-type
-\tparam CsTagContaining tag of coordinate system of (possibly) containing type
-\tparam Geometry geometry-type of input (often point, or box)
+\tparam GeometryContained geometry-type of input (possibly) contained type
\tparam GeometryContaining geometry-type of input (possibly) containing type
+\tparam TagContained casted tag of (possibly) contained type
+\tparam TagContaining casted tag of (possibly) containing type
+\tparam CsTagContained tag of coordinate system of (possibly) contained type
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type
*/
template
<
- typename TagContained,
- typename TagContaining,
- typename CastedTagContained,
- typename CastedTagContaining,
- typename CsTagContained,
- typename CsTagContaining,
typename GeometryContained,
- typename GeometryContaining
+ typename GeometryContaining,
+ typename TagContained = typename tag<GeometryContained>::type,
+ typename TagContaining = typename tag<GeometryContaining>::type,
+ typename CastedTagContained = typename tag_cast
+ <
+ typename tag<GeometryContained>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CastedTagContaining = typename tag_cast
+ <
+ typename tag<GeometryContaining>::type,
+ pointlike_tag, linear_tag, polygonal_tag, areal_tag
+ >::type,
+ typename CsTagContained = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContained>::type>::type,
+ spherical_tag
+ >::type,
+ typename CsTagContaining = typename tag_cast
+ <
+ typename cs_tag<typename point_type<GeometryContaining>::type>::type,
+ spherical_tag
+ >::type
>
struct default_strategy
{
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
index 234cfa1ed0..b1c3648c98 100644
--- a/boost/geometry/util/math.hpp
+++ b/boost/geometry/util/math.hpp
@@ -71,6 +71,19 @@ inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T c
}
+template <typename T>
+inline T bounded(T const& v, T const& lower, T const& upper)
+{
+ return (std::min)((std::max)(v, lower), upper);
+}
+
+template <typename T>
+inline T bounded(T const& v, T const& lower)
+{
+ return (std::max)(v, lower);
+}
+
+
template <typename T,
bool IsFloatingPoint = boost::is_floating_point<T>::value>
struct abs
@@ -518,7 +531,7 @@ inline T scaled_epsilon(T const& value)
}
-// Maybe replace this by boost equals or boost ublas numeric equals or so
+// Maybe replace this by boost equals or so
/*!
\brief returns true if both arguments are equal.
diff --git a/boost/geometry/util/normalize_spheroidal_coordinates.hpp b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
index 377051eef1..19d4d33d28 100644
--- a/boost/geometry/util/normalize_spheroidal_coordinates.hpp
+++ b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
@@ -282,6 +282,40 @@ inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitud
return diff;
}
+/*!
+\brief The abs difference between longitudes in range [0, 180].
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude1 Longitude 1
+\param longitude2 Longitude 2
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline CoordinateType longitude_difference(CoordinateType const& longitude1,
+ CoordinateType const& longitude2)
+{
+ return math::abs(math::longitude_distance_signed<Units>(longitude1, longitude2));
+}
+
+template <typename Units, typename CoordinateType>
+inline CoordinateType longitude_interval_distance_signed(CoordinateType const& longitude_a1,
+ CoordinateType const& longitude_a2,
+ CoordinateType const& longitude_b)
+{
+ CoordinateType const c0 = 0;
+ CoordinateType dist_a12 = longitude_distance_signed<Units>(longitude_a1, longitude_a2);
+ CoordinateType dist_a1b = longitude_distance_signed<Units>(longitude_a1, longitude_b);
+ if (dist_a12 < c0)
+ {
+ dist_a12 = -dist_a12;
+ dist_a1b = -dist_a1b;
+ }
+
+ return dist_a1b < c0 ? dist_a1b
+ : dist_a1b > dist_a12 ? dist_a1b - dist_a12
+ : c0;
+}
+
} // namespace math