summaryrefslogtreecommitdiff
path: root/boost/geometry
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry')
-rw-r--r--boost/geometry/algorithms/append.hpp2
-rw-r--r--boost/geometry/algorithms/assign.hpp6
-rw-r--r--boost/geometry/algorithms/buffer.hpp13
-rw-r--r--boost/geometry/algorithms/centroid.hpp20
-rw-r--r--boost/geometry/algorithms/clear.hpp2
-rw-r--r--boost/geometry/algorithms/convert.hpp2
-rw-r--r--boost/geometry/algorithms/convex_hull.hpp13
-rw-r--r--boost/geometry/algorithms/crosses.hpp53
-rw-r--r--boost/geometry/algorithms/detail/andoyer_inverse.hpp163
-rw-r--r--boost/geometry/algorithms/detail/azimuth.hpp4
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp104
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_policies.hpp35
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp192
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_ring.hpp9
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp51
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp244
-rw-r--r--boost/geometry/algorithms/detail/check_iterator_range.hpp4
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp5
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp6
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp15
-rw-r--r--boost/geometry/algorithms/detail/comparable_distance/interface.hpp8
-rw-r--r--boost/geometry/algorithms/detail/disjoint/interface.hpp2
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp140
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_geometry.hpp47
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_point.hpp165
-rw-r--r--boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp24
-rw-r--r--boost/geometry/algorithms/detail/distance/interface.hpp8
-rw-r--r--boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp5
-rw-r--r--boost/geometry/algorithms/detail/distance/segment_to_box.hpp8
-rw-r--r--boost/geometry/algorithms/detail/envelope/box.hpp167
-rw-r--r--boost/geometry/algorithms/detail/envelope/implementation.hpp106
-rw-r--r--boost/geometry/algorithms/detail/envelope/initialize.hpp86
-rw-r--r--boost/geometry/algorithms/detail/envelope/interface.hpp126
-rw-r--r--boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp78
-rw-r--r--boost/geometry/algorithms/detail/envelope/linear.hpp96
-rw-r--r--boost/geometry/algorithms/detail/envelope/multipoint.hpp378
-rw-r--r--boost/geometry/algorithms/detail/envelope/point.hpp127
-rw-r--r--boost/geometry/algorithms/detail/envelope/range.hpp179
-rw-r--r--boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp326
-rw-r--r--boost/geometry/algorithms/detail/envelope/segment.hpp386
-rw-r--r--boost/geometry/algorithms/detail/envelope/transform_units.hpp103
-rw-r--r--boost/geometry/algorithms/detail/expand/box.hpp126
-rw-r--r--boost/geometry/algorithms/detail/expand/implementation.hpp27
-rw-r--r--boost/geometry/algorithms/detail/expand/indexed.hpp144
-rw-r--r--boost/geometry/algorithms/detail/expand/interface.hpp128
-rw-r--r--boost/geometry/algorithms/detail/expand/point.hpp303
-rw-r--r--boost/geometry/algorithms/detail/expand/segment.hpp115
-rw-r--r--boost/geometry/algorithms/detail/get_left_turns.hpp18
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp28
-rw-r--r--boost/geometry/algorithms/detail/intersection/multi.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp12
-rw-r--r--boost/geometry/algorithms/detail/is_valid/box.hpp5
-rw-r--r--boost/geometry/algorithms/detail/is_valid/complement_graph.hpp18
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_spikes.hpp40
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp7
-rw-r--r--boost/geometry/algorithms/detail/is_valid/interface.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp5
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp18
-rw-r--r--boost/geometry/algorithms/detail/is_valid/pointlike.hpp10
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp15
-rw-r--r--boost/geometry/algorithms/detail/is_valid/ring.hpp9
-rw-r--r--boost/geometry/algorithms/detail/is_valid/segment.hpp5
-rw-r--r--boost/geometry/algorithms/detail/max_interval_gap.hpp278
-rw-r--r--boost/geometry/algorithms/detail/normalize.hpp294
-rw-r--r--boost/geometry/algorithms/detail/occupation_info.hpp31
-rw-r--r--boost/geometry/algorithms/detail/overlay/add_rings.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/check_enrich.hpp4
-rw-r--r--boost/geometry/algorithms/detail/overlay/clip_linestring.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp14
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segments.hpp47
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrichment_info.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow.hpp14
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp20
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp3
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_ring.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp25
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp93
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp8
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp27
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp132
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp30
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp23
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp343
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp8
-rw-r--r--boost/geometry/algorithms/detail/overlay/ring_properties.hpp7
-rw-r--r--boost/geometry/algorithms/detail/overlay/segment_identifier.hpp18
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp1
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp9
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp456
-rw-r--r--boost/geometry/algorithms/detail/recalculate.hpp1
-rw-r--r--boost/geometry/algorithms/detail/relate/areal_areal.hpp28
-rw-r--r--boost/geometry/algorithms/detail/relate/boundary_checker.hpp2
-rw-r--r--boost/geometry/algorithms/detail/relate/de9im.hpp439
-rw-r--r--boost/geometry/algorithms/detail/relate/follow_helpers.hpp22
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation.hpp110
-rw-r--r--boost/geometry/algorithms/detail/relate/interface.hpp348
-rw-r--r--boost/geometry/algorithms/detail/relate/less.hpp4
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_areal.hpp71
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_linear.hpp16
-rw-r--r--boost/geometry/algorithms/detail/relate/point_geometry.hpp17
-rw-r--r--boost/geometry/algorithms/detail/relate/point_point.hpp39
-rw-r--r--boost/geometry/algorithms/detail/relate/relate.hpp339
-rw-r--r--boost/geometry/algorithms/detail/relate/relate_impl.hpp80
-rw-r--r--boost/geometry/algorithms/detail/relate/result.hpp648
-rw-r--r--boost/geometry/algorithms/detail/relate/turns.hpp33
-rw-r--r--boost/geometry/algorithms/detail/relation/implementation.hpp18
-rw-r--r--boost/geometry/algorithms/detail/relation/interface.hpp186
-rw-r--r--boost/geometry/algorithms/detail/result_inverse.hpp44
-rw-r--r--boost/geometry/algorithms/detail/ring_identifier.hpp14
-rw-r--r--boost/geometry/algorithms/detail/sections/range_by_section.hpp4
-rw-r--r--boost/geometry/algorithms/detail/sections/sectionalize.hpp33
-rw-r--r--boost/geometry/algorithms/detail/signed_size_type.hpp (renamed from boost/geometry/algorithms/detail/signed_index_type.hpp)11
-rw-r--r--boost/geometry/algorithms/detail/single_geometry.hpp12
-rw-r--r--boost/geometry/algorithms/detail/sub_range.hpp12
-rw-r--r--boost/geometry/algorithms/detail/sweep.hpp87
-rw-r--r--boost/geometry/algorithms/detail/thomas_inverse.hpp191
-rw-r--r--boost/geometry/algorithms/detail/throw_on_empty_input.hpp15
-rw-r--r--boost/geometry/algorithms/detail/turns/compare_turns.hpp16
-rw-r--r--boost/geometry/algorithms/detail/turns/print_turns.hpp4
-rw-r--r--boost/geometry/algorithms/detail/vincenty_direct.hpp121
-rw-r--r--boost/geometry/algorithms/detail/vincenty_inverse.hpp166
-rw-r--r--boost/geometry/algorithms/detail/within/point_in_geometry.hpp8
-rw-r--r--boost/geometry/algorithms/dispatch/envelope.hpp49
-rw-r--r--boost/geometry/algorithms/dispatch/expand.hpp58
-rw-r--r--boost/geometry/algorithms/envelope.hpp294
-rw-r--r--boost/geometry/algorithms/equals.hpp13
-rw-r--r--boost/geometry/algorithms/expand.hpp348
-rw-r--r--boost/geometry/algorithms/is_convex.hpp160
-rw-r--r--boost/geometry/algorithms/is_empty.hpp207
-rw-r--r--boost/geometry/algorithms/length.hpp2
-rw-r--r--boost/geometry/algorithms/overlaps.hpp7
-rw-r--r--boost/geometry/algorithms/relate.hpp17
-rw-r--r--boost/geometry/algorithms/relation.hpp17
-rw-r--r--boost/geometry/algorithms/simplify.hpp2
-rw-r--r--boost/geometry/algorithms/sym_difference.hpp201
-rw-r--r--boost/geometry/algorithms/touches.hpp17
-rw-r--r--boost/geometry/algorithms/transform.hpp31
-rw-r--r--boost/geometry/algorithms/within.hpp30
-rw-r--r--boost/geometry/arithmetic/arithmetic.hpp101
-rw-r--r--boost/geometry/core/assert.hpp43
-rw-r--r--boost/geometry/core/exception.hpp38
-rw-r--r--boost/geometry/core/radian_access.hpp16
-rw-r--r--boost/geometry/geometries/box.hpp89
-rw-r--r--boost/geometry/geometries/concepts/point_concept.hpp2
-rw-r--r--boost/geometry/geometries/helper_geometry.hpp162
-rw-r--r--boost/geometry/geometries/linestring.hpp5
-rw-r--r--boost/geometry/geometries/multi_linestring.hpp11
-rw-r--r--boost/geometry/geometries/multi_point.hpp6
-rw-r--r--boost/geometry/geometries/multi_polygon.hpp11
-rw-r--r--boost/geometry/geometries/point.hpp62
-rw-r--r--boost/geometry/geometries/point_xy.hpp10
-rw-r--r--boost/geometry/geometries/pointing_segment.hpp13
-rw-r--r--boost/geometry/geometries/polygon.hpp10
-rw-r--r--boost/geometry/geometries/ring.hpp5
-rw-r--r--boost/geometry/geometries/segment.hpp21
-rw-r--r--boost/geometry/geometry.hpp7
-rw-r--r--boost/geometry/index/detail/assert.hpp10
-rw-r--r--boost/geometry/index/detail/bounded_view.hpp64
-rw-r--r--boost/geometry/index/detail/predicates.hpp10
-rw-r--r--boost/geometry/index/detail/rtree/iterators.hpp122
-rw-r--r--boost/geometry/index/detail/rtree/node/node.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp66
-rw-r--r--boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/query_iterators.hpp27
-rw-r--r--boost/geometry/index/detail/rtree/visitors/distance_query.hpp8
-rw-r--r--boost/geometry/index/detail/rtree/visitors/iterator.hpp134
-rw-r--r--boost/geometry/index/detail/rtree/visitors/spatial_query.hpp10
-rw-r--r--boost/geometry/index/rtree.hpp341
-rw-r--r--boost/geometry/io/svg/svg_mapper.hpp21
-rw-r--r--boost/geometry/io/wkt/read.hpp146
-rw-r--r--boost/geometry/io/wkt/write.hpp19
-rw-r--r--boost/geometry/iterators/concatenate_iterator.hpp1
-rw-r--r--boost/geometry/iterators/detail/segment_iterator/value_type.hpp38
-rw-r--r--boost/geometry/iterators/flatten_iterator.hpp19
-rw-r--r--boost/geometry/iterators/point_iterator.hpp1
-rw-r--r--boost/geometry/multi/multi.hpp73
-rw-r--r--boost/geometry/policies/is_valid/failing_reason_policy.hpp12
-rw-r--r--boost/geometry/policies/relate/de9im.hpp168
-rw-r--r--boost/geometry/policies/relate/intersection_points.hpp32
-rw-r--r--boost/geometry/policies/robustness/get_rescale_policy.hpp56
-rw-r--r--boost/geometry/policies/robustness/rescale_policy.hpp17
-rw-r--r--boost/geometry/policies/robustness/segment_ratio.hpp38
-rw-r--r--boost/geometry/strategies/agnostic/hull_graham_andrew.hpp3
-rw-r--r--boost/geometry/strategies/agnostic/relate.hpp30
-rw-r--r--boost/geometry/strategies/agnostic/side_by_azimuth.hpp87
-rw-r--r--boost/geometry/strategies/buffer.hpp14
-rw-r--r--boost/geometry/strategies/cartesian/buffer_end_round.hpp10
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_miter.hpp4
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_round.hpp16
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp1
-rw-r--r--boost/geometry/strategies/cartesian/buffer_point_circle.hpp3
-rw-r--r--boost/geometry/strategies/cartesian/buffer_side_straight.hpp39
-rw-r--r--boost/geometry/strategies/cartesian/cart_intersect.hpp27
-rw-r--r--boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp24
-rw-r--r--boost/geometry/strategies/cartesian/centroid_weighted_length.hpp41
-rw-r--r--boost/geometry/strategies/cartesian/side_of_intersection.hpp248
-rw-r--r--boost/geometry/strategies/geographic/distance_thomas.hpp156
-rw-r--r--boost/geometry/strategies/geographic/distance_vincenty.hpp13
-rw-r--r--boost/geometry/strategies/geographic/side_andoyer.hpp55
-rw-r--r--boost/geometry/strategies/geographic/side_detail.hpp139
-rw-r--r--boost/geometry/strategies/geographic/side_thomas.hpp55
-rw-r--r--boost/geometry/strategies/geographic/side_vincenty.hpp55
-rw-r--r--boost/geometry/strategies/intersection_result.hpp143
-rw-r--r--boost/geometry/strategies/spherical/area_huiller.hpp58
-rw-r--r--boost/geometry/strategies/spherical/distance_cross_track.hpp19
-rw-r--r--boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp293
-rw-r--r--boost/geometry/strategies/strategies.hpp12
-rw-r--r--boost/geometry/strategies/strategy_transform.hpp33
-rw-r--r--boost/geometry/strategies/transform/matrix_transformers.hpp15
-rw-r--r--boost/geometry/util/math.hpp171
-rw-r--r--boost/geometry/util/normalize_spheroidal_box_coordinates.hpp160
-rw-r--r--boost/geometry/util/normalize_spheroidal_coordinates.hpp218
-rw-r--r--boost/geometry/util/range.hpp28
-rw-r--r--boost/geometry/views/detail/boundary_view.hpp16
-rw-r--r--boost/geometry/views/detail/boundary_view/implementation.hpp466
-rw-r--r--boost/geometry/views/detail/boundary_view/interface.hpp70
-rw-r--r--boost/geometry/views/detail/indexed_point_view.hpp33
-rw-r--r--boost/geometry/views/detail/two_dimensional_view.hpp196
223 files changed, 12572 insertions, 3522 deletions
diff --git a/boost/geometry/algorithms/append.hpp b/boost/geometry/algorithms/append.hpp
index 6ffb5f9587..894f52c68b 100644
--- a/boost/geometry/algorithms/append.hpp
+++ b/boost/geometry/algorithms/append.hpp
@@ -327,7 +327,7 @@ struct append<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
int ring_index,
int multi_index)
{
- apply_visitor(
+ boost::apply_visitor(
visitor<RangeOrPoint>(
range_or_point,
ring_index,
diff --git a/boost/geometry/algorithms/assign.hpp b/boost/geometry/algorithms/assign.hpp
index 2f325448ad..b17e305f2a 100644
--- a/boost/geometry/algorithms/assign.hpp
+++ b/boost/geometry/algorithms/assign.hpp
@@ -281,7 +281,7 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
Geometry2 const& geometry2)
{
- return apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor(geometry2), geometry1);
}
};
@@ -313,7 +313,7 @@ struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
apply(Geometry1& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
{
- return apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor(geometry1), geometry2);
}
};
@@ -341,7 +341,7 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
{
- return apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor(), geometry1, geometry2);
}
};
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
index d85d32a0c6..e776072a2f 100644
--- a/boost/geometry/algorithms/buffer.hpp
+++ b/boost/geometry/algorithms/buffer.hpp
@@ -18,12 +18,15 @@
#include <boost/numeric/conversion/cast.hpp>
+#include <boost/range.hpp>
+
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -261,9 +264,15 @@ inline void buffer(GeometryIn const& geometry_in,
geometry_out.clear();
+ if (geometry::is_empty(geometry_in))
+ {
+ // Then output geometry is kept empty as well
+ return;
+ }
+
model::box<point_type> box;
- envelope(geometry_in, box);
- buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
+ geometry::envelope(geometry_in, box);
+ geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
rescale_policy_type rescale_policy
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
diff --git a/boost/geometry/algorithms/centroid.hpp b/boost/geometry/algorithms/centroid.hpp
index 67ed68ac03..1b99ab2ef3 100644
--- a/boost/geometry/algorithms/centroid.hpp
+++ b/boost/geometry/algorithms/centroid.hpp
@@ -1,14 +1,15 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// 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.
// This file was modified by Oracle on 2014, 2015.
// Modifications copyright (c) 2014-2015 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -55,8 +56,7 @@
#include <boost/geometry/util/for_each_coordinate.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
-#include <boost/geometry/algorithms/num_points.hpp>
-#include <boost/geometry/multi/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
@@ -361,7 +361,7 @@ struct centroid_multi
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
// If there is nothing in any of the ranges, it is not possible
// to calculate the centroid
- if (geometry::num_points(multi) == 0)
+ if (geometry::is_empty(multi))
{
throw centroid_exception();
}
@@ -624,7 +624,7 @@ inline void centroid(Geometry const& geometry, Point& c,
template<typename Geometry, typename Point>
inline void centroid(Geometry const& geometry, Point& c)
{
- centroid(geometry, c, default_strategy());
+ geometry::centroid(geometry, c, default_strategy());
}
@@ -643,7 +643,7 @@ template<typename Point, typename Geometry>
inline Point return_centroid(Geometry const& geometry)
{
Point c;
- centroid(geometry, c);
+ geometry::centroid(geometry, c);
return c;
}
@@ -666,7 +666,7 @@ template<typename Point, typename Geometry, typename Strategy>
inline Point return_centroid(Geometry const& geometry, Strategy const& strategy)
{
Point c;
- centroid(geometry, c, strategy);
+ geometry::centroid(geometry, c, strategy);
return c;
}
diff --git a/boost/geometry/algorithms/clear.hpp b/boost/geometry/algorithms/clear.hpp
index 22b61e7c30..54b2162767 100644
--- a/boost/geometry/algorithms/clear.hpp
+++ b/boost/geometry/algorithms/clear.hpp
@@ -162,7 +162,7 @@ struct clear<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
static inline void apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
{
- apply_visitor(visitor(), geometry);
+ boost::apply_visitor(visitor(), geometry);
}
};
diff --git a/boost/geometry/algorithms/convert.hpp b/boost/geometry/algorithms/convert.hpp
index 5d68854a45..78618aed2d 100644
--- a/boost/geometry/algorithms/convert.hpp
+++ b/boost/geometry/algorithms/convert.hpp
@@ -522,7 +522,7 @@ struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Geometry2& geometry2
)
{
- apply_visitor(visitor(geometry2), geometry1);
+ boost::apply_visitor(visitor(geometry2), geometry1);
}
};
diff --git a/boost/geometry/algorithms/convex_hull.hpp b/boost/geometry/algorithms/convex_hull.hpp
index c6db004f3d..71c18bb5f3 100644
--- a/boost/geometry/algorithms/convex_hull.hpp
+++ b/boost/geometry/algorithms/convex_hull.hpp
@@ -1,13 +1,14 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
// Contributed and/or modified by Adam Wulkiewicz, 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
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -40,7 +41,7 @@
#include <boost/geometry/views/detail/range_type.hpp>
-#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/as_range.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
@@ -301,7 +302,7 @@ template<typename Geometry, typename OutputGeometry, typename Strategy>
inline void convex_hull(Geometry const& geometry,
OutputGeometry& out, Strategy const& strategy)
{
- if (geometry::num_points(geometry) == 0)
+ if (geometry::is_empty(geometry))
{
// Leave output empty
return;
@@ -326,7 +327,7 @@ template<typename Geometry, typename OutputGeometry>
inline void convex_hull(Geometry const& geometry,
OutputGeometry& hull)
{
- convex_hull(geometry, hull, default_strategy());
+ geometry::convex_hull(geometry, hull, default_strategy());
}
#ifndef DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/crosses.hpp b/boost/geometry/algorithms/crosses.hpp
index cec4931a64..9546a5335b 100644
--- a/boost/geometry/algorithms/crosses.hpp
+++ b/boost/geometry/algorithms/crosses.hpp
@@ -30,7 +30,8 @@
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
namespace boost { namespace geometry
{
@@ -48,9 +49,9 @@ template
typename Tag2 = typename tag<Geometry2>::type
>
struct crosses
- : detail::relate::relate_base
+ : detail::relate::relate_impl
<
- detail::relate::static_mask_crosses_type,
+ detail::de9im::static_mask_crosses_type,
Geometry1,
Geometry2
>
@@ -87,18 +88,17 @@ namespace resolve_variant
Geometry2 const& m_geometry2;
visitor(Geometry2 const& geometry2)
- : m_geometry2(geometry2)
+ : m_geometry2(geometry2)
{}
template <typename Geometry1>
result_type operator()(Geometry1 const& geometry1) const
{
return crosses
- <
- Geometry1,
- Geometry2
- >::apply
- (geometry1, m_geometry2);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, m_geometry2);
}
};
@@ -106,7 +106,7 @@ namespace resolve_variant
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2)
{
- return apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor(geometry2), geometry1);
}
};
@@ -119,27 +119,25 @@ namespace resolve_variant
Geometry1 const& m_geometry1;
visitor(Geometry1 const& geometry1)
- : m_geometry1(geometry1)
+ : m_geometry1(geometry1)
{}
template <typename Geometry2>
result_type operator()(Geometry2 const& geometry2) const
{
return crosses
- <
- Geometry1,
- Geometry2
- >::apply
- (m_geometry1, geometry2);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(m_geometry1, geometry2);
}
};
static inline bool
- apply(
- Geometry1 const& geometry1,
+ apply(Geometry1 const& geometry1,
const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2)
{
- return apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor(geometry1), geometry2);
}
};
@@ -150,25 +148,22 @@ namespace resolve_variant
struct visitor: static_visitor<bool>
{
template <typename Geometry1, typename Geometry2>
- result_type operator()(
- Geometry1 const& geometry1,
+ result_type operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return crosses
- <
- Geometry1,
- Geometry2
- >::apply
- (geometry1, geometry2);
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2);
}
};
static inline bool
- apply(
- const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
+ apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2)
{
- return apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor(), geometry1, geometry2);
}
};
diff --git a/boost/geometry/algorithms/detail/andoyer_inverse.hpp b/boost/geometry/algorithms/detail/andoyer_inverse.hpp
new file mode 100644
index 0000000000..eb8485b8e1
--- /dev/null
+++ b/boost/geometry/algorithms/detail/andoyer_inverse.hpp
@@ -0,0 +1,163 @@
+// Boost.Geometry
+
+// Copyright (c) 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_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP
+
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+#include <boost/geometry/algorithms/detail/result_inverse.hpp>
+
+
+namespace boost { namespace geometry { namespace detail
+{
+
+/*!
+\brief The solution of the inverse problem of geodesics on latlong coordinates,
+ Forsyth-Andoyer-Lambert type approximation with first order terms.
+\author See
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965
+ http://www.dtic.mil/docs/citations/AD0627893
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970
+ http://www.dtic.mil/docs/citations/AD703541
+*/
+
+template <typename CT, bool EnableDistance, bool EnableAzimuth>
+struct andoyer_inverse
+{
+ typedef result_inverse<CT> result_type;
+
+ template <typename T1, typename T2, typename Spheroid>
+ static inline result_type apply(T1 const& lon1,
+ T1 const& lat1,
+ T2 const& lon2,
+ T2 const& lat2,
+ Spheroid const& spheroid)
+ {
+ result_type result;
+
+ // coordinates in radians
+
+ if ( math::equals(lon1, lon2)
+ && math::equals(lat1, lat2) )
+ {
+ result.set(CT(0), CT(0));
+ return result;
+ }
+
+ CT const pi_half = math::pi<CT>() / CT(2);
+
+ if ( math::equals(math::abs(lat1), pi_half)
+ && math::equals(math::abs(lat2), pi_half) )
+ {
+ result.set(CT(0), CT(0));
+ return result;
+ }
+
+ CT const dlon = lon2 - lon1;
+ CT const sin_dlon = sin(dlon);
+ CT const cos_dlon = cos(dlon);
+ CT const sin_lat1 = sin(lat1);
+ CT const cos_lat1 = cos(lat1);
+ CT const sin_lat2 = sin(lat2);
+ CT const cos_lat2 = cos(lat2);
+
+ // H,G,T = infinity if cos_d = 1 or cos_d = -1
+ // lat1 == +-90 && lat2 == +-90
+ // lat1 == lat2 && lon1 == lon2
+ CT const cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon;
+ CT const d = acos(cos_d);
+ CT const sin_d = sin(d);
+
+ // just in case since above lat1 and lat2 is checked
+ // the check below is equal to cos_d == 1 || cos_d == -1 || d == 0
+ if ( math::equals(sin_d, CT(0)) )
+ {
+ result.set(CT(0), CT(0));
+ return result;
+ }
+
+ // if the function returned before this place
+ // and endpoints were on the poles +-90 deg
+ // in this case the azimuth could either be 0 or +-pi
+
+ CT const f = detail::flattening<CT>(spheroid);
+
+ if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
+ {
+ CT const K = math::sqr(sin_lat1-sin_lat2);
+ CT const L = math::sqr(sin_lat1+sin_lat2);
+ CT const three_sin_d = CT(3) * sin_d;
+ // H or G = infinity if cos_d = 1 or cos_d = -1
+ CT const H = (d+three_sin_d)/(CT(1)-cos_d);
+ CT const G = (d-three_sin_d)/(CT(1)+cos_d);
+
+ // for e.g. lat1=-90 && lat2=90 here we have G*L=INF*0
+ CT const dd = -(f/CT(4))*(H*K+G*L);
+
+ CT const a = get_radius<0>(spheroid);
+
+ result.distance = a * (d + dd);
+ }
+ else
+ {
+ result.distance = CT(0);
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
+ {
+ CT A = CT(0);
+ CT U = CT(0);
+ if ( ! math::equals(cos_lat2, CT(0)) )
+ {
+ CT const tan_lat2 = sin_lat2/cos_lat2;
+ CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
+ A = atan2(sin_dlon, M);
+ CT const sin_2A = sin(CT(2)*A);
+ U = (f/CT(2))*math::sqr(cos_lat1)*sin_2A;
+ }
+
+ CT V = CT(0);
+ if ( ! math::equals(cos_lat1, CT(0)) )
+ {
+ CT const tan_lat1 = sin_lat1/cos_lat1;
+ CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
+ CT const B = atan2(sin_dlon, N);
+ CT const sin_2B = sin(CT(2)*B);
+ V = (f/CT(2))*math::sqr(cos_lat2)*sin_2B;
+ }
+
+ // infinity if sin_d = 0, so cos_d = 1 or cos_d = -1
+ CT const T = d / sin_d;
+ CT const dA = V*T-U;
+
+ result.azimuth = A - dA;
+ }
+ else
+ {
+ result.azimuth = CT(0);
+ }
+
+ return result;
+ }
+};
+
+}}} // namespace boost::geometry::detail
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/azimuth.hpp b/boost/geometry/algorithms/detail/azimuth.hpp
index 7810b4814e..f0a8d65c86 100644
--- a/boost/geometry/algorithms/detail/azimuth.hpp
+++ b/boost/geometry/algorithms/detail/azimuth.hpp
@@ -49,10 +49,10 @@ struct azimuth<ReturnType, geographic_tag>
template <typename P1, typename P2, typename Spheroid>
static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid)
{
- return geometry::detail::vincenty_inverse<ReturnType>
+ return geometry::detail::vincenty_inverse<ReturnType, false, true>
( get_as_radian<0>(p1), get_as_radian<1>(p1),
get_as_radian<0>(p2), get_as_radian<1>(p2),
- spheroid ).azimuth12();
+ spheroid ).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 127e4c3fb2..b25bcc7fb5 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -12,11 +12,12 @@
#include <cstddef>
#include <iterator>
+
#include <boost/core/ignore_unused.hpp>
#include <boost/numeric/conversion/cast.hpp>
-
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@@ -227,7 +228,7 @@ struct buffer_range
typename EndStrategy,
typename RobustPolicy
>
- static inline bool iterate(Collection& collection,
+ static inline strategy::buffer::result_code iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@@ -266,7 +267,7 @@ struct buffer_range
* pup: penultimate_point
*/
- bool result = false;
+ strategy::buffer::result_code result = strategy::buffer::result_no_output;
bool first = true;
Iterator it = begin;
@@ -277,18 +278,25 @@ struct buffer_range
for (Iterator prev = it++; it != end; ++it)
{
generated_side.clear();
- side_strategy.apply(*prev, *it, side,
+ strategy::buffer::result_code error_code
+ = side_strategy.apply(*prev, *it, side,
distance_strategy, generated_side);
- if (generated_side.empty())
+ if (error_code == strategy::buffer::result_no_output)
{
// Because input is simplified, this is improbable,
// but it can happen for degenerate geometries
// Further handling of this side is skipped
continue;
}
+ else if (error_code == strategy::buffer::result_error_numerical)
+ {
+ return error_code;
+ }
+
+ BOOST_GEOMETRY_ASSERT(! generated_side.empty());
- result = true;
+ result = strategy::buffer::result_normal;
if (! first)
{
@@ -383,6 +391,7 @@ inline void buffer_point(Point const& point, Collection& collection,
std::vector<OutputPointType> range_out;
point_strategy.apply(point, distance_strategy, range_out);
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
+ collection.set_piece_center(point);
collection.finish_ring();
}
@@ -458,7 +467,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typename EndStrategy,
typename RobustPolicy
>
- static inline bool iterate(Collection& collection,
+ static inline strategy::buffer::result_code iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@@ -471,13 +480,14 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typedef detail::buffer::buffer_range<RingOutput> buffer_range;
- bool result = buffer_range::iterate(collection, begin, end,
+ strategy::buffer::result_code result
+ = buffer_range::iterate(collection, begin, end,
side,
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1, first_p2, last_p1, last_p2);
// Generate closing join
- if (result)
+ if (result == strategy::buffer::result_normal)
{
buffer_range::add_join(collection,
*(end - 2),
@@ -502,7 +512,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typename PointStrategy,
typename RobustPolicy
>
- static inline void apply(RingInput const& ring,
+ static inline strategy::buffer::result_code apply(RingInput const& ring,
Collection& collection,
DistanceStrategy const& distance,
SideStrategy const& side_strategy,
@@ -514,7 +524,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
RingInput simplified;
detail::buffer::simplify_input(ring, distance, simplified);
- bool has_output = false;
+ strategy::buffer::result_code code = strategy::buffer::result_no_output;
std::size_t n = boost::size(simplified);
std::size_t const min_points = core_detail::closure::minimum_ring_size
@@ -528,21 +538,19 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
if (distance.negative())
{
// Walk backwards (rings will be reversed afterwards)
- // It might be that this will be changed later.
- // TODO: decide this.
- has_output = iterate(collection, boost::rbegin(view), boost::rend(view),
+ code = iterate(collection, boost::rbegin(view), boost::rend(view),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy);
}
else
{
- has_output = iterate(collection, boost::begin(view), boost::end(view),
+ code = iterate(collection, boost::begin(view), boost::end(view),
strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy);
}
}
- if (! has_output && n >= 1)
+ if (code == strategy::buffer::result_no_output && n >= 1)
{
// Use point_strategy to buffer degenerated ring
detail::buffer::buffer_point<output_point_type>
@@ -551,6 +559,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
collection, distance, point_strategy
);
}
+ return code;
}
};
@@ -576,7 +585,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename EndStrategy,
typename RobustPolicy
>
- static inline bool iterate(Collection& collection,
+ static inline strategy::buffer::result_code iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@@ -601,27 +610,33 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
else
{
std::vector<output_point_type> generated_side;
- side_strategy.apply(ultimate_point, penultimate_point,
+ strategy::buffer::result_code code
+ = side_strategy.apply(ultimate_point, penultimate_point,
strategy::buffer::buffer_side_right,
distance_strategy, generated_side);
- if (generated_side.empty())
+ if (code != strategy::buffer::result_normal)
{
- return false;
+ // No output or numerical error
+ return code;
}
reverse_p1 = generated_side.front();
}
output_point_type first_p2, last_p1, last_p2;
- detail::buffer::buffer_range<output_ring_type>::iterate(collection,
+ strategy::buffer::result_code result
+ = detail::buffer::buffer_range<output_ring_type>::iterate(collection,
begin, end, side,
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1, first_p2, last_p1, last_p2);
- std::vector<output_point_type> range_out;
- end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);
- collection.add_endcap(end_strategy, range_out, ultimate_point);
- return true;
+ if (result == strategy::buffer::result_normal)
+ {
+ std::vector<output_point_type> range_out;
+ end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);
+ collection.add_endcap(end_strategy, range_out, ultimate_point);
+ }
+ return result;
}
template
@@ -634,7 +649,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename PointStrategy,
typename RobustPolicy
>
- static inline void apply(Linestring const& linestring, Collection& collection,
+ static inline strategy::buffer::result_code apply(Linestring const& linestring, Collection& collection,
DistanceStrategy const& distance,
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
@@ -645,28 +660,29 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
Linestring simplified;
detail::buffer::simplify_input(linestring, distance, simplified);
- bool has_output = false;
+ strategy::buffer::result_code code = strategy::buffer::result_no_output;
std::size_t n = boost::size(simplified);
if (n > 1)
{
collection.start_new_ring();
output_point_type first_p1;
- has_output = iterate(collection,
+ code = iterate(collection,
boost::begin(simplified), boost::end(simplified),
strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
- if (has_output)
+ if (code == strategy::buffer::result_normal)
{
- iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
+ code = iterate(collection,
+ boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
}
collection.finish_ring();
}
- if (! has_output && n >= 1)
+ if (code == strategy::buffer::result_no_output && n >= 1)
{
// Use point_strategy to buffer degenerated linestring
detail::buffer::buffer_point<output_point_type>
@@ -675,6 +691,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
collection, distance, point_strategy
);
}
+ return code;
}
};
@@ -718,9 +735,16 @@ private:
for (Iterator it = begin; it != end; ++it)
{
collection.start_new_ring();
- policy::apply(*it, collection, distance, side_strategy,
+ strategy::buffer::result_code const code
+ = policy::apply(*it, collection, distance, side_strategy,
join_strategy, end_strategy, point_strategy,
robust_policy);
+
+ if (code == strategy::buffer::result_error_numerical)
+ {
+ collection.abort_ring();
+ return;
+ }
collection.finish_ring(is_interior);
}
}
@@ -774,11 +798,21 @@ public:
{
{
collection.start_new_ring();
- policy::apply(exterior_ring(polygon), collection,
+
+ strategy::buffer::result_code const code
+ = policy::apply(exterior_ring(polygon), collection,
distance, side_strategy,
join_strategy, end_strategy, point_strategy,
robust_policy);
- collection.finish_ring(false, geometry::num_interior_rings(polygon) > 0u);
+
+ if (code == strategy::buffer::result_error_numerical)
+ {
+ collection.abort_ring();
+ }
+ else
+ {
+ collection.finish_ring(false, geometry::num_interior_rings(polygon) > 0u);
+ }
}
apply_interior_rings(interior_rings(polygon),
@@ -910,7 +944,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.reverse();
}
- if (distance_strategy.negative() && areal)
+ if (BOOST_GEOMETRY_CONDITION(distance_strategy.negative() && areal))
{
collection.discard_nonintersecting_deflated_rings();
}
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
index c5bb8acc05..255ac797dc 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
@@ -9,6 +9,9 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION
+#endif
#include <cstddef>
@@ -81,8 +84,8 @@ template <typename Point, typename SegmentRatio>
struct buffer_turn_operation
: public detail::overlay::traversal_turn_operation<Point, SegmentRatio>
{
- int piece_index;
- int index_in_robust_ring;
+ signed_size_type piece_index;
+ signed_size_type index_in_robust_ring;
inline buffer_turn_operation()
: piece_index(-1)
@@ -103,7 +106,7 @@ struct buffer_turn_info
typedef Point point_type;
typedef RobustPoint robust_point_type;
- int turn_index; // TODO: this might go if partition can operate on non-const input
+ std::size_t turn_index; // TODO: this might go if partition can operate on non-const input
RobustPoint robust_point;
#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
@@ -122,24 +125,30 @@ struct buffer_turn_info
intersection_location_type location;
- int count_within;
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;
+#endif
+
+ std::size_t count_within;
bool within_original;
- int count_on_original_boundary;
- int count_in_original; // increased by +1 for in ext.ring, -1 for int.ring
+ std::size_t count_on_original_boundary;
+ signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring
- int count_on_offsetted;
- int count_on_helper;
- int count_within_near_offsetted;
+ std::size_t count_on_offsetted;
+ std::size_t count_on_helper;
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ std::size_t count_within_near_offsetted;
+#endif
bool remove_on_multi;
// Obsolete:
- int count_on_occupied;
- int count_on_multi;
+ std::size_t count_on_occupied;
+ std::size_t count_on_multi;
inline buffer_turn_info()
- : turn_index(-1)
+ : turn_index(0)
, location(location_ok)
, count_within(0)
, within_original(false)
@@ -147,7 +156,9 @@ struct buffer_turn_info
, count_in_original(0)
, count_on_offsetted(0)
, count_on_helper(0)
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
, count_within_near_offsetted(0)
+#endif
, remove_on_multi(false)
, count_on_occupied(0)
, count_on_multi(0)
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index a501e3f197..545d89cb9b 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -16,11 +16,14 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/is_convex.hpp>
#include <boost/geometry/strategies/buffer.hpp>
@@ -126,6 +129,11 @@ struct buffered_piece_collection
typedef geometry::model::ring<robust_point_type> robust_ring_type;
typedef geometry::model::box<robust_point_type> robust_box_type;
+ typedef typename default_comparable_distance_result
+ <
+ robust_point_type
+ >::type robust_comparable_radius_type;
+
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<point_type>::type
@@ -159,7 +167,7 @@ struct buffered_piece_collection
struct robust_turn
{
- int turn_index;
+ std::size_t turn_index;
int operation_index;
robust_point_type point;
segment_identifier seg_id;
@@ -172,10 +180,10 @@ struct buffered_piece_collection
typedef geometry::section<robust_box_type, 1> section_type;
strategy::buffer::piece_type type;
- int index;
+ signed_size_type index;
- int left_index; // points to previous piece of same ring
- int right_index; // points to next piece of same ring
+ signed_size_type left_index; // points to previous piece of same ring
+ signed_size_type right_index; // points to next piece of same ring
// The next two members (1, 2) form together a complete clockwise ring
// for each piece (with one dupped point)
@@ -183,21 +191,21 @@ struct buffered_piece_collection
// 1: half, part of offsetted_rings
segment_identifier first_seg_id;
- int last_segment_index; // no segment-identifier - it is the same as first_seg_id
- int offsetted_count; // part in robust_ring which is part of offsetted ring
+ signed_size_type last_segment_index; // no segment-identifier - it is the same as first_seg_id
+ signed_size_type offsetted_count; // part in robust_ring which is part of offsetted ring
#if defined(BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS)
// 2: half, not part of offsetted rings - part of robust ring
std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
#endif
+ bool is_convex;
bool is_monotonic_increasing[2]; // 0=x, 1=y
bool is_monotonic_decreasing[2]; // 0=x, 1=y
// Monotonic sections of pieces around points
std::vector<section_type> sections;
-
// Robust representations
// 3: complete ring
robust_ring_type robust_ring;
@@ -206,6 +214,27 @@ struct buffered_piece_collection
robust_box_type robust_offsetted_envelope;
std::vector<robust_turn> robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead
+
+ robust_point_type robust_center;
+ robust_comparable_radius_type robust_min_comparable_radius;
+ robust_comparable_radius_type robust_max_comparable_radius;
+
+ piece()
+ : type(strategy::buffer::piece_type_unknown)
+ , index(-1)
+ , left_index(-1)
+ , right_index(-1)
+ , last_segment_index(-1)
+ , offsetted_count(-1)
+ , is_convex(false)
+ , robust_min_comparable_radius(0)
+ , robust_max_comparable_radius(0)
+ {
+ is_monotonic_increasing[0] = false;
+ is_monotonic_increasing[1] = false;
+ is_monotonic_decreasing[0] = false;
+ is_monotonic_decreasing[1] = false;
+ }
};
struct robust_original
@@ -244,7 +273,7 @@ struct buffered_piece_collection
piece_vector_type m_pieces;
turn_vector_type m_turns;
- int m_first_piece_index;
+ signed_size_type m_first_piece_index;
buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index
std::vector<robust_original> robust_originals; // robust representation of the original(s)
@@ -444,6 +473,7 @@ struct buffered_piece_collection
{
it->location = inside_buffer;
}
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
if (it->count_within_near_offsetted > 0)
{
// Within can have in rare cases a rounding issue. We don't discard this
@@ -451,6 +481,7 @@ struct buffered_piece_collection
// will never start a new ring from this type of points.
it->selectable_start = false;
}
+#endif
}
}
@@ -515,7 +546,7 @@ struct buffered_piece_collection
{
// Add rescaled turn points to corresponding pieces
// (after this, each turn occurs twice)
- int index = 0;
+ std::size_t index = 0;
for (typename boost::range_iterator<turn_vector_type>::type it =
boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)
{
@@ -544,16 +575,16 @@ struct buffered_piece_collection
}
}
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
// Insert all rescaled turn-points into these rings, to form a
// reliable integer-based ring. All turns can be compared (inside) to this
// rings to see if they are inside.
- for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
- it != boost::end(m_pieces);
- ++it)
+ for (typename boost::range_iterator<piece_vector_type>::type
+ it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it)
{
piece& pc = *it;
- int piece_segment_index = pc.first_seg_id.segment_index;
+ signed_size_type piece_segment_index = pc.first_seg_id.segment_index;
if (! pc.robust_turns.empty())
{
if (pc.robust_turns.size() > 1u)
@@ -561,14 +592,14 @@ struct buffered_piece_collection
std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less());
}
// Walk through them, in reverse to insert at right index
- int index_offset = pc.robust_turns.size() - 1;
- for (typename std::vector<robust_turn>::const_reverse_iterator
- rit = pc.robust_turns.rbegin();
- rit != pc.robust_turns.rend();
+ signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1;
+ for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type
+ rit = boost::const_rbegin(pc.robust_turns);
+ rit != boost::const_rend(pc.robust_turns);
++rit, --index_offset)
{
- int const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
- BOOST_ASSERT
+ signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
+ BOOST_GEOMETRY_ASSERT
(
index_in_vector > 0
&& index_in_vector < pc.offsetted_count
@@ -582,7 +613,8 @@ struct buffered_piece_collection
}
}
- BOOST_ASSERT(assert_indices_in_robust_rings());
+ BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings());
+#endif
}
template <std::size_t Dimension>
@@ -607,6 +639,8 @@ struct buffered_piece_collection
pc.is_monotonic_decreasing[0] = true;
pc.is_monotonic_decreasing[1] = true;
+ pc.is_convex = geometry::is_convex(pc.robust_ring);
+
if (pc.offsetted_count < 2)
{
return;
@@ -615,14 +649,13 @@ struct buffered_piece_collection
typename robust_ring_type::const_iterator current = pc.robust_ring.begin();
typename robust_ring_type::const_iterator next = current + 1;
- for (int i = 1; i < pc.offsetted_count; i++)
+ for (signed_size_type i = 1; i < pc.offsetted_count; i++)
{
determine_monotonicity<0>(pc, *current, *next);
determine_monotonicity<1>(pc, *current, *next);
current = next;
++next;
}
-
}
void determine_properties()
@@ -659,7 +692,31 @@ struct buffered_piece_collection
geometry::sectionalize<false, dimensions>(pc.robust_ring,
detail::no_rescale_policy(), pc.sections);
- // TODO (next phase) determine min/max radius
+ // Determine min/max radius
+ typedef geometry::model::referring_segment<robust_point_type const>
+ robust_segment_type;
+
+ typename robust_ring_type::const_iterator current = pc.robust_ring.begin();
+ typename robust_ring_type::const_iterator next = current + 1;
+
+ for (signed_size_type i = 1; i < pc.offsetted_count; i++)
+ {
+ robust_segment_type s(*current, *next);
+ robust_comparable_radius_type const d
+ = geometry::comparable_distance(pc.robust_center, s);
+
+ if (i == 1 || d < pc.robust_min_comparable_radius)
+ {
+ pc.robust_min_comparable_radius = d;
+ }
+ if (i == 1 || d > pc.robust_max_comparable_radius)
+ {
+ pc.robust_max_comparable_radius = d;
+ }
+
+ current = next;
+ ++next;
+ }
}
inline void prepare_buffered_point_pieces()
@@ -730,7 +787,7 @@ struct buffered_piece_collection
inline void start_new_ring()
{
- int const n = offsetted_rings.size();
+ signed_size_type const n = static_cast<signed_size_type>(offsetted_rings.size());
current_segment_id.source_index = 0;
current_segment_id.multi_index = n;
current_segment_id.ring_index = -1;
@@ -739,12 +796,35 @@ struct buffered_piece_collection
offsetted_rings.resize(n + 1);
current_robust_ring.clear();
- m_first_piece_index = boost::size(m_pieces);
+ m_first_piece_index = static_cast<signed_size_type>(boost::size(m_pieces));
+ }
+
+ inline void abort_ring()
+ {
+ // Remove all created pieces for this ring, sections, last offsetted
+ while (! m_pieces.empty()
+ && m_pieces.back().first_seg_id.multi_index
+ == current_segment_id.multi_index)
+ {
+ m_pieces.erase(m_pieces.end() - 1);
+ }
+
+ while (! monotonic_sections.empty()
+ && monotonic_sections.back().ring_id.multi_index
+ == current_segment_id.multi_index)
+ {
+ monotonic_sections.erase(monotonic_sections.end() - 1);
+ }
+
+ offsetted_rings.erase(offsetted_rings.end() - 1);
+ current_robust_ring.clear();
+
+ m_first_piece_index = -1;
}
inline void update_closing_point()
{
- BOOST_ASSERT(! offsetted_rings.empty());
+ BOOST_GEOMETRY_ASSERT(! offsetted_rings.empty());
buffered_ring<Ring>& added = offsetted_rings.back();
if (! boost::empty(added))
{
@@ -764,7 +844,7 @@ struct buffered_piece_collection
// For now, it is made equal because due to numerical instability,
// it can be a tiny bit off, possibly causing a self-intersection
- BOOST_ASSERT(boost::size(m_pieces) > 0);
+ BOOST_GEOMETRY_ASSERT(boost::size(m_pieces) > 0);
if (! ring.empty()
&& current_segment_id.segment_index
== m_pieces.back().first_seg_id.segment_index)
@@ -773,6 +853,13 @@ struct buffered_piece_collection
}
}
+ inline void set_piece_center(point_type const& center)
+ {
+ BOOST_GEOMETRY_ASSERT(! m_pieces.empty());
+ geometry::recalculate(m_pieces.back().robust_center, center,
+ m_robust_policy);
+ }
+
inline void finish_ring(bool is_interior = false, bool has_interiors = false)
{
if (m_first_piece_index == -1)
@@ -780,12 +867,12 @@ struct buffered_piece_collection
return;
}
- if (m_first_piece_index < static_cast<int>(boost::size(m_pieces)))
+ if (m_first_piece_index < static_cast<signed_size_type>(boost::size(m_pieces)))
{
// If piece was added
// Reassign left-of-first and right-of-last
geometry::range::at(m_pieces, m_first_piece_index).left_index
- = boost::size(m_pieces) - 1;
+ = static_cast<signed_size_type>(boost::size(m_pieces)) - 1;
geometry::range::back(m_pieces).right_index = m_first_piece_index;
}
m_first_piece_index = -1;
@@ -794,7 +881,7 @@ struct buffered_piece_collection
if (! current_robust_ring.empty())
{
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
geometry::equals(current_robust_ring.front(),
current_robust_ring.back())
@@ -808,20 +895,20 @@ struct buffered_piece_collection
inline void set_current_ring_concave()
{
- BOOST_ASSERT(boost::size(offsetted_rings) > 0);
+ BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);
offsetted_rings.back().has_concave = true;
}
- inline int add_point(point_type const& p)
+ inline signed_size_type add_point(point_type const& p)
{
- BOOST_ASSERT(boost::size(offsetted_rings) > 0);
+ BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);
buffered_ring<Ring>& current_ring = offsetted_rings.back();
update_last_point(p, current_ring);
current_segment_id.segment_index++;
current_ring.push_back(p);
- return current_ring.size();
+ return static_cast<signed_size_type>(current_ring.size());
}
//-------------------------------------------------------------------------
@@ -836,7 +923,7 @@ struct buffered_piece_collection
piece pc;
pc.type = type;
- pc.index = boost::size(m_pieces);
+ pc.index = static_cast<signed_size_type>(boost::size(m_pieces));
pc.first_seg_id = current_segment_id;
// Assign left/right (for first/last piece per ring they will be re-assigned later)
@@ -862,11 +949,11 @@ struct buffered_piece_collection
return;
}
- BOOST_ASSERT(pc.first_seg_id.multi_index >= 0);
- BOOST_ASSERT(pc.last_segment_index >= 0);
+ BOOST_GEOMETRY_ASSERT(pc.first_seg_id.multi_index >= 0);
+ BOOST_GEOMETRY_ASSERT(pc.last_segment_index >= 0);
pc.offsetted_count = pc.last_segment_index - pc.first_seg_id.segment_index;
- BOOST_ASSERT(pc.offsetted_count >= 0);
+ BOOST_GEOMETRY_ASSERT(pc.offsetted_count >= 0);
pc.robust_ring.reserve(pc.offsetted_count + helper_points_size);
@@ -915,11 +1002,10 @@ struct buffered_piece_collection
return;
}
- geometry::detail::envelope::envelope_range::apply(pc.robust_ring,
- pc.robust_envelope);
+ geometry::envelope(pc.robust_ring, pc.robust_envelope);
geometry::assign_inverse(pc.robust_offsetted_envelope);
- for (int i = 0; i < pc.offsetted_count; i++)
+ for (signed_size_type i = 0; i < pc.offsetted_count; i++)
{
geometry::expand(pc.robust_offsetted_envelope, pc.robust_ring[i]);
}
@@ -1010,7 +1096,7 @@ struct buffered_piece_collection
template <typename Range>
inline void add_range_to_piece(piece& pc, Range const& range, bool add_front)
{
- BOOST_ASSERT(boost::size(range) != 0u);
+ BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u);
typename Range::const_iterator it = boost::begin(range);
@@ -1046,7 +1132,7 @@ struct buffered_piece_collection
inline void add_side_piece(point_type const& p1, point_type const& p2,
Range const& range, bool first)
{
- BOOST_ASSERT(boost::size(range) >= 2u);
+ BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u);
piece& pc = create_piece(strategy::buffer::buffered_segment, ! first);
add_range_to_piece(pc, range, first);
@@ -1133,7 +1219,7 @@ struct buffered_piece_collection
robust_point_type any_point;
geometry::recalculate(any_point, point, m_robust_policy);
- int count_in_original = 0;
+ signed_size_type count_in_original = 0;
// Check of the robust point of this outputted ring is in
// any of the robust original rings
@@ -1279,7 +1365,7 @@ struct buffered_piece_collection
// Inner rings, for deflate, which do not have intersections, and
// which are outside originals, are skipped
// (other ones should be traversed)
- int index = 0;
+ signed_size_type index = 0;
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
it != boost::end(offsetted_rings);
++it, ++index)
@@ -1287,8 +1373,12 @@ struct buffered_piece_collection
if (! it->has_intersections()
&& ! it->is_untouched_outside_original)
{
- ring_identifier id(0, index, -1);
- selected[id] = properties(*it);
+ properties p = properties(*it);
+ if (p.valid)
+ {
+ ring_identifier id(0, index, -1);
+ selected[id] = p;
+ }
}
}
@@ -1299,8 +1389,12 @@ struct buffered_piece_collection
it != boost::end(traversed_rings);
++it, ++index)
{
- ring_identifier id(2, index, -1);
- selected[id] = properties(*it);
+ properties p = properties(*it);
+ if (p.valid)
+ {
+ ring_identifier id(2, index, -1);
+ selected[id] = p;
+ }
}
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true);
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp b/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
index 9ea8bc1e85..19c91544ac 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -14,11 +14,14 @@
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/buffer.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
@@ -26,8 +29,6 @@
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
-#include <boost/geometry/multi/algorithms/within.hpp>
-
namespace boost { namespace geometry
{
@@ -225,7 +226,7 @@ struct get_ring<detail::buffer::buffered_ring_collection_tag>
ring_identifier const& id,
MultiGeometry const& multi_ring)
{
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
id.multi_index >= 0
&& id.multi_index < int(boost::size(multi_ring))
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
index 6a3daa282e..3425ee6ffd 100644
--- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -17,6 +17,7 @@
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
+#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
namespace boost { namespace geometry
@@ -28,6 +29,34 @@ namespace detail { namespace buffer
{
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+struct buffer_assign_turn
+{
+ static bool const include_no_turn = false;
+ static bool const include_degenerate = false;
+ static bool const include_opposite = false;
+
+ template
+ <
+ typename Info,
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo
+ >
+ static inline void apply(Info& info,
+ Point1 const& /*p1*/,
+ Point2 const& /*p2*/,
+ IntersectionInfo const& iinfo)
+ {
+ info.rob_pi = iinfo.rpi();
+ info.rob_pj = iinfo.rpj();
+ info.rob_qi = iinfo.rqi();
+ info.rob_qj = iinfo.rqj();
+ }
+
+};
+#endif
+
template
<
typename Pieces,
@@ -91,7 +120,7 @@ class piece_turn_visitor
template <std::size_t Dimension, typename Iterator, typename Box>
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
- int& index, int dir, Box const& other_bounding_box)
+ signed_size_type& index, int dir, Box const& other_bounding_box)
{
for(; it_begin != it_beyond
&& it_begin + 1 != it_beyond
@@ -129,20 +158,20 @@ class piece_turn_visitor
typedef typename boost::range_value<Turns const>::type turn_type;
typedef typename boost::range_iterator<ring_type const>::type iterator;
- int const piece1_first_index = piece1.first_seg_id.segment_index;
- int const piece2_first_index = piece2.first_seg_id.segment_index;
+ signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index;
+ signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index;
if (piece1_first_index < 0 || piece2_first_index < 0)
{
return;
}
// Get indices of part of offsetted_rings for this monotonic section:
- int const sec1_first_index = piece1_first_index + section1.begin_index;
- int const sec2_first_index = piece2_first_index + section2.begin_index;
+ signed_size_type const sec1_first_index = piece1_first_index + section1.begin_index;
+ signed_size_type const sec2_first_index = piece2_first_index + section2.begin_index;
// index of last point in section, beyond-end is one further
- int const sec1_last_index = piece1_first_index + section1.end_index;
- int const sec2_last_index = piece2_first_index + section2.end_index;
+ signed_size_type const sec1_last_index = piece1_first_index + section1.end_index;
+ signed_size_type const sec2_last_index = piece2_first_index + section2.end_index;
// get geometry and iterators over these sections
ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
@@ -154,7 +183,7 @@ class piece_turn_visitor
iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
// Set begin/end of monotonic ranges, in both x/y directions
- int index1 = sec1_first_index;
+ signed_size_type index1 = sec1_first_index;
move_begin_iterator<0>(it1_first, it1_beyond, index1,
section1.directions[0], section2.bounding_box);
move_end_iterator<0>(it1_first, it1_beyond,
@@ -164,7 +193,7 @@ class piece_turn_visitor
move_end_iterator<1>(it1_first, it1_beyond,
section1.directions[1], section2.bounding_box);
- int index2 = sec2_first_index;
+ signed_size_type index2 = sec2_first_index;
move_begin_iterator<0>(it2_first, it2_beyond, index2,
section2.directions[0], section1.bounding_box);
move_end_iterator<0>(it2_first, it2_beyond,
@@ -204,7 +233,11 @@ class piece_turn_visitor
// and iterating in sync with them...
typedef detail::overlay::get_turn_info
<
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ buffer_assign_turn
+#else
detail::overlay::assign_null_policy
+#endif
> turn_policy;
turn_policy::apply(*prev1, *it1, *next1,
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
index 8803efdec9..0aca21ce88 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
@@ -14,6 +14,8 @@
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
+
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
@@ -25,6 +27,11 @@
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
+#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
+
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
+#endif
namespace boost { namespace geometry
@@ -89,8 +96,10 @@ enum analyse_result
analyse_disjoint,
analyse_within,
analyse_on_original_boundary,
- analyse_on_offsetted,
- analyse_near_offsetted
+ analyse_on_offsetted
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ , analyse_near_offsetted
+#endif
};
template <typename Point>
@@ -112,6 +121,31 @@ inline analyse_result check_segment(Point const& previous,
Point const& current, Turn const& turn,
bool from_monotonic)
{
+
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ typedef geometry::model::referring_segment<Point const> segment_type;
+ segment_type const p(turn.rob_pi, turn.rob_pj);
+ segment_type const q(turn.rob_qi, turn.rob_qj);
+ segment_type const r(previous, current);
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,
+ turn.robust_point);
+
+ if (side == 0)
+ {
+ return analyse_on_offsetted;
+ }
+ if (side == -1 && from_monotonic)
+ {
+ return analyse_within;
+ }
+ if (side == 1 && from_monotonic)
+ {
+ return analyse_disjoint;
+ }
+ return analyse_continue;
+
+#else
+
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
@@ -156,6 +190,7 @@ inline analyse_result check_segment(Point const& previous,
// Not monotonic, on left or right side: continue analysing
return analyse_continue;
+#endif
}
@@ -169,14 +204,22 @@ public :
typedef typename Turn::robust_point_type point_type;
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
- coordinate_type const point_y = geometry::get<1>(turn.robust_point);
-
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ typedef geometry::model::referring_segment<point_type const> segment_type;
+ segment_type const p(turn.rob_pi, turn.rob_pj);
+ segment_type const q(turn.rob_qi, turn.rob_qj);
+#else
typedef strategy::within::winding<point_type> strategy_type;
typename strategy_type::state_type state;
strategy_type strategy;
boost::ignore_unused(strategy);
-
+#endif
+
+ BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
+
+ coordinate_type const point_y = geometry::get<1>(turn.robust_point);
+
for (std::size_t s = 0; s < piece.sections.size(); s++)
{
section_type const& section = piece.sections[s];
@@ -186,11 +229,43 @@ public :
&& point_y >= geometry::get<min_corner, 1>(section.bounding_box) - 1
&& point_y <= geometry::get<max_corner, 1>(section.bounding_box) + 1)
{
- for (int i = section.begin_index + 1; i <= section.end_index; i++)
+ for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)
{
point_type const& previous = piece.robust_ring[i - 1];
point_type const& current = piece.robust_ring[i];
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+
+ // First check if it is in range - if it is not, the
+ // expensive side_of_intersection does not need to be
+ // applied
+ coordinate_type y1 = geometry::get<1>(previous);
+ coordinate_type y2 = geometry::get<1>(current);
+
+ if (y1 > y2)
+ {
+ std::swap(y1, y2);
+ }
+
+ if (point_y >= y1 - 1 && point_y <= y2 + 1)
+ {
+ segment_type const r(previous, current);
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,
+ turn.robust_point);
+
+ // Sections are monotonic in y-dimension
+ if (side == 1)
+ {
+ // Left on segment
+ return analyse_disjoint;
+ }
+ else if (side == 0)
+ {
+ // Collinear - TODO: check if really on segment
+ return analyse_on_offsetted;
+ }
+ }
+#else
analyse_result code = check_segment(previous, current, turn, false);
if (code != analyse_continue)
{
@@ -200,10 +275,15 @@ public :
// Get the state (to determine it is within), we don't have
// to cover the on-segment case (covered above)
strategy.apply(turn.robust_point, previous, current, state);
+#endif
}
}
}
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ // It is nowhere outside, and not on segment, so it is within
+ return analyse_within;
+#else
int const code = strategy.result(state);
if (code == 1)
{
@@ -216,6 +296,7 @@ public :
// Should normally not occur - on-segment is covered
return analyse_unknown;
+#endif
}
};
@@ -228,6 +309,49 @@ class analyse_turn_wrt_piece
bool is_original,
Point const& offsetted)
{
+ boost::ignore_unused(offsetted);
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ typedef geometry::model::referring_segment<Point const> segment_type;
+ segment_type const p(turn.rob_pi, turn.rob_pj);
+ segment_type const q(turn.rob_qi, turn.rob_qj);
+ segment_type const r(s1, s2);
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,
+ turn.robust_point);
+
+ if (side == 1)
+ {
+ // left of segment
+ return analyse_disjoint;
+ }
+ else if (side == 0)
+ {
+ // If is collinear, either on segment or before/after
+ typedef geometry::model::box<Point> box_type;
+
+ box_type box;
+ geometry::assign_inverse(box);
+ geometry::expand(box, s1);
+ geometry::expand(box, s2);
+
+ if (geometry::covered_by(turn.robust_point, box))
+ {
+ // Points on helper-segments are considered as within
+ // Points on original boundary are processed differently
+ return is_original
+ ? analyse_on_original_boundary
+ : analyse_within;
+ }
+
+ // It is collinear but not on the segment. Because these
+ // segments are convex, it is outside
+ // Unless the offsetted ring is collinear or concave w.r.t.
+ // helper-segment but that scenario is not yet supported
+ return analyse_disjoint;
+ }
+
+ // right of segment
+ return analyse_continue;
+#else
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
@@ -276,6 +400,7 @@ class analyse_turn_wrt_piece
// right of segment
return analyse_continue;
+#endif
}
template <typename Turn, typename Piece>
@@ -286,7 +411,8 @@ class analyse_turn_wrt_piece
point_type points[4];
- int helper_count = piece.robust_ring.size() - piece.offsetted_count;
+ signed_size_type helper_count = static_cast<signed_size_type>(piece.robust_ring.size())
+ - piece.offsetted_count;
if (helper_count == 4)
{
for (int i = 0; i < 4; i++)
@@ -436,7 +562,7 @@ public :
// It is small or not monotonic, walk linearly through offset
// TODO: this will be combined with winding strategy
- for (int i = 1; i < piece.offsetted_count; i++)
+ for (signed_size_type i = 1; i < piece.offsetted_count; i++)
{
point_type const& previous = piece.robust_ring[i - 1];
point_type const& current = piece.robust_ring[i];
@@ -492,6 +618,61 @@ class turn_in_piece_visitor
return false;
}
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ // NOTE: this function returns a side value in {-1, 0, 1}
+ template <typename Turn, typename Piece>
+ static inline int turn_in_convex_piece(Turn const& turn,
+ Piece const& piece)
+ {
+ typedef typename Turn::robust_point_type point_type;
+ typedef typename Piece::piece_robust_ring_type ring_type;
+ typedef geometry::model::referring_segment<point_type const> segment;
+
+ segment const p(turn.rob_pi, turn.rob_pj);
+ segment const q(turn.rob_qi, turn.rob_qj);
+
+ typedef typename boost::range_iterator<ring_type const>::type iterator_type;
+ iterator_type it = boost::begin(piece.robust_ring);
+ iterator_type end = boost::end(piece.robust_ring);
+
+ // A robust ring is always closed, and always clockwise
+ for (iterator_type previous = it++; it != end; ++previous, ++it)
+ {
+ geometry::equal_to<point_type> comparator;
+ if (comparator(*previous, *it))
+ {
+ // Points are the same
+ continue;
+ }
+
+ segment r(*previous, *it);
+
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,
+ turn.robust_point);
+
+ if (side == 1)
+ {
+ // IP is left of segment, so it is outside
+ return -1; // outside
+ }
+ else if (side == 0)
+ {
+ // IP is collinear with segment. TODO: we should analyze this further
+ // For now we use the fallback point
+ if (in_box(*previous, *it, turn.robust_point))
+ {
+ return 0;
+ }
+ else
+ {
+ return -1; // outside
+ }
+ }
+ }
+ return 1; // inside
+ }
+#endif
+
public:
@@ -530,12 +711,37 @@ public:
}
// TODO: mutable_piece to make some on-demand preparations in analyse
+ Turn& mutable_turn = m_turns[turn.turn_index];
+
+ if (piece.type == geometry::strategy::buffer::buffered_point)
+ {
+ // Optimization for buffer around points: if distance from center
+ // is not between min/max radius, the result is clear
+ typedef typename default_comparable_distance_result
+ <
+ typename Turn::robust_point_type
+ >::type distance_type;
+
+ distance_type const cd
+ = geometry::comparable_distance(piece.robust_center,
+ turn.robust_point);
+
+ if (cd < piece.robust_min_comparable_radius)
+ {
+ mutable_turn.count_within++;
+ return;
+ }
+ if (cd > piece.robust_max_comparable_radius)
+ {
+ return;
+ }
+ }
+
analyse_result analyse_code =
piece.type == geometry::strategy::buffer::buffered_point
? analyse_turn_wrt_point_piece::apply(turn, piece)
: analyse_turn_wrt_piece::apply(turn, piece);
- Turn& mutable_turn = m_turns[turn.turn_index];
switch(analyse_code)
{
case analyse_disjoint :
@@ -549,16 +755,32 @@ public:
case analyse_within :
mutable_turn.count_within++;
return;
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
case analyse_near_offsetted :
mutable_turn.count_within_near_offsetted++;
return;
+#endif
default :
break;
}
- // TODO: this point_in_geometry is a performance-bottleneck here and
- // will be replaced completely by extending analyse_piece functionality
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
+ // We don't know (yet)
+ int geometry_code = 0;
+ if (piece.is_convex)
+ {
+ geometry_code = turn_in_convex_piece(turn, piece);
+ }
+ else
+ {
+
+ // TODO: this point_in_geometry is a performance-bottleneck here and
+ // will be replaced completely by extending analyse_piece functionality
+ geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
+ }
+#else
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
+#endif
if (geometry_code == 1)
{
diff --git a/boost/geometry/algorithms/detail/check_iterator_range.hpp b/boost/geometry/algorithms/detail/check_iterator_range.hpp
index 09ea7f79a0..9bd1d7ae27 100644
--- a/boost/geometry/algorithms/detail/check_iterator_range.hpp
+++ b/boost/geometry/algorithms/detail/check_iterator_range.hpp
@@ -33,7 +33,7 @@ struct check_iterator_range
{
for (InputIterator it = first; it != beyond; ++it)
{
- if ( !Predicate::apply(*it) )
+ if (! Predicate::apply(*it))
{
return false;
}
@@ -54,7 +54,7 @@ struct check_iterator_range
for (InputIterator it = first; it != beyond; ++it)
{
- if ( !predicate.apply(*it) )
+ if (! predicate.apply(*it))
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
index 04fa9ee86b..4ac5ac6976 100644
--- a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
@@ -12,8 +12,7 @@
#include <iterator>
-#include <boost/assert.hpp>
-
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
@@ -49,7 +48,7 @@ private:
RangeIterator& it_min,
Distance& dist_min)
{
- BOOST_ASSERT( first != last );
+ BOOST_GEOMETRY_ASSERT( first != last );
Distance const zero = Distance(0);
diff --git a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
index 91be6b0ad0..df67890138 100644
--- a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
@@ -12,9 +12,9 @@
#include <utility>
-#include <boost/assert.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
@@ -51,7 +51,7 @@ protected:
iterator_type& it_min2,
Distance& dist_min)
{
- BOOST_ASSERT( first != last );
+ BOOST_GEOMETRY_ASSERT( first != last );
Distance const zero = Distance(0);
@@ -162,7 +162,7 @@ private:
iterator_type& it_min2,
Distance& dist_min)
{
- BOOST_ASSERT( first != last );
+ BOOST_GEOMETRY_ASSERT( first != last );
base_type::apply(point, first, last, strategy,
it_min1, it_min2, dist_min);
diff --git a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
index ceba59b41a..26b8684828 100644
--- a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
@@ -15,8 +15,7 @@
#include <iterator>
#include <utility>
-#include <boost/assert.hpp>
-
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -56,8 +55,8 @@ private:
{
typedef index::rtree<RTreeValueType, index::linear<8> > rtree_type;
- BOOST_ASSERT( rtree_first != rtree_last );
- BOOST_ASSERT( queries_first != queries_last );
+ BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last );
+ BOOST_GEOMETRY_ASSERT( queries_first != queries_last );
Distance const zero = Distance(0);
dist_min = zero;
@@ -73,13 +72,13 @@ private:
{
std::size_t n = rt.query(index::nearest(*qit, 1), &t_v);
- BOOST_ASSERT( n > 0 );
- // n above is unused outside BOOST_ASSERT, hence the call
- // to boost::ignore_unused below
+ BOOST_GEOMETRY_ASSERT( n > 0 );
+ // n above is unused outside BOOST_GEOMETRY_ASSERT,
+ // hence the call to boost::ignore_unused below
//
// however, t_v (initialized by the call to rt.query(...))
// is used below, which is why we cannot put the call to
- // rt.query(...) inside BOOST_ASSERT
+ // rt.query(...) inside BOOST_GEOMETRY_ASSERT
boost::ignore_unused(n);
Distance dist = dispatch::distance
diff --git a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
index c443a54e58..86eec4c036 100644
--- a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
@@ -164,7 +164,7 @@ struct comparable_distance
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
@@ -225,7 +225,7 @@ struct comparable_distance
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
- return apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -287,7 +287,7 @@ struct comparable_distance
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
- return apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -353,7 +353,7 @@ comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2)
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
- return comparable_distance(geometry1, geometry2, default_strategy());
+ return geometry::comparable_distance(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/disjoint/interface.hpp b/boost/geometry/algorithms/detail/disjoint/interface.hpp
index 96d6881296..18c010731e 100644
--- a/boost/geometry/algorithms/detail/disjoint/interface.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/interface.hpp
@@ -175,7 +175,7 @@ struct disjoint<
*/
template <typename Geometry1, typename Geometry2>
inline bool disjoint(Geometry1 const& geometry1,
- Geometry2 const& geometry2)
+ Geometry2 const& geometry2)
{
return resolve_variant::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
}
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
index 7d1bb05242..29e438e546 100644
--- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -13,10 +13,20 @@
#include <algorithm>
#include <vector>
-#include <boost/assert.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/iterators/segment_iterator.hpp>
+
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
+#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
@@ -33,7 +43,8 @@ namespace boost { namespace geometry
namespace detail { namespace disjoint
{
-template<typename MultiPoint1, typename MultiPoint2>
+
+template <typename MultiPoint1, typename MultiPoint2>
class multipoint_multipoint
{
private:
@@ -66,7 +77,7 @@ public:
static inline bool apply(MultiPoint1 const& multipoint1,
MultiPoint2 const& multipoint2)
{
- BOOST_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
+ BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
typedef typename boost::range_value<MultiPoint1>::type point1_type;
@@ -90,6 +101,98 @@ public:
};
+template <typename MultiPoint, typename Linear>
+class multipoint_linear
+{
+private:
+ // structs for partition -- start
+ struct expand_box
+ {
+ template <typename Box, typename Geometry>
+ static inline void apply(Box& total, Geometry const& geometry)
+ {
+ geometry::expand(total, geometry::return_envelope<Box>(geometry));
+ }
+
+ };
+
+ struct overlaps_box
+ {
+ template <typename Box, typename Geometry>
+ static inline bool apply(Box const& box, Geometry const& geometry)
+ {
+ return ! dispatch::disjoint<Geometry, Box>::apply(geometry, box);
+ }
+ };
+
+ class item_visitor_type
+ {
+ public:
+ item_visitor_type() : m_intersection_found(false) {}
+
+ 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))
+ {
+ m_intersection_found = true;
+ }
+ }
+
+ inline bool intersection_found() const { return m_intersection_found; }
+
+ private:
+ bool m_intersection_found;
+ };
+ // structs for partition -- end
+
+ class segment_range
+ {
+ public:
+ typedef geometry::segment_iterator<Linear const> const_iterator;
+ typedef const_iterator iterator;
+
+ segment_range(Linear const& linear)
+ : m_linear(linear)
+ {}
+
+ const_iterator begin() const
+ {
+ return geometry::segments_begin(m_linear);
+ }
+
+ const_iterator end() const
+ {
+ return geometry::segments_end(m_linear);
+ }
+
+ private:
+ Linear const& m_linear;
+ };
+
+public:
+ static inline bool apply(MultiPoint const& multipoint, Linear const& linear)
+ {
+ item_visitor_type visitor;
+
+ geometry::partition
+ <
+ geometry::model::box<typename point_type<MultiPoint>::type>,
+ expand_box,
+ overlaps_box
+ >::apply(multipoint, segment_range(linear), visitor);
+
+ return ! visitor.intersection_found();
+ }
+
+ static inline bool apply(Linear const& linear, MultiPoint const& multipoint)
+ {
+ return apply(multipoint, linear);
+ }
+};
+
+
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
@@ -101,7 +204,7 @@ namespace dispatch
{
-template<typename Point, typename MultiPoint, std::size_t DimensionCount>
+template <typename Point, typename MultiPoint, std::size_t DimensionCount>
struct disjoint
<
Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false
@@ -109,7 +212,7 @@ struct disjoint
{};
-template<typename MultiPoint, typename Segment, std::size_t DimensionCount>
+template <typename MultiPoint, typename Segment, std::size_t DimensionCount>
struct disjoint
<
MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false
@@ -117,7 +220,7 @@ struct disjoint
{};
-template<typename MultiPoint, typename Box, std::size_t DimensionCount>
+template <typename MultiPoint, typename Box, std::size_t DimensionCount>
struct disjoint
<
MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false
@@ -125,7 +228,12 @@ struct disjoint
{};
-template<typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount>
+template
+<
+ typename MultiPoint1,
+ typename MultiPoint2,
+ std::size_t DimensionCount
+>
struct disjoint
<
MultiPoint1, MultiPoint2, DimensionCount,
@@ -151,6 +259,22 @@ struct disjoint
};
+template <typename Linear, typename MultiPoint, std::size_t DimensionCount>
+struct disjoint
+ <
+ Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false
+ > : detail::disjoint::multipoint_linear<MultiPoint, Linear>
+{};
+
+
+template <typename MultiPoint, typename Linear, std::size_t DimensionCount>
+struct disjoint
+ <
+ MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false
+ > : detail::disjoint::multipoint_linear<MultiPoint, Linear>
+{};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
index a58bff41da..9ae43f73d0 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
@@ -1,12 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
+// 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) 2013-2015 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, 2014, 2015.
+// Modifications copyright (c) 2013-2015, 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
@@ -21,8 +21,6 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
-#include <boost/geometry/geometries/segment.hpp>
-
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
@@ -39,24 +37,13 @@ namespace detail { namespace disjoint
{
-template<typename Point, typename Geometry>
-struct disjoint_point_linear
-{
- static inline
- bool apply(Point const& pt, Geometry const& g)
- {
- return !geometry::covered_by(pt, g);
- }
-};
-
-
-template <typename Geometry1, typename Geometry2>
struct reverse_covered_by
{
+ template <typename Geometry1, typename Geometry2>
static inline
bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return !geometry::covered_by(geometry1, geometry2);
+ return ! geometry::covered_by(geometry1, geometry2);
}
};
@@ -74,30 +61,20 @@ namespace dispatch
template<typename Point, typename Linear, std::size_t DimensionCount>
struct disjoint<Point, Linear, DimensionCount, point_tag, linear_tag, false>
- : public detail::disjoint::disjoint_point_linear<Point, Linear>
+ : detail::disjoint::reverse_covered_by
{};
template <typename Point, typename Areal, std::size_t DimensionCount>
struct disjoint<Point, Areal, DimensionCount, point_tag, areal_tag, false>
- : detail::disjoint::reverse_covered_by<Point, Areal>
+ : detail::disjoint::reverse_covered_by
{};
template<typename Point, typename Segment, std::size_t DimensionCount>
struct disjoint<Point, Segment, DimensionCount, point_tag, segment_tag, false>
-{
- static inline bool apply(Point const& point, Segment const& segment)
- {
- typedef geometry::model::referring_segment<Point const> other_segment;
-
- other_segment other(point, point);
- return detail::disjoint::disjoint_segment
- <
- Segment, other_segment
- >::apply(segment, other);
- }
-};
+ : detail::disjoint::reverse_covered_by
+{};
} // namespace dispatch
diff --git a/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/boost/geometry/algorithms/detail/disjoint/point_point.hpp
index b1d32bf95e..7580b7287b 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_point.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_point.hpp
@@ -1,12 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland
+// 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) 2013-2015 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, 2014, 2015.
+// Modifications copyright (c) 2013-2015, 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
@@ -23,11 +23,26 @@
#include <cstddef>
+#include <boost/type_traits/is_same.hpp>
+
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+#include <boost/geometry/strategies/strategy_transform.hpp>
+
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
+#include <boost/geometry/algorithms/transform.hpp>
+
+#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
@@ -40,38 +55,146 @@ namespace boost { namespace geometry
namespace detail { namespace disjoint
{
-template
-<
- typename Point1, typename Point2,
- std::size_t Dimension, std::size_t DimensionCount
->
-struct point_point
+
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct point_point_generic
{
+ template <typename Point1, typename Point2>
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
{
return true;
}
- return point_point
- <
- Point1, Point2,
- Dimension + 1, DimensionCount
- >::apply(p1, p2);
+ return
+ point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2);
}
};
-
-template <typename Point1, typename Point2, std::size_t DimensionCount>
-struct point_point<Point1, Point2, DimensionCount, DimensionCount>
+template <std::size_t DimensionCount>
+struct point_point_generic<DimensionCount, DimensionCount>
{
- static inline bool apply(Point1 const& , Point2 const& )
+ template <typename Point1, typename Point2>
+ static inline bool apply(Point1 const&, Point2 const&)
{
return false;
}
};
+class point_point_on_spheroid
+{
+private:
+ template <typename Point1, typename Point2, bool SameUnits>
+ struct are_same_points
+ {
+ static inline bool apply(Point1 const& point1, Point2 const& point2)
+ {
+ typedef typename helper_geometry<Point1>::type helper_point_type1;
+ typedef typename helper_geometry<Point2>::type helper_point_type2;
+
+ helper_point_type1 point1_normalized
+ = return_normalized<helper_point_type1>(point1);
+ helper_point_type2 point2_normalized
+ = return_normalized<helper_point_type2>(point2);
+
+ return point_point_generic
+ <
+ 0, dimension<Point1>::value
+ >::apply(point1_normalized, point2_normalized);
+ }
+ };
+
+ template <typename Point1, typename Point2>
+ struct are_same_points<Point1, Point2, false> // points have different units
+ {
+ static inline bool apply(Point1 const& point1, Point2 const& point2)
+ {
+ typedef typename geometry::select_most_precise
+ <
+ typename fp_coordinate_type<Point1>::type,
+ typename fp_coordinate_type<Point2>::type
+ >::type calculation_type;
+
+ typename helper_geometry
+ <
+ Point1, calculation_type, radian
+ >::type helper_point1, helper_point2;
+
+ Point1 point1_normalized = return_normalized<Point1>(point1);
+ Point2 point2_normalized = return_normalized<Point2>(point2);
+
+ geometry::transform(point1_normalized, helper_point1);
+ geometry::transform(point2_normalized, helper_point2);
+
+ return point_point_generic
+ <
+ 0, dimension<Point1>::value
+ >::apply(helper_point1, helper_point2);
+ }
+ };
+
+public:
+ template <typename Point1, typename Point2>
+ static inline bool apply(Point1 const& point1, Point2 const& point2)
+ {
+ return are_same_points
+ <
+ Point1,
+ Point2,
+ boost::is_same
+ <
+ typename coordinate_system<Point1>::type::units,
+ typename coordinate_system<Point2>::type::units
+ >::value
+ >::apply(point1, point2);
+ }
+};
+
+
+template
+<
+ typename Point1, typename Point2,
+ std::size_t Dimension, std::size_t DimensionCount,
+ typename CSTag1 = typename cs_tag<Point1>::type,
+ typename CSTag2 = CSTag1
+>
+struct point_point
+ : point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
+{};
+
+template
+<
+ typename Point1, typename Point2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_point
+ <
+ Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag
+ > : point_point_on_spheroid
+{};
+
+template
+<
+ typename Point1, typename Point2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_point
+ <
+ Point1, Point2, Dimension, DimensionCount, geographic_tag
+ > : point_point_on_spheroid
+{};
+
+template
+<
+ typename Point1, typename Point2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
+ : point_point_generic<Dimension, DimensionCount>
+{};
+
+
/*!
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
diff --git a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
index 57257dbdcc..d6de7cac91 100644
--- a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
@@ -185,10 +185,10 @@ public:
Geometry const
> segment_iterator_type;
- typedef typename std::vector
+ typedef typename boost::range_const_iterator
<
- segment_or_box_point
- >::const_iterator seg_or_box_iterator_type;
+ std::vector<segment_or_box_point>
+ >::type seg_or_box_const_iterator;
typedef assign_new_min_iterator<SegmentOrBox> assign_new_value;
@@ -219,8 +219,9 @@ public:
// segment or box
comparable_return_type cd_min1(0);
point_iterator_type pit_min;
- seg_or_box_iterator_type it_min1 = seg_or_box_points.begin();
- seg_or_box_iterator_type it_min2 = ++seg_or_box_points.begin();
+ seg_or_box_const_iterator it_min1 = boost::const_begin(seg_or_box_points);
+ seg_or_box_const_iterator it_min2 = it_min1;
+ ++it_min2;
bool first = true;
for (point_iterator_type pit = points_begin(geometry);
@@ -229,11 +230,11 @@ public:
comparable_return_type cd;
std::pair
<
- seg_or_box_iterator_type, seg_or_box_iterator_type
+ seg_or_box_const_iterator, seg_or_box_const_iterator
> it_pair
= point_to_point_range::apply(*pit,
- seg_or_box_points.begin(),
- seg_or_box_points.end(),
+ boost::const_begin(seg_or_box_points),
+ boost::const_end(seg_or_box_points),
cstrategy,
cd);
@@ -250,12 +251,11 @@ public:
// segments of the geometry
comparable_return_type cd_min2(0);
segment_iterator_type sit_min;
- typename std::vector<segment_or_box_point>::const_iterator it_min;
+ seg_or_box_const_iterator it_min;
first = true;
- for (typename std::vector<segment_or_box_point>::const_iterator it
- = seg_or_box_points.begin();
- it != seg_or_box_points.end(); ++it, first = false)
+ for (seg_or_box_const_iterator it = boost::const_begin(seg_or_box_points);
+ it != boost::const_end(seg_or_box_points); ++it, first = false)
{
comparable_return_type cd;
segment_iterator_type sit
diff --git a/boost/geometry/algorithms/detail/distance/interface.hpp b/boost/geometry/algorithms/detail/distance/interface.hpp
index fa8cbd69ee..1e7cc433ef 100644
--- a/boost/geometry/algorithms/detail/distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/distance/interface.hpp
@@ -198,7 +198,7 @@ struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
@@ -253,7 +253,7 @@ struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
Strategy const& strategy)
{
- return apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
@@ -312,7 +312,7 @@ struct distance
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
- return apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
@@ -395,7 +395,7 @@ distance(Geometry1 const& geometry1,
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
- return distance(geometry1, geometry2, default_strategy());
+ return geometry::distance(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
index 78189794a1..6e78bee694 100644
--- a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
+++ b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
@@ -13,8 +13,7 @@
#include <iterator>
#include <utility>
-#include <boost/assert.hpp>
-
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/iterators/has_one_element.hpp>
@@ -70,7 +69,7 @@ public:
{
namespace sds = strategy::distance::services;
- BOOST_ASSERT( first != last );
+ BOOST_GEOMETRY_ASSERT( first != last );
if ( geometry::has_one_element(first, last) )
{
diff --git a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
index 79d9adb703..783699ee0a 100644
--- a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
@@ -15,13 +15,13 @@
#include <functional>
#include <vector>
-#include <boost/assert.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -561,7 +561,7 @@ private:
typedef compare_less_equal<ReturnType, true> less_equal;
// assert that the segment has non-negative slope
- BOOST_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))
+ BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))
&& geometry::get<1>(p0) < geometry::get<1>(p1))
||
( geometry::get<0>(p0) < geometry::get<0>(p1)
@@ -617,7 +617,7 @@ private:
typedef compare_less_equal<ReturnType, false> greater_equal;
// assert that the segment has negative slope
- BOOST_ASSERT( geometry::get<0>(p0) < geometry::get<0>(p1)
+ BOOST_GEOMETRY_ASSERT( geometry::get<0>(p0) < geometry::get<0>(p1)
&& geometry::get<1>(p0) > geometry::get<1>(p1) );
ReturnType result(0);
@@ -665,7 +665,7 @@ public:
PPStrategy const& pp_strategy,
PSStrategy const& ps_strategy)
{
- BOOST_ASSERT( geometry::less<SegmentPoint>()(p0, p1) );
+ BOOST_GEOMETRY_ASSERT( geometry::less<SegmentPoint>()(p0, p1) );
if (geometry::get<0>(p0) < geometry::get<0>(p1)
&& geometry::get<1>(p0) > geometry::get<1>(p1))
diff --git a/boost/geometry/algorithms/detail/envelope/box.hpp b/boost/geometry/algorithms/detail/envelope/box.hpp
new file mode 100644
index 0000000000..3790262948
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/box.hpp
@@ -0,0 +1,167 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
+
+#include <cstddef>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
+
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+template
+<
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct envelope_indexed_box
+{
+ template <typename BoxIn, typename BoxOut>
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ {
+ detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
+ detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
+
+ detail::conversion::point_to_point
+ <
+ detail::indexed_point_view<BoxIn const, Index>,
+ detail::indexed_point_view<BoxOut, Index>,
+ Dimension,
+ DimensionCount
+ >::apply(box_in_corner, mbr_corner);
+ }
+};
+
+template
+<
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct envelope_indexed_box_on_spheroid
+{
+ template <typename BoxIn, typename BoxOut>
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ {
+ // transform() does not work with boxes of dimension higher
+ // than 2; to account for such boxes we transform the min/max
+ // points of the boxes using the indexed_point_view
+ detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
+ detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
+
+ // first transform the units
+ transform_units(box_in_corner, mbr_corner);
+
+ // now transform the remaining coordinates
+ detail::conversion::point_to_point
+ <
+ detail::indexed_point_view<BoxIn const, Index>,
+ detail::indexed_point_view<BoxOut, Index>,
+ 2,
+ DimensionCount
+ >::apply(box_in_corner, mbr_corner);
+ }
+};
+
+
+struct envelope_box
+{
+ template<typename BoxIn, typename BoxOut>
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ {
+ envelope_indexed_box
+ <
+ min_corner, 0, dimension<BoxIn>::value
+ >::apply(box_in, mbr);
+
+ envelope_indexed_box
+ <
+ max_corner, 0, dimension<BoxIn>::value
+ >::apply(box_in, mbr);
+ }
+};
+
+
+struct envelope_box_on_spheroid
+{
+ template <typename BoxIn, typename BoxOut>
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)
+ {
+ BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
+
+ envelope_indexed_box_on_spheroid
+ <
+ min_corner, dimension<BoxIn>::value
+ >::apply(box_in_normalized, mbr);
+
+ envelope_indexed_box_on_spheroid
+ <
+ max_corner, dimension<BoxIn>::value
+ >::apply(box_in_normalized, mbr);
+ }
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Box, typename CS_Tag>
+struct envelope<Box, box_tag, CS_Tag>
+ : detail::envelope::envelope_box
+{};
+
+
+template <typename Box>
+struct envelope<Box, box_tag, spherical_equatorial_tag>
+ : detail::envelope::envelope_box_on_spheroid
+{};
+
+
+template <typename Box>
+struct envelope<Box, box_tag, geographic_tag>
+ : detail::envelope::envelope_box_on_spheroid
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/implementation.hpp b/boost/geometry/algorithms/detail/envelope/implementation.hpp
new file mode 100644
index 0000000000..c1dbf8e589
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/implementation.hpp
@@ -0,0 +1,106 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/is_empty.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>
+#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
+#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
+#include <boost/geometry/algorithms/detail/envelope/point.hpp>
+#include <boost/geometry/algorithms/detail/envelope/range.hpp>
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+struct envelope_polygon
+{
+ template <typename Polygon, typename Box>
+ static inline void apply(Polygon const& polygon, Box& mbr)
+ {
+ typename ring_return_type<Polygon const>::type ext_ring
+ = exterior_ring(polygon);
+
+ if (geometry::is_empty(ext_ring))
+ {
+ // if the exterior ring is empty, consider the interior rings
+ envelope_multi_range
+ <
+ envelope_range
+ >::apply(interior_rings(polygon), mbr);
+ }
+ else
+ {
+ // otherwise, consider only the exterior ring
+ envelope_range::apply(ext_ring, mbr);
+ }
+ }
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Ring>
+struct envelope<Ring, ring_tag>
+ : detail::envelope::envelope_range
+{};
+
+
+template <typename Polygon>
+struct envelope<Polygon, polygon_tag>
+ : detail::envelope::envelope_polygon
+{};
+
+
+template <typename MultiPolygon>
+struct envelope<MultiPolygon, multi_polygon_tag>
+ : detail::envelope::envelope_multi_range
+ <
+ detail::envelope::envelope_polygon
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/initialize.hpp b/boost/geometry/algorithms/detail/envelope/initialize.hpp
new file mode 100644
index 0000000000..d8e252b53a
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/initialize.hpp
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/bounds.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct initialize_loop
+{
+ template <typename Box, typename CoordinateType>
+ static inline void apply(Box& box,
+ CoordinateType min_value,
+ CoordinateType max_value)
+ {
+ geometry::set<min_corner, Dimension>(box, min_value);
+ geometry::set<max_corner, Dimension>(box, max_value);
+
+ initialize_loop
+ <
+ Dimension + 1, DimensionCount
+ >::apply(box, min_value, max_value);
+ }
+};
+
+template <std::size_t DimensionCount>
+struct initialize_loop<DimensionCount, DimensionCount>
+{
+ template <typename Box, typename CoordinateType>
+ static inline void apply(Box&, CoordinateType, CoordinateType)
+ {
+ }
+};
+
+
+template
+<
+ typename Box,
+ std::size_t Dimension = 0,
+ std::size_t DimensionCount = dimension<Box>::value
+>
+struct initialize
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ static inline void apply(Box& box,
+ coordinate_type min_value
+ = boost::numeric::bounds<coordinate_type>::highest(),
+ coordinate_type max_value
+ = boost::numeric::bounds<coordinate_type>::lowest())
+ {
+ initialize_loop
+ <
+ Dimension, DimensionCount
+ >::apply(box, min_value, max_value);
+ }
+};
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp
new file mode 100644
index 0000000000..997ac1b23e
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/interface.hpp
@@ -0,0 +1,126 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace resolve_variant
+{
+
+template <typename Geometry>
+struct envelope
+{
+ template <typename Box>
+ static inline void apply(Geometry const& geometry, Box& box)
+ {
+ concept::check<Geometry const>();
+ concept::check<Box>();
+
+ dispatch::envelope<Geometry>::apply(geometry, box);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Box>
+ struct visitor: boost::static_visitor<void>
+ {
+ Box& m_box;
+
+ visitor(Box& box): m_box(box) {}
+
+ template <typename Geometry>
+ void operator()(Geometry const& geometry) const
+ {
+ envelope<Geometry>::apply(geometry, m_box);
+ }
+ };
+
+ template <typename Box>
+ static inline void
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Box& box)
+ {
+ boost::apply_visitor(visitor<Box>(box), geometry);
+ }
+};
+
+} // namespace resolve_variant
+
+
+/*!
+\brief \brief_calc{envelope}
+\ingroup envelope
+\details \details_calc{envelope,\det_envelope}.
+\tparam Geometry \tparam_geometry
+\tparam Box \tparam_box
+\param geometry \param_geometry
+\param mbr \param_box \param_set{envelope}
+
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[envelope] [envelope_output]
+}
+*/
+template<typename Geometry, typename Box>
+inline void envelope(Geometry const& geometry, Box& mbr)
+{
+ resolve_variant::envelope<Geometry>::apply(geometry, 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}
+
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[return_envelope] [return_envelope_output]
+}
+*/
+template<typename Box, typename Geometry>
+inline Box return_envelope(Geometry const& geometry)
+{
+ Box mbr;
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr);
+ return mbr;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
new file mode 100644
index 0000000000..47937bf740
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace envelope
+{
+
+
+struct intersects_antimeridian
+{
+ template <typename Units, typename CoordinateType>
+ static inline bool apply(CoordinateType const& lon1,
+ CoordinateType const& lat1,
+ CoordinateType const& lon2,
+ CoordinateType const& lat2)
+ {
+ typedef math::detail::constants_on_spheroid
+ <
+ CoordinateType, Units
+ > constants;
+
+ return
+ math::equals(math::abs(lat1), constants::max_latitude())
+ ||
+ math::equals(math::abs(lat2), constants::max_latitude())
+ ||
+ math::larger(math::abs(lon1 - lon2), constants::half_period());
+ }
+
+ template <typename Segment>
+ static inline bool apply(Segment const& segment)
+ {
+ return apply(detail::indexed_point_view<Segment, 0>(segment),
+ detail::indexed_point_view<Segment, 1>(segment));
+ }
+
+ template <typename Point>
+ static inline bool apply(Point const& p1, Point const& p2)
+ {
+ Point p1_normalized = detail::return_normalized<Point>(p1);
+ Point p2_normalized = detail::return_normalized<Point>(p2);
+
+ return apply
+ <
+ typename coordinate_system<Point>::type::units
+ >(geometry::get<0>(p1_normalized),
+ geometry::get<1>(p1_normalized),
+ geometry::get<0>(p2_normalized),
+ geometry::get<1>(p2_normalized));
+ }
+};
+
+
+}} // namespace detail::envelope
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/linear.hpp b/boost/geometry/algorithms/detail/envelope/linear.hpp
new file mode 100644
index 0000000000..49c3cf3135
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/linear.hpp
@@ -0,0 +1,96 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/iterators/segment_iterator.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/range.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+struct envelope_linestring_on_spheroid
+{
+ template <typename Linestring, typename Box>
+ static inline void apply(Linestring const& linestring, Box& mbr)
+ {
+ envelope_range::apply(geometry::segments_begin(linestring),
+ geometry::segments_end(linestring),
+ mbr);
+ }
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Linestring, typename CS_Tag>
+struct envelope<Linestring, linestring_tag, CS_Tag>
+ : detail::envelope::envelope_range
+{};
+
+template <typename Linestring>
+struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
+ : detail::envelope::envelope_linestring_on_spheroid
+{};
+
+
+template <typename MultiLinestring, typename CS_Tag>
+struct envelope
+ <
+ MultiLinestring, multi_linestring_tag, CS_Tag
+ > : detail::envelope::envelope_multi_range
+ <
+ detail::envelope::envelope_range
+ >
+{};
+
+template <typename MultiLinestring>
+struct envelope
+ <
+ MultiLinestring, multi_linestring_tag, spherical_equatorial_tag
+ > : detail::envelope::envelope_multi_range_on_spheroid
+ <
+ detail::envelope::envelope_linestring_on_spheroid
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/boost/geometry/algorithms/detail/envelope/multipoint.hpp
new file mode 100644
index 0000000000..210debfdba
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/multipoint.hpp
@@ -0,0 +1,378 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
+
+#include <cstddef>
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include <boost/algorithm/minmax_element.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/range.hpp>
+
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
+#include <boost/geometry/algorithms/detail/envelope/range.hpp>
+#include <boost/geometry/algorithms/detail/expand/point.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+class envelope_multipoint_on_spheroid
+{
+private:
+ template <std::size_t Dim>
+ struct coordinate_less
+ {
+ template <typename Point>
+ inline bool operator()(Point const& point1, Point const& point2) const
+ {
+ return math::smaller(geometry::get<Dim>(point1),
+ geometry::get<Dim>(point2));
+ }
+ };
+
+ template <typename Constants, typename MultiPoint, typename OutputIterator>
+ static inline void analyze_point_coordinates(MultiPoint const& multipoint,
+ bool& has_south_pole,
+ bool& has_north_pole,
+ OutputIterator oit)
+ {
+ typedef typename boost::range_value<MultiPoint>::type point_type;
+ typedef typename boost::range_iterator
+ <
+ MultiPoint const
+ >::type iterator_type;
+
+ // analyze point coordinates:
+ // (1) normalize point coordinates
+ // (2) check if any point is the north or the south pole
+ // (3) put all non-pole points in a container
+ //
+ // notice that at this point in the algorithm, we have at
+ // least two points on the spheroid
+ has_south_pole = false;
+ has_north_pole = false;
+
+ for (iterator_type it = boost::begin(multipoint);
+ it != boost::end(multipoint);
+ ++it)
+ {
+ point_type point = detail::return_normalized<point_type>(*it);
+
+ if (math::equals(geometry::get<1>(point),
+ Constants::min_latitude()))
+ {
+ has_south_pole = true;
+ }
+ else if (math::equals(geometry::get<1>(point),
+ Constants::max_latitude()))
+ {
+ has_north_pole = true;
+ }
+ else
+ {
+ *oit++ = point;
+ }
+ }
+ }
+
+ template <typename SortedRange, typename Value>
+ static inline Value maximum_gap(SortedRange const& sorted_range,
+ Value& max_gap_left,
+ Value& max_gap_right)
+ {
+ typedef typename boost::range_iterator
+ <
+ SortedRange const
+ >::type iterator_type;
+
+ iterator_type it1 = boost::begin(sorted_range), it2 = it1;
+ ++it2;
+ max_gap_left = geometry::get<0>(*it1);
+ max_gap_right = geometry::get<0>(*it2);
+
+ Value max_gap = max_gap_right - max_gap_left;
+ for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2)
+ {
+ Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1);
+ if (math::larger(gap, max_gap))
+ {
+ max_gap_left = geometry::get<0>(*it1);
+ max_gap_right = geometry::get<0>(*it2);
+ max_gap = gap;
+ }
+ }
+
+ return max_gap;
+ }
+
+ template
+ <
+ typename Constants,
+ typename PointRange,
+ typename LongitudeLess,
+ typename CoordinateType
+ >
+ static inline void get_min_max_longitudes(PointRange& range,
+ LongitudeLess const& lon_less,
+ CoordinateType& lon_min,
+ CoordinateType& lon_max)
+ {
+ typedef typename boost::range_iterator
+ <
+ PointRange const
+ >::type iterator_type;
+
+ // compute min and max longitude values
+ std::pair<iterator_type, iterator_type> min_max_longitudes
+ = boost::minmax_element(boost::begin(range),
+ boost::end(range),
+ lon_less);
+
+ lon_min = geometry::get<0>(*min_max_longitudes.first);
+ lon_max = geometry::get<0>(*min_max_longitudes.second);
+
+ // if the longitude span is "large" compute the true maximum gap
+ if (math::larger(lon_max - lon_min, Constants::half_period()))
+ {
+ std::sort(boost::begin(range), boost::end(range), lon_less);
+
+ CoordinateType max_gap_left = 0, max_gap_right = 0;
+ CoordinateType max_gap
+ = maximum_gap(range, max_gap_left, max_gap_right);
+
+ CoordinateType complement_gap
+ = Constants::period() + lon_min - lon_max;
+
+ if (math::larger(max_gap, complement_gap))
+ {
+ lon_min = max_gap_right;
+ lon_max = max_gap_left + Constants::period();
+ }
+ }
+ }
+
+ template
+ <
+ typename Constants,
+ typename Iterator,
+ typename LatitudeLess,
+ typename CoordinateType
+ >
+ static inline void get_min_max_latitudes(Iterator const first,
+ Iterator const last,
+ LatitudeLess const& lat_less,
+ bool has_south_pole,
+ bool has_north_pole,
+ CoordinateType& lat_min,
+ CoordinateType& lat_max)
+ {
+ if (has_south_pole && has_north_pole)
+ {
+ lat_min = Constants::min_latitude();
+ lat_max = Constants::max_latitude();
+ }
+ else if (has_south_pole)
+ {
+ lat_min = Constants::min_latitude();
+ lat_max
+ = geometry::get<1>(*std::max_element(first, last, lat_less));
+ }
+ else if (has_north_pole)
+ {
+ lat_min
+ = geometry::get<1>(*std::min_element(first, last, lat_less));
+ lat_max = Constants::max_latitude();
+ }
+ else
+ {
+ std::pair<Iterator, Iterator> min_max_latitudes
+ = boost::minmax_element(first, last, lat_less);
+
+ lat_min = geometry::get<1>(*min_max_latitudes.first);
+ lat_max = geometry::get<1>(*min_max_latitudes.second);
+ }
+ }
+
+public:
+ template <typename MultiPoint, typename Box>
+ static inline void apply(MultiPoint const& multipoint, Box& mbr)
+ {
+ typedef typename point_type<MultiPoint>::type point_type;
+ typedef typename coordinate_type<MultiPoint>::type coordinate_type;
+ typedef typename boost::range_iterator
+ <
+ MultiPoint const
+ >::type iterator_type;
+
+ typedef math::detail::constants_on_spheroid
+ <
+ coordinate_type,
+ typename coordinate_system<MultiPoint>::type::units
+ > constants;
+
+ if (boost::empty(multipoint))
+ {
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);
+ return;
+ }
+
+ initialize<Box, 0, 2>::apply(mbr);
+
+ if (boost::size(multipoint) == 1)
+ {
+ return dispatch::envelope
+ <
+ typename boost::range_value<MultiPoint>::type
+ >::apply(range::front(multipoint), mbr);
+ }
+
+ // analyze the points and put the non-pole ones in the
+ // points vector
+ std::vector<point_type> points;
+ bool has_north_pole = false, has_south_pole = false;
+
+ analyze_point_coordinates<constants>(multipoint,
+ has_south_pole, has_north_pole,
+ std::back_inserter(points));
+
+ coordinate_type lon_min, lat_min, lon_max, lat_max;
+ if (points.size() == 1)
+ {
+ // we have one non-pole point and at least one pole point
+ lon_min = geometry::get<0>(range::front(points));
+ lon_max = geometry::get<0>(range::front(points));
+ lat_min = has_south_pole
+ ? constants::min_latitude()
+ : constants::max_latitude();
+ lat_max = has_north_pole
+ ? constants::max_latitude()
+ : constants::min_latitude();
+ }
+ else if (points.empty())
+ {
+ // all points are pole points
+ BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole);
+ lon_min = coordinate_type(0);
+ lon_max = coordinate_type(0);
+ lat_min = has_south_pole
+ ? constants::min_latitude()
+ : constants::max_latitude();
+ lat_max = (has_north_pole)
+ ? constants::max_latitude()
+ : constants::min_latitude();
+ }
+ else
+ {
+ get_min_max_longitudes<constants>(points,
+ coordinate_less<0>(),
+ lon_min,
+ lon_max);
+
+ get_min_max_latitudes<constants>(points.begin(),
+ points.end(),
+ coordinate_less<1>(),
+ has_south_pole,
+ has_north_pole,
+ lat_min,
+ lat_max);
+ }
+
+ typedef typename helper_geometry
+ <
+ Box,
+ coordinate_type,
+ typename coordinate_system<MultiPoint>::type::units
+ >::type helper_box_type;
+
+ helper_box_type helper_mbr;
+
+ geometry::set<min_corner, 0>(helper_mbr, lon_min);
+ geometry::set<min_corner, 1>(helper_mbr, lat_min);
+ geometry::set<max_corner, 0>(helper_mbr, lon_max);
+ geometry::set<max_corner, 1>(helper_mbr, lat_max);
+
+ // now transform to output MBR (per index)
+ envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);
+ envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
+
+ // compute envelope for higher coordinates
+ iterator_type it = boost::begin(multipoint);
+ envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);
+
+ for (++it; it != boost::end(multipoint); ++it)
+ {
+ detail::expand::point_loop
+ <
+ strategy::compare::default_strategy,
+ strategy::compare::default_strategy,
+ 2, dimension<Box>::value
+ >::apply(mbr, *it);
+ }
+ }
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPoint, typename CSTag>
+struct envelope<MultiPoint, multi_point_tag, CSTag>
+ : detail::envelope::envelope_range
+{};
+
+template <typename MultiPoint>
+struct envelope<MultiPoint, multi_point_tag, spherical_equatorial_tag>
+ : detail::envelope::envelope_multipoint_on_spheroid
+{};
+
+template <typename MultiPoint>
+struct envelope<MultiPoint, multi_point_tag, geographic_tag>
+ : detail::envelope::envelope_multipoint_on_spheroid
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/point.hpp b/boost/geometry/algorithms/detail/envelope/point.hpp
new file mode 100644
index 0000000000..e914e7e8a0
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/point.hpp
@@ -0,0 +1,127 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
+
+#include <cstddef>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
+
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct envelope_one_point
+{
+ template <std::size_t Index, typename Point, typename Box>
+ static inline void apply(Point const& point, Box& mbr)
+ {
+ detail::indexed_point_view<Box, Index> box_corner(mbr);
+ detail::conversion::point_to_point
+ <
+ Point,
+ detail::indexed_point_view<Box, Index>,
+ Dimension,
+ DimensionCount
+ >::apply(point, box_corner);
+ }
+
+ template <typename Point, typename Box>
+ static inline void apply(Point const& point, Box& mbr)
+ {
+ apply<min_corner>(point, mbr);
+ apply<max_corner>(point, mbr);
+ }
+};
+
+
+struct envelope_point_on_spheroid
+{
+ template<typename Point, typename Box>
+ static inline void apply(Point const& point, Box& mbr)
+ {
+ Point normalized_point = detail::return_normalized<Point>(point);
+
+ typename point_type<Box>::type box_point;
+
+ // transform units of input point to units of a box point
+ transform_units(normalized_point, box_point);
+
+ geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));
+ geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));
+
+ geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));
+ geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));
+
+ envelope_one_point
+ <
+ 2, dimension<Point>::value
+ >::apply(normalized_point, mbr);
+ }
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Point, typename CS_Tag>
+struct envelope<Point, point_tag, CS_Tag>
+ : detail::envelope::envelope_one_point<0, dimension<Point>::value>
+{};
+
+
+template <typename Point>
+struct envelope<Point, point_tag, spherical_equatorial_tag>
+ : detail::envelope::envelope_point_on_spheroid
+{};
+
+
+template <typename Point>
+struct envelope<Point, point_tag, geographic_tag>
+ : detail::envelope::envelope_point_on_spheroid
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp
new file mode 100644
index 0000000000..63b518114b
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/range.hpp
@@ -0,0 +1,179 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
+
+#include <iterator>
+#include <vector>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+
+#include <boost/geometry/util/range.hpp>
+
+#include <boost/geometry/algorithms/is_empty.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
+#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
+
+#include <boost/geometry/algorithms/detail/expand/box.hpp>
+#include <boost/geometry/algorithms/detail/expand/point.hpp>
+#include <boost/geometry/algorithms/detail/expand/segment.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+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)
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+
+ // initialize MBR
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);
+
+ Iterator it = first;
+ if (it != last)
+ {
+ // initialize box with first element in range
+ dispatch::envelope<value_type>::apply(*it, mbr);
+
+ // consider now the remaining elements in the range (if any)
+ for (++it; it != last; ++it)
+ {
+ dispatch::expand<Box, value_type>::apply(mbr, *it);
+ }
+ }
+ }
+
+ template <typename Range, typename Box>
+ static inline void apply(Range const& range, Box& mbr)
+ {
+ return apply(boost::begin(range), boost::end(range), mbr);
+ }
+};
+
+
+// implementation for multi-ranges
+template <typename EnvelopePolicy>
+struct envelope_multi_range
+{
+ template <typename MultiRange, typename Box>
+ static inline void apply(MultiRange const& multirange, Box& mbr)
+ {
+ typedef typename boost::range_iterator
+ <
+ MultiRange const
+ >::type iterator_type;
+
+ bool initialized = false;
+ for (iterator_type it = boost::begin(multirange);
+ it != boost::end(multirange);
+ ++it)
+ {
+ if (! geometry::is_empty(*it))
+ {
+ if (initialized)
+ {
+ Box helper_mbr;
+ EnvelopePolicy::apply(*it, helper_mbr);
+
+ dispatch::expand<Box, Box>::apply(mbr, helper_mbr);
+ }
+ else
+ {
+ // compute the initial envelope
+ EnvelopePolicy::apply(*it, mbr);
+ initialized = true;
+ }
+ }
+ }
+
+ if (! initialized)
+ {
+ // if not already initialized, initialize MBR
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);
+ }
+ }
+};
+
+
+// implementation for multi-range on a spheroid (longitude is periodic)
+template <typename EnvelopePolicy>
+struct envelope_multi_range_on_spheroid
+{
+ template <typename MultiRange, typename Box>
+ static inline void apply(MultiRange const& multirange, Box& mbr)
+ {
+ typedef typename boost::range_iterator
+ <
+ MultiRange const
+ >::type iterator_type;
+
+ // due to the periodicity of longitudes we need to compute the boxes
+ // of all the single geometries and keep them in a container
+ std::vector<Box> boxes;
+ for (iterator_type it = boost::begin(multirange);
+ it != boost::end(multirange);
+ ++it)
+ {
+ if (! geometry::is_empty(*it))
+ {
+ Box helper_box;
+ EnvelopePolicy::apply(*it, helper_box);
+ boxes.push_back(helper_box);
+ }
+ }
+
+ // now we need to compute the envelope of the range of boxes
+ // (cannot be done in an incremental fashion as in the
+ // Cartesian coordinate system)
+ // if all single geometries are empty no boxes have been found
+ // and the MBR is simply initialized
+ if (! boxes.empty())
+ {
+ envelope_range_of_boxes::apply(boxes, mbr);
+ }
+ else
+ {
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);
+ }
+
+ }
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
new file mode 100644
index 0000000000..64bdb9b9cb
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
@@ -0,0 +1,326 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
+
+#include <cstddef>
+
+#include <algorithm>
+#include <vector>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/range.hpp>
+
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>
+#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+template <typename T>
+class longitude_interval
+{
+ typedef T const& reference_type;
+
+public:
+ typedef T value_type;
+ typedef T difference_type;
+
+ longitude_interval(T const& left, T const& right)
+ {
+ m_end[0] = left;
+ m_end[1] = right;
+ }
+
+ template <std::size_t Index>
+ reference_type get() const
+ {
+ return m_end[Index];
+ }
+
+ difference_type length() const
+ {
+ return get<1>() - get<0>();
+ }
+
+private:
+ T m_end[2];
+};
+
+
+template <typename Units>
+struct envelope_range_of_longitudes
+{
+ template <std::size_t Index>
+ struct longitude_less
+ {
+ template <typename Interval>
+ inline bool operator()(Interval const& i1, Interval const& i2) const
+ {
+ return math::smaller(i1.template get<Index>(),
+ i2.template get<Index>());
+ }
+ };
+
+ template <typename RangeOfLongitudeIntervals, typename Longitude>
+ static inline void apply(RangeOfLongitudeIntervals const& range,
+ Longitude& lon_min, Longitude& lon_max)
+ {
+ typedef typename math::detail::constants_on_spheroid
+ <
+ Longitude, Units
+ > constants;
+
+ Longitude const zero = 0;
+ Longitude const period = constants::period();
+
+ lon_min = lon_max = zero;
+
+ // the range of longitude intervals can be empty if all input boxes
+ // degenerate to the north or south pole (or combination of the two)
+ // in this case the initialization values for lon_min and
+ // lon_max are valid choices
+ if (! boost::empty(range))
+ {
+ lon_min = std::min_element(boost::begin(range),
+ boost::end(range),
+ longitude_less<0>())->template get<0>();
+ lon_max = std::max_element(boost::begin(range),
+ boost::end(range),
+ longitude_less<1>())->template get<1>();
+
+ if (math::larger(lon_max - lon_min, constants::half_period()))
+ {
+ Longitude max_gap_left, max_gap_right;
+ Longitude max_gap = geometry::maximum_gap(range,
+ max_gap_left,
+ max_gap_right);
+
+ BOOST_GEOMETRY_ASSERT(! math::larger(lon_min, lon_max));
+ BOOST_GEOMETRY_ASSERT
+ (! math::larger(lon_max, constants::max_longitude()));
+ BOOST_GEOMETRY_ASSERT
+ (! math::smaller(lon_min, constants::min_longitude()));
+
+ BOOST_GEOMETRY_ASSERT
+ (! math::larger(max_gap_left, max_gap_right));
+ BOOST_GEOMETRY_ASSERT
+ (! math::larger(max_gap_right, constants::max_longitude()));
+ BOOST_GEOMETRY_ASSERT
+ (! math::smaller(max_gap_left, constants::min_longitude()));
+
+ if (math::larger(max_gap, zero))
+ {
+ Longitude wrapped_gap = period + lon_min - lon_max;
+ if (math::larger(max_gap, wrapped_gap))
+ {
+ lon_min = max_gap_right;
+ lon_max = max_gap_left + period;
+ }
+ }
+ }
+ }
+ }
+};
+
+
+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)
+ {
+ typedef typename boost::range_value<RangeOfBoxes>::type box_type;
+
+ typedef typename boost::range_iterator
+ <
+ RangeOfBoxes const
+ >::type iterator_type;
+
+ // first initialize MBR
+ detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
+ detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
+
+ detail::indexed_point_view<box_type const, min_corner>
+ first_box_min(range::front(range_of_boxes));
+
+ detail::indexed_point_view<box_type const, max_corner>
+ first_box_max(range::front(range_of_boxes));
+
+ detail::conversion::point_to_point
+ <
+ detail::indexed_point_view<box_type const, min_corner>,
+ detail::indexed_point_view<Box, min_corner>,
+ Dimension,
+ DimensionCount
+ >::apply(first_box_min, mbr_min);
+
+ detail::conversion::point_to_point
+ <
+ detail::indexed_point_view<box_type const, max_corner>,
+ detail::indexed_point_view<Box, max_corner>,
+ Dimension,
+ DimensionCount
+ >::apply(first_box_max, mbr_max);
+
+ // now expand using the remaining boxes
+ iterator_type it = boost::begin(range_of_boxes);
+ for (++it; it != boost::end(range_of_boxes); ++it)
+ {
+ detail::expand::indexed_loop
+ <
+ strategy::compare::default_strategy,
+ strategy::compare::default_strategy,
+ min_corner,
+ Dimension,
+ DimensionCount
+ >::apply(mbr, *it);
+
+ detail::expand::indexed_loop
+ <
+ strategy::compare::default_strategy,
+ strategy::compare::default_strategy,
+ max_corner,
+ Dimension,
+ DimensionCount
+ >::apply(mbr, *it);
+ }
+ }
+
+};
+
+
+struct envelope_range_of_boxes
+{
+ template <std::size_t Index>
+ struct latitude_less
+ {
+ template <typename Box>
+ inline bool operator()(Box const& box1, Box const& box2) const
+ {
+ return math::smaller(geometry::get<Index, 1>(box1),
+ geometry::get<Index, 1>(box2));
+ }
+ };
+
+ template <typename RangeOfBoxes, typename Box>
+ static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
+ {
+ // boxes in the range are assumed to be normalized already
+
+ typedef typename boost::range_value<RangeOfBoxes>::type box_type;
+ typedef typename coordinate_type<box_type>::type coordinate_type;
+ typedef typename coordinate_system<box_type>::type::units units_type;
+ typedef typename boost::range_iterator
+ <
+ RangeOfBoxes const
+ >::type iterator_type;
+
+ typedef math::detail::constants_on_spheroid
+ <
+ coordinate_type, units_type
+ > constants;
+
+ typedef longitude_interval<coordinate_type> interval_type;
+ typedef std::vector<interval_type> interval_range_type;
+
+ BOOST_GEOMETRY_ASSERT(! boost::empty(range_of_boxes));
+
+ iterator_type it_min = std::min_element(boost::begin(range_of_boxes),
+ boost::end(range_of_boxes),
+ latitude_less<min_corner>());
+ iterator_type it_max = std::max_element(boost::begin(range_of_boxes),
+ boost::end(range_of_boxes),
+ latitude_less<max_corner>());
+
+ coordinate_type const min_longitude = constants::min_longitude();
+ coordinate_type const max_longitude = constants::max_longitude();
+ coordinate_type const period = constants::period();
+
+ interval_range_type intervals;
+ for (iterator_type it = boost::begin(range_of_boxes);
+ it != boost::end(range_of_boxes);
+ ++it)
+ {
+ coordinate_type lat_min = geometry::get<min_corner, 1>(*it);
+ coordinate_type lat_max = geometry::get<max_corner, 1>(*it);
+ if (math::equals(lat_min, constants::max_latitude())
+ || math::equals(lat_max, constants::min_latitude()))
+ {
+ // if the box degenerates to the south or north pole
+ // just ignore it
+ continue;
+ }
+
+ coordinate_type lon_left = geometry::get<min_corner, 0>(*it);
+ coordinate_type lon_right = geometry::get<max_corner, 0>(*it);
+
+ if (math::larger(lon_right, max_longitude))
+ {
+ intervals.push_back(interval_type(lon_left, max_longitude));
+ intervals.push_back
+ (interval_type(min_longitude, lon_right - period));
+ }
+ else
+ {
+ intervals.push_back(interval_type(lon_left, lon_right));
+ }
+ }
+
+ coordinate_type lon_min = 0;
+ coordinate_type lon_max = 0;
+ envelope_range_of_longitudes
+ <
+ units_type
+ >::apply(intervals, lon_min, lon_max);
+
+ // do not convert units; conversion will be performed at a
+ // higher level
+
+ // assign now the min/max longitude/latitude values
+ detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
+ detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
+
+ geometry::set<0>(mbr_min, lon_min);
+ geometry::set<1>(mbr_min, geometry::get<min_corner, 1>(*it_min));
+ geometry::set<0>(mbr_max, lon_max);
+ geometry::set<1>(mbr_max, geometry::get<max_corner, 1>(*it_max));
+
+ // what remains to be done is to compute the envelope range
+ // for the remaining dimensions (if any)
+ envelope_range_of_boxes_by_expansion
+ <
+ 2, dimension<Box>::value
+ >::apply(range_of_boxes, mbr);
+ }
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp
new file mode 100644
index 0000000000..570f0e1a43
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/segment.hpp
@@ -0,0 +1,386 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
+
+#include <cstddef>
+#include <utility>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
+#include <boost/geometry/strategies/compare.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>
+
+#include <boost/geometry/algorithms/detail/expand/point.hpp>
+
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct envelope_one_segment
+{
+ template<typename Point, typename Box>
+ static inline void apply(Point const& p1, Point const& p2, Box& mbr)
+ {
+ 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);
+ }
+};
+
+
+// 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
+{
+private:
+ // computes the azimuths of the segment with endpoints (lon1, lat1)
+ // and (lon2, lat2)
+ template <typename CalculationType>
+ static inline void azimuths(CalculationType const& lon1,
+ CalculationType const& lat1,
+ CalculationType const& lon2,
+ CalculationType const& lat2,
+ CalculationType& a1,
+ CalculationType& a2)
+ {
+ BOOST_GEOMETRY_ASSERT(math::smaller(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>();
+ }
+
+ template <typename CalculationType>
+ static inline void swap(CalculationType& lon1,
+ CalculationType& lat1,
+ CalculationType& lon2,
+ CalculationType& lat2)
+ {
+ std::swap(lon1, lon2);
+ std::swap(lat1, lat2);
+ }
+
+ template <typename CalculationType>
+ static inline bool contains_pi_half(CalculationType const& a1,
+ CalculationType const& a2)
+ {
+ // azimuths a1 and a2 are assumed to be in radians
+ BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2));
+
+ static CalculationType const pi_half = math::half_pi<CalculationType>();
+
+ return (a1 < a2)
+ ? (a1 < pi_half && pi_half < a2)
+ : (a1 > pi_half && pi_half > a2);
+ }
+
+ template <typename CoordinateType>
+ static inline bool crosses_antimeridian(CoordinateType const& lon1,
+ CoordinateType const& lon2)
+ {
+ return math::larger(math::abs(lon1 - lon2), math::pi<CoordinateType>());
+ }
+
+ 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)) );
+ }
+
+ template <typename CalculationType>
+ static inline void compute_box_corners(CalculationType& lon1,
+ CalculationType& lat1,
+ CalculationType& lon2,
+ CalculationType& lat2,
+ CalculationType const& a1,
+ CalculationType const& a2)
+ {
+ // coordinates are assumed to be in radians
+ BOOST_GEOMETRY_ASSERT(! math::larger(lon1, lon2));
+
+ if (math::equals(a1, a2))
+ {
+ // the segment must lie on the equator; nothing to do
+ BOOST_GEOMETRY_ASSERT(math::equals(lat1, CalculationType(0)));
+ BOOST_GEOMETRY_ASSERT(math::equals(lat2, CalculationType(0)));
+ return;
+ }
+
+ if (math::larger(lat1, lat2))
+ {
+ std::swap(lat1, lat2);
+ }
+
+ if (contains_pi_half(a1, a2))
+ {
+ CalculationType mid_lat = lat1 + lat2;
+ if (mid_lat < 0)
+ {
+ // update using min latitude
+ CalculationType lat_min = -max_latitude(a1, lat1);
+
+ if (math::larger(lat1, lat_min))
+ {
+ lat1 = lat_min;
+ }
+ }
+ else if (mid_lat > 0)
+ {
+ // update using max latitude
+ CalculationType lat_max = max_latitude(a1, lat1);
+
+ if (math::smaller(lat2, lat_max))
+ {
+ lat2 = lat_max;
+ }
+ }
+ }
+ }
+
+ template <typename CalculationType>
+ static inline void apply(CalculationType& lon1,
+ CalculationType& lat1,
+ CalculationType& lon2,
+ CalculationType& lat2)
+ {
+ CalculationType const half_pi = math::half_pi<CalculationType>();
+
+ bool is_pole1 = math::equals(math::abs(lat1), half_pi);
+ bool is_pole2 = math::equals(math::abs(lat2), half_pi);
+
+ if (is_pole1 && is_pole2)
+ {
+ // both points are poles; nothing more to do:
+ // longitudes are already normalized to 0
+ BOOST_GEOMETRY_ASSERT(lon1 == CalculationType(0)
+ &&
+ lon2 == CalculationType(0));
+ }
+ else if (is_pole1 && !is_pole2)
+ {
+ // first point is a pole, second point is not:
+ // make the longitude of the first point the same as that
+ // of the second point
+ lon1 = lon2;
+ }
+ else if (!is_pole1 && is_pole2)
+ {
+ // second point is a pole, first point is not:
+ // make the longitude of the second point the same as that
+ // of the first point
+ lon2 = lon1;
+ }
+
+ if (math::equals(lon1, lon2))
+ {
+ // segment lies on a meridian
+ if (math::larger(lat1, lat2))
+ {
+ std::swap(lat1, lat2);
+ }
+ return;
+ }
+
+ BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2);
+
+ if (math::larger(lon1, lon2))
+ {
+ swap(lon1, lat1, lon2, lat2);
+ }
+
+ if (crosses_antimeridian(lon1, lon2))
+ {
+ lon1 += math::two_pi<CalculationType>();
+ swap(lon1, lat1, lon2, lat2);
+ }
+
+ CalculationType a1 = 0, a2 = 0;
+ azimuths(lon1, lat1, lon2, lat2, a1, a2);
+
+ compute_box_corners(lon1, lat1, lon2, lat2, a1, a2);
+ }
+
+public:
+ template <typename CalculationType, typename Box>
+ static inline void apply(CalculationType lon1,
+ CalculationType lat1,
+ CalculationType lon2,
+ CalculationType lat2,
+ Box& mbr)
+ {
+ typedef typename coordinate_type<Box>::type box_coordinate_type;
+
+ typedef typename helper_geometry
+ <
+ Box, box_coordinate_type, radian
+ >::type helper_box_type;
+
+ helper_box_type radian_mbr;
+
+ apply(lon1, lat1, lon2, lat2);
+
+ geometry::set
+ <
+ min_corner, 0
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
+
+ geometry::set
+ <
+ min_corner, 1
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
+
+ geometry::set
+ <
+ max_corner, 0
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
+
+ geometry::set
+ <
+ max_corner, 1
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
+
+ transform_units(radian_mbr, mbr);
+ }
+};
+
+
+template <std::size_t DimensionCount>
+struct envelope_segment_on_sphere
+{
+ template <typename Point, typename Box>
+ static inline void apply(Point const& p1, Point const& p2, Box& mbr)
+ {
+ // 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);
+
+ compute_mbr_of_segment::apply(geometry::get_as_radian<0>(p1_normalized),
+ geometry::get_as_radian<1>(p1_normalized),
+ geometry::get_as_radian<0>(p2_normalized),
+ geometry::get_as_radian<1>(p2_normalized),
+ mbr);
+
+ // now compute the envelope range for coordinates of
+ // dimension 2 and higher
+ envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr);
+ }
+
+ template <typename Segment, typename Box>
+ static inline void apply(Segment const& segment, Box& mbr)
+ {
+ 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]);
+ apply(p[0], p[1], mbr);
+ }
+};
+
+
+
+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
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Segment, typename CS_Tag>
+struct envelope<Segment, segment_tag, CS_Tag>
+{
+ template <typename Box>
+ static inline void apply(Segment const& segment, Box& mbr)
+ {
+ 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);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/transform_units.hpp b/boost/geometry/algorithms/detail/envelope/transform_units.hpp
new file mode 100644
index 0000000000..0c5382a47b
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/transform_units.hpp
@@ -0,0 +1,103 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP
+
+#include <cstddef>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/strategies/strategy_transform.hpp>
+
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
+#include <boost/geometry/views/detail/two_dimensional_view.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/transform.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+template
+<
+ typename GeometryIn,
+ typename GeometryOut,
+ typename TagIn = typename tag<GeometryIn>::type,
+ typename TagOut = typename tag<GeometryOut>::type
+>
+struct transform_units_impl
+ : not_implemented<TagIn, TagOut>
+{};
+
+template <typename PointIn, typename PointOut>
+struct transform_units_impl<PointIn, PointOut, point_tag, point_tag>
+{
+ static inline void apply(PointIn const& point_in, PointOut& point_out)
+ {
+ detail::two_dimensional_view<PointIn const> view_in(point_in);
+ detail::two_dimensional_view<PointOut> view_out(point_out);
+
+ geometry::transform(view_in, view_out);
+ }
+};
+
+template <typename BoxIn, typename BoxOut>
+struct transform_units_impl<BoxIn, BoxOut, box_tag, box_tag>
+{
+ template <std::size_t Index>
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out)
+ {
+ typedef detail::indexed_point_view<BoxIn const, Index> view_in_type;
+ typedef detail::indexed_point_view<BoxOut, Index> view_out_type;
+
+ view_in_type view_in(box_in);
+ view_out_type view_out(box_out);
+
+ transform_units_impl
+ <
+ view_in_type, view_out_type
+ >::apply(view_in, view_out);
+ }
+
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out)
+ {
+ apply<min_corner>(box_in, box_out);
+ apply<max_corner>(box_in, box_out);
+ }
+};
+
+
+// Short utility to transform the units of the first two coordinates of
+// geometry_in to the units of geometry_out
+template <typename GeometryIn, typename GeometryOut>
+inline void transform_units(GeometryIn const& geometry_in,
+ GeometryOut& geometry_out)
+{
+ transform_units_impl
+ <
+ GeometryIn, GeometryOut
+ >::apply(geometry_in, geometry_out);
+};
+
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost:geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP
diff --git a/boost/geometry/algorithms/detail/expand/box.hpp b/boost/geometry/algorithms/detail/expand/box.hpp
new file mode 100644
index 0000000000..4c89e6f1d4
--- /dev/null
+++ b/boost/geometry/algorithms/detail/expand/box.hpp
@@ -0,0 +1,126 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
+
+#include <cstddef>
+#include <algorithm>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>
+#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
+
+#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
+
+#include <boost/geometry/algorithms/dispatch/expand.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace expand
+{
+
+
+struct box_on_spheroid
+{
+ template <typename BoxOut, typename BoxIn>
+ static inline void apply(BoxOut& box_out, BoxIn const& box_in)
+ {
+ // 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]);
+
+ // compute the envelope of the two boxes
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out);
+ }
+};
+
+
+}} // namespace detail::expand
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// Box + box -> new box containing two input boxes
+template
+<
+ typename BoxOut, typename BoxIn,
+ typename StrategyLess, typename StrategyGreater,
+ typename CSTagOut, typename CSTag
+>
+struct expand
+ <
+ BoxOut, BoxIn,
+ StrategyLess, StrategyGreater,
+ box_tag, box_tag,
+ CSTagOut, CSTag
+ > : detail::expand::expand_indexed
+ <
+ 0, dimension<BoxIn>::value, StrategyLess, StrategyGreater
+ >
+{
+ BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
+ COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
+ (types<CSTagOut, CSTag>()));
+};
+
+template
+<
+ typename BoxOut, typename BoxIn,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand
+ <
+ BoxOut, BoxIn,
+ StrategyLess, StrategyGreater,
+ box_tag, box_tag,
+ spherical_equatorial_tag, spherical_equatorial_tag
+ > : detail::expand::box_on_spheroid
+{};
+
+template
+<
+ typename BoxOut, typename BoxIn,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand
+ <
+ BoxOut, BoxIn,
+ StrategyLess, StrategyGreater,
+ box_tag, box_tag,
+ geographic_tag, geographic_tag
+ > : detail::expand::box_on_spheroid
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
diff --git a/boost/geometry/algorithms/detail/expand/implementation.hpp b/boost/geometry/algorithms/detail/expand/implementation.hpp
new file mode 100644
index 0000000000..95de1b5049
--- /dev/null
+++ b/boost/geometry/algorithms/detail/expand/implementation.hpp
@@ -0,0 +1,27 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP
+
+#include <boost/geometry/algorithms/detail/expand/point.hpp>
+#include <boost/geometry/algorithms/detail/expand/segment.hpp>
+#include <boost/geometry/algorithms/detail/expand/box.hpp>
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp
new file mode 100644
index 0000000000..bdd6eb4506
--- /dev/null
+++ b/boost/geometry/algorithms/detail/expand/indexed.hpp
@@ -0,0 +1,144 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
+
+#include <cstddef>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/policies/compare.hpp>
+
+#include <boost/geometry/algorithms/dispatch/expand.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace expand
+{
+
+
+template
+<
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct indexed_loop
+{
+ template <typename Box, typename Geometry>
+ static inline void apply(Box& box, Geometry const& source)
+ {
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyLess, 1, Box, Dimension
+ >::type less_type;
+
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyGreater, -1, Box, Dimension
+ >::type greater_type;
+
+ typedef typename select_coordinate_type
+ <
+ Box,
+ Geometry
+ >::type coordinate_type;
+
+ less_type less;
+ greater_type greater;
+
+ coordinate_type const coord = get<Index, Dimension>(source);
+
+ if (less(coord, get<min_corner, Dimension>(box)))
+ {
+ set<min_corner, Dimension>(box, coord);
+ }
+
+ if (greater(coord, get<max_corner, Dimension>(box)))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ indexed_loop
+ <
+ StrategyLess, StrategyGreater,
+ Index, Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index, std::size_t DimensionCount
+>
+struct indexed_loop
+ <
+ StrategyLess, StrategyGreater,
+ Index, DimensionCount, DimensionCount
+ >
+{
+ template <typename Box, typename Geometry>
+ static inline void apply(Box&, Geometry const&) {}
+};
+
+
+
+// Changes a box such that the other box is also contained by the box
+template
+<
+ std::size_t Dimension, std::size_t DimensionCount,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand_indexed
+{
+ template <typename Box, typename Geometry>
+ static inline void apply(Box& box, Geometry const& geometry)
+ {
+ indexed_loop
+ <
+ StrategyLess, StrategyGreater,
+ 0, Dimension, DimensionCount
+ >::apply(box, geometry);
+
+ indexed_loop
+ <
+ StrategyLess, StrategyGreater,
+ 1, Dimension, DimensionCount
+ >::apply(box, geometry);
+ }
+};
+
+
+}} // namespace detail::expand
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
diff --git a/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp
new file mode 100644
index 0000000000..01936387a7
--- /dev/null
+++ b/boost/geometry/algorithms/detail/expand/interface.hpp
@@ -0,0 +1,128 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/dispatch/expand.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry>
+struct expand
+{
+ template <typename Box>
+ static inline void apply(Box& box, Geometry const& geometry)
+ {
+ concept::check<Box>();
+ concept::check<Geometry const>();
+ concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
+
+ dispatch::expand<Box, Geometry>::apply(box, geometry);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Box>
+ struct visitor: boost::static_visitor<void>
+ {
+ Box& m_box;
+
+ visitor(Box& box) : m_box(box) {}
+
+ template <typename Geometry>
+ void operator()(Geometry const& geometry) const
+ {
+ return expand<Geometry>::apply(m_box, geometry);
+ }
+ };
+
+ template <class Box>
+ static inline void
+ apply(Box& box,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ {
+ return boost::apply_visitor(visitor<Box>(box), geometry);
+ }
+};
+
+} // namespace resolve_variant
+
+
+/***
+*!
+\brief Expands a box using the extend (envelope) of another geometry (box, point)
+\ingroup expand
+\tparam Box type of the box
+\tparam Geometry of second geometry, to be expanded with the box
+\param box box to expand another geometry with, might be changed
+\param geometry other geometry
+\param strategy_less
+\param strategy_greater
+\note Strategy is currently ignored
+ *
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+inline void expand(Box& box, Geometry const& geometry,
+ StrategyLess const& strategy_less,
+ StrategyGreater const& strategy_greater)
+{
+ concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
+
+ dispatch::expand<Box, Geometry>::apply(box, geometry);
+}
+***/
+
+
+/*!
+\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
+
+\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);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/expand/point.hpp b/boost/geometry/algorithms/detail/expand/point.hpp
new file mode 100644
index 0000000000..56b7f1c738
--- /dev/null
+++ b/boost/geometry/algorithms/detail/expand/point.hpp
@@ -0,0 +1,303 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
+
+#include <cstddef>
+#include <algorithm>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/policies/compare.hpp>
+
+#include <boost/geometry/algorithms/detail/normalize.hpp>
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
+
+#include <boost/geometry/algorithms/dispatch/expand.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace expand
+{
+
+
+template
+<
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_loop
+{
+ template <typename Box, typename Point>
+ static inline void apply(Box& box, Point const& source)
+ {
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyLess, 1, Point, Dimension
+ >::type less_type;
+
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyGreater, -1, Point, Dimension
+ >::type greater_type;
+
+ typedef typename select_coordinate_type
+ <
+ Point, Box
+ >::type coordinate_type;
+
+ less_type less;
+ greater_type greater;
+
+ coordinate_type const coord = get<Dimension>(source);
+
+ if (less(coord, get<min_corner, Dimension>(box)))
+ {
+ set<min_corner, Dimension>(box, coord);
+ }
+
+ if (greater(coord, get<max_corner, Dimension>(box)))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ point_loop
+ <
+ StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ 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&) {}
+};
+
+
+// implementation for the spherical equatorial and geographic coordinate systems
+template
+<
+ typename StrategyLess,
+ typename StrategyGreater,
+ std::size_t DimensionCount
+>
+struct point_loop_on_spheroid
+{
+ template <typename Box, typename Point>
+ static inline void apply(Box& box, Point const& point)
+ {
+ typedef typename point_type<Box>::type box_point_type;
+ typedef typename coordinate_type<Box>::type box_coordinate_type;
+
+ typedef math::detail::constants_on_spheroid
+ <
+ box_coordinate_type,
+ typename coordinate_system<Box>::type::units
+ > constants;
+
+ // normalize input point and input box
+ Point p_normalized = detail::return_normalized<Point>(point);
+ detail::normalize(box, box);
+
+ // transform input point to be of the same type as the box point
+ box_point_type box_point;
+ detail::envelope::transform_units(p_normalized, box_point);
+
+ box_coordinate_type p_lon = geometry::get<0>(box_point);
+ box_coordinate_type p_lat = geometry::get<1>(box_point);
+
+ typename coordinate_type<Box>::type
+ b_lon_min = geometry::get<min_corner, 0>(box),
+ b_lat_min = geometry::get<min_corner, 1>(box),
+ b_lon_max = geometry::get<max_corner, 0>(box),
+ b_lat_max = geometry::get<max_corner, 1>(box);
+
+ if (math::equals(math::abs(p_lat), constants::max_latitude()))
+ {
+ // the point of expansion is the either the north or the
+ // south pole; the only important coordinate here is the
+ // pole's latitude, as the longitude can be anything;
+ // we, thus, take into account the point's latitude only and return
+ geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
+ geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
+ return;
+ }
+
+ if (math::equals(b_lat_min, b_lat_max)
+ && math::equals(math::abs(b_lat_min), constants::max_latitude()))
+ {
+ // the box degenerates to either the north or the south pole;
+ // the only important coordinate here is the pole's latitude,
+ // as the longitude can be anything;
+ // we thus take into account the box's latitude only and return
+ geometry::set<min_corner, 0>(box, p_lon);
+ geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
+ geometry::set<max_corner, 0>(box, p_lon);
+ geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
+ return;
+ }
+
+ // update latitudes
+ b_lat_min = (std::min)(b_lat_min, p_lat);
+ b_lat_max = (std::max)(b_lat_max, p_lat);
+
+ // update longitudes
+ if (math::smaller(p_lon, b_lon_min))
+ {
+ box_coordinate_type p_lon_shifted = p_lon + constants::period();
+
+ if (math::larger(p_lon_shifted, b_lon_max))
+ {
+ // here we could check using: ! math::larger(.., ..)
+ if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
+ {
+ b_lon_min = p_lon;
+ }
+ else
+ {
+ b_lon_max = p_lon_shifted;
+ }
+ }
+ }
+ else if (math::larger(p_lon, b_lon_max))
+ {
+ // in this case, and since p_lon is normalized in the range
+ // (-180, 180], we must have that b_lon_max <= 180
+ if (b_lon_min < 0
+ && math::larger(p_lon - b_lon_max,
+ constants::period() - p_lon + b_lon_min))
+ {
+ b_lon_min = p_lon;
+ b_lon_max += constants::period();
+ }
+ else
+ {
+ b_lon_max = p_lon;
+ }
+ }
+
+ geometry::set<min_corner, 0>(box, b_lon_min);
+ geometry::set<min_corner, 1>(box, b_lat_min);
+ geometry::set<max_corner, 0>(box, b_lon_max);
+ geometry::set<max_corner, 1>(box, b_lat_max);
+
+ point_loop
+ <
+ StrategyLess, StrategyGreater, 2, DimensionCount
+ >::apply(box, point);
+ }
+};
+
+
+}} // namespace detail::expand
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// Box + point -> new box containing also point
+template
+<
+ typename BoxOut, typename Point,
+ typename StrategyLess, typename StrategyGreater,
+ typename CSTagOut, typename CSTag
+>
+struct expand
+ <
+ BoxOut, Point,
+ StrategyLess, StrategyGreater,
+ box_tag, point_tag,
+ CSTagOut, CSTag
+ > : detail::expand::point_loop
+ <
+ StrategyLess, StrategyGreater, 0, dimension<Point>::value
+ >
+{
+ BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
+ COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
+ (types<CSTagOut, CSTag>()));
+};
+
+template
+<
+ typename BoxOut, typename Point,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand
+ <
+ BoxOut, Point,
+ StrategyLess, StrategyGreater,
+ box_tag, point_tag,
+ spherical_equatorial_tag, spherical_equatorial_tag
+ > : detail::expand::point_loop_on_spheroid
+ <
+ StrategyLess, StrategyGreater, dimension<Point>::value
+ >
+{};
+
+template
+<
+ typename BoxOut, typename Point,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand
+ <
+ BoxOut, Point,
+ StrategyLess, StrategyGreater,
+ box_tag, point_tag,
+ geographic_tag, geographic_tag
+ > : detail::expand::point_loop_on_spheroid
+ <
+ StrategyLess, StrategyGreater, dimension<Point>::value
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
diff --git a/boost/geometry/algorithms/detail/expand/segment.hpp b/boost/geometry/algorithms/detail/expand/segment.hpp
new file mode 100644
index 0000000000..041c1e175f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/expand/segment.hpp
@@ -0,0 +1,115 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>
+#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
+
+#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
+
+#include <boost/geometry/algorithms/dispatch/expand.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace expand
+{
+
+
+struct segment_on_sphere
+{
+ template <typename Box, typename Segment>
+ static inline void apply(Box& box, Segment const& segment)
+ {
+ Box mbrs[2];
+
+ // compute the envelope of the segment
+ detail::envelope::envelope_segment_on_sphere
+ <
+ dimension<Segment>::value
+ >::apply(segment, mbrs[0]);
+
+ // normalize the box
+ detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]);
+
+ // compute the envelope of the two boxes
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box);
+ }
+};
+
+
+}} // namespace detail::expand
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Box, typename Segment,
+ typename StrategyLess, typename StrategyGreater,
+ typename CSTagOut, typename CSTag
+>
+struct expand
+ <
+ Box, Segment,
+ StrategyLess, StrategyGreater,
+ box_tag, segment_tag,
+ CSTagOut, CSTag
+ > : detail::expand::expand_indexed
+ <
+ 0, dimension<Segment>::value, StrategyLess, StrategyGreater
+ >
+{
+ BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
+ COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
+ (types<CSTagOut, CSTag>()));
+};
+
+template
+<
+ typename Box, typename Segment,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand
+ <
+ Box, Segment,
+ StrategyLess, StrategyGreater,
+ box_tag, segment_tag,
+ spherical_equatorial_tag, spherical_equatorial_tag
+ > : detail::expand::segment_on_sphere
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
diff --git a/boost/geometry/algorithms/detail/get_left_turns.hpp b/boost/geometry/algorithms/detail/get_left_turns.hpp
index 0fd243d8e3..95ab98c236 100644
--- a/boost/geometry/algorithms/detail/get_left_turns.hpp
+++ b/boost/geometry/algorithms/detail/get_left_turns.hpp
@@ -9,6 +9,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
+#include <boost/geometry/core/assert.hpp>
+
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
@@ -154,8 +156,8 @@ template <typename AngleCollection, typename Turns>
inline void get_left_turns(AngleCollection const& sorted_angles,
Turns& turns)
{
- std::set<int> good_incoming;
- std::set<int> good_outgoing;
+ std::set<std::size_t> good_incoming;
+ std::set<std::size_t> good_outgoing;
for (typename boost::range_iterator<AngleCollection const>::type it =
sorted_angles.begin(); it != sorted_angles.end(); ++it)
@@ -195,7 +197,7 @@ template <typename Point, typename AngleCollection>
inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin)
{
// Assign same cluster_index for all turns in same direction
- BOOST_ASSERT(boost::size(sorted) >= 4u);
+ BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u);
angle_equal_to<Point> comparator(origin);
typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
@@ -218,7 +220,7 @@ inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const&
template <typename AngleCollection>
inline void block_turns(AngleCollection& sorted, std::size_t cluster_size)
{
- BOOST_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0);
+ BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0);
std::vector<std::pair<bool, bool> > directions;
for (std::size_t i = 0; i < cluster_size; i++)
@@ -242,14 +244,14 @@ inline void block_turns(AngleCollection& sorted, std::size_t cluster_size)
for (typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
it != sorted.end(); ++it)
{
- int cluster_index = it->cluster_index;
- int previous_index = cluster_index - 1;
+ signed_size_type cluster_index = static_cast<signed_size_type>(it->cluster_index);
+ signed_size_type previous_index = cluster_index - 1;
if (previous_index < 0)
{
previous_index = cluster_size - 1;
}
- int next_index = cluster_index + 1;
- if (next_index >= static_cast<int>(cluster_size))
+ signed_size_type next_index = cluster_index + 1;
+ if (next_index >= static_cast<signed_size_type>(cluster_size))
{
next_index = 0;
}
diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp
index d57535e61f..2af618d974 100644
--- a/boost/geometry/algorithms/detail/intersection/interface.hpp
+++ b/boost/geometry/algorithms/detail/intersection/interface.hpp
@@ -120,7 +120,8 @@ struct intersection
>::type rescale_policy_type;
rescale_policy_type robust_policy
- = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
+ geometry2);
typedef strategy_intersection
<
@@ -151,8 +152,8 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
visitor(Geometry2 const& geometry2,
GeometryOut& geometry_out)
- : m_geometry2(geometry2),
- m_geometry_out(geometry_out)
+ : m_geometry2(geometry2)
+ , m_geometry_out(geometry_out)
{}
template <typename Geometry1>
@@ -176,7 +177,7 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Geometry2 const& geometry2,
GeometryOut& geometry_out)
{
- return apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1);
+ return boost::apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1);
}
};
@@ -192,8 +193,8 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
visitor(Geometry1 const& geometry1,
GeometryOut& geometry_out)
- : m_geometry1(geometry1),
- m_geometry_out(geometry_out)
+ : m_geometry1(geometry1)
+ , m_geometry_out(geometry_out)
{}
template <typename Geometry2>
@@ -213,12 +214,11 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename GeometryOut>
static inline bool
- apply(
- Geometry1 const& geometry1,
+ apply(Geometry1 const& geometry1,
const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
GeometryOut& geometry_out)
{
- return apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2);
+ return boost::apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2);
}
};
@@ -232,12 +232,11 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIAN
GeometryOut& m_geometry_out;
visitor(GeometryOut& geometry_out)
- : m_geometry_out(geometry_out)
+ : m_geometry_out(geometry_out)
{}
template <typename Geometry1, typename Geometry2>
- result_type operator()(
- Geometry1 const& geometry1,
+ result_type operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return intersection
@@ -254,12 +253,11 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIAN
template <typename GeometryOut>
static inline bool
- apply(
- const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
+ apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2,
GeometryOut& geometry_out)
{
- return apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2);
+ return boost::apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2);
}
};
diff --git a/boost/geometry/algorithms/detail/intersection/multi.hpp b/boost/geometry/algorithms/detail/intersection/multi.hpp
index b1f13862fc..88b49b0167 100644
--- a/boost/geometry/algorithms/detail/intersection/multi.hpp
+++ b/boost/geometry/algorithms/detail/intersection/multi.hpp
@@ -1,9 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -36,8 +36,6 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
-// TODO: remove this after moving num_point from multi directory
-#include <boost/geometry/multi/algorithms/num_points.hpp>
namespace boost { namespace geometry
{
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index 4f3e875eef..0f77a49498 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp
@@ -13,9 +13,9 @@
#include <algorithm>
#include <deque>
-#include <boost/assert.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -33,7 +33,7 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
-#include <boost/geometry/algorithms/detail/signed_index_type.hpp>
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
@@ -60,7 +60,7 @@ namespace detail { namespace is_simple
template <typename Turn>
inline bool check_segment_indices(Turn const& turn,
- signed_index_type last_index)
+ signed_size_type last_index)
{
return
(turn.operations[0].seg_id.segment_index == 0
@@ -89,7 +89,7 @@ public:
template <typename Turn>
inline bool apply(Turn const& turn) const
{
- BOOST_ASSERT(boost::size(m_linestring) > 1);
+ BOOST_GEOMETRY_ASSERT(boost::size(m_linestring) > 1);
return m_is_closed
&& turn.method == overlay::method_none
&& check_segment_indices(turn, boost::size(m_linestring) - 2)
@@ -112,7 +112,7 @@ private:
static inline bool is_boundary_point_of(Point const& point,
Linestring const& linestring)
{
- BOOST_ASSERT(boost::size(linestring) > 1);
+ BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1);
return
! geometry::equals(range::front(linestring),
range::back(linestring))
@@ -125,7 +125,7 @@ private:
static inline bool is_closing_point_of(Turn const& turn,
Linestring const& linestring)
{
- BOOST_ASSERT(boost::size(linestring) > 1);
+ BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1);
return
turn.method == overlay::method_none
&&
diff --git a/boost/geometry/algorithms/detail/is_valid/box.hpp b/boost/geometry/algorithms/detail/is_valid/box.hpp
index 139502af78..e7a67252ba 100644
--- a/boost/geometry/algorithms/detail/is_valid/box.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/box.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2014-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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -12,6 +13,8 @@
#include <cstddef>
+#include <boost/core/ignore_unused.hpp>
+
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -57,6 +60,8 @@ struct has_valid_corners<Box, 0>
template <typename VisitPolicy>
static inline bool apply(Box const&, VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
return visitor.template apply<no_failure>();
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
index c59139a92e..f08e70242c 100644
--- a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
@@ -17,9 +17,9 @@
#include <utility>
#include <vector>
-#include <boost/assert.hpp>
#include <boost/core/addressof.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/policies/compare.hpp>
@@ -104,12 +104,12 @@ private:
, m_parent_id(num_nodes, -1)
{}
- inline signed_index_type parent_id(vertex_handle v) const
+ inline signed_size_type parent_id(vertex_handle v) const
{
return m_parent_id[v->id()];
}
- inline void set_parent_id(vertex_handle v, signed_index_type id)
+ inline void set_parent_id(vertex_handle v, signed_size_type id)
{
m_parent_id[v->id()] = id;
}
@@ -125,7 +125,7 @@ private:
}
private:
std::vector<bool> m_visited;
- std::vector<signed_index_type> m_parent_id;
+ std::vector<signed_size_type> m_parent_id;
};
@@ -145,7 +145,7 @@ private:
= m_neighbors[v->id()].begin();
nit != m_neighbors[v->id()].end(); ++nit)
{
- if ( static_cast<signed_index_type>((*nit)->id()) != data.parent_id(v) )
+ if ( static_cast<signed_size_type>((*nit)->id()) != data.parent_id(v) )
{
if ( data.visited(*nit) )
{
@@ -153,7 +153,7 @@ private:
}
else
{
- data.set_parent_id(*nit, static_cast<signed_index_type>(v->id()));
+ data.set_parent_id(*nit, static_cast<signed_size_type>(v->id()));
stack.push(*nit);
}
}
@@ -173,7 +173,7 @@ public:
// inserts a ring vertex in the graph and returns its handle
// ring id's are zero-based (so the first interior ring has id 1)
- inline vertex_handle add_vertex(signed_index_type id)
+ inline vertex_handle add_vertex(signed_size_type id)
{
return m_vertices.insert(vertex(static_cast<std::size_t>(id))).first;
}
@@ -197,8 +197,8 @@ public:
inline void add_edge(vertex_handle v1, vertex_handle v2)
{
- BOOST_ASSERT( v1 != m_vertices.end() );
- BOOST_ASSERT( v2 != m_vertices.end() );
+ BOOST_GEOMETRY_ASSERT( v1 != m_vertices.end() );
+ BOOST_GEOMETRY_ASSERT( v2 != m_vertices.end() );
m_neighbors[v1->id()].insert(v2);
m_neighbors[v2->id()].insert(v1);
}
diff --git a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp b/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
index 5878841e70..685a4aac35 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
@@ -10,6 +10,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -35,8 +36,13 @@ struct has_duplicates
template <typename VisitPolicy>
static inline bool apply(Range const& range, VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
typedef typename closeable_view<Range const, Closure>::type view_type;
- typedef typename boost::range_iterator<view_type const>::type iterator;
+ typedef typename boost::range_const_iterator
+ <
+ view_type const
+ >::type const_iterator;
view_type view(range);
@@ -47,9 +53,10 @@ struct has_duplicates
geometry::equal_to<typename boost::range_value<Range>::type> equal;
- iterator it = boost::begin(view);
- iterator next = ++boost::begin(view);
- for (; next != boost::end(view); ++it, ++next)
+ const_iterator it = boost::const_begin(view);
+ const_iterator next = it;
+ ++next;
+ for (; next != boost::const_end(view); ++it, ++next)
{
if ( equal(*it, *next) )
{
diff --git a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
index 090c026e8b..aa90e52db6 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
@@ -12,9 +12,11 @@
#include <algorithm>
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -76,10 +78,23 @@ struct not_equal_to
template <typename Range, closure_selector Closure>
struct has_spikes
{
+ template <typename Iterator>
+ static inline Iterator find_different_from_first(Iterator first,
+ Iterator last)
+ {
+ typedef not_equal_to<typename point_type<Range>::type> not_equal;
+
+ BOOST_GEOMETRY_ASSERT(first != last);
+
+ Iterator second = first;
+ ++second;
+ return std::find_if(second, last, not_equal(*first));
+ }
+
template <typename VisitPolicy>
static inline bool apply(Range const& range, VisitPolicy& visitor)
{
- typedef not_equal_to<typename point_type<Range>::type> not_equal;
+ boost::ignore_unused(visitor);
typedef typename closeable_view<Range const, Closure>::type view_type;
typedef typename boost::range_iterator<view_type const>::type iterator;
@@ -91,23 +106,23 @@ struct has_spikes
iterator prev = boost::begin(view);
- iterator cur = std::find_if(prev, boost::end(view), not_equal(*prev));
- if ( cur == boost::end(view) )
+ iterator cur = find_different_from_first(prev, boost::end(view));
+ if (cur == boost::end(view))
{
// the range has only one distinct point, so it
// cannot have a spike
return ! visitor.template apply<no_failure>();
}
- iterator next = std::find_if(cur, boost::end(view), not_equal(*cur));
- if ( next == boost::end(view) )
+ iterator next = find_different_from_first(cur, boost::end(view));
+ if (next == boost::end(view))
{
// the range has only two distinct points, so it
// cannot have a spike
return ! visitor.template apply<no_failure>();
}
- while ( next != boost::end(view) )
+ while (next != boost::end(view))
{
if ( geometry::detail::point_is_spike_or_equal(*prev,
*next,
@@ -118,20 +133,19 @@ struct has_spikes
}
prev = cur;
cur = next;
- next = std::find_if(cur, boost::end(view), not_equal(*cur));
+ next = find_different_from_first(cur, boost::end(view));
}
- if ( geometry::equals(range::front(view), range::back(view)) )
+ if (geometry::equals(range::front(view), range::back(view)))
{
iterator cur = boost::begin(view);
typename boost::range_reverse_iterator
<
view_type const
- >::type prev = std::find_if(boost::rbegin(view),
- boost::rend(view),
- not_equal(range::back(view)));
- iterator next =
- std::find_if(cur, boost::end(view), not_equal(*cur));
+ >::type prev = find_different_from_first(boost::rbegin(view),
+ boost::rend(view));
+
+ iterator next = find_different_from_first(cur, boost::end(view));
if (detail::point_is_spike_or_equal(*prev, *next, *cur))
{
return
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 ecbc4782b2..0a81213743 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
@@ -12,9 +12,10 @@
#include <vector>
-#include <boost/assert.hpp>
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/policies/predicate_based_interrupt_policy.hpp>
@@ -73,6 +74,8 @@ public:
Turns& turns,
VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
@@ -88,7 +91,7 @@ public:
if (interrupt_policy.has_intersections)
{
- BOOST_ASSERT(! boost::empty(turns));
+ BOOST_GEOMETRY_ASSERT(! boost::empty(turns));
return visitor.template apply<failure_self_intersections>(turns);
}
else
diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp
index f83b09c437..0ec13b1b38 100644
--- a/boost/geometry/algorithms/detail/is_valid/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/interface.hpp
@@ -97,7 +97,7 @@ template <typename Geometry>
inline bool is_valid(Geometry const& geometry)
{
is_valid_default_policy<> policy_visitor;
- return is_valid(geometry, policy_visitor);
+ return geometry::is_valid(geometry, policy_visitor);
}
@@ -121,7 +121,7 @@ template <typename Geometry>
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)
{
failure_type_policy<> policy_visitor;
- bool result = is_valid(geometry, policy_visitor);
+ bool result = geometry::is_valid(geometry, policy_visitor);
failure = policy_visitor.failure();
return result;
}
@@ -148,7 +148,7 @@ inline bool is_valid(Geometry const& geometry, std::string& message)
{
std::ostringstream stream;
failing_reason_policy<> policy_visitor(stream);
- bool result = is_valid(geometry, policy_visitor);
+ bool result = geometry::is_valid(geometry, policy_visitor);
message = stream.str();
return result;
}
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index 69243563ec..e30064faf0 100644
--- a/boost/geometry/algorithms/detail/is_valid/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2014-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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -18,6 +19,7 @@
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/equals.hpp>
@@ -138,7 +140,8 @@ public:
static inline bool apply(MultiLinestring const& multilinestring,
VisitPolicy& visitor)
{
- if (AllowEmptyMultiGeometries && boost::empty(multilinestring))
+ if (BOOST_GEOMETRY_CONDITION(
+ AllowEmptyMultiGeometries && boost::empty(multilinestring)))
{
return visitor.template apply<no_failure>();
}
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 9362bfca0e..0025445c2c 100644
--- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2014-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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -13,6 +14,7 @@
#include <deque>
#include <vector>
+#include <boost/core/ignore_unused.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/range.hpp>
@@ -21,6 +23,7 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -80,8 +83,10 @@ private:
TurnIterator turns_beyond,
VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
// collect all polygons that have turns
- std::set<signed_index_type> multi_indices;
+ std::set<signed_size_type> multi_indices;
for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)
{
multi_indices.insert(tit->operations[0].seg_id.multi_index);
@@ -90,7 +95,7 @@ private:
// put polygon iterators without turns in a vector
std::vector<PolygonIterator> polygon_iterators;
- signed_index_type multi_index = 0;
+ signed_size_type multi_index = 0;
for (PolygonIterator it = polygons_first; it != polygons_beyond;
++it, ++multi_index)
{
@@ -124,7 +129,7 @@ private:
class has_multi_index
{
public:
- has_multi_index(signed_index_type multi_index)
+ has_multi_index(signed_size_type multi_index)
: m_multi_index(multi_index)
{}
@@ -136,7 +141,7 @@ private:
}
private:
- signed_index_type const m_multi_index;
+ signed_size_type const m_multi_index;
};
@@ -156,7 +161,7 @@ private:
TurnIterator turns_beyond,
VisitPolicy& visitor)
{
- signed_index_type multi_index = 0;
+ signed_size_type multi_index = 0;
for (PolygonIterator it = polygons_first; it != polygons_beyond;
++it, ++multi_index)
{
@@ -250,7 +255,8 @@ public:
{
typedef debug_validity_phase<MultiPolygon> debug_phase;
- if (AllowEmptyMultiGeometries && boost::empty(multipolygon))
+ if (BOOST_GEOMETRY_CONDITION(
+ AllowEmptyMultiGeometries && boost::empty(multipolygon)))
{
return visitor.template apply<no_failure>();
}
diff --git a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
index 8e5ebaadcc..e51ab74643 100644
--- a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2014-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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -10,6 +11,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -17,6 +19,8 @@
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -34,6 +38,7 @@ struct is_valid<Point, point_tag>
template <typename VisitPolicy>
static inline bool apply(Point const&, VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
return visitor.template apply<no_failure>();
}
};
@@ -51,7 +56,10 @@ struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries>
static inline bool apply(MultiPoint const& multipoint,
VisitPolicy& visitor)
{
- if (AllowEmptyMultiGeometries || boost::size(multipoint) > 0)
+ boost::ignore_unused(multipoint, visitor);
+
+ if (BOOST_GEOMETRY_CONDITION(
+ AllowEmptyMultiGeometries || !boost::empty(multipoint)))
{
// we allow empty multi-geometries, so an empty multipoint
// is considered valid
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index 17eefd226f..6e87273aa1 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
@@ -18,9 +18,10 @@
#include <set>
#include <vector>
-#include <boost/assert.hpp>
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
@@ -185,24 +186,26 @@ protected:
TurnIterator turns_beyond,
VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
// collect the interior ring indices that have turns with the
// exterior ring
- std::set<signed_index_type> ring_indices;
+ std::set<signed_size_type> ring_indices;
for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)
{
if (tit->operations[0].seg_id.ring_index == -1)
{
- BOOST_ASSERT(tit->operations[1].seg_id.ring_index != -1);
+ BOOST_GEOMETRY_ASSERT(tit->operations[1].seg_id.ring_index != -1);
ring_indices.insert(tit->operations[1].seg_id.ring_index);
}
else if (tit->operations[1].seg_id.ring_index == -1)
{
- BOOST_ASSERT(tit->operations[0].seg_id.ring_index != -1);
+ BOOST_GEOMETRY_ASSERT(tit->operations[0].seg_id.ring_index != -1);
ring_indices.insert(tit->operations[0].seg_id.ring_index);
}
}
- signed_index_type ring_index = 0;
+ signed_size_type ring_index = 0;
for (RingIterator it = rings_first; it != rings_beyond;
++it, ++ring_index)
{
@@ -303,6 +306,8 @@ protected:
TurnIterator beyond,
VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
typedef typename std::iterator_traits
<
TurnIterator
diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp
index c663a96d28..c35e843418 100644
--- a/boost/geometry/algorithms/detail/is_valid/ring.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2014-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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -12,6 +13,8 @@
#include <deque>
+#include <boost/core/ignore_unused.hpp>
+
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_order.hpp>
@@ -53,6 +56,8 @@ struct is_topologically_closed
template <typename VisitPolicy>
static inline bool apply(Ring const&, VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
return visitor.template apply<no_failure>();
}
};
@@ -63,6 +68,8 @@ struct is_topologically_closed<Ring, closed>
template <typename VisitPolicy>
static inline bool apply(Ring const& ring, VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
if (geometry::equals(range::front(ring), range::back(ring)))
{
return visitor.template apply<no_failure>();
@@ -112,6 +119,8 @@ struct is_properly_oriented
template <typename VisitPolicy>
static inline bool apply(Ring const& ring, VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
typename ring_area_predicate
<
area_result_type, IsInteriorRing
diff --git a/boost/geometry/algorithms/detail/is_valid/segment.hpp b/boost/geometry/algorithms/detail/is_valid/segment.hpp
index 0b60890dc0..a93d2bfe9e 100644
--- a/boost/geometry/algorithms/detail/is_valid/segment.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/segment.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2014-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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -10,6 +11,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP
+#include <boost/core/ignore_unused.hpp>
+
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -44,6 +47,8 @@ struct is_valid<Segment, segment_tag>
template <typename VisitPolicy>
static inline bool apply(Segment const& segment, VisitPolicy& visitor)
{
+ boost::ignore_unused(visitor);
+
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]);
diff --git a/boost/geometry/algorithms/detail/max_interval_gap.hpp b/boost/geometry/algorithms/detail/max_interval_gap.hpp
new file mode 100644
index 0000000000..e8a70a6b5f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/max_interval_gap.hpp
@@ -0,0 +1,278 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP
+
+#include <cstddef>
+#include <queue>
+#include <utility>
+#include <vector>
+
+#include <boost/core/ref.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/algorithms/detail/sweep.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace max_interval_gap
+{
+
+// the class Interval must provide the following:
+// * must define the type value_type
+// * must define the type difference_type
+// * must have the methods:
+// value_type get<Index>() const
+// difference_type length() const
+// where an Index value of 0 (resp., 1) refers to the left (resp.,
+// right) endpoint of the interval
+
+template <typename Interval>
+class sweep_event
+{
+public:
+ typedef Interval interval_type;
+ typedef typename Interval::value_type time_type;
+
+ sweep_event(Interval const& interval, bool start_event = true)
+ : m_interval(boost::cref(interval))
+ , m_start_event(start_event)
+ {}
+
+ inline bool is_start_event() const
+ {
+ return m_start_event;
+ }
+
+ inline interval_type const& interval() const
+ {
+ return m_interval;
+ }
+
+ inline time_type time() const
+ {
+ return (m_start_event)
+ ? interval().template get<0>()
+ : interval().template get<1>();
+ }
+
+ inline bool operator<(sweep_event const& other) const
+ {
+ if (! math::equals(time(), other.time()))
+ {
+ return time() < other.time();
+ }
+ // a start-event is before an end-event with the same event time
+ return is_start_event() && ! other.is_start_event();
+ }
+
+private:
+ boost::reference_wrapper<Interval const> m_interval;
+ bool m_start_event;
+};
+
+template <typename Event>
+struct event_greater
+{
+ inline bool operator()(Event const& event1, Event const& event2) const
+ {
+ return event2 < event1;
+ }
+};
+
+
+struct initialization_visitor
+{
+ template <typename Range, typename PriorityQueue, typename EventVisitor>
+ static inline void apply(Range const& range,
+ PriorityQueue& queue,
+ EventVisitor&)
+ {
+ BOOST_GEOMETRY_ASSERT(queue.empty());
+
+ // it is faster to build the queue directly from the entire
+ // range, rather than insert elements one after the other
+ PriorityQueue pq(boost::begin(range), boost::end(range));
+ std::swap(pq, queue);
+ }
+};
+
+
+template <typename Event>
+class event_visitor
+{
+ typedef typename Event::time_type event_time_type;
+ typedef typename Event::interval_type::difference_type difference_type;
+
+ typedef typename boost::remove_const
+ <
+ typename boost::remove_reference
+ <
+ event_time_type
+ >::type
+ >::type bare_time_type;
+
+
+public:
+ event_visitor()
+ : m_overlap_count(0)
+ , m_max_gap_left(0)
+ , m_max_gap_right(0)
+ {}
+
+ template <typename PriorityQueue>
+ inline void apply(Event const& event, PriorityQueue& queue)
+ {
+ if (event.is_start_event())
+ {
+ ++m_overlap_count;
+ queue.push(Event(event.interval(), false));
+ }
+ else
+ {
+ --m_overlap_count;
+ if (m_overlap_count == 0 && ! queue.empty())
+ {
+ // we may have a gap
+ BOOST_GEOMETRY_ASSERT(queue.top().is_start_event());
+
+ event_time_type next_event_time
+ = queue.top().interval().template get<0>();
+ difference_type gap = next_event_time - event.time();
+ if (gap > max_gap())
+ {
+ m_max_gap_left = event.time();
+ m_max_gap_right = next_event_time;
+ }
+ }
+ }
+ }
+
+ bare_time_type const& max_gap_left() const
+ {
+ return m_max_gap_left;
+ }
+
+ bare_time_type const& max_gap_right() const
+ {
+ return m_max_gap_right;
+ }
+
+ difference_type max_gap() const
+ {
+ return m_max_gap_right - m_max_gap_left;
+ }
+
+private:
+ std::size_t m_overlap_count;
+ bare_time_type m_max_gap_left, m_max_gap_right;
+};
+
+}} // namespace detail::max_interval_gap
+#endif // DOXYGEN_NO_DETAIL
+
+
+// Given a range of intervals I1, I2, ..., In, maximum_gap() returns
+// the maximum length of an interval M that satisfies the following
+// properties:
+//
+// 1. M.left >= min(I1, I2, ..., In)
+// 2. M.right <= max(I1, I2, ..., In)
+// 3. intersection(interior(M), Ik) is the empty set for all k=1, ..., n
+// 4. length(M) is maximal
+//
+// where M.left and M.right denote the left and right extreme values
+// for the interval M, and length(M) is equal to M.right - M.left.
+//
+// If M does not exist (or, alternatively, M is identified as the
+// empty set), 0 is returned.
+//
+// The algorithm proceeds for performing a sweep: the left endpoints
+// are inserted into a min-priority queue with the priority being the
+// value of the endpoint. The sweep algorithm maintains an "overlap
+// counter" that counts the number of overlaping intervals at any
+// specific sweep-time value.
+// There are two types of events encountered during the sweep:
+// (a) a start event: the left endpoint of an interval is found.
+// In this case the overlap count is increased by one and the
+// right endpoint of the interval in inserted into the event queue
+// (b) an end event: the right endpoint of an interval is found.
+// In this case the overlap count is decreased by one. If the
+// updated overlap count is 0, then we could expect to have a gap
+// in-between intervals. This gap is measured as the (absolute)
+// distance of the current interval right endpoint (being
+// processed) to the upcoming left endpoint of the next interval
+// to be processed (if such an interval exists). If the measured
+// gap is greater than the current maximum gap, it is recorded.
+// The initial maximum gap is initialized to 0. This value is returned
+// if no gap is found during the sweeping procedure.
+
+template <typename RangeOfIntervals, typename T>
+inline typename boost::range_value<RangeOfIntervals>::type::difference_type
+maximum_gap(RangeOfIntervals const& range_of_intervals,
+ T& max_gap_left, T& max_gap_right)
+{
+ typedef typename boost::range_value<RangeOfIntervals>::type interval_type;
+ typedef detail::max_interval_gap::sweep_event<interval_type> event_type;
+
+ // create a min-priority queue for the events
+ std::priority_queue
+ <
+ event_type,
+ std::vector<event_type>,
+ detail::max_interval_gap::event_greater<event_type>
+ > queue;
+
+ // define initialization and event-process visitors
+ detail::max_interval_gap::initialization_visitor init_visitor;
+ detail::max_interval_gap::event_visitor<event_type> sweep_visitor;
+
+ // perform the sweep
+ geometry::sweep(range_of_intervals,
+ queue,
+ init_visitor,
+ sweep_visitor);
+
+ max_gap_left = sweep_visitor.max_gap_left();
+ max_gap_right = sweep_visitor.max_gap_right();
+ return sweep_visitor.max_gap();
+}
+
+template <typename RangeOfIntervals>
+inline typename boost::range_value<RangeOfIntervals>::type::difference_type
+maximum_gap(RangeOfIntervals const& range_of_intervals)
+{
+ typedef typename boost::remove_const
+ <
+ typename boost::remove_reference
+ <
+ typename boost::range_value
+ <
+ RangeOfIntervals
+ >::type::value_type
+ >::type
+ >::type value_type;
+
+ value_type left, right;
+
+ return maximum_gap(range_of_intervals, left, right);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP
diff --git a/boost/geometry/algorithms/detail/normalize.hpp b/boost/geometry/algorithms/detail/normalize.hpp
new file mode 100644
index 0000000000..913fe324b7
--- /dev/null
+++ b/boost/geometry/algorithms/detail/normalize.hpp
@@ -0,0 +1,294 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
+#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
+
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace normalization
+{
+
+
+struct do_nothing
+{
+ template <typename GeometryIn, typename GeometryOut>
+ static inline void apply(GeometryIn const&, GeometryOut&)
+ {
+ }
+};
+
+
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct assign_loop
+{
+ template <typename CoordinateType, typename PointIn, typename PointOut>
+ static inline void apply(CoordinateType const& longitude,
+ CoordinateType const& latitude,
+ PointIn const& point_in,
+ PointOut& point_out)
+ {
+ geometry::set<Dimension>(point_out, boost::numeric_cast
+ <
+ typename coordinate_type<PointOut>::type
+ >(geometry::get<Dimension>(point_in)));
+
+ assign_loop
+ <
+ Dimension + 1, DimensionCount
+ >::apply(longitude, latitude, point_in, point_out);
+ }
+};
+
+template <std::size_t DimensionCount>
+struct assign_loop<DimensionCount, DimensionCount>
+{
+ template <typename CoordinateType, typename PointIn, typename PointOut>
+ static inline void apply(CoordinateType const&,
+ CoordinateType const&,
+ PointIn const&,
+ PointOut&)
+ {
+ }
+};
+
+template <std::size_t DimensionCount>
+struct assign_loop<0, DimensionCount>
+{
+ template <typename CoordinateType, typename PointIn, typename PointOut>
+ static inline void apply(CoordinateType const& longitude,
+ CoordinateType const& latitude,
+ PointIn const& point_in,
+ PointOut& point_out)
+ {
+ geometry::set<0>(point_out, boost::numeric_cast
+ <
+ typename coordinate_type<PointOut>::type
+ >(longitude));
+
+ assign_loop
+ <
+ 1, DimensionCount
+ >::apply(longitude, latitude, point_in, point_out);
+ }
+};
+
+template <std::size_t DimensionCount>
+struct assign_loop<1, DimensionCount>
+{
+ template <typename CoordinateType, typename PointIn, typename PointOut>
+ static inline void apply(CoordinateType const& longitude,
+ CoordinateType const& latitude,
+ PointIn const& point_in,
+ PointOut& point_out)
+ {
+ geometry::set<1>(point_out, boost::numeric_cast
+ <
+ typename coordinate_type<PointOut>::type
+ >(latitude));
+
+ assign_loop
+ <
+ 2, DimensionCount
+ >::apply(longitude, latitude, point_in, point_out);
+ }
+};
+
+
+template <typename PointIn, typename PointOut>
+struct normalize_point
+{
+ static inline void apply(PointIn const& point_in, PointOut& point_out)
+ {
+ typedef typename coordinate_type<PointIn>::type in_coordinate_type;
+
+ in_coordinate_type longitude = geometry::get<0>(point_in);
+ in_coordinate_type latitude = geometry::get<1>(point_in);
+
+ math::normalize_spheroidal_coordinates
+ <
+ typename coordinate_system<PointIn>::type::units,
+ in_coordinate_type
+ >(longitude, latitude);
+
+ assign_loop
+ <
+ 0, dimension<PointIn>::value
+ >::apply(longitude, latitude, point_in, point_out);
+ }
+};
+
+
+template <typename BoxIn, typename BoxOut>
+class normalize_box
+{
+ template <typename UnitsIn, typename UnitsOut, typename CoordinateInType>
+ static inline void apply_to_coordinates(CoordinateInType& lon_min,
+ CoordinateInType& lat_min,
+ CoordinateInType& lon_max,
+ CoordinateInType& lat_max,
+ BoxIn const& box_in,
+ BoxOut& box_out)
+ {
+ detail::indexed_point_view<BoxOut, min_corner> p_min_out(box_out);
+ assign_loop
+ <
+ 0, dimension<BoxIn>::value
+ >::apply(lon_min,
+ lat_min,
+ detail::indexed_point_view
+ <
+ BoxIn const, min_corner
+ >(box_in),
+ p_min_out);
+
+ detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out);
+ assign_loop
+ <
+ 0, dimension<BoxIn>::value
+ >::apply(lon_max,
+ lat_max,
+ detail::indexed_point_view
+ <
+ BoxIn const, max_corner
+ >(box_in),
+ p_max_out);
+ }
+
+public:
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out)
+ {
+ typedef typename coordinate_type<BoxIn>::type in_coordinate_type;
+
+ in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in);
+ in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in);
+ in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in);
+ in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in);
+
+ math::normalize_spheroidal_box_coordinates
+ <
+ typename coordinate_system<BoxIn>::type::units,
+ in_coordinate_type
+ >(lon_min, lat_min, lon_max, lat_max);
+
+ apply_to_coordinates
+ <
+ typename coordinate_system<BoxIn>::type::units,
+ typename coordinate_system<BoxOut>::type::units
+ >(lon_min, lat_min, lon_max, lat_max, box_in, box_out);
+ }
+};
+
+
+}} // namespace detail::normalization
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryIn,
+ typename GeometryOut,
+ typename TagIn = typename tag<GeometryIn>::type,
+ typename TagOut = typename tag<GeometryOut>::type,
+ typename CSTagIn = typename cs_tag<GeometryIn>::type,
+ typename CSTagOut = typename cs_tag<GeometryOut>::type
+>
+struct normalize : detail::normalization::do_nothing
+{};
+
+
+template <typename PointIn, typename PointOut>
+struct normalize
+ <
+ PointIn, PointOut, point_tag, point_tag,
+ spherical_equatorial_tag, spherical_equatorial_tag
+ > : detail::normalization::normalize_point<PointIn, PointOut>
+{};
+
+
+template <typename PointIn, typename PointOut>
+struct normalize
+ <
+ PointIn, PointOut, point_tag, point_tag, geographic_tag, geographic_tag
+ > : detail::normalization::normalize_point<PointIn, PointOut>
+{};
+
+
+template <typename BoxIn, typename BoxOut>
+struct normalize
+ <
+ BoxIn, BoxOut, box_tag, box_tag,
+ spherical_equatorial_tag, spherical_equatorial_tag
+ > : detail::normalization::normalize_box<BoxIn, BoxOut>
+{};
+
+
+template <typename BoxIn, typename BoxOut>
+struct normalize
+ <
+ BoxIn, BoxOut, box_tag, box_tag, geographic_tag, geographic_tag
+ > : detail::normalization::normalize_box<BoxIn, BoxOut>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename GeometryIn, typename GeometryOut>
+inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out)
+{
+ dispatch::normalize
+ <
+ GeometryIn, GeometryOut
+ >::apply(geometry_in, geometry_out);
+}
+
+template <typename GeometryOut, typename GeometryIn>
+inline GeometryOut return_normalized(GeometryIn const& geometry_in)
+{
+ GeometryOut geometry_out;
+ detail::normalize(geometry_in, geometry_out);
+ return geometry_out;
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP
diff --git a/boost/geometry/algorithms/detail/occupation_info.hpp b/boost/geometry/algorithms/detail/occupation_info.hpp
index 002c946170..4048d59d75 100644
--- a/boost/geometry/algorithms/detail/occupation_info.hpp
+++ b/boost/geometry/algorithms/detail/occupation_info.hpp
@@ -12,6 +12,7 @@
#include <algorithm>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -36,7 +37,7 @@ struct angle_info
typedef Point point_type;
segment_identifier seg_id;
- int turn_index;
+ std::size_t turn_index;
int operation_index;
std::size_t cluster_index;
Point intersection_point;
@@ -57,7 +58,7 @@ class occupation_info
public :
typedef std::vector<AngleInfo> collection_type;
- int count;
+ std::size_t count;
inline occupation_info()
: count(0)
@@ -67,7 +68,7 @@ public :
inline void add(RobustPoint const& incoming_point,
RobustPoint const& outgoing_point,
RobustPoint const& intersection_point,
- int turn_index, int operation_index,
+ std::size_t turn_index, int operation_index,
segment_identifier const& seg_id)
{
geometry::equal_to<RobustPoint> comparator;
@@ -125,11 +126,19 @@ private :
};
template<typename Pieces>
-inline void move_index(Pieces const& pieces, int& index, int& piece_index, int direction)
+inline void move_index(Pieces const& pieces, signed_size_type& index, signed_size_type& piece_index, int direction)
{
- BOOST_ASSERT(direction == 1 || direction == -1);
- BOOST_ASSERT(piece_index >= 0 && piece_index < static_cast<int>(boost::size(pieces)) );
- BOOST_ASSERT(index >= 0 && index < static_cast<int>(boost::size(pieces[piece_index].robust_ring)));
+ BOOST_GEOMETRY_ASSERT(direction == 1 || direction == -1);
+ BOOST_GEOMETRY_ASSERT(
+ piece_index >= 0
+ && piece_index < static_cast<signed_size_type>(boost::size(pieces)) );
+ BOOST_GEOMETRY_ASSERT(
+ index >= 0
+ && index < static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring)));
+
+ // NOTE: both index and piece_index must be in valid range
+ // this means that then they could be of type std::size_t
+ // if the code below was refactored
index += direction;
if (direction == -1 && index < 0)
@@ -142,10 +151,10 @@ inline void move_index(Pieces const& pieces, int& index, int& piece_index, int d
index = boost::size(pieces[piece_index].robust_ring) - 1;
}
if (direction == 1
- && index >= static_cast<int>(boost::size(pieces[piece_index].robust_ring)))
+ && index >= static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring)))
{
piece_index++;
- if (piece_index >= static_cast<int>(boost::size(pieces)))
+ if (piece_index >= static_cast<signed_size_type>(boost::size(pieces)))
{
piece_index = 0;
}
@@ -176,8 +185,8 @@ inline void add_incoming_and_outgoing_angles(
RobustPoint direction_points[2];
for (int i = 0; i < 2; i++)
{
- int index = turn.operations[operation_index].index_in_robust_ring;
- int piece_index = turn.operations[operation_index].piece_index;
+ signed_size_type index = turn.operations[operation_index].index_in_robust_ring;
+ signed_size_type piece_index = turn.operations[operation_index].piece_index;
while(comparator(pieces[piece_index].robust_ring[index], intersection_point))
{
move_index(pieces, index, piece_index, i == 0 ? -1 : 1);
diff --git a/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
index 5ff0b57d6e..fcb240941f 100644
--- a/boost/geometry/algorithms/detail/overlay/add_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
@@ -9,6 +9,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
+#include <boost/range.hpp>
+
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index 178f3825d7..047eb4993e 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -9,6 +9,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP
+#include <boost/range.hpp>
+
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
index 03be18e07a..25e442982b 100644
--- a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
+++ b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
@@ -12,12 +12,8 @@
#include <cstddef>
-
-#include <boost/assert.hpp>
#include <boost/range.hpp>
-
-
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
index fc4f657322..b1a25c9f5e 100644
--- a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
+++ b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// 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
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -160,10 +165,12 @@ template
typename OutputLinestring,
typename OutputIterator,
typename Range,
+ typename RobustPolicy,
typename Box,
typename Strategy
>
OutputIterator clip_range_with_box(Box const& b, Range const& range,
+ RobustPolicy const&,
OutputIterator out, Strategy const& strategy)
{
if (boost::begin(range) == boost::end(range))
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
index 13e0a5a51e..dbf3770357 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
@@ -11,10 +11,10 @@
#include <boost/array.hpp>
-#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@@ -43,8 +43,8 @@ struct copy_segment_point_range
{
detail::normalized_view<Range const> view(range);
- signed_index_type const n = boost::size(view);
- signed_index_type index = seg_id.segment_index;
+ signed_size_type const n = boost::size(view);
+ signed_size_type index = seg_id.segment_index;
if (second)
{
index++;
@@ -54,7 +54,7 @@ struct copy_segment_point_range
}
}
- BOOST_ASSERT(index >= 0 && index < n);
+ BOOST_GEOMETRY_ASSERT(index >= 0 && index < n);
geometry::convert(*(boost::begin(view) + index), point);
return true;
@@ -95,7 +95,7 @@ struct copy_segment_point_box
SegmentIdentifier const& seg_id, bool second,
PointOut& point)
{
- signed_index_type index = seg_id.segment_index;
+ signed_size_type index = seg_id.segment_index;
if (second)
{
index++;
@@ -123,7 +123,7 @@ struct copy_segment_point_multi
PointOut& point)
{
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
seg_id.multi_index >= 0
&& seg_id.multi_index < int(boost::size(multi))
@@ -306,7 +306,7 @@ inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geom
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
- BOOST_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1);
+ BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1);
if (seg_id.source_index == 0)
{
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
index ceeb1a3b8b..2eefa03c67 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
@@ -19,14 +19,11 @@
#include <vector>
#include <boost/array.hpp>
-#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/integral_constant.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
@@ -64,7 +61,7 @@ struct copy_segments_ring
>
static inline void apply(Ring const& ring,
SegmentIdentifier const& seg_id,
- signed_index_type to_index,
+ signed_size_type to_index,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@@ -93,10 +90,10 @@ struct copy_segments_ring
// So we use the ever-circling iterator and determine when to step out
- signed_index_type const from_index = seg_id.segment_index + 1;
+ signed_size_type const from_index = seg_id.segment_index + 1;
// Sanity check
- BOOST_ASSERT(from_index < static_cast<signed_index_type>(boost::size(view)));
+ BOOST_GEOMETRY_ASSERT(from_index < static_cast<signed_size_type>(boost::size(view)));
ec_iterator it(boost::begin(view), boost::end(view),
boost::begin(view) + from_index);
@@ -104,12 +101,12 @@ struct copy_segments_ring
// [2..4] -> 4 - 2 + 1 = 3 -> {2,3,4} -> OK
// [4..2],size=6 -> 6 - 4 + 2 + 1 = 5 -> {4,5,0,1,2} -> OK
// [1..1], travel the whole ring round
- signed_index_type const count = from_index <= to_index
+ signed_size_type const count = from_index <= to_index
? to_index - from_index + 1
- : static_cast<signed_index_type>(boost::size(view))
+ : static_cast<signed_size_type>(boost::size(view))
- from_index + to_index + 1;
- for (signed_index_type i = 0; i < count; ++i, ++it)
+ for (signed_size_type i = 0; i < count; ++i, ++it)
{
detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy);
}
@@ -151,26 +148,26 @@ public:
>
static inline void apply(LineString const& ls,
SegmentIdentifier const& seg_id,
- signed_index_type to_index,
+ signed_size_type to_index,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
- signed_index_type const from_index = seg_id.segment_index + 1;
+ signed_size_type const from_index = seg_id.segment_index + 1;
// Sanity check
if ( from_index > to_index
|| from_index < 0
- || to_index >= static_cast<signed_index_type>(boost::size(ls)) )
+ || to_index >= static_cast<signed_size_type>(boost::size(ls)) )
{
return;
}
- signed_index_type const count = to_index - from_index + 1;
+ signed_size_type const count = to_index - from_index + 1;
typename boost::range_iterator<LineString const>::type
it = boost::begin(ls) + from_index;
- for (signed_index_type i = 0; i < count; ++i, ++it)
+ for (signed_size_type i = 0; i < count; ++i, ++it)
{
append_to_output(current_output, *it, robust_policy,
boost::integral_constant<bool, RemoveSpikes>());
@@ -190,7 +187,7 @@ struct copy_segments_polygon
>
static inline void apply(Polygon const& polygon,
SegmentIdentifier const& seg_id,
- signed_index_type to_index,
+ signed_size_type to_index,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
@@ -220,14 +217,14 @@ struct copy_segments_box
>
static inline void apply(Box const& box,
SegmentIdentifier const& seg_id,
- signed_index_type to_index,
+ signed_size_type to_index,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
- signed_index_type index = seg_id.segment_index + 1;
- BOOST_ASSERT(index < 5);
+ signed_size_type index = seg_id.segment_index + 1;
+ BOOST_GEOMETRY_ASSERT(index < 5);
- signed_index_type const count = index <= to_index
+ signed_size_type const count = index <= to_index
? to_index - index + 1
: 5 - index + to_index + 1;
@@ -238,7 +235,7 @@ struct copy_segments_box
// (possibly cyclic) copy to output
// (see comments in ring-version)
- for (signed_index_type i = 0; i < count; i++, index++)
+ for (signed_size_type i = 0; i < count; i++, index++)
{
detail::overlay::append_no_dups_or_spikes(current_output,
bp[index % 5], robust_policy);
@@ -260,15 +257,15 @@ struct copy_segments_multi
>
static inline void apply(MultiGeometry const& multi_geometry,
SegmentIdentifier const& seg_id,
- signed_index_type to_index,
+ signed_size_type to_index,
RobustPolicy const& robust_policy,
RangeOut& current_output)
{
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
seg_id.multi_index >= 0
- && seg_id.multi_index < int(boost::size(multi_geometry))
+ && static_cast<std::size_t>(seg_id.multi_index) < boost::size(multi_geometry)
);
// Call the single-version
@@ -348,7 +345,7 @@ template
>
inline void copy_segments(Geometry const& geometry,
SegmentIdentifier const& seg_id,
- signed_index_type to_index,
+ signed_size_type to_index,
RobustPolicy const& robust_policy,
RangeOut& range_out)
{
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
index 7ed93f542a..3f81c4dca9 100644
--- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -22,7 +22,6 @@
# define BOOST_GEOMETRY_DEBUG_IDENTIFIER
#endif
-#include <boost/assert.hpp>
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
@@ -358,14 +357,14 @@ inline void enrich_assign(Container& operations,
= turn_points[it->turn_index].operations[it->operation_index];
prev_op.enriched.travels_to_ip_index
- = static_cast<int>(it->turn_index);
+ = static_cast<signed_size_type>(it->turn_index);
prev_op.enriched.travels_to_vertex_index
= it->subject->seg_id.segment_index;
if (! first
&& prev_op.seg_id.segment_index == op.seg_id.segment_index)
{
- prev_op.enriched.next_ip_index = static_cast<int>(it->turn_index);
+ prev_op.enriched.next_ip_index = static_cast<signed_size_type>(it->turn_index);
}
first = false;
}
diff --git a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
index ef32edeefa..5964f3ba44 100644
--- a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
@@ -37,13 +37,13 @@ struct enrichment_info
// vertex to which is free travel after this IP,
// so from "segment_index+1" to "travels_to_vertex_index", without IP-s,
// can be -1
- signed_index_type travels_to_vertex_index;
+ signed_size_type travels_to_vertex_index;
// same but now IP index, so "next IP index" but not on THIS segment
- int travels_to_ip_index;
+ signed_size_type travels_to_ip_index;
// index of next IP on this segment, -1 if there is no one
- int next_ip_index;
+ signed_size_type next_ip_index;
};
diff --git a/boost/geometry/algorithms/detail/overlay/follow.hpp b/boost/geometry/algorithms/detail/overlay/follow.hpp
index acf38d09ab..22807b5140 100644
--- a/boost/geometry/algorithms/detail/overlay/follow.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow.hpp
@@ -163,7 +163,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
static inline void enter(LineStringOut& current_piece,
LineString const& ,
segment_identifier& segment_id,
- signed_index_type , Point const& point,
+ signed_size_type , Point const& point,
Operation const& operation,
RobustPolicy const& ,
OutputIterator& )
@@ -186,7 +186,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
static inline void leave(LineStringOut& current_piece,
LineString const& linestring,
segment_identifier& segment_id,
- signed_index_type index, Point const& point,
+ signed_size_type index, Point const& point,
Operation const& ,
RobustPolicy const& robust_policy,
OutputIterator& out)
@@ -217,7 +217,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
static inline void isolated_point(LineStringOut&,
LineString const&,
segment_identifier&,
- signed_index_type, Point const& point,
+ signed_size_type, Point const& point,
Operation const& , OutputIterator& out)
{
LineStringOut isolated_point_ls;
@@ -268,7 +268,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
static inline void enter(LineStringOut& current_piece,
LineString const& linestring,
segment_identifier& segment_id,
- signed_index_type index, Point const& point,
+ signed_size_type index, Point const& point,
Operation const& operation,
RobustPolicy const& robust_policy,
OutputIterator& out)
@@ -289,7 +289,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
static inline void leave(LineStringOut& current_piece,
LineString const& linestring,
segment_identifier& segment_id,
- signed_index_type index, Point const& point,
+ signed_size_type index, Point const& point,
Operation const& operation,
RobustPolicy const& robust_policy,
OutputIterator& out)
@@ -309,7 +309,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
static inline void isolated_point(LineStringOut&,
LineString const&,
segment_identifier&,
- signed_index_type, Point const&,
+ signed_size_type, Point const&,
Operation const&, OutputIterator&)
{
}
@@ -496,7 +496,7 @@ public :
false, RemoveSpikes
>::apply(linestring,
current_segment_id,
- static_cast<signed_index_type>(boost::size(linestring) - 1),
+ static_cast<signed_size_type>(boost::size(linestring) - 1),
robust_policy,
current_piece);
}
diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
index 7bcc0b951e..b2c3836712 100644
--- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
@@ -14,9 +14,9 @@
#include <algorithm>
#include <iterator>
-#include <boost/assert.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -142,7 +142,7 @@ static inline bool is_isolated_point(Turn const& turn,
if ( turn.method == method_none )
{
- BOOST_ASSERT( operation.operation == operation_continue );
+ BOOST_GEOMETRY_ASSERT( operation.operation == operation_continue );
return true;
}
@@ -282,7 +282,7 @@ protected:
false, false // do not reverse; do not remove spikes
>::apply(linestring,
current_segment_id,
- static_cast<signed_index_type>(boost::size(linestring) - 1),
+ static_cast<signed_size_type>(boost::size(linestring) - 1),
robust_policy,
current_piece);
}
@@ -327,7 +327,7 @@ public:
throw inconsistent_turns_exception();
}
#else
- BOOST_ASSERT(enter_count == 0);
+ BOOST_GEOMETRY_ASSERT(enter_count == 0);
#endif
return process_end(entered, linestring,
@@ -404,7 +404,7 @@ protected:
};
template <typename TurnIterator>
- static inline signed_index_type get_multi_index(TurnIterator it)
+ static inline signed_size_type get_multi_index(TurnIterator it)
{
return boost::begin(it->operations)->seg_id.multi_index;
}
@@ -412,10 +412,10 @@ protected:
class has_other_multi_id
{
private:
- signed_index_type m_multi_id;
+ signed_size_type m_multi_id;
public:
- has_other_multi_id(signed_index_type multi_id)
+ has_other_multi_id(signed_size_type multi_id)
: m_multi_id(multi_id) {}
template <typename Turn>
@@ -433,7 +433,7 @@ public:
TurnIterator first, TurnIterator beyond,
OutputIterator oit)
{
- BOOST_ASSERT( first != beyond );
+ BOOST_GEOMETRY_ASSERT( first != beyond );
typedef copy_linestrings_in_range
<
@@ -446,7 +446,7 @@ public:
// Iterate through all intersection points (they are
// ordered along the each linestring)
- signed_index_type current_multi_id = get_multi_index(first);
+ signed_size_type current_multi_id = get_multi_index(first);
oit = copy_linestrings::apply(ls_first,
ls_first + current_multi_id,
@@ -463,7 +463,7 @@ public:
oit = Base::apply(*(ls_first + current_multi_id),
linear, per_ls_current, per_ls_next, oit);
- signed_index_type next_multi_id(-1);
+ signed_size_type next_multi_id = -1;
linestring_iterator ls_next = ls_beyond;
if ( per_ls_next != beyond )
{
diff --git a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
index 63011c7d48..4668189924 100644
--- a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
@@ -12,6 +12,9 @@
#include <cstddef>
+#include <boost/mpl/if.hpp>
+#include <boost/range.hpp>
+
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/boost/geometry/algorithms/detail/overlay/get_ring.hpp
index 131d58d582..460c30def3 100644
--- a/boost/geometry/algorithms/detail/overlay/get_ring.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_ring.hpp
@@ -10,9 +10,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
-#include <boost/assert.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
@@ -82,7 +82,7 @@ struct get_ring<polygon_tag>
ring_identifier const& id,
Polygon const& polygon)
{
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
id.ring_index >= -1
&& id.ring_index < int(boost::size(interior_rings(polygon)))
@@ -102,7 +102,7 @@ struct get_ring<multi_polygon_tag>
ring_identifier const& id,
MultiPolygon const& multi_polygon)
{
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
id.multi_index >= 0
&& id.multi_index < int(boost::size(multi_polygon))
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index b3b1a06f68..717f0b47a9 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -15,10 +15,10 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
-#include <boost/assert.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/algorithms/convert.hpp>
@@ -115,7 +115,7 @@ struct base_turn_handler
{
ti.method = method;
- BOOST_ASSERT(index < info.count);
+ BOOST_GEOMETRY_ASSERT(index < info.count);
geometry::convert(info.intersections[index], ti.point);
ti.operations[0].fraction = info.fractions[index].robust_ra;
@@ -597,7 +597,7 @@ struct collinear : public base_turn_handler
int const arrival = dir_info.arrival[0];
// Should not be 0, this is checked before
- BOOST_ASSERT(arrival != 0);
+ BOOST_GEOMETRY_ASSERT(arrival != 0);
int const side_p = side.pk_wrt_p1();
int const side_q = side.qk_wrt_q1();
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 4a3cacbedd..0b3cb72747 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
@@ -14,6 +14,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
@@ -153,7 +154,7 @@ public:
}
else
{
- BOOST_ASSERT(result.template get<0>().count == 1);
+ BOOST_GEOMETRY_ASSERT(result.template get<0>().count == 1);
ips[0].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last);
ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last);
@@ -297,10 +298,10 @@ struct get_turn_info_for_endpoint
// may this give false positives for INTs?
typename IntersectionResult::point_type const&
inters_pt = result.template get<0>().intersections[ip_index];
- BOOST_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt));
- BOOST_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt));
- BOOST_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt));
- BOOST_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt));
#endif
// TODO - calculate first/last only if needed
@@ -412,8 +413,8 @@ struct get_turn_info_for_endpoint
// may this give false positives for INTs?
typename IntersectionResult::point_type const&
inters_pt = inters.i_info().intersections[ip_index];
- BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));
- BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));
#endif
if ( ip_i2 )
{
@@ -448,7 +449,7 @@ struct get_turn_info_for_endpoint
}
else
{
- BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union));
+ BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union));
//op1 = operation_union;
//op2 = operation_union;
}
@@ -463,8 +464,8 @@ struct get_turn_info_for_endpoint
// may this give false positives for INTs?
typename IntersectionResult::point_type const&
inters_pt = inters.i_info().intersections[ip_index];
- BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));
- BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));
+ BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));
#endif
if ( ip_i2 )
{
@@ -499,7 +500,7 @@ struct get_turn_info_for_endpoint
}
else
{
- BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union));
+ BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union));
//op1 = operation_blocked;
//op2 = operation_union;
}
@@ -560,7 +561,7 @@ struct get_turn_info_for_endpoint
// NOTE: is_collinear is NOT set for the first endpoint
// for which there is no preceding segment
- //BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
+ //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
if ( ! is_p_first_ip )
{
tp.operations[0].is_collinear = op0 != operation_intersection
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 e0d75108b9..e4f8de42e1 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -42,7 +42,8 @@ template <typename PointP, typename PointQ,
>
struct side_calculator
{
- typedef boost::geometry::strategy::side::side_by_triangle<> side; // todo: get from coordinate system
+ // todo: get from coordinate system
+ typedef boost::geometry::strategy::side::side_by_triangle<> side;
inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
Qi const& qi, Qj const& qj, Qk const& qk)
@@ -71,8 +72,9 @@ struct robust_points
{
typedef typename geometry::robust_point_type
<
- Point1, RobustPolicy
+ Point1, RobustPolicy
>::type robust_point1_type;
+
// TODO: define robust_point2_type using Point2?
typedef robust_point1_type robust_point2_type;
@@ -96,23 +98,23 @@ template <typename Point1, typename Point2, typename RobustPolicy>
class intersection_info_base
: private robust_points<Point1, Point2, RobustPolicy>
{
- typedef robust_points<Point1, Point2, RobustPolicy> base_t;
+ typedef robust_points<Point1, Point2, RobustPolicy> base;
public:
typedef Point1 point1_type;
typedef Point2 point2_type;
- typedef typename base_t::robust_point1_type robust_point1_type;
- typedef typename base_t::robust_point2_type robust_point2_type;
+ typedef typename base::robust_point1_type robust_point1_type;
+ typedef typename base::robust_point2_type robust_point2_type;
typedef side_calculator<robust_point1_type, robust_point2_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,
RobustPolicy const& robust_policy)
- : base_t(pi, pj, pk, qi, qj, qk, robust_policy)
- , m_side_calc(base_t::m_rpi, base_t::m_rpj, base_t::m_rpk,
- base_t::m_rqi, base_t::m_rqj, base_t::m_rqk)
+ : 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)
, m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
{}
@@ -125,13 +127,13 @@ public:
inline Point2 const& qj() const { return m_qj; }
inline Point2 const& qk() const { return m_qk; }
- inline robust_point1_type const& rpi() const { return base_t::m_rpi; }
- inline robust_point1_type const& rpj() const { return base_t::m_rpj; }
- inline robust_point1_type const& rpk() const { return base_t::m_rpk; }
+ inline robust_point1_type const& rpi() const { return base::m_rpi; }
+ inline robust_point1_type const& rpj() const { return base::m_rpj; }
+ inline robust_point1_type const& rpk() const { return base::m_rpk; }
- inline robust_point2_type const& rqi() const { return base_t::m_rqi; }
- inline robust_point2_type const& rqj() const { return base_t::m_rqj; }
- inline robust_point2_type const& rqk() const { return base_t::m_rqk; }
+ inline robust_point2_type const& rqi() const { return base::m_rqi; }
+ inline robust_point2_type const& rqj() const { return base::m_rqj; }
+ inline robust_point2_type const& rqk() const { return base::m_rqk; }
inline side_calculator_type const& sides() const { return m_side_calc; }
@@ -187,11 +189,17 @@ private:
};
-template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>
+template
+<
+ typename Point1,
+ typename Point2,
+ typename TurnPoint,
+ typename RobustPolicy
+>
class intersection_info
: public intersection_info_base<Point1, Point2, RobustPolicy>
{
- typedef intersection_info_base<Point1, Point2, RobustPolicy> base_t;
+ typedef intersection_info_base<Point1, Point2, RobustPolicy> base;
typedef typename strategy_intersection
<
@@ -205,7 +213,7 @@ class intersection_info
public:
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
- typedef typename base_t::side_calculator_type side_calculator_type;
+ typedef typename base::side_calculator_type side_calculator_type;
typedef typename strategy::return_type result_type;
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
@@ -214,10 +222,12 @@ public:
intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
RobustPolicy const& robust_policy)
- : base_t(pi, pj, pk, qi, qj, qk, 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))
+ robust_policy,
+ base::rpi(), base::rpj(),
+ base::rqi(), base::rqj()))
, m_robust_policy(robust_policy)
{}
@@ -228,19 +238,22 @@ public:
// TODO: it's more like is_spike_ip_p
inline bool is_spike_p() const
{
- if ( base_t::sides().pk_wrt_p1() == 0 )
+ if (base::sides().pk_wrt_p1() == 0)
{
- if ( ! is_ip_j<0>() )
+ if (! is_ip_j<0>())
+ {
return false;
+ }
- int const qk_p1 = base_t::sides().qk_wrt_p1();
- int const qk_p2 = base_t::sides().qk_wrt_p2();
+ int const qk_p1 = base::sides().qk_wrt_p1();
+ int const qk_p2 = base::sides().qk_wrt_p2();
- if ( qk_p1 == -qk_p2 )
+ if (qk_p1 == -qk_p2)
{
- if ( qk_p1 == 0 )
+ if (qk_p1 == 0)
{
- return is_spike_of_collinear(base_t::pi(), base_t::pj(), base_t::pk());
+ return is_spike_of_collinear(base::pi(), base::pj(),
+ base::pk());
}
return true;
@@ -253,19 +266,22 @@ public:
// TODO: it's more like is_spike_ip_q
inline bool is_spike_q() const
{
- if ( base_t::sides().qk_wrt_q1() == 0 )
+ if (base::sides().qk_wrt_q1() == 0)
{
- if ( ! is_ip_j<1>() )
+ if (! is_ip_j<1>())
+ {
return false;
+ }
- int const pk_q1 = base_t::sides().pk_wrt_q1();
- int const pk_q2 = base_t::sides().pk_wrt_q2();
+ int const pk_q1 = base::sides().pk_wrt_q1();
+ int const pk_q2 = base::sides().pk_wrt_q2();
- if ( pk_q1 == -pk_q2 )
+ if (pk_q1 == -pk_q2)
{
- if ( pk_q1 == 0 )
+ if (pk_q1 == 0)
{
- return is_spike_of_collinear(base_t::qi(), base_t::qj(), base_t::qk());
+ return is_spike_of_collinear(base::qi(), base::qj(),
+ base::qk());
}
return true;
@@ -277,9 +293,10 @@ public:
private:
template <typename Point>
- inline bool is_spike_of_collinear(Point const& i, Point const& j, Point const& k) const
+ inline bool is_spike_of_collinear(Point const& i, Point const& j,
+ Point const& k) const
{
- typedef model::referring_segment<Point const> seg_t;
+ typedef model::referring_segment<Point const> seg;
typedef strategy_intersection
<
@@ -289,7 +306,7 @@ private:
typedef typename si::segment_intersection_strategy_type strategy;
typename strategy::return_type result
- = strategy::apply(seg_t(i, j), seg_t(j, k), m_robust_policy);
+ = strategy::apply(seg(i, j), seg(j, k), m_robust_policy);
return result.template get<0>().count == 2;
}
@@ -300,9 +317,9 @@ private:
int arrival = d_info().arrival[OpId];
bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0;
- if ( same_dirs )
+ if (same_dirs)
{
- if ( i_info().count == 2 )
+ if (i_info().count == 2)
{
return arrival != -1;
}
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 71946543ee..ccb42d4c92 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
@@ -14,6 +14,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/geometry/core/assert.hpp>
+
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
@@ -569,7 +571,7 @@ struct get_turn_info_linear_areal
tp.operations[0].is_collinear = true;
//tp.operations[1].is_collinear = false;
- BOOST_ASSERT(inters.i_info().count > 1);
+ BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1);
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1);
AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters);
@@ -816,7 +818,7 @@ struct get_turn_info_linear_areal
if ( inters.i_info().count > 1 )
{
- //BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
+ //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
tp.operations[0].is_collinear = true;
tp.operations[1].operation = opposite ? operation_continue : operation_union;
}
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 1ec88e54a0..19f0859cbb 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
@@ -14,6 +14,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP
+#include <boost/geometry/core/assert.hpp>
+
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp>
@@ -579,7 +581,7 @@ struct get_turn_info_linear_linear
tp.operations[0].is_collinear = true;
tp.operations[1].is_collinear = false;
- BOOST_ASSERT(inters.i_info().count > 1);
+ BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1);
base_turn_handler::assign_point(tp, method_touch_interior,
inters.i_info(), 1);
@@ -612,7 +614,7 @@ struct get_turn_info_linear_linear
tp.operations[0].is_collinear = false;
tp.operations[1].is_collinear = true;
- BOOST_ASSERT(inters.i_info().count > 0);
+ BOOST_GEOMETRY_ASSERT(inters.i_info().count > 0);
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0);
@@ -686,7 +688,7 @@ struct get_turn_info_linear_linear
operation_type & op0 = turn.operations[0].operation;
operation_type & op1 = turn.operations[1].operation;
- BOOST_ASSERT(op0 != operation_blocked || op1 != operation_blocked );
+ BOOST_GEOMETRY_ASSERT(op0 != operation_blocked || op1 != operation_blocked );
if ( op0 == operation_blocked )
{
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
index a5d8f3f023..098c7b5642 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -22,6 +22,7 @@
#include <boost/array.hpp>
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
+#include <boost/mpl/vector_c.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/access.hpp>
@@ -142,7 +143,7 @@ class get_turns_in_sections
template <typename Geometry, typename Section>
static inline bool neighbouring(Section const& section,
- int index1, int index2)
+ signed_size_type index1, signed_size_type index2)
{
// About n-2:
// (square: range_count=5, indices 0,1,2,3
@@ -150,7 +151,7 @@ class get_turns_in_sections
// Also tested for open polygons, and/or duplicates
// About first condition: will be optimized by compiler (static)
// It checks if it is areal (box,ring,(multi)polygon
- int const n = int(section.range_count);
+ signed_size_type const n = static_cast<signed_size_type>(section.range_count);
boost::ignore_unused_variable_warning(n);
boost::ignore_unused_variable_warning(index1);
@@ -207,8 +208,8 @@ public :
int const dir1 = sec1.directions[0];
int const dir2 = sec2.directions[0];
- int index1 = sec1.begin_index;
- int ndi1 = sec1.non_duplicate_index;
+ signed_size_type index1 = sec1.begin_index;
+ signed_size_type ndi1 = sec1.non_duplicate_index;
bool const same_source =
source_id1 == source_id2
@@ -236,8 +237,8 @@ public :
begin_range_1, end_range_1, next1, true);
advance_to_non_duplicate_next(nd_next1, it1, sec1, robust_policy);
- int index2 = sec2.begin_index;
- int ndi2 = sec2.non_duplicate_index;
+ signed_size_type index2 = sec2.begin_index;
+ signed_size_type ndi2 = sec2.non_duplicate_index;
range2_iterator prev2, it2, end2;
@@ -359,7 +360,7 @@ private :
typename boost::range_iterator<Range const>::type& it,
typename boost::range_iterator<Range const>::type& prev,
typename boost::range_iterator<Range const>::type& end,
- int& index, int& ndi,
+ signed_size_type& index, signed_size_type& ndi,
int dir, Box const& other_bounding_box, RobustPolicy const& robust_policy)
{
it = boost::begin(range) + section.begin_index;
@@ -524,8 +525,8 @@ struct get_turns_cs
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
- signed_index_type multi_index = -1,
- signed_index_type ring_index = -1)
+ signed_size_type multi_index = -1,
+ signed_size_type ring_index = -1)
{
if ( boost::size(range) <= 1)
{
@@ -552,7 +553,7 @@ struct get_turns_cs
//char previous_side[2] = {0, 0};
- signed_index_type index = 0;
+ signed_size_type index = 0;
for (iterator_type prev = it++;
it != boost::end(view);
@@ -696,7 +697,7 @@ struct get_turns_polygon_cs
int source_id2, Box const& box,
RobustPolicy const& robust_policy,
Turns& turns, InterruptPolicy& interrupt_policy,
- signed_index_type multi_index = -1)
+ signed_size_type multi_index = -1)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
@@ -714,7 +715,7 @@ struct get_turns_polygon_cs
turns, interrupt_policy,
multi_index, -1);
- signed_index_type i = 0;
+ signed_size_type i = 0;
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -753,7 +754,7 @@ struct get_turns_multi_polygon_cs
Multi const
>::type iterator_type;
- signed_index_type i = 0;
+ signed_size_type i = 0;
for (iterator_type it = boost::begin(multi);
it != boost::end(multi);
++it, ++i)
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index 3101de8c35..af0731f5a9 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -1,9 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2015 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, 2015.
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -39,9 +39,11 @@
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/views/segment_view.hpp>
+#include <boost/geometry/views/detail/boundary_view.hpp>
#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
+#include <boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp>
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
@@ -283,7 +285,8 @@ namespace dispatch
template
<
// real types
- typename Geometry1, typename Geometry2,
+ typename Geometry1,
+ typename Geometry2,
typename GeometryOut,
overlay_type OverlayType,
// orientation
@@ -409,13 +412,13 @@ struct intersection_insert
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Linestring const& linestring,
Box const& box,
- RobustPolicy const& ,
+ RobustPolicy const& robust_policy,
OutputIterator out, Strategy const& )
{
typedef typename point_type<GeometryOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
return detail::intersection::clip_range_with_box
- <GeometryOut>(box, linestring, out, lb_strategy);
+ <GeometryOut>(box, linestring, robust_policy, out, lb_strategy);
}
};
@@ -487,7 +490,7 @@ struct intersection_insert
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Segment const& segment,
Box const& box,
- RobustPolicy const& ,// TODO: propagate to clip_range_with_box
+ RobustPolicy const& robust_policy,
OutputIterator out, Strategy const& )
{
geometry::segment_view<Segment> range(segment);
@@ -495,7 +498,7 @@ struct intersection_insert
typedef typename point_type<GeometryOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
return detail::intersection::clip_range_with_box
- <GeometryOut>(box, range, out, lb_strategy);
+ <GeometryOut>(box, range, robust_policy, out, lb_strategy);
}
};
@@ -573,6 +576,46 @@ struct intersection_insert_reversed
};
+// dispatch for intersection(areal, areal, linear)
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename LinestringOut,
+ bool Reverse1, bool Reverse2, bool ReverseOut,
+ typename Tag1, typename Tag2
+>
+struct intersection_insert
+ <
+ Geometry1, Geometry2,
+ LinestringOut,
+ overlay_intersection,
+ Reverse1, Reverse2, ReverseOut,
+ Tag1, Tag2, linestring_tag,
+ true, true, false
+ >
+{
+ template
+ <
+ typename RobustPolicy, typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator oit,
+ Strategy const& strategy)
+ {
+ detail::boundary_view<Geometry1 const> view1(geometry1);
+ detail::boundary_view<Geometry2 const> view2(geometry2);
+
+ return detail::overlay::linear_linear_linestring
+ <
+ detail::boundary_view<Geometry1 const>,
+ detail::boundary_view<Geometry2 const>,
+ LinestringOut,
+ overlay_intersection
+ >::apply(view1, view2, robust_policy, oit, strategy);
+ }
+};
// dispatch for non-areal geometries
template
@@ -700,6 +743,79 @@ struct intersection_insert
{};
+// dispatch for difference/intersection of pointlike-linear geometries
+template
+<
+ typename Point, typename Linear, typename PointOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut,
+ typename Tag
+>
+struct intersection_insert
+ <
+ Point, Linear, PointOut, OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ point_tag, Tag, point_tag,
+ false, false, false
+ > : detail_dispatch::overlay::pointlike_linear_point
+ <
+ Point, Linear, PointOut, OverlayType,
+ point_tag, typename tag_cast<Tag, segment_tag, linear_tag>::type
+ >
+{};
+
+
+template
+<
+ typename MultiPoint, typename Linear, typename PointOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut,
+ typename Tag
+>
+struct intersection_insert
+ <
+ MultiPoint, Linear, PointOut, OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ multi_point_tag, Tag, point_tag,
+ false, false, false
+ > : detail_dispatch::overlay::pointlike_linear_point
+ <
+ MultiPoint, Linear, PointOut, OverlayType,
+ multi_point_tag,
+ typename tag_cast<Tag, segment_tag, linear_tag>::type
+ >
+{};
+
+
+template
+<
+ typename Linestring, typename MultiPoint, typename PointOut,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Linestring, MultiPoint, PointOut, overlay_intersection,
+ Reverse1, Reverse2, ReverseOut,
+ linestring_tag, multi_point_tag, point_tag,
+ false, false, false
+ >
+{
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(Linestring const& linestring,
+ MultiPoint const& multipoint,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ return detail_dispatch::overlay::pointlike_linear_point
+ <
+ MultiPoint, Linestring, PointOut, overlay_intersection,
+ multi_point_tag, linear_tag
+ >::apply(multipoint, linestring, robust_policy, out, strategy);
+ }
+};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index d4ebcf296b..34517f6590 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -157,13 +157,18 @@ protected:
<
typename Turns,
typename LinearGeometry1,
- typename LinearGeometry2
+ typename LinearGeometry2,
+ typename RobustPolicy
>
static inline void compute_turns(Turns& turns,
LinearGeometry1 const& linear1,
- LinearGeometry2 const& linear2)
+ LinearGeometry2 const& linear2,
+ RobustPolicy const& robust_policy)
{
turns.clear();
+
+ detail::get_turns::no_interrupt_policy interrupt_policy;
+
geometry::detail::relate::turns::get_turns
<
LinearGeometry1,
@@ -173,8 +178,9 @@ protected:
LinearGeometry1,
LinearGeometry2,
assign_policy
- >
- >::apply(turns, linear1, linear2);
+ >,
+ RobustPolicy
+ >::apply(turns, linear1, linear2, interrupt_policy, robust_policy);
}
@@ -229,19 +235,27 @@ public:
>
static inline OutputIterator apply(Linear1 const& linear1,
Linear2 const& linear2,
- RobustPolicy const&,
+ RobustPolicy const& robust_policy,
OutputIterator oit,
Strategy const& )
{
typedef typename detail::relate::turns::get_turns
<
- Linear1, Linear2
+ Linear1,
+ Linear2,
+ detail::get_turns::get_turn_info_type
+ <
+ Linear1,
+ Linear2,
+ assign_policy
+ >,
+ RobustPolicy
>::turn_info turn_info;
typedef std::vector<turn_info> turns_container;
turns_container turns;
- compute_turns(turns, linear1, linear2);
+ compute_turns(turns, linear1, linear2, robust_policy);
if ( turns.empty() )
{
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index a2f52848d1..baf9d4777d 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -1,7 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland
+// 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.
+
+// 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
@@ -28,7 +33,7 @@
#include <boost/geometry/algorithms/detail/recalculate.hpp>
-#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/reverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>
@@ -125,8 +130,7 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
// Intersection: return nothing
// Difference: return first of them
if (Direction == overlay_intersection
- || (Direction == overlay_difference
- && geometry::num_points(geometry1) == 0))
+ || (Direction == overlay_difference && geometry::is_empty(geometry1)))
{
return out;
}
@@ -162,14 +166,15 @@ struct overlay
OutputIterator out,
Strategy const& )
{
- if ( geometry::num_points(geometry1) == 0
- && geometry::num_points(geometry2) == 0 )
+ bool const is_empty1 = geometry::is_empty(geometry1);
+ bool const is_empty2 = geometry::is_empty(geometry2);
+
+ if (is_empty1 && is_empty2)
{
return out;
}
- if ( geometry::num_points(geometry1) == 0
- || geometry::num_points(geometry2) == 0 )
+ if (is_empty1 || is_empty2)
{
return return_if_one_input_is_empty
<
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
new file mode 100644
index 0000000000..156cb54867
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
@@ -0,0 +1,343 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, 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
+
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
+
+#include <iterator>
+#include <vector>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/iterators/segment_iterator.hpp>
+
+#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/algorithms/detail/not.hpp>
+#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/algorithms/detail/relate/less.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+// action struct for pointlike-linear difference/intersection
+// it works the same as its pointlike-pointlike counterpart, hence the
+// derivation
+template <typename PointOut, overlay_type OverlayType>
+struct action_selector_pl_l
+ : action_selector_pl_pl<PointOut, OverlayType>
+{};
+
+// difference/intersection of point-linear
+template
+<
+ typename Point,
+ typename Linear,
+ typename PointOut,
+ overlay_type OverlayType,
+ typename Policy
+>
+struct point_linear_point
+{
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(Point const& point,
+ Linear const& linear,
+ RobustPolicy const&,
+ OutputIterator oit,
+ Strategy const&)
+ {
+ action_selector_pl_l
+ <
+ PointOut, OverlayType
+ >::apply(point, Policy::apply(point, linear), oit);
+ return oit;
+ }
+};
+
+// difference/intersection of multipoint-segment
+template
+<
+ typename MultiPoint,
+ typename Segment,
+ typename PointOut,
+ overlay_type OverlayType,
+ typename Policy
+>
+struct multipoint_segment_point
+{
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(MultiPoint const& multipoint,
+ Segment const& segment,
+ RobustPolicy const&,
+ OutputIterator oit,
+ Strategy const&)
+ {
+ for (typename boost::range_iterator<MultiPoint const>::type
+ it = boost::begin(multipoint);
+ it != boost::end(multipoint);
+ ++it)
+ {
+ action_selector_pl_l
+ <
+ PointOut, OverlayType
+ >::apply(*it, Policy::apply(*it, segment), oit);
+ }
+
+ return oit;
+ }
+};
+
+
+// difference/intersection of multipoint-linear
+template
+<
+ typename MultiPoint,
+ typename Linear,
+ typename PointOut,
+ overlay_type OverlayType,
+ typename Policy
+>
+class multipoint_linear_point
+{
+private:
+ // structs for partition -- start
+ struct expand_box
+ {
+ template <typename Box, typename Geometry>
+ static inline void apply(Box& total, Geometry const& geometry)
+ {
+ geometry::expand(total, geometry::return_envelope<Box>(geometry));
+ }
+
+ };
+
+ struct overlaps_box
+ {
+ template <typename Box, typename Geometry>
+ static inline bool apply(Box const& box, Geometry const& geometry)
+ {
+ return ! geometry::disjoint(geometry, box);
+ }
+ };
+
+ template <typename OutputIterator>
+ class item_visitor_type
+ {
+ public:
+ item_visitor_type(OutputIterator& oit) : m_oit(oit) {}
+
+ template <typename Item1, typename Item2>
+ inline void apply(Item1 const& item1, Item2 const& item2)
+ {
+ action_selector_pl_l
+ <
+ PointOut, overlay_intersection
+ >::apply(item1, Policy::apply(item1, item2), m_oit);
+ }
+
+ private:
+ OutputIterator& m_oit;
+ };
+ // structs for partition -- end
+
+ class segment_range
+ {
+ public:
+ typedef geometry::segment_iterator<Linear const> const_iterator;
+ typedef const_iterator iterator;
+
+ segment_range(Linear const& linear)
+ : m_linear(linear)
+ {}
+
+ const_iterator begin() const
+ {
+ return geometry::segments_begin(m_linear);
+ }
+
+ const_iterator end() const
+ {
+ return geometry::segments_end(m_linear);
+ }
+
+ private:
+ Linear const& m_linear;
+ };
+
+ template <typename OutputIterator>
+ static inline OutputIterator get_common_points(MultiPoint const& multipoint,
+ Linear const& linear,
+ OutputIterator oit)
+ {
+ item_visitor_type<OutputIterator> item_visitor(oit);
+
+ segment_range rng(linear);
+
+ geometry::partition
+ <
+ geometry::model::box
+ <
+ typename boost::range_value<MultiPoint>::type
+ >,
+ expand_box,
+ overlaps_box
+ >::apply(multipoint, rng, item_visitor);
+
+ return oit;
+ }
+
+public:
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(MultiPoint const& multipoint,
+ Linear const& linear,
+ RobustPolicy const& robust_policy,
+ OutputIterator oit,
+ Strategy const& strategy)
+ {
+ typedef std::vector
+ <
+ typename boost::range_value<MultiPoint>::type
+ > point_vector_type;
+
+ point_vector_type common_points;
+
+ // compute the common points
+ get_common_points(multipoint, linear,
+ std::back_inserter(common_points));
+
+ return multipoint_multipoint_point
+ <
+ MultiPoint, point_vector_type, PointOut, OverlayType
+ >::apply(multipoint, common_points, robust_policy, oit, strategy);
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace detail_dispatch { namespace overlay
+{
+
+// dispatch struct for pointlike-linear difference/intersection computation
+template
+<
+ typename PointLike,
+ typename Linear,
+ typename PointOut,
+ overlay_type OverlayType,
+ typename Tag1,
+ typename Tag2
+>
+struct pointlike_linear_point
+ : not_implemented<PointLike, Linear, PointOut>
+{};
+
+
+template
+<
+ typename Point,
+ typename Linear,
+ typename PointOut,
+ overlay_type OverlayType
+>
+struct pointlike_linear_point
+ <
+ Point, Linear, PointOut, OverlayType, point_tag, linear_tag
+ > : detail::overlay::point_linear_point
+ <
+ Point, Linear, PointOut, OverlayType,
+ detail::not_<detail::disjoint::reverse_covered_by>
+ >
+{};
+
+
+template
+<
+ typename Point,
+ typename Segment,
+ typename PointOut,
+ overlay_type OverlayType
+>
+struct pointlike_linear_point
+ <
+ Point, Segment, PointOut, OverlayType, point_tag, segment_tag
+ > : detail::overlay::point_linear_point
+ <
+ Point, Segment, PointOut, OverlayType,
+ detail::not_<detail::disjoint::reverse_covered_by>
+ >
+{};
+
+
+template
+<
+ typename MultiPoint,
+ typename Linear,
+ typename PointOut,
+ overlay_type OverlayType
+>
+struct pointlike_linear_point
+ <
+ MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag
+ > : detail::overlay::multipoint_linear_point
+ <
+ MultiPoint, Linear, PointOut, OverlayType,
+ detail::not_<detail::disjoint::reverse_covered_by>
+ >
+{};
+
+
+template
+<
+ typename MultiPoint,
+ typename Segment,
+ typename PointOut,
+ overlay_type OverlayType
+>
+struct pointlike_linear_point
+ <
+ MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag
+ > : detail::overlay::multipoint_segment_point
+ <
+ MultiPoint, Segment, PointOut, OverlayType,
+ detail::not_<detail::disjoint::reverse_covered_by>
+ >
+{};
+
+
+}} // namespace detail_dispatch::overlay
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
index 0af062d271..438a377876 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -14,9 +14,9 @@
#include <algorithm>
#include <vector>
-#include <boost/assert.hpp>
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -182,7 +182,7 @@ struct multipoint_point_point
OutputIterator oit,
Strategy const&)
{
- BOOST_ASSERT( OverlayType == overlay_difference );
+ BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference );
for (typename boost::range_iterator<MultiPoint const>::type
it = boost::begin(multipoint);
@@ -264,7 +264,7 @@ struct multipoint_multipoint_point
>::apply(multipoint2, multipoint1, robust_policy, oit, strategy);
}
- std::vector<typename point_type<MultiPoint2>::type>
+ std::vector<typename boost::range_value<MultiPoint2>::type>
points2(boost::begin(multipoint2), boost::end(multipoint2));
std::sort(points2.begin(), points2.end(), detail::relate::less());
diff --git a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
index b469052c84..0f2da67b62 100644
--- a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
+++ b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
@@ -29,6 +29,8 @@ struct ring_properties
typedef Point point_type;
typedef typename default_area_result<Point>::type area_type;
+ bool valid;
+
// Filled by "select_rings"
Point point;
area_type area;
@@ -43,7 +45,8 @@ struct ring_properties
std::vector<ring_identifier> children;
inline ring_properties()
- : area(area_type())
+ : valid(false)
+ , area(area_type())
, reversed(false)
, discarded(false)
, parent_area(-1)
@@ -59,7 +62,7 @@ struct ring_properties
// We should take a point somewhere in the middle of the ring,
// to avoid taking a point on a (self)tangency,
// in cases where multiple points come together
- geometry::point_on_border(this->point, ring_or_box, true);
+ valid = geometry::point_on_border(this->point, ring_or_box, true);
}
inline area_type get_area() const
diff --git a/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
index 516ec349e8..e77a163dd5 100644
--- a/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
+++ b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
@@ -19,7 +19,7 @@
#endif
-#include <boost/geometry/algorithms/detail/signed_index_type.hpp>
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
namespace boost { namespace geometry
@@ -40,10 +40,10 @@ struct segment_identifier
, segment_index(-1)
{}
- inline segment_identifier(signed_index_type src,
- signed_index_type mul,
- signed_index_type rin,
- signed_index_type seg)
+ inline segment_identifier(signed_size_type src,
+ signed_size_type mul,
+ signed_size_type rin,
+ signed_size_type seg)
: source_index(src)
, multi_index(mul)
, ring_index(rin)
@@ -81,10 +81,10 @@ struct segment_identifier
}
#endif
- signed_index_type source_index;
- signed_index_type multi_index;
- signed_index_type ring_index;
- signed_index_type segment_index;
+ signed_size_type source_index;
+ signed_size_type multi_index;
+ signed_size_type ring_index;
+ signed_size_type segment_index;
};
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
index b1f984ffe1..a74cb83f77 100644
--- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
@@ -12,6 +12,7 @@
#include <cstddef>
+#include <boost/mpl/vector_c.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/access.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
index 59d2ba703e..803a164711 100644
--- a/boost/geometry/algorithms/detail/overlay/traverse.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -18,6 +18,7 @@
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -116,8 +117,8 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2,
return false;
}
- BOOST_ASSERT(info.enriched.travels_to_vertex_index >= 0);
- BOOST_ASSERT(info.enriched.travels_to_ip_index >= 0);
+ BOOST_GEOMETRY_ASSERT(info.enriched.travels_to_vertex_index >= 0);
+ BOOST_GEOMETRY_ASSERT(info.enriched.travels_to_ip_index >= 0);
if (info.seg_id.source_index == 0)
{
@@ -150,8 +151,8 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2,
inline bool select_source(operation_type operation,
- signed_index_type source1,
- signed_index_type source2)
+ signed_size_type source1,
+ signed_size_type source2)
{
return (operation == operation_intersection && source1 != source2)
|| (operation == operation_union && source1 == source2)
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
index 25a34ba2ec..8b19add479 100644
--- a/boost/geometry/algorithms/detail/partition.hpp
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2011-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
+
+// 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
@@ -9,10 +14,13 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
+#include <cstddef>
#include <vector>
-#include <boost/range/algorithm/copy.hpp>
-#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/range.hpp>
+#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+
namespace boost { namespace geometry
{
@@ -20,8 +28,6 @@ namespace boost { namespace geometry
namespace detail { namespace partition
{
-typedef std::vector<std::size_t> index_vector_type;
-
template <int Dimension, typename Box>
inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
{
@@ -38,31 +44,26 @@ inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
geometry::set<min_corner, Dimension>(upper_box, mid);
}
-// Divide collection into three subsets: lower, upper and oversized
+// Divide forward_range into three subsets: lower, upper and oversized
// (not-fitting)
// (lower == left or bottom, upper == right or top)
-template <typename OverlapsPolicy, typename InputCollection, typename Box>
+template <typename OverlapsPolicy, typename Box, typename IteratorVector>
inline void divide_into_subsets(Box const& lower_box,
Box const& upper_box,
- InputCollection const& collection,
- index_vector_type const& input,
- index_vector_type& lower,
- index_vector_type& upper,
- index_vector_type& exceeding)
+ IteratorVector const& input,
+ IteratorVector& lower,
+ IteratorVector& upper,
+ IteratorVector& exceeding)
{
- typedef boost::range_iterator
+ typedef typename boost::range_iterator
<
- index_vector_type const
- >::type index_iterator_type;
+ IteratorVector const
+ >::type it_type;
- for(index_iterator_type it = boost::begin(input);
- it != boost::end(input);
- ++it)
+ for(it_type it = boost::begin(input); it != boost::end(input); ++it)
{
- bool const lower_overlapping = OverlapsPolicy::apply(lower_box,
- collection[*it]);
- bool const upper_overlapping = OverlapsPolicy::apply(upper_box,
- collection[*it]);
+ bool const lower_overlapping = OverlapsPolicy::apply(lower_box, **it);
+ bool const upper_overlapping = OverlapsPolicy::apply(upper_box, **it);
if (lower_overlapping && upper_overlapping)
{
@@ -84,99 +85,109 @@ inline void divide_into_subsets(Box const& lower_box,
}
}
-template <typename ExpandPolicy, typename Box, typename InputCollection>
-inline void expand_with_elements(Box& total,
- InputCollection const& collection,
- index_vector_type const& input)
+template
+<
+ typename ExpandPolicy,
+ typename Box,
+ typename IteratorVector
+>
+inline void expand_with_elements(Box& total, IteratorVector const& input)
{
- typedef boost::range_iterator<index_vector_type const>::type it_type;
+ 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, collection[*it]);
+ ExpandPolicy::apply(total, **it);
}
}
-// Match collection with itself
-template <typename InputCollection, typename Policy>
-inline void handle_one(InputCollection const& collection,
- index_vector_type const& input,
- Policy& policy)
+// Match forward_range with itself
+template <typename Policy, typename IteratorVector>
+inline void handle_one(IteratorVector const& input, Policy& policy)
{
if (boost::size(input) == 0)
{
return;
}
- typedef boost::range_iterator<index_vector_type const>::type
- index_iterator_type;
+ typedef typename boost::range_iterator<IteratorVector const>::type it_type;
// Quadratic behaviour at lowest level (lowest quad, or all exceeding)
- for(index_iterator_type it1 = boost::begin(input);
- it1 != boost::end(input);
- ++it1)
+ for (it_type it1 = boost::begin(input); it1 != boost::end(input); ++it1)
{
- index_iterator_type it2 = it1;
- for(++it2; it2 != boost::end(input); ++it2)
+ it_type it2 = it1;
+ for (++it2; it2 != boost::end(input); ++it2)
{
- policy.apply(collection[*it1], collection[*it2]);
+ policy.apply(**it1, **it2);
}
}
}
-// Match collection 1 with collection 2
+// Match forward range 1 with forward range 2
template
<
- typename InputCollection1,
- typename InputCollection2,
- typename Policy
+ typename Policy,
+ typename IteratorVector1,
+ typename IteratorVector2
>
-inline void handle_two(
- InputCollection1 const& collection1, index_vector_type const& input1,
- InputCollection2 const& collection2, index_vector_type const& input2,
+inline void handle_two(IteratorVector1 const& input1,
+ IteratorVector2 const& input2,
Policy& policy)
{
+ typedef typename boost::range_iterator
+ <
+ IteratorVector1 const
+ >::type iterator_type1;
+
+ typedef typename boost::range_iterator
+ <
+ IteratorVector2 const
+ >::type iterator_type2;
+
if (boost::size(input1) == 0 || boost::size(input2) == 0)
{
return;
}
- typedef boost::range_iterator
- <
- index_vector_type const
- >::type index_iterator_type;
-
- for(index_iterator_type it1 = boost::begin(input1);
+ for(iterator_type1 it1 = boost::begin(input1);
it1 != boost::end(input1);
++it1)
{
- for(index_iterator_type it2 = boost::begin(input2);
+ for(iterator_type2 it2 = boost::begin(input2);
it2 != boost::end(input2);
++it2)
{
- policy.apply(collection1[*it1], collection2[*it2]);
+ policy.apply(**it1, **it2);
}
}
}
-inline bool recurse_ok(index_vector_type const& input,
+template <typename IteratorVector>
+inline bool recurse_ok(IteratorVector const& input,
std::size_t min_elements, std::size_t level)
{
return boost::size(input) >= min_elements
&& level < 100;
}
-inline bool recurse_ok(index_vector_type const& input1,
- index_vector_type const& input2,
+template <typename IteratorVector1, typename IteratorVector2>
+inline bool recurse_ok(IteratorVector1 const& input1,
+ IteratorVector2 const& input2,
std::size_t min_elements, std::size_t level)
{
return boost::size(input1) >= min_elements
&& recurse_ok(input2, min_elements, level);
}
-inline bool recurse_ok(index_vector_type const& input1,
- index_vector_type const& input2,
- index_vector_type const& input3,
+template
+<
+ typename IteratorVector1,
+ typename IteratorVector2,
+ typename IteratorVector3
+>
+inline bool recurse_ok(IteratorVector1 const& input1,
+ IteratorVector2 const& input2,
+ IteratorVector3 const& input3,
std::size_t min_elements, std::size_t level)
{
return boost::size(input1) >= min_elements
@@ -193,7 +204,7 @@ template
typename ExpandPolicy2,
typename VisitBoxPolicy
>
-class partition_two_collections;
+class partition_two_ranges;
template
@@ -204,79 +215,71 @@ template
typename ExpandPolicy,
typename VisitBoxPolicy
>
-class partition_one_collection
+class partition_one_range
{
- typedef std::vector<std::size_t> index_vector_type;
-
- template <typename InputCollection>
- static inline Box get_new_box(InputCollection const& collection,
- index_vector_type const& input)
+ template <typename IteratorVector>
+ static inline Box get_new_box(IteratorVector const& input)
{
Box box;
geometry::assign_inverse(box);
- expand_with_elements<ExpandPolicy>(box, collection, input);
+ expand_with_elements<ExpandPolicy>(box, input);
return box;
}
- template <typename InputCollection, typename Policy>
+ template <typename Policy, typename IteratorVector>
static inline void next_level(Box const& box,
- InputCollection const& collection,
- index_vector_type const& input,
+ IteratorVector const& input,
std::size_t level, std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
if (recurse_ok(input, min_elements, level))
{
- partition_one_collection
+ partition_one_range
<
1 - Dimension,
Box,
OverlapsPolicy,
ExpandPolicy,
VisitBoxPolicy
- >::apply(box, collection, input,
- level + 1, min_elements, policy, box_policy);
+ >::apply(box, input, level + 1, min_elements, policy, box_policy);
}
else
{
- handle_one(collection, input, policy);
+ handle_one(input, policy);
}
}
- // Function to switch to two collections if there are geometries exceeding
- // the separation line
- template <typename InputCollection, typename Policy>
+ // Function to switch to two forward ranges if there are
+ // geometries exceeding the separation line
+ template <typename Policy, typename IteratorVector>
static inline void next_level2(Box const& box,
- InputCollection const& collection,
- index_vector_type const& input1,
- index_vector_type const& input2,
+ IteratorVector const& input1,
+ IteratorVector const& input2,
std::size_t level, std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
-
if (recurse_ok(input1, input2, min_elements, level))
{
- partition_two_collections
+ partition_two_ranges
<
1 - Dimension,
Box,
OverlapsPolicy, OverlapsPolicy,
ExpandPolicy, ExpandPolicy,
VisitBoxPolicy
- >::apply(box, collection, input1, collection, input2,
- level + 1, min_elements, policy, box_policy);
+ >::apply(box, input1, input2, level + 1, min_elements,
+ policy, box_policy);
}
else
{
- handle_two(collection, input1, collection, input2, policy);
+ handle_two(input1, input2, policy);
}
}
public :
- template <typename InputCollection, typename Policy>
+ template <typename Policy, typename IteratorVector>
static inline void apply(Box const& box,
- InputCollection const& collection,
- index_vector_type const& input,
+ IteratorVector const& input,
std::size_t level,
std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
@@ -286,33 +289,31 @@ public :
Box lower_box, upper_box;
divide_box<Dimension>(box, lower_box, upper_box);
- index_vector_type lower, upper, exceeding;
- divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection,
+ IteratorVector lower, upper, exceeding;
+ divide_into_subsets<OverlapsPolicy>(lower_box, upper_box,
input, lower, upper, exceeding);
if (boost::size(exceeding) > 0)
{
// Get the box of exceeding-only
- Box exceeding_box = get_new_box(collection, exceeding);
+ Box exceeding_box = get_new_box(exceeding);
// Recursively do exceeding elements only, in next dimension they
// will probably be less exceeding within the new box
- next_level(exceeding_box, collection, exceeding, level,
- min_elements, policy, box_policy);
-
- // Switch to two collections, combine exceeding with lower resp upper
- // but not lower/lower, upper/upper
- next_level2(exceeding_box, collection, exceeding, lower, level,
- min_elements, policy, box_policy);
- next_level2(exceeding_box, collection, exceeding, upper, level,
- min_elements, policy, box_policy);
+ next_level(exceeding_box, exceeding, level, min_elements,
+ 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);
+ next_level2(exceeding_box, exceeding, upper, level, min_elements,
+ policy, box_policy);
}
// Recursively call operation both parts
- next_level(lower_box, collection, lower, level, min_elements,
- policy, box_policy);
- next_level(upper_box, collection, upper, level, min_elements,
- policy, box_policy);
+ next_level(lower_box, lower, level, min_elements, policy, box_policy);
+ next_level(upper_box, upper, level, min_elements, policy, box_policy);
}
};
@@ -326,25 +327,21 @@ template
typename ExpandPolicy2,
typename VisitBoxPolicy
>
-class partition_two_collections
+class partition_two_ranges
{
- typedef std::vector<std::size_t> index_vector_type;
-
template
<
- typename InputCollection1,
- typename InputCollection2,
- typename Policy
+ typename Policy,
+ typename IteratorVector1,
+ typename IteratorVector2
>
static inline void next_level(Box const& box,
- InputCollection1 const& collection1,
- index_vector_type const& input1,
- InputCollection2 const& collection2,
- index_vector_type const& input2,
+ IteratorVector1 const& input1,
+ IteratorVector2 const& input2,
std::size_t level, std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
- partition_two_collections
+ partition_two_ranges
<
1 - Dimension,
Box,
@@ -353,50 +350,38 @@ class partition_two_collections
ExpandPolicy1,
ExpandPolicy2,
VisitBoxPolicy
- >::apply(box, collection1, input1, collection2, input2,
- level + 1, min_elements,
- policy, box_policy);
+ >::apply(box, input1, input2, level + 1, min_elements,
+ policy, box_policy);
}
- template
- <
- typename ExpandPolicy,
- typename InputCollection
- >
- static inline Box get_new_box(InputCollection const& collection,
- index_vector_type const& input)
+ template <typename ExpandPolicy, typename IteratorVector>
+ static inline Box get_new_box(IteratorVector const& input)
{
Box box;
geometry::assign_inverse(box);
- expand_with_elements<ExpandPolicy>(box, collection, input);
+ expand_with_elements<ExpandPolicy>(box, input);
return box;
}
- template
- <
- typename InputCollection1,
- typename InputCollection2
- >
- static inline Box get_new_box(InputCollection1 const& collection1,
- index_vector_type const& input1,
- InputCollection2 const& collection2,
- index_vector_type const& input2)
+ template <typename IteratorVector1, typename IteratorVector2>
+ static inline Box get_new_box(IteratorVector1 const& input1,
+ IteratorVector2 const& input2)
{
- Box box = get_new_box<ExpandPolicy1>(collection1, input1);
- expand_with_elements<ExpandPolicy2>(box, collection2, input2);
+ Box box = get_new_box<ExpandPolicy1>(input1);
+ expand_with_elements<ExpandPolicy2>(box, input2);
return box;
}
public :
template
<
- typename InputCollection1,
- typename InputCollection2,
- typename Policy
+ typename Policy,
+ typename IteratorVector1,
+ typename IteratorVector2
>
static inline void apply(Box const& box,
- InputCollection1 const& collection1, index_vector_type const& input1,
- InputCollection2 const& collection2, index_vector_type const& input2,
+ IteratorVector1 const& input1,
+ IteratorVector2 const& input2,
std::size_t level,
std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
@@ -406,11 +391,11 @@ public :
Box lower_box, upper_box;
divide_box<Dimension>(box, lower_box, upper_box);
- index_vector_type lower1, upper1, exceeding1;
- index_vector_type lower2, upper2, exceeding2;
- divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box, collection1,
+ 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, collection2,
+ divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box,
input2, lower2, upper2, exceeding2);
if (boost::size(exceeding1) > 0)
@@ -419,35 +404,31 @@ public :
if (recurse_ok(exceeding1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box(collection1, exceeding1,
- collection2, exceeding2);
- next_level(exceeding_box, collection1, exceeding1,
- collection2, exceeding2, level,
- min_elements, policy, box_policy);
+ Box exceeding_box = get_new_box(exceeding1, exceeding2);
+ next_level(exceeding_box, exceeding1, exceeding2, level,
+ min_elements, policy, box_policy);
}
else
{
- handle_two(collection1, exceeding1, collection2, exceeding2,
- policy);
+ handle_two(exceeding1, exceeding2, policy);
}
// All exceeding from 1 with lower and upper of 2:
- // (Check sizes of all three collections to avoid recurse into
+ // (Check sizes of all three forward ranges to avoid recurse into
// the same combinations again and again)
if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
{
- Box exceeding_box
- = get_new_box<ExpandPolicy1>(collection1, exceeding1);
- next_level(exceeding_box, collection1, exceeding1,
- collection2, lower2, level, min_elements, policy, box_policy);
- next_level(exceeding_box, collection1, exceeding1,
- collection2, upper2, level, min_elements, policy, box_policy);
+ Box exceeding_box = get_new_box<ExpandPolicy1>(exceeding1);
+ next_level(exceeding_box, exceeding1, lower2, level,
+ min_elements, policy, box_policy);
+ next_level(exceeding_box, exceeding1, upper2, level,
+ min_elements, policy, box_policy);
}
else
{
- handle_two(collection1, exceeding1, collection2, lower2, policy);
- handle_two(collection1, exceeding1, collection2, upper2, policy);
+ handle_two(exceeding1, lower2, policy);
+ handle_two(exceeding1, upper2, policy);
}
}
@@ -456,37 +437,36 @@ 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>(collection2, exceeding2);
- next_level(exceeding_box, collection1, lower1,
- collection2, exceeding2, level, min_elements, policy, box_policy);
- next_level(exceeding_box, collection1, upper1,
- collection2, exceeding2, level, min_elements, policy, box_policy);
+ Box exceeding_box = get_new_box<ExpandPolicy2>(exceeding2);
+ next_level(exceeding_box, lower1, exceeding2, level,
+ min_elements, policy, box_policy);
+ next_level(exceeding_box, upper1, exceeding2, level,
+ min_elements, policy, box_policy);
}
else
{
- handle_two(collection1, lower1, collection2, exceeding2, policy);
- handle_two(collection1, upper1, collection2, exceeding2, policy);
+ handle_two(lower1, exceeding2, policy);
+ handle_two(upper1, exceeding2, policy);
}
}
if (recurse_ok(lower1, lower2, min_elements, level))
{
- next_level(lower_box, collection1, lower1, collection2, lower2, level,
- min_elements, policy, box_policy);
+ next_level(lower_box, lower1, lower2, level,
+ min_elements, policy, box_policy);
}
else
{
- handle_two(collection1, lower1, collection2, lower2, policy);
+ handle_two(lower1, lower2, policy);
}
if (recurse_ok(upper1, upper2, min_elements, level))
{
- next_level(upper_box, collection1, upper1, collection2, upper2, level,
- min_elements, policy, box_policy);
+ next_level(upper_box, upper1, upper2, level,
+ min_elements, policy, box_policy);
}
else
{
- handle_two(collection1, upper1, collection2, upper2, policy);
+ handle_two(upper1, upper2, policy);
}
}
};
@@ -523,63 +503,67 @@ template
>
class partition
{
- typedef std::vector<std::size_t> index_vector_type;
-
- template <typename ExpandPolicy, typename IncludePolicy, typename InputCollection>
- static inline void expand_to_collection(InputCollection const& collection,
- Box& total, index_vector_type& index_vector)
+ template
+ <
+ typename ExpandPolicy,
+ typename IncludePolicy,
+ typename ForwardRange,
+ typename IteratorVector
+ >
+ static inline void expand_to_range(ForwardRange const& forward_range,
+ Box& total, IteratorVector& iterator_vector)
{
- std::size_t index = 0;
- for(typename boost::range_iterator<InputCollection const>::type it
- = boost::begin(collection);
- it != boost::end(collection);
- ++it, ++index)
+ 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);
- index_vector.push_back(index);
+ iterator_vector.push_back(it);
}
}
}
public :
- template <typename InputCollection, typename VisitPolicy>
- static inline void apply(InputCollection const& collection,
+ template <typename ForwardRange, typename VisitPolicy>
+ static inline void apply(ForwardRange const& forward_range,
VisitPolicy& visitor,
std::size_t min_elements = 16,
VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()
)
{
- if (std::size_t(boost::size(collection)) > min_elements)
+ typedef typename boost::range_iterator
+ <
+ ForwardRange const
+ >::type iterator_type;
+
+ if (std::size_t(boost::size(forward_range)) > min_elements)
{
- index_vector_type index_vector;
+ std::vector<iterator_type> iterator_vector;
Box total;
assign_inverse(total);
- expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection,
- total, index_vector);
+ expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range,
+ total, iterator_vector);
- detail::partition::partition_one_collection
+ detail::partition::partition_one_range
<
0, Box,
OverlapsPolicy1,
ExpandPolicy1,
VisitBoxPolicy
- >::apply(total, collection, index_vector, 0, min_elements,
- visitor, box_visitor);
+ >::apply(total, iterator_vector, 0, min_elements,
+ visitor, box_visitor);
}
else
{
- typedef typename boost::range_iterator
- <
- InputCollection const
- >::type iterator_type;
- for(iterator_type it1 = boost::begin(collection);
- it1 != boost::end(collection);
+ for(iterator_type it1 = boost::begin(forward_range);
+ it1 != boost::end(forward_range);
++it1)
{
iterator_type it2 = it1;
- for(++it2; it2 != boost::end(collection); ++it2)
+ for(++it2; it2 != boost::end(forward_range); ++it2)
{
visitor.apply(*it1, *it2);
}
@@ -589,53 +573,55 @@ public :
template
<
- typename InputCollection1,
- typename InputCollection2,
+ typename ForwardRange1,
+ typename ForwardRange2,
typename VisitPolicy
>
- static inline void apply(InputCollection1 const& collection1,
- InputCollection2 const& collection2,
+ 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()
+ VisitBoxPolicy box_visitor
+ = detail::partition::visit_no_policy()
)
{
- if (std::size_t(boost::size(collection1)) > min_elements
- && std::size_t(boost::size(collection2)) > min_elements)
+ typedef typename boost::range_iterator
+ <
+ ForwardRange1 const
+ >::type iterator_type1;
+
+ typedef typename boost::range_iterator
+ <
+ ForwardRange2 const
+ >::type iterator_type2;
+
+ if (std::size_t(boost::size(forward_range1)) > min_elements
+ && std::size_t(boost::size(forward_range2)) > min_elements)
{
- index_vector_type index_vector1, index_vector2;
+ std::vector<iterator_type1> iterator_vector1;
+ std::vector<iterator_type2> iterator_vector2;
Box total;
assign_inverse(total);
- expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection1,
- total, index_vector1);
- expand_to_collection<ExpandPolicy2, IncludePolicy2>(collection2,
- total, index_vector2);
+ expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range1,
+ total, iterator_vector1);
+ expand_to_range<ExpandPolicy2, IncludePolicy2>(forward_range2,
+ total, iterator_vector2);
- detail::partition::partition_two_collections
+ detail::partition::partition_two_ranges
<
0, Box, OverlapsPolicy1, OverlapsPolicy2,
ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy
- >::apply(total,
- collection1, index_vector1,
- collection2, index_vector2,
- 0, min_elements, visitor, box_visitor);
+ >::apply(total, iterator_vector1, iterator_vector2,
+ 0, min_elements, visitor, box_visitor);
}
else
{
- typedef typename boost::range_iterator
- <
- InputCollection1 const
- >::type iterator_type1;
- typedef typename boost::range_iterator
- <
- InputCollection2 const
- >::type iterator_type2;
- for(iterator_type1 it1 = boost::begin(collection1);
- it1 != boost::end(collection1);
+ for(iterator_type1 it1 = boost::begin(forward_range1);
+ it1 != boost::end(forward_range1);
++it1)
{
- for(iterator_type2 it2 = boost::begin(collection2);
- it2 != boost::end(collection2);
+ for(iterator_type2 it2 = boost::begin(forward_range2);
+ it2 != boost::end(forward_range2);
++it2)
{
visitor.apply(*it1, *it2);
diff --git a/boost/geometry/algorithms/detail/recalculate.hpp b/boost/geometry/algorithms/detail/recalculate.hpp
index 2c3ea7413b..056f7c6e1d 100644
--- a/boost/geometry/algorithms/detail/recalculate.hpp
+++ b/boost/geometry/algorithms/detail/recalculate.hpp
@@ -21,6 +21,7 @@
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/conversion/cast.hpp>
+#include <boost/range.hpp>
#include <boost/type_traits.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
index 2859841de4..cc9c1b67ca 100644
--- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
@@ -88,7 +88,7 @@ public:
// TODO: This is O(N)
// Run in a loop O(NM) - optimize!
int const pig = detail::within::point_in_geometry(pt, m_other_areal);
- //BOOST_ASSERT( pig != 0 );
+ //BOOST_GEOMETRY_ASSERT( pig != 0 );
// inside
if ( pig > 0 )
@@ -104,9 +104,9 @@ public:
// Check if any interior ring is outside
ring_identifier ring_id(0, -1, 0);
- int const irings_count = boost::numeric_cast<int>(
- geometry::num_interior_rings(areal) );
- for ( ; ring_id.ring_index < irings_count ; ++ring_id.ring_index )
+ std::size_t const irings_count = geometry::num_interior_rings(areal);
+ for ( ; static_cast<std::size_t>(ring_id.ring_index) < irings_count ;
+ ++ring_id.ring_index )
{
typename detail::sub_range_return_type<Areal const>::type
range_ref = detail::sub_range(areal, ring_id);
@@ -140,9 +140,9 @@ public:
// Check if any interior ring is inside
ring_identifier ring_id(0, -1, 0);
- int const irings_count = boost::numeric_cast<int>(
- geometry::num_interior_rings(areal) );
- for ( ; ring_id.ring_index < irings_count ; ++ring_id.ring_index )
+ std::size_t const irings_count = geometry::num_interior_rings(areal);
+ for ( ; static_cast<std::size_t>(ring_id.ring_index) < irings_count ;
+ ++ring_id.ring_index )
{
typename detail::sub_range_return_type<Areal const>::type
range_ref = detail::sub_range(areal, ring_id);
@@ -405,7 +405,7 @@ struct areal_areal
typename TurnIt>
void apply(Result & result, TurnIt it)
{
- //BOOST_ASSERT( it != last );
+ //BOOST_GEOMETRY_ASSERT( it != last );
overlay::operation_type const op = it->operations[op_id].operation;
@@ -498,7 +498,7 @@ struct areal_areal
template <typename Result>
void apply(Result & result)
{
- //BOOST_ASSERT( first != last );
+ //BOOST_GEOMETRY_ASSERT( first != last );
if ( m_exit_detected /*m_previous_operation == overlay::operation_union*/ )
{
@@ -618,7 +618,7 @@ struct areal_areal
// O(N) - running it in a loop gives O(NM)
int const pig = detail::within::point_in_geometry(range::front(range_ref), other_geometry);
- //BOOST_ASSERT(pig != 0);
+ //BOOST_GEOMETRY_ASSERT(pig != 0);
if ( pig > 0 )
{
update<interior, interior, '2', transpose_result>(m_result);
@@ -793,8 +793,8 @@ struct areal_areal
{
segment_identifier const& seg_id = turn.operations[OpId].seg_id;
- signed_index_type
- count = boost::numeric_cast<signed_index_type>(
+ signed_size_type
+ count = boost::numeric_cast<signed_size_type>(
geometry::num_interior_rings(
detail::single_geometry(analyser.geometry, seg_id)));
@@ -804,8 +804,8 @@ struct areal_areal
template <typename Analyser, typename Turn>
static inline void for_no_turns_rings(Analyser & analyser,
Turn const& turn,
- signed_index_type first,
- signed_index_type last)
+ signed_size_type first,
+ signed_size_type last)
{
segment_identifier seg_id = turn.operations[OpId].seg_id;
diff --git a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
index f98c3e9b82..9de1bacb7d 100644
--- a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
+++ b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
@@ -47,7 +47,7 @@ public:
boost::ignore_unused_variable_warning(pt);
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
// may give false positives for INT
- BOOST_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
+ BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
&& detail::equals::equals_point_point(pt, range::front(geometry))
|| (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
&& detail::equals::equals_point_point(pt, range::back(geometry)) );
diff --git a/boost/geometry/algorithms/detail/relate/de9im.hpp b/boost/geometry/algorithms/detail/relate/de9im.hpp
new file mode 100644
index 0000000000..713a3fc8f0
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/de9im.hpp
@@ -0,0 +1,439 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP
+
+#include <boost/mpl/is_sequence.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/vector_c.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#include <boost/geometry/algorithms/detail/relate/result.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/core/tag.hpp>
+
+// TEMP - move this header to geometry/detail
+#include <boost/geometry/index/detail/tuples.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace de9im
+{
+
+/*!
+\brief DE-9IM model intersection matrix.
+\ingroup de9im
+\details This matrix can be used to express spatial relations as defined in
+ Dimensionally Extended 9-Intersection Model.
+
+\qbk{[heading See also]}
+\qbk{* [link geometry.reference.algorithms.relation relation]}
+ */
+class matrix
+ : public detail::relate::matrix<3, 3>
+{
+#ifdef DOXYGEN_INVOKED
+public:
+ /*!
+ \brief Initializes all of the matrix elements to F
+ */
+ matrix();
+ /*!
+ \brief Subscript operator
+ \param index The index of the element
+ \return The element
+ */
+ char operator[](std::size_t index) const;
+ /*!
+ \brief Returns the iterator to the first element
+ \return const RandomAccessIterator
+ */
+ const_iterator begin() const;
+ /*!
+ \brief Returns the iterator past the last element
+ \return const RandomAccessIterator
+ */
+ const_iterator end() const;
+ /*!
+ \brief Returns the number of elements
+ \return 9
+ */
+ static std::size_t size();
+ /*!
+ \brief Returns raw pointer to elements
+ \return const pointer to array of elements
+ */
+ inline const char * data() const;
+ /*!
+ \brief Returns std::string containing elements
+ \return string containing elements
+ */
+ inline std::string str() const;
+#endif
+};
+
+/*!
+\brief DE-9IM model intersection mask.
+\ingroup de9im
+\details This mask can be used to check spatial relations as defined in
+ Dimensionally Extended 9-Intersection Model.
+
+\qbk{[heading See also]}
+\qbk{* [link geometry.reference.algorithms.relate relate]}
+ */
+class mask
+ : public detail::relate::mask<3, 3>
+{
+ typedef detail::relate::mask<3, 3> base_type;
+
+public:
+ /*!
+ \brief The constructor.
+ \param code The mask pattern.
+ */
+ inline explicit mask(const char* code)
+ : base_type(code)
+ {}
+
+ /*!
+ \brief The constructor.
+ \param code The mask pattern.
+ */
+ inline explicit mask(std::string const& code)
+ : base_type(code.c_str(), code.size())
+ {}
+};
+
+// static_mask
+
+/*!
+\brief DE-9IM model intersection mask (static version).
+\ingroup de9im
+\details This mask can be used to check spatial relations as defined in
+ Dimensionally Extended 9-Intersection Model.
+\tparam II Interior/Interior intersection mask element
+\tparam IB Interior/Boundary intersection mask element
+\tparam IE Interior/Exterior intersection mask element
+\tparam BI Boundary/Interior intersection mask element
+\tparam BB Boundary/Boundary intersection mask element
+\tparam BE Boundary/Exterior intersection mask element
+\tparam EI Exterior/Interior intersection mask element
+\tparam EB Exterior/Boundary intersection mask element
+\tparam EE Exterior/Exterior intersection mask element
+
+\qbk{[heading See also]}
+\qbk{* [link geometry.reference.algorithms.relate relate]}
+ */
+template
+<
+ char II = '*', char IB = '*', char IE = '*',
+ char BI = '*', char BB = '*', char BE = '*',
+ char EI = '*', char EB = '*', char EE = '*'
+>
+class static_mask
+ : public detail::relate::static_mask
+ <
+ boost::mpl::vector_c
+ <
+ char, II, IB, IE, BI, BB, BE, EI, EB, EE
+ >,
+ 3, 3
+ >
+{};
+
+} // namespace de9im
+
+namespace detail { namespace de9im
+{
+
+// a small helper util for ORing static masks
+
+template
+<
+ typename Seq,
+ typename T,
+ bool IsSeq = boost::mpl::is_sequence<Seq>::value
+>
+struct push_back
+{
+ typedef typename boost::mpl::push_back
+ <
+ Seq,
+ T
+ >::type type;
+};
+
+template <typename Seq, typename T>
+struct push_back<Seq, T, false>
+{};
+
+}} // namespace detail::de9im
+
+namespace de9im
+{
+
+inline
+boost::tuples::cons
+ <
+ mask,
+ boost::tuples::cons<mask, boost::tuples::null_type>
+ >
+operator||(mask const& m1, mask const& m2)
+{
+ namespace bt = boost::tuples;
+
+ return bt::cons<mask, bt::cons<mask, bt::null_type> >
+ ( m1, bt::cons<mask, bt::null_type>(m2, bt::null_type()) );
+}
+
+template <typename Tail>
+inline
+typename index::detail::tuples::push_back
+ <
+ boost::tuples::cons<mask, Tail>,
+ mask
+ >::type
+operator||(boost::tuples::cons<mask, Tail> const& t, mask const& m)
+{
+ namespace bt = boost::tuples;
+
+ return index::detail::tuples::push_back
+ <
+ bt::cons<mask, Tail>,
+ mask
+ >::apply(t, m);
+}
+
+template
+<
+ char II1, char IB1, char IE1,
+ char BI1, char BB1, char BE1,
+ char EI1, char EB1, char EE1,
+ char II2, char IB2, char IE2,
+ char BI2, char BB2, char BE2,
+ char EI2, char EB2, char EE2
+>
+inline
+boost::mpl::vector<
+ static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,
+ static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>
+>
+operator||(static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1> const& ,
+ static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2> const& )
+{
+ return boost::mpl::vector
+ <
+ static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,
+ static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>
+ >();
+}
+
+template
+<
+ typename Seq,
+ char II, char IB, char IE,
+ char BI, char BB, char BE,
+ char EI, char EB, char EE
+>
+inline
+typename detail::de9im::push_back
+ <
+ Seq,
+ static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>
+ >::type
+operator||(Seq const& ,
+ static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> const& )
+{
+ return typename detail::de9im::push_back
+ <
+ Seq,
+ static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>
+ >::type();
+}
+
+} // namespace de9im
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace de9im
+{
+
+// PREDEFINED MASKS
+
+// TODO:
+// 1. specialize for simplified masks if available
+// e.g. for TOUCHES use 1 mask for A/A
+// 2. Think about dimensions > 2 e.g. should TOUCHES be true
+// if the interior of the Areal overlaps the boundary of the Volumetric
+// like it's true for Linear/Areal
+
+// EQUALS
+template <typename Geometry1, typename Geometry2>
+struct static_mask_equals_type
+{
+ typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia
+ //typedef geometry::de9im::static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC
+};
+
+// DISJOINT
+template <typename Geometry1, typename Geometry2>
+struct static_mask_disjoint_type
+{
+ typedef geometry::de9im::static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> type;
+};
+
+// TOUCHES - NOT P/P
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
+ std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value
+>
+struct static_mask_touches_impl
+{
+ typedef boost::mpl::vector
+ <
+ geometry::de9im::static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>,
+ geometry::de9im::static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>,
+ geometry::de9im::static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'>
+ > type;
+};
+// According to OGC, doesn't apply to P/P
+// Using the above mask the result would be always false
+template <typename Geometry1, typename Geometry2>
+struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
+ : not_implemented<typename geometry::tag<Geometry1>::type,
+ typename geometry::tag<Geometry2>::type>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_touches_type
+ : static_mask_touches_impl<Geometry1, Geometry2>
+{};
+
+// WITHIN
+template <typename Geometry1, typename Geometry2>
+struct static_mask_within_type
+{
+ typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> type;
+};
+
+// COVERED_BY (non OGC)
+template <typename Geometry1, typename Geometry2>
+struct static_mask_covered_by_type
+{
+ typedef boost::mpl::vector
+ <
+ geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>,
+ geometry::de9im::static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>,
+ geometry::de9im::static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>,
+ geometry::de9im::static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'>
+ > type;
+};
+
+// CROSSES
+// dim(G1) < dim(G2) - P/L P/A L/A
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
+ std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value,
+ bool D1LessD2 = (Dim1 < Dim2)
+>
+struct static_mask_crosses_impl
+{
+ typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type;
+};
+// TODO: I'm not sure if this one below should be available!
+// dim(G1) > dim(G2) - L/P A/P A/L
+template
+<
+ typename Geometry1, typename Geometry2, std::size_t Dim1, std::size_t Dim2
+>
+struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false>
+{
+ typedef geometry::de9im::static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type;
+};
+// dim(G1) == dim(G2) - P/P A/A
+template
+<
+ typename Geometry1, typename Geometry2, std::size_t Dim
+>
+struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false>
+ : not_implemented
+ <
+ typename geometry::tag<Geometry1>::type,
+ typename geometry::tag<Geometry2>::type
+ >
+{};
+// dim(G1) == 1 && dim(G2) == 1 - L/L
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false>
+{
+ typedef geometry::de9im::static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type;
+};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_type
+ : static_mask_crosses_impl<Geometry1, Geometry2>
+{};
+
+// OVERLAPS
+
+// dim(G1) != dim(G2) - NOT P/P, L/L, A/A
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,
+ std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value
+>
+struct static_mask_overlaps_impl
+ : not_implemented
+ <
+ typename geometry::tag<Geometry1>::type,
+ typename geometry::tag<Geometry2>::type
+ >
+{};
+// dim(G1) == D && dim(G2) == D - P/P A/A
+template <typename Geometry1, typename Geometry2, std::size_t Dim>
+struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim>
+{
+ typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
+};
+// dim(G1) == 1 && dim(G2) == 1 - L/L
+template <typename Geometry1, typename Geometry2>
+struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
+{
+ typedef geometry::de9im::static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
+};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_overlaps_type
+ : static_mask_overlaps_impl<Geometry1, Geometry2>
+{};
+
+}} // namespace detail::de9im
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP
diff --git a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
index 2c44b009e7..20122471e5 100644
--- a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
+++ b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
@@ -14,6 +14,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP
+#include <boost/geometry/core/assert.hpp>
+
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
//#include <boost/geometry/algorithms/detail/sub_range.hpp>
@@ -89,7 +91,7 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
Geometry const& geometry,
Pred & pred)
{
- BOOST_ASSERT(first != last);
+ BOOST_GEOMETRY_ASSERT(first != last);
const std::size_t count = boost::size(geometry);
boost::ignore_unused_variable_warning(count);
@@ -99,10 +101,10 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
std::vector<bool> detected_intersections(count, false);
for ( TurnIt it = first ; it != last ; ++it )
{
- signed_index_type multi_index = it->operations[OpId].seg_id.multi_index;
- BOOST_ASSERT(multi_index >= 0);
+ signed_size_type multi_index = it->operations[OpId].seg_id.multi_index;
+ BOOST_GEOMETRY_ASSERT(multi_index >= 0);
std::size_t const index = static_cast<std::size_t>(multi_index);
- BOOST_ASSERT(index < count);
+ BOOST_GEOMETRY_ASSERT(index < count);
detected_intersections[index] = true;
}
@@ -141,12 +143,12 @@ public:
{}
segment_identifier const& seg_id() const
{
- BOOST_ASSERT(sid_ptr);
+ BOOST_GEOMETRY_ASSERT(sid_ptr);
return *sid_ptr;
}
Point const& point() const
{
- BOOST_ASSERT(pt_ptr);
+ BOOST_GEOMETRY_ASSERT(pt_ptr);
return *pt_ptr;
}
@@ -300,15 +302,15 @@ public:
point_type const& get_exit_point() const
{
- BOOST_ASSERT(m_exit_operation != overlay::operation_none);
- BOOST_ASSERT(m_exit_turn_ptr);
+ BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none);
+ BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr);
return m_exit_turn_ptr->point;
}
TurnInfo const& get_exit_turn() const
{
- BOOST_ASSERT(m_exit_operation != overlay::operation_none);
- BOOST_ASSERT(m_exit_turn_ptr);
+ BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none);
+ BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr);
return *m_exit_turn_ptr;
}
diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp
new file mode 100644
index 0000000000..a6f1545ed1
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/implementation.hpp
@@ -0,0 +1,110 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2013, 2014, 2015.
+// Modifications copyright (c) 2013-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_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP
+
+
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+
+#include <boost/geometry/algorithms/detail/relate/point_point.hpp>
+#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
+#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
+#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Point1, typename Point2>
+struct relate<Point1, Point2, point_tag, point_tag, 0, 0, false>
+ : detail::relate::point_point<Point1, Point2>
+{};
+
+template <typename Point, typename MultiPoint>
+struct relate<Point, MultiPoint, point_tag, multi_point_tag, 0, 0, false>
+ : detail::relate::point_multipoint<Point, MultiPoint>
+{};
+
+template <typename MultiPoint, typename Point>
+struct relate<MultiPoint, Point, multi_point_tag, point_tag, 0, 0, false>
+ : detail::relate::multipoint_point<MultiPoint, Point>
+{};
+
+template <typename MultiPoint1, typename MultiPoint2>
+struct relate<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, 0, 0, false>
+ : detail::relate::multipoint_multipoint<MultiPoint1, MultiPoint2>
+{};
+
+// TODO - for now commented out because before implementing it we must consider:
+// 1. how the Box degenerated to a Point should be treated
+// 2. what should be the definition of a Box degenerated to a Point
+// 3. what fields should the matrix/mask contain for dimension > 2 and dimension > 9
+//
+//template <typename Point, typename Box, int TopDim2>
+//struct relate<Point, Box, point_tag, box_tag, 0, TopDim2, false>
+// : detail::relate::point_box<Point, Box>
+//{};
+//
+//template <typename Box, typename Point, int TopDim1>
+//struct relate<Box, Point, box_tag, point_tag, TopDim1, 0, false>
+// : detail::relate::box_point<Box, Point>
+//{};
+
+
+template <typename Point, typename Geometry, typename Tag2, int TopDim2>
+struct relate<Point, Geometry, point_tag, Tag2, 0, TopDim2, true>
+ : detail::relate::point_geometry<Point, Geometry>
+{};
+
+template <typename Geometry, typename Point, typename Tag1, int TopDim1>
+struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true>
+ : detail::relate::geometry_point<Geometry, Point>
+{};
+
+
+template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
+struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true>
+ : detail::relate::linear_linear<Linear1, Linear2>
+{};
+
+
+template <typename Linear, typename Areal, typename Tag1, typename Tag2>
+struct relate<Linear, Areal, Tag1, Tag2, 1, 2, true>
+ : detail::relate::linear_areal<Linear, Areal>
+{};
+
+template <typename Areal, typename Linear, typename Tag1, typename Tag2>
+struct relate<Areal, Linear, Tag1, Tag2, 2, 1, true>
+ : detail::relate::areal_linear<Areal, Linear>
+{};
+
+
+template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>
+struct relate<Areal1, Areal2, Tag1, Tag2, 2, 2, true>
+ : detail::relate::areal_areal<Areal1, Areal2>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/relate/interface.hpp b/boost/geometry/algorithms/detail/relate/interface.hpp
new file mode 100644
index 0000000000..e2c067b68d
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/interface.hpp
@@ -0,0 +1,348 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2013, 2014, 2015.
+// Modifications copyright (c) 2013-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_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP
+
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/algorithms/detail/relate/de9im.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate {
+
+// Those are used only to allow dispatch::relate to produce compile-time error
+
+template <typename Geometry,
+ typename Tag = typename geometry::tag<Geometry>::type>
+struct is_supported_by_generic
+{
+ static const bool value
+ = boost::is_same<Tag, linestring_tag>::value
+ || boost::is_same<Tag, multi_linestring_tag>::value
+ || boost::is_same<Tag, ring_tag>::value
+ || boost::is_same<Tag, polygon_tag>::value
+ || boost::is_same<Tag, multi_polygon_tag>::value;
+};
+
+template <typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type>
+struct is_generic
+{
+ static const bool value = is_supported_by_generic<Geometry1>::value
+ && is_supported_by_generic<Geometry2>::value;
+};
+
+
+template <typename Point, typename Geometry, typename Tag>
+struct is_generic<Point, Geometry, point_tag, Tag>
+{
+ static const bool value = is_supported_by_generic<Geometry>::value;
+};
+
+template <typename Geometry, typename Point, typename Tag>
+struct is_generic<Geometry, Point, Tag, point_tag>
+{
+ static const bool value = is_supported_by_generic<Geometry>::value;
+};
+
+template <typename Point1, typename Point2>
+struct is_generic<Point1, Point2, point_tag, point_tag>
+{
+ static const bool value = false;
+};
+
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+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,
+ bool IsGeneric = detail::relate::is_generic<Geometry1, Geometry2>::value
+>
+struct relate : not_implemented<Tag1, Tag2>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate {
+
+template <typename Geometry1, typename Geometry2>
+struct interruption_enabled
+{
+ static const bool value =
+ dispatch::relate<Geometry1, Geometry2>::interruption_enabled;
+};
+
+template <typename Geometry1,
+ typename Geometry2,
+ typename Result,
+ bool IsSequence = boost::mpl::is_sequence<Result>::value>
+struct result_handler_type
+ : not_implemented<Result>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct result_handler_type<Geometry1, Geometry2, geometry::de9im::mask, false>
+{
+ typedef mask_handler
+ <
+ geometry::de9im::mask,
+ interruption_enabled
+ <
+ Geometry1,
+ Geometry2
+ >::value
+ > type;
+};
+
+template <typename Geometry1, typename Geometry2, typename Head, typename Tail>
+struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail>, false>
+{
+ typedef mask_handler
+ <
+ boost::tuples::cons<Head, Tail>,
+ interruption_enabled
+ <
+ Geometry1,
+ Geometry2
+ >::value
+ > type;
+};
+
+template <typename Geometry1, typename Geometry2,
+ char II, char IB, char IE,
+ char BI, char BB, char BE,
+ char EI, char EB, char EE>
+struct result_handler_type
+ <
+ Geometry1,
+ Geometry2,
+ geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>,
+ false
+ >
+{
+ typedef static_mask_handler
+ <
+ geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>,
+ interruption_enabled
+ <
+ Geometry1,
+ Geometry2
+ >::value
+ > type;
+};
+
+template <typename Geometry1, typename Geometry2, typename StaticSequence>
+struct result_handler_type<Geometry1, Geometry2, StaticSequence, true>
+{
+ typedef static_mask_handler
+ <
+ StaticSequence,
+ interruption_enabled
+ <
+ Geometry1,
+ Geometry2
+ >::value
+ > type;
+};
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+namespace resolve_variant {
+
+template <typename Geometry1, typename Geometry2>
+struct relate
+{
+ template <typename Mask>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask)
+ {
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ typename detail::relate::result_handler_type
+ <
+ Geometry1,
+ Geometry2,
+ Mask
+ >::type handler(mask);
+
+ dispatch::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, handler);
+
+ return handler.result();
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Mask>
+ struct visitor : boost::static_visitor<bool>
+ {
+ Geometry2 const& m_geometry2;
+ Mask const& m_mask;
+
+ visitor(Geometry2 const& geometry2, Mask const& mask)
+ : m_geometry2(geometry2), m_mask(mask) {}
+
+ template <typename Geometry1>
+ bool operator()(Geometry1 const& geometry1) const
+ {
+ return relate<Geometry1, Geometry2>
+ ::apply(geometry1, m_geometry2, m_mask);
+ }
+ };
+
+ template <typename Mask>
+ static inline bool
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask)
+ {
+ return boost::apply_visitor(visitor<Mask>(geometry2, mask), geometry1);
+ }
+};
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Mask>
+ struct visitor : boost::static_visitor<bool>
+ {
+ Geometry1 const& m_geometry1;
+ Mask const& m_mask;
+
+ visitor(Geometry1 const& geometry1, Mask const& mask)
+ : m_geometry1(geometry1), m_mask(mask) {}
+
+ template <typename Geometry2>
+ bool operator()(Geometry2 const& geometry2) const
+ {
+ return relate<Geometry1, Geometry2>
+ ::apply(m_geometry1, geometry2, m_mask);
+ }
+ };
+
+ template <typename Mask>
+ static inline bool
+ apply(Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
+ Mask const& mask)
+ {
+ return boost::apply_visitor(visitor<Mask>(geometry1, mask), geometry2);
+ }
+};
+
+template <
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
+>
+struct relate<
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+>
+{
+ template <typename Mask>
+ struct visitor : boost::static_visitor<bool>
+ {
+ Mask const& m_mask;
+
+ visitor(Mask const& mask)
+ : m_mask(mask) {}
+
+ template <typename Geometry1, typename Geometry2>
+ bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ return relate<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2, m_mask);
+ }
+ };
+
+ template <typename Mask>
+ 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)
+ {
+ return boost::apply_visitor(visitor<Mask>(mask), geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
+/*!
+\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.
+\return true if the relation is compatible with the mask, false otherwise.
+
+\qbk{[include reference/algorithms/relate.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Mask>
+inline bool relate(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask)
+{
+ return resolve_variant::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, mask);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/relate/less.hpp b/boost/geometry/algorithms/detail/relate/less.hpp
index 3f11d4e87d..462fcc35f1 100644
--- a/boost/geometry/algorithms/detail/relate/less.hpp
+++ b/boost/geometry/algorithms/detail/relate/less.hpp
@@ -14,6 +14,10 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/math.hpp>
+
namespace boost { namespace geometry
{
diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
index 7d85a1d9a1..e7cbf6f6c2 100644
--- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
@@ -15,7 +15,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP
#include <boost/core/ignore_unused.hpp>
+#include <boost/range/size.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -97,7 +99,7 @@ public:
}
int const pig = detail::within::point_in_geometry(range::front(linestring), m_geometry2);
- //BOOST_ASSERT_MSG(pig != 0, "There should be no IPs");
+ //BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs");
if ( pig > 0 )
{
@@ -323,8 +325,8 @@ struct linear_areal
// if there was some previous ring
if ( prev_seg_id_ptr != NULL )
{
- signed_index_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
- BOOST_ASSERT(next_ring_index >= 0);
+ signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
+ BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);
// if one of the last rings of previous single geometry was ommited
if ( static_cast<std::size_t>(next_ring_index)
@@ -394,8 +396,8 @@ struct linear_areal
// if there was some previous ring
if ( prev_seg_id_ptr != NULL )
{
- signed_index_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
- BOOST_ASSERT(next_ring_index >= 0);
+ signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
+ BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);
// if one of the last rings of previous single geometry was ommited
if ( static_cast<std::size_t>(next_ring_index)
@@ -456,7 +458,7 @@ struct linear_areal
template <typename TurnIt>
void operator()(TurnIt first, TurnIt last) const
{
- BOOST_ASSERT(first != last);
+ BOOST_GEOMETRY_ASSERT(first != last);
static OpToPriority op_to_priority;
// find the operation with the least priority
int least_priority = op_to_priority(first->operations[0]);
@@ -736,6 +738,8 @@ struct linear_areal
// handle the interior overlap
if ( m_interior_detected )
{
+ BOOST_GEOMETRY_ASSERT_MSG(m_previous_turn_ptr, "non-NULL ptr expected");
+
// real interior overlap
if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )
{
@@ -745,21 +749,16 @@ struct linear_areal
// new range detected - reset previous state and check the boundary
if ( first_in_range )
{
- // actually it should be != NULL if m_interior_detected
- // so an assert could be checked here
- if ( m_previous_turn_ptr )
- {
- segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
+ segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
+ range::back(sub_range(geometry, prev_seg_id)),
+ boundary_checker);
- // if there is a boundary on the last point
- if ( prev_back_b )
- {
- update<boundary, interior, '0', TransposeResult>(res);
- }
+ // if there is a boundary on the last point
+ if ( prev_back_b )
+ {
+ update<boundary, interior, '0', TransposeResult>(res);
}
// The exit_watcher is reset below
@@ -1002,7 +1001,7 @@ struct linear_areal
/*&& ( op == overlay::operation_blocked
|| op == overlay::operation_union )*/ ) // if we're here it's u or x
{
- BOOST_ASSERT(m_first_from_unknown);
+ BOOST_GEOMETRY_ASSERT(m_first_from_unknown);
m_first_from_unknown_boundary_detected = true;
}
else
@@ -1043,7 +1042,7 @@ struct linear_areal
BoundaryChecker const& boundary_checker)
{
boost::ignore_unused(first, last);
- //BOOST_ASSERT( first != last );
+ //BOOST_GEOMETRY_ASSERT( first != last );
// For MultiPolygon many x/u operations may be generated as a first IP
// if for all turns x/u was generated and any of the Polygons doesn't contain the LineString
@@ -1071,8 +1070,8 @@ struct linear_areal
// for sure
update<interior, exterior, '1', TransposeResult>(res);
- BOOST_ASSERT(first != last);
- BOOST_ASSERT(m_previous_turn_ptr);
+ BOOST_GEOMETRY_ASSERT(first != last);
+ BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr);
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
@@ -1094,8 +1093,8 @@ struct linear_areal
update<interior, interior, '1', TransposeResult>(res);
m_interior_detected = false;
- BOOST_ASSERT(first != last);
- BOOST_ASSERT(m_previous_turn_ptr);
+ BOOST_GEOMETRY_ASSERT(first != last);
+ BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr);
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
@@ -1112,7 +1111,7 @@ struct linear_areal
// This condition may be false if the Linestring is lying on the Polygon's collinear spike
// if Polygon's spikes are not handled in get_turns() or relate() (they currently aren't)
- //BOOST_ASSERT_MSG(m_previous_operation != overlay::operation_continue,
+ //BOOST_GEOMETRY_ASSERT_MSG(m_previous_operation != overlay::operation_continue,
// "Unexpected operation! Probably the error in get_turns(L,A) or relate(L,A)");
// Currently one c/c turn is generated for the exit
// when a Linestring is going out on a collinear spike
@@ -1160,16 +1159,16 @@ struct linear_areal
typedef typename boost::range_iterator<range2_type>::type range2_iterator;
range2_type range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));
- BOOST_ASSERT(boost::size(range1));
+ BOOST_GEOMETRY_ASSERT(boost::size(range1));
std::size_t const s2 = boost::size(range2);
- BOOST_ASSERT(s2 > 2);
+ BOOST_GEOMETRY_ASSERT(s2 > 2);
std::size_t const seg_count2 = s2 - 1;
std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index);
std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index);
- BOOST_ASSERT(p_seg_ij + 1 < boost::size(range1));
- BOOST_ASSERT(q_seg_ij + 1 < s2);
+ BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1));
+ BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2);
point1_type const& pi = range::at(range1, p_seg_ij);
point2_type const& qi = range::at(range2, q_seg_ij);
@@ -1178,8 +1177,8 @@ struct linear_areal
geometry::convert(qi, qi_conv);
bool const is_ip_qj = equals::equals_point_point(turn.point, qj);
// TODO: test this!
-// BOOST_ASSERT(!equals::equals_point_point(turn.point, pi));
-// BOOST_ASSERT(!equals::equals_point_point(turn.point, qi));
+// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
+// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));
point1_type new_pj;
geometry::convert(turn.point, new_pj);
@@ -1211,7 +1210,7 @@ struct linear_areal
template <typename It>
static inline It find_next_non_duplicated(It first, It current, It last)
{
- BOOST_ASSERT( current != last );
+ BOOST_GEOMETRY_ASSERT( current != last );
It it = current;
@@ -1332,8 +1331,8 @@ struct linear_areal
if ( first == last )
return last;
- signed_index_type const multi_index = first->operations[1].seg_id.multi_index;
- signed_index_type const ring_index = first->operations[1].seg_id.ring_index;
+ signed_size_type const multi_index = first->operations[1].seg_id.multi_index;
+ signed_size_type const ring_index = first->operations[1].seg_id.ring_index;
fun(*first);
++first;
@@ -1379,7 +1378,7 @@ struct linear_areal
if ( is_union_detected )
{
- BOOST_ASSERT(m_previous_turn_ptr != NULL);
+ BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr != NULL);
if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point) )
{
// break
diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
index 20a22c3018..7a3f373e03 100644
--- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
@@ -14,7 +14,12 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP
+#include <algorithm>
+
#include <boost/core/ignore_unused.hpp>
+#include <boost/range/size.hpp>
+
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
@@ -23,6 +28,7 @@
#include <boost/geometry/algorithms/detail/single_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
+#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/algorithms/detail/relate/turns.hpp>
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
@@ -576,7 +582,7 @@ struct linear_linear
OtherBoundaryChecker const& /*other_boundary_checker*/)
{
boost::ignore_unused(first, last);
- //BOOST_ASSERT( first != last );
+ //BOOST_GEOMETRY_ASSERT( first != last );
// here, the possible exit is the real one
// we know that we entered and now we exit
@@ -586,7 +592,7 @@ struct linear_linear
{
update<interior, exterior, '1', transpose_result>(res);
- BOOST_ASSERT(first != last);
+ BOOST_GEOMETRY_ASSERT(first != last);
const TurnInfo * turn_ptr = NULL;
if ( m_degenerated_turn_ptr )
@@ -598,7 +604,7 @@ struct linear_linear
{
segment_identifier const& prev_seg_id = turn_ptr->operations[op_id].seg_id;
- //BOOST_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id)));
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id)));
bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
range::back(sub_range(geometry, prev_seg_id)),
boundary_checker);
@@ -688,7 +694,7 @@ struct linear_linear
if ( first_in_range )
{
- //BOOST_ASSERT(!boost::empty(ls1_ref));
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));
bool const front_b = is_endpoint_on_boundary<boundary_front>(
range::front(ls1_ref), boundary_checker);
if ( front_b )
@@ -717,7 +723,7 @@ struct linear_linear
if ( first_in_range )
{
- //BOOST_ASSERT(!boost::empty(ls1_ref));
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));
bool const front_b = is_endpoint_on_boundary<boundary_front>(
range::front(ls1_ref), boundary_checker);
if ( front_b )
diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
index 62ab100919..be08016a16 100644
--- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
@@ -18,6 +18,7 @@
//#include <boost/geometry/algorithms/within.hpp>
//#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -43,18 +44,18 @@ struct point_geometry
if ( pig > 0 ) // within
{
- set<interior, interior, '0', Transpose>(result);
+ relate::set<interior, interior, '0', Transpose>(result);
}
else if ( pig == 0 )
{
- set<interior, boundary, '0', Transpose>(result);
+ relate::set<interior, boundary, '0', Transpose>(result);
}
else // pig < 0 - not within
{
- set<interior, exterior, '0', Transpose>(result);
+ relate::set<interior, exterior, '0', Transpose>(result);
}
- set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
+ relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
@@ -69,9 +70,9 @@ struct point_geometry
typedef detail::relate::topology_check<Geometry> tc_t;
//tc_t tc(geometry, point);
//if ( tc.has_interior )
- set<exterior, interior, tc_t::interior, Transpose>(result);
+ relate::set<exterior, interior, tc_t::interior, Transpose>(result);
//if ( tc.has_boundary )
- set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
else
{
@@ -79,9 +80,9 @@ struct point_geometry
typedef detail::relate::topology_check<Geometry> tc_t;
tc_t tc(geometry);
if ( tc.has_interior )
- set<exterior, interior, tc_t::interior, Transpose>(result);
+ relate::set<exterior, interior, tc_t::interior, Transpose>(result);
if ( tc.has_boundary )
- set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
};
diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp
index e623868b92..e55be08225 100644
--- a/boost/geometry/algorithms/detail/relate/point_point.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_point.hpp
@@ -17,9 +17,12 @@
#include <algorithm>
#include <vector>
+#include <boost/range/empty.hpp>
+
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
+#include <boost/geometry/algorithms/detail/relate/result.hpp>
namespace boost { namespace geometry
{
@@ -38,15 +41,15 @@ struct point_point
bool equal = detail::equals::equals_point_point(point1, point2);
if ( equal )
{
- set<interior, interior, '0'>(result);
+ relate::set<interior, interior, '0'>(result);
}
else
{
- set<interior, exterior, '0'>(result);
- set<exterior, interior, '0'>(result);
+ relate::set<interior, exterior, '0'>(result);
+ relate::set<exterior, interior, '0'>(result);
}
- set<exterior, exterior, result_dimension<Point1>::value>(result);
+ relate::set<exterior, exterior, result_dimension<Point1>::value>(result);
}
};
@@ -89,7 +92,7 @@ struct point_multipoint
if ( boost::empty(multi_point) )
{
// TODO: throw on empty input?
- set<interior, exterior, '0', Transpose>(result);
+ relate::set<interior, exterior, '0', Transpose>(result);
return;
}
@@ -97,20 +100,20 @@ struct point_multipoint
if ( rel.first ) // some point of MP is equal to P
{
- set<interior, interior, '0', Transpose>(result);
+ relate::set<interior, interior, '0', Transpose>(result);
if ( rel.second ) // a point of MP was found outside P
{
- set<exterior, interior, '0', Transpose>(result);
+ relate::set<exterior, interior, '0', Transpose>(result);
}
}
else
{
- set<interior, exterior, '0', Transpose>(result);
- set<exterior, interior, '0', Transpose>(result);
+ relate::set<interior, exterior, '0', Transpose>(result);
+ relate::set<exterior, interior, '0', Transpose>(result);
}
- set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
+ relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
}
};
@@ -144,12 +147,12 @@ struct multipoint_multipoint
}
else if ( empty1 )
{
- set<exterior, interior, '0'>(result);
+ relate::set<exterior, interior, '0'>(result);
return;
}
else if ( empty2 )
{
- set<interior, exterior, '0'>(result);
+ relate::set<interior, exterior, '0'>(result);
return;
}
}
@@ -165,7 +168,7 @@ struct multipoint_multipoint
// NlogN + MlogN
bool all_handled = search<false>(multi_point1, multi_point2, result);
- if ( all_handled || result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) )
return;
// MlogM + NlogM
@@ -212,23 +215,23 @@ struct multipoint_multipoint
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
// so if e.g. only I/I must be analysed we musn't check the other MPt
- set<interior, interior, '0', Transpose>(result);
+ relate::set<interior, interior, '0', Transpose>(result);
if ( found_outside ) // some point of MP2 was found outside of MP1
{
- set<exterior, interior, '0', Transpose>(result);
+ relate::set<exterior, interior, '0', Transpose>(result);
}
}
else
{
- set<interior, exterior, '0', Transpose>(result);
- set<exterior, interior, '0', Transpose>(result);
+ relate::set<interior, exterior, '0', Transpose>(result);
+ relate::set<exterior, interior, '0', Transpose>(result);
// if no point is intersecting the other MPt then we musn't analyse the reversed case
all_handled = true;
}
- set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result);
+ relate::set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result);
return all_handled;
}
diff --git a/boost/geometry/algorithms/detail/relate/relate.hpp b/boost/geometry/algorithms/detail/relate/relate.hpp
deleted file mode 100644
index 946653452a..0000000000
--- a/boost/geometry/algorithms/detail/relate/relate.hpp
+++ /dev/null
@@ -1,339 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_HPP
-
-#include <cstddef>
-
-#include <boost/concept_check.hpp>
-#include <boost/range.hpp>
-
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/or.hpp>
-#include <boost/type_traits/is_base_of.hpp>
-
-#include <boost/geometry/algorithms/make.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/exterior_ring.hpp>
-#include <boost/geometry/core/interior_rings.hpp>
-#include <boost/geometry/core/point_order.hpp>
-#include <boost/geometry/core/ring_type.hpp>
-#include <boost/geometry/core/interior_rings.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-#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/util/math.hpp>
-#include <boost/geometry/util/order_as_direction.hpp>
-#include <boost/geometry/views/closeable_view.hpp>
-#include <boost/geometry/views/reversible_view.hpp>
-
-#include <boost/geometry/algorithms/detail/relate/result.hpp>
-
-#include <boost/geometry/algorithms/detail/relate/point_point.hpp>
-#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
-#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
-#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
-#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace relate {
-
-// Those are used only to allow dispatch::relate to produce compile-time error
-
-template <typename Geometry,
- typename Tag = typename geometry::tag<Geometry>::type>
-struct is_supported_by_generic
-{
- static const bool value
- = boost::is_same<Tag, linestring_tag>::value
- || boost::is_same<Tag, multi_linestring_tag>::value
- || boost::is_same<Tag, ring_tag>::value
- || boost::is_same<Tag, polygon_tag>::value
- || boost::is_same<Tag, multi_polygon_tag>::value;
-};
-
-template <typename Geometry1,
- typename Geometry2,
- typename Tag1 = typename geometry::tag<Geometry1>::type,
- typename Tag2 = typename geometry::tag<Geometry2>::type>
-struct is_generic
-{
- static const bool value = is_supported_by_generic<Geometry1>::value
- && is_supported_by_generic<Geometry2>::value;
-};
-
-
-template <typename Point, typename Geometry, typename Tag>
-struct is_generic<Point, Geometry, point_tag, Tag>
-{
- static const bool value = is_supported_by_generic<Geometry>::value;
-};
-
-template <typename Geometry, typename Point, typename Tag>
-struct is_generic<Geometry, Point, Tag, point_tag>
-{
- static const bool value = is_supported_by_generic<Geometry>::value;
-};
-
-template <typename Point1, typename Point2>
-struct is_generic<Point1, Point2, point_tag, point_tag>
-{
- static const bool value = false;
-};
-
-
-}} // namespace detail::relate
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace detail_dispatch { namespace relate {
-
-
-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,
- bool IsGeneric = detail::relate::is_generic<Geometry1, Geometry2>::value
->
-struct relate : not_implemented<Tag1, Tag2>
-{};
-
-
-template <typename Point1, typename Point2>
-struct relate<Point1, Point2, point_tag, point_tag, 0, 0, false>
- : detail::relate::point_point<Point1, Point2>
-{};
-
-template <typename Point, typename MultiPoint>
-struct relate<Point, MultiPoint, point_tag, multi_point_tag, 0, 0, false>
- : detail::relate::point_multipoint<Point, MultiPoint>
-{};
-
-template <typename MultiPoint, typename Point>
-struct relate<MultiPoint, Point, multi_point_tag, point_tag, 0, 0, false>
- : detail::relate::multipoint_point<MultiPoint, Point>
-{};
-
-template <typename MultiPoint1, typename MultiPoint2>
-struct relate<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, 0, 0, false>
- : detail::relate::multipoint_multipoint<MultiPoint1, MultiPoint2>
-{};
-
-//template <typename Point, typename Box, int TopDim2>
-//struct relate<Point, Box, point_tag, box_tag, 0, TopDim2, false>
-// : detail::relate::point_box<Point, Box>
-//{};
-//
-//template <typename Box, typename Point, int TopDim1>
-//struct relate<Box, Point, box_tag, point_tag, TopDim1, 0, false>
-// : detail::relate::box_point<Box, Point>
-//{};
-
-
-template <typename Point, typename Geometry, typename Tag2, int TopDim2>
-struct relate<Point, Geometry, point_tag, Tag2, 0, TopDim2, true>
- : detail::relate::point_geometry<Point, Geometry>
-{};
-
-template <typename Geometry, typename Point, typename Tag1, int TopDim1>
-struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true>
- : detail::relate::geometry_point<Geometry, Point>
-{};
-
-
-template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
-struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true>
- : detail::relate::linear_linear<Linear1, Linear2>
-{};
-
-
-template <typename Linear, typename Areal, typename Tag1, typename Tag2>
-struct relate<Linear, Areal, Tag1, Tag2, 1, 2, true>
- : detail::relate::linear_areal<Linear, Areal>
-{};
-
-template <typename Areal, typename Linear, typename Tag1, typename Tag2>
-struct relate<Areal, Linear, Tag1, Tag2, 2, 1, true>
- : detail::relate::areal_linear<Areal, Linear>
-{};
-
-
-template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>
-struct relate<Areal1, Areal2, Tag1, Tag2, 2, 2, true>
- : detail::relate::areal_areal<Areal1, Areal2>
-{};
-
-
-}} // namespace detail_dispatch::relate
-#endif // DOXYGEN_NO_DISPATCH
-
-namespace detail { namespace relate {
-
-template <typename Geometry1, typename Geometry2>
-struct interruption_enabled
-{
- static const bool value =
- detail_dispatch::relate::relate<Geometry1, Geometry2>::interruption_enabled;
-};
-
-template <typename Geometry1,
- typename Geometry2,
- typename Result,
- bool IsSequence = boost::mpl::is_sequence<Result>::value>
-struct result_handler_type
- : not_implemented<Result>
-{};
-
-template <typename Geometry1, typename Geometry2>
-struct result_handler_type<Geometry1, Geometry2, matrix9, false>
-{
- typedef matrix_handler<matrix9> type;
-};
-
-template <typename Geometry1, typename Geometry2>
-struct result_handler_type<Geometry1, Geometry2, mask9, false>
-{
- typedef mask_handler
- <
- mask9,
- interruption_enabled
- <
- Geometry1,
- Geometry2
- >::value
- > type;
-};
-
-template <typename Geometry1, typename Geometry2, typename Head, typename Tail>
-struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail>, false>
-{
- typedef mask_handler
- <
- boost::tuples::cons<Head, Tail>,
- interruption_enabled
- <
- Geometry1,
- Geometry2
- >::value
- > type;
-};
-
-template <typename Geometry1, typename Geometry2,
- char II, char IB, char IE,
- char BI, char BB, char BE,
- char EI, char EB, char EE>
-struct result_handler_type<Geometry1, Geometry2, static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>, false>
-{
- typedef static_mask_handler
- <
- static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>,
- interruption_enabled
- <
- Geometry1,
- Geometry2
- >::value
- > type;
-};
-
-template <typename Geometry1, typename Geometry2, typename StaticSequence>
-struct result_handler_type<Geometry1, Geometry2, StaticSequence, true>
-{
- typedef static_mask_handler
- <
- StaticSequence,
- interruption_enabled
- <
- Geometry1,
- Geometry2
- >::value
- > type;
-};
-
-template <typename MatrixOrMask, typename Geometry1, typename Geometry2>
-inline
-typename result_handler_type
- <
- Geometry1,
- Geometry2,
- MatrixOrMask
- >::type::result_type
-relate(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- MatrixOrMask const& matrix_or_mask = MatrixOrMask())
-{
- typedef typename result_handler_type
- <
- Geometry1,
- Geometry2,
- MatrixOrMask
- >::type handler_type;
-
- handler_type handler(matrix_or_mask);
- detail_dispatch::relate::relate<Geometry1, Geometry2>::apply(geometry1, geometry2, handler);
- return handler.result();
-}
-
-struct implemented_tag {};
-
-template <template <typename, typename> class StaticMaskTrait,
- typename Geometry1,
- typename Geometry2>
-struct relate_base
- : boost::mpl::if_
- <
- boost::mpl::or_
- <
- boost::is_base_of
- <
- nyi::not_implemented_tag,
- StaticMaskTrait<Geometry1, Geometry2>
- >,
- boost::is_base_of
- <
- nyi::not_implemented_tag,
- detail_dispatch::relate::relate<Geometry1, Geometry2>
- >
- >,
- not_implemented
- <
- typename geometry::tag<Geometry1>::type,
- typename geometry::tag<Geometry2>::type
- >,
- implemented_tag
- >::type
-{
- static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
- {
- typedef typename StaticMaskTrait<Geometry1, Geometry2>::type static_mask;
- return detail::relate::relate<static_mask>(g1, g2);
- }
-};
-
-}} // namespace detail::relate
-#endif // DOXYGEN_NO_DETAIL
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_HPP
diff --git a/boost/geometry/algorithms/detail/relate/relate_impl.hpp b/boost/geometry/algorithms/detail/relate/relate_impl.hpp
new file mode 100644
index 0000000000..e8e422993d
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/relate_impl.hpp
@@ -0,0 +1,80 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2013, 2014, 2015.
+// Modifications copyright (c) 2013-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_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/tag.hpp>
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate {
+
+struct implemented_tag {};
+
+template <template <typename, typename> class StaticMaskTrait,
+ typename Geometry1,
+ typename Geometry2>
+struct relate_impl
+ : boost::mpl::if_
+ <
+ boost::mpl::or_
+ <
+ boost::is_base_of
+ <
+ nyi::not_implemented_tag,
+ StaticMaskTrait<Geometry1, Geometry2>
+ >,
+ boost::is_base_of
+ <
+ nyi::not_implemented_tag,
+ dispatch::relate<Geometry1, Geometry2>
+ >
+ >,
+ not_implemented
+ <
+ typename geometry::tag<Geometry1>::type,
+ typename geometry::tag<Geometry2>::type
+ >,
+ implemented_tag
+ >::type
+{
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ {
+ typename detail::relate::result_handler_type
+ <
+ Geometry1,
+ Geometry2,
+ typename StaticMaskTrait<Geometry1, Geometry2>::type
+ >::type handler;
+
+ dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler);
+
+ return handler.result();
+ }
+};
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP
diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp
index e26bda67f2..b7b9264449 100644
--- a/boost/geometry/algorithms/detail/relate/result.hpp
+++ b/boost/geometry/algorithms/detail/relate/result.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
@@ -14,21 +14,24 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
-#include <boost/tuple/tuple.hpp>
+#include <cstddef>
-#include <boost/mpl/is_sequence.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/at.hpp>
#include <boost/mpl/begin.hpp>
+#include <boost/mpl/deref.hpp>
#include <boost/mpl/end.hpp>
+#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/next.hpp>
-#include <boost/mpl/at.hpp>
-#include <boost/mpl/vector_c.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/integral_constant.hpp>
-#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/util/condition.hpp>
-// TEMP - move this header to geometry/detail
-#include <boost/geometry/index/detail/tuples.hpp>
-
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
@@ -42,125 +45,110 @@ enum field { interior = 0, boundary = 1, exterior = 2 };
// but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that
// so some additional function could be added, e.g. set_dim()
-// matrix
+// --------------- MATRIX ----------------
-// TODO add height?
+// matrix
-template <std::size_t Width>
+template <std::size_t Height, std::size_t Width = Height>
class matrix
{
- BOOST_STATIC_ASSERT(Width == 2 || Width == 3);
-
public:
-
- static const std::size_t size = Width * Width;
+ typedef char value_type;
+ typedef std::size_t size_type;
+ typedef const char * const_iterator;
+ typedef const_iterator iterator;
+
+ static const std::size_t static_width = Width;
+ static const std::size_t static_height = Height;
+ static const std::size_t static_size = Width * Height;
inline matrix()
{
- ::memset(m_array, 'F', size);
+ ::memset(m_array, 'F', static_size);
}
template <field F1, field F2>
inline char get() const
{
- static const bool in_bounds = F1 * Width + F2 < size;
- return get_dispatch<F1, F2>(integral_constant<bool, in_bounds>());
+ BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
+ static const std::size_t index = F1 * Width + F2;
+ BOOST_STATIC_ASSERT(index < static_size);
+ return m_array[index];
}
template <field F1, field F2, char V>
inline void set()
{
- static const bool in_bounds = F1 * Width + F2 < size;
- set_dispatch<F1, F2, V>(integral_constant<bool, in_bounds>());
+ BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
+ static const std::size_t index = F1 * Width + F2;
+ BOOST_STATIC_ASSERT(index < static_size);
+ m_array[index] = V;
}
- template <field F1, field F2, char D>
- inline void update()
+ inline char operator[](std::size_t index) const
{
- static const bool in_bounds = F1 * Width + F2 < size;
- update_dispatch<F1, F2, D>(integral_constant<bool, in_bounds>());
+ BOOST_GEOMETRY_ASSERT(index < static_size);
+ return m_array[index];
}
-
- inline const char * data() const
+
+ inline const_iterator begin() const
{
return m_array;
}
-private:
- template <field F1, field F2>
- inline char get_dispatch(integral_constant<bool, true>) const
+ inline const_iterator end() const
{
- return m_array[F1 * Width + F2];
+ return m_array + static_size;
}
- template <field F1, field F2>
- inline char get_dispatch(integral_constant<bool, false>) const
+
+ inline static std::size_t size()
{
- return 'F';
+ return static_size;
}
-
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<bool, true>)
+
+ inline const char * data() const
{
- BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');
- m_array[F1 * Width + F2] = V;
+ return m_array;
}
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<bool, false>)
- {}
- template <field F1, field F2, char D>
- inline void update_dispatch(integral_constant<bool, true>)
+ inline std::string str() const
{
- BOOST_STATIC_ASSERT('0' <= D && D <= '9');
- char c = m_array[F1 * Width + F2];
- if ( D > c || c > '9')
- m_array[F1 * Width + F2] = D;
+ return std::string(m_array, static_size);
}
- template <field F1, field F2, char D>
- inline void update_dispatch(integral_constant<bool, false>)
- {}
- char m_array[size];
-};
-
-// TODO add EnableDimensions parameter?
-
-struct matrix9 {};
-//struct matrix4 {};
-
-// matrix_width
-
-template <typename MatrixOrMask>
-struct matrix_width
- : not_implemented<MatrixOrMask>
-{};
-
-template <>
-struct matrix_width<matrix9>
-{
- static const std::size_t value = 3;
+private:
+ char m_array[static_size];
};
// matrix_handler
template <typename Matrix>
class matrix_handler
- : private matrix<matrix_width<Matrix>::value>
{
- typedef matrix<matrix_width<Matrix>::value> base_t;
-
public:
- typedef std::string result_type;
+ typedef Matrix result_type;
static const bool interrupt = false;
+ matrix_handler()
+ {}
+
matrix_handler(Matrix const&)
{}
- result_type result() const
+ result_type const& result() const
{
- return std::string(this->data(),
- this->data() + base_t::size);
+ return m_matrix;
+ }
+
+ result_type const& matrix() const
+ {
+ return m_matrix;
+ }
+
+ result_type & matrix()
+ {
+ return m_matrix;
}
template <field F1, field F2, char D>
@@ -168,53 +156,124 @@ public:
{
BOOST_STATIC_ASSERT('0' <= D && D <= '9');
- char const c = static_cast<base_t const&>(*this).template get<F1, F2>();
+ char const c = m_matrix.template get<F1, F2>();
return D > c || c > '9';
}
- //template <field F1, field F2>
- //inline char get() const
- //{
- // return static_cast<base_t const&>(*this).template get<F1, F2>();
- //}
-
template <field F1, field F2, char V>
inline void set()
{
- static_cast<base_t&>(*this).template set<F1, F2, V>();
+ static const bool in_bounds = F1 < Matrix::static_height
+ && F2 < Matrix::static_width;
+ typedef boost::integral_constant<bool, in_bounds> in_bounds_t;
+ set_dispatch<F1, F2, V>(in_bounds_t());
}
template <field F1, field F2, char D>
inline void update()
{
- static_cast<base_t&>(*this).template update<F1, F2, D>();
+ static const bool in_bounds = F1 < Matrix::static_height
+ && F2 < Matrix::static_width;
+ typedef boost::integral_constant<bool, in_bounds> in_bounds_t;
+ update_dispatch<F1, F2, D>(in_bounds_t());
}
+
+private:
+ template <field F1, field F2, char V>
+ inline void set_dispatch(integral_constant<bool, true>)
+ {
+ static const std::size_t index = F1 * Matrix::static_width + F2;
+ BOOST_STATIC_ASSERT(index < Matrix::static_size);
+ BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');
+ m_matrix.template set<F1, F2, V>();
+ }
+ template <field F1, field F2, char V>
+ inline void set_dispatch(integral_constant<bool, false>)
+ {}
+
+ template <field F1, field F2, char D>
+ inline void update_dispatch(integral_constant<bool, true>)
+ {
+ static const std::size_t index = F1 * Matrix::static_width + F2;
+ BOOST_STATIC_ASSERT(index < Matrix::static_size);
+ BOOST_STATIC_ASSERT('0' <= D && D <= '9');
+ char const c = m_matrix.template get<F1, F2>();
+ if ( D > c || c > '9')
+ m_matrix.template set<F1, F2, D>();
+ }
+ template <field F1, field F2, char D>
+ inline void update_dispatch(integral_constant<bool, false>)
+ {}
+
+ Matrix m_matrix;
};
-// RUN-TIME MASKS
+// --------------- RUN-TIME MASK ----------------
-// mask9
+// run-time mask
-class mask9
+template <std::size_t Height, std::size_t Width = Height>
+class mask
{
public:
- static const std::size_t width = 3; // TEMP
+ static const std::size_t static_width = Width;
+ static const std::size_t static_height = Height;
+ static const std::size_t static_size = Width * Height;
+
+ inline mask(const char * s)
+ {
+ char * it = m_array;
+ char * const last = m_array + static_size;
+ for ( ; it != last && *s != '\0' ; ++it, ++s )
+ {
+ char c = *s;
+ check_char(c);
+ *it = c;
+ }
+ if ( it != last )
+ {
+ ::memset(it, '*', last - it);
+ }
+ }
- inline mask9(std::string const& de9im_mask)
+ inline mask(const char * s, std::size_t count)
{
- // TODO: throw an exception here?
- BOOST_ASSERT(de9im_mask.size() == 9);
- ::memcpy(m_mask, de9im_mask.c_str(), 9);
+ if ( count > static_size )
+ {
+ count = static_size;
+ }
+ if ( count > 0 )
+ {
+ std::for_each(s, s + count, check_char);
+ ::memcpy(m_array, s, count);
+ }
+ if ( count < static_size )
+ {
+ ::memset(m_array + count, '*', static_size - count);
+ }
}
template <field F1, field F2>
inline char get() const
{
- return m_mask[F1 * 3 + F2];
+ BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
+ static const std::size_t index = F1 * Width + F2;
+ BOOST_STATIC_ASSERT(index < static_size);
+ return m_array[index];
}
private:
- char m_mask[9];
+ static inline void check_char(char c)
+ {
+ bool const is_valid = c == '*' || c == 'T' || c == 'F'
+ || ( c >= '0' && c <= '9' );
+ if ( !is_valid )
+ {
+ throw geometry::invalid_input_exception();
+ }
+ }
+
+ char m_array[static_size];
};
// interrupt()
@@ -277,18 +336,18 @@ struct interrupt_dispatch_tuple<Masks, N, N>
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8, typename T9>
-struct interrupt_dispatch<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, true>
-{
- typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
+//template <typename T0, typename T1, typename T2, typename T3, typename T4,
+// typename T5, typename T6, typename T7, typename T8, typename T9>
+//struct interrupt_dispatch<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, true>
+//{
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
- template <field F1, field F2, char V>
- static inline bool apply(mask_type const& mask)
- {
- return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);
- }
-};
+// template <field F1, field F2, char V>
+// static inline bool apply(mask_type const& mask)
+// {
+// return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);
+// }
+//};
template <typename Head, typename Tail>
struct interrupt_dispatch<boost::tuples::cons<Head, Tail>, true>
@@ -363,18 +422,18 @@ struct may_update_dispatch_tuple<Masks, N, N>
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8, typename T9>
-struct may_update_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
-{
- typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
+//template <typename T0, typename T1, typename T2, typename T3, typename T4,
+// typename T5, typename T6, typename T7, typename T8, typename T9>
+//struct may_update_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+//{
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
- template <field F1, field F2, char D, typename Matrix>
- static inline bool apply(mask_type const& mask, Matrix const& matrix)
- {
- return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);
- }
-};
+// template <field F1, field F2, char D, typename Matrix>
+// static inline bool apply(mask_type const& mask, Matrix const& matrix)
+// {
+// return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);
+// }
+//};
template <typename Head, typename Tail>
struct may_update_dispatch< boost::tuples::cons<Head, Tail> >
@@ -460,18 +519,18 @@ struct check_dispatch_tuple<Masks, N, N>
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8, typename T9>
-struct check_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
-{
- typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
+//template <typename T0, typename T1, typename T2, typename T3, typename T4,
+// typename T5, typename T6, typename T7, typename T8, typename T9>
+//struct check_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+//{
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;
- template <typename Matrix>
- static inline bool apply(mask_type const& mask, Matrix const& matrix)
- {
- return check_dispatch_tuple<mask_type>::apply(mask, matrix);
- }
-};
+// template <typename Matrix>
+// static inline bool apply(mask_type const& mask, Matrix const& matrix)
+// {
+// return check_dispatch_tuple<mask_type>::apply(mask, matrix);
+// }
+//};
template <typename Head, typename Tail>
struct check_dispatch< boost::tuples::cons<Head, Tail> >
@@ -493,10 +552,10 @@ inline bool check_matrix(Mask const& mask, Matrix const& matrix)
// matrix_width
-template <>
-struct matrix_width<mask9>
+template <typename MatrixOrMask>
+struct matrix_width
{
- static const std::size_t value = 3;
+ static const std::size_t value = MatrixOrMask::static_width;
};
template <typename Tuple,
@@ -526,20 +585,30 @@ struct matrix_width< boost::tuples::cons<Head, Tail> >
value = matrix_width_tuple< boost::tuples::cons<Head, Tail> >::value;
};
-// matrix_handler
+// mask_handler
template <typename Mask, bool Interrupt>
class mask_handler
- : private matrix<matrix_width<Mask>::value>
+ : private matrix_handler
+ <
+ relate::matrix<matrix_width<Mask>::value>
+ >
{
- typedef matrix<matrix_width<Mask>::value> base_t;
+ typedef matrix_handler
+ <
+ relate::matrix<matrix_width<Mask>::value>
+ > base_t;
public:
typedef bool result_type;
bool interrupt;
- inline mask_handler(Mask const& m)
+ inline mask_handler()
+ : interrupt(false)
+ {}
+
+ inline explicit mask_handler(Mask const& m)
: interrupt(false)
, m_mask(m)
{}
@@ -547,23 +616,17 @@ public:
result_type result() const
{
return !interrupt
- && check_matrix(m_mask, static_cast<base_t const&>(*this));
+ && check_matrix(m_mask, base_t::matrix());
}
template <field F1, field F2, char D>
inline bool may_update() const
{
return detail::relate::may_update<F1, F2, D>(
- m_mask, static_cast<base_t const&>(*this)
+ m_mask, base_t::matrix()
);
}
- //template <field F1, field F2>
- //inline char get() const
- //{
- // return static_cast<base_t const&>(*this).template get<F1, F2>();
- //}
-
template <field F1, field F2, char V>
inline void set()
{
@@ -594,29 +657,65 @@ private:
Mask const& m_mask;
};
-// STATIC MASKS
+// --------------- COMPILE-TIME MASK ----------------
+
+// static_check_characters
+template
+<
+ typename Seq,
+ typename First = typename boost::mpl::begin<Seq>::type,
+ typename Last = typename boost::mpl::end<Seq>::type
+>
+struct static_check_characters
+ : static_check_characters
+ <
+ Seq,
+ typename boost::mpl::next<First>::type
+ >
+{
+ typedef typename boost::mpl::deref<First>::type type;
+ static const char value = type::value;
+ static const bool is_valid = (value >= '0' && value <= '9')
+ || value == 'T' || value == 'F' || value == '*';
+ BOOST_MPL_ASSERT_MSG((is_valid),
+ INVALID_STATIC_MASK_CHARACTER,
+ (type));
+};
+
+template <typename Seq, typename Last>
+struct static_check_characters<Seq, Last, Last>
+{};
// static_mask
-template <char II, char IB, char IE,
- char BI, char BB, char BE,
- char EI, char EB, char EE>
-class static_mask
+template
+<
+ typename Seq,
+ std::size_t Height,
+ std::size_t Width = Height
+>
+struct static_mask
{
- typedef boost::mpl::vector_c
- <
- char, II, IB, IE, BI, BB, BE, EI, EB, EE
- > vector_type;
+ static const std::size_t static_width = Width;
+ static const std::size_t static_height = Height;
+ static const std::size_t static_size = Width * Height;
-public:
- template <field F1, field F2>
- struct get
+ BOOST_STATIC_ASSERT(
+ std::size_t(boost::mpl::size<Seq>::type::value) == static_size);
+
+ template <detail::relate::field F1, detail::relate::field F2>
+ struct static_get
{
- BOOST_STATIC_ASSERT(F1 * 3 + F2 < boost::mpl::size<vector_type>::value);
+ BOOST_STATIC_ASSERT(std::size_t(F1) < static_height);
+ BOOST_STATIC_ASSERT(std::size_t(F2) < static_width);
static const char value
- = boost::mpl::at_c<vector_type, F1 * 3 + F2>::type::value;
+ = boost::mpl::at_c<Seq, F1 * static_width + F2>::type::value;
};
+
+private:
+ // check static_mask characters
+ enum { mask_check = sizeof(static_check_characters<Seq>) };
};
// static_should_handle_element
@@ -624,7 +723,7 @@ public:
template <typename StaticMask, field F1, field F2, bool IsSequence>
struct static_should_handle_element_dispatch
{
- static const char mask_el = StaticMask::template get<F1, F2>::value;
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;
static const bool value = mask_el == 'F'
|| mask_el == 'T'
|| ( mask_el >= '0' && mask_el <= '9' );
@@ -691,7 +790,7 @@ struct static_interrupt_dispatch
template <typename StaticMask, char V, field F1, field F2, bool IsSequence>
struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>
{
- static const char mask_el = StaticMask::template get<F1, F2>::value;
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;
static const bool value
= ( V >= '0' && V <= '9' ) ?
@@ -756,7 +855,7 @@ struct static_interrupt
template <typename StaticMask, char D, field F1, field F2, bool IsSequence>
struct static_may_update_dispatch
{
- static const char mask_el = StaticMask::template get<F1, F2>::value;
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;
static const int version
= mask_el == 'F' ? 0
: mask_el == 'T' ? 1
@@ -860,7 +959,7 @@ struct static_may_update
}
};
-// static_check
+// static_check_matrix
template <typename StaticMask, bool IsSequence>
struct static_check_dispatch
@@ -882,7 +981,7 @@ struct static_check_dispatch
template <field F1, field F2>
struct per_one
{
- static const char mask_el = StaticMask::template get<F1, F2>::value;
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;
static const int version
= mask_el == 'F' ? 0
: mask_el == 'T' ? 1
@@ -982,31 +1081,34 @@ struct static_check_matrix
template <typename StaticMask, bool Interrupt>
class static_mask_handler
- : private matrix<3>
+ : private matrix_handler< matrix<3> >
{
- typedef matrix<3> base_t;
+ typedef matrix_handler< relate::matrix<3> > base_type;
public:
typedef bool result_type;
bool interrupt;
- inline static_mask_handler(StaticMask const& /*dummy*/)
+ inline static_mask_handler()
+ : interrupt(false)
+ {}
+
+ inline explicit static_mask_handler(StaticMask const& /*dummy*/)
: interrupt(false)
{}
result_type result() const
{
return (!Interrupt || !interrupt)
- && static_check_matrix<StaticMask>::
- apply(static_cast<base_t const&>(*this));
+ && static_check_matrix<StaticMask>::apply(base_type::matrix());
}
template <field F1, field F2, char D>
inline bool may_update() const
{
return static_may_update<StaticMask, D, F1, F2>::
- apply(static_cast<base_t const&>(*this));
+ apply(base_type::matrix());
}
template <field F1, field F2>
@@ -1015,12 +1117,6 @@ public:
return static_should_handle_element<StaticMask, F1, F2>::value;
}
- //template <field F1, field F2>
- //inline char get() const
- //{
- // return base_t::template get<F1, F2>();
- //}
-
template <field F1, field F2, char V>
inline void set()
{
@@ -1056,7 +1152,7 @@ private:
template <field F1, field F2, char V>
inline void set_dispatch(integral_constant<int, 1>)
{
- base_t::template set<F1, F2, V>();
+ base_type::template set<F1, F2, V>();
}
// else
template <field F1, field F2, char V>
@@ -1073,7 +1169,7 @@ private:
template <field F1, field F2, char V>
inline void update_dispatch(integral_constant<int, 1>)
{
- base_t::template update<F1, F2, V>();
+ base_type::template update<F1, F2, V>();
}
// else
template <field F1, field F2, char V>
@@ -1081,165 +1177,9 @@ private:
{}
};
-// OPERATORS
-
-template <typename Mask1, typename Mask2> inline
-boost::tuples::cons<
- Mask1,
- boost::tuples::cons<Mask2, boost::tuples::null_type>
->
-operator||(Mask1 const& m1, Mask2 const& m2)
-{
- namespace bt = boost::tuples;
-
- return
- bt::cons< Mask1, bt::cons<Mask2, bt::null_type> >
- ( m1, bt::cons<Mask2, bt::null_type>(m2, bt::null_type()) );
-}
-
-template <typename Head, typename Tail, typename Mask> inline
-typename index::detail::tuples::push_back<
- boost::tuples::cons<Head, Tail>, Mask
->::type
-operator||(boost::tuples::cons<Head, Tail> const& t, Mask const& m)
-{
- namespace bt = boost::tuples;
-
- return
- index::detail::tuples::push_back<
- bt::cons<Head, Tail>, Mask
- >::apply(t, m);
-}
-
-// PREDEFINED MASKS
-
-// TODO:
-// 1. specialize for simplified masks if available
-// e.g. for TOUCHES use 1 mask for A/A
-// 2. Think about dimensions > 2 e.g. should TOUCHES be true
-// if the interior of the Areal overlaps the boundary of the Volumetric
-// like it's true for Linear/Areal
-
-// EQUALS
-template <typename Geometry1, typename Geometry2>
-struct static_mask_equals_type
-{
- typedef static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia
- //typedef static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC
-};
-
-// DISJOINT
-typedef static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> static_mask_disjoint;
+// --------------- UTIL FUNCTIONS ----------------
-// TOUCHES - NOT P/P
-template <typename Geometry1,
- typename Geometry2,
- std::size_t Dim1 = topological_dimension<Geometry1>::value,
- std::size_t Dim2 = topological_dimension<Geometry2>::value>
-struct static_mask_touches_impl
-{
- typedef boost::mpl::vector<
- static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>,
- static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>,
- static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'>
- > type;
-};
-// According to OGC, doesn't apply to P/P
-// Using the above mask the result would be always false
-template <typename Geometry1, typename Geometry2>
-struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
- : not_implemented<typename geometry::tag<Geometry1>::type,
- typename geometry::tag<Geometry2>::type>
-{};
-
-template <typename Geometry1, typename Geometry2>
-struct static_mask_touches_type
- : static_mask_touches_impl<Geometry1, Geometry2>
-{};
-
-// WITHIN
-typedef static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> static_mask_within;
-
-// COVERED_BY (non OGC)
-typedef boost::mpl::vector<
- static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>,
- static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>,
- static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>,
- static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'>
- > static_mask_covered_by;
-
-// CROSSES
-// dim(G1) < dim(G2) - P/L P/A L/A
-template <typename Geometry1,
- typename Geometry2,
- std::size_t Dim1 = topological_dimension<Geometry1>::value,
- std::size_t Dim2 = topological_dimension<Geometry2>::value,
- bool D1LessD2 = (Dim1 < Dim2)
->
-struct static_mask_crosses_impl
-{
- typedef static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type;
-};
-// TODO: I'm not sure if this one below should be available!
-// dim(G1) > dim(G2) - L/P A/P A/L
-template <typename Geometry1, typename Geometry2,
- std::size_t Dim1, std::size_t Dim2
->
-struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false>
-{
- typedef static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type;
-};
-// dim(G1) == dim(G2) - P/P A/A
-template <typename Geometry1, typename Geometry2,
- std::size_t Dim
->
-struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false>
- : not_implemented<typename geometry::tag<Geometry1>::type,
- typename geometry::tag<Geometry2>::type>
-{};
-// dim(G1) == 1 && dim(G2) == 1 - L/L
-template <typename Geometry1, typename Geometry2>
-struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false>
-{
- typedef static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type;
-};
-
-template <typename Geometry1, typename Geometry2>
-struct static_mask_crosses_type
- : static_mask_crosses_impl<Geometry1, Geometry2>
-{};
-
-// OVERLAPS
-
-// dim(G1) != dim(G2) - NOT P/P, L/L, A/A
-template <typename Geometry1,
- typename Geometry2,
- std::size_t Dim1 = topological_dimension<Geometry1>::value,
- std::size_t Dim2 = topological_dimension<Geometry2>::value
->
-struct static_mask_overlaps_impl
- : not_implemented<typename geometry::tag<Geometry1>::type,
- typename geometry::tag<Geometry2>::type>
-{};
-// dim(G1) == D && dim(G2) == D - P/P A/A
-template <typename Geometry1, typename Geometry2, std::size_t Dim>
-struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim>
-{
- typedef static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
-};
-// dim(G1) == 1 && dim(G2) == 1 - L/L
-template <typename Geometry1, typename Geometry2>
-struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
-{
- typedef static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;
-};
-
-template <typename Geometry1, typename Geometry2>
-struct static_mask_overlaps_type
- : static_mask_overlaps_impl<Geometry1, Geometry2>
-{};
-
-// RESULTS/HANDLERS UTILS
+// set
template <field F1, field F2, char V, typename Result>
inline void set(Result & res)
@@ -1273,33 +1213,7 @@ inline void set(Result & res)
set_dispatch<F1, F2, V, Transpose>::apply(res);
}
-template <char V, typename Result>
-inline void set(Result & res)
-{
- res.template set<interior, interior, V>();
- res.template set<interior, boundary, V>();
- res.template set<interior, exterior, V>();
- res.template set<boundary, interior, V>();
- res.template set<boundary, boundary, V>();
- res.template set<boundary, exterior, V>();
- res.template set<exterior, interior, V>();
- res.template set<exterior, boundary, V>();
- res.template set<exterior, exterior, V>();
-}
-
-template <char II, char IB, char IE, char BI, char BB, char BE, char EI, char EB, char EE, typename Result>
-inline void set(Result & res)
-{
- res.template set<interior, interior, II>();
- res.template set<interior, boundary, IB>();
- res.template set<interior, exterior, IE>();
- res.template set<boundary, interior, BI>();
- res.template set<boundary, boundary, BB>();
- res.template set<boundary, exterior, BE>();
- res.template set<exterior, interior, EI>();
- res.template set<exterior, boundary, EB>();
- res.template set<exterior, exterior, EE>();
-}
+// update
template <field F1, field F2, char D, typename Result>
inline void update(Result & res)
@@ -1333,6 +1247,8 @@ inline void update(Result & res)
update_result_dispatch<F1, F2, D, Transpose>::apply(res);
}
+// may_update
+
template <field F1, field F2, char D, typename Result>
inline bool may_update(Result const& res)
{
@@ -1365,13 +1281,7 @@ inline bool may_update(Result const& res)
return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res);
}
-template <typename Result, char II, char IB, char IE, char BI, char BB, char BE, char EI, char EB, char EE>
-inline Result return_result()
-{
- Result res;
- set<II, IB, IE, BI, BB, BE, EI, EB, EE>(res);
- return res;
-}
+// result_dimension
template <typename Geometry>
struct result_dimension
diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp
index 636c9756d8..d54948e1f5 100644
--- a/boost/geometry/algorithms/detail/relate/turns.hpp
+++ b/boost/geometry/algorithms/detail/relate/turns.hpp
@@ -84,14 +84,30 @@ struct get_turns
Geometry2 const& geometry2,
InterruptPolicy & interrupt_policy)
{
- static const bool reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value;
- static const bool reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value;
-
RobustPolicy robust_policy = geometry::get_rescale_policy
<
RobustPolicy
>(geometry1, geometry2);
+ apply(turns, geometry1, geometry2, interrupt_policy, robust_policy);
+ }
+
+ template <typename Turns, typename InterruptPolicy>
+ static inline void apply(Turns & turns,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ InterruptPolicy & interrupt_policy,
+ RobustPolicy const& robust_policy)
+ {
+ static const bool reverse1 = detail::overlay::do_reverse
+ <
+ geometry::point_order<Geometry1>::value
+ >::value;
+
+ static const bool reverse2 = detail::overlay::do_reverse
+ <
+ geometry::point_order<Geometry2>::value
+ >::value;
dispatch::get_turns
<
@@ -255,9 +271,14 @@ struct less
{
static LessOp less_op;
- return left.operations[OpId].fraction < right.operations[OpId].fraction
- || ( left.operations[OpId].fraction == right.operations[OpId].fraction
- && less_op(left, right) );
+ return
+ geometry::math::equals(left.operations[OpId].fraction,
+ right.operations[OpId].fraction)
+ ?
+ less_op(left, right)
+ :
+ (left.operations[OpId].fraction < right.operations[OpId].fraction)
+ ;
}
template <typename Turn>
diff --git a/boost/geometry/algorithms/detail/relation/implementation.hpp b/boost/geometry/algorithms/detail/relation/implementation.hpp
new file mode 100644
index 0000000000..b9a238d6c8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relation/implementation.hpp
@@ -0,0 +1,18 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 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_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP
+
+
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/relation/interface.hpp b/boost/geometry/algorithms/detail/relation/interface.hpp
new file mode 100644
index 0000000000..73737cf2c2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relation/interface.hpp
@@ -0,0 +1,186 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_INTERFACE_HPP
+
+
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate
+{
+
+template <typename Geometry1, typename Geometry2>
+struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix, false>
+{
+ typedef matrix_handler<geometry::de9im::matrix> type;
+};
+
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry1, typename Geometry2>
+struct relation
+{
+ template <typename Matrix>
+ static inline Matrix apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
+ {
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ typename detail::relate::result_handler_type
+ <
+ Geometry1,
+ Geometry2,
+ Matrix
+ >::type handler;
+
+ dispatch::relate
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, handler);
+
+ return handler.result();
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ template <typename Matrix>
+ struct visitor : boost::static_visitor<Matrix>
+ {
+ Geometry2 const& m_geometry2;
+
+ visitor(Geometry2 const& geometry2)
+ : m_geometry2(geometry2) {}
+
+ template <typename Geometry1>
+ Matrix operator()(Geometry1 const& geometry1) const
+ {
+ return relation<Geometry1, Geometry2>
+ ::template apply<Matrix>(geometry1, m_geometry2);
+ }
+ };
+
+ template <typename Matrix>
+ static inline Matrix
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2)
+ {
+ return boost::apply_visitor(visitor<Matrix>(geometry2), geometry1);
+ }
+};
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Matrix>
+ struct visitor : boost::static_visitor<Matrix>
+ {
+ Geometry1 const& m_geometry1;
+
+ visitor(Geometry1 const& geometry1)
+ : m_geometry1(geometry1) {}
+
+ template <typename Geometry2>
+ Matrix operator()(Geometry2 const& geometry2) const
+ {
+ return relation<Geometry1, Geometry2>
+ ::template apply<Matrix>(m_geometry1, geometry2);
+ }
+ };
+
+ template <typename Matrix>
+ static inline Matrix
+ apply(Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
+ {
+ return boost::apply_visitor(visitor<Matrix>(geometry1), geometry2);
+ }
+};
+
+template
+<
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
+>
+struct relation
+ <
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+ >
+{
+ template <typename Matrix>
+ struct visitor : boost::static_visitor<Matrix>
+ {
+ template <typename Geometry1, typename Geometry2>
+ Matrix operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ return relation<Geometry1, Geometry2>
+ ::template apply<Matrix>(geometry1, geometry2);
+ }
+ };
+
+ template <typename Matrix>
+ static inline Matrix
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
+ {
+ return boost::apply_visitor(visitor<Matrix>(), geometry1, geometry2);
+ }
+};
+
+} // namespace resolve_variant
+
+
+/*!
+\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.
+
+\qbk{[include reference/algorithms/relation.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline de9im::matrix relation(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
+{
+ return resolve_variant::relation
+ <
+ Geometry1,
+ Geometry2
+ >::template apply<de9im::matrix>(geometry1, geometry2);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/result_inverse.hpp b/boost/geometry/algorithms/detail/result_inverse.hpp
new file mode 100644
index 0000000000..01a1997e49
--- /dev/null
+++ b/boost/geometry/algorithms/detail/result_inverse.hpp
@@ -0,0 +1,44 @@
+// Boost.Geometry
+
+// Copyright (c) 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_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP
+
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+
+
+namespace boost { namespace geometry { namespace detail
+{
+
+template <typename T>
+struct result_inverse
+{
+ void set(T const& d, T const& a)
+ {
+ distance = d;
+ azimuth = a;
+ }
+
+ T distance;
+ T azimuth;
+};
+
+}}} // namespace boost::geometry::detail
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/ring_identifier.hpp b/boost/geometry/algorithms/detail/ring_identifier.hpp
index bc3fe1fef3..9ba39e4a8b 100644
--- a/boost/geometry/algorithms/detail/ring_identifier.hpp
+++ b/boost/geometry/algorithms/detail/ring_identifier.hpp
@@ -15,7 +15,7 @@
#endif
-#include <boost/geometry/algorithms/detail/signed_index_type.hpp>
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
namespace boost { namespace geometry
@@ -32,9 +32,9 @@ struct ring_identifier
, ring_index(-1)
{}
- inline ring_identifier(signed_index_type src,
- signed_index_type mul,
- signed_index_type rin)
+ inline ring_identifier(signed_size_type src,
+ signed_size_type mul,
+ signed_size_type rin)
: source_index(src)
, multi_index(mul)
, ring_index(rin)
@@ -68,9 +68,9 @@ struct ring_identifier
#endif
- signed_index_type source_index;
- signed_index_type multi_index;
- signed_index_type ring_index;
+ signed_size_type source_index;
+ signed_size_type multi_index;
+ signed_size_type ring_index;
};
diff --git a/boost/geometry/algorithms/detail/sections/range_by_section.hpp b/boost/geometry/algorithms/detail/sections/range_by_section.hpp
index d139a3fdd2..02cec6cb48 100644
--- a/boost/geometry/algorithms/detail/sections/range_by_section.hpp
+++ b/boost/geometry/algorithms/detail/sections/range_by_section.hpp
@@ -19,11 +19,11 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
-#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@@ -77,7 +77,7 @@ struct full_section_multi
{
typedef typename boost::range_size<MultiGeometry>::type size_type;
- BOOST_ASSERT
+ BOOST_GEOMETRY_ASSERT
(
section.ring_id.multi_index >= 0
&& size_type(section.ring_id.multi_index) < boost::size(multi)
diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
index a744ea0a34..1ced394353 100644
--- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp
+++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
@@ -1,12 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// 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.
-// 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, 2015.
+// Modifications copyright (c) 2013-2015 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
@@ -36,6 +36,7 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -80,12 +81,14 @@ struct section
ring_identifier ring_id;
Box bounding_box;
- int begin_index;
- int end_index;
+ // NOTE: size_type could be passed as template parameter
+ // NOTE: these probably also could be of type std::size_t
+ signed_size_type begin_index;
+ signed_size_type end_index;
std::size_t count;
std::size_t range_count;
bool duplicate;
- int non_duplicate_index;
+ signed_size_type non_duplicate_index;
bool is_non_duplicate_first;
bool is_non_duplicate_last;
@@ -248,7 +251,7 @@ struct check_duplicate_loop<DimensionCount, DimensionCount>
template <typename T, std::size_t Index, std::size_t Count>
struct assign_loop
{
- static inline void apply(T dims[Count], int const value)
+ static inline void apply(T dims[Count], T const value)
{
dims[Index] = value;
assign_loop<T, Index + 1, Count>::apply(dims, value);
@@ -258,7 +261,7 @@ struct assign_loop
template <typename T, std::size_t Count>
struct assign_loop<T, Count, Count>
{
- static inline void apply(T [Count], int const)
+ static inline void apply(T [Count], T const)
{
}
};
@@ -291,8 +294,8 @@ struct sectionalize_part
typedef typename boost::range_value<Sections>::type section_type;
BOOST_STATIC_ASSERT
(
- (static_cast<int>(section_type::dimension_count)
- == static_cast<int>(boost::mpl::size<DimensionVector>::value))
+ (static_cast<std::size_t>(section_type::dimension_count)
+ == static_cast<std::size_t>(boost::mpl::size<DimensionVector>::value))
);
typedef typename geometry::robust_point_type
@@ -307,8 +310,8 @@ struct sectionalize_part
return;
}
- int index = 0;
- int ndi = 0; // non duplicate index
+ signed_size_type index = 0;
+ signed_size_type ndi = 0; // non duplicate index
section_type section;
bool mark_first_non_duplicated = true;
diff --git a/boost/geometry/algorithms/detail/signed_index_type.hpp b/boost/geometry/algorithms/detail/signed_size_type.hpp
index 36dcf4de4c..db7344ec80 100644
--- a/boost/geometry/algorithms/detail/signed_index_type.hpp
+++ b/boost/geometry/algorithms/detail/signed_size_type.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2015, 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_SIGNED_INDEX_TYPE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_INDEX_TYPE_HPP
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP
#include <cstddef>
@@ -20,10 +20,9 @@ namespace boost { namespace geometry
{
-typedef boost::make_signed<std::size_t>::type signed_index_type;
-//typedef std::ptrdiff_t signed_index_type;
+typedef boost::make_signed<std::size_t>::type signed_size_type;
}} // namespace boost::geometry
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_INDEX_TYPE_HPP
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP
diff --git a/boost/geometry/algorithms/detail/single_geometry.hpp b/boost/geometry/algorithms/detail/single_geometry.hpp
index f38295ada6..31e4401099 100644
--- a/boost/geometry/algorithms/detail/single_geometry.hpp
+++ b/boost/geometry/algorithms/detail/single_geometry.hpp
@@ -14,7 +14,10 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SINGLE_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SINGLE_GEOMETRY_HPP
+#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_base_of.hpp>
+
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/util/range.hpp>
@@ -44,17 +47,12 @@ struct single_geometry
template <typename Geometry>
struct single_geometry<Geometry, true>
{
- typedef typename boost::mpl::if_c
- <
- boost::is_const<Geometry>::value,
- typename boost::range_value<Geometry>::type const&,
- typename boost::range_value<Geometry>::type
- >::type return_type;
+ typedef typename boost::range_reference<Geometry>::type return_type;
template <typename Id>
static inline return_type apply(Geometry & g, Id const& id)
{
- BOOST_ASSERT(id.multi_index >= 0);
+ BOOST_GEOMETRY_ASSERT(id.multi_index >= 0);
typedef typename boost::range_size<Geometry>::type size_type;
return range::at(g, static_cast<size_type>(id.multi_index));
}
diff --git a/boost/geometry/algorithms/detail/sub_range.hpp b/boost/geometry/algorithms/detail/sub_range.hpp
index eda3ce58ba..29edc94e6c 100644
--- a/boost/geometry/algorithms/detail/sub_range.hpp
+++ b/boost/geometry/algorithms/detail/sub_range.hpp
@@ -14,6 +14,9 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
+#include <boost/mpl/if.hpp>
+
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry {
@@ -84,7 +87,7 @@ struct sub_range<Geometry, Tag, true>
template <typename Id> static inline
return_type apply(Geometry & geometry, Id const& id)
{
- BOOST_ASSERT(0 <= id.multi_index);
+ BOOST_GEOMETRY_ASSERT(0 <= id.multi_index);
typedef typename boost::range_size<Geometry>::type size_type;
size_type const mi = static_cast<size_type>(id.multi_index);
return sub_sub_range::apply(range::at(geometry, mi), id);
@@ -111,6 +114,13 @@ sub_range(Geometry & geometry, Id const& id)
return detail_dispatch::sub_range<Geometry>::apply(geometry, id);
}
+template <typename Geometry, typename Id> inline
+typename sub_range_return_type<Geometry const>::type
+sub_range(Geometry const& geometry, Id const& id)
+{
+ return detail_dispatch::sub_range<Geometry const>::apply(geometry, id);
+}
+
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/sweep.hpp b/boost/geometry/algorithms/detail/sweep.hpp
new file mode 100644
index 0000000000..3dc78261f2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/sweep.hpp
@@ -0,0 +1,87 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP
+
+#include <boost/core/ignore_unused.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace sweep
+{
+
+struct no_interrupt_policy
+{
+ static bool const enabled = false;
+
+ template <typename Event>
+ static inline bool apply(Event const&)
+ {
+ return false;
+ }
+};
+
+}} // namespace detail::sweep
+#endif // DOXYGEN_NO_DETAIL
+
+
+template
+<
+ typename Range,
+ typename PriorityQueue,
+ typename InitializationVisitor,
+ typename EventVisitor,
+ typename InterruptPolicy
+>
+inline void sweep(Range const& range, PriorityQueue& queue,
+ InitializationVisitor& initialization_visitor,
+ EventVisitor& event_visitor,
+ InterruptPolicy const& interrupt_policy)
+{
+ typedef typename PriorityQueue::value_type event_type;
+
+ initialization_visitor.apply(range, queue, event_visitor);
+ while (! queue.empty())
+ {
+ event_type event = queue.top();
+ queue.pop();
+ event_visitor.apply(event, queue);
+ if (interrupt_policy.enabled && interrupt_policy.apply(event))
+ {
+ break;
+ }
+ }
+
+ boost::ignore_unused(interrupt_policy);
+}
+
+
+template
+<
+ typename Range,
+ typename PriorityQueue,
+ typename InitializationVisitor,
+ typename EventVisitor
+>
+inline void sweep(Range const& range, PriorityQueue& queue,
+ InitializationVisitor& initialization_visitor,
+ EventVisitor& event_visitor)
+{
+ sweep(range, queue, initialization_visitor, event_visitor,
+ detail::sweep::no_interrupt_policy());
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP
diff --git a/boost/geometry/algorithms/detail/thomas_inverse.hpp b/boost/geometry/algorithms/detail/thomas_inverse.hpp
new file mode 100644
index 0000000000..96b237e054
--- /dev/null
+++ b/boost/geometry/algorithms/detail/thomas_inverse.hpp
@@ -0,0 +1,191 @@
+// Boost.Geometry
+
+// Copyright (c) 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_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP
+
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+#include <boost/geometry/algorithms/detail/result_inverse.hpp>
+
+namespace boost { namespace geometry { namespace detail
+{
+
+/*!
+\brief The solution of the inverse problem of geodesics on latlong coordinates,
+ Forsyth-Andoyer-Lambert type approximation with second order terms.
+\author See
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965
+ http://www.dtic.mil/docs/citations/AD0627893
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970
+ http://www.dtic.mil/docs/citations/AD703541
+*/
+template <typename CT, bool EnableDistance, bool EnableAzimuth>
+struct thomas_inverse
+{
+ typedef result_inverse<CT> result_type;
+
+ template <typename T1, typename T2, typename Spheroid>
+ static inline result_type apply(T1 const& lon1,
+ T1 const& lat1,
+ T2 const& lon2,
+ T2 const& lat2,
+ Spheroid const& spheroid)
+ {
+ result_type result;
+
+ // coordinates in radians
+
+ if ( math::equals(lon1, lon2)
+ && math::equals(lat1, lat2) )
+ {
+ result.set(CT(0), CT(0));
+ return result;
+ }
+
+ CT const f = detail::flattening<CT>(spheroid);
+ CT const one_minus_f = CT(1) - f;
+
+// CT const tan_theta1 = one_minus_f * tan(lat1);
+// CT const tan_theta2 = one_minus_f * tan(lat2);
+// CT const theta1 = atan(tan_theta1);
+// CT const theta2 = atan(tan_theta2);
+
+ CT const pi_half = math::pi<CT>() / CT(2);
+ CT const theta1 = math::equals(lat1, pi_half) ? lat1 :
+ math::equals(lat1, -pi_half) ? lat1 :
+ atan(one_minus_f * tan(lat1));
+ CT const theta2 = math::equals(lat2, pi_half) ? lat2 :
+ math::equals(lat2, -pi_half) ? lat2 :
+ atan(one_minus_f * tan(lat2));
+
+ CT const theta_m = (theta1 + theta2) / CT(2);
+ CT const d_theta_m = (theta2 - theta1) / CT(2);
+ CT const d_lambda = lon2 - lon1;
+ CT const d_lambda_m = d_lambda / CT(2);
+
+ CT const sin_theta_m = sin(theta_m);
+ CT const cos_theta_m = cos(theta_m);
+ CT const sin_d_theta_m = sin(d_theta_m);
+ CT const cos_d_theta_m = cos(d_theta_m);
+ CT const sin2_theta_m = math::sqr(sin_theta_m);
+ CT const cos2_theta_m = math::sqr(cos_theta_m);
+ CT const sin2_d_theta_m = math::sqr(sin_d_theta_m);
+ CT const cos2_d_theta_m = math::sqr(cos_d_theta_m);
+ CT const sin_d_lambda_m = sin(d_lambda_m);
+ CT const sin2_d_lambda_m = math::sqr(sin_d_lambda_m);
+
+ CT const H = cos2_theta_m - sin2_d_theta_m;
+ CT const L = sin2_d_theta_m + H * sin2_d_lambda_m;
+ CT const cos_d = CT(1) - CT(2) * L;
+ CT const d = acos(cos_d);
+ CT const sin_d = sin(d);
+
+ CT const one_minus_L = CT(1) - L;
+
+ if ( math::equals(sin_d, CT(0))
+ || math::equals(L, CT(0))
+ || math::equals(one_minus_L, CT(0)) )
+ {
+ result.set(CT(0), CT(0));
+ return result;
+ }
+
+ CT const U = CT(2) * sin2_theta_m * cos2_d_theta_m / one_minus_L;
+ CT const V = CT(2) * sin2_d_theta_m * cos2_theta_m / L;
+ CT const X = U + V;
+ CT const Y = U - V;
+ CT const T = d / sin_d;
+ //CT const D = CT(4) * math::sqr(T);
+ //CT const E = CT(2) * cos_d;
+ //CT const A = D * E;
+ //CT const B = CT(2) * D;
+ //CT const C = T - (A - E) / CT(2);
+
+ if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
+ {
+ //CT const n1 = X * (A + C*X);
+ //CT const n2 = Y * (B + E*Y);
+ //CT const n3 = D*X*Y;
+
+ //CT const f_sqr = math::sqr(f);
+ //CT const f_sqr_per_64 = f_sqr / CT(64);
+
+ CT const delta1d = f * (T*X-Y) / CT(4);
+ //CT const delta2d = f_sqr_per_64 * (n1 - n2 + n3);
+
+ CT const a = get_radius<0>(spheroid);
+
+ result.distance = a * sin_d * (T - delta1d);
+ //double S2 = a * sin_d * (T - delta1d + delta2d);
+ }
+ else
+ {
+ result.distance = CT(0);
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
+ {
+ // NOTE: if both cos_latX == 0 then below we'd have 0 * INF
+ // it's a situation when the endpoints are on the poles +-90 deg
+ // in this case the azimuth could either be 0 or +-pi
+ // but above always 0 is returned
+
+ // may also be used to calculate distance21
+ //CT const D = CT(4) * math::sqr(T);
+ CT const E = CT(2) * cos_d;
+ //CT const A = D * E;
+ //CT const B = CT(2) * D;
+ // may also be used to calculate distance21
+ CT const f_sqr = math::sqr(f);
+ CT const f_sqr_per_64 = f_sqr / CT(64);
+
+ CT const F = CT(2)*Y-E*(CT(4)-X);
+ //CT const M = CT(32)*T-(CT(20)*T-A)*X-(B+CT(4))*Y;
+ CT const G = f*T/CT(2) + f_sqr_per_64;
+ CT const tan_d_lambda = tan(d_lambda);
+ CT const Q = -(F*G*tan_d_lambda) / CT(4);
+
+ CT const d_lambda_p = (d_lambda + Q) / CT(2);
+ CT const tan_d_lambda_p = tan(d_lambda_p);
+
+ CT const v = atan2(cos_d_theta_m, sin_theta_m * tan_d_lambda_p);
+ CT const u = atan2(-sin_d_theta_m, cos_theta_m * tan_d_lambda_p);
+
+ CT const pi = math::pi<CT>();
+ CT alpha1 = v + u;
+ if ( alpha1 > pi )
+ {
+ alpha1 -= CT(2) * pi;
+ }
+
+ result.azimuth = alpha1;
+ }
+ else
+ {
+ result.azimuth = CT(0);
+ }
+
+ return result;
+ }
+};
+
+}}} // namespace boost::geometry::detail
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
index 21f5fe40b7..2f82e1a8bd 100644
--- a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
+++ b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -12,7 +17,7 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
#include <boost/geometry/core/exception.hpp>
-#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
// BSG 2012-02-06: we use this currently only for distance.
// For other scalar results area,length,perimeter it is commented on purpose.
@@ -39,7 +44,7 @@ template <typename Geometry>
inline void throw_on_empty_input(Geometry const& geometry)
{
#if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)
- if (geometry::num_points(geometry) == 0)
+ if (geometry::is_empty(geometry))
{
throw empty_input_exception();
}
diff --git a/boost/geometry/algorithms/detail/turns/compare_turns.hpp b/boost/geometry/algorithms/detail/turns/compare_turns.hpp
index c29d5863b7..ec383bf103 100644
--- a/boost/geometry/algorithms/detail/turns/compare_turns.hpp
+++ b/boost/geometry/algorithms/detail/turns/compare_turns.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -30,7 +30,7 @@ namespace detail { namespace turns
// seg_id -> fraction -> other_id -> operation
template
<
- typename IdLess = std::less<signed_index_type>,
+ typename IdLess = std::less<signed_size_type>,
int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0,
std::size_t OpId = 0
>
@@ -85,10 +85,14 @@ struct less_seg_fraction_other_op
template <typename Turn>
static inline bool use_fraction(Turn const& left, Turn const& right)
{
- return left.operations[OpId].fraction < right.operations[OpId].fraction
- || ( geometry::math::equals(left.operations[OpId].fraction, right.operations[OpId].fraction)
- && use_other_id(left, right)
- );
+ return
+ geometry::math::equals(left.operations[OpId].fraction,
+ right.operations[OpId].fraction)
+ ?
+ use_other_id(left, right)
+ :
+ (left.operations[OpId].fraction < right.operations[OpId].fraction)
+ ;
}
template <typename Turn>
diff --git a/boost/geometry/algorithms/detail/turns/print_turns.hpp b/boost/geometry/algorithms/detail/turns/print_turns.hpp
index 9d4e45c41f..1e9b9df409 100644
--- a/boost/geometry/algorithms/detail/turns/print_turns.hpp
+++ b/boost/geometry/algorithms/detail/turns/print_turns.hpp
@@ -56,7 +56,7 @@ struct turn_printer
<<": seg: " << turn.operations[0].seg_id.source_index
<< ", m: " << turn.operations[0].seg_id.multi_index
<< ", r: " << turn.operations[0].seg_id.ring_index
- << ", s: " << turn.operations[0].seg_id.segment_index << ", ";
+ << ", s: " << turn.operations[0].seg_id.segment_index;
out << ", fr: " << fraction[0];
out << ", col?: " << turn.operations[0].is_collinear;
out << ' ' << geometry::dsv(turn.point) << ' ';
@@ -70,7 +70,7 @@ struct turn_printer
<< ": seg: " << turn.operations[1].seg_id.source_index
<< ", m: " << turn.operations[1].seg_id.multi_index
<< ", r: " << turn.operations[1].seg_id.ring_index
- << ", s: " << turn.operations[1].seg_id.segment_index << ", ";
+ << ", s: " << turn.operations[1].seg_id.segment_index;
out << ", fr: " << fraction[1];
out << ", col?: " << turn.operations[1].is_collinear;
out << ' ' << geometry::dsv(turn.point) << ' ';
diff --git a/boost/geometry/algorithms/detail/vincenty_direct.hpp b/boost/geometry/algorithms/detail/vincenty_direct.hpp
index 775687cfdb..1c47a0f68d 100644
--- a/boost/geometry/algorithms/detail/vincenty_direct.hpp
+++ b/boost/geometry/algorithms/detail/vincenty_direct.hpp
@@ -33,6 +33,18 @@
namespace boost { namespace geometry { namespace detail
{
+template <typename T>
+struct result_direct
+{
+ void set(T const& lo2, T const& la2)
+ {
+ lon2 = lo2;
+ lat2 = la2;
+ }
+ T lon2;
+ T lat2;
+};
+
/*!
\brief The solution of the direct problem of geodesics on latlong coordinates, after Vincenty, 1975
\author See
@@ -45,45 +57,49 @@ namespace boost { namespace geometry { namespace detail
*/
template <typename CT>
-class vincenty_direct
+struct vincenty_direct
{
+ typedef result_direct<CT> result_type;
+
public:
template <typename T, typename Dist, typename Azi, typename Spheroid>
- vincenty_direct(T const& lo1,
- T const& la1,
- Dist const& distance,
- Azi const& azimuth12,
- Spheroid const& spheroid)
- : lon1(lo1)
- , lat1(la1)
- , is_distance_zero(false)
+ static inline result_type apply(T const& lo1,
+ T const& la1,
+ Dist const& distance,
+ Azi const& azimuth12,
+ Spheroid const& spheroid)
{
+ result_type result;
+
+ CT const lon1 = lo1;
+ CT const lat1 = la1;
+
if ( math::equals(distance, Dist(0)) || distance < Dist(0) )
{
- is_distance_zero = true;
- return;
+ result.set(lon1, lat1);
+ return result;
}
CT const radius_a = CT(get_radius<0>(spheroid));
CT const radius_b = CT(get_radius<2>(spheroid));
- flattening = geometry::detail::flattening<CT>(spheroid);
+ CT const flattening = geometry::detail::flattening<CT>(spheroid);
- sin_azimuth12 = sin(azimuth12);
- cos_azimuth12 = cos(azimuth12);
+ CT const sin_azimuth12 = sin(azimuth12);
+ CT const cos_azimuth12 = cos(azimuth12);
// U: reduced latitude, defined by tan U = (1-f) tan phi
- one_min_f = CT(1) - flattening;
+ CT const one_min_f = CT(1) - flattening;
CT const tan_U1 = one_min_f * tan(lat1);
CT const sigma1 = atan2(tan_U1, cos_azimuth12); // (1)
// may be calculated from tan using 1 sqrt()
CT const U1 = atan(tan_U1);
- sin_U1 = sin(U1);
- cos_U1 = cos(U1);
+ CT const sin_U1 = sin(U1);
+ CT const cos_U1 = cos(U1);
- sin_alpha = cos_U1 * sin_azimuth12; // (2)
- sin_alpha_sqr = math::sqr(sin_alpha);
- cos_alpha_sqr = CT(1) - sin_alpha_sqr;
+ CT const sin_alpha = cos_U1 * sin_azimuth12; // (2)
+ CT const sin_alpha_sqr = math::sqr(sin_alpha);
+ CT const cos_alpha_sqr = CT(1) - sin_alpha_sqr;
CT const b_sqr = radius_b * radius_b;
CT const u_sqr = cos_alpha_sqr * (radius_a * radius_a - b_sqr) / b_sqr;
@@ -91,9 +107,13 @@ public:
CT const B = (u_sqr/CT(1024))*(CT(256) + u_sqr*(CT(-128) + u_sqr*(CT(74) - u_sqr*CT(47)))); // (4)
CT s_div_bA = distance / (radius_b * A);
- sigma = s_div_bA; // (7)
+ CT sigma = s_div_bA; // (7)
CT previous_sigma;
+ CT sin_sigma;
+ CT cos_sigma;
+ CT cos_2sigma_m;
+ CT cos_2sigma_m_sqr;
int counter = 0; // robustness
@@ -120,35 +140,27 @@ public:
} while ( geometry::math::abs(previous_sigma - sigma) > CT(1e-12)
//&& geometry::math::abs(sigma) < pi
&& counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness
- }
- inline CT lat2() const
- {
- if ( is_distance_zero )
{
- return lat1;
+ result.lat2
+ = atan2( sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_azimuth12,
+ one_min_f * math::sqrt(sin_alpha_sqr + math::sqr(sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12))); // (8)
}
- return atan2( sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_azimuth12,
- one_min_f * math::sqrt(sin_alpha_sqr + math::sqr(sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12))); // (8)
- }
-
- inline CT lon2() const
- {
- if ( is_distance_zero )
{
- return lon1;
- }
+ CT const lambda = atan2( sin_sigma * sin_azimuth12,
+ cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_azimuth12); // (9)
+ CT const C = (flattening/CT(16)) * cos_alpha_sqr * ( CT(4) + flattening * ( CT(4) - CT(3) * cos_alpha_sqr ) ); // (10)
+ CT const L = lambda - (CT(1) - C) * flattening * sin_alpha
+ * ( sigma + C * sin_sigma * ( cos_2sigma_m + C * cos_sigma * ( CT(-1) + CT(2) * cos_2sigma_m_sqr ) ) ); // (11)
- CT const lambda = atan2( sin_sigma * sin_azimuth12,
- cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_azimuth12); // (9)
- CT const C = (flattening/CT(16)) * cos_alpha_sqr * ( CT(4) + flattening * ( CT(4) - CT(3) * cos_alpha_sqr ) ); // (10)
- CT const L = lambda - (CT(1) - C) * flattening * sin_alpha
- * ( sigma + C * sin_sigma * ( cos_2sigma_m + C * cos_sigma * ( CT(-1) + CT(2) * cos_2sigma_m_sqr ) ) ); // (11)
+ result.lon2 = lon1 + L;
+ }
- return lon1 + L;
+ return result;
}
+ /*
inline CT azimuth21() const
{
// NOTE: signs of X and Y are different than in the original paper
@@ -156,32 +168,7 @@ public:
CT(0) :
atan2(-sin_alpha, sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12); // (12)
}
-
-private:
- CT sigma;
- CT sin_sigma;
- CT cos_sigma;
-
- CT cos_2sigma_m;
- CT cos_2sigma_m_sqr;
-
- CT sin_alpha;
- CT sin_alpha_sqr;
- CT cos_alpha_sqr;
-
- CT sin_azimuth12;
- CT cos_azimuth12;
-
- CT sin_U1;
- CT cos_U1;
-
- CT flattening;
- CT one_min_f;
-
- CT const lon1;
- CT const lat1;
-
- bool is_distance_zero;
+ */
};
}}} // namespace boost::geometry::detail
diff --git a/boost/geometry/algorithms/detail/vincenty_inverse.hpp b/boost/geometry/algorithms/detail/vincenty_inverse.hpp
index 861452af00..fe05e95932 100644
--- a/boost/geometry/algorithms/detail/vincenty_inverse.hpp
+++ b/boost/geometry/algorithms/detail/vincenty_inverse.hpp
@@ -20,9 +20,11 @@
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/srs.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/flattening.hpp>
+#include <boost/geometry/algorithms/detail/result_inverse.hpp>
#ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS
@@ -44,22 +46,25 @@ namespace boost { namespace geometry { namespace detail
- http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
*/
-template <typename CT>
-class vincenty_inverse
+template <typename CT, bool EnableDistance, bool EnableAzimuth>
+struct vincenty_inverse
{
+ typedef result_inverse<CT> result_type;
+
public:
template <typename T1, typename T2, typename Spheroid>
- vincenty_inverse(T1 const& lon1,
- T1 const& lat1,
- T2 const& lon2,
- T2 const& lat2,
- Spheroid const& spheroid)
- : is_result_zero(false)
+ static inline result_type apply(T1 const& lon1,
+ T1 const& lat1,
+ T2 const& lon2,
+ T2 const& lat2,
+ Spheroid const& spheroid)
{
+ result_type result;
+
if (math::equals(lat1, lat2) && math::equals(lon1, lon2))
{
- is_result_zero = true;
- return;
+ result.set(CT(0), CT(0));
+ return result;
}
CT const c1 = 1;
@@ -79,8 +84,8 @@ public:
if (L < -pi) L += two_pi;
if (L > pi) L -= two_pi;
- radius_a = CT(get_radius<0>(spheroid));
- radius_b = CT(get_radius<2>(spheroid));
+ 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);
// U: reduced latitude, defined by tan U = (1-f) tan phi
@@ -92,11 +97,11 @@ public:
CT const temp_den_U1 = math::sqrt(c1 + math::sqr(tan_U1));
CT const temp_den_U2 = math::sqrt(c1 + math::sqr(tan_U2));
// cos = 1 / sqrt(1 + tan^2)
- cos_U1 = c1 / temp_den_U1;
- cos_U2 = c1 / temp_den_U2;
+ CT const cos_U1 = c1 / temp_den_U1;
+ CT const cos_U2 = c1 / temp_den_U2;
// sin = tan / sqrt(1 + tan^2)
- sin_U1 = tan_U1 / temp_den_U1;
- sin_U2 = tan_U2 / temp_den_U2;
+ CT const sin_U1 = tan_U1 / temp_den_U1;
+ CT const sin_U2 = tan_U2 / temp_den_U2;
// calculate sin U and cos U directly
//CT const U1 = atan(tan_U1);
@@ -107,6 +112,13 @@ public:
//sin_U2 = tan_U2 * cos_U2; // sin(U2);
CT previous_lambda;
+ CT sin_lambda;
+ CT cos_lambda;
+ CT sin_sigma;
+ CT sin_alpha;
+ CT cos2_alpha;
+ CT cos2_sigma_m;
+ CT sigma;
int counter = 0; // robustness
@@ -131,85 +143,59 @@ public:
} while ( geometry::math::abs(previous_lambda - lambda) > c_e_12
&& geometry::math::abs(lambda) < pi
&& counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness
- }
-
- inline CT distance() const
- {
- if ( is_result_zero )
+
+ if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
{
- return CT(0);
+ // Oops getting hard here
+ // (again, problem is that ttmath cannot divide by doubles, which is OK)
+ CT const c1 = 1;
+ CT const c2 = 2;
+ CT const c3 = 3;
+ CT const c4 = 4;
+ CT const c6 = 6;
+ CT const c47 = 47;
+ CT const c74 = 74;
+ CT const c128 = 128;
+ CT const c256 = 256;
+ CT const c175 = 175;
+ CT const c320 = 320;
+ CT const c768 = 768;
+ CT const c1024 = 1024;
+ CT const c4096 = 4096;
+ CT const c16384 = 16384;
+
+ //CT sqr_u = cos2_alpha * (math::sqr(radius_a) - math::sqr(radius_b)) / math::sqr(radius_b); // above (1)
+ CT sqr_u = cos2_alpha * ( math::sqr(radius_a / radius_b) - c1 ); // above (1)
+
+ 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)
+
+ result.distance = radius_b * A * (sigma - delta_sigma); // (19)
+ }
+ else
+ {
+ result.distance = CT(0);
+ }
+
+ if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
+ {
+ result.azimuth = atan2(cos_U2 * sin_lambda, cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); // (20)
+ }
+ else
+ {
+ result.azimuth = CT(0);
}
- // Oops getting hard here
- // (again, problem is that ttmath cannot divide by doubles, which is OK)
- CT const c1 = 1;
- CT const c2 = 2;
- CT const c3 = 3;
- CT const c4 = 4;
- CT const c6 = 6;
- CT const c47 = 47;
- CT const c74 = 74;
- CT const c128 = 128;
- CT const c256 = 256;
- CT const c175 = 175;
- CT const c320 = 320;
- CT const c768 = 768;
- CT const c1024 = 1024;
- CT const c4096 = 4096;
- CT const c16384 = 16384;
-
- //CT sqr_u = cos2_alpha * (math::sqr(radius_a) - math::sqr(radius_b)) / math::sqr(radius_b); // above (1)
- CT sqr_u = cos2_alpha * ( math::sqr(radius_a / radius_b) - c1 ); // above (1)
-
- 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)
-
- return radius_b * A * (sigma - delta_sigma); // (19)
- }
-
- inline CT azimuth12() const
- {
- return is_result_zero ?
- CT(0) :
- atan2(cos_U2 * sin_lambda, cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); // (20)
- }
-
- inline CT azimuth21() const
- {
- // NOTE: signs of X and Y are different than in the original paper
- return is_result_zero ?
- CT(0) :
- atan2(-cos_U1 * sin_lambda, sin_U1 * cos_U2 - cos_U1 * sin_U2 * cos_lambda); // (21)
+ return result;
}
-private:
- // alpha: azimuth of the geodesic at the equator
- CT cos2_alpha;
- CT sin_alpha;
-
- // sigma: angular distance p1,p2 on the sphere
- // sigma1: angular distance on the sphere from the equator to p1
- // sigma_m: angular distance on the sphere from the equator to the midpoint of the line
- CT sigma;
- CT sin_sigma;
- CT cos2_sigma_m;
-
- CT sin_lambda;
- CT cos_lambda;
-
- // set only once
- CT cos_U1;
- CT cos_U2;
- CT sin_U1;
- CT sin_U2;
-
- // set only once
- CT radius_a;
- CT radius_b;
-
- bool is_result_zero;
+// inline CT azimuth21() const
+// {
+// // NOTE: signs of X and Y are different than in the original paper
+// atan2(-cos_U1 * sin_lambda, sin_U1 * cos_U2 - cos_U1 * sin_U2 * cos_lambda); // (21)
+// }
};
}}} // namespace boost::geometry::detail
diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
index e7486f0e45..68e74a8c5c 100644
--- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
@@ -20,13 +20,15 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP
-#include <boost/assert.hpp>
+
#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
+#include <boost/geometry/core/assert.hpp>
+
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
@@ -53,7 +55,7 @@ inline int check_result_type(int result)
template <typename T>
inline T check_result_type(T result)
{
- BOOST_ASSERT(false);
+ BOOST_GEOMETRY_ASSERT(false);
return result;
}
@@ -291,7 +293,7 @@ struct point_in_geometry<Geometry, multi_point_tag>
{
int pip = point_in_geometry<point_type>::apply(point, *it, strategy);
- //BOOST_ASSERT(pip != 0);
+ //BOOST_GEOMETRY_ASSERT(pip != 0);
if ( pip > 0 ) // inside
return 1;
}
diff --git a/boost/geometry/algorithms/dispatch/envelope.hpp b/boost/geometry/algorithms/dispatch/envelope.hpp
new file mode 100644
index 0000000000..bb8a99f5a8
--- /dev/null
+++ b/boost/geometry/algorithms/dispatch/envelope.hpp
@@ -0,0 +1,49 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tag.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type,
+ typename CS_Tag = typename cs_tag<Geometry>::type
+>
+struct envelope : not_implemented<Tag>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP
diff --git a/boost/geometry/algorithms/dispatch/expand.hpp b/boost/geometry/algorithms/dispatch/expand.hpp
new file mode 100644
index 0000000000..2c23d6a1ce
--- /dev/null
+++ b/boost/geometry/algorithms/dispatch/expand.hpp
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tag.hpp>
+
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/policies/compare.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryOut, typename Geometry,
+ typename StrategyLess = strategy::compare::default_strategy,
+ typename StrategyGreater = strategy::compare::default_strategy,
+ typename TagOut = typename tag<GeometryOut>::type,
+ typename Tag = typename tag<Geometry>::type,
+ typename CSTagOut = typename cs_tag<GeometryOut>::type,
+ typename CSTag = typename cs_tag<Geometry>::type
+>
+struct expand : not_implemented<TagOut, Tag>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP
diff --git a/boost/geometry/algorithms/envelope.hpp b/boost/geometry/algorithms/envelope.hpp
index bd1ea9cb7a..00981224b2 100644
--- a/boost/geometry/algorithms/envelope.hpp
+++ b/boost/geometry/algorithms/envelope.hpp
@@ -1,295 +1,25 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
-#include <vector>
-
-#include <boost/numeric/conversion/cast.hpp>
-#include <boost/range.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/assign.hpp>
-#include <boost/geometry/algorithms/expand.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/exterior_ring.hpp>
-#include <boost/geometry/core/point_type.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-#include <boost/geometry/geometries/concepts/check.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace envelope
-{
-
-
-/// Calculate envelope of an 2D or 3D segment
-struct envelope_expand_one
-{
- template<typename Geometry, typename Box>
- static inline void apply(Geometry const& geometry, Box& mbr)
- {
- assign_inverse(mbr);
- geometry::expand(mbr, geometry);
- }
-};
-
-
-/// Iterate through range (also used in multi*)
-template<typename Range, typename Box>
-inline void envelope_range_additional(Range const& range, Box& mbr)
-{
- typedef typename boost::range_iterator<Range const>::type iterator_type;
-
- for (iterator_type it = boost::begin(range);
- it != boost::end(range);
- ++it)
- {
- geometry::expand(mbr, *it);
- }
-}
-
-
-
-/// Generic range dispatching struct
-struct envelope_range
-{
- /// Calculate envelope of range using a strategy
- template <typename Range, typename Box>
- static inline void apply(Range const& range, Box& mbr)
- {
- assign_inverse(mbr);
- envelope_range_additional(range, mbr);
- }
-};
-
-
-struct envelope_multi_linestring
-{
- template<typename MultiLinestring, typename Box>
- static inline void apply(MultiLinestring const& mp, Box& mbr)
- {
- assign_inverse(mbr);
- for (typename boost::range_iterator<MultiLinestring const>::type
- it = mp.begin();
- it != mp.end();
- ++it)
- {
- envelope_range_additional(*it, mbr);
- }
- }
-};
-
-
-// version for multi_polygon: outer ring's of all polygons
-struct envelope_multi_polygon
-{
- template<typename MultiPolygon, typename Box>
- static inline void apply(MultiPolygon const& mp, Box& mbr)
- {
- assign_inverse(mbr);
- for (typename boost::range_const_iterator<MultiPolygon>::type
- it = mp.begin();
- it != mp.end();
- ++it)
- {
- envelope_range_additional(exterior_ring(*it), mbr);
- }
- }
-};
-
-
-}} // namespace detail::envelope
-#endif // DOXYGEN_NO_DETAIL
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-
-template
-<
- typename Geometry,
- typename Tag = typename tag<Geometry>::type
->
-struct envelope: not_implemented<Tag>
-{};
-
-
-template <typename Point>
-struct envelope<Point, point_tag>
- : detail::envelope::envelope_expand_one
-{};
-
-
-template <typename Box>
-struct envelope<Box, box_tag>
- : detail::envelope::envelope_expand_one
-{};
-
-
-template <typename Segment>
-struct envelope<Segment, segment_tag>
- : detail::envelope::envelope_expand_one
-{};
-
-
-template <typename Linestring>
-struct envelope<Linestring, linestring_tag>
- : detail::envelope::envelope_range
-{};
-
-
-template <typename Ring>
-struct envelope<Ring, ring_tag>
- : detail::envelope::envelope_range
-{};
-
-
-template <typename Polygon>
-struct envelope<Polygon, polygon_tag>
- : detail::envelope::envelope_range
-{
- template <typename Box>
- static inline void apply(Polygon const& poly, Box& mbr)
- {
- // For polygon, inspecting outer ring is sufficient
- detail::envelope::envelope_range::apply(exterior_ring(poly), mbr);
- }
-
-};
-
-
-template <typename Multi>
-struct envelope<Multi, multi_point_tag>
- : detail::envelope::envelope_range
-{};
-
-
-template <typename Multi>
-struct envelope<Multi, multi_linestring_tag>
- : detail::envelope::envelope_multi_linestring
-{};
-
-
-template <typename Multi>
-struct envelope<Multi, multi_polygon_tag>
- : detail::envelope::envelope_multi_polygon
-{};
-
-
-} // namespace dispatch
-#endif
-
-
-namespace resolve_variant {
-
-template <typename Geometry>
-struct envelope
-{
- template <typename Box>
- static inline void apply(Geometry const& geometry, Box& box)
- {
- concept::check<Geometry const>();
- concept::check<Box>();
-
- dispatch::envelope<Geometry>::apply(geometry, box);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- template <typename Box>
- struct visitor: boost::static_visitor<void>
- {
- Box& m_box;
-
- visitor(Box& box): m_box(box) {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
- {
- envelope<Geometry>::apply(geometry, m_box);
- }
- };
-
- template <typename Box>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Box& box)
- {
- boost::apply_visitor(visitor<Box>(box), geometry);
- }
-};
-
-} // namespace resolve_variant
-
-
-/*!
-\brief \brief_calc{envelope}
-\ingroup envelope
-\details \details_calc{envelope,\det_envelope}.
-\tparam Geometry \tparam_geometry
-\tparam Box \tparam_box
-\param geometry \param_geometry
-\param mbr \param_box \param_set{envelope}
-
-\qbk{[include reference/algorithms/envelope.qbk]}
-\qbk{
-[heading Example]
-[envelope] [envelope_output]
-}
-*/
-template<typename Geometry, typename Box>
-inline void envelope(Geometry const& geometry, Box& mbr)
-{
- resolve_variant::envelope<Geometry>::apply(geometry, 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}
-
-\qbk{[include reference/algorithms/envelope.qbk]}
-\qbk{
-[heading Example]
-[return_envelope] [return_envelope_output]
-}
-*/
-template<typename Box, typename Geometry>
-inline Box return_envelope(Geometry const& geometry)
-{
- Box mbr;
- resolve_variant::envelope<Geometry>::apply(geometry, mbr);
- return mbr;
-}
-
-}} // namespace boost::geometry
+#include <boost/geometry/algorithms/detail/envelope/interface.hpp>
+#include <boost/geometry/algorithms/detail/envelope/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp
index 7c709c808d..0f0bdde584 100644
--- a/boost/geometry/algorithms/equals.hpp
+++ b/boost/geometry/algorithms/equals.hpp
@@ -51,7 +51,8 @@
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
@@ -181,9 +182,9 @@ struct equals_by_collection
template<typename Geometry1, typename Geometry2>
struct equals_by_relate
- : detail::relate::relate_base
+ : detail::relate::relate_impl
<
- detail::relate::static_mask_equals_type,
+ detail::de9im::static_mask_equals_type,
Geometry1,
Geometry2
>
@@ -371,7 +372,7 @@ struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Geometry2 const& geometry2
)
{
- return apply_visitor(visitor(geometry2), geometry1);
+ return boost::apply_visitor(visitor(geometry2), geometry1);
}
};
@@ -400,7 +401,7 @@ struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2
)
{
- return apply_visitor(visitor(geometry1), geometry2);
+ return boost::apply_visitor(visitor(geometry1), geometry2);
}
};
@@ -430,7 +431,7 @@ struct equals<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2
)
{
- return apply_visitor(visitor(), geometry1, geometry2);
+ return boost::apply_visitor(visitor(), geometry1, geometry2);
}
};
diff --git a/boost/geometry/algorithms/expand.hpp b/boost/geometry/algorithms/expand.hpp
index 9dc0a48e06..f41df53801 100644
--- a/boost/geometry/algorithms/expand.hpp
+++ b/boost/geometry/algorithms/expand.hpp
@@ -1,348 +1,26 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
+// 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 Samuel Debionne, Grenoble, France.
+
+// 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
#define BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
-
-#include <cstddef>
-
-#include <boost/numeric/conversion/cast.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/geometries/concepts/check.hpp>
-
-#include <boost/geometry/util/select_coordinate_type.hpp>
-
-#include <boost/geometry/strategies/compare.hpp>
-#include <boost/geometry/policies/compare.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace expand
-{
-
-
-template
-<
- typename StrategyLess, typename StrategyGreater,
- std::size_t Dimension, std::size_t DimensionCount
->
-struct point_loop
-{
- template <typename Box, typename Point>
- static inline void apply(Box& box, Point const& source)
- {
- typedef typename strategy::compare::detail::select_strategy
- <
- StrategyLess, 1, Point, Dimension
- >::type less_type;
-
- typedef typename strategy::compare::detail::select_strategy
- <
- StrategyGreater, -1, Point, Dimension
- >::type greater_type;
-
- typedef typename select_coordinate_type<Point, Box>::type coordinate_type;
-
- less_type less;
- greater_type greater;
-
- coordinate_type const coord = get<Dimension>(source);
-
- if (less(coord, get<min_corner, Dimension>(box)))
- {
- set<min_corner, Dimension>(box, coord);
- }
-
- if (greater(coord, get<max_corner, Dimension>(box)))
- {
- set<max_corner, Dimension>(box, coord);
- }
-
- point_loop
- <
- StrategyLess, StrategyGreater,
- Dimension + 1, DimensionCount
- >::apply(box, source);
- }
-};
-
-
-template
-<
- 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 StrategyLess, typename StrategyGreater,
- std::size_t Index,
- std::size_t Dimension, std::size_t DimensionCount
->
-struct indexed_loop
-{
- template <typename Box, typename Geometry>
- static inline void apply(Box& box, Geometry const& source)
- {
- typedef typename strategy::compare::detail::select_strategy
- <
- StrategyLess, 1, Box, Dimension
- >::type less_type;
-
- typedef typename strategy::compare::detail::select_strategy
- <
- StrategyGreater, -1, Box, Dimension
- >::type greater_type;
-
- typedef typename select_coordinate_type
- <
- Box,
- Geometry
- >::type coordinate_type;
-
- less_type less;
- greater_type greater;
-
- coordinate_type const coord = get<Index, Dimension>(source);
-
- if (less(coord, get<min_corner, Dimension>(box)))
- {
- set<min_corner, Dimension>(box, coord);
- }
-
- if (greater(coord, get<max_corner, Dimension>(box)))
- {
- set<max_corner, Dimension>(box, coord);
- }
-
- indexed_loop
- <
- StrategyLess, StrategyGreater,
- Index, Dimension + 1, DimensionCount
- >::apply(box, source);
- }
-};
-
-
-template
-<
- typename StrategyLess, typename StrategyGreater,
- std::size_t Index, std::size_t DimensionCount
->
-struct indexed_loop
- <
- StrategyLess, StrategyGreater,
- Index, DimensionCount, DimensionCount
- >
-{
- template <typename Box, typename Geometry>
- static inline void apply(Box&, Geometry const&) {}
-};
-
-
-
-// Changes a box such that the other box is also contained by the box
-template
-<
- typename StrategyLess, typename StrategyGreater
->
-struct expand_indexed
-{
- template <typename Box, typename Geometry>
- static inline void apply(Box& box, Geometry const& geometry)
- {
- indexed_loop
- <
- StrategyLess, StrategyGreater,
- 0, 0, dimension<Geometry>::type::value
- >::apply(box, geometry);
-
- indexed_loop
- <
- StrategyLess, StrategyGreater,
- 1, 0, dimension<Geometry>::type::value
- >::apply(box, geometry);
- }
-};
-
-}} // namespace detail::expand
-#endif // DOXYGEN_NO_DETAIL
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-template
-<
- typename GeometryOut, typename Geometry,
- typename StrategyLess = strategy::compare::default_strategy,
- typename StrategyGreater = strategy::compare::default_strategy,
- typename TagOut = typename tag<GeometryOut>::type,
- typename Tag = typename tag<Geometry>::type
->
-struct expand: not_implemented<TagOut, Tag>
-{};
-
-
-// Box + point -> new box containing also point
-template
-<
- typename BoxOut, typename Point,
- typename StrategyLess, typename StrategyGreater
->
-struct expand<BoxOut, Point, StrategyLess, StrategyGreater, box_tag, point_tag>
- : detail::expand::point_loop
- <
- StrategyLess, StrategyGreater,
- 0, dimension<Point>::type::value
- >
-{};
-
-
-// Box + box -> new box containing two input boxes
-template
-<
- typename BoxOut, typename BoxIn,
- typename StrategyLess, typename StrategyGreater
->
-struct expand<BoxOut, BoxIn, StrategyLess, StrategyGreater, box_tag, box_tag>
- : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
-{};
-
-template
-<
- typename Box, typename Segment,
- typename StrategyLess, typename StrategyGreater
->
-struct expand<Box, Segment, StrategyLess, StrategyGreater, box_tag, segment_tag>
- : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
-{};
-
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-
-namespace resolve_variant {
-
-template <typename Geometry>
-struct expand
-{
- template <typename Box>
- static inline void apply(Box& box, Geometry const& geometry)
- {
- concept::check<Box>();
- concept::check<Geometry const>();
- concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
-
- dispatch::expand<Box, Geometry>::apply(box, geometry);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- template <typename Box>
- struct visitor: boost::static_visitor<void>
- {
- Box& m_box;
-
- visitor(Box& box) : m_box(box) {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
- {
- return expand<Geometry>::apply(m_box, geometry);
- }
- };
-
- template <class Box>
- static inline void
- apply(Box& box,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
- {
- return boost::apply_visitor(visitor<Box>(box), geometry);
- }
-};
-
-} // namespace resolve_variant
-
-
-/***
-*!
-\brief Expands a box using the extend (envelope) of another geometry (box, point)
-\ingroup expand
-\tparam Box type of the box
-\tparam Geometry of second geometry, to be expanded with the box
-\param box box to expand another geometry with, might be changed
-\param geometry other geometry
-\param strategy_less
-\param strategy_greater
-\note Strategy is currently ignored
- *
-template
-<
- typename Box, typename Geometry,
- typename StrategyLess, typename StrategyGreater
->
-inline void expand(Box& box, Geometry const& geometry,
- StrategyLess const& strategy_less,
- StrategyGreater const& strategy_greater)
-{
- concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
-
- dispatch::expand<Box, Geometry>::apply(box, geometry);
-}
-***/
-
-
-/*!
-\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
-
-\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);
-}
-
-}} // namespace boost::geometry
+#include <boost/geometry/algorithms/detail/expand/interface.hpp>
+#include <boost/geometry/algorithms/detail/expand/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
diff --git a/boost/geometry/algorithms/is_convex.hpp b/boost/geometry/algorithms/is_convex.hpp
new file mode 100644
index 0000000000..8feb48db6a
--- /dev/null
+++ b/boost/geometry/algorithms/is_convex.hpp
@@ -0,0 +1,160 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
+#include <boost/geometry/views/detail/normalized_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace is_convex
+{
+
+struct ring_is_convex
+{
+ template <typename Ring>
+ static inline bool apply(Ring const& ring)
+ {
+ typedef typename geometry::point_type<Ring>::type point_type;
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<point_type>::type
+ >::type side_strategy_type;
+
+ std::size_t n = boost::size(ring);
+ if (boost::size(ring) < core_detail::closure::minimum_ring_size
+ <
+ geometry::closure<Ring>::value
+ >::value)
+ {
+ // (Too) small rings are considered as non-concave, is convex
+ return true;
+ }
+
+ // Walk in clockwise direction, consider ring as closed
+ // (though closure is not important in this algorithm - any dupped
+ // point is skipped)
+ typedef detail::normalized_view<Ring const> view_type;
+ view_type view(ring);
+
+ typedef geometry::ever_circling_range_iterator<view_type const> it_type;
+ it_type previous(view);
+ it_type current(view);
+ current++;
+
+ std::size_t index = 1;
+ while (equals::equals_point_point(*current, *previous) && index < n)
+ {
+ current++;
+ index++;
+ }
+
+ if (index == n)
+ {
+ // All points are apparently equal
+ return true;
+ }
+
+ it_type next = current;
+ next++;
+ while (equals::equals_point_point(*current, *next))
+ {
+ next++;
+ }
+
+ // We have now three different points on the ring
+ // Walk through all points, use a counter because of the ever-circling
+ // iterator
+ for (std::size_t i = 0; i < n; i++)
+ {
+ int const side = side_strategy_type::apply(*previous, *current, *next);
+ if (side == 1)
+ {
+ // Next is on the left side of clockwise ring:
+ // the piece is not convex
+ return false;
+ }
+
+ previous = current;
+ current = next;
+
+ // Advance next to next different point
+ // (because there are non-equal points, this loop is not infinite)
+ next++;
+ while (equals::equals_point_point(*current, *next))
+ {
+ next++;
+ }
+ }
+ return true;
+ }
+};
+
+
+}} // namespace detail::is_convex
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct is_convex : not_implemented<Tag>
+{};
+
+template <typename Box>
+struct is_convex<Box, box_tag>
+{
+ static inline bool apply(Box const& )
+ {
+ // Any box is convex (TODO: consider spherical boxes)
+ return true;
+ }
+};
+
+template <typename Box>
+struct is_convex<Box, ring_tag> : detail::is_convex::ring_is_convex
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+// TODO: variants
+
+// TODO: documentation / qbk
+template<typename Geometry>
+inline bool is_convex(Geometry const& geometry)
+{
+ return dispatch::is_convex<Geometry>::apply(geometry);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
diff --git a/boost/geometry/algorithms/is_empty.hpp b/boost/geometry/algorithms/is_empty.hpp
new file mode 100644
index 0000000000..02c295eaba
--- /dev/null
+++ b/boost/geometry/algorithms/is_empty.hpp
@@ -0,0 +1,207 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_EMPTY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_IS_EMPTY_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace is_empty
+{
+
+struct always_not_empty
+{
+ template <typename Geometry>
+ static inline bool apply(Geometry const&)
+ {
+ return false;
+ }
+};
+
+struct range_is_empty
+{
+ template <typename Range>
+ static inline bool apply(Range const& range)
+ {
+ return boost::empty(range);
+ }
+};
+
+class polygon_is_empty
+{
+ template <typename InteriorRings>
+ static inline bool check_interior_rings(InteriorRings const& interior_rings)
+ {
+ return check_iterator_range
+ <
+ range_is_empty, true // allow empty range
+ >::apply(boost::begin(interior_rings), boost::end(interior_rings));
+ }
+
+public:
+ template <typename Polygon>
+ static inline bool apply(Polygon const& polygon)
+ {
+ return boost::empty(exterior_ring(polygon))
+ && check_interior_rings(interior_rings(polygon));
+ }
+};
+
+template <typename Policy = range_is_empty>
+struct multi_is_empty
+{
+ template <typename MultiGeometry>
+ static inline bool apply(MultiGeometry const& multigeometry)
+ {
+ return check_iterator_range
+ <
+ Policy, true // allow empty range
+ >::apply(boost::begin(multigeometry), boost::end(multigeometry));
+ }
+
+};
+
+}} // namespace detail::is_empty
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct is_empty : not_implemented<Tag>
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, point_tag>
+ : detail::is_empty::always_not_empty
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, box_tag>
+ : detail::is_empty::always_not_empty
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, segment_tag>
+ : detail::is_empty::always_not_empty
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, linestring_tag>
+ : detail::is_empty::range_is_empty
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, ring_tag>
+ : detail::is_empty::range_is_empty
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, polygon_tag>
+ : detail::is_empty::polygon_is_empty
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, multi_point_tag>
+ : detail::is_empty::range_is_empty
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, multi_linestring_tag>
+ : detail::is_empty::multi_is_empty<>
+{};
+
+template <typename Geometry>
+struct is_empty<Geometry, multi_polygon_tag>
+ : detail::is_empty::multi_is_empty<detail::is_empty::polygon_is_empty>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_variant
+{
+
+template <typename Geometry>
+struct is_empty
+{
+ static inline bool apply(Geometry const& geometry)
+ {
+ concept::check<Geometry const>();
+
+ return dispatch::is_empty<Geometry>::apply(geometry);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct is_empty<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ struct visitor : boost::static_visitor<bool>
+ {
+ template <typename Geometry>
+ inline bool operator()(Geometry const& geometry) const
+ {
+ return is_empty<Geometry>::apply(geometry);
+ }
+ };
+
+ static bool
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ {
+ return boost::apply_visitor(visitor(), geometry);
+ }
+};
+
+} // namespace resolve_variant
+
+
+/*!
+\brief \brief_check{is the empty set}
+\ingroup is_empty
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_check{is the empty set}
+
+\qbk{[include reference/algorithms/is_empty.qbk]}
+*/
+template <typename Geometry>
+inline bool is_empty(Geometry const& geometry)
+{
+ return resolve_variant::is_empty<Geometry>::apply(geometry);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_IS_EMPTY_HPP
diff --git a/boost/geometry/algorithms/length.hpp b/boost/geometry/algorithms/length.hpp
index fad17ade46..58324bcc80 100644
--- a/boost/geometry/algorithms/length.hpp
+++ b/boost/geometry/algorithms/length.hpp
@@ -229,7 +229,7 @@ struct length<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
Strategy const& strategy
)
{
- return apply_visitor(visitor<Strategy>(strategy), geometry);
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
}
};
diff --git a/boost/geometry/algorithms/overlaps.hpp b/boost/geometry/algorithms/overlaps.hpp
index f724a544fd..96310d6cb5 100644
--- a/boost/geometry/algorithms/overlaps.hpp
+++ b/boost/geometry/algorithms/overlaps.hpp
@@ -28,7 +28,8 @@
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
namespace boost { namespace geometry
{
@@ -149,9 +150,9 @@ template
typename Tag2 = typename tag<Geometry2>::type
>
struct overlaps
- : detail::relate::relate_base
+ : detail::relate::relate_impl
<
- detail::relate::static_mask_overlaps_type,
+ detail::de9im::static_mask_overlaps_type,
Geometry1,
Geometry2
>
diff --git a/boost/geometry/algorithms/relate.hpp b/boost/geometry/algorithms/relate.hpp
new file mode 100644
index 0000000000..34733ec596
--- /dev/null
+++ b/boost/geometry/algorithms/relate.hpp
@@ -0,0 +1,17 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 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_ALGORITHMS_RELATE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_RELATE_HPP
+
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_RELATE_HPP
diff --git a/boost/geometry/algorithms/relation.hpp b/boost/geometry/algorithms/relation.hpp
new file mode 100644
index 0000000000..c3cf2f99f8
--- /dev/null
+++ b/boost/geometry/algorithms/relation.hpp
@@ -0,0 +1,17 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 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_ALGORITHMS_RELATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_RELATION_HPP
+
+#include <boost/geometry/algorithms/detail/relation/interface.hpp>
+#include <boost/geometry/algorithms/detail/relation/implementation.hpp>
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_RELATION_HPP
diff --git a/boost/geometry/algorithms/simplify.hpp b/boost/geometry/algorithms/simplify.hpp
index 0047546718..9dd87f61a9 100644
--- a/boost/geometry/algorithms/simplify.hpp
+++ b/boost/geometry/algorithms/simplify.hpp
@@ -491,7 +491,7 @@ inline void simplify(Geometry const& geometry, Geometry& out,
{
concept::check<Geometry>();
- simplify(geometry, out, max_distance, default_strategy());
+ geometry::simplify(geometry, out, max_distance, default_strategy());
}
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp
index de34c9c7b0..6c49ca634c 100644
--- a/boost/geometry/algorithms/sym_difference.hpp
+++ b/boost/geometry/algorithms/sym_difference.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// 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
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -10,9 +15,12 @@
#define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
#include <algorithm>
-
+#include <iterator>
+#include <vector>
#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/geometries/multi_polygon.hpp>
namespace boost { namespace geometry
@@ -23,6 +31,177 @@ namespace detail { namespace sym_difference
{
+template <typename GeometryOut>
+struct compute_difference
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename RobustPolicy,
+ typename OutputIterator,
+ typename Strategy
+ >
+ static inline OutputIterator apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ return geometry::dispatch::intersection_insert
+ <
+ Geometry1,
+ Geometry2,
+ GeometryOut,
+ overlay_difference,
+ geometry::detail::overlay::do_reverse
+ <
+ geometry::point_order<Geometry1>::value
+ >::value,
+ geometry::detail::overlay::do_reverse
+ <
+ geometry::point_order<Geometry2>::value, true
+ >::value
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);
+ }
+};
+
+
+
+template <typename GeometryOut, typename Geometry1, typename Geometry2>
+struct sym_difference_generic
+{
+ template
+ <
+ typename RobustPolicy,
+ typename OutputIterator,
+ typename Strategy
+ >
+ static inline OutputIterator apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ out = compute_difference
+ <
+ GeometryOut
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);
+
+ return compute_difference
+ <
+ GeometryOut
+ >::apply(geometry2, geometry1, robust_policy, out, strategy);
+ }
+};
+
+
+template <typename GeometryOut, typename Areal1, typename Areal2>
+struct sym_difference_areal_areal
+{
+ template
+ <
+ typename RobustPolicy,
+ typename OutputIterator,
+ typename Strategy
+ >
+ static inline OutputIterator apply(Areal1 const& areal1,
+ Areal2 const& areal2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ typedef geometry::model::multi_polygon
+ <
+ GeometryOut
+ > helper_geometry_type;
+
+ helper_geometry_type diff12, diff21;
+
+ std::back_insert_iterator<helper_geometry_type> oit12(diff12);
+ std::back_insert_iterator<helper_geometry_type> oit21(diff21);
+
+ compute_difference
+ <
+ GeometryOut
+ >::apply(areal1, areal2, robust_policy, oit12, strategy);
+
+ compute_difference
+ <
+ GeometryOut
+ >::apply(areal2, areal1, robust_policy, oit21, strategy);
+
+ return geometry::dispatch::union_insert
+ <
+ helper_geometry_type,
+ helper_geometry_type,
+ GeometryOut
+ >::apply(diff12, diff21, robust_policy, out, strategy);
+ }
+};
+
+
+}} // namespace detail::sym_difference
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename GeometryOut,
+ typename TagIn1 = typename geometry::tag_cast
+ <
+ typename tag<Geometry1>::type, areal_tag
+ >::type,
+ typename TagIn2 = typename geometry::tag_cast
+ <
+ typename tag<Geometry2>::type, areal_tag
+ >::type,
+ typename TagOut = typename geometry::tag<GeometryOut>::type
+>
+struct sym_difference_insert
+ : detail::sym_difference::sym_difference_generic
+ <
+ GeometryOut, Geometry1, Geometry2
+ >
+{};
+
+
+template
+<
+ typename Areal1,
+ typename Areal2,
+ typename GeometryOut,
+ typename TagOut
+>
+struct sym_difference_insert
+ <
+ Areal1, Areal2, GeometryOut,
+ areal_tag, areal_tag, TagOut
+ > : detail::sym_difference::sym_difference_areal_areal
+ <
+ GeometryOut, Areal1, Areal2
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace sym_difference
+{
+
+
/*!
\brief \brief_calc2{symmetric difference} \brief_strategy
@@ -60,24 +239,10 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
concept::check<Geometry2 const>();
concept::check<GeometryOut>();
- out = geometry::dispatch::intersection_insert
+ return dispatch::sym_difference_insert
<
- Geometry1, Geometry2,
- GeometryOut,
- overlay_difference,
- geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
- geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
+ Geometry1, Geometry2, GeometryOut
>::apply(geometry1, geometry2, robust_policy, out, strategy);
- out = geometry::dispatch::intersection_insert
- <
- Geometry2, Geometry1,
- GeometryOut,
- overlay_difference,
- geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
- geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value, true>::value,
- geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
- >::apply(geometry2, geometry1, robust_policy, out, strategy);
- return out;
}
diff --git a/boost/geometry/algorithms/touches.hpp b/boost/geometry/algorithms/touches.hpp
index 48334d7255..d6f0df3c74 100644
--- a/boost/geometry/algorithms/touches.hpp
+++ b/boost/geometry/algorithms/touches.hpp
@@ -37,7 +37,8 @@
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
-#include <boost/geometry/algorithms/detail/relate/relate.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
namespace boost { namespace geometry
{
@@ -67,7 +68,7 @@ struct box_box_loop
coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
// TODO assert or exception?
- //BOOST_ASSERT(min1 <= max1 && min2 <= max2);
+ //BOOST_GEOMETRY_ASSERT(min1 <= max1 && min2 <= max2);
if ( max1 < min2 || max2 < min1 )
{
@@ -349,9 +350,9 @@ struct touches<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, false>
template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>
- : detail::relate::relate_base
+ : detail::relate::relate_impl
<
- detail::relate::static_mask_touches_type,
+ detail::de9im::static_mask_touches_type,
Linear1,
Linear2
>
@@ -361,9 +362,9 @@ struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>
- : detail::relate::relate_base
+ : detail::relate::relate_impl
<
- detail::relate::static_mask_touches_type,
+ detail::de9im::static_mask_touches_type,
Linear,
Areal
>
@@ -372,9 +373,9 @@ struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>
// A/L
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, true>
- : detail::relate::relate_base
+ : detail::relate::relate_impl
<
- detail::relate::static_mask_touches_type,
+ detail::de9im::static_mask_touches_type,
Areal,
Linear
>
diff --git a/boost/geometry/algorithms/transform.hpp b/boost/geometry/algorithms/transform.hpp
index 357263a4ea..c7f3bd6cbb 100644
--- a/boost/geometry/algorithms/transform.hpp
+++ b/boost/geometry/algorithms/transform.hpp
@@ -70,9 +70,9 @@ struct transform_box
typedef typename point_type<Box2>::type point_type2;
point_type1 lower_left, upper_right;
- detail::assign::assign_box_2d_corner<min_corner, min_corner>(
+ geometry::detail::assign::assign_box_2d_corner<min_corner, min_corner>(
b1, lower_left);
- detail::assign::assign_box_2d_corner<max_corner, max_corner>(
+ geometry::detail::assign::assign_box_2d_corner<max_corner, max_corner>(
b1, upper_right);
point_type2 p1, p2;
@@ -88,10 +88,10 @@ struct transform_box
if (x1 > x2) { std::swap(x1, x2); }
if (y1 > y2) { std::swap(y1, y2); }
- set<min_corner, 0>(b2, x1);
- set<min_corner, 1>(b2, y1);
- set<max_corner, 0>(b2, x2);
- set<max_corner, 1>(b2, y2);
+ geometry::set<min_corner, 0>(b2, x1);
+ geometry::set<min_corner, 1>(b2, y1);
+ geometry::set<max_corner, 0>(b2, x2);
+ geometry::set<max_corner, 1>(b2, y2);
return true;
}
@@ -161,8 +161,8 @@ struct transform_polygon
geometry::clear(poly2);
- if (!transform_range_out<point2_type>(exterior_ring(poly1),
- std::back_inserter(exterior_ring(poly2)), strategy))
+ if (!transform_range_out<point2_type>(geometry::exterior_ring(poly1),
+ std::back_inserter(geometry::exterior_ring(poly2)), strategy))
{
return false;
}
@@ -174,12 +174,13 @@ struct transform_polygon
<
typename traits::interior_mutable_type<Polygon2>::type
>::type
- >::apply(interior_rings(poly2), num_interior_rings(poly1));
+ >::apply(geometry::interior_rings(poly2),
+ geometry::num_interior_rings(poly1));
- typename interior_return_type<Polygon1 const>::type
- rings1 = interior_rings(poly1);
- typename interior_return_type<Polygon2>::type
- rings2 = interior_rings(poly2);
+ typename geometry::interior_return_type<Polygon1 const>::type
+ rings1 = geometry::interior_rings(poly1);
+ typename geometry::interior_return_type<Polygon2>::type
+ rings2 = geometry::interior_rings(poly2);
typename detail::interior_iterator<Polygon1 const>::type
it1 = boost::begin(rings1);
@@ -424,7 +425,7 @@ struct transform<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Strategy const& strategy
)
{
- return apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
@@ -469,7 +470,7 @@ inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
template <typename Geometry1, typename Geometry2>
inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
{
- return transform(geometry1, geometry2, default_strategy());
+ return geometry::transform(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp
index 9f2b6fedf7..35f9396ba6 100644
--- a/boost/geometry/algorithms/within.hpp
+++ b/boost/geometry/algorithms/within.hpp
@@ -358,9 +358,9 @@ struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
- visitor(Geometry2 const& geometry2, Strategy const& strategy):
- m_geometry2(geometry2),
- m_strategy(strategy)
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)
+ : m_geometry2(geometry2)
+ , m_strategy(strategy)
{}
template <typename Geometry1>
@@ -378,10 +378,8 @@ struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return boost::apply_visitor(
- visitor<Strategy>(geometry2, strategy),
- geometry1
- );
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
+ geometry1);
}
};
@@ -394,9 +392,9 @@ struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
- visitor(Geometry1 const& geometry1, Strategy const& strategy):
- m_geometry1(geometry1),
- m_strategy(strategy)
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_strategy(strategy)
{}
template <typename Geometry2>
@@ -414,9 +412,8 @@ struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
- return boost::apply_visitor(
- visitor<Strategy>(geometry1, strategy),
- geometry2
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
+ geometry2
);
}
};
@@ -453,10 +450,9 @@ struct within<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
- return boost::apply_visitor(
- visitor<Strategy>(strategy),
- geometry1, geometry2
- );
+ return boost::apply_visitor(visitor<Strategy>(strategy),
+ geometry1,
+ geometry2);
}
};
diff --git a/boost/geometry/arithmetic/arithmetic.hpp b/boost/geometry/arithmetic/arithmetic.hpp
index 6eb31f488e..fbc3ca443e 100644
--- a/boost/geometry/arithmetic/arithmetic.hpp
+++ b/boost/geometry/arithmetic/arithmetic.hpp
@@ -22,6 +22,7 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
@@ -32,80 +33,94 @@ namespace detail
{
-template <typename P>
+template <typename Point>
struct param
{
typedef typename boost::call_traits
<
- typename coordinate_type<P>::type
+ typename coordinate_type<Point>::type
>::param_type type;
};
-template <typename C, template <typename> class Function>
+template <typename Value, template <typename> class Function>
struct value_operation
{
- C m_value;
+ Value m_value;
- inline value_operation(C const &value)
+ inline value_operation(Value const &value)
: m_value(value)
{}
- template <typename P, int I>
- inline void apply(P& point) const
+ template <typename PointDst, std::size_t Index>
+ inline void apply(PointDst& point_dst) const
{
- set<I>(point, Function<C>()(get<I>(point), m_value));
+ set<Index>(point_dst,
+ Function
+ <
+ typename geometry::select_most_precise
+ <
+ Value,
+ typename geometry::coordinate_type<PointDst>::type
+ >::type
+ >()(get<Index>(point_dst), m_value));
}
};
template <typename PointSrc, template <typename> class Function>
struct point_operation
{
- typedef typename coordinate_type<PointSrc>::type coordinate_type;
- PointSrc const& m_source_point;
+ PointSrc const& m_point_src;
inline point_operation(PointSrc const& point)
- : m_source_point(point)
+ : m_point_src(point)
{}
- template <typename PointDst, int I>
- inline void apply(PointDst& dest_point) const
+ template <typename PointDst, std::size_t Index>
+ inline void apply(PointDst& point_dst) const
{
- set<I>(dest_point,
- Function<coordinate_type>()(get<I>(dest_point), get<I>(m_source_point)));
+ set<Index>(point_dst,
+ Function
+ <
+ typename geometry::select_most_precise
+ <
+ typename geometry::coordinate_type<PointSrc>::type,
+ typename geometry::coordinate_type<PointDst>::type
+ >::type
+ >()(get<Index>(point_dst), get<Index>(m_point_src)));
}
};
-template <typename C>
+template <typename Value>
struct value_assignment
{
- C m_value;
+ Value m_value;
- inline value_assignment(C const &value)
+ inline value_assignment(Value const &value)
: m_value(value)
{}
- template <typename P, int I>
- inline void apply(P& point) const
+ template <typename PointDst, std::size_t Index>
+ inline void apply(PointDst& point_dst) const
{
- set<I>(point, m_value);
+ set<Index>(point_dst, m_value);
}
};
template <typename PointSrc>
struct point_assignment
{
- PointSrc const& m_source_point;
+ PointSrc const& m_point_src;
inline point_assignment(PointSrc const& point)
- : m_source_point(point)
+ : m_point_src(point)
{}
- template <typename PointDst, int I>
- inline void apply(PointDst& dest_point) const
+ template <typename PointDst, std::size_t Index>
+ inline void apply(PointDst& point_dst) const
{
- set<I>(dest_point, get<I>(m_source_point));
+ set<Index>(point_dst, get<Index>(m_point_src));
}
};
@@ -126,7 +141,12 @@ inline void add_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
- for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::plus>(value));
+ for_each_coordinate(p,
+ detail::value_operation
+ <
+ typename coordinate_type<Point>::type,
+ std::plus
+ >(value));
}
/*!
@@ -161,7 +181,12 @@ inline void subtract_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
- for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::minus>(value));
+ for_each_coordinate(p,
+ detail::value_operation
+ <
+ typename coordinate_type<Point>::type,
+ std::minus
+ >(value));
}
/*!
@@ -196,7 +221,12 @@ inline void multiply_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
- for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::multiplies>(value));
+ for_each_coordinate(p,
+ detail::value_operation
+ <
+ typename coordinate_type<Point>::type,
+ std::multiplies
+ >(value));
}
/*!
@@ -232,7 +262,12 @@ inline void divide_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
- for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::divides>(value));
+ for_each_coordinate(p,
+ detail::value_operation
+ <
+ typename coordinate_type<Point>::type,
+ std::divides
+ >(value));
}
/*!
@@ -267,7 +302,11 @@ inline void assign_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
- for_each_coordinate(p, detail::value_assignment<typename coordinate_type<Point>::type>(value));
+ for_each_coordinate(p,
+ detail::value_assignment
+ <
+ typename coordinate_type<Point>::type
+ >(value));
}
/*!
diff --git a/boost/geometry/core/assert.hpp b/boost/geometry/core/assert.hpp
new file mode 100644
index 0000000000..0f3ae6baea
--- /dev/null
+++ b/boost/geometry/core/assert.hpp
@@ -0,0 +1,43 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2007, 2014 Peter Dimov
+// Copyright (c) Beman Dawes 2011
+// Copyright (c) 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_CORE_ASSERT_HPP
+#define BOOST_GEOMETRY_CORE_ASSERT_HPP
+
+#include <boost/assert.hpp>
+
+#undef BOOST_GEOMETRY_ASSERT
+#undef BOOST_GEOMETRY_ASSERT_MSG
+
+#if defined(BOOST_GEOMETRY_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_GEOMETRY_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )
+
+#include <boost/config.hpp> // for BOOST_LIKELY
+#include <boost/current_function.hpp>
+
+namespace boost { namespace geometry
+{
+ void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
+ void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line); // user defined
+}} // namespace boost::geometry
+
+#define BOOST_GEOMETRY_ASSERT(expr) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::geometry::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
+#define BOOST_GEOMETRY_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::geometry::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
+
+#else
+
+#define BOOST_GEOMETRY_ASSERT(expr) BOOST_ASSERT(expr)
+#define BOOST_GEOMETRY_ASSERT_MSG(expr, msg) BOOST_ASSERT_MSG(expr, msg)
+
+#endif
+
+#endif // BOOST_GEOMETRY_CORE_EXCEPTION_HPP
diff --git a/boost/geometry/core/exception.hpp b/boost/geometry/core/exception.hpp
index 97d249e938..6868ca775a 100644
--- a/boost/geometry/core/exception.hpp
+++ b/boost/geometry/core/exception.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
+
+// 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.
@@ -26,8 +31,31 @@ namespace boost { namespace geometry
are derived from exception, so it might be convenient to catch it.
*/
class exception : public std::exception
-{};
+{
+ virtual char const* what() const throw()
+ {
+ return "Boost.Geometry exception";
+ }
+};
+
+/*!
+\brief Invalid Input Exception
+\ingroup core
+\details The invalid_input_exception is thrown if an invalid attribute
+ is passed into a function, e.g. a DE-9IM mask string code containing
+ invalid characters passed into a de9im::mask constructor.
+ */
+class invalid_input_exception : public geometry::exception
+{
+public:
+
+ inline invalid_input_exception() {}
+ virtual char const* what() const throw()
+ {
+ return "Boost.Geometry Invalid-Input exception";
+ }
+};
/*!
\brief Empty Input Exception
@@ -42,7 +70,7 @@ class exception : public std::exception
\* [link geometry.reference.algorithms.length the length function]
}
*/
-class empty_input_exception : public geometry::exception
+class empty_input_exception : public geometry::invalid_input_exception
{
public:
diff --git a/boost/geometry/core/radian_access.hpp b/boost/geometry/core/radian_access.hpp
index bac77d7bc7..374c2954a2 100644
--- a/boost/geometry/core/radian_access.hpp
+++ b/boost/geometry/core/radian_access.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -47,7 +52,8 @@ struct degree_radian_converter
return boost::numeric_cast
<
coordinate_type
- >(geometry::get<Dimension>(geometry) * geometry::math::d2r);
+ >(geometry::get<Dimension>(geometry)
+ * math::d2r<coordinate_type>());
}
static inline void set(Geometry& geometry, coordinate_type const& radians)
@@ -55,7 +61,7 @@ struct degree_radian_converter
geometry::set<Dimension>(geometry, boost::numeric_cast
<
coordinate_type
- >(radians * geometry::math::r2d));
+ >(radians * math::r2d<coordinate_type>()));
}
};
diff --git a/boost/geometry/geometries/box.hpp b/boost/geometry/geometries/box.hpp
index a2e3d4fd79..97a4ba06da 100644
--- a/boost/geometry/geometries/box.hpp
+++ b/boost/geometry/geometries/box.hpp
@@ -17,10 +17,14 @@
#include <cstddef>
#include <boost/concept/assert.hpp>
+#include <boost/config.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+#include <boost/geometry/core/assert.hpp>
+#endif
namespace boost { namespace geometry
@@ -29,18 +33,21 @@ namespace boost { namespace geometry
namespace model
{
-
/*!
- \brief Class box: defines a box made of two describing points
- \ingroup geometries
- \details Box is always described by a min_corner() and a max_corner() point. If another
- rectangle is used, use linear_ring or polygon.
- \note Boxes are for selections and for calculating the envelope of geometries. Not all algorithms
- are implemented for box. Boxes are also used in Spatial Indexes.
- \tparam Point point type. The box takes a point type as template parameter.
- The point type can be any point type.
- It can be 2D but can also be 3D or more dimensional.
- The box can also take a latlong point type as template parameter.
+\brief Class box: defines a box made of two describing points
+\ingroup geometries
+\details Box is always described by a min_corner() and a max_corner() point. If another
+ rectangle is used, use linear_ring or polygon.
+\note Boxes are for selections and for calculating the envelope of geometries. Not all algorithms
+are implemented for box. Boxes are also used in Spatial Indexes.
+\tparam Point point type. The box takes a point type as template parameter.
+The point type can be any point type.
+It can be 2D but can also be 3D or more dimensional.
+The box can also take a latlong point type as template parameter.
+
+\qbk{[include reference/geometries/box.qbk]}
+\qbk{before.synopsis, [heading Model of]}
+\qbk{before.synopsis, [link geometry.reference.concepts.concept_box Box Concept]}
*/
template<typename Point>
@@ -50,7 +57,25 @@ class box
public:
- inline box() {}
+#if !defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
+ /// \constructor_default_no_init
+ box() = default;
+#else
+ /// \constructor_default_no_init
+ inline box()
+ {}
+#endif
+#else // defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ inline box()
+ {
+ m_created = 1;
+ }
+ ~box()
+ {
+ m_created = 0;
+ }
+#endif
/*!
\brief Constructor taking the minimum corner point and the maximum corner point
@@ -59,18 +84,50 @@ public:
{
geometry::convert(min_corner, m_min_corner);
geometry::convert(max_corner, m_max_corner);
+
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ m_created = 1;
+#endif
}
- inline Point const& min_corner() const { return m_min_corner; }
- inline Point const& max_corner() const { return m_max_corner; }
+ inline Point const& min_corner() const
+ {
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ BOOST_GEOMETRY_ASSERT(m_created == 1);
+#endif
+ return m_min_corner;
+ }
+ inline Point const& max_corner() const
+ {
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ BOOST_GEOMETRY_ASSERT(m_created == 1);
+#endif
+ return m_max_corner;
+ }
- inline Point& min_corner() { return m_min_corner; }
- inline Point& max_corner() { return m_max_corner; }
+ inline Point& min_corner()
+ {
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ BOOST_GEOMETRY_ASSERT(m_created == 1);
+#endif
+ return m_min_corner;
+ }
+ inline Point& max_corner()
+ {
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ BOOST_GEOMETRY_ASSERT(m_created == 1);
+#endif
+ return m_max_corner;
+ }
private:
Point m_min_corner;
Point m_max_corner;
+
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ int m_created;
+#endif
};
diff --git a/boost/geometry/geometries/concepts/point_concept.hpp b/boost/geometry/geometries/concepts/point_concept.hpp
index db49771129..52f8d038ea 100644
--- a/boost/geometry/geometries/concepts/point_concept.hpp
+++ b/boost/geometry/geometries/concepts/point_concept.hpp
@@ -165,7 +165,7 @@ class ConstPoint
{
const P* p = 0;
ctype coord(geometry::get<Dimension>(*p));
- boost::ignore_unused(coord);
+ boost::ignore_unused(p, coord);
dimension_checker<P, Dimension+1, DimensionCount>::apply();
}
};
diff --git a/boost/geometry/geometries/helper_geometry.hpp b/boost/geometry/geometries/helper_geometry.hpp
new file mode 100644
index 0000000000..9cf14a9117
--- /dev/null
+++ b/boost/geometry/geometries/helper_geometry.hpp
@@ -0,0 +1,162 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/geometries/point.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace helper_geometries
+{
+
+template <typename Geometry, typename CS_Tag = typename cs_tag<Geometry>::type>
+struct default_units
+{
+ typedef typename coordinate_system<Geometry>::type::units type;
+};
+
+// The Cartesian coordinate system does not define the type units.
+// For that reason the generic implementation for default_units cannot be used
+// and specialization needs to be defined.
+// Moreover, it makes sense to define the units for the Cartesian
+// coordinate system to be radians, as this way a Cartesian point can
+// potentially be used in algorithms taking non-Cartesian strategies
+// and work as if it was as point in the non-Cartesian coordinate
+// system with radian units.
+template <typename Geometry>
+struct default_units<Geometry, cartesian_tag>
+{
+ typedef radian type;
+};
+
+
+template <typename Units, typename CS_Tag>
+struct cs_tag_to_coordinate_system
+{
+ typedef cs::cartesian type;
+};
+
+template <typename Units>
+struct cs_tag_to_coordinate_system<Units, spherical_equatorial_tag>
+{
+ typedef cs::spherical_equatorial<Units> type;
+};
+
+template <typename Units>
+struct cs_tag_to_coordinate_system<Units, spherical_tag>
+{
+ typedef cs::spherical<Units> type;
+};
+
+template <typename Units>
+struct cs_tag_to_coordinate_system<Units, geographic_tag>
+{
+ typedef cs::geographic<Units> type;
+};
+
+
+template
+<
+ typename Point,
+ typename NewCoordinateType,
+ typename NewUnits,
+ typename CS_Tag = typename cs_tag<Point>::type
+>
+struct helper_point
+{
+ typedef model::point
+ <
+ NewCoordinateType,
+ dimension<Point>::value,
+ typename cs_tag_to_coordinate_system<NewUnits, CS_Tag>::type
+ > type;
+};
+
+
+}} // detail::helper_geometries
+
+
+namespace detail_dispatch
+{
+
+
+template
+<
+ typename Geometry,
+ typename NewCoordinateType,
+ typename NewUnits,
+ typename Tag = typename tag<Geometry>::type>
+struct helper_geometry : not_implemented<Geometry>
+{};
+
+
+template <typename Point, typename NewCoordinateType, typename NewUnits>
+struct helper_geometry<Point, NewCoordinateType, NewUnits, point_tag>
+{
+ typedef typename detail::helper_geometries::helper_point
+ <
+ Point, NewCoordinateType, NewUnits
+ >::type type;
+};
+
+
+template <typename Box, typename NewCoordinateType, typename NewUnits>
+struct helper_geometry<Box, NewCoordinateType, NewUnits, box_tag>
+{
+ typedef model::box
+ <
+ typename helper_geometry
+ <
+ typename point_type<Box>::type, NewCoordinateType, NewUnits
+ >::type
+ > type;
+};
+
+
+} // detail_dispatch
+
+
+// Meta-function that provides a new helper geometry of the same kind as
+// the input geometry and the same coordinate system type,
+// but with a possibly different coordinate type and coordinate system units
+template
+<
+ typename Geometry,
+ typename NewCoordinateType = typename coordinate_type<Geometry>::type,
+ typename NewUnits = typename detail::helper_geometries::default_units
+ <
+ Geometry
+ >::type
+>
+struct helper_geometry
+{
+ typedef typename detail_dispatch::helper_geometry
+ <
+ Geometry, NewCoordinateType, NewUnits
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP
diff --git a/boost/geometry/geometries/linestring.hpp b/boost/geometry/geometries/linestring.hpp
index 68dc87a3cf..22c9c99de9 100644
--- a/boost/geometry/geometries/linestring.hpp
+++ b/boost/geometry/geometries/linestring.hpp
@@ -26,12 +26,10 @@
#include <boost/geometry/geometries/concepts/point_concept.hpp>
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
-#endif
namespace boost { namespace geometry
{
@@ -46,6 +44,7 @@ namespace model
\tparam Container \tparam_container
\tparam Allocator \tparam_allocator
+\qbk{[include reference/geometries/linestring.qbk]}
\qbk{before.synopsis,
[heading Model of]
[link geometry.reference.concepts.concept_linestring Linestring Concept]
@@ -76,7 +75,6 @@ public :
: base_type(begin, end)
{}
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/// \constructor_initializer_list{linestring}
@@ -98,7 +96,6 @@ public :
//#endif
#endif
-#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/multi_linestring.hpp b/boost/geometry/geometries/multi_linestring.hpp
index 195a58139c..cd08fdbe14 100644
--- a/boost/geometry/geometries/multi_linestring.hpp
+++ b/boost/geometry/geometries/multi_linestring.hpp
@@ -23,12 +23,10 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
-#endif
namespace boost { namespace geometry
{
@@ -43,6 +41,7 @@ namespace model
e.g. a highway (with interruptions)
\ingroup geometries
+\qbk{[include reference/geometries/multi_linestring.qbk]}
\qbk{before.synopsis,
[heading Model of]
[link geometry.reference.concepts.concept_multi_linestring MultiLineString Concept]
@@ -58,7 +57,10 @@ class multi_linestring : public Container<LineString, Allocator<LineString> >
{
BOOST_CONCEPT_ASSERT( (concept::Linestring<LineString>) );
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+ // default constructor and base_type definitions are required only
+ // if the constructor taking std::initializer_list is defined
typedef Container<LineString, Allocator<LineString> > base_type;
@@ -68,8 +70,6 @@ public:
: base_type()
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
/// \constructor_initializer_list{multi_linestring}
inline multi_linestring(std::initializer_list<LineString> l)
: base_type(l.begin(), l.end())
@@ -89,7 +89,6 @@ public:
//#endif
#endif
-#endif
};
diff --git a/boost/geometry/geometries/multi_point.hpp b/boost/geometry/geometries/multi_point.hpp
index a5e64bb91c..ab4cd88177 100644
--- a/boost/geometry/geometries/multi_point.hpp
+++ b/boost/geometry/geometries/multi_point.hpp
@@ -23,12 +23,10 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
-#endif
namespace boost { namespace geometry
{
@@ -45,6 +43,8 @@ namespace model
\tparam Allocator \tparam_allocator
\details Multipoint can be used to group points belonging to each other,
e.g. a constellation, or the result set of an intersection
+
+\qbk{[include reference/geometries/multi_point.qbk]}
\qbk{before.synopsis,
[heading Model of]
[link geometry.reference.concepts.concept_multi_point MultiPoint Concept]
@@ -74,7 +74,6 @@ public :
: base_type(begin, end)
{}
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/// \constructor_initializer_list{multi_point}
@@ -96,7 +95,6 @@ public :
//#endif
#endif
-#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/multi_polygon.hpp b/boost/geometry/geometries/multi_polygon.hpp
index 51fcf235f8..9db74b4ec4 100644
--- a/boost/geometry/geometries/multi_polygon.hpp
+++ b/boost/geometry/geometries/multi_polygon.hpp
@@ -23,12 +23,10 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
-#endif
namespace boost { namespace geometry
{
@@ -42,6 +40,7 @@ namespace model
e.g. Hawaii
\ingroup geometries
+\qbk{[include reference/geometries/multi_polygon.qbk]}
\qbk{before.synopsis,
[heading Model of]
[link geometry.reference.concepts.concept_multi_polygon MultiPolygon Concept]
@@ -57,7 +56,10 @@ class multi_polygon : public Container<Polygon, Allocator<Polygon> >
{
BOOST_CONCEPT_ASSERT( (concept::Polygon<Polygon>) );
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+ // default constructor and base_type definitions are required only
+ // if the constructor taking std::initializer_list is defined
typedef Container<Polygon, Allocator<Polygon> > base_type;
@@ -67,8 +69,6 @@ public:
: base_type()
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
/// \constructor_initializer_list{multi_polygon}
inline multi_polygon(std::initializer_list<Polygon> l)
: base_type(l.begin(), l.end())
@@ -88,7 +88,6 @@ public:
//#endif
#endif
-#endif
};
diff --git a/boost/geometry/geometries/point.hpp b/boost/geometry/geometries/point.hpp
index 056c7d5d02..70bfeed447 100644
--- a/boost/geometry/geometries/point.hpp
+++ b/boost/geometry/geometries/point.hpp
@@ -22,14 +22,21 @@
#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/mpl/assert.hpp>
#include <boost/mpl/int.hpp>
-#include <boost/static_assert.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+#include <algorithm>
+#include <boost/geometry/core/assert.hpp>
+#endif
+
namespace boost { namespace geometry
{
@@ -100,7 +107,10 @@ template
>
class point
{
-private:
+ BOOST_MPL_ASSERT_MSG((DimensionCount >= 1),
+ DIMENSION_GREATER_THAN_ZERO_EXPECTED,
+ (boost::mpl::int_<DimensionCount>));
+
// The following enum is used to fully instantiate the
// CoordinateSystem class and check the correctness of the units
// passed for non-Cartesian coordinate systems.
@@ -108,11 +118,27 @@ private:
public:
- /// @brief Default constructor, no initialization
+#if !defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
+ /// \constructor_default_no_init
+ point() = default;
+#else
+ /// \constructor_default_no_init
inline point()
+ {}
+#endif
+#else // defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ point()
{
- BOOST_STATIC_ASSERT(DimensionCount >= 1);
+ m_created = 1;
+ std::fill_n(m_values_initialized, DimensionCount, 0);
}
+ ~point()
+ {
+ m_created = 0;
+ std::fill_n(m_values_initialized, DimensionCount, 0);
+ }
+#endif
/// @brief Constructor to set one value
explicit inline point(CoordinateType const& v0)
@@ -120,6 +146,11 @@ public:
detail::array_assign<DimensionCount, 0>::apply(m_values, v0);
detail::array_assign<DimensionCount, 1>::apply(m_values, CoordinateType());
detail::array_assign<DimensionCount, 2>::apply(m_values, CoordinateType());
+
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ m_created = 1;
+ std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);
+#endif
}
/// @brief Constructor to set two values
@@ -128,6 +159,11 @@ public:
detail::array_assign<DimensionCount, 0>::apply(m_values, v0);
detail::array_assign<DimensionCount, 1>::apply(m_values, v1);
detail::array_assign<DimensionCount, 2>::apply(m_values, CoordinateType());
+
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ m_created = 1;
+ std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);
+#endif
}
/// @brief Constructor to set three values
@@ -137,6 +173,11 @@ public:
detail::array_assign<DimensionCount, 0>::apply(m_values, v0);
detail::array_assign<DimensionCount, 1>::apply(m_values, v1);
detail::array_assign<DimensionCount, 2>::apply(m_values, v2);
+
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ m_created = 1;
+ std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);
+#endif
}
/// @brief Get a coordinate
@@ -145,6 +186,10 @@ public:
template <std::size_t K>
inline CoordinateType const& get() const
{
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ BOOST_GEOMETRY_ASSERT(m_created == 1);
+ BOOST_GEOMETRY_ASSERT(m_values_initialized[K] == 1);
+#endif
BOOST_STATIC_ASSERT(K < DimensionCount);
return m_values[K];
}
@@ -155,6 +200,10 @@ public:
template <std::size_t K>
inline void set(CoordinateType const& value)
{
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ BOOST_GEOMETRY_ASSERT(m_created == 1);
+ m_values_initialized[K] = 1;
+#endif
BOOST_STATIC_ASSERT(K < DimensionCount);
m_values[K] = value;
}
@@ -162,6 +211,11 @@ public:
private:
CoordinateType m_values[DimensionCount];
+
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
+ int m_created;
+ int m_values_initialized[DimensionCount];
+#endif
};
diff --git a/boost/geometry/geometries/point_xy.hpp b/boost/geometry/geometries/point_xy.hpp
index 652930666f..bbc35d5cec 100644
--- a/boost/geometry/geometries/point_xy.hpp
+++ b/boost/geometry/geometries/point_xy.hpp
@@ -16,6 +16,7 @@
#include <cstddef>
+#include <boost/config.hpp>
#include <boost/mpl/int.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -32,6 +33,7 @@ namespace model { namespace d2
\tparam CoordinateType numeric type, for example, double, float, int
\tparam CoordinateSystem coordinate system, defaults to cs::cartesian
+\qbk{[include reference/geometries/point_xy.qbk]}
\qbk{before.synopsis,
[heading Model of]
[link geometry.reference.concepts.concept_point Point Concept]
@@ -45,10 +47,14 @@ class point_xy : public model::point<CoordinateType, 2, CoordinateSystem>
{
public:
- /// Default constructor, does not initialize anything
+#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+ /// \constructor_default_no_init
+ point_xy() = default;
+#else
+ /// \constructor_default_no_init
inline point_xy()
- : model::point<CoordinateType, 2, CoordinateSystem>()
{}
+#endif
/// Constructor with x/y values
inline point_xy(CoordinateType const& x, CoordinateType const& y)
diff --git a/boost/geometry/geometries/pointing_segment.hpp b/boost/geometry/geometries/pointing_segment.hpp
index 681752ef2d..2c4284d10a 100644
--- a/boost/geometry/geometries/pointing_segment.hpp
+++ b/boost/geometry/geometries/pointing_segment.hpp
@@ -12,17 +12,16 @@
#include <cstddef>
-#include <boost/assert.hpp>
#include <boost/concept/assert.hpp>
#include <boost/core/addressof.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
-#include <boost/geometry/geometries/concepts/point_concept.hpp>
-
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
namespace boost { namespace geometry
{
@@ -99,13 +98,13 @@ struct indexed_access<model::pointing_segment<Point>, 0, Dimension>
static inline coordinate_type get(segment_type const& s)
{
- BOOST_ASSERT( s.first != NULL );
+ BOOST_GEOMETRY_ASSERT( s.first != NULL );
return geometry::get<Dimension>(*s.first);
}
static inline void set(segment_type& s, coordinate_type const& value)
{
- BOOST_ASSERT( s.first != NULL );
+ BOOST_GEOMETRY_ASSERT( s.first != NULL );
geometry::set<Dimension>(*s.first, value);
}
};
@@ -122,13 +121,13 @@ struct indexed_access<model::pointing_segment<Point>, 1, Dimension>
static inline coordinate_type get(segment_type const& s)
{
- BOOST_ASSERT( s.second != NULL );
+ BOOST_GEOMETRY_ASSERT( s.second != NULL );
return geometry::get<Dimension>(*s.second);
}
static inline void set(segment_type& s, coordinate_type const& value)
{
- BOOST_ASSERT( s.second != NULL );
+ BOOST_GEOMETRY_ASSERT( s.second != NULL );
geometry::set<Dimension>(*s.second, value);
}
};
diff --git a/boost/geometry/geometries/polygon.hpp b/boost/geometry/geometries/polygon.hpp
index 5f2e87a11d..5e6064e893 100644
--- a/boost/geometry/geometries/polygon.hpp
+++ b/boost/geometry/geometries/polygon.hpp
@@ -27,12 +27,10 @@
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/ring.hpp>
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
-#endif
namespace boost { namespace geometry
{
@@ -57,6 +55,7 @@ namespace model
\note The container collecting the points in the rings can be different
from the container collecting the inner rings. They all default to vector.
+\qbk{[include reference/geometries/polygon.qbk]}
\qbk{before.synopsis,
[heading Model of]
[link geometry.reference.concepts.concept_polygon Polygon Concept]
@@ -91,7 +90,10 @@ public:
inline ring_type& outer() { return m_outer; }
inline inner_container_type & inners() { return m_inners; }
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+ // default constructor definition is required only
+ // if the constructor taking std::initializer_list is defined
/// \constructor_default{polygon}
inline polygon()
@@ -99,7 +101,6 @@ public:
, m_inners()
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/// \constructor_initializer_list{polygon}
inline polygon(std::initializer_list<ring_type> l)
: m_outer(l.size() > 0 ? *l.begin() : ring_type())
@@ -129,7 +130,6 @@ public:
//#endif
#endif
-#endif
/// Utility method, clears outer and inner rings
inline void clear()
diff --git a/boost/geometry/geometries/ring.hpp b/boost/geometry/geometries/ring.hpp
index 502c95d759..01bcf58cf5 100644
--- a/boost/geometry/geometries/ring.hpp
+++ b/boost/geometry/geometries/ring.hpp
@@ -27,12 +27,10 @@
#include <boost/geometry/geometries/concepts/point_concept.hpp>
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#include <boost/config.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
-#endif
namespace boost { namespace geometry
{
@@ -50,6 +48,7 @@ namespace model
\tparam Container container type, for example std::vector, std::deque
\tparam Allocator container-allocator-type
+\qbk{[include reference/geometries/ring.qbk]}
\qbk{before.synopsis,
[heading Model of]
[link geometry.reference.concepts.concept_ring Ring Concept]
@@ -80,7 +79,6 @@ public :
: base_type(begin, end)
{}
-#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/// \constructor_initializer_list{ring}
@@ -102,7 +100,6 @@ public :
//#endif
#endif
-#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/segment.hpp b/boost/geometry/geometries/segment.hpp
index 3f47f79ec4..af406aa09f 100644
--- a/boost/geometry/geometries/segment.hpp
+++ b/boost/geometry/geometries/segment.hpp
@@ -35,14 +35,32 @@ namespace model
by two distinct end points, and contains every point on the line between its end points.
\note There is also a point-referring-segment, class referring_segment,
containing point references, where points are NOT copied
+
+\qbk{[include reference/geometries/segment.qbk]}
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_segment Segment Concept]
+}
*/
template<typename Point>
class segment : public std::pair<Point, Point>
{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
public :
+
+#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+ /// \constructor_default_no_init
+ segment() = default;
+#else
+ /// \constructor_default_no_init
inline segment()
{}
+#endif
+ /*!
+ \brief Constructor taking the first and the second point
+ */
inline segment(Point const& p1, Point const& p2)
{
this->first = p1;
@@ -83,6 +101,9 @@ public:
point_type& first;
point_type& second;
+ /*!
+ \brief Constructor taking the first and the second point
+ */
inline referring_segment(point_type& p1, point_type& p2)
: first(p1)
, second(p2)
diff --git a/boost/geometry/geometry.hpp b/boost/geometry/geometry.hpp
index 8d34a0e4ef..d96facb340 100644
--- a/boost/geometry/geometry.hpp
+++ b/boost/geometry/geometry.hpp
@@ -70,6 +70,7 @@
#include <boost/geometry/algorithms/for_each.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/is_simple.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
#include <boost/geometry/algorithms/length.hpp>
@@ -80,6 +81,8 @@
#include <boost/geometry/algorithms/num_segments.hpp>
#include <boost/geometry/algorithms/overlaps.hpp>
#include <boost/geometry/algorithms/perimeter.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/relation.hpp>
#include <boost/geometry/algorithms/remove_spikes.hpp>
#include <boost/geometry/algorithms/reverse.hpp>
#include <boost/geometry/algorithms/simplify.hpp>
@@ -90,10 +93,6 @@
#include <boost/geometry/algorithms/unique.hpp>
#include <boost/geometry/algorithms/within.hpp>
-// Include multi a.o. because it can give weird effects
-// if you don't (e.g. area=0 of a multipolygon)
-#include <boost/geometry/multi/multi.hpp>
-
// check includes all concepts
#include <boost/geometry/geometries/concepts/check.hpp>
diff --git a/boost/geometry/index/detail/assert.hpp b/boost/geometry/index/detail/assert.hpp
index 311f37f640..08889df478 100644
--- a/boost/geometry/index/detail/assert.hpp
+++ b/boost/geometry/index/detail/assert.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry Index
//
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2015 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
@@ -9,13 +9,11 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
-#include <boost/assert.hpp>
+#include <boost/geometry/core/assert.hpp>
-#ifndef BOOST_GEOMETRY_INDEX_ASSERT
+#undef BOOST_GEOMETRY_INDEX_ASSERT
#define BOOST_GEOMETRY_INDEX_ASSERT(CONDITION, TEXT_MSG) \
- BOOST_ASSERT_MSG(CONDITION, TEXT_MSG)
-
-#endif // BOOST_GEOMETRY_INDEX_ASSERT
+ BOOST_GEOMETRY_ASSERT_MSG(CONDITION, TEXT_MSG)
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
diff --git a/boost/geometry/index/detail/bounded_view.hpp b/boost/geometry/index/detail/bounded_view.hpp
index 0cd882fc94..e5f489d76b 100644
--- a/boost/geometry/index/detail/bounded_view.hpp
+++ b/boost/geometry/index/detail/bounded_view.hpp
@@ -3,7 +3,7 @@
// This view makes possible to treat some simple primitives as its bounding geometry
// e.g. box, nsphere, etc.
//
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2015 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,6 +12,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP
+#include <boost/geometry/algorithms/envelope.hpp>
+
namespace boost { namespace geometry {
namespace index { namespace detail {
@@ -19,7 +21,8 @@ namespace index { namespace detail {
template <typename Geometry,
typename BoundingGeometry,
typename Tag = typename geometry::tag<Geometry>::type,
- typename BoundingTag = typename geometry::tag<BoundingGeometry>::type>
+ typename BoundingTag = typename geometry::tag<BoundingGeometry>::type,
+ typename CSystem = typename geometry::coordinate_system<Geometry>::type>
struct bounded_view
{
BOOST_MPL_ASSERT_MSG(
@@ -32,7 +35,7 @@ struct bounded_view
// Segment -> Box
template <typename Segment, typename Box>
-struct bounded_view<Segment, Box, segment_tag, box_tag>
+struct bounded_view<Segment, Box, segment_tag, box_tag, cs::cartesian>
{
public:
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
@@ -61,10 +64,37 @@ private:
Segment const& m_segment;
};
+template <typename Segment, typename Box, typename CSystem>
+struct bounded_view<Segment, Box, segment_tag, box_tag, CSystem>
+{
+public:
+ typedef typename geometry::coordinate_type<Box>::type coordinate_type;
+
+ explicit bounded_view(Segment const& segment)
+ {
+ geometry::envelope(segment, m_box);
+ }
+
+ template <std::size_t Dimension>
+ inline coordinate_type get_min() const
+ {
+ return geometry::get<min_corner, Dimension>(m_box);
+ }
+
+ template <std::size_t Dimension>
+ inline coordinate_type get_max() const
+ {
+ return geometry::get<max_corner, Dimension>(m_box);
+ }
+
+private:
+ Box m_box;
+};
+
// Box -> Box
-template <typename BoxIn, typename Box>
-struct bounded_view<BoxIn, Box, box_tag, box_tag>
+template <typename BoxIn, typename Box, typename CSystem>
+struct bounded_view<BoxIn, Box, box_tag, box_tag, CSystem>
{
public:
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
@@ -93,8 +123,8 @@ private:
// Point -> Box
-template <typename Point, typename Box>
-struct bounded_view<Point, Box, point_tag, box_tag>
+template <typename Point, typename Box, typename CSystem>
+struct bounded_view<Point, Box, point_tag, box_tag, CSystem>
{
public:
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
@@ -129,23 +159,23 @@ private:
namespace traits
{
-template <typename Geometry, typename Box, typename Tag>
-struct tag< index::detail::bounded_view<Geometry, Box, Tag, box_tag> >
+template <typename Geometry, typename Box, typename Tag, typename CSystem>
+struct tag< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >
{
typedef box_tag type;
};
-template <typename Segment, typename Box, typename Tag>
-struct point_type< index::detail::bounded_view<Segment, Box, Tag, box_tag> >
+template <typename Geometry, typename Box, typename Tag, typename CSystem>
+struct point_type< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >
{
typedef typename point_type<Box>::type type;
};
-template <typename Segment, typename Box, typename Tag, std::size_t Dimension>
-struct indexed_access<index::detail::bounded_view<Segment, Box, Tag, box_tag>,
+template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>
+struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,
min_corner, Dimension>
{
- typedef index::detail::bounded_view<Segment, Box, Tag, box_tag> box_type;
+ typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
static inline coordinate_type get(box_type const& b)
@@ -159,11 +189,11 @@ struct indexed_access<index::detail::bounded_view<Segment, Box, Tag, box_tag>,
//}
};
-template <typename Segment, typename Box, typename Tag, std::size_t Dimension>
-struct indexed_access<index::detail::bounded_view<Segment, Box, Tag, box_tag>,
+template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>
+struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,
max_corner, Dimension>
{
- typedef index::detail::bounded_view<Segment, Box, Tag, box_tag> box_type;
+ typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;
typedef typename geometry::coordinate_type<Box>::type coordinate_type;
static inline coordinate_type get(box_type const& b)
diff --git a/boost/geometry/index/detail/predicates.hpp b/boost/geometry/index/detail/predicates.hpp
index 60f80207d8..01afd16ba6 100644
--- a/boost/geometry/index/detail/predicates.hpp
+++ b/boost/geometry/index/detail/predicates.hpp
@@ -25,6 +25,7 @@ namespace predicates {
template <typename Fun, bool IsFunction>
struct satisfies_impl
{
+ satisfies_impl() : fun(NULL) {}
satisfies_impl(Fun f) : fun(f) {}
Fun * fun;
};
@@ -32,6 +33,7 @@ struct satisfies_impl
template <typename Fun>
struct satisfies_impl<Fun, false>
{
+ satisfies_impl() {}
satisfies_impl(Fun const& f) : fun(f) {}
Fun fun;
};
@@ -42,6 +44,7 @@ struct satisfies
{
typedef satisfies_impl<Fun, ::boost::is_function<Fun>::value> base;
+ satisfies() {}
satisfies(Fun const& f) : base(f) {}
satisfies(base const& b) : base(b) {}
};
@@ -60,6 +63,7 @@ struct within_tag {};
template <typename Geometry, typename Tag, bool Negated>
struct spatial_predicate
{
+ spatial_predicate() {}
spatial_predicate(Geometry const& g) : geometry(g) {}
Geometry geometry;
};
@@ -75,6 +79,9 @@ struct spatial_predicate
template <typename PointOrRelation>
struct nearest
{
+ nearest()
+// : count(0)
+ {}
nearest(PointOrRelation const& por, unsigned k)
: point_or_relation(por)
, count(k)
@@ -86,6 +93,9 @@ struct nearest
template <typename SegmentOrLinestring>
struct path
{
+ path()
+// : count(0)
+ {}
path(SegmentOrLinestring const& g, unsigned k)
: geometry(g)
, count(k)
diff --git a/boost/geometry/index/detail/rtree/iterators.hpp b/boost/geometry/index/detail/rtree/iterators.hpp
new file mode 100644
index 0000000000..a47dd7ea43
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/iterators.hpp
@@ -0,0 +1,122 @@
+// Boost.Geometry Index
+//
+// R-tree iterators
+//
+// Copyright (c) 2011-2015 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_RTREE_ITERATORS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
+
+template <typename Value, typename Allocators>
+struct end_iterator
+{
+ typedef std::forward_iterator_tag iterator_category;
+ typedef Value value_type;
+ typedef typename Allocators::const_reference reference;
+ typedef typename Allocators::difference_type difference_type;
+ typedef typename Allocators::const_pointer pointer;
+
+ reference operator*() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
+ pointer p(0);
+ return *p;
+ }
+
+ const value_type * operator->() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
+ const value_type * p = 0;
+ return p;
+ }
+
+ end_iterator & operator++()
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
+ return *this;
+ }
+
+ end_iterator operator++(int)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
+ return *this;
+ }
+
+ friend bool operator==(end_iterator const& /*l*/, end_iterator const& /*r*/)
+ {
+ return true;
+ }
+};
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class iterator
+{
+ typedef visitors::iterator<Value, Options, Translator, Box, Allocators> visitor_type;
+ typedef typename visitor_type::node_pointer node_pointer;
+
+public:
+ typedef std::forward_iterator_tag iterator_category;
+ typedef Value value_type;
+ typedef typename Allocators::const_reference reference;
+ typedef typename Allocators::difference_type difference_type;
+ typedef typename Allocators::const_pointer pointer;
+
+ inline iterator()
+ {}
+
+ inline iterator(node_pointer root)
+ {
+ m_visitor.initialize(root);
+ }
+
+ reference operator*() const
+ {
+ return m_visitor.dereference();
+ }
+
+ const value_type * operator->() const
+ {
+ return boost::addressof(m_visitor.dereference());
+ }
+
+ iterator & operator++()
+ {
+ m_visitor.increment();
+ return *this;
+ }
+
+ iterator operator++(int)
+ {
+ iterator temp = *this;
+ this->operator++();
+ return temp;
+ }
+
+ friend bool operator==(iterator const& l, iterator const& r)
+ {
+ return l.m_visitor == r.m_visitor;
+ }
+
+ friend bool operator==(iterator const& l, end_iterator<Value, Allocators> const& /*r*/)
+ {
+ return l.m_visitor.is_end();
+ }
+
+ friend bool operator==(end_iterator<Value, Allocators> const& /*l*/, iterator const& r)
+ {
+ return r.m_visitor.is_end();
+ }
+
+private:
+ visitor_type m_visitor;
+};
+
+}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node.hpp b/boost/geometry/index/detail/rtree/node/node.hpp
index 528d473170..b04744c85a 100644
--- a/boost/geometry/index/detail/rtree/node/node.hpp
+++ b/boost/geometry/index/detail/rtree/node/node.hpp
@@ -46,11 +46,7 @@ inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr)
{
Box result;
- if ( first == last )
- {
- geometry::assign_inverse(result);
- return result;
- }
+ BOOST_GEOMETRY_INDEX_ASSERT(first != last, "non-empty range required");
detail::bounds(element_indexable(*first, tr), result);
++first;
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
index b7be41ab2b..ce07d293db 100644
--- a/boost/geometry/index/detail/rtree/pack_create.hpp
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -11,6 +11,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>
+
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
namespace pack_utils {
@@ -157,8 +160,7 @@ public:
values_count = static_cast<size_type>(diff);
entries.reserve(values_count);
- Box hint_box;
- geometry::assign_inverse(hint_box);
+ expandable_box<Box> hint_box;
for ( ; first != last ; ++first )
{
// NOTE: support for iterators not returning true references adapted
@@ -172,7 +174,7 @@ public:
// CONSIDER: alternative - ignore invalid indexable or throw an exception
BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(indexable), "Indexable is invalid");
- geometry::expand(hint_box, indexable);
+ hint_box.expand(indexable);
point_type pt;
geometry::centroid(indexable, pt);
@@ -180,13 +182,49 @@ public:
}
subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters, leafs_level);
- internal_element el = per_level(entries.begin(), entries.end(), hint_box, values_count, subtree_counts,
+ internal_element el = per_level(entries.begin(), entries.end(), hint_box.get(), values_count, subtree_counts,
parameters, translator, allocators);
return el.second;
}
private:
+ template <typename BoxType>
+ class expandable_box
+ {
+ public:
+ expandable_box()
+ : m_initialized(false)
+ {}
+
+ template <typename Indexable>
+ void expand(Indexable const& indexable)
+ {
+ if ( !m_initialized )
+ {
+ // it's guaranteed that the Box will be initialized
+ // only for Points, Boxes and Segments but that's ok
+ // since only those Geometries can be stored
+ detail::bounds(indexable, m_box);
+ m_initialized = true;
+ }
+ else
+ {
+ geometry::expand(m_box, indexable);
+ }
+ }
+
+ BoxType const& get() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(m_initialized, "uninitialized envelope accessed");
+ return m_box;
+ }
+
+ private:
+ bool m_initialized;
+ BoxType m_box;
+ };
+
struct subtree_elements_counts
{
subtree_elements_counts(std::size_t ma, std::size_t mi) : maxc(ma), minc(mi) {}
@@ -216,19 +254,18 @@ private:
// reserve space for values
rtree::elements(l).reserve(values_count); // MAY THROW (A)
// calculate values box and copy values
- Box elements_box;
- geometry::assign_inverse(elements_box);
+ expandable_box<Box> elements_box;
for ( ; first != last ; ++first )
{
// NOTE: push_back() must be called at the end in order to support move_iterator.
// The iterator is dereferenced 2x (no temporary reference) to support
// non-true reference types and move_iterator without boost::forward<>.
- geometry::expand(elements_box, translator(*(first->second)));
+ elements_box.expand(translator(*(first->second)));
rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
}
auto_remover.release();
- return internal_element(elements_box, n);
+ return internal_element(elements_box.get(), n);
}
// calculate next max and min subtree counts
@@ -245,23 +282,22 @@ private:
std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts);
rtree::elements(in).reserve(nodes_count); // MAY THROW (A)
// calculate values box and copy values
- Box elements_box;
- geometry::assign_inverse(elements_box);
-
+ expandable_box<Box> elements_box;
+
per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts,
rtree::elements(in), elements_box,
parameters, translator, allocators);
auto_remover.release();
- return internal_element(elements_box, n);
+ return internal_element(elements_box.get(), n);
}
- template <typename EIt> inline static
+ template <typename EIt, typename ExpandableBox> inline static
void per_level_packets(EIt first, EIt last, Box const& hint_box,
std::size_t values_count,
subtree_elements_counts const& subtree_counts,
subtree_elements_counts const& next_subtree_counts,
- internal_elements & elements, Box & elements_box,
+ internal_elements & elements, ExpandableBox & elements_box,
parameters_type const& parameters, Translator const& translator, Allocators & allocators)
{
BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count,
@@ -285,7 +321,7 @@ private:
elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't
auto_remover.release();
- geometry::expand(elements_box, el.first);
+ elements_box.expand(el.first);
return;
}
diff --git a/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
index 634d879864..928ffd47d9 100644
--- a/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
@@ -2,7 +2,7 @@
//
// R-tree quadratic split algorithm implementation
//
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2015 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
@@ -57,7 +57,6 @@ inline void pick_seeds(Elements const& elements,
indexable_type const& ind2 = rtree::element_indexable(elements[j], tr);
box_type enlarged_box;
- //geometry::convert(ind1, enlarged_box);
detail::bounds(ind1, enlarged_box);
geometry::expand(enlarged_box, ind2);
@@ -133,9 +132,7 @@ struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadra
elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
// calculate boxes
- //geometry::convert(rtree::element_indexable(elements_copy[seed1], translator), box1);
detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);
- //geometry::convert(rtree::element_indexable(elements_copy[seed2], translator), box2);
detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), box2);
// remove seeds
diff --git a/boost/geometry/index/detail/rtree/query_iterators.hpp b/boost/geometry/index/detail/rtree/query_iterators.hpp
index 74000d03ef..83be106b8b 100644
--- a/boost/geometry/index/detail/rtree/query_iterators.hpp
+++ b/boost/geometry/index/detail/rtree/query_iterators.hpp
@@ -20,7 +20,7 @@ namespace boost { namespace geometry { namespace index { namespace detail { name
template <typename Value, typename Allocators>
struct end_query_iterator
{
- typedef std::input_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef Value value_type;
typedef typename Allocators::const_reference reference;
typedef typename Allocators::difference_type difference_type;
@@ -65,12 +65,15 @@ class spatial_query_iterator
typedef typename visitor_type::node_pointer node_pointer;
public:
- typedef std::input_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef Value value_type;
typedef typename Allocators::const_reference reference;
typedef typename Allocators::difference_type difference_type;
typedef typename Allocators::const_pointer pointer;
+ inline spatial_query_iterator()
+ {}
+
inline spatial_query_iterator(Translator const& t, Predicates const& p)
: m_visitor(t, p)
{}
@@ -130,12 +133,15 @@ class distance_query_iterator
typedef typename visitor_type::node_pointer node_pointer;
public:
- typedef std::input_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef Value value_type;
typedef typename Allocators::const_reference reference;
typedef typename Allocators::difference_type difference_type;
typedef typename Allocators::const_pointer pointer;
+ inline distance_query_iterator()
+ {}
+
inline distance_query_iterator(Translator const& t, Predicates const& p)
: m_visitor(t, p)
{}
@@ -188,22 +194,19 @@ private:
visitor_type m_visitor;
};
+
template <typename L, typename R>
inline bool operator!=(L const& l, R const& r)
{
return !(l == r);
}
-}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
-
-
-namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
template <typename Value, typename Allocators>
class query_iterator_base
{
public:
- typedef std::input_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef Value value_type;
typedef typename Allocators::const_reference reference;
typedef typename Allocators::difference_type difference_type;
@@ -226,12 +229,13 @@ class query_iterator_wrapper
typedef query_iterator_base<Value, Allocators> base_t;
public:
- typedef std::input_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef Value value_type;
typedef typename Allocators::const_reference reference;
typedef typename Allocators::difference_type difference_type;
typedef typename Allocators::const_pointer pointer;
+ query_iterator_wrapper() : m_iterator() {}
explicit query_iterator_wrapper(Iterator const& it) : m_iterator(it) {}
virtual base_t * clone() const { return new query_iterator_wrapper(m_iterator); }
@@ -258,13 +262,14 @@ class query_iterator
typedef boost::scoped_ptr<iterator_base> iterator_ptr;
public:
- typedef std::input_iterator_tag iterator_category;
+ typedef std::forward_iterator_tag iterator_category;
typedef Value value_type;
typedef typename Allocators::const_reference reference;
typedef typename Allocators::difference_type difference_type;
typedef typename Allocators::const_pointer pointer;
- query_iterator() {}
+ query_iterator()
+ {}
template <typename It>
query_iterator(It const& it)
diff --git a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
index fc0929e9ed..b930714433 100644
--- a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
@@ -337,6 +337,13 @@ public:
};
typedef std::vector<internal_stack_element> internal_stack_type;
+ inline distance_query_incremental()
+ : m_translator(NULL)
+// , m_pred()
+ , current_neighbor((std::numeric_limits<size_type>::max)())
+// , next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
+ {}
+
inline distance_query_incremental(Translator const& translator, Predicates const& pred)
: m_translator(::boost::addressof(translator))
, m_pred(pred)
@@ -428,6 +435,7 @@ public:
{
BOOST_GEOMETRY_INDEX_ASSERT(l.current_neighbor != r.current_neighbor ||
(std::numeric_limits<size_type>::max)() == l.current_neighbor ||
+ (std::numeric_limits<size_type>::max)() == r.current_neighbor ||
l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,
"not corresponding iterators");
return l.current_neighbor == r.current_neighbor;
diff --git a/boost/geometry/index/detail/rtree/visitors/iterator.hpp b/boost/geometry/index/detail/rtree/visitors/iterator.hpp
new file mode 100644
index 0000000000..621231ae9a
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/iterator.hpp
@@ -0,0 +1,134 @@
+// Boost.Geometry Index
+//
+// R-tree iterator visitor implementation
+//
+// Copyright (c) 2011-2015 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_RTREE_VISITORS_ITERATOR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class iterator
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+public:
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Allocators::size_type size_type;
+ typedef typename Allocators::const_reference const_reference;
+ typedef typename Allocators::node_pointer node_pointer;
+
+ typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
+ typedef typename rtree::elements_type<leaf>::type leaf_elements;
+ typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
+
+ inline iterator()
+ : m_values(NULL)
+ , m_current()
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ m_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ m_values = ::boost::addressof(rtree::elements(n));
+ m_current = rtree::elements(n).begin();
+ }
+
+ const_reference dereference() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");
+ return *m_current;
+ }
+
+ void initialize(node_pointer root)
+ {
+ rtree::apply_visitor(*this, *root);
+ search_value();
+ }
+
+ void increment()
+ {
+ ++m_current;
+ search_value();
+ }
+
+ void search_value()
+ {
+ for (;;)
+ {
+ // if leaf is choosen, move to the next value in leaf
+ if ( m_values )
+ {
+ // there are more values in the current leaf
+ if ( m_current != m_values->end() )
+ {
+ return;
+ }
+ // no more values, clear current leaf
+ else
+ {
+ m_values = 0;
+ }
+ }
+ // if leaf isn't choosen, move to the next leaf
+ else
+ {
+ // return if there is no more nodes to traverse
+ if ( m_internal_stack.empty() )
+ return;
+
+ // no more children in current node, remove it from stack
+ if ( m_internal_stack.back().first == m_internal_stack.back().second )
+ {
+ m_internal_stack.pop_back();
+ continue;
+ }
+
+ internal_iterator it = m_internal_stack.back().first;
+ ++m_internal_stack.back().first;
+
+ // push the next node to the stack
+ rtree::apply_visitor(*this, *(it->second));
+ }
+ }
+ }
+
+ bool is_end() const
+ {
+ return 0 == m_values;
+ }
+
+ friend bool operator==(iterator const& l, iterator const& r)
+ {
+ return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );
+ }
+
+private:
+
+ std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
+ const leaf_elements * m_values;
+ leaf_iterator m_current;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
index f00189fe77..b9cd0ae2c0 100644
--- a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
@@ -94,10 +94,18 @@ public:
static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
+ inline spatial_query_incremental()
+ : m_translator(NULL)
+// , m_pred()
+ , m_values(NULL)
+ , m_current()
+ {}
+
inline spatial_query_incremental(Translator const& t, Predicates const& p)
: m_translator(::boost::addressof(t))
, m_pred(p)
- , m_values(0)
+ , m_values(NULL)
+ , m_current()
{}
inline void operator()(internal_node const& n)
diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp
index 9d5d57d059..84c4da8a2a 100644
--- a/boost/geometry/index/rtree.hpp
+++ b/boost/geometry/index/rtree.hpp
@@ -59,6 +59,7 @@
#include <boost/geometry/index/detail/algorithms/is_valid.hpp>
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/iterator.hpp>
#include <boost/geometry/index/detail/rtree/visitors/remove.hpp>
#include <boost/geometry/index/detail/rtree/visitors/copy.hpp>
#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
@@ -78,6 +79,7 @@
#include <boost/geometry/index/detail/rtree/utilities/view.hpp>
+#include <boost/geometry/index/detail/rtree/iterators.hpp>
#include <boost/geometry/index/detail/rtree/query_iterators.hpp>
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
@@ -220,8 +222,17 @@ public:
/*! \brief Unsigned integral type used by the container. */
typedef typename allocators_type::size_type size_type;
- /*! \brief Type of const query iterator. */
- typedef index::detail::rtree::iterators::query_iterator<value_type, allocators_type> const_query_iterator;
+ /*! \brief Type of const iterator, category ForwardIterator. */
+ typedef index::detail::rtree::iterators::iterator
+ <
+ value_type, options_type, translator_type, box_type, allocators_type
+ > const_iterator;
+
+ /*! \brief Type of const query iterator, category ForwardIterator. */
+ typedef index::detail::rtree::iterators::query_iterator
+ <
+ value_type, allocators_type
+ > const_query_iterator;
public:
@@ -766,6 +777,27 @@ public:
tree.query(bgi::overlaps(box) && bgi::satisfies(my_fun), std::back_inserter(result));
// return 5 elements nearest to pt and elements are intersecting box
tree.query(bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));
+
+ // For each found value do_something (it is a type of function object)
+ tree.query(bgi::intersects(box),
+ boost::make_function_output_iterator(do_something()));
+
+ // For each value stored in the rtree do_something
+ // always_true is a type of function object always returning true
+ tree.query(bgi::satisfies(always_true()),
+ boost::make_function_output_iterator(do_something()));
+
+ // C++11 (lambda expression)
+ tree.query(bgi::intersects(box),
+ boost::make_function_output_iterator([](value_type const& val){
+ // do something
+ }));
+
+ // C++14 (generic lambda expression)
+ tree.query(bgi::intersects(box),
+ boost::make_function_output_iterator([](auto const& val){
+ // do something
+ }));
\endverbatim
\par Throws
@@ -774,7 +806,7 @@ public:
\warning
Only one \c nearest() perdicate may be passed to the query. Passing more of them results in compile-time error.
-
+
\param predicates Predicates.
\param out_it The output iterator, e.g. generated by std::back_inserter().
@@ -794,11 +826,11 @@ public:
}
/*!
- \brief Returns the query iterator pointing at the begin of the query range.
+ \brief Returns a query iterator pointing at the begin of the query range.
+
+ This method returns an iterator which may be used to perform iterative queries.
+ For the information about predicates which may be passed to this method see query().
- This method returns the iterator which may be used to perform iterative queries. For the information
- about the predicates which may be passed to this method see query().
-
\par Example
\verbatim
for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;
@@ -808,12 +840,29 @@ public:
if ( has_enough_nearest_values() )
break;
}
+
+ // C++11 (auto)
+ for ( auto it = tree.qbegin(bgi::nearest(pt, 3)) ; it != tree.qend() ; ++it )
+ {
+ // do something with value
+ }
+
+ // C++14 (generic lambda expression)
+ std::for_each(tree.qbegin(bgi::nearest(pt, 3)), tree.qend(), [](auto const& val){
+ // do something with value
+ });
\endverbatim
+ \par Iterator category
+ ForwardIterator
+
\par Throws
If predicates copy throws.
If allocation throws.
+ \warning
+ The modification of the rtree may invalidate the iterators.
+
\param predicates Predicates.
\return The iterator pointing at the begin of the query range.
@@ -825,10 +874,10 @@ public:
}
/*!
- \brief Returns the query iterator pointing at the end of the query range.
+ \brief Returns a query iterator pointing at the end of the query range.
+
+ This method returns an iterator which may be used to check if the query has ended.
- This method returns the iterator which may be used to check if the query has ended.
-
\par Example
\verbatim
for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;
@@ -838,10 +887,27 @@ public:
if ( has_enough_nearest_values() )
break;
}
+
+ // C++11 (auto)
+ for ( auto it = tree.qbegin(bgi::nearest(pt, 3)) ; it != tree.qend() ; ++it )
+ {
+ // do something with value
+ }
+
+ // C++14 (generic lambda expression)
+ std::for_each(tree.qbegin(bgi::nearest(pt, 3)), tree.qend(), [](auto const& val){
+ // do something with value
+ });
\endverbatim
+ \par Iterator category
+ ForwardIterator
+
\par Throws
Nothing
+
+ \warning
+ The modification of the rtree may invalidate the iterators.
\return The iterator pointing at the end of the query range.
*/
@@ -854,10 +920,10 @@ public:
private:
#endif
/*!
- \brief Returns the query iterator pointing at the begin of the query range.
+ \brief Returns a query iterator pointing at the begin of the query range.
- This method returns the iterator which may be used to perform iterative queries. For the information
- about the predicates which may be passed to this method see query().
+ This method returns an iterator which may be used to perform iterative queries.
+ For the information about predicates which may be passed to this method see query().
The type of the returned iterator depends on the type of passed Predicates but the iterator of this type
may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator
@@ -867,16 +933,24 @@ private:
\par Example
\verbatim
// Store the result in the container using std::copy() - it requires both iterators of the same type
- std::copy(tree.qbegin(bgi::intersects(box)), tree.qend(bgi::intersects(box)), std::back_inserter(result));
+ std::copy(tree.qbegin_(bgi::intersects(box)), tree.qend_(bgi::intersects(box)), std::back_inserter(result));
// Store the result in the container using std::copy() and type-erased iterators
- Rtree::const_query_iterator first = tree.qbegin(bgi::intersects(box));
- Rtree::const_query_iterator last = tree.qend();
+ Rtree::const_query_iterator first = tree.qbegin_(bgi::intersects(box));
+ Rtree::const_query_iterator last = tree.qend_();
std::copy(first, last, std::back_inserter(result));
// Boost.Typeof
typedef BOOST_TYPEOF(tree.qbegin(bgi::nearest(pt, 10000))) Iter;
- for ( Iter it = tree.qbegin(bgi::nearest(pt, 10000)) ; it != tree.qend() ; ++it )
+ for ( Iter it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )
+ {
+ // do something with value
+ if ( has_enough_nearest_values() )
+ break;
+ }
+
+ // C++11 (auto)
+ for ( auto it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )
{
// do something with value
if ( has_enough_nearest_values() )
@@ -884,10 +958,16 @@ private:
}
\endverbatim
+ \par Iterator category
+ ForwardIterator
+
\par Throws
If predicates copy throws.
If allocation throws.
+ \warning
+ The modification of the rtree may invalidate the iterators.
+
\param predicates Predicates.
\return The iterator pointing at the begin of the query range.
@@ -937,12 +1017,18 @@ private:
\par Example
\verbatim
// Store the result in the container using std::copy() - it requires both iterators of the same type
- std::copy(tree.qbegin(bgi::intersects(box)), tree.qend(bgi::intersects(box)), std::back_inserter(result));
+ std::copy(tree.qbegin_(bgi::intersects(box)), tree.qend_(bgi::intersects(box)), std::back_inserter(result));
\endverbatim
+ \par Iterator category
+ ForwardIterator
+
\par Throws
If predicates copy throws.
+ \warning
+ The modification of the rtree may invalidate the iterators.
+
\param predicates Predicates.
\return The iterator pointing at the end of the query range.
@@ -989,13 +1075,21 @@ private:
\par Example
\verbatim
// Store the result in the container using std::copy() and type-erased iterators
- Rtree::const_query_iterator first = tree.qbegin(bgi::intersects(box));
- Rtree::const_query_iterator last = tree.qend();
+ Rtree::const_query_iterator first = tree.qbegin_(bgi::intersects(box));
+ Rtree::const_query_iterator last = tree.qend_();
std::copy(first, last, std::back_inserter(result));
// Boost.Typeof
typedef BOOST_TYPEOF(tree.qbegin(bgi::nearest(pt, 10000))) Iter;
- for ( Iter it = tree.qbegin(bgi::nearest(pt, 10000)) ; it != tree.qend() ; ++it )
+ for ( Iter it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )
+ {
+ // do something with value
+ if ( has_enough_nearest_values() )
+ break;
+ }
+
+ // C++11 (auto)
+ for ( auto it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )
{
// do something with value
if ( has_enough_nearest_values() )
@@ -1003,8 +1097,14 @@ private:
}
\endverbatim
+ \par Iterator category
+ ForwardIterator
+
\par Throws
Nothing
+
+ \warning
+ The modification of the rtree may invalidate the iterators.
\return The iterator pointing at the end of the query range.
*/
@@ -1017,6 +1117,88 @@ private:
public:
/*!
+ \brief Returns the iterator pointing at the begin of the rtree values range.
+
+ This method returns the iterator which may be used to iterate over all values
+ stored in the rtree.
+
+ \par Example
+ \verbatim
+ // Copy all values into the vector
+ std::copy(tree.begin(), tree.end(), std::back_inserter(vec));
+
+ for ( Rtree::const_iterator it = tree.begin() ; it != tree.end() ; ++it )
+ {
+ // do something with value
+ }
+
+ // C++11 (auto)
+ for ( auto it = tree.begin() ; it != tree.end() ; ++it )
+ {
+ // do something with value
+ }
+
+ // C++14 (generic lambda expression)
+ std::for_each(tree.begin(), tree.end(), [](auto const& val){
+ // do something with value
+ })
+ \endverbatim
+
+ \par Iterator category
+ ForwardIterator
+
+ \par Throws
+ If allocation throws.
+
+ \warning
+ The modification of the rtree may invalidate the iterators.
+
+ \return The iterator pointing at the begin of the range.
+ */
+ const_iterator begin() const
+ {
+ if ( !m_members.root )
+ return const_iterator();
+
+ return const_iterator(m_members.root);
+ }
+
+ /*!
+ \brief Returns the iterator pointing at the end of the rtree values range.
+
+ This method returns the iterator which may be compared with the iterator returned by begin()
+ in order to check if the iteration has ended.
+
+ \par Example
+ \verbatim
+ for ( Rtree::const_iterator it = tree.begin() ; it != tree.end() ; ++it )
+ {
+ // do something with value
+ }
+
+ // C++11 (lambda expression)
+ std::for_each(tree.begin(), tree.end(), [](value_type const& val){
+ // do something with value
+ })
+ \endverbatim
+
+ \par Iterator category
+ ForwardIterator
+
+ \par Throws
+ Nothing.
+
+ \warning
+ The modification of the rtree may invalidate the iterators.
+
+ \return The iterator pointing at the end of the range.
+ */
+ const_iterator end() const
+ {
+ return const_iterator();
+ }
+
+ /*!
\brief Returns the number of stored values.
\return The number of stored values.
@@ -1763,6 +1945,10 @@ bgi::query(tree, bgi::intersects(poly) && !bgi::within(box), std::back_inserter(
bgi::query(tree, bgi::overlaps(box) && bgi::satisfies(my_fun), std::back_inserter(result));
// return 5 elements nearest to pt and elements are intersecting box
bgi::query(tree, bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));
+
+// For each found value do_something (it is a type of function object)
+tree.query(bgi::intersects(box),
+ boost::make_function_output_iterator(do_something()));
\endverbatim
\par Throws
@@ -1797,20 +1983,19 @@ about the predicates which may be passed to this method see query().
\par Example
\verbatim
-
-for ( Rtree::const_query_iterator it = qbegin(tree, bgi::nearest(pt, 10000)) ;
- it != qend(tree) ; ++it )
-{
- // do something with value
- if ( has_enough_nearest_values() )
- break;
-}
+std::for_each(bgi::qbegin(tree, bgi::nearest(pt, 3)), bgi::qend(tree), do_something());
\endverbatim
+\par Iterator category
+ForwardIterator
+
\par Throws
If predicates copy throws.
If allocation throws.
+\warning
+The modification of the rtree may invalidate the iterators.
+
\ingroup rtree_functions
\param tree The rtree.
@@ -1834,19 +2019,18 @@ This method returns the iterator which may be used to check if the query has end
\par Example
\verbatim
-
-for ( Rtree::const_query_iterator it = qbegin(tree, bgi::nearest(pt, 10000)) ;
- it != qend(tree) ; ++it )
-{
- // do something with value
- if ( has_enough_nearest_values() )
- break;
-}
+std::for_each(bgi::qbegin(tree, bgi::nearest(pt, 3)), bgi::qend(tree), do_something());
\endverbatim
+\par Iterator category
+ForwardIterator
+
\par Throws
Nothing
+\warning
+The modification of the rtree may invalidate the iterators.
+
\ingroup rtree_functions
\return The iterator pointing at the end of the query range.
@@ -1859,6 +2043,72 @@ qend(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)
}
/*!
+\brief Returns the iterator pointing at the begin of the rtree values range.
+
+This method returns the iterator which may be used to iterate over all values
+stored in the rtree.
+
+\par Example
+\verbatim
+std::for_each(bgi::begin(tree), bgi::end(tree), do_something());
+// the same as
+std::for_each(boost::begin(tree), boost::end(tree), do_something());
+\endverbatim
+
+\par Iterator category
+ForwardIterator
+
+\par Throws
+If allocation throws.
+
+\warning
+The modification of the rtree may invalidate the iterators.
+
+\ingroup rtree_functions
+
+\return The iterator pointing at the begin of the range.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator> inline
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::const_iterator
+begin(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)
+{
+ return tree.begin();
+}
+
+/*!
+\brief Returns the iterator pointing at the end of the rtree values range.
+
+This method returns the iterator which may be compared with the iterator returned by begin()
+in order to check if the iteration has ended.
+
+\par Example
+\verbatim
+std::for_each(bgi::begin(tree), bgi::end(tree), do_something());
+// the same as
+std::for_each(boost::begin(tree), boost::end(tree), do_something());
+\endverbatim
+
+\par Iterator category
+ForwardIterator
+
+\par Throws
+Nothing.
+
+\warning
+The modification of the rtree may invalidate the iterators.
+
+\ingroup rtree_functions
+
+\return The iterator pointing at the end of the range.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator> inline
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::const_iterator
+end(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)
+{
+ return tree.end();
+}
+
+/*!
\brief Remove all values from the index.
It calls \c rtree::clear().
@@ -1944,6 +2194,23 @@ inline void swap(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> &
}}} // namespace boost::geometry::index
+// Boost.Range adaptation
+namespace boost {
+
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+struct range_mutable_iterator
+ <
+ boost::geometry::index::rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>
+ >
+{
+ typedef typename boost::geometry::index::rtree
+ <
+ Value, Parameters, IndexableGetter, EqualTo, Allocator
+ >::const_iterator type;
+};
+
+} // namespace boost
+
// TODO: don't include the implementation at the end of the file
#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>
diff --git a/boost/geometry/io/svg/svg_mapper.hpp b/boost/geometry/io/svg/svg_mapper.hpp
index b53fef2ceb..c8e63d5ab7 100644
--- a/boost/geometry/io/svg/svg_mapper.hpp
+++ b/boost/geometry/io/svg/svg_mapper.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -16,6 +21,7 @@
#include <vector>
+#include <boost/config.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
@@ -31,15 +37,11 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/transform.hpp>
-#include <boost/geometry/algorithms/num_points.hpp>
-#include <boost/geometry/strategies/transform.hpp>
#include <boost/geometry/strategies/transform/map_transformer.hpp>
#include <boost/geometry/views/segment_view.hpp>
-#include <boost/geometry/multi/algorithms/envelope.hpp>
-#include <boost/geometry/multi/algorithms/num_points.hpp>
-
#include <boost/geometry/io/svg/write_svg.hpp>
// Helper geometries (all points are transformed to integer-points)
@@ -97,6 +99,11 @@ struct svg_map<box_tag, Box>
Box const& box, TransformStrategy const& strategy)
{
model::box<detail::svg::svg_point_type> ibox;
+
+ // Fix bug in gcc compiler warning for possible uninitialation
+#if defined(BOOST_GCC)
+ geometry::assign_zero(ibox);
+#endif
geometry::transform(box, ibox, strategy);
stream << geometry::svg(ibox, style, size) << std::endl;
@@ -307,7 +314,7 @@ public :
template <typename Geometry>
void add(Geometry const& geometry)
{
- if (num_points(geometry) > 0)
+ if (! geometry::is_empty(geometry))
{
expand(m_bounding_box,
return_envelope
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp
index 2415f21a69..a39c8f89d4 100644
--- a/boost/geometry/io/wkt/read.hpp
+++ b/boost/geometry/io/wkt/read.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, 2015.
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -64,7 +64,9 @@ struct read_wkt_exception : public geometry::exception
{
template <typename Iterator>
read_wkt_exception(std::string const& msg,
- Iterator const& it, Iterator const& end, std::string const& wkt)
+ Iterator const& it,
+ Iterator const& end,
+ std::string const& wkt)
: message(msg)
, wkt(wkt)
{
@@ -110,8 +112,10 @@ template <typename Point,
std::size_t DimensionCount = geometry::dimension<Point>::value>
struct parsing_assigner
{
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- Point& point, std::string const& wkt)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ Point& point,
+ std::string const& wkt)
{
typedef typename coordinate_type<Point>::type coordinate_type;
@@ -151,8 +155,10 @@ struct parsing_assigner
template <typename Point, std::size_t DimensionCount>
struct parsing_assigner<Point, DimensionCount, DimensionCount>
{
- static inline void apply(tokenizer::iterator&, tokenizer::iterator, Point&,
- std::string const&)
+ static inline void apply(tokenizer::iterator&,
+ tokenizer::iterator const&,
+ Point&,
+ std::string const&)
{
}
};
@@ -161,7 +167,8 @@ struct parsing_assigner<Point, DimensionCount, DimensionCount>
template <typename Iterator>
inline void handle_open_parenthesis(Iterator& it,
- Iterator const& end, std::string const& wkt)
+ Iterator const& end,
+ std::string const& wkt)
{
if (it == end || *it != "(")
{
@@ -173,7 +180,8 @@ inline void handle_open_parenthesis(Iterator& it,
template <typename Iterator>
inline void handle_close_parenthesis(Iterator& it,
- Iterator const& end, std::string const& wkt)
+ Iterator const& end,
+ std::string const& wkt)
{
if (it != end && *it == ")")
{
@@ -187,7 +195,8 @@ inline void handle_close_parenthesis(Iterator& it,
template <typename Iterator>
inline void check_end(Iterator& it,
- Iterator const& end, std::string const& wkt)
+ Iterator const& end,
+ std::string const& wkt)
{
if (it != end)
{
@@ -206,8 +215,10 @@ struct container_inserter
{
// Version with output iterator
template <typename OutputIterator>
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, OutputIterator out)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ std::string const& wkt,
+ OutputIterator out)
{
handle_open_parenthesis(it, end, wkt);
@@ -300,8 +311,10 @@ struct container_appender
{
typedef typename geometry::point_type<Geometry>::type point_type;
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, Geometry out)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ std::string const& wkt,
+ Geometry out)
{
handle_open_parenthesis(it, end, wkt);
@@ -335,8 +348,10 @@ struct container_appender
template <typename P>
struct point_parser
{
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, P& point)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ std::string const& wkt,
+ P& point)
{
handle_open_parenthesis(it, end, wkt);
parsing_assigner<P>::apply(it, end, point, wkt);
@@ -348,8 +363,10 @@ struct point_parser
template <typename Geometry>
struct linestring_parser
{
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, Geometry& geometry)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ std::string const& wkt,
+ Geometry& geometry)
{
container_appender<Geometry&>::apply(it, end, wkt, geometry);
}
@@ -359,8 +376,10 @@ struct linestring_parser
template <typename Ring>
struct ring_parser
{
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, Ring& ring)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ std::string const& wkt,
+ Ring& ring)
{
// A ring should look like polygon((x y,x y,x y...))
// So handle the extra opening/closing parentheses
@@ -382,8 +401,10 @@ struct polygon_parser
typedef typename ring_return_type<Polygon>::type ring_return_type;
typedef container_appender<ring_return_type> appender;
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, Polygon& poly)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ std::string const& wkt,
+ Polygon& poly)
{
handle_open_parenthesis(it, end, wkt);
@@ -423,8 +444,9 @@ struct polygon_parser
};
-inline bool one_of(tokenizer::iterator const& it, std::string const& value,
- bool& is_present)
+inline bool one_of(tokenizer::iterator const& it,
+ std::string const& value,
+ bool& is_present)
{
if (boost::iequals(*it, value))
{
@@ -434,8 +456,10 @@ inline bool one_of(tokenizer::iterator const& it, std::string const& value,
return false;
}
-inline bool one_of(tokenizer::iterator const& it, std::string const& value,
- bool& present1, bool& present2)
+inline bool one_of(tokenizer::iterator const& it,
+ std::string const& value,
+ bool& present1,
+ bool& present2)
{
if (boost::iequals(*it, value))
{
@@ -447,8 +471,11 @@ inline bool one_of(tokenizer::iterator const& it, std::string const& value,
}
-inline void handle_empty_z_m(tokenizer::iterator& it, tokenizer::iterator end,
- bool& has_empty, bool& has_z, bool& has_m)
+inline void handle_empty_z_m(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ bool& has_empty,
+ bool& has_z,
+ bool& has_m)
{
has_empty = false;
has_z = false;
@@ -478,15 +505,18 @@ inline void handle_empty_z_m(tokenizer::iterator& it, tokenizer::iterator end,
*/
template <typename Geometry>
inline bool initialize(tokenizer const& tokens,
- std::string const& geometry_name, std::string const& wkt,
- tokenizer::iterator& it)
+ std::string const& geometry_name,
+ std::string const& wkt,
+ tokenizer::iterator& it,
+ tokenizer::iterator& end)
{
it = tokens.begin();
- if (it != tokens.end() && boost::iequals(*it++, geometry_name))
+ end = tokens.end();
+ if (it != end && boost::iequals(*it++, geometry_name))
{
bool has_empty, has_z, has_m;
- handle_empty_z_m(it, tokens.end(), has_empty, has_z, has_m);
+ handle_empty_z_m(it, end, has_empty, has_z, has_m);
// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
@@ -505,7 +535,7 @@ inline bool initialize(tokenizer const& tokens,
if (has_empty)
{
- check_end(it, tokens.end(), wkt);
+ check_end(it, end, wkt);
return false;
}
// M is ignored at all.
@@ -524,11 +554,11 @@ struct geometry_parser
geometry::clear(geometry);
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- tokenizer::iterator it;
- if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it))
+ tokenizer::iterator it, end;
+ if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
{
- Parser<Geometry>::apply(it, tokens.end(), wkt, geometry);
- check_end(it, tokens.end(), wkt);
+ Parser<Geometry>::apply(it, end, wkt, geometry);
+ check_end(it, end, wkt);
}
}
};
@@ -542,38 +572,40 @@ struct multi_parser
traits::clear<MultiGeometry>::apply(geometry);
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- tokenizer::iterator it;
- if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it))
+ tokenizer::iterator it, end;
+ if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
{
- handle_open_parenthesis(it, tokens.end(), wkt);
+ handle_open_parenthesis(it, end, wkt);
// Parse sub-geometries
- while(it != tokens.end() && *it != ")")
+ while(it != end && *it != ")")
{
traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1);
Parser
<
typename boost::range_value<MultiGeometry>::type
- >::apply(it, tokens.end(), wkt, *(boost::end(geometry) - 1));
- if (it != tokens.end() && *it == ",")
+ >::apply(it, end, wkt, *(boost::end(geometry) - 1));
+ if (it != end && *it == ",")
{
// Skip "," after multi-element is parsed
++it;
}
}
- handle_close_parenthesis(it, tokens.end(), wkt);
+ handle_close_parenthesis(it, end, wkt);
}
- check_end(it, tokens.end(), wkt);
+ check_end(it, end, wkt);
}
};
template <typename P>
struct noparenthesis_point_parser
{
- static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
- std::string const& wkt, P& point)
+ static inline void apply(tokenizer::iterator& it,
+ tokenizer::iterator const& end,
+ std::string const& wkt,
+ P& point)
{
parsing_assigner<P>::apply(it, end, point, wkt);
}
@@ -587,17 +619,17 @@ struct multi_point_parser
traits::clear<MultiGeometry>::apply(geometry);
tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- tokenizer::iterator it;
+ tokenizer::iterator it, end;
- if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it))
+ if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))
{
- handle_open_parenthesis(it, tokens.end(), wkt);
+ handle_open_parenthesis(it, end, wkt);
// If first point definition starts with "(" then parse points as (x y)
// otherwise as "x y"
- bool using_brackets = (it != tokens.end() && *it == "(");
+ bool using_brackets = (it != end && *it == "(");
- while(it != tokens.end() && *it != ")")
+ while(it != end && *it != ")")
{
traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1);
@@ -606,27 +638,27 @@ struct multi_point_parser
point_parser
<
typename boost::range_value<MultiGeometry>::type
- >::apply(it, tokens.end(), wkt, *(boost::end(geometry) - 1));
+ >::apply(it, end, wkt, *(boost::end(geometry) - 1));
}
else
{
noparenthesis_point_parser
<
typename boost::range_value<MultiGeometry>::type
- >::apply(it, tokens.end(), wkt, *(boost::end(geometry) - 1));
+ >::apply(it, end, wkt, *(boost::end(geometry) - 1));
}
- if (it != tokens.end() && *it == ",")
+ if (it != end && *it == ",")
{
// Skip "," after point is parsed
++it;
}
}
- handle_close_parenthesis(it, tokens.end(), wkt);
+ handle_close_parenthesis(it, end, wkt);
}
- check_end(it, tokens.end(), wkt);
+ check_end(it, end, wkt);
}
};
diff --git a/boost/geometry/io/wkt/write.hpp b/boost/geometry/io/wkt/write.hpp
index add40e2551..a556aa440f 100644
--- a/boost/geometry/io/wkt/write.hpp
+++ b/boost/geometry/io/wkt/write.hpp
@@ -1,9 +1,14 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// 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.
+
+// 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -28,7 +33,7 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/convert.hpp>
-#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
@@ -150,7 +155,7 @@ struct wkt_range
// optionally, close range to ring by repeating the first point
if (force_closed
&& boost::size(range) > 1
- && geometry::disjoint(*begin, *(end - 1)))
+ && detail::disjoint::disjoint_point_point(*begin, *(end - 1)))
{
os << ",";
stream_type::apply(os, *begin);
@@ -444,7 +449,7 @@ struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry
)
{
- apply_visitor(visitor<OutputStream>(os), geometry);
+ boost::apply_visitor(visitor<OutputStream>(os), geometry);
}
};
diff --git a/boost/geometry/iterators/concatenate_iterator.hpp b/boost/geometry/iterators/concatenate_iterator.hpp
index 5c4ae0af1e..ea5728d0bc 100644
--- a/boost/geometry/iterators/concatenate_iterator.hpp
+++ b/boost/geometry/iterators/concatenate_iterator.hpp
@@ -10,7 +10,6 @@
#ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP
-#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator.hpp>
diff --git a/boost/geometry/iterators/detail/segment_iterator/value_type.hpp b/boost/geometry/iterators/detail/segment_iterator/value_type.hpp
index 0b3c66670c..ff3267c884 100644
--- a/boost/geometry/iterators/detail/segment_iterator/value_type.hpp
+++ b/boost/geometry/iterators/detail/segment_iterator/value_type.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -10,7 +10,14 @@
#ifndef BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_VALUE_TYPE_HPP
#define BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_VALUE_TYPE_HPP
-#include <boost/geometry/iterators/detail/point_iterator/value_type.hpp>
+#include <iterator>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_reference.hpp>
+
+#include <boost/geometry/iterators/point_iterator.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/pointing_segment.hpp>
@@ -24,15 +31,36 @@ namespace detail { namespace segment_iterator
template <typename Geometry>
struct value_type
{
+ typedef typename std::iterator_traits
+ <
+ geometry::point_iterator<Geometry>
+ >::reference point_iterator_reference_type;
+
typedef typename detail::point_iterator::value_type
<
Geometry
>::type point_iterator_value_type;
- typedef geometry::model::pointing_segment
+ // If the reference type of the point iterator is not really a
+ // reference, then dereferencing a point iterator would create
+ // a temporary object.
+ // In this case using a pointing_segment to represent the
+ // dereferenced value of the segment iterator cannot be used, as
+ // it would store pointers to temporary objects. Instead we use a
+ // segment, which does a full copy of the temporary objects
+ // returned by the point iterator.
+ typedef typename boost::mpl::if_
<
- point_iterator_value_type
- > type;
+ boost::is_reference<point_iterator_reference_type>,
+ geometry::model::pointing_segment<point_iterator_value_type>,
+ geometry::model::segment
+ <
+ typename geometry::util::bare_type
+ <
+ point_iterator_value_type
+ >::type
+ >
+ >::type type;
};
}} // namespace detail::segment_iterator
diff --git a/boost/geometry/iterators/flatten_iterator.hpp b/boost/geometry/iterators/flatten_iterator.hpp
index 07450afbea..5ba7050220 100644
--- a/boost/geometry/iterators/flatten_iterator.hpp
+++ b/boost/geometry/iterators/flatten_iterator.hpp
@@ -10,13 +10,13 @@
#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP
-#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
+#include <boost/geometry/core/assert.hpp>
namespace boost { namespace geometry
{
@@ -154,8 +154,8 @@ private:
inline Reference dereference() const
{
- BOOST_ASSERT( m_outer_it != m_outer_end );
- BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
+ BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
+ BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
return *m_inner_it;
}
@@ -194,8 +194,8 @@ private:
inline void increment()
{
- BOOST_ASSERT( m_outer_it != m_outer_end );
- BOOST_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
+ BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );
+ BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );
++m_inner_it;
if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )
@@ -215,12 +215,9 @@ private:
--m_outer_it;
}
while ( empty(m_outer_it) );
- m_inner_it = --AccessInnerEnd::apply(*m_outer_it);
- }
- else
- {
- --m_inner_it;
- }
+ m_inner_it = AccessInnerEnd::apply(*m_outer_it);
+ }
+ --m_inner_it;
}
};
diff --git a/boost/geometry/iterators/point_iterator.hpp b/boost/geometry/iterators/point_iterator.hpp
index 5971cfcef0..5ee0e54917 100644
--- a/boost/geometry/iterators/point_iterator.hpp
+++ b/boost/geometry/iterators/point_iterator.hpp
@@ -10,7 +10,6 @@
#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP
-#include <boost/assert.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
diff --git a/boost/geometry/multi/multi.hpp b/boost/geometry/multi/multi.hpp
index 4b3063e520..85d763ee6e 100644
--- a/boost/geometry/multi/multi.hpp
+++ b/boost/geometry/multi/multi.hpp
@@ -1,11 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013.
-// Modifications copyright (c) 2013, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2015.
+// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -17,65 +17,8 @@
#ifndef BOOST_GEOMETRY_MULTI_HPP
#define BOOST_GEOMETRY_MULTI_HPP
-
-#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/geometry_id.hpp>
-#include <boost/geometry/core/interior_rings.hpp>
-#include <boost/geometry/core/is_areal.hpp>
-#include <boost/geometry/core/point_order.hpp>
-#include <boost/geometry/core/point_type.hpp>
-#include <boost/geometry/core/ring_type.hpp>
-#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/core/topological_dimension.hpp>
-
-#include <boost/geometry/algorithms/append.hpp>
-#include <boost/geometry/algorithms/area.hpp>
-#include <boost/geometry/algorithms/centroid.hpp>
-#include <boost/geometry/algorithms/clear.hpp>
-#include <boost/geometry/algorithms/convert.hpp>
-#include <boost/geometry/algorithms/correct.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/disjoint.hpp>
-#include <boost/geometry/algorithms/distance.hpp>
-#include <boost/geometry/algorithms/envelope.hpp>
-#include <boost/geometry/algorithms/equals.hpp>
-#include <boost/geometry/algorithms/for_each.hpp>
-#include <boost/geometry/algorithms/intersection.hpp>
-#include <boost/geometry/algorithms/length.hpp>
-#include <boost/geometry/algorithms/num_geometries.hpp>
-#include <boost/geometry/algorithms/num_interior_rings.hpp>
-#include <boost/geometry/algorithms/num_points.hpp>
-#include <boost/geometry/algorithms/perimeter.hpp>
-#include <boost/geometry/algorithms/remove_spikes.hpp>
-#include <boost/geometry/algorithms/reverse.hpp>
-#include <boost/geometry/algorithms/simplify.hpp>
-#include <boost/geometry/algorithms/transform.hpp>
-#include <boost/geometry/algorithms/unique.hpp>
-#include <boost/geometry/algorithms/within.hpp>
-
-#include <boost/geometry/algorithms/detail/point_on_border.hpp>
-
-#include <boost/geometry/algorithms/detail/for_each_range.hpp>
-#include <boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp>
-#include <boost/geometry/algorithms/detail/multi_sum.hpp>
-
-#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
-#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
-
-#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
-#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
-#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
-#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
-#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
-#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
-
-#include <boost/geometry/geometries/concepts/check.hpp>
-
-#include <boost/geometry/views/detail/range_type.hpp>
-#include <boost/geometry/strategies/cartesian/centroid_average.hpp>
-
-#include <boost/geometry/io/dsv/write.hpp>
-#include <boost/geometry/io/wkt/wkt.hpp>
-
+// keep this file for now, for backward compatibility
+// functionality-wise, make it equivalent to boost/geometry/geometry.hpp
+#include <boost/geometry/geometry.hpp>
#endif // BOOST_GEOMETRY_MULTI_HPP
diff --git a/boost/geometry/policies/is_valid/failing_reason_policy.hpp b/boost/geometry/policies/is_valid/failing_reason_policy.hpp
index b99803bead..d1918adbda 100644
--- a/boost/geometry/policies/is_valid/failing_reason_policy.hpp
+++ b/boost/geometry/policies/is_valid/failing_reason_policy.hpp
@@ -3,6 +3,7 @@
// 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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -13,6 +14,7 @@
#include <sstream>
#include <boost/geometry/io/dsv/write.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
@@ -65,7 +67,8 @@ private:
static inline
validity_failure_type transform_failure_type(validity_failure_type failure)
{
- if (AllowDuplicates && failure == failure_duplicate_points)
+ if (BOOST_GEOMETRY_CONDITION(
+ AllowDuplicates && failure == failure_duplicate_points))
{
return no_failure;
}
@@ -76,7 +79,8 @@ private:
validity_failure_type transform_failure_type(validity_failure_type failure,
bool is_linear)
{
- if (is_linear && AllowSpikes && failure == failure_spikes)
+ if (BOOST_GEOMETRY_CONDITION(
+ is_linear && AllowSpikes && failure == failure_spikes))
{
return no_failure;
}
@@ -117,7 +121,7 @@ private:
bool is_linear,
SpikePoint const& spike_point)
{
- if (is_linear && AllowSpikes)
+ if (BOOST_GEOMETRY_CONDITION(is_linear && AllowSpikes))
{
return;
}
@@ -167,7 +171,7 @@ private:
static inline void apply(std::ostringstream& oss,
Point const& point)
{
- if (AllowDuplicates)
+ if (BOOST_GEOMETRY_CONDITION(AllowDuplicates))
{
return;
}
diff --git a/boost/geometry/policies/relate/de9im.hpp b/boost/geometry/policies/relate/de9im.hpp
deleted file mode 100644
index e2d6b5111c..0000000000
--- a/boost/geometry/policies/relate/de9im.hpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
-#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
-
-
-#include <boost/geometry/strategies/intersection_result.hpp>
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/select_coordinate_type.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-namespace policies { namespace relate
-{
-
-
-template <typename S1, typename S2>
-struct segments_de9im
-{
- typedef de9im_segment return_type;
- typedef S1 segment_type1;
- typedef S2 segment_type2;
- typedef typename select_coordinate_type<S1, S2>::type coordinate_type;
-
- static inline return_type rays_intersect(bool on_segment,
- double ra, double rb,
- coordinate_type const& dx1, coordinate_type const& dy1,
- coordinate_type const& dx2, coordinate_type const& dy2,
- coordinate_type const& wx, coordinate_type const& wy,
- S1 const& s1, S2 const& s2)
- {
- if(on_segment)
- {
- // 0 <= ra <= 1 and 0 <= rb <= 1
- // Now check if one of them is 0 or 1, these are "touch" cases
- bool a = math::equals(ra, 0.0) || math::equals(ra, 1.0);
- bool b = math::equals(rb, 0.0) || math::equals(rb, 1.0);
- if (a && b)
- {
- // Touch boundary/boundary: i-i == -1, i-b == -1, b-b == 0
- // Opposite: if both are equal they touch in opposite direction
- return de9im_segment(ra,rb,
- -1, -1, 1,
- -1, 0, 0,
- 1, 0, 2, false, math::equals(ra,rb));
- }
- else if (a || b)
- {
- // Touch boundary/interior: i-i == -1, i-b == -1 or 0, b-b == -1
- int A = a ? 0 : -1;
- int B = b ? 0 : -1;
- return de9im_segment(ra,rb,
- -1, B, 1,
- A, -1, 0,
- 1, 0, 2);
- }
-
- // Intersects: i-i == 0, i-b == -1, i-e == 1
- return de9im_segment(ra,rb,
- 0, -1, 1,
- -1, -1, 0,
- 1, 0, 2);
- }
-
- // Not on segment, disjoint
- return de9im_segment(ra,rb,
- -1, -1, 1,
- -1, -1, 0,
- 1, 0, 2);
- }
-
- static inline return_type collinear_touch(coordinate_type const& x,
- coordinate_type const& y, bool opposite, char)
- {
- return de9im_segment(0,0,
- -1, -1, 1,
- -1, 0, 0,
- 1, 0, 2,
- true, opposite);
- }
-
- template <typename S>
- static inline return_type collinear_interior_boundary_intersect(S const& s,
- bool a_within_b, bool opposite)
- {
- return a_within_b
- ? de9im_segment(0,0,
- 1, -1, -1,
- 0, 0, -1,
- 1, 0, 2,
- true, opposite)
- : de9im_segment(0,0,
- 1, 0, 1,
- -1, 0, 0,
- -1, -1, 2,
- true, opposite);
- }
-
-
-
- static inline return_type collinear_a_in_b(S1 const& s, bool opposite)
- {
- return de9im_segment(0,0,
- 1, -1, -1,
- 0, -1, -1,
- 1, 0, 2,
- true, opposite);
- }
- static inline return_type collinear_b_in_a(S2 const& s, bool opposite)
- {
- return de9im_segment(0,0,
- 1, 0, 1,
- -1, -1, 0,
- -1, -1, 2,
- true, opposite);
- }
-
- static inline return_type collinear_overlaps(
- coordinate_type const& x1, coordinate_type const& y1,
- coordinate_type const& x2, coordinate_type const& y2, bool opposite)
- {
- return de9im_segment(0,0,
- 1, 0, 1,
- 0, -1, 0,
- 1, 0, 2,
- true, opposite);
- }
-
- static inline return_type segment_equal(S1 const& s, bool opposite)
- {
- return de9im_segment(0,0,
- 1, -1, -1,
- -1, 0, -1,
- -1, -1, 2,
- true, opposite);
- }
-
- static inline return_type degenerate(S1 const& segment, bool a_degenerate)
- {
- return a_degenerate
- ? de9im_segment(0,0,
- 0, -1, -1,
- -1, -1, -1,
- 1, 0, 2,
- false, false, false, true)
- : de9im_segment(0,0,
- 0, -1, 1,
- -1, -1, 0,
- -1, -1, 2,
- false, false, false, true);
- }
-
-};
-
-
-}} // namespace policies::relate
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
diff --git a/boost/geometry/policies/relate/intersection_points.hpp b/boost/geometry/policies/relate/intersection_points.hpp
index 082dc4ca7f..50f9b43122 100644
--- a/boost/geometry/policies/relate/intersection_points.hpp
+++ b/boost/geometry/policies/relate/intersection_points.hpp
@@ -18,6 +18,7 @@
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/util/promote_integral.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
@@ -60,7 +61,7 @@ struct segments_intersection_points
// Up to now, division was postponed. Here we divide using numerator/
// denominator. In case of integer this results in an integer
// division.
- BOOST_ASSERT(ratio.denominator() != 0);
+ BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0);
typedef typename promote_integral<coordinate_type>::type promoted_type;
@@ -81,7 +82,6 @@ struct segments_intersection_points
>(numerator * dy_promoted / denominator));
}
-
template
<
typename Segment1,
@@ -95,7 +95,33 @@ struct segments_intersection_points
return_type result;
result.count = 1;
- if (sinfo.robust_ra < sinfo.robust_rb)
+ bool use_a = true;
+
+ // Prefer one segment if one is on or near an endpoint
+ bool const a_near_end = sinfo.robust_ra.near_end();
+ bool const b_near_end = sinfo.robust_rb.near_end();
+ if (a_near_end && ! b_near_end)
+ {
+ use_a = true;
+ }
+ else if (b_near_end && ! a_near_end)
+ {
+ use_a = false;
+ }
+ else
+ {
+ // Prefer shorter segment
+ typedef typename SegmentIntersectionInfo::promoted_type ptype;
+ ptype const len_a = sinfo.dx_a * sinfo.dx_a + sinfo.dy_a * sinfo.dy_a;
+ ptype const len_b = sinfo.dx_b * sinfo.dx_b + sinfo.dy_b * sinfo.dy_b;
+ if (len_b < len_a)
+ {
+ use_a = false;
+ }
+ // else use_a is true but was already assigned like that
+ }
+
+ if (use_a)
{
assign(result.intersections[0], s1, sinfo.robust_ra,
sinfo.dx_a, sinfo.dy_a);
diff --git a/boost/geometry/policies/robustness/get_rescale_policy.hpp b/boost/geometry/policies/robustness/get_rescale_policy.hpp
index 52570995f6..e7bef1d2e1 100644
--- a/boost/geometry/policies/robustness/get_rescale_policy.hpp
+++ b/boost/geometry/policies/robustness/get_rescale_policy.hpp
@@ -23,10 +23,12 @@
#include <boost/type_traits.hpp>
#include <boost/mpl/assert.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/algorithms/detail/get_max_size.hpp>
#include <boost/geometry/policies/robustness/robust_type.hpp>
@@ -66,11 +68,18 @@ inline void scale_box_to_integer_range(Box const& box,
num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(box));
num_type const range = 10000000.0; // Define a large range to get precise integer coordinates
num_type const half = 0.5;
- factor = math::equals(diff, num_type()) || diff >= range ? 1
- : boost::numeric_cast<num_type>(
+ if (math::equals(diff, num_type())
+ || diff >= range
+ || ! boost::math::isfinite(diff))
+ {
+ factor = 1;
+ }
+ else
+ {
+ factor = boost::numeric_cast<num_type>(
boost::numeric_cast<boost::long_long_type>(half + range / diff));
-
- BOOST_ASSERT(factor >= 1);
+ BOOST_GEOMETRY_ASSERT(factor >= 1);
+ }
// Assign input/output minimal points
detail::assign_point_from_index<0>(box, min_point);
@@ -86,6 +95,11 @@ static inline void init_rescale_policy(Geometry const& geometry,
RobustPoint& min_robust_point,
Factor& factor)
{
+ if (geometry::is_empty(geometry))
+ {
+ return;
+ }
+
// Get bounding boxes
model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);
@@ -99,10 +113,36 @@ static inline void init_rescale_policy(Geometry1 const& geometry1,
RobustPoint& min_robust_point,
Factor& factor)
{
- // Get bounding boxes
- model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry1);
- model::box<Point> env2 = geometry::return_envelope<model::box<Point> >(geometry2);
- geometry::expand(env, env2);
+ // Get bounding boxes (when at least one of the geometries is not empty)
+ bool const is_empty1 = geometry::is_empty(geometry1);
+ bool const is_empty2 = geometry::is_empty(geometry2);
+ if (is_empty1 && is_empty2)
+ {
+ return;
+ }
+
+ model::box<Point> env;
+ if (is_empty1)
+ {
+ geometry::envelope(geometry2, env);
+ }
+ else if (is_empty2)
+ {
+ geometry::envelope(geometry1, env);
+ }
+ else
+ {
+ // The following approach (envelope + expand) may not give the
+ // optimal MBR when then two geometries are in the spherical
+ // equatorial or geographic coordinate systems.
+ // TODO: implement envelope for two (or possibly more geometries)
+ geometry::envelope(geometry1, env);
+ model::box<Point> env2 = geometry::return_envelope
+ <
+ model::box<Point>
+ >(geometry2);
+ geometry::expand(env, env2);
+ }
scale_box_to_integer_range(env, min_point, min_robust_point, factor);
}
diff --git a/boost/geometry/policies/robustness/rescale_policy.hpp b/boost/geometry/policies/robustness/rescale_policy.hpp
index 5b3b566976..8f34bf3dee 100644
--- a/boost/geometry/policies/robustness/rescale_policy.hpp
+++ b/boost/geometry/policies/robustness/rescale_policy.hpp
@@ -1,9 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2014 Bruno Lalande, Paris, France.
-// Copyright (c) 2014 Mateusz Loskot, London, UK.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2014-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2014-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
+
+// Copyright (c) 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
@@ -20,6 +24,8 @@
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
+#include <boost/geometry/util/math.hpp>
+
namespace boost { namespace geometry
{
@@ -48,7 +54,8 @@ struct robust_policy
CalculationType const a = static_cast<CalculationType>(get<Dimension>(m_int_min));
CalculationType const b = static_cast<CalculationType>(get<Dimension>(m_fp_min));
CalculationType const result = a + (value - b) * m_multiplier;
- return static_cast<output_ct>(result);
+
+ return geometry::math::rounding_cast<output_ct>(result);
}
FpPoint m_fp_min;
diff --git a/boost/geometry/policies/robustness/segment_ratio.hpp b/boost/geometry/policies/robustness/segment_ratio.hpp
index 8b55605c7f..ec659257a2 100644
--- a/boost/geometry/policies/robustness/segment_ratio.hpp
+++ b/boost/geometry/policies/robustness/segment_ratio.hpp
@@ -9,10 +9,10 @@
#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
-#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/rational.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
@@ -47,8 +47,8 @@ struct less<Type, false>
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
- BOOST_ASSERT(lhs.denominator() != 0);
- BOOST_ASSERT(rhs.denominator() != 0);
+ BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);
+ BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);
return lhs.numerator() * rhs.denominator()
< rhs.numerator() * lhs.denominator();
}
@@ -78,8 +78,8 @@ struct equal<Type, false>
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
- BOOST_ASSERT(lhs.denominator() != 0);
- BOOST_ASSERT(rhs.denominator() != 0);
+ BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);
+ BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);
return geometry::math::equals
(
lhs.numerator() * rhs.denominator(),
@@ -139,14 +139,12 @@ public :
m_denominator = -m_denominator;
}
- typedef typename promote_floating_point<Type>::type num_type;
- static const num_type scale = 1000000.0;
m_approximation =
m_denominator == 0 ? 0
: boost::numeric_cast<double>
(
- boost::numeric_cast<num_type>(m_numerator) * scale
- / boost::numeric_cast<num_type>(m_denominator)
+ boost::numeric_cast<fp_type>(m_numerator) * scale()
+ / boost::numeric_cast<fp_type>(m_denominator)
);
}
@@ -178,6 +176,18 @@ public :
return m_numerator > m_denominator;
}
+ inline bool near_end() const
+ {
+ if (left() || right())
+ {
+ return false;
+ }
+
+ static fp_type const small_part_of_scale = scale() / 100.0;
+ return m_approximation < small_part_of_scale
+ || m_approximation > scale() - small_part_of_scale;
+ }
+
inline bool close_to(thistype const& other) const
{
return geometry::math::abs(m_approximation - other.m_approximation) < 2;
@@ -222,6 +232,8 @@ public :
private :
+ typedef typename promote_floating_point<Type>::type fp_type;
+
Type m_numerator;
Type m_denominator;
@@ -230,7 +242,13 @@ private :
// Boost.Rational is used if the approximations are close.
// Reason: performance, Boost.Rational does a GCD by default and also the
// comparisons contain while-loops.
- double m_approximation;
+ fp_type m_approximation;
+
+
+ static inline fp_type scale()
+ {
+ return 1000000.0;
+ }
};
diff --git a/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
index 1d59e13cf6..0cd0cdc4db 100644
--- a/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
+++ b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
@@ -24,6 +24,7 @@
#include <boost/range.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
@@ -354,7 +355,7 @@ private:
{
std::copy(boost::begin(first), boost::end(first), out);
- BOOST_ASSERT(closed ? !boost::empty(second) : boost::size(second) > 1);
+ BOOST_GEOMETRY_ASSERT(closed ? !boost::empty(second) : boost::size(second) > 1);
std::copy(++boost::rbegin(second), // skip the first Point
closed ? boost::rend(second) : --boost::rend(second), // skip the last Point if open
out);
diff --git a/boost/geometry/strategies/agnostic/relate.hpp b/boost/geometry/strategies/agnostic/relate.hpp
index 9e8753251d..676207694f 100644
--- a/boost/geometry/strategies/agnostic/relate.hpp
+++ b/boost/geometry/strategies/agnostic/relate.hpp
@@ -1,17 +1,17 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014 Oracle and/or its affiliates.
+// 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)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP
-#include <boost/geometry/algorithms/detail/relate/relate.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
namespace boost { namespace geometry
@@ -25,7 +25,7 @@ struct relate
{
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return detail::relate::relate<StaticMask>(geometry1, geometry2);
+ return geometry::relate(geometry1, geometry2, StaticMask());
}
};
@@ -47,7 +47,10 @@ struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geomet
<
Geometry1,
Geometry2,
- detail::relate::static_mask_within
+ typename detail::de9im::static_mask_within_type
+ <
+ Geometry1, Geometry2
+ >::type
> type;
};
@@ -58,7 +61,10 @@ struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geom
<
Geometry1,
Geometry2,
- detail::relate::static_mask_within
+ typename detail::de9im::static_mask_within_type
+ <
+ Geometry1, Geometry2
+ >::type
> type;
};
@@ -84,7 +90,10 @@ struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geomet
<
Geometry1,
Geometry2,
- detail::relate::static_mask_covered_by
+ typename detail::de9im::static_mask_covered_by_type
+ <
+ Geometry1, Geometry2
+ >::type
> type;
};
@@ -95,7 +104,10 @@ struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geom
<
Geometry1,
Geometry2,
- detail::relate::static_mask_covered_by
+ typename detail::de9im::static_mask_covered_by_type
+ <
+ Geometry1, Geometry2
+ >::type
> type;
};
diff --git a/boost/geometry/strategies/agnostic/side_by_azimuth.hpp b/boost/geometry/strategies/agnostic/side_by_azimuth.hpp
deleted file mode 100644
index 14c69a0597..0000000000
--- a/boost/geometry/strategies/agnostic/side_by_azimuth.hpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// Boost.Geometry
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
-
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_SIDE_BY_AZIMUTH_HPP
-#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_SIDE_BY_AZIMUTH_HPP
-
-#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
-#include <boost/core/ignore_unused.hpp>
-
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/radian_access.hpp>
-
-#include <boost/geometry/algorithms/detail/azimuth.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
-{
-
-/*!
-\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 CalculationType \tparam_calculation
- */
-template <typename Model, typename CalculationType = void>
-class side_by_azimuth
-{
-public:
- side_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;
-
- calc_t d1 = 0.001;
- calc_t crs_AD = geometry::detail::azimuth<calc_t>(p1, p, m_model);
- calc_t crs_AB = geometry::detail::azimuth<calc_t>(p1, p2, m_model);
- calc_t XTD = asin(sin(d1) * sin(crs_AD - crs_AB));
-
- return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1;
- }
-
-private:
- Model m_model;
-};
-
-}} // namespace strategy::side
-
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_SIDE_BY_AZIMUTH_HPP
diff --git a/boost/geometry/strategies/buffer.hpp b/boost/geometry/strategies/buffer.hpp
index 7dbe03b4a9..86bdcc37bf 100644
--- a/boost/geometry/strategies/buffer.hpp
+++ b/boost/geometry/strategies/buffer.hpp
@@ -66,7 +66,8 @@ enum piece_type
buffered_round_end,
buffered_flat_end,
buffered_point,
- buffered_concave // always on the inside
+ buffered_concave, // always on the inside
+ piece_type_unknown
};
@@ -82,6 +83,17 @@ enum join_selector
join_spike // collinear, with overlap, next segment goes back
};
+/*!
+\brief Enumerates types of result codes from buffer strategies
+\ingroup enum
+*/
+enum result_code
+{
+ result_normal,
+ result_error_numerical,
+ result_no_output
+};
+
}} // namespace strategy::buffer
diff --git a/boost/geometry/strategies/cartesian/buffer_end_round.hpp b/boost/geometry/strategies/cartesian/buffer_end_round.hpp
index a233f1c4be..3d7d5bb467 100644
--- a/boost/geometry/strategies/cartesian/buffer_end_round.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_end_round.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2012-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
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -62,8 +67,7 @@ private :
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
- PromotedType const two = 2.0;
- PromotedType const two_pi = two * geometry::math::pi<PromotedType>();
+ PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
std::size_t point_buffer_count = m_points_per_circle;
diff --git a/boost/geometry/strategies/cartesian/buffer_join_miter.hpp b/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
index 99ec80527f..5358156f6d 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
@@ -9,7 +9,7 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
-#include <boost/assert.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/util/math.hpp>
@@ -99,7 +99,7 @@ public:
if (distance > max_distance)
{
- BOOST_ASSERT(distance != 0.0);
+ BOOST_GEOMETRY_ASSERT(distance != 0.0);
promoted_type const proportion = max_distance / distance;
set<0>(p, get<0>(vertex) + dx * proportion);
diff --git a/boost/geometry/strategies/cartesian/buffer_join_round.hpp b/boost/geometry/strategies/cartesian/buffer_join_round.hpp
index 9ec51cd1ec..e1a433e1ee 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_round.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_round.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2012-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
+
// 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)
@@ -11,7 +16,6 @@
#include <algorithm>
-#include <boost/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
@@ -19,6 +23,7 @@
#include <boost/geometry/util/select_most_precise.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
+#include <iostream>
#include <boost/geometry/io/wkt/wkt.hpp>
#endif
@@ -76,8 +81,7 @@ private :
PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
- PromotedType const two = 2.0;
- PromotedType const two_pi = two * geometry::math::pi<PromotedType>();
+ PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
PromotedType const angle1 = atan2(dy1, dx1);
PromotedType angle2 = atan2(dy2, dx2);
@@ -96,14 +100,14 @@ private :
// - generates 1 point in between for an angle of 125 based on 3 points
// - generates 0 points in between for an angle of 90 based on 4 points
- int const n = (std::max)(static_cast<int>(
- ceil(m_points_per_circle * angle_diff / two_pi)), 1);
+ std::size_t const n = (std::max)(static_cast<std::size_t>(
+ ceil(m_points_per_circle * angle_diff / two_pi)), std::size_t(1));
PromotedType const diff = angle_diff / static_cast<PromotedType>(n);
PromotedType a = angle1 - diff;
// Walk to n - 1 to avoid generating the last point
- for (int i = 0; i < n - 1; i++, a -= diff)
+ for (std::size_t i = 0; i < n - 1; i++, a -= diff)
{
Point p;
set<0>(p, get<0>(vertex) + buffer_distance * cos(a));
diff --git a/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp b/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp
index 1444c795af..ed3a010cd5 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp
@@ -9,7 +9,6 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
-#include <boost/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
diff --git a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
index 86ebc43c9c..f289857177 100644
--- a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
@@ -85,8 +85,7 @@ public :
promoted_type const buffer_distance = distance_strategy.apply(point, point,
strategy::buffer::buffer_side_left);
- promoted_type const two = 2.0;
- promoted_type const two_pi = two * geometry::math::pi<promoted_type>();
+ promoted_type const two_pi = geometry::math::two_pi<promoted_type>();
promoted_type const diff = two_pi / promoted_type(m_count);
promoted_type a = 0;
diff --git a/boost/geometry/strategies/cartesian/buffer_side_straight.hpp b/boost/geometry/strategies/cartesian/buffer_side_straight.hpp
index 24655ab3d7..75247377fa 100644
--- a/boost/geometry/strategies/cartesian/buffer_side_straight.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_side_straight.hpp
@@ -9,6 +9,8 @@
#include <cstddef>
+#include <boost/math/special_functions/fpclassify.hpp>
+
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
@@ -51,9 +53,9 @@ public :
typename OutputRange,
typename DistanceStrategy
>
- static inline void apply(
+ static inline result_code apply(
Point const& input_p1, Point const& input_p2,
- strategy::buffer::buffer_side_selector side,
+ buffer_side_selector side,
DistanceStrategy const& distance,
OutputRange& output_range)
{
@@ -73,19 +75,46 @@ public :
// For normalization [0,1] (=dot product d.d, sqrt)
promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);
+ if (! boost::math::isfinite(length))
+ {
+ // In case of coordinates differences of e.g. 1e300, length
+ // will overflow and we should not generate output
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
+ std::cout << "Error in length calculation for points "
+ << geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)
+ << " length: " << length << std::endl;
+#endif
+ return result_error_numerical;
+ }
+
if (geometry::math::equals(length, 0))
{
// Coordinates are simplified and therefore most often not equal.
// But if simplify is skipped, or for lines with two
// equal points, length is 0 and we cannot generate output.
- return;
+ return result_no_output;
}
+ promoted_type const d = distance.apply(input_p1, input_p2, side);
+
// Generate the normalized perpendicular p, to the left (ccw)
promoted_type const px = -dy / length;
promoted_type const py = dx / length;
- promoted_type const d = distance.apply(input_p1, input_p2, side);
+ if (geometry::math::equals(px, 0)
+ && geometry::math::equals(py, 0))
+ {
+ // This basically should not occur - because of the checks above.
+ // There are no unit tests triggering this condition
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
+ std::cout << "Error in perpendicular calculation for points "
+ << geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)
+ << " length: " << length
+ << " distance: " << d
+ << std::endl;
+#endif
+ return result_no_output;
+ }
output_range.resize(2);
@@ -93,6 +122,8 @@ public :
set<1>(output_range.front(), get<1>(input_p1) + py * d);
set<0>(output_range.back(), get<0>(input_p2) + px * d);
set<1>(output_range.back(), get<1>(input_p2) + py * d);
+
+ return result_normal;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
diff --git a/boost/geometry/strategies/cartesian/cart_intersect.hpp b/boost/geometry/strategies/cartesian/cart_intersect.hpp
index a7bd385226..8a9857376a 100644
--- a/boost/geometry/strategies/cartesian/cart_intersect.hpp
+++ b/boost/geometry/strategies/cartesian/cart_intersect.hpp
@@ -119,15 +119,10 @@ struct relate_cartesian_segments
boost::ignore_unused_variable_warning(robust_policy);
- typedef typename select_calculation_type
- <Segment1, Segment2, CalculationType>::type coordinate_type;
-
using geometry::detail::equals::equals_point_point;
bool const a_is_point = equals_point_point(robust_a1, robust_a2);
bool const b_is_point = equals_point_point(robust_b1, robust_b2);
- typedef side::side_by_triangle<coordinate_type> side;
-
if(a_is_point && b_is_point)
{
return equals_point_point(robust_a1, robust_b2)
@@ -136,20 +131,32 @@ 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<1>(side::apply(robust_a1, robust_a2, robust_b1),
- side::apply(robust_a1, robust_a2, robust_b2));
- bool collinear = sides.collinear();
+ if (sides.same<0>())
+ {
+ // Both points are at same side of other segment, we can leave
+ return Policy::disjoint();
+ }
- if (sides.same<0>() || sides.same<1>())
+ sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1),
+ side::apply(robust_a1, robust_a2, robust_b2));
+
+ if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
+ bool collinear = sides.collinear();
+
typedef typename select_most_precise
<
coordinate_type, double
@@ -264,7 +271,7 @@ private:
bool const a_is_point,
bool const b_is_point)
{
- //BOOST_ASSERT_MSG(!(a_is_point && b_is_point), "both segments shouldn't be degenerated");
+ //BOOST_GEOMETRY_ASSERT_MSG(!(a_is_point && b_is_point), "both segments shouldn't be degenerated");
// for degenerated segments the second is always true because this function
// shouldn't be called if both segments were degenerated
diff --git a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
index 0357f17e7a..47763a9f30 100644
--- a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
+++ b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
@@ -1,8 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
@@ -22,6 +22,7 @@
#include <cstddef>
+#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits.hpp>
@@ -206,11 +207,18 @@ public :
Point
>::type coordinate_type;
- set<0>(centroid,
- boost::numeric_cast<coordinate_type>(state.sum_x / a3));
- set<1>(centroid,
- boost::numeric_cast<coordinate_type>(state.sum_y / a3));
- return true;
+ // Prevent NaN centroid coordinates
+ if (boost::math::isfinite(a3))
+ {
+ // NOTE: above calculation_type is checked, not the centroid coordinate_type
+ // which means that the centroid can still be filled with INF
+ // if e.g. calculation_type is double and centroid contains floats
+ set<0>(centroid,
+ boost::numeric_cast<coordinate_type>(state.sum_x / a3));
+ set<1>(centroid,
+ boost::numeric_cast<coordinate_type>(state.sum_y / a3));
+ return true;
+ }
}
return false;
diff --git a/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp b/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
index b788738d15..0735e925b6 100644
--- a/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
+++ b/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
@@ -1,7 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2009-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 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.
@@ -13,9 +18,13 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
+#include <boost/math/special_functions/fpclassify.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/util/for_each_coordinate.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
@@ -91,17 +100,37 @@ public :
static inline bool result(state_type const& state, Point& centroid)
{
distance_type const zero = distance_type();
- if (! geometry::math::equals(state.length, zero))
+ if (! geometry::math::equals(state.length, zero)
+ && boost::math::isfinite(state.length)) // Prevent NaN centroid coordinates
{
- assign_zero(centroid);
- add_point(centroid, state.average_sum);
- divide_value(centroid, state.length);
+ // NOTE: above distance_type is checked, not the centroid coordinate_type
+ // which means that the centroid can still be filled with INF
+ // if e.g. distance_type is double and centroid contains floats
+ geometry::for_each_coordinate(centroid, set_sum_div_length(state));
return true;
}
return false;
}
+ struct set_sum_div_length
+ {
+ state_type const& m_state;
+ set_sum_div_length(state_type const& state)
+ : m_state(state)
+ {}
+ template <typename Pt, std::size_t Dimension>
+ void apply(Pt & centroid) const
+ {
+ typedef typename geometry::coordinate_type<Pt>::type coordinate_type;
+ geometry::set<Dimension>(
+ centroid,
+ boost::numeric_cast<coordinate_type>(
+ geometry::get<Dimension>(m_state.average_sum) / m_state.length
+ )
+ );
+ }
+ };
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/boost/geometry/strategies/cartesian/side_of_intersection.hpp b/boost/geometry/strategies/cartesian/side_of_intersection.hpp
index 39487676c1..db57644ad5 100644
--- a/boost/geometry/strategies/cartesian/side_of_intersection.hpp
+++ b/boost/geometry/strategies/cartesian/side_of_intersection.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2015.
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -10,11 +15,25 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP
+#include <limits>
+
+#include <boost/core/ignore_unused.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/util/math.hpp>
+#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
+#include <boost/math/common_factor_ct.hpp>
+#include <boost/math/common_factor_rt.hpp>
+#include <boost/multiprecision/cpp_int.hpp>
+#endif
namespace boost { namespace geometry
{
@@ -22,6 +41,94 @@ namespace boost { namespace geometry
namespace strategy { namespace side
{
+namespace detail
+{
+
+// A tool for multiplication of integers avoiding overflow
+// It's a temporary workaround until we can use Multiprecision
+// The algorithm is based on Karatsuba algorithm
+// see: http://en.wikipedia.org/wiki/Karatsuba_algorithm
+template <typename T>
+struct multiplicable_integral
+{
+ // Currently this tool can't be used with non-integral coordinate types.
+ // Also side_of_intersection strategy sign_of_product() and sign_of_compare()
+ // functions would have to be modified to properly support floating-point
+ // types (comparisons and multiplication).
+ BOOST_STATIC_ASSERT(boost::is_integral<T>::value);
+
+ static const std::size_t bits = CHAR_BIT * sizeof(T);
+ static const std::size_t half_bits = bits / 2;
+ typedef typename boost::make_unsigned<T>::type unsigned_type;
+ static const unsigned_type base = unsigned_type(1) << half_bits; // 2^half_bits
+
+ int m_sign;
+ unsigned_type m_ms;
+ unsigned_type m_ls;
+
+ multiplicable_integral(int sign, unsigned_type ms, unsigned_type ls)
+ : m_sign(sign), m_ms(ms), m_ls(ls)
+ {}
+
+ explicit multiplicable_integral(T const& val)
+ {
+ unsigned_type val_u = val > 0 ?
+ unsigned_type(val)
+ : val == (std::numeric_limits<T>::min)() ?
+ unsigned_type((std::numeric_limits<T>::max)()) + 1
+ : unsigned_type(-val);
+ // MMLL -> S 00MM 00LL
+ m_sign = math::sign(val);
+ m_ms = val_u >> half_bits; // val_u / base
+ m_ls = val_u - m_ms * base;
+ }
+
+ friend multiplicable_integral operator*(multiplicable_integral const& a,
+ multiplicable_integral const& b)
+ {
+ // (S 00MM 00LL) * (S 00MM 00LL) -> (S Z2MM 00LL)
+ unsigned_type z2 = a.m_ms * b.m_ms;
+ unsigned_type z0 = a.m_ls * b.m_ls;
+ unsigned_type z1 = (a.m_ms + a.m_ls) * (b.m_ms + b.m_ls) - z2 - z0;
+ // z0 may be >= base so it must be normalized to allow comparison
+ unsigned_type z0_ms = z0 >> half_bits; // z0 / base
+ return multiplicable_integral(a.m_sign * b.m_sign,
+ z2 * base + z1 + z0_ms,
+ z0 - base * z0_ms);
+ }
+
+ friend bool operator<(multiplicable_integral const& a,
+ multiplicable_integral const& b)
+ {
+ if ( a.m_sign == b.m_sign )
+ {
+ bool u_less = a.m_ms < b.m_ms
+ || (a.m_ms == b.m_ms && a.m_ls < b.m_ls);
+ return a.m_sign > 0 ? u_less : (! u_less);
+ }
+ else
+ {
+ return a.m_sign < b.m_sign;
+ }
+ }
+
+ friend bool operator>(multiplicable_integral const& a,
+ multiplicable_integral const& b)
+ {
+ return b < a;
+ }
+
+ template <typename CmpVal>
+ void check_value(CmpVal const& cmp_val) const
+ {
+ unsigned_type b = base; // a workaround for MinGW - undefined reference base
+ CmpVal val = CmpVal(m_sign) * (CmpVal(m_ms) * CmpVal(b) + CmpVal(m_ls));
+ BOOST_GEOMETRY_ASSERT(cmp_val == val);
+ }
+};
+
+} // namespace detail
+
// Calculates the side of the intersection-point (if any) of
// of segment a//b w.r.t. segment c
// This is calculated without (re)calculating the IP itself again and fully
@@ -29,15 +136,93 @@ namespace strategy { namespace side
// It can be used for either integer (rescaled) points, and also for FP
class side_of_intersection
{
+private :
+ template <typename T, typename U>
+ static inline
+ int sign_of_product(T const& a, U const& b)
+ {
+ return a == 0 || b == 0 ? 0
+ : a > 0 && b > 0 ? 1
+ : a < 0 && b < 0 ? 1
+ : -1;
+ }
+
+ template <typename T>
+ static inline
+ int sign_of_compare(T const& a, T const& b, T const& c, T const& d)
+ {
+ // Both a*b and c*d are positive
+ // We have to judge if a*b > c*d
+
+ using side::detail::multiplicable_integral;
+ multiplicable_integral<T> ab = multiplicable_integral<T>(a)
+ * multiplicable_integral<T>(b);
+ multiplicable_integral<T> cd = multiplicable_integral<T>(c)
+ * multiplicable_integral<T>(d);
+
+ int result = ab > cd ? 1
+ : ab < cd ? -1
+ : 0
+ ;
+
+#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
+ using namespace boost::multiprecision;
+ cpp_int const lab = cpp_int(a) * cpp_int(b);
+ cpp_int const lcd = cpp_int(c) * cpp_int(d);
+
+ ab.check_value(lab);
+ cd.check_value(lcd);
+
+ int result2 = lab > lcd ? 1
+ : lab < lcd ? -1
+ : 0
+ ;
+ BOOST_GEOMETRY_ASSERT(result == result2);
+#endif
+
+ return result;
+ }
+
+ template <typename T>
+ static inline
+ int sign_of_addition_of_two_products(T const& a, T const& b, T const& c, T const& d)
+ {
+ // sign of a*b+c*d, 1 if positive, -1 if negative, else 0
+ int const ab = sign_of_product(a, b);
+ int const cd = sign_of_product(c, d);
+ if (ab == 0)
+ {
+ return cd;
+ }
+ if (cd == 0)
+ {
+ return ab;
+ }
+
+ if (ab == cd)
+ {
+ // Both positive or both negative
+ return ab;
+ }
+
+ // One is positive, one is negative, both are non zero
+ // If ab is positive, we have to judge if a*b > -c*d (then 1 because sum is positive)
+ // If ab is negative, we have to judge if c*d > -a*b (idem)
+ return ab == 1
+ ? sign_of_compare(a, b, -c, d)
+ : sign_of_compare(c, d, -a, b);
+ }
+
+
public :
// Calculates the side of the intersection-point (if any) of
// of segment a//b w.r.t. segment c
// This is calculated without (re)calculating the IP itself again and fully
// based on integer mathematics
- template <typename T, typename Segment>
+ template <typename T, typename Segment, typename Point>
static inline T side_value(Segment const& a, Segment const& b,
- Segment const& c)
+ Segment const& c, Point const& fallback_point)
{
// The first point of the three segments is reused several times
T const ax = get<0, 0>(a);
@@ -67,9 +252,15 @@ public :
if (d == zero)
{
// There is no IP of a//b, they are collinear or parallel
- // We don't have to divide but we can already conclude the side-value
- // is meaningless and the resulting determinant will be 0
- return zero;
+ // Assuming they intersect (this method should be called for
+ // segments known to intersect), they are collinear and overlap.
+ // They have one or two intersection points - we don't know and
+ // have to rely on the fallback intersection point
+
+ Point c1, c2;
+ geometry::detail::assign_point_from_index<0>(c, c1);
+ geometry::detail::assign_point_from_index<1>(c, c2);
+ return side_by_triangle<>::apply(c1, c2, fallback_point);
}
// Cramer's rule: da (see cart_intersect.hpp)
@@ -82,7 +273,9 @@ public :
// IP is at (ax + (da/d) * dx_a, ay + (da/d) * dy_a)
// Side of IP is w.r.t. c is: determinant(dx_c, dy_c, ipx-cx, ipy-cy)
// We replace ipx by expression above and multiply each term by d
- T const result = geometry::detail::determinant<T>
+
+#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
+ T const result1 = geometry::detail::determinant<T>
(
dx_c * d, dy_c * d,
d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
@@ -93,15 +286,52 @@ public :
// Therefore, the sign is always the same as that result, and the
// resulting side (left,right,collinear) is the same
+ // The first row we divide again by d because of determinant multiply rule
+ T const result2 = d * geometry::detail::determinant<T>
+ (
+ dx_c, dy_c,
+ d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
+ );
+ // Write out:
+ T const result3 = d * (dx_c * (d * (ay - cy) + dy_a * da)
+ - dy_c * (d * (ax - cx) + dx_a * da));
+ // Write out in braces:
+ T const result4 = d * (dx_c * d * (ay - cy) + dx_c * dy_a * da
+ - dy_c * d * (ax - cx) - dy_c * dx_a * da);
+ // Write in terms of d * XX + da * YY
+ T const result5 = d * (d * (dx_c * (ay - cy) - dy_c * (ax - cx))
+ + da * (dx_c * dy_a - dy_c * dx_a));
+
+ boost::ignore_unused(result1, result2, result3, result4, result5);
+ //return result;
+#endif
+
+ // We consider the results separately
+ // (in the end we only have to return the side-value 1,0 or -1)
+
+ // To avoid multiplications we judge the product (easy, avoids *d)
+ // and the sign of p*q+r*s (more elaborate)
+ T const result = sign_of_product
+ (
+ d,
+ sign_of_addition_of_two_products
+ (
+ d, dx_c * (ay - cy) - dy_c * (ax - cx),
+ da, dx_c * dy_a - dy_c * dx_a
+ )
+ );
return result;
+
}
- template <typename Segment>
- static inline int apply(Segment const& a, Segment const& b, Segment const& c)
+ template <typename Segment, typename Point>
+ static inline int apply(Segment const& a, Segment const& b,
+ Segment const& c,
+ Point const& fallback_point)
{
typedef typename geometry::coordinate_type<Segment>::type coordinate_type;
- coordinate_type const s = side_value<coordinate_type>(a, b, c);
+ coordinate_type const s = side_value<coordinate_type>(a, b, c, fallback_point);
coordinate_type const zero = coordinate_type();
return math::equals(s, zero) ? 0
: s > zero ? 1
diff --git a/boost/geometry/strategies/geographic/distance_thomas.hpp b/boost/geometry/strategies/geographic/distance_thomas.hpp
new file mode 100644
index 0000000000..7252b723dd
--- /dev/null
+++ b/boost/geometry/strategies/geographic/distance_thomas.hpp
@@ -0,0 +1,156 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 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 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_THOMAS_HPP
+#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/distance.hpp>
+
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#include <boost/geometry/algorithms/detail/thomas_inverse.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance
+{
+
+/*!
+\brief The solution of the inverse problem of geodesics on latlong coordinates,
+ Forsyth-Andoyer-Lambert type approximation with second order terms.
+\ingroup distance
+\tparam Spheroid The reference spheroid model
+\tparam CalculationType \tparam_calculation
+\author See
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965
+ http://www.dtic.mil/docs/citations/AD0627893
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970
+ http://www.dtic.mil/docs/citations/AD703541
+*/
+template
+<
+ typename Spheroid,
+ typename CalculationType = void
+>
+class thomas
+{
+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 thomas()
+ : m_spheroid()
+ {}
+
+ explicit inline thomas(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 geometry::detail::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
+namespace services
+{
+
+template <typename Spheroid, typename CalculationType>
+struct tag<thomas<Spheroid, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>
+struct return_type<thomas<Spheroid, CalculationType>, P1, P2>
+ : thomas<Spheroid, CalculationType>::template calculation_type<P1, P2>
+{};
+
+
+template <typename Spheroid, typename CalculationType>
+struct comparable_type<thomas<Spheroid, CalculationType> >
+{
+ typedef thomas<Spheroid, CalculationType> type;
+};
+
+
+template <typename Spheroid, typename CalculationType>
+struct get_comparable<thomas<Spheroid, CalculationType> >
+{
+ static inline thomas<Spheroid, CalculationType> apply(thomas<Spheroid, CalculationType> const& input)
+ {
+ return input;
+ }
+};
+
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>
+struct result_from_distance<thomas<Spheroid, CalculationType>, P1, P2 >
+{
+ template <typename T>
+ static inline typename return_type<thomas<Spheroid, CalculationType>, P1, P2>::type
+ apply(thomas<Spheroid, CalculationType> const& , T const& value)
+ {
+ return value;
+ }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_THOMAS_HPP
diff --git a/boost/geometry/strategies/geographic/distance_vincenty.hpp b/boost/geometry/strategies/geographic/distance_vincenty.hpp
index 56dd14bbdc..65bfa19939 100644
--- a/boost/geometry/strategies/geographic/distance_vincenty.hpp
+++ b/boost/geometry/strategies/geographic/distance_vincenty.hpp
@@ -82,12 +82,13 @@ public :
{
return geometry::detail::vincenty_inverse
<
- typename calculation_type<Point1, Point2>::type
- >(get_as_radian<0>(point1),
- get_as_radian<1>(point1),
- get_as_radian<0>(point2),
- get_as_radian<1>(point2),
- m_spheroid).distance();
+ 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
diff --git a/boost/geometry/strategies/geographic/side_andoyer.hpp b/boost/geometry/strategies/geographic/side_andoyer.hpp
new file mode 100644
index 0000000000..e0f0c04067
--- /dev/null
+++ b/boost/geometry/strategies/geographic/side_andoyer.hpp
@@ -0,0 +1,55 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014, 2015.
+// Modifications 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_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP
+
+
+#include <boost/geometry/algorithms/detail/andoyer_inverse.hpp>
+
+#include <boost/geometry/strategies/geographic/side_detail.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 Model Reference model of coordinate system.
+\tparam CalculationType \tparam_calculation
+ */
+template <typename Model, typename CalculationType = void>
+class andoyer
+ : public detail::by_azimuth<geometry::detail::andoyer_inverse, Model, CalculationType>
+{
+ typedef detail::by_azimuth<geometry::detail::andoyer_inverse, Model, CalculationType> base_t;
+
+public:
+ andoyer(Model const& model = Model())
+ : base_t(model)
+ {}
+};
+
+}} // namespace strategy::side
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP
diff --git a/boost/geometry/strategies/geographic/side_detail.hpp b/boost/geometry/strategies/geographic/side_detail.hpp
new file mode 100644
index 0000000000..c00213d072
--- /dev/null
+++ b/boost/geometry/strategies/geographic/side_detail.hpp
@@ -0,0 +1,139 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014, 2015.
+// Modifications 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_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> 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> 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
new file mode 100644
index 0000000000..a96cabdaab
--- /dev/null
+++ b/boost/geometry/strategies/geographic/side_thomas.hpp
@@ -0,0 +1,55 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014, 2015.
+// Modifications 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_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP
+
+
+#include <boost/geometry/algorithms/detail/thomas_inverse.hpp>
+
+#include <boost/geometry/strategies/geographic/side_detail.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 Model Reference model of coordinate system.
+\tparam CalculationType \tparam_calculation
+ */
+template <typename Model, typename CalculationType = void>
+class thomas
+ : public detail::by_azimuth<geometry::detail::thomas_inverse, Model, CalculationType>
+{
+ typedef detail::by_azimuth<geometry::detail::thomas_inverse, Model, CalculationType> base_t;
+
+public:
+ thomas(Model const& model = Model())
+ : base_t(model)
+ {}
+};
+
+}} // namespace strategy::side
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP
diff --git a/boost/geometry/strategies/geographic/side_vincenty.hpp b/boost/geometry/strategies/geographic/side_vincenty.hpp
new file mode 100644
index 0000000000..a8ef9550d6
--- /dev/null
+++ b/boost/geometry/strategies/geographic/side_vincenty.hpp
@@ -0,0 +1,55 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014, 2015.
+// Modifications 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_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP
+
+
+#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>
+
+#include <boost/geometry/strategies/geographic/side_detail.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 Model Reference model of coordinate system.
+\tparam CalculationType \tparam_calculation
+ */
+template <typename Model, typename CalculationType = void>
+class vincenty
+ : public detail::by_azimuth<geometry::detail::vincenty_inverse, Model, CalculationType>
+{
+ typedef detail::by_azimuth<geometry::detail::vincenty_inverse, Model, CalculationType> base_t;
+
+public:
+ vincenty(Model const& model = Model())
+ : base_t(model)
+ {}
+};
+
+}} // namespace strategy::side
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP
diff --git a/boost/geometry/strategies/intersection_result.hpp b/boost/geometry/strategies/intersection_result.hpp
index b467b92a7f..9c6d17ec5e 100644
--- a/boost/geometry/strategies/intersection_result.hpp
+++ b/boost/geometry/strategies/intersection_result.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// 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 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
@@ -20,140 +25,6 @@
namespace boost { namespace geometry
{
-/*!
- \brief Dimensionally Extended 9 Intersection Matrix
- \details
- \ingroup overlay
- \see http://gis.hsr.ch/wiki/images/3/3d/9dem_springer.pdf
-*/
-struct de9im
-{
- int ii, ib, ie,
- bi, bb, be,
- ei, eb, ee;
-
- inline de9im()
- : ii(-1), ib(-1), ie(-1)
- , bi(-1), bb(-1), be(-1)
- , ei(-1), eb(-1), ee(-1)
- {
- }
-
- inline de9im(int ii0, int ib0, int ie0,
- int bi0, int bb0, int be0,
- int ei0, int eb0, int ee0)
- : ii(ii0), ib(ib0), ie(ie0)
- , bi(bi0), bb(bb0), be(be0)
- , ei(ei0), eb(eb0), ee(ee0)
- {}
-
- inline bool equals() const
- {
- return ii >= 0 && ie < 0 && be < 0 && ei < 0 && eb < 0;
- }
-
- inline bool disjoint() const
- {
- return ii < 0 && ib < 0 && bi < 0 && bb < 0;
- }
-
- inline bool intersects() const
- {
- return ii >= 0 || bb >= 0 || bi >= 0 || ib >= 0;
- }
-
- inline bool touches() const
- {
- return ii < 0 && (bb >= 0 || bi >= 0 || ib >= 0);
- }
-
- inline bool crosses() const
- {
- return (ii >= 0 && ie >= 0) || (ii == 0);
- }
-
- inline bool overlaps() const
- {
- return ii >= 0 && ie >= 0 && ei >= 0;
- }
-
- inline bool within() const
- {
- return ii >= 0 && ie < 0 && be < 0;
- }
-
- inline bool contains() const
- {
- return ii >= 0 && ei < 0 && eb < 0;
- }
-
-
- static inline char as_char(int v)
- {
- return v >= 0 && v < 10 ? static_cast<char>('0' + v) : '-';
- }
-
-#if defined(HAVE_MATRIX_AS_STRING)
- inline std::string matrix_as_string(std::string const& tab, std::string const& nl) const
- {
- std::string ret;
- ret.reserve(9 + tab.length() * 3 + nl.length() * 3);
- ret += tab; ret += as_char(ii); ret += as_char(ib); ret += as_char(ie); ret += nl;
- ret += tab; ret += as_char(bi); ret += as_char(bb); ret += as_char(be); ret += nl;
- ret += tab; ret += as_char(ei); ret += as_char(eb); ret += as_char(ee);
- return ret;
- }
-
- inline std::string matrix_as_string() const
- {
- return matrix_as_string("", "");
- }
-#endif
-
-};
-
-struct de9im_segment : public de9im
-{
- bool collinear; // true if segments are aligned (for equal,overlap,touch)
- bool opposite; // true if direction is reversed (for equal,overlap,touch)
- bool parallel; // true if disjoint but parallel
- bool degenerate; // true for segment(s) of zero length
-
- double ra, rb; // temp
-
- inline de9im_segment()
- : de9im()
- , collinear(false)
- , opposite(false)
- , parallel(false)
- , degenerate(false)
- {}
-
- inline de9im_segment(double a, double b,
- int ii0, int ib0, int ie0,
- int bi0, int bb0, int be0,
- int ei0, int eb0, int ee0,
- bool c = false, bool o = false, bool p = false, bool d = false)
- : de9im(ii0, ib0, ie0, bi0, bb0, be0, ei0, eb0, ee0)
- , collinear(c)
- , opposite(o)
- , parallel(p)
- , degenerate(d)
- , ra(a), rb(b)
- {}
-
-
-#if defined(HAVE_MATRIX_AS_STRING)
- inline std::string as_string() const
- {
- std::string ret = matrix_as_string();
- ret += collinear ? "c" : "-";
- ret += opposite ? "o" : "-";
- return ret;
- }
-#endif
-};
-
template <typename SegmentRatio>
struct fraction_type
{
@@ -209,7 +80,7 @@ struct segment_intersection_info
typedef PromotedType promoted_type;
CoordinateType dx_a, dy_a;
- CoordinateType dx_b, dy_b; // TODO b can be removed
+ CoordinateType dx_b, dy_b;
SegmentRatio robust_ra;
SegmentRatio robust_rb;
};
diff --git a/boost/geometry/strategies/spherical/area_huiller.hpp b/boost/geometry/strategies/spherical/area_huiller.hpp
index e55fdb2b0e..37d8d20124 100644
--- a/boost/geometry/strategies/spherical/area_huiller.hpp
+++ b/boost/geometry/strategies/spherical/area_huiller.hpp
@@ -1,6 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// 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
@@ -31,18 +37,22 @@ namespace strategy { namespace area
\tparam PointOfSegment point type of segments of rings/polygons
\tparam CalculationType \tparam_calculation
\author Barend Gehrels. Adapted from:
-- http://www.soe.ucsc.edu/~pang/160/f98/Gems/GemsIV/sph_poly.c
+- 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 Gems didn't account for polygons crossing the 180 meridian.
+\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://trs-new.jpl.nasa.gov/dspace/bitstream/2014/40409/1/07-03.pdf, is simple
-and works well in most cases but not in 180 meridian crossing cases. This probably
-could be solved.
+\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
@@ -113,8 +123,12 @@ public :
calculation_type const half = 0.5;
calculation_type const two = 2.0;
calculation_type const four = 4.0;
- calculation_type const two_pi = two * geometry::math::pi<calculation_type>();
- calculation_type const half_pi = half * geometry::math::pi<calculation_type>();
+ 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);
@@ -128,33 +142,31 @@ public :
// 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 E = four
+ 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))));
- E = geometry::math::abs(E);
+ 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, other is positive,
+ // Longitude comparisons are not so obvious. If one is negative and other is positive,
// we have to take the dateline into account.
- // TODO: check this / enhance this, should be more robust. See also the "grow" for ll
- // TODO: use minmax or "smaller"/"compare" strategy for this
- calculation_type lon1 = geometry::get_as_radian<0>(p1) < 0
- ? geometry::get_as_radian<0>(p1) + two_pi
- : geometry::get_as_radian<0>(p1);
- calculation_type lon2 = geometry::get_as_radian<0>(p2) < 0
- ? geometry::get_as_radian<0>(p2) + two_pi
- : geometry::get_as_radian<0>(p2);
+ 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 (lon2 < lon1)
+ if (lon_diff > pi)
{
- E = -E;
+ excess = -excess;
}
- state.sum += E;
+ state.sum += excess;
}
}
diff --git a/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp
index 486c7effbd..31b59e77ff 100644
--- a/boost/geometry/strategies/spherical/distance_cross_track.hpp
+++ b/boost/geometry/strategies/spherical/distance_cross_track.hpp
@@ -340,6 +340,8 @@ public :
>
{};
+ typedef typename Strategy::radius_type radius_type;
+
inline cross_track()
{}
@@ -372,11 +374,16 @@ public :
typedef typename return_type<Point, PointOfSegment>::type return_type;
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
- std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl;
- std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl;
- std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " " << crs_BD * geometry::math::r2d << std::endl;
- std::cout << "Projection AD-AB " << projection1 << " : " << d_crs1 * geometry::math::r2d << std::endl;
- std::cout << "Projection BD-BA " << projection2 << " : " << d_crs2 * geometry::math::r2d << std::endl;
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "
+ << crs_AD * geometry::math::r2d<return_type>() << std::endl;
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " "
+ << crs_AB * geometry::math::r2d<return_type>() << std::endl;
+ std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " "
+ << crs_BD * geometry::math::r2d << std::endl;
+ std::cout << "Projection AD-AB " << projection1 << " : "
+ << d_crs1 * geometry::math::r2d<return_type>() << std::endl;
+ std::cout << "Projection BD-BA " << projection2 << " : "
+ << d_crs2 * geometry::math::r2d<return_type>() << std::endl;
#endif
// http://williams.best.vwh.net/avform.htm#XTE
@@ -487,6 +494,8 @@ public :
>
{};
+ typedef typename Strategy::radius_type radius_type;
+
inline cross_track()
{}
diff --git a/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp b/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp
index fe32f77236..14c5bd4eda 100644
--- a/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp
+++ b/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp
@@ -1,13 +1,14 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
-// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2015 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, 2015.
+// Modifications copyright (c) 2014-2015, 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
@@ -16,14 +17,23 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP
+#include <boost/config.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>
+#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/calculation_type.hpp>
-
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
namespace boost { namespace geometry
@@ -32,131 +42,197 @@ namespace boost { namespace geometry
namespace strategy { namespace distance
{
+
+/*!
+\brief Strategy functor for distance point to box calculation
+\ingroup strategies
+\details Class which calculates the distance of a point to a box, for
+points and boxes on a sphere or globe
+\tparam CalculationType \tparam_calculation
+\tparam Strategy underlying point-segment distance strategy, defaults
+to cross track
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
+}
+
+*/
template
<
typename CalculationType = void,
- typename Strategy = haversine<double, CalculationType>
+ typename Strategy = cross_track<CalculationType>
>
class cross_track_point_box
{
public:
template <typename Point, typename Box>
struct return_type
- : promote_floating_point
- <
- typename select_calculation_type
- <
- Point,
- typename point_type<Box>::type,
- CalculationType
- >::type
- >
+ : services::return_type<Strategy, Point, typename point_type<Box>::type>
{};
+ typedef typename Strategy::radius_type radius_type;
+
inline cross_track_point_box()
{}
explicit inline cross_track_point_box(typename Strategy::radius_type const& r)
- : m_pp_strategy(r)
+ : m_ps_strategy(r)
{}
inline cross_track_point_box(Strategy const& s)
- : m_pp_strategy(s)
+ : m_ps_strategy(s)
{}
-
+
+
+ // It might be useful in the future
+ // to overload constructor with strategy info.
+ // crosstrack(...) {}
+
template <typename Point, typename Box>
inline typename return_type<Point, Box>::type
apply(Point const& point, Box const& box) const
{
-
#if !defined(BOOST_MSVC)
BOOST_CONCEPT_ASSERT
(
- (concept::PointDistanceStrategy
+ (concept::PointSegmentDistanceStrategy
<
- Strategy, Point,
- typename point_type<Box>::type
+ Strategy, Point, typename point_type<Box>::type
>)
);
#endif
+ // this method assumes that the coordinates of the point and
+ // the box are normalized
+
typedef typename return_type<Point, Box>::type return_type;
- typedef typename point_type<Box>::type box_point_t;
-
- // Create (counterclockwise) array of points, the fifth one closes it
- // If every point is on the LEFT side (=1) or ON the border (=0)
- // the distance should be equal to 0.
+ typedef typename point_type<Box>::type box_point_type;
// TODO: This strategy as well as other cross-track strategies
// and therefore e.g. spherical within(Point, Box) may not work
// properly for a Box degenerated to a Segment or Point
- boost::array<box_point_t, 5> bp;
- geometry::detail::assign_box_corners_oriented<true>(box, bp);
- bp[4] = bp[0];
+ box_point_type bottom_left, bottom_right, top_left, top_right;
+ geometry::detail::assign_box_corners(box,
+ bottom_left, bottom_right,
+ top_left, top_right);
+
+ return_type const plon = geometry::get_as_radian<0>(point);
+ return_type const plat = geometry::get_as_radian<1>(point);
+
+ return_type const lon_min = geometry::get_as_radian<0>(bottom_left);
+ return_type const lat_min = geometry::get_as_radian<1>(bottom_left);
+ return_type const lon_max = geometry::get_as_radian<0>(top_right);
+ return_type const lat_max = geometry::get_as_radian<1>(top_right);
+
+ return_type const pi = math::pi<return_type>();
+ return_type const two_pi = math::two_pi<return_type>();
+
+ // First check if the point is within the band defined by the
+ // minimum and maximum longitude of the box; if yes, determine
+ // if the point is above, below or inside the box and compute
+ // the distance (easy in this case)
+ //
+ // Notice that the point may not be inside the longitude range
+ // of the box, but the shifted point may be inside the
+ // longitude range of the box; in this case the point is still
+ // considered as inside the longitude range band of the box
+ if ((plon >= lon_min && plon <= lon_max) || plon + two_pi <= lon_max)
+ {
+ if (plat > lat_max)
+ {
+ return services::result_from_distance
+ <
+ Strategy, Point, box_point_type
+ >::apply(m_ps_strategy, radius() * (plat - lat_max));
+ }
+ else if (plat < lat_min)
+ {
+ return services::result_from_distance
+ <
+ Strategy, Point, box_point_type
+ >::apply(m_ps_strategy, radius() * (lat_min - plat));
+ }
+ else
+ {
+ BOOST_GEOMETRY_ASSERT(plat >= lat_min && plat <= lat_max);
+ return return_type(0);
+ }
+ }
- for (int i = 1; i < 5; i++)
+ // Otherwise determine which αμονγ the two medirian segments of the
+ // box the point is closest to, and compute the distance of
+ // the point to this closest segment
+
+ // Below lon_midway is the longitude of the meridian that:
+ // (1) is midway between the meridians of the left and right
+ // meridians of the box, and
+ // (2) does not intersect the box
+ return_type const two = 2.0;
+ bool use_left_segment;
+ if (lon_max > pi)
{
- box_point_t const& p1 = bp[i - 1];
- box_point_t const& p2 = bp[i];
+ // the box crosses the antimeridian
- return_type const crs_AD = geometry::detail::course<return_type>(p1, point);
- return_type const crs_AB = geometry::detail::course<return_type>(p1, p2);
- return_type const d_crs1 = crs_AD - crs_AB;
- return_type const sin_d_crs1 = sin(d_crs1);
+ // midway longitude = lon_min - (lon_min + (lon_max - 2 * pi)) / 2;
+ return_type const lon_midway = (lon_min - lon_max) / two + pi;
+ BOOST_GEOMETRY_ASSERT(lon_midway >= -pi && lon_midway <= pi);
- // this constant sin() is here to be consistent with the side strategy
- return_type const sigXTD = asin(sin(0.001) * sin_d_crs1);
+ use_left_segment = plon > lon_midway;
+ }
+ else
+ {
+ // the box does not cross the antimeridian
- // If the point is on the right side of the edge
- if ( sigXTD > 0 )
+ return_type const lon_sum = lon_min + lon_max;
+ if (math::equals(lon_sum, return_type(0)))
{
- return_type const crs_BA = crs_AB - geometry::math::pi<return_type>();
- return_type const crs_BD = geometry::detail::course<return_type>(p2, point);
- return_type const d_crs2 = crs_BD - crs_BA;
+ // special case: the box is symmetric with respect to
+ // the prime meridian; the midway meridian is the antimeridian
- return_type const projection1 = cos( d_crs1 );
- return_type const projection2 = cos( d_crs2 );
+ use_left_segment = plon < lon_min;
+ }
+ else
+ {
+ // midway long. = lon_min - (2 * pi - (lon_max - lon_min)) / 2;
+ return_type lon_midway = (lon_min + lon_max) / two - pi;
- if(projection1 > 0.0 && projection2 > 0.0)
+ // normalize the midway longitude
+ if (lon_midway > pi)
{
- return_type const d1 = m_pp_strategy.apply(p1, point);
- return_type const
- XTD = radius()
- * geometry::math::abs(
- asin( sin( d1 / radius() ) * sin_d_crs1 )
- );
-
- return return_type(XTD);
+ lon_midway -= two_pi;
}
- else
+ else if (lon_midway < -pi)
{
- // OPTIMIZATION
- // Return d1 if projection1 <= 0 and d2 if projection2 <= 0
- // if both == 0 then return d1 or d2
- // both shouldn't be < 0
-
- return_type const d1 = m_pp_strategy.apply(p1, point);
- return_type const d2 = m_pp_strategy.apply(p2, point);
-
- return return_type((std::min)( d1 , d2 ));
+ lon_midway += two_pi;
}
+ BOOST_GEOMETRY_ASSERT(lon_midway >= -pi && lon_midway <= pi);
+
+ // if lon_sum is positive the midway meridian is left
+ // of the box, or right of the box otherwise
+ use_left_segment = lon_sum > 0
+ ? (plon < lon_min && plon >= lon_midway)
+ : (plon <= lon_max || plon > lon_midway);
}
}
- // Return 0 if the point isn't on the right side of any segment
- return return_type(0);
+ return use_left_segment
+ ? m_ps_strategy.apply(point, bottom_left, top_left)
+ : m_ps_strategy.apply(point, bottom_right, top_right);
}
inline typename Strategy::radius_type radius() const
- { return m_pp_strategy.radius(); }
-
-private :
+ {
+ return m_ps_strategy.radius();
+ }
- Strategy m_pp_strategy;
+private:
+ Strategy m_ps_strategy;
};
+
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
@@ -170,67 +246,68 @@ struct tag<cross_track_point_box<CalculationType, Strategy> >
template <typename CalculationType, typename Strategy, typename P, typename Box>
struct return_type<cross_track_point_box<CalculationType, Strategy>, P, Box>
- : cross_track_point_box<CalculationType, Strategy>::template return_type<P, Box>
+ : cross_track_point_box
+ <
+ CalculationType, Strategy
+ >::template return_type<P, Box>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<cross_track_point_box<CalculationType, Strategy> >
{
- // There is no shortcut, so the strategy itself is its comparable type
- typedef cross_track_point_box<CalculationType, Strategy> type;
+ typedef cross_track_point_box
+ <
+ CalculationType, typename comparable_type<Strategy>::type
+ > type;
};
-template
-<
- typename CalculationType,
- typename Strategy
->
+template <typename CalculationType, typename Strategy>
struct get_comparable<cross_track_point_box<CalculationType, Strategy> >
{
- typedef typename comparable_type
- <
- cross_track_point_box<CalculationType, Strategy>
- >::type comparable_type;
-public :
- static inline comparable_type apply(
- cross_track_point_box<CalculationType, Strategy> const& strategy)
+ typedef cross_track_point_box<CalculationType, Strategy> this_strategy;
+ typedef typename comparable_type<this_strategy>::type comparable_type;
+
+public:
+ static inline comparable_type apply(this_strategy const& strategy)
{
- return cross_track_point_box<CalculationType, Strategy>(strategy.radius());
+ return comparable_type(strategy.radius());
}
};
-template
-<
- typename CalculationType,
- typename Strategy,
- typename P, typename Box
->
+template <typename CalculationType, typename Strategy, typename P, typename Box>
struct result_from_distance
<
- cross_track_point_box<CalculationType, Strategy>,
- P,
- Box
+ cross_track_point_box<CalculationType, Strategy>, P, Box
>
{
-private :
- typedef typename cross_track_point_box
+private:
+ typedef cross_track_point_box<CalculationType, Strategy> this_strategy;
+
+ typedef typename this_strategy::template return_type
<
- CalculationType, Strategy
- >::template return_type<P, Box> return_type;
-public :
+ P, Box
+ >::type return_type;
+
+public:
template <typename T>
- static inline return_type apply(
- cross_track_point_box<CalculationType, Strategy> const& ,
- T const& distance)
+ static inline return_type apply(this_strategy const& strategy,
+ T const& distance)
{
- return distance;
+ Strategy s(strategy.radius());
+
+ return result_from_distance
+ <
+ Strategy, P, typename point_type<Box>::type
+ >::apply(s, distance);
}
};
+// define cross_track_point_box<default_point_segment_strategy> as
+// default point-box strategy for the spherical equatorial coordinate system
template <typename Point, typename Box, typename Strategy>
struct default_strategy
<
@@ -247,7 +324,7 @@ struct default_strategy
boost::is_void<Strategy>,
typename default_strategy
<
- point_tag, point_tag,
+ point_tag, segment_tag,
Point, typename point_type<Box>::type,
spherical_equatorial_tag, spherical_equatorial_tag
>::type,
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
index bf436dba2b..28850020af 100644
--- a/boost/geometry/strategies/strategies.hpp
+++ b/boost/geometry/strategies/strategies.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 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015.
+// Modifications copyright (c) 2014-2015 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_STRATEGIES_STRATEGIES_HPP
#define BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP
@@ -64,7 +64,11 @@
#include <boost/geometry/strategies/spherical/ssf.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/agnostic/buffer_distance_symmetric.hpp>
#include <boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp>
diff --git a/boost/geometry/strategies/strategy_transform.hpp b/boost/geometry/strategies/strategy_transform.hpp
index 9d3b1d910c..99fcb720c6 100644
--- a/boost/geometry/strategies/strategy_transform.hpp
+++ b/boost/geometry/strategies/strategy_transform.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -28,6 +33,7 @@
#include <boost/geometry/strategies/transform.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
@@ -130,7 +136,15 @@ struct degree_radian_vv
assert_dimension<P1, 2>();
assert_dimension<P2, 2>();
- detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
+ typedef typename promote_floating_point
+ <
+ typename select_coordinate_type<P1, P2>::type
+ >::type calculation_type;
+
+ detail::transform_coordinates
+ <
+ P1, P2, 0, 2, F
+ >::transform(p1, p2, math::d2r<calculation_type>());
return true;
}
};
@@ -143,7 +157,16 @@ struct degree_radian_vv_3
assert_dimension<P1, 3>();
assert_dimension<P2, 3>();
- detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
+ typedef typename promote_floating_point
+ <
+ typename select_coordinate_type<P1, P2>::type
+ >::type calculation_type;
+
+ detail::transform_coordinates
+ <
+ P1, P2, 0, 2, F
+ >::transform(p1, p2, math::d2r<calculation_type>());
+
// Copy height or other third dimension
set<2>(p2, get<2>(p1));
return true;
diff --git a/boost/geometry/strategies/transform/matrix_transformers.hpp b/boost/geometry/strategies/transform/matrix_transformers.hpp
index 27a3a2ae80..699b91b3aa 100644
--- a/boost/geometry/strategies/transform/matrix_transformers.hpp
+++ b/boost/geometry/strategies/transform/matrix_transformers.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -40,6 +45,7 @@
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
@@ -340,7 +346,8 @@ struct as_radian<degree>
template <typename T>
static inline T get(T const& value)
{
- return value * math::d2r;
+ typedef typename promote_floating_point<T>::type promoted_type;
+ return value * math::d2r<promoted_type>();
}
};
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
index 4042f4e4cd..d84b11f480 100644
--- a/boost/geometry/util/math.hpp
+++ b/boost/geometry/util/math.hpp
@@ -26,12 +26,11 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/math/constants/constants.hpp>
-#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
#include <boost/math/special_functions/fpclassify.hpp>
-#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
-#include <boost/math/special_functions/round.hpp>
+//#include <boost/math/special_functions/round.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_integral.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
@@ -86,6 +85,9 @@ struct abs<T, true>
{
static inline T apply(T const& value)
{
+ using ::fabs;
+ using std::fabs; // for long double
+
return fabs(value);
}
};
@@ -161,7 +163,17 @@ struct equals<Type, true>
return true;
}
- return abs<Type>::apply(a - b) <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
+ if (boost::math::isfinite(a) && boost::math::isfinite(b))
+ {
+ // If a is INF and b is e.g. 0, the expression below returns true
+ // but the values are obviously not equal, hence the condition
+ return abs<Type>::apply(a - b)
+ <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
+ }
+ else
+ {
+ return a == b;
+ }
}
};
@@ -295,8 +307,66 @@ struct square_root<T, true>
};
+
+template
+<
+ typename T,
+ bool IsFundemantal = boost::is_fundamental<T>::value /* false */
+>
+struct modulo
+{
+ typedef T return_type;
+
+ static inline T apply(T const& value1, T const& value2)
+ {
+ // for non-fundamental number types assume that a free
+ // function mod() is defined either:
+ // 1) at T's scope, or
+ // 2) at global scope
+ return mod(value1, value2);
+ }
+};
+
+template
+<
+ typename Fundamental,
+ bool IsIntegral = boost::is_integral<Fundamental>::value
+>
+struct modulo_for_fundamental
+{
+ typedef Fundamental return_type;
+
+ static inline Fundamental apply(Fundamental const& value1,
+ Fundamental const& value2)
+ {
+ return value1 % value2;
+ }
+};
+
+// specialization for floating-point numbers
+template <typename Fundamental>
+struct modulo_for_fundamental<Fundamental, false>
+{
+ typedef Fundamental return_type;
+
+ static inline Fundamental apply(Fundamental const& value1,
+ Fundamental const& value2)
+ {
+ return std::fmod(value1, value2);
+ }
+};
+
+// specialization for fundamental number type
+template <typename Fundamental>
+struct modulo<Fundamental, true>
+ : modulo_for_fundamental<Fundamental>
+{};
+
+
+
/*!
-\brief Short construct to enable partial specialization for PI, currently not possible in Math.
+\brief Short constructs to enable partial specialization for PI, 2*PI
+ and PI/2, currently not possible in Math.
*/
template <typename T>
struct define_pi
@@ -309,6 +379,26 @@ struct define_pi
};
template <typename T>
+struct define_two_pi
+{
+ static inline T apply()
+ {
+ // Default calls Boost.Math
+ return boost::math::constants::two_pi<T>();
+ }
+};
+
+template <typename T>
+struct define_half_pi
+{
+ static inline T apply()
+ {
+ // Default calls Boost.Math
+ return boost::math::constants::half_pi<T>();
+ }
+};
+
+template <typename T>
struct relaxed_epsilon
{
static inline T apply(const T& factor)
@@ -321,7 +411,7 @@ struct relaxed_epsilon
template <typename Result, typename Source,
bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
-struct round
+struct rounding_cast
{
static inline Result apply(Source const& v)
{
@@ -329,16 +419,25 @@ struct round
}
};
+// TtoT
+template <typename Source, bool ResultIsInteger, bool SourceIsInteger>
+struct rounding_cast<Source, Source, ResultIsInteger, SourceIsInteger>
+{
+ static inline Source apply(Source const& v)
+ {
+ return v;
+ }
+};
+
// FtoI
template <typename Result, typename Source>
-struct round<Result, Source, true, false>
+struct rounding_cast<Result, Source, true, false>
{
static inline Result apply(Source const& v)
{
- namespace bmp = boost::math::policies;
- // ignore rounding errors for backward compatibility
- typedef bmp::policy< bmp::rounding_error<bmp::ignore_error> > policy;
- return boost::numeric_cast<Result>(boost::math::round(v, policy()));
+ return boost::numeric_cast<Result>(v < Source(0) ?
+ v - Source(0.5) :
+ v + Source(0.5));
}
};
@@ -350,6 +449,12 @@ template <typename T>
inline T pi() { return detail::define_pi<T>::apply(); }
template <typename T>
+inline T two_pi() { return detail::define_two_pi<T>::apply(); }
+
+template <typename T>
+inline T half_pi() { return detail::define_half_pi<T>::apply(); }
+
+template <typename T>
inline T relaxed_epsilon(T const& factor)
{
return detail::relaxed_epsilon<T>::apply(factor);
@@ -408,9 +513,20 @@ inline bool larger(T1 const& a, T2 const& b)
}
+template <typename T>
+inline T d2r()
+{
+ static T const conversion_coefficient = geometry::math::pi<T>() / T(180.0);
+ return conversion_coefficient;
+}
+
+template <typename T>
+inline T r2d()
+{
+ static T const conversion_coefficient = T(180.0) / geometry::math::pi<T>();
+ return conversion_coefficient;
+}
-double const d2r = geometry::math::pi<double>() / 180.0;
-double const r2d = 1.0 / d2r;
/*!
\brief Calculates the haversine of an angle
@@ -455,6 +571,24 @@ sqrt(T const& value)
}
/*!
+\brief Short utility to return the modulo of two values
+\ingroup utility
+\param value1 First value
+\param value2 Second value
+\return The result of the modulo operation on the (ordered) pair
+(value1, value2)
+*/
+template <typename T>
+inline typename detail::modulo<T>::return_type
+mod(T const& value1, T const& value2)
+{
+ return detail::modulo
+ <
+ T, boost::is_fundamental<T>::value
+ >::apply(value1, value2);
+}
+
+/*!
\brief Short utility to workaround gcc/clang problem that abs is converting to integer
and that older versions of MSVC does not support abs of long long...
\ingroup utility
@@ -470,23 +604,24 @@ inline T abs(T const& value)
\ingroup utility
*/
template <typename T>
-static inline int sign(T const& value)
+inline int sign(T const& value)
{
T const zero = T();
return value > zero ? 1 : value < zero ? -1 : 0;
}
/*!
-\brief Short utility to calculate the rounded value of a number.
+\brief Short utility to cast a value possibly rounding it to the nearest
+ integral value.
\ingroup utility
\note If the source T is NOT an integral type and Result is an integral type
the value is rounded towards the closest integral value. Otherwise it's
- casted.
+ casted without rounding.
*/
template <typename Result, typename T>
-inline Result round(T const& v)
+inline Result rounding_cast(T const& v)
{
- return detail::round<Result, T>::apply(v);
+ return detail::rounding_cast<Result, T>::apply(v);
}
} // namespace math
diff --git a/boost/geometry/util/normalize_spheroidal_box_coordinates.hpp b/boost/geometry/util/normalize_spheroidal_box_coordinates.hpp
new file mode 100644
index 0000000000..eb947bb092
--- /dev/null
+++ b/boost/geometry/util/normalize_spheroidal_box_coordinates.hpp
@@ -0,0 +1,160 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
+#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace math
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename Units, typename CoordinateType>
+class normalize_spheroidal_box_coordinates
+{
+private:
+ typedef normalize_spheroidal_coordinates<Units, CoordinateType> normalize;
+ typedef constants_on_spheroid<CoordinateType, Units> constants;
+
+ static inline bool is_band(CoordinateType const& longitude1,
+ CoordinateType const& longitude2)
+ {
+ return ! math::smaller(math::abs(longitude1 - longitude2),
+ constants::period());
+ }
+
+public:
+ static inline void apply(CoordinateType& longitude1,
+ CoordinateType& latitude1,
+ CoordinateType& longitude2,
+ CoordinateType& latitude2,
+ bool band)
+ {
+ normalize::apply(longitude1, latitude1, false);
+ normalize::apply(longitude2, latitude2, false);
+
+ if (math::equals(latitude1, constants::min_latitude())
+ && math::equals(latitude2, constants::min_latitude()))
+ {
+ // box degenerates to the south pole
+ longitude1 = longitude2 = CoordinateType(0);
+ }
+ else if (math::equals(latitude1, constants::max_latitude())
+ && math::equals(latitude2, constants::max_latitude()))
+ {
+ // box degenerates to the north pole
+ longitude1 = longitude2 = CoordinateType(0);
+ }
+ else if (band)
+ {
+ // the box is a band between two small circles (parallel
+ // to the equator) on the spheroid
+ longitude1 = constants::min_longitude();
+ longitude2 = constants::max_longitude();
+ }
+ else if (longitude1 > longitude2)
+ {
+ // the box crosses the antimeridian, so we need to adjust
+ // the longitudes
+ longitude2 += constants::period();
+ }
+
+#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
+ BOOST_GEOMETRY_ASSERT(! math::larger(latitude1, latitude2));
+ BOOST_GEOMETRY_ASSERT(! math::smaller(latitude1, constants::min_latitude()));
+ BOOST_GEOMETRY_ASSERT(! math::larger(latitude2, constants::max_latitude()));
+#endif
+
+ BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2));
+ BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude()));
+ BOOST_GEOMETRY_ASSERT
+ (! math::larger(longitude2 - longitude1, constants::period()));
+ }
+
+ static inline void apply(CoordinateType& longitude1,
+ CoordinateType& latitude1,
+ CoordinateType& longitude2,
+ CoordinateType& latitude2)
+ {
+ bool const band = is_band(longitude1, longitude2);
+
+ apply(longitude1, latitude1, longitude2, latitude2, band);
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Short utility to normalize the coordinates of a box on a spheroid
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude1 Minimum longitude of the box
+\param latitude1 Minimum latitude of the box
+\param longitude2 Maximum longitude of the box
+\param latitude2 Maximum latitude of the box
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
+ CoordinateType& latitude1,
+ CoordinateType& longitude2,
+ CoordinateType& latitude2)
+{
+ detail::normalize_spheroidal_box_coordinates
+ <
+ Units, CoordinateType
+ >::apply(longitude1, latitude1, longitude2, latitude2);
+}
+
+/*!
+\brief Short utility to normalize the coordinates of a box on a spheroid
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude1 Minimum longitude of the box
+\param latitude1 Minimum latitude of the box
+\param longitude2 Maximum longitude of the box
+\param latitude2 Maximum latitude of the box
+\param band Indicates whether the box should be treated as a band or
+ not and avoid the computation done in the other version of the function
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
+ CoordinateType& latitude1,
+ CoordinateType& longitude2,
+ CoordinateType& latitude2,
+ bool band)
+{
+ detail::normalize_spheroidal_box_coordinates
+ <
+ Units, CoordinateType
+ >::apply(longitude1, latitude1, longitude2, latitude2, band);
+}
+
+
+} // namespace math
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
diff --git a/boost/geometry/util/normalize_spheroidal_coordinates.hpp b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
new file mode 100644
index 0000000000..72dfa5a6f1
--- /dev/null
+++ b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
@@ -0,0 +1,218 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
+#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace math
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename CoordinateType, typename Units>
+struct constants_on_spheroid
+{
+ static inline CoordinateType period()
+ {
+ return math::two_pi<CoordinateType>();
+ }
+
+ static inline CoordinateType half_period()
+ {
+ return math::pi<CoordinateType>();
+ }
+
+ static inline CoordinateType min_longitude()
+ {
+ static CoordinateType const minus_pi = -math::pi<CoordinateType>();
+ return minus_pi;
+ }
+
+ static inline CoordinateType max_longitude()
+ {
+ return math::pi<CoordinateType>();
+ }
+
+ static inline CoordinateType min_latitude()
+ {
+ static CoordinateType const minus_half_pi
+ = -math::half_pi<CoordinateType>();
+ return minus_half_pi;
+ }
+
+ static inline CoordinateType max_latitude()
+ {
+ return math::half_pi<CoordinateType>();
+ }
+};
+
+template <typename CoordinateType>
+struct constants_on_spheroid<CoordinateType, degree>
+{
+ static inline CoordinateType period()
+ {
+ return CoordinateType(360.0);
+ }
+
+ static inline CoordinateType half_period()
+ {
+ return CoordinateType(180.0);
+ }
+
+ static inline CoordinateType min_longitude()
+ {
+ return CoordinateType(-180.0);
+ }
+
+ static inline CoordinateType max_longitude()
+ {
+ return CoordinateType(180.0);
+ }
+
+ static inline CoordinateType min_latitude()
+ {
+ return CoordinateType(-90.0);
+ }
+
+ static inline CoordinateType max_latitude()
+ {
+ return CoordinateType(90.0);
+ }
+};
+
+
+template <typename Units, typename CoordinateType>
+class normalize_spheroidal_coordinates
+{
+ typedef constants_on_spheroid<CoordinateType, Units> constants;
+
+protected:
+ static inline CoordinateType normalize_up(CoordinateType const& value)
+ {
+ return
+ math::mod(value + constants::half_period(), constants::period())
+ - constants::half_period();
+ }
+
+ static inline CoordinateType normalize_down(CoordinateType const& value)
+ {
+ return
+ math::mod(value - constants::half_period(), constants::period())
+ + constants::half_period();
+ }
+
+public:
+ static inline void apply(CoordinateType& longitude,
+ CoordinateType& latitude,
+ bool normalize_poles = true)
+ {
+#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
+ // normalize latitude
+ if (math::larger(latitude, constants::half_period()))
+ {
+ latitude = normalize_up(latitude);
+ }
+ else if (math::smaller(latitude, -constants::half_period()))
+ {
+ latitude = normalize_down(latitude);
+ }
+
+ // fix latitude range
+ if (latitude < constants::min_latitude())
+ {
+ latitude = -constants::half_period() - latitude;
+ longitude -= constants::half_period();
+ }
+ else if (latitude > constants::max_latitude())
+ {
+ latitude = constants::half_period() - latitude;
+ longitude -= constants::half_period();
+ }
+#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
+
+ // normalize longitude
+ if (math::equals(math::abs(longitude), constants::half_period()))
+ {
+ longitude = constants::half_period();
+ }
+ else if (longitude > constants::half_period())
+ {
+ longitude = normalize_up(longitude);
+ if (math::equals(longitude, -constants::half_period()))
+ {
+ longitude = constants::half_period();
+ }
+ }
+ else if (longitude < -constants::half_period())
+ {
+ longitude = normalize_down(longitude);
+ }
+
+ // finally normalize poles
+ if (normalize_poles)
+ {
+ if (math::equals(math::abs(latitude), constants::max_latitude()))
+ {
+ // for the north and south pole we set the longitude to 0
+ // (works for both radians and degrees)
+ longitude = CoordinateType(0);
+ }
+ }
+
+#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
+ BOOST_GEOMETRY_ASSERT(! math::larger(constants::min_latitude(), latitude));
+ BOOST_GEOMETRY_ASSERT(! math::larger(latitude, constants::max_latitude()));
+#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
+
+ BOOST_GEOMETRY_ASSERT(math::smaller(constants::min_longitude(), longitude));
+ BOOST_GEOMETRY_ASSERT(! math::larger(longitude, constants::max_longitude()));
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Short utility to normalize the coordinates on a spheroid
+\tparam Units The units of the coordindate system in the spheroid
+\tparam CoordinateType The type of the coordinates
+\param longitude Longitude
+\param latitude Latitude
+\ingroup utility
+*/
+template <typename Units, typename CoordinateType>
+inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
+ CoordinateType& latitude)
+{
+ detail::normalize_spheroidal_coordinates
+ <
+ Units, CoordinateType
+ >::apply(longitude, latitude);
+}
+
+
+} // namespace math
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
diff --git a/boost/geometry/util/range.hpp b/boost/geometry/util/range.hpp
index cf69413411..0f480df58a 100644
--- a/boost/geometry/util/range.hpp
+++ b/boost/geometry/util/range.hpp
@@ -16,7 +16,6 @@
#include <algorithm>
-#include <boost/assert.hpp>
#include <boost/concept_check.hpp>
#include <boost/config.hpp>
#include <boost/range/concepts.hpp>
@@ -26,6 +25,7 @@
#include <boost/range/size.hpp>
#include <boost/type_traits/is_convertible.hpp>
+#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/mutable_range.hpp>
namespace boost { namespace geometry { namespace range {
@@ -59,7 +59,7 @@ inline typename boost::range_iterator<RandomAccessRange const>::type
pos(RandomAccessRange const& rng,
typename boost::range_size<RandomAccessRange const>::type i)
{
- BOOST_ASSERT(i <= boost::size(rng));
+ BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
return detail::pos<RandomAccessRange const>::apply(rng, i);
}
@@ -72,7 +72,7 @@ inline typename boost::range_iterator<RandomAccessRange>::type
pos(RandomAccessRange & rng,
typename boost::range_size<RandomAccessRange>::type i)
{
- BOOST_ASSERT(i <= boost::size(rng));
+ BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
return detail::pos<RandomAccessRange>::apply(rng, i);
}
@@ -85,7 +85,7 @@ inline typename boost::range_reference<RandomAccessRange const>::type
at(RandomAccessRange const& rng,
typename boost::range_size<RandomAccessRange const>::type i)
{
- BOOST_ASSERT(i < boost::size(rng));
+ BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
return * detail::pos<RandomAccessRange const>::apply(rng, i);
}
@@ -98,7 +98,7 @@ inline typename boost::range_reference<RandomAccessRange>::type
at(RandomAccessRange & rng,
typename boost::range_size<RandomAccessRange>::type i)
{
- BOOST_ASSERT(i < boost::size(rng));
+ BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
return * detail::pos<RandomAccessRange>::apply(rng, i);
}
@@ -110,7 +110,7 @@ template <typename Range>
inline typename boost::range_reference<Range const>::type
front(Range const& rng)
{
- BOOST_ASSERT(!boost::empty(rng));
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
@@ -122,7 +122,7 @@ template <typename Range>
inline typename boost::range_reference<Range>::type
front(Range & rng)
{
- BOOST_ASSERT(!boost::empty(rng));
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
@@ -137,7 +137,7 @@ inline typename boost::range_reference<BidirectionalRange const>::type
back(BidirectionalRange const& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));
- BOOST_ASSERT(!boost::empty(rng));
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *(boost::rbegin(rng));
}
@@ -150,7 +150,7 @@ inline typename boost::range_reference<BidirectionalRange>::type
back(BidirectionalRange & rng)
{
BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));
- BOOST_ASSERT(!boost::empty(rng));
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *(boost::rbegin(rng));
}
@@ -200,7 +200,7 @@ inline void resize(Range & rng,
template <typename Range>
inline void pop_back(Range & rng)
{
- BOOST_ASSERT(!boost::empty(rng));
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
range::resize(rng, boost::size(rng) - 1);
}
@@ -260,8 +260,8 @@ inline typename boost::range_iterator<Range>::type
erase(Range & rng,
typename boost::range_iterator<Range>::type it)
{
- BOOST_ASSERT(!boost::empty(rng));
- BOOST_ASSERT(it != boost::end(rng));
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
+ BOOST_GEOMETRY_ASSERT(it != boost::end(rng));
typename boost::range_difference<Range>::type const
d = std::distance(boost::begin(rng), it);
@@ -314,10 +314,10 @@ erase(Range & rng,
{
typename boost::range_difference<Range>::type const
diff = std::distance(first, last);
- BOOST_ASSERT(diff >= 0);
+ BOOST_GEOMETRY_ASSERT(diff >= 0);
std::size_t const count = static_cast<std::size_t>(diff);
- BOOST_ASSERT(count <= boost::size(rng));
+ BOOST_GEOMETRY_ASSERT(count <= boost::size(rng));
if ( count > 0 )
{
diff --git a/boost/geometry/views/detail/boundary_view.hpp b/boost/geometry/views/detail/boundary_view.hpp
new file mode 100644
index 0000000000..43bd5b202d
--- /dev/null
+++ b/boost/geometry/views/detail/boundary_view.hpp
@@ -0,0 +1,16 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP
+
+#include <boost/geometry/views/detail/boundary_view/interface.hpp>
+#include <boost/geometry/views/detail/boundary_view/implementation.hpp>
+
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP
diff --git a/boost/geometry/views/detail/boundary_view/implementation.hpp b/boost/geometry/views/detail/boundary_view/implementation.hpp
new file mode 100644
index 0000000000..e6a09afd68
--- /dev/null
+++ b/boost/geometry/views/detail/boundary_view/implementation.hpp
@@ -0,0 +1,466 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP
+
+#include <cstddef>
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <new>
+#include <utility>
+#include <vector>
+
+#include <boost/core/addressof.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/iterators/flatten_iterator.hpp>
+
+#include <boost/geometry/util/range.hpp>
+
+#include <boost/geometry/views/closeable_view.hpp>
+
+#include <boost/geometry/algorithms/num_interior_rings.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace boundary_views
+{
+
+
+template
+<
+ typename Polygon,
+ typename Value = typename ring_type<Polygon>::type,
+ typename Reference = typename ring_return_type<Polygon>::type,
+ typename Difference = typename boost::range_difference
+ <
+ typename boost::remove_reference
+ <
+ typename interior_return_type<Polygon>::type
+ >::type
+ >::type
+>
+class polygon_rings_iterator
+ : public boost::iterator_facade
+ <
+ polygon_rings_iterator<Polygon, Value, Reference, Difference>,
+ Value,
+ boost::random_access_traversal_tag,
+ Reference,
+ Difference
+ >
+{
+ typedef typename boost::range_size
+ <
+ typename boost::remove_reference
+ <
+ typename interior_return_type<Polygon>::type
+ >::type
+ >::type size_type;
+
+public:
+ // default constructor
+ polygon_rings_iterator()
+ : m_polygon(NULL)
+ , m_index(0)
+ {}
+
+ // for begin
+ polygon_rings_iterator(Polygon& polygon)
+ : m_polygon(boost::addressof(polygon))
+ , m_index(0)
+ {}
+
+ // for end
+ polygon_rings_iterator(Polygon& polygon, bool)
+ : m_polygon(boost::addressof(polygon))
+ , m_index(static_cast<size_type>(num_rings(polygon)))
+ {}
+
+ template
+ <
+ typename OtherPolygon,
+ typename OtherValue,
+ typename OtherReference,
+ typename OtherDifference
+ >
+ polygon_rings_iterator(polygon_rings_iterator
+ <
+ OtherPolygon,
+ OtherValue,
+ OtherReference,
+ OtherDifference
+ > const& other)
+ : m_polygon(other.m_polygon)
+ , m_index(other.m_index)
+ {
+ static const bool is_convertible
+ = boost::is_convertible<OtherPolygon, Polygon>::value;
+
+ BOOST_MPL_ASSERT_MSG((is_convertible),
+ NOT_CONVERTIBLE,
+ (types<OtherPolygon>));
+ }
+
+private:
+ friend class boost::iterator_core_access;
+
+ template
+ <
+ typename OtherPolygon,
+ typename OtherValue,
+ typename OtherReference,
+ typename OtherDifference
+ >
+ friend class polygon_rings_iterator;
+
+
+ static inline std::size_t num_rings(Polygon const& polygon)
+ {
+ return geometry::num_interior_rings(polygon) + 1;
+ }
+
+ inline Reference dereference() const
+ {
+ if (m_index == 0)
+ {
+ return exterior_ring(*m_polygon);
+ }
+ return range::at(interior_rings(*m_polygon), m_index - 1);
+ }
+
+ template
+ <
+ typename OtherPolygon,
+ typename OtherValue,
+ typename OtherReference,
+ typename OtherDifference
+ >
+ inline bool equal(polygon_rings_iterator
+ <
+ OtherPolygon,
+ OtherValue,
+ OtherReference,
+ OtherDifference
+ > const& other) const
+ {
+ BOOST_GEOMETRY_ASSERT(m_polygon == other.m_polygon);
+ return m_index == other.m_index;
+ }
+
+ inline void increment()
+ {
+ ++m_index;
+ }
+
+ inline void decrement()
+ {
+ --m_index;
+ }
+
+ template
+ <
+ typename OtherPolygon,
+ typename OtherValue,
+ typename OtherReference,
+ typename OtherDifference
+ >
+ inline Difference distance_to(polygon_rings_iterator
+ <
+ OtherPolygon,
+ OtherValue,
+ OtherReference,
+ OtherDifference
+ > const& other) const
+ {
+ return static_cast<Difference>(other.m_index)
+ - static_cast<Difference>(m_index);
+ }
+
+ inline void advance(Difference n)
+ {
+ m_index += n;
+ }
+
+private:
+ Polygon* m_polygon;
+ size_type m_index;
+};
+
+
+template <typename Ring>
+class ring_boundary : closeable_view<Ring, closure<Ring>::value>::type
+{
+private:
+ typedef typename closeable_view<Ring, closure<Ring>::value>::type base_type;
+
+public:
+ typedef typename base_type::iterator iterator;
+ typedef typename base_type::const_iterator const_iterator;
+
+ typedef linestring_tag tag_type;
+
+ explicit ring_boundary(Ring& ring)
+ : base_type(ring) {}
+
+ iterator begin() { return base_type::begin(); }
+ iterator end() { return base_type::end(); }
+ const_iterator begin() const { return base_type::begin(); }
+ const_iterator end() const { return base_type::end(); }
+};
+
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct num_rings
+{};
+
+template <typename Polygon>
+struct num_rings<Polygon, polygon_tag>
+{
+ static inline std::size_t apply(Polygon const& polygon)
+ {
+ return geometry::num_interior_rings(polygon) + 1;
+ }
+};
+
+template <typename MultiPolygon>
+struct num_rings<MultiPolygon, multi_polygon_tag>
+{
+ static inline std::size_t apply(MultiPolygon const& multipolygon)
+ {
+ return geometry::num_interior_rings(multipolygon)
+ + static_cast<std::size_t>(boost::size(multipolygon));
+ }
+};
+
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct views_container_initializer
+{};
+
+template <typename Polygon>
+struct views_container_initializer<Polygon, polygon_tag>
+{
+ template <typename BoundaryView>
+ static inline void apply(Polygon const& polygon, BoundaryView* views)
+ {
+ typedef polygon_rings_iterator<Polygon> rings_iterator_type;
+
+ std::uninitialized_copy(rings_iterator_type(polygon),
+ rings_iterator_type(polygon, true),
+ views);
+ }
+};
+
+template <typename MultiPolygon>
+class views_container_initializer<MultiPolygon, multi_polygon_tag>
+{
+ typedef typename boost::mpl::if_
+ <
+ boost::is_const<MultiPolygon>,
+ typename boost::range_value<MultiPolygon>::type const,
+ typename boost::range_value<MultiPolygon>::type
+ >::type polygon_type;
+
+ typedef polygon_rings_iterator<polygon_type> inner_iterator_type;
+
+ struct polygon_rings_begin
+ {
+ static inline inner_iterator_type apply(polygon_type& polygon)
+ {
+ return inner_iterator_type(polygon);
+ }
+ };
+
+ struct polygon_rings_end
+ {
+ static inline inner_iterator_type apply(polygon_type& polygon)
+ {
+ return inner_iterator_type(polygon, true);
+ }
+ };
+
+ typedef flatten_iterator
+ <
+ typename boost::range_iterator<MultiPolygon>::type,
+ inner_iterator_type,
+ typename std::iterator_traits<inner_iterator_type>::value_type,
+ polygon_rings_begin,
+ polygon_rings_end,
+ typename std::iterator_traits<inner_iterator_type>::reference
+ > rings_iterator_type;
+
+public:
+ template <typename BoundaryView>
+ static inline void apply(MultiPolygon const& multipolygon,
+ BoundaryView* views)
+ {
+ rings_iterator_type first(boost::begin(multipolygon),
+ boost::end(multipolygon));
+ rings_iterator_type last(boost::end(multipolygon));
+
+ std::uninitialized_copy(first, last, views);
+ }
+};
+
+
+template <typename Areal>
+class areal_boundary
+{
+ typedef boundary_view<typename ring_type<Areal>::type> boundary_view_type;
+ typedef views_container_initializer<Areal> exception_safe_initializer;
+
+ template <typename T>
+ struct automatic_deallocator
+ {
+ automatic_deallocator(T* ptr) : m_ptr(ptr) {}
+
+ ~automatic_deallocator()
+ {
+ operator delete(m_ptr);
+ }
+
+ inline void release() { m_ptr = NULL; }
+
+ T* m_ptr;
+ };
+
+ inline void initialize_views(Areal const& areal)
+ {
+ // initialize number of rings
+ std::size_t n_rings = num_rings<Areal>::apply(areal);
+
+ if (n_rings == 0)
+ {
+ return;
+ }
+
+ // allocate dynamic memory
+ boundary_view_type* views_ptr = static_cast
+ <
+ boundary_view_type*
+ >(operator new(sizeof(boundary_view_type) * n_rings));
+
+ // initialize; if exceptions are thrown by constructors
+ // they are handled automatically by automatic_deallocator
+ automatic_deallocator<boundary_view_type> deallocator(views_ptr);
+ exception_safe_initializer::apply(areal, views_ptr);
+ deallocator.release();
+
+ // now initialize member variables safely
+ m_views = views_ptr;
+ m_num_rings = n_rings;
+ }
+
+ // disallow copies and/or assignments
+ areal_boundary(areal_boundary const&);
+ areal_boundary& operator=(areal_boundary const&);
+
+public:
+ typedef boundary_view_type* iterator;
+ typedef boundary_view_type const* const_iterator;
+
+ typedef multi_linestring_tag tag_type;
+
+ explicit areal_boundary(Areal& areal)
+ : m_views(NULL)
+ , m_num_rings(0)
+ {
+ initialize_views(areal);
+ }
+
+ ~areal_boundary()
+ {
+ boundary_view_type* last = m_views + m_num_rings;
+ for (boundary_view_type* it = m_views; it != last; ++it)
+ {
+ it->~boundary_view_type();
+ }
+ operator delete(m_views);
+ }
+
+ inline iterator begin() { return m_views; }
+ inline iterator end() { return m_views + m_num_rings; }
+ inline const_iterator begin() const { return m_views; }
+ inline const_iterator end() const { return m_views + m_num_rings; }
+
+private:
+ boundary_view_type* m_views;
+ std::size_t m_num_rings;
+};
+
+
+}} // namespace detail::boundary_view
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace detail_dispatch
+{
+
+
+template <typename Ring>
+struct boundary_view<Ring, ring_tag>
+ : detail::boundary_views::ring_boundary<Ring>
+{
+ explicit boundary_view(Ring& ring)
+ : detail::boundary_views::ring_boundary<Ring>(ring)
+ {}
+};
+
+template <typename Polygon>
+struct boundary_view<Polygon, polygon_tag>
+ : detail::boundary_views::areal_boundary<Polygon>
+{
+ explicit boundary_view(Polygon& polygon)
+ : detail::boundary_views::areal_boundary<Polygon>(polygon)
+ {}
+};
+
+template <typename MultiPolygon>
+struct boundary_view<MultiPolygon, multi_polygon_tag>
+ : detail::boundary_views::areal_boundary<MultiPolygon>
+{
+ explicit boundary_view(MultiPolygon& multipolygon)
+ : detail::boundary_views::areal_boundary
+ <
+ MultiPolygon
+ >(multipolygon)
+ {}
+};
+
+
+} // namespace detail_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP
diff --git a/boost/geometry/views/detail/boundary_view/interface.hpp b/boost/geometry/views/detail/boundary_view/interface.hpp
new file mode 100644
index 0000000000..4d0b6d0303
--- /dev/null
+++ b/boost/geometry/views/detail/boundary_view/interface.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP
+#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace detail_dispatch
+{
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct boundary_view
+ : not_implemented<Tag>
+{};
+
+} // namespace detail_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Geometry>
+struct boundary_view
+ : detail_dispatch::boundary_view<Geometry>
+{
+ explicit boundary_view(Geometry& geometry)
+ : detail_dispatch::boundary_view<Geometry>(geometry)
+ {}
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename Geometry>
+struct tag< geometry::detail::boundary_view<Geometry> >
+{
+ typedef typename detail_dispatch::boundary_view
+ <
+ Geometry
+ >::tag_type type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP
diff --git a/boost/geometry/views/detail/indexed_point_view.hpp b/boost/geometry/views/detail/indexed_point_view.hpp
index 88b13ec5c4..e5a89c9ae7 100644
--- a/boost/geometry/views/detail/indexed_point_view.hpp
+++ b/boost/geometry/views/detail/indexed_point_view.hpp
@@ -1,9 +1,14 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland
+// 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
+
+// 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
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -62,41 +67,47 @@ namespace traits
{
template <typename Geometry, std::size_t Index>
-struct tag< detail::indexed_point_view<Geometry, Index> >
+struct tag< geometry::detail::indexed_point_view<Geometry, Index> >
{
typedef point_tag type;
};
template <typename Geometry, std::size_t Index>
-struct coordinate_type< detail::indexed_point_view<Geometry, Index> >
+struct coordinate_type< geometry::detail::indexed_point_view<Geometry, Index> >
{
typedef typename geometry::coordinate_type<Geometry>::type type;
};
template <typename Geometry, std::size_t Index>
-struct coordinate_system< detail::indexed_point_view<Geometry, Index> >
+struct coordinate_system
+ <
+ geometry::detail::indexed_point_view<Geometry, Index>
+ >
{
typedef typename geometry::coordinate_system<Geometry>::type type;
};
template <typename Geometry, std::size_t Index>
-struct dimension< detail::indexed_point_view<Geometry, Index> >
+struct dimension< geometry::detail::indexed_point_view<Geometry, Index> >
: geometry::dimension<Geometry>
{};
template<typename Geometry, std::size_t Index, std::size_t Dimension>
-struct access< detail::indexed_point_view<Geometry, Index>, Dimension >
+struct access
+ <
+ geometry::detail::indexed_point_view<Geometry, Index>, Dimension
+ >
{
typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
static inline coordinate_type get(
- detail::indexed_point_view<Geometry, Index> const& p)
+ geometry::detail::indexed_point_view<Geometry, Index> const& p)
{
return p.template get<Dimension>();
}
static inline void set(
- detail::indexed_point_view<Geometry, Index> & p,
+ geometry::detail::indexed_point_view<Geometry, Index> & p,
coordinate_type const& value)
{
p.template set<Dimension>(value);
diff --git a/boost/geometry/views/detail/two_dimensional_view.hpp b/boost/geometry/views/detail/two_dimensional_view.hpp
new file mode 100644
index 0000000000..fbd993cafc
--- /dev/null
+++ b/boost/geometry/views/detail/two_dimensional_view.hpp
@@ -0,0 +1,196 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/int.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.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_DETAIL
+namespace detail
+{
+
+template
+<
+ typename Geometry,
+ std::size_t Dimension1 = 0,
+ std::size_t Dimension2 = 1,
+ typename Tag = typename tag<Geometry>::type
+>
+struct two_dimensional_view
+ : not_implemented<Tag>
+{};
+
+
+// View that enables to choose two dimensions of a point and see it as
+// a two-dimensional point
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct two_dimensional_view<Point, Dimension1, Dimension2, point_tag>
+{
+ BOOST_MPL_ASSERT_MSG(
+ (Dimension1 < static_cast<std::size_t>(dimension<Point>::value)),
+ COORDINATE_DIMENSION1_IS_LARGER_THAN_POINT_DIMENSION,
+ (boost::mpl::int_<Dimension1>));
+
+ BOOST_MPL_ASSERT_MSG(
+ (Dimension2 < static_cast<std::size_t>(dimension<Point>::value)),
+ COORDINATE_DIMENSION2_IS_LARGER_THAN_POINT_DIMENSION,
+ (boost::mpl::int_<Dimension2>));
+
+ two_dimensional_view(Point& point)
+ : m_point(point)
+ {}
+
+ Point& m_point;
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct tag
+ <
+ geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ >
+ >
+{
+ typedef point_tag type;
+};
+
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct coordinate_system
+ <
+ geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ >
+ > : coordinate_system<typename geometry::point_type<Point>::type>
+{};
+
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct coordinate_type
+ <
+ geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ >
+ > : coordinate_type<typename geometry::point_type<Point>::type>
+{};
+
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct dimension
+ <
+ geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ >
+ > : boost::mpl::int_<2>
+{};
+
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct point_type
+ <
+ geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ >
+ >
+{
+ typedef typename geometry::point_type<Point>::type type;
+};
+
+
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct access
+ <
+ geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ >,
+ 0
+ >
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+ typedef geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ > view_type;
+
+ static inline coordinate_type get(view_type const& view)
+ {
+ return geometry::get<Dimension1>(view.m_point);
+ }
+
+ static inline void set(view_type& view, coordinate_type const& value)
+ {
+ geometry::set<Dimension1>(view.m_point, value);
+ }
+};
+
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>
+struct access
+ <
+ geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ >,
+ 1
+ >
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+ typedef geometry::detail::two_dimensional_view
+ <
+ Point, Dimension1, Dimension2, point_tag
+ > view_type;
+
+ static inline coordinate_type get(view_type const& view)
+ {
+ return geometry::get<Dimension2>(view.m_point);
+ }
+
+ static inline void set(view_type& view, coordinate_type const& value)
+ {
+ geometry::set<Dimension2>(view.m_point, value);
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP