summaryrefslogtreecommitdiff
path: root/boost/geometry
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry')
-rw-r--r--boost/geometry/algorithms/append.hpp4
-rw-r--r--boost/geometry/algorithms/area.hpp3
-rw-r--r--boost/geometry/algorithms/assign.hpp37
-rw-r--r--boost/geometry/algorithms/buffer.hpp3
-rw-r--r--boost/geometry/algorithms/centroid.hpp119
-rw-r--r--boost/geometry/algorithms/clear.hpp1
-rw-r--r--boost/geometry/algorithms/convert.hpp5
-rw-r--r--boost/geometry/algorithms/convex_hull.hpp11
-rw-r--r--boost/geometry/algorithms/correct.hpp3
-rw-r--r--boost/geometry/algorithms/covered_by.hpp2
-rw-r--r--boost/geometry/algorithms/crosses.hpp11
-rw-r--r--boost/geometry/algorithms/detail/azimuth.hpp158
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp155
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_policies.hpp11
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp503
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_ring.hpp6
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp152
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_input.hpp98
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp268
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp557
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp3
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp1
-rw-r--r--boost/geometry/algorithms/detail/comparable_distance/interface.hpp20
-rw-r--r--boost/geometry/algorithms/detail/course.hpp24
-rw-r--r--boost/geometry/algorithms/detail/disjoint/box_box.hpp2
-rw-r--r--boost/geometry/algorithms/detail/disjoint/implementation.hpp1
-rw-r--r--boost/geometry/algorithms/detail/disjoint/interface.hpp2
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_areal.hpp104
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_linear.hpp47
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp31
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp162
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp85
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_box.hpp15
-rw-r--r--boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp8
-rw-r--r--boost/geometry/algorithms/detail/distance/interface.hpp20
-rw-r--r--boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp33
-rw-r--r--boost/geometry/algorithms/detail/distance/segment_to_box.hpp3
-rw-r--r--boost/geometry/algorithms/detail/distance/segment_to_segment.hpp4
-rw-r--r--boost/geometry/algorithms/detail/equals/collect_vectors.hpp5
-rw-r--r--boost/geometry/algorithms/detail/flattening.hpp69
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp8
-rw-r--r--boost/geometry/algorithms/detail/is_simple/areal.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp81
-rw-r--r--boost/geometry/algorithms/detail/is_simple/failure_policy.hpp53
-rw-r--r--boost/geometry/algorithms/detail/is_simple/interface.hpp2
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp305
-rw-r--r--boost/geometry/algorithms/detail/is_simple/multipoint.hpp9
-rw-r--r--boost/geometry/algorithms/detail/is_valid/box.hpp27
-rw-r--r--boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp50
-rw-r--r--boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp4
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp13
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_spikes.hpp36
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp32
-rw-r--r--boost/geometry/algorithms/detail/is_valid/interface.hpp99
-rw-r--r--boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp12
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp81
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp131
-rw-r--r--boost/geometry/algorithms/detail/is_valid/pointlike.hpp28
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp163
-rw-r--r--boost/geometry/algorithms/detail/is_valid/ring.hpp98
-rw-r--r--boost/geometry/algorithms/detail/is_valid/segment.hpp16
-rw-r--r--boost/geometry/algorithms/detail/not.hpp17
-rw-r--r--boost/geometry/algorithms/detail/occupation_info.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp7
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp19
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp33
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp59
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp26
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp111
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp4
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp195
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp78
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp80
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp43
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp118
-rw-r--r--boost/geometry/algorithms/detail/overlay/ring_properties.hpp14
-rw-r--r--boost/geometry/algorithms/detail/overlay/select_rings.hpp217
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp25
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp349
-rw-r--r--boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp3
-rw-r--r--boost/geometry/algorithms/detail/relate/areal_areal.hpp52
-rw-r--r--boost/geometry/algorithms/detail/relate/follow_helpers.hpp13
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_areal.hpp385
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_linear.hpp35
-rw-r--r--boost/geometry/algorithms/detail/relate/point_geometry.hpp12
-rw-r--r--boost/geometry/algorithms/detail/relate/result.hpp27
-rw-r--r--boost/geometry/algorithms/detail/relate/turns.hpp85
-rw-r--r--boost/geometry/algorithms/detail/sections/range_by_section.hpp9
-rw-r--r--boost/geometry/algorithms/detail/sections/section_box_policies.hpp49
-rw-r--r--boost/geometry/algorithms/detail/sections/section_functions.hpp66
-rw-r--r--boost/geometry/algorithms/detail/sections/sectionalize.hpp368
-rw-r--r--boost/geometry/algorithms/detail/single_geometry.hpp3
-rw-r--r--boost/geometry/algorithms/detail/sub_range.hpp12
-rw-r--r--boost/geometry/algorithms/detail/turns/print_turns.hpp37
-rw-r--r--boost/geometry/algorithms/detail/vincenty_direct.hpp190
-rw-r--r--boost/geometry/algorithms/detail/vincenty_inverse.hpp218
-rw-r--r--boost/geometry/algorithms/detail/within/point_in_geometry.hpp24
-rw-r--r--boost/geometry/algorithms/dispatch/is_valid.hpp6
-rw-r--r--boost/geometry/algorithms/envelope.hpp3
-rw-r--r--boost/geometry/algorithms/equals.hpp21
-rw-r--r--boost/geometry/algorithms/expand.hpp7
-rw-r--r--boost/geometry/algorithms/length.hpp9
-rw-r--r--boost/geometry/algorithms/not_implemented.hpp29
-rw-r--r--boost/geometry/algorithms/num_geometries.hpp3
-rw-r--r--boost/geometry/algorithms/num_interior_rings.hpp2
-rw-r--r--boost/geometry/algorithms/num_points.hpp2
-rw-r--r--boost/geometry/algorithms/num_segments.hpp2
-rw-r--r--boost/geometry/algorithms/perimeter.hpp3
-rw-r--r--boost/geometry/algorithms/remove_spikes.hpp11
-rw-r--r--boost/geometry/algorithms/reverse.hpp3
-rw-r--r--boost/geometry/algorithms/simplify.hpp13
-rw-r--r--boost/geometry/algorithms/touches.hpp7
-rw-r--r--boost/geometry/algorithms/transform.hpp3
-rw-r--r--boost/geometry/algorithms/validity_failure_type.hpp87
-rw-r--r--boost/geometry/algorithms/within.hpp3
-rw-r--r--boost/geometry/core/cs.hpp63
-rw-r--r--boost/geometry/core/interior_type.hpp2
-rw-r--r--boost/geometry/core/radius.hpp250
-rw-r--r--boost/geometry/core/ring_type.hpp17
-rw-r--r--boost/geometry/core/srs.hpp195
-rw-r--r--boost/geometry/core/tags.hpp13
-rw-r--r--boost/geometry/geometries/adapted/boost_fusion.hpp24
-rw-r--r--boost/geometry/geometries/concepts/point_concept.hpp30
-rw-r--r--boost/geometry/geometries/linestring.hpp31
-rw-r--r--boost/geometry/geometries/multi_linestring.hpp40
-rw-r--r--boost/geometry/geometries/multi_point.hpp31
-rw-r--r--boost/geometry/geometries/multi_polygon.hpp41
-rw-r--r--boost/geometry/geometries/point.hpp81
-rw-r--r--boost/geometry/geometries/polygon.hpp48
-rw-r--r--boost/geometry/geometries/ring.hpp31
-rw-r--r--boost/geometry/geometries/variant.hpp7
-rw-r--r--boost/geometry/geometry.hpp15
-rw-r--r--boost/geometry/index/detail/algorithms/is_valid.hpp3
-rw-r--r--boost/geometry/index/detail/assert.hpp17
-rw-r--r--boost/geometry/index/detail/bounded_view.hpp4
-rw-r--r--boost/geometry/index/detail/distance_predicates.hpp18
-rw-r--r--boost/geometry/index/detail/exception.hpp33
-rw-r--r--boost/geometry/index/detail/predicates.hpp114
-rw-r--r--boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp2
-rw-r--r--boost/geometry/index/detail/rtree/node/auto_deallocator.hpp38
-rw-r--r--boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp67
-rw-r--r--boost/geometry/index/detail/rtree/node/node.hpp14
-rw-r--r--boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp48
-rw-r--r--boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp (renamed from boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp)24
-rw-r--r--boost/geometry/index/detail/rtree/node/variant_dynamic.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/node/variant_static.hpp36
-rw-r--r--boost/geometry/index/detail/rtree/node/variant_visitor.hpp4
-rw-r--r--boost/geometry/index/detail/rtree/node/weak_dynamic.hpp2
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp46
-rw-r--r--boost/geometry/index/detail/rtree/query_iterators.hpp267
-rw-r--r--boost/geometry/index/detail/rtree/rstar/insert.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp110
-rw-r--r--boost/geometry/index/detail/rtree/visitors/copy.hpp10
-rw-r--r--boost/geometry/index/detail/rtree/visitors/destroy.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/visitors/distance_query.hpp12
-rw-r--r--boost/geometry/index/detail/rtree/visitors/insert.hpp16
-rw-r--r--boost/geometry/index/detail/rtree/visitors/is_leaf.hpp8
-rw-r--r--boost/geometry/index/detail/rtree/visitors/remove.hpp23
-rw-r--r--boost/geometry/index/detail/rtree/visitors/spatial_query.hpp4
-rw-r--r--boost/geometry/index/detail/serialization.hpp14
-rw-r--r--boost/geometry/index/detail/varray.hpp66
-rw-r--r--boost/geometry/index/detail/varray_detail.hpp24
-rw-r--r--boost/geometry/index/equal_to.hpp9
-rw-r--r--boost/geometry/index/parameters.hpp3
-rw-r--r--boost/geometry/index/predicates.hpp90
-rw-r--r--boost/geometry/index/rtree.hpp83
-rw-r--r--boost/geometry/io/wkt/read.hpp115
-rw-r--r--boost/geometry/io/wkt/write.hpp1
-rw-r--r--boost/geometry/iterators/closing_iterator.hpp20
-rw-r--r--boost/geometry/iterators/concatenate_iterator.hpp30
-rw-r--r--boost/geometry/iterators/detail/segment_iterator/range_segment_iterator.hpp52
-rw-r--r--boost/geometry/iterators/ever_circling_iterator.hpp9
-rw-r--r--boost/geometry/iterators/flatten_iterator.hpp43
-rw-r--r--boost/geometry/iterators/point_iterator.hpp24
-rw-r--r--boost/geometry/iterators/point_reverse_iterator.hpp17
-rw-r--r--boost/geometry/iterators/segment_iterator.hpp36
-rw-r--r--boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp16
-rw-r--r--boost/geometry/policies/is_valid/default_policy.hpp59
-rw-r--r--boost/geometry/policies/is_valid/failing_reason_policy.hpp218
-rw-r--r--boost/geometry/policies/is_valid/failure_type_policy.hpp83
-rw-r--r--boost/geometry/policies/relate/direction.hpp55
-rw-r--r--boost/geometry/policies/relate/intersection_points.hpp38
-rw-r--r--boost/geometry/policies/relate/tupled.hpp17
-rw-r--r--boost/geometry/policies/robustness/get_rescale_policy.hpp74
-rw-r--r--boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp4
-rw-r--r--boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp5
-rw-r--r--boost/geometry/strategies/agnostic/hull_graham_andrew.hpp2
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp12
-rw-r--r--boost/geometry/strategies/agnostic/relate.hpp31
-rw-r--r--boost/geometry/strategies/agnostic/side_by_azimuth.hpp87
-rw-r--r--boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp51
-rw-r--r--boost/geometry/strategies/cartesian/buffer_end_round.hpp12
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_miter.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_round.hpp48
-rw-r--r--boost/geometry/strategies/cartesian/buffer_point_circle.hpp14
-rw-r--r--boost/geometry/strategies/cartesian/cart_intersect.hpp169
-rw-r--r--boost/geometry/strategies/cartesian/centroid_average.hpp18
-rw-r--r--boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp9
-rw-r--r--boost/geometry/strategies/cartesian/side_by_triangle.hpp179
-rw-r--r--boost/geometry/strategies/cartesian/side_of_intersection.hpp119
-rw-r--r--boost/geometry/strategies/comparable_distance_result.hpp20
-rw-r--r--boost/geometry/strategies/concepts/distance_concept.hpp66
-rw-r--r--boost/geometry/strategies/distance_result.hpp36
-rw-r--r--boost/geometry/strategies/geographic/distance_andoyer.hpp224
-rw-r--r--boost/geometry/strategies/geographic/distance_vincenty.hpp161
-rw-r--r--boost/geometry/strategies/geographic/mapping_ssf.hpp185
-rw-r--r--boost/geometry/strategies/spherical/distance_cross_track.hpp531
-rw-r--r--boost/geometry/strategies/spherical/distance_haversine.hpp2
-rw-r--r--boost/geometry/strategies/spherical/side_by_cross_track.hpp42
-rw-r--r--boost/geometry/strategies/spherical/ssf.hpp109
-rw-r--r--boost/geometry/strategies/strategies.hpp3
-rw-r--r--boost/geometry/util/combine_if.hpp44
-rw-r--r--boost/geometry/util/compress_variant.hpp44
-rw-r--r--boost/geometry/util/condition.hpp44
-rw-r--r--boost/geometry/util/math.hpp224
-rw-r--r--boost/geometry/util/promote_integral.hpp318
-rw-r--r--boost/geometry/util/range.hpp78
-rw-r--r--boost/geometry/util/select_calculation_type.hpp27
-rw-r--r--boost/geometry/util/select_coordinate_type.hpp26
-rw-r--r--boost/geometry/util/select_most_precise.hpp23
-rw-r--r--boost/geometry/util/transform_variant.hpp17
-rw-r--r--boost/geometry/views/detail/normalized_view.hpp1
225 files changed, 10018 insertions, 3247 deletions
diff --git a/boost/geometry/algorithms/append.hpp b/boost/geometry/algorithms/append.hpp
index 1a8828ba4b..6ffb5f9587 100644
--- a/boost/geometry/algorithms/append.hpp
+++ b/boost/geometry/algorithms/append.hpp
@@ -22,8 +22,10 @@
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp
index 7377798719..cb1501d8c9 100644
--- a/boost/geometry/algorithms/area.hpp
+++ b/boost/geometry/algorithms/area.hpp
@@ -18,8 +18,9 @@
#include <boost/mpl/if.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/metafunctions.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
diff --git a/boost/geometry/algorithms/assign.hpp b/boost/geometry/algorithms/assign.hpp
index 32f095b9ac..2f325448ad 100644
--- a/boost/geometry/algorithms/assign.hpp
+++ b/boost/geometry/algorithms/assign.hpp
@@ -26,6 +26,10 @@
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
@@ -41,8 +45,6 @@
#include <boost/geometry/util/for_each_coordinate.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
namespace boost { namespace geometry
{
@@ -224,28 +226,27 @@ template <typename Geometry1, typename Geometry2>
struct assign
{
static inline void
- apply(
- Geometry1& geometry1,
- const Geometry2& geometry2)
+ apply(Geometry1& geometry1, const Geometry2& geometry2)
{
concept::check<Geometry1>();
concept::check<Geometry2 const>();
concept::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
- bool const same_point_order =
- point_order<Geometry1>::value == point_order<Geometry2>::value;
- bool const same_closure =
- closure<Geometry1>::value == closure<Geometry2>::value;
-
+ static bool const same_point_order
+ = point_order<Geometry1>::value == point_order<Geometry2>::value;
BOOST_MPL_ASSERT_MSG
(
- same_point_order, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER
- , (types<Geometry1, Geometry2>)
+ (same_point_order),
+ ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER,
+ (types<Geometry1, Geometry2>)
);
+ static bool const same_closure
+ = closure<Geometry1>::value == closure<Geometry2>::value;
BOOST_MPL_ASSERT_MSG
(
- same_closure, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE
- , (types<Geometry1, Geometry2>)
+ (same_closure),
+ ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE,
+ (types<Geometry1, Geometry2>)
);
dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);
@@ -317,8 +318,8 @@ struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename A), BOOST_VARIANT_ENUM_PARAMS(typename B)>
-struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(A)>, variant<BOOST_VARIANT_ENUM_PARAMS(B)> >
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
struct visitor: static_visitor<void>
{
@@ -337,8 +338,8 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(A)>, variant<BOOST_VARIANT_ENUM_
};
static inline void
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(A)>& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(B)> const& geometry2)
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
{
return apply_visitor(visitor(), geometry1, geometry2);
}
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
index b8b07ad4d9..d85d32a0c6 100644
--- a/boost/geometry/algorithms/buffer.hpp
+++ b/boost/geometry/algorithms/buffer.hpp
@@ -17,8 +17,9 @@
#include <cstddef>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/variant/static_visitor.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>
diff --git a/boost/geometry/algorithms/centroid.hpp b/boost/geometry/algorithms/centroid.hpp
index 65dc9c3753..67ed68ac03 100644
--- a/boost/geometry/algorithms/centroid.hpp
+++ b/boost/geometry/algorithms/centroid.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+// 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
@@ -23,9 +23,11 @@
#include <cstddef>
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -41,8 +43,9 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/assign.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/concepts/centroid_concept.hpp>
@@ -116,8 +119,8 @@ template
<
typename Indexed,
typename Point,
- std::size_t Dimension,
- std::size_t DimensionCount
+ std::size_t Dimension = 0,
+ std::size_t DimensionCount = dimension<Indexed>::type::value
>
struct centroid_indexed_calculator
{
@@ -137,8 +140,7 @@ struct centroid_indexed_calculator
centroid_indexed_calculator
<
- Indexed, Point,
- Dimension + 1, DimensionCount
+ Indexed, Point, Dimension + 1
>::apply(indexed, centroid);
}
};
@@ -161,8 +163,7 @@ struct centroid_indexed
{
centroid_indexed_calculator
<
- Indexed, Point,
- 0, dimension<Indexed>::type::value
+ Indexed, Point
>::apply(indexed, centroid);
}
};
@@ -183,8 +184,9 @@ inline bool range_ok(Range const& range, Point& centroid)
{
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
throw centroid_exception();
-#endif
+#else
return false;
+#endif
}
else // if (n == 1)
{
@@ -192,7 +194,7 @@ inline bool range_ok(Range const& range, Point& centroid)
geometry::convert(*boost::begin(range), centroid);
return false;
}
- return true;
+ //return true; // unreachable
}
/*!
@@ -207,6 +209,8 @@ struct centroid_range_state
Strategy const& strategy,
typename Strategy::state_type& state)
{
+ boost::ignore_unused(strategy);
+
typedef typename geometry::point_type<Ring const>::type point_type;
typedef typename closeable_view<Ring const, Closure>::type view_type;
@@ -237,7 +241,7 @@ template <closure_selector Closure>
struct centroid_range
{
template<typename Range, typename Point, typename Strategy>
- static inline void apply(Range const& range, Point& centroid,
+ static inline bool apply(Range const& range, Point& centroid,
Strategy const& strategy)
{
if (range_ok(range, centroid))
@@ -248,11 +252,16 @@ struct centroid_range
typename Strategy::state_type state;
centroid_range_state<Closure>::apply(range, transformer,
strategy, state);
- strategy.result(state, centroid);
-
- // translate the result back
- transformer.apply_reverse(centroid);
+
+ if ( strategy.result(state, centroid) )
+ {
+ // translate the result back
+ transformer.apply_reverse(centroid);
+ return true;
+ }
}
+
+ return false;
}
};
@@ -289,8 +298,8 @@ struct centroid_polygon_state
struct centroid_polygon
{
template<typename Polygon, typename Point, typename Strategy>
- static inline void apply(Polygon const& poly, Point& centroid,
- Strategy const& strategy)
+ static inline bool apply(Polygon const& poly, Point& centroid,
+ Strategy const& strategy)
{
if (range_ok(exterior_ring(poly), centroid))
{
@@ -300,11 +309,16 @@ struct centroid_polygon
typename Strategy::state_type state;
centroid_polygon_state::apply(poly, transformer, strategy, state);
- strategy.result(state, centroid);
-
- // translate the result back
- transformer.apply_reverse(centroid);
+
+ if ( strategy.result(state, centroid) )
+ {
+ // translate the result back
+ transformer.apply_reverse(centroid);
+ return true;
+ }
}
+
+ return false;
}
};
@@ -321,6 +335,7 @@ struct centroid_multi_point_state
Strategy const& strategy,
typename Strategy::state_type& state)
{
+ boost::ignore_unused(strategy);
strategy.apply(static_cast<Point const&>(transformer.apply(point)),
state);
}
@@ -339,7 +354,7 @@ template <typename Policy>
struct centroid_multi
{
template <typename Multi, typename Point, typename Strategy>
- static inline void apply(Multi const& multi,
+ static inline bool apply(Multi const& multi,
Point& centroid,
Strategy const& strategy)
{
@@ -364,10 +379,31 @@ struct centroid_multi
{
Policy::apply(*it, transformer, strategy, state);
}
- Strategy::result(state, centroid);
- // translate the result back
- transformer.apply_reverse(centroid);
+ if ( strategy.result(state, centroid) )
+ {
+ // translate the result back
+ transformer.apply_reverse(centroid);
+ return true;
+ }
+
+ return false;
+ }
+};
+
+
+template <typename Algorithm>
+struct centroid_linear_areal
+{
+ template <typename Geometry, typename Point, typename Strategy>
+ static inline void apply(Geometry const& geom,
+ Point& centroid,
+ Strategy const& strategy)
+ {
+ if ( ! Algorithm::apply(geom, centroid, strategy) )
+ {
+ geometry::point_on_border(centroid, geom);
+ }
}
};
@@ -405,32 +441,47 @@ struct centroid<Segment, segment_tag>
template <typename Ring>
struct centroid<Ring, ring_tag>
- : detail::centroid::centroid_range<geometry::closure<Ring>::value>
+ : detail::centroid::centroid_linear_areal
+ <
+ detail::centroid::centroid_range<geometry::closure<Ring>::value>
+ >
{};
template <typename Linestring>
struct centroid<Linestring, linestring_tag>
- : detail::centroid::centroid_range<closed>
+ : detail::centroid::centroid_linear_areal
+ <
+ detail::centroid::centroid_range<closed>
+ >
{};
template <typename Polygon>
struct centroid<Polygon, polygon_tag>
- : detail::centroid::centroid_polygon
+ : detail::centroid::centroid_linear_areal
+ <
+ detail::centroid::centroid_polygon
+ >
{};
template <typename MultiLinestring>
struct centroid<MultiLinestring, multi_linestring_tag>
- : detail::centroid::centroid_multi
+ : detail::centroid::centroid_linear_areal
<
- detail::centroid::centroid_range_state<closed>
+ detail::centroid::centroid_multi
+ <
+ detail::centroid::centroid_range_state<closed>
+ >
>
{};
template <typename MultiPolygon>
struct centroid<MultiPolygon, multi_polygon_tag>
- : detail::centroid::centroid_multi
+ : detail::centroid::centroid_linear_areal
<
- detail::centroid::centroid_polygon_state
+ detail::centroid::centroid_multi
+ <
+ detail::centroid::centroid_polygon_state
+ >
>
{};
diff --git a/boost/geometry/algorithms/clear.hpp b/boost/geometry/algorithms/clear.hpp
index 1850816b1b..22b61e7c30 100644
--- a/boost/geometry/algorithms/clear.hpp
+++ b/boost/geometry/algorithms/clear.hpp
@@ -16,6 +16,7 @@
#include <boost/type_traits/remove_const.hpp>
+
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
diff --git a/boost/geometry/algorithms/convert.hpp b/boost/geometry/algorithms/convert.hpp
index 914ef8f420..5d68854a45 100644
--- a/boost/geometry/algorithms/convert.hpp
+++ b/boost/geometry/algorithms/convert.hpp
@@ -22,8 +22,9 @@
#include <boost/range.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
@@ -276,7 +277,7 @@ template
bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value
&& !boost::is_array<Geometry1>::value
>
-struct convert: not_implemented<Tag1, Tag2, mpl::int_<DimensionCount> >
+struct convert: not_implemented<Tag1, Tag2, boost::mpl::int_<DimensionCount> >
{};
diff --git a/boost/geometry/algorithms/convex_hull.hpp b/boost/geometry/algorithms/convex_hull.hpp
index 09f4c5142d..c6db004f3d 100644
--- a/boost/geometry/algorithms/convex_hull.hpp
+++ b/boost/geometry/algorithms/convex_hull.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
@@ -20,8 +20,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
#include <boost/array.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -35,6 +36,8 @@
#include <boost/geometry/strategies/concepts/convex_hull_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/util/condition.hpp>
+
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
@@ -122,7 +125,7 @@ struct convex_hull<Box, box_tag>
boost::array<typename point_type<Box>::type, 4> range;
geometry::detail::assign_box_corners_oriented<Reverse>(box, range);
geometry::append(out, range);
- if (Close)
+ if (BOOST_GEOMETRY_CONDITION(Close))
{
geometry::append(out, *boost::begin(range));
}
diff --git a/boost/geometry/algorithms/correct.hpp b/boost/geometry/algorithms/correct.hpp
index 3c61b2c0d2..11ed6ecff9 100644
--- a/boost/geometry/algorithms/correct.hpp
+++ b/boost/geometry/algorithms/correct.hpp
@@ -23,8 +23,9 @@
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
diff --git a/boost/geometry/algorithms/covered_by.hpp b/boost/geometry/algorithms/covered_by.hpp
index e50dc338af..eb8e732409 100644
--- a/boost/geometry/algorithms/covered_by.hpp
+++ b/boost/geometry/algorithms/covered_by.hpp
@@ -22,8 +22,8 @@
#include <cstddef>
-#include <boost/variant/static_visitor.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>
diff --git a/boost/geometry/algorithms/crosses.hpp b/boost/geometry/algorithms/crosses.hpp
index 91ed3e0806..cec4931a64 100644
--- a/boost/geometry/algorithms/crosses.hpp
+++ b/boost/geometry/algorithms/crosses.hpp
@@ -21,6 +21,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
#include <cstddef>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/access.hpp>
@@ -141,8 +144,8 @@ namespace resolve_variant
};
- template <BOOST_VARIANT_ENUM_PARAMS(typename A), BOOST_VARIANT_ENUM_PARAMS(typename B)>
- struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(A)>, variant<BOOST_VARIANT_ENUM_PARAMS(B)> >
+ template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+ struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
struct visitor: static_visitor<bool>
{
@@ -162,8 +165,8 @@ namespace resolve_variant
static inline bool
apply(
- const variant<BOOST_VARIANT_ENUM_PARAMS(A)>& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(B)>& geometry2)
+ const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
+ const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2)
{
return apply_visitor(visitor(), geometry1, geometry2);
}
diff --git a/boost/geometry/algorithms/detail/azimuth.hpp b/boost/geometry/algorithms/detail/azimuth.hpp
new file mode 100644
index 0000000000..7810b4814e
--- /dev/null
+++ b/boost/geometry/algorithms/detail/azimuth.hpp
@@ -0,0 +1,158 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>
+
+namespace boost { namespace geometry
+{
+
+// An azimuth is an angle between a vector/segment from origin to a point of
+// interest and a reference vector. Typically north-based azimuth is used.
+// North direction is used as a reference, angle is measured clockwise
+// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS
+// the reference vector is Y axis, angle is measured clockwise.
+// http://en.wikipedia.org/wiki/Azimuth
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace detail_dispatch
+{
+
+template <typename ReturnType, typename Tag>
+struct azimuth
+ : not_implemented<Tag>
+{};
+
+template <typename ReturnType>
+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>
+ ( get_as_radian<0>(p1), get_as_radian<1>(p1),
+ get_as_radian<0>(p2), get_as_radian<1>(p2),
+ spheroid ).azimuth12();
+ }
+
+ template <typename P1, typename P2>
+ static inline ReturnType apply(P1 const& p1, P2 const& p2)
+ {
+ return apply(p1, p2, srs::spheroid<ReturnType>());
+ }
+};
+
+template <typename ReturnType>
+struct azimuth<ReturnType, spherical_equatorial_tag>
+{
+ template <typename P1, typename P2, typename Sphere>
+ static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)
+ {
+ // http://williams.best.vwh.net/avform.htm#Crs
+ ReturnType dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
+ ReturnType cos_p2lat = cos(get_as_radian<1>(p2));
+
+ // An optimization which should kick in often for Boxes
+ //if ( math::equals(dlon, ReturnType(0)) )
+ //if ( get<0>(p1) == get<0>(p2) )
+ //{
+ // return - sin(get_as_radian<1>(p1)) * cos_p2lat);
+ //}
+
+ // "An alternative formula, not requiring the pre-computation of d"
+ // In the formula below dlon is used as "d"
+ return atan2(sin(dlon) * cos_p2lat,
+ cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
+ - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
+ }
+
+ template <typename P1, typename P2>
+ static inline ReturnType apply(P1 const& p1, P2 const& p2)
+ {
+ return apply(p1, p2, 0); // dummy model
+ }
+};
+
+template <typename ReturnType>
+struct azimuth<ReturnType, spherical_polar_tag>
+ : azimuth<ReturnType, spherical_equatorial_tag>
+{};
+
+template <typename ReturnType>
+struct azimuth<ReturnType, cartesian_tag>
+{
+ template <typename P1, typename P2, typename Plane>
+ static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/)
+ {
+ ReturnType x = get<0>(p2) - get<0>(p1);
+ ReturnType y = get<1>(p2) - get<1>(p1);
+
+ // NOTE: azimuth 0 is at Y axis, increasing right
+ // as in spherical/geographic where 0 is at North axis
+ return atan2(x, y);
+ }
+
+ template <typename P1, typename P2>
+ static inline ReturnType apply(P1 const& p1, P2 const& p2)
+ {
+ return apply(p1, p2, 0); // dummy model
+ }
+};
+
+} // detail_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+/// Calculate azimuth between two points.
+/// The result is in radians.
+template <typename ReturnType, typename Point1, typename Point2>
+inline ReturnType azimuth(Point1 const& p1, Point2 const& p2)
+{
+ return detail_dispatch::azimuth
+ <
+ ReturnType,
+ typename geometry::cs_tag<Point1>::type
+ >::apply(p1, p2);
+}
+
+/// Calculate azimuth between two points.
+/// The result is in radians.
+template <typename ReturnType, typename Point1, typename Point2, typename Model>
+inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model)
+{
+ return detail_dispatch::azimuth
+ <
+ ReturnType,
+ typename geometry::cs_tag<Point1>::type
+ >::apply(p1, p2, model);
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
index c959ee849b..127e4c3fb2 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -12,6 +12,7 @@
#include <cstddef>
#include <iterator>
+#include <boost/core/ignore_unused.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range.hpp>
@@ -20,6 +21,7 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/buffer.hpp>
@@ -28,6 +30,7 @@
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>
+#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/simplify.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
@@ -144,15 +147,25 @@ struct buffer_range
intersection_point);
}
+
switch(join)
{
case strategy::buffer::join_continue :
// No join, we get two consecutive sides
- return;
+ break;
case strategy::buffer::join_concave :
- collection.add_piece(strategy::buffer::buffered_concave,
- previous_input, prev_perp2, perp1);
- return;
+ {
+ std::vector<output_point_type> range_out;
+ range_out.push_back(prev_perp2);
+ range_out.push_back(previous_input);
+ collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
+
+ range_out.clear();
+ range_out.push_back(previous_input);
+ range_out.push_back(perp1);
+ collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
+ }
+ break;
case strategy::buffer::join_spike :
{
// For linestrings, only add spike at one side to avoid
@@ -160,22 +173,24 @@ struct buffer_range
std::vector<output_point_type> range_out;
end_strategy.apply(penultimate_input, prev_perp2, previous_input, perp1, side, distance, range_out);
collection.add_endcap(end_strategy, range_out, previous_input);
+ collection.set_current_ring_concave();
}
- return;
+ break;
case strategy::buffer::join_convex :
- break; // All code below handles this
- }
-
- // The corner is convex, we create a join
- // TODO (future) - avoid a separate vector, add the piece directly
- std::vector<output_point_type> range_out;
- if (join_strategy.apply(intersection_point,
- previous_input, prev_perp2, perp1,
- distance.apply(previous_input, input, side),
- range_out))
- {
- collection.add_piece(strategy::buffer::buffered_join,
- previous_input, range_out);
+ {
+ // The corner is convex, we create a join
+ // TODO (future) - avoid a separate vector, add the piece directly
+ std::vector<output_point_type> range_out;
+ if (join_strategy.apply(intersection_point,
+ previous_input, prev_perp2, perp1,
+ distance.apply(previous_input, input, side),
+ range_out))
+ {
+ collection.add_piece(strategy::buffer::buffered_join,
+ previous_input, range_out);
+ }
+ }
+ break;
}
}
@@ -225,18 +240,13 @@ struct buffer_range
output_point_type& last_p1,
output_point_type& last_p2)
{
+ boost::ignore_unused(side_strategy);
+
typedef typename std::iterator_traits
<
Iterator
>::value_type point_type;
- typedef typename robust_point_type
- <
- point_type,
- RobustPolicy
- >::type robust_point_type;
-
- robust_point_type previous_robust_input;
point_type second_point, penultimate_point, ultimate_point; // last two points from begin/end
/*
@@ -261,57 +271,50 @@ struct buffer_range
Iterator it = begin;
- geometry::recalculate(previous_robust_input, *begin, robust_policy);
-
std::vector<output_point_type> generated_side;
generated_side.reserve(2);
for (Iterator prev = it++; it != end; ++it)
{
- robust_point_type robust_input;
- geometry::recalculate(robust_input, *it, robust_policy);
- // Check on equality - however, if input is simplified, this is
- // unlikely (though possible by rescaling or for degenerated pointlike polygons)
- if (! detail::equals::equals_point_point(previous_robust_input, robust_input))
- {
- generated_side.clear();
- side_strategy.apply(*prev, *it, side,
- distance_strategy, generated_side);
+ generated_side.clear();
+ side_strategy.apply(*prev, *it, side,
+ distance_strategy, generated_side);
- if (generated_side.empty())
- {
- break;
- }
+ if (generated_side.empty())
+ {
+ // Because input is simplified, this is improbable,
+ // but it can happen for degenerate geometries
+ // Further handling of this side is skipped
+ continue;
+ }
- result = true;
+ result = true;
- if (! first)
- {
- add_join(collection,
- penultimate_point,
- *prev, last_p1, last_p2,
- *it, generated_side.front(), generated_side.back(),
- side,
- distance_strategy, join_strategy, end_strategy,
- robust_policy);
- }
+ if (! first)
+ {
+ add_join(collection,
+ penultimate_point,
+ *prev, last_p1, last_p2,
+ *it, generated_side.front(), generated_side.back(),
+ side,
+ distance_strategy, join_strategy, end_strategy,
+ robust_policy);
+ }
- collection.add_side_piece(*prev, *it, generated_side, first);
+ collection.add_side_piece(*prev, *it, generated_side, first);
- penultimate_point = *prev;
- ultimate_point = *it;
- last_p1 = generated_side.front();
- last_p2 = generated_side.back();
- prev = it;
- if (first)
- {
- first = false;
- second_point = *it;
- first_p1 = generated_side.front();
- first_p2 = generated_side.back();
- }
+ penultimate_point = *prev;
+ ultimate_point = *it;
+ last_p1 = generated_side.front();
+ last_p2 = generated_side.back();
+ prev = it;
+ if (first)
+ {
+ first = false;
+ second_point = *it;
+ first_p1 = generated_side.front();
+ first_p2 = generated_side.back();
}
- previous_robust_input = robust_input;
}
return result;
}
@@ -775,7 +778,7 @@ public:
distance, side_strategy,
join_strategy, end_strategy, point_strategy,
robust_policy);
- collection.finish_ring();
+ collection.finish_ring(false, geometry::num_interior_rings(polygon) > 0u);
}
apply_interior_rings(interior_rings(polygon),
@@ -839,6 +842,8 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
VisitPiecesPolicy& visit_pieces_policy
)
{
+ boost::ignore_unused(visit_pieces_policy);
+
typedef detail::buffer::buffered_piece_collection
<
typename geometry::ring_type<GeometryOutput>::type,
@@ -852,6 +857,11 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
typename tag_cast<typename tag<GeometryInput>::type, areal_tag>::type,
areal_tag
>::type::value;
+ bool const linear = boost::is_same
+ <
+ typename tag_cast<typename tag<GeometryInput>::type, linear_tag>::type,
+ linear_tag
+ >::type::value;
dispatch::buffer_inserter
<
@@ -868,9 +878,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
robust_policy);
collection.get_turns();
- if (areal)
+ collection.classify_turns(linear);
+ if (BOOST_GEOMETRY_CONDITION(areal))
{
- collection.check_remaining_points(distance_strategy.factor());
+ collection.check_remaining_points(distance_strategy);
}
// Visit the piece collection. This does nothing (by default), but
@@ -889,7 +900,8 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
// - the output is counter clockwise
// and avoid reversing twice
bool reverse = distance_strategy.negative() && areal;
- if (geometry::point_order<GeometryOutput>::value == counterclockwise)
+ if (BOOST_GEOMETRY_CONDITION(
+ geometry::point_order<GeometryOutput>::value == counterclockwise))
{
reverse = ! reverse;
}
@@ -898,6 +910,11 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.reverse();
}
+ if (distance_strategy.negative() && areal)
+ {
+ collection.discard_nonintersecting_deflated_rings();
+ }
+
collection.template assign<GeometryOutput>(out);
// Visit collection again
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
index 6a2e6b32c5..c5bb8acc05 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
@@ -35,7 +35,7 @@ namespace detail { namespace buffer
enum intersection_location_type
{
- location_ok, inside_buffer, inside_original
+ location_ok, inside_buffer, location_discard
};
class backtrack_for_buffer
@@ -120,10 +120,14 @@ struct buffer_turn_info
return robust_point;
}
-
intersection_location_type location;
int 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
+
int count_on_offsetted;
int count_on_helper;
int count_within_near_offsetted;
@@ -138,6 +142,9 @@ struct buffer_turn_info
: turn_index(-1)
, location(location_ok)
, count_within(0)
+ , within_original(false)
+ , count_on_original_boundary(0)
+ , count_in_original(0)
, count_on_offsetted(0)
, count_on_helper(0)
, count_within_near_offsetted(0)
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index 558a61fcb4..a501e3f197 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -12,8 +12,9 @@
#include <algorithm>
#include <cstddef>
#include <set>
-#include <boost/range.hpp>
+#include <boost/core/ignore_unused.hpp>
+#include <boost/range.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -24,13 +25,14 @@
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/geometries/ring.hpp>
-#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffered_ring.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
#include <boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp>
#include <boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp>
+#include <boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>
#include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
@@ -41,6 +43,8 @@
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/occupation_info.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
+#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
#include <boost/geometry/util/range.hpp>
@@ -89,7 +93,7 @@ enum segment_relation_code
* form together the offsetted ring (marked with o below)
* The 8 pieces are part of the piece collection and use for inside-checks
* The inner parts form (using 1 or 2 points per piece, often co-located)
- * form together the robust_ring (marked with r below)
+ * form together the robust_polygons (marked with r below)
* The remaining piece-segments are helper-segments (marked with h)
*
* ooooooooooooooooo
@@ -120,7 +124,7 @@ struct buffered_piece_collection
// Robust ring/polygon type, always clockwise
typedef geometry::model::ring<robust_point_type> robust_ring_type;
- typedef geometry::model::polygon<robust_point_type> robust_polygon_type;
+ typedef geometry::model::box<robust_point_type> robust_box_type;
typedef typename strategy::side::services::default_strategy
<
@@ -164,6 +168,9 @@ struct buffered_piece_collection
struct piece
{
+ typedef robust_ring_type piece_robust_ring_type;
+ typedef geometry::section<robust_box_type, 1> section_type;
+
strategy::buffer::piece_type type;
int index;
@@ -181,18 +188,58 @@ struct buffered_piece_collection
#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 segment, 3 points for join - 0 points for flat-end
+ std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
#endif
+ 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;
- geometry::model::box<robust_point_type> robust_envelope;
+ robust_box_type robust_envelope;
+ 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
};
+ struct robust_original
+ {
+ typedef robust_ring_type original_robust_ring_type;
+ typedef geometry::sections<robust_box_type, 1> sections_type;
+
+ inline robust_original()
+ : m_is_interior(false)
+ , m_has_interiors(true)
+ {}
+
+ inline robust_original(robust_ring_type const& ring,
+ bool is_interior, bool has_interiors)
+ : m_ring(ring)
+ , m_is_interior(is_interior)
+ , m_has_interiors(has_interiors)
+ {
+ geometry::envelope(m_ring, m_box);
+
+ // create monotonic sections in y-dimension
+ typedef boost::mpl::vector_c<std::size_t, 1> dimensions;
+ geometry::sectionalize<false, dimensions>(m_ring,
+ detail::no_rescale_policy(), m_sections);
+ }
+
+ robust_ring_type m_ring;
+ robust_box_type m_box;
+ sections_type m_sections;
+
+ bool m_is_interior;
+ bool m_has_interiors;
+ };
+
typedef std::vector<piece> piece_vector_type;
piece_vector_type m_pieces;
@@ -200,11 +247,17 @@ struct buffered_piece_collection
int m_first_piece_index;
buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index
- buffered_ring_collection<robust_polygon_type> robust_polygons; // robust representation of the original(s)
+ std::vector<robust_original> robust_originals; // robust representation of the original(s)
robust_ring_type current_robust_ring;
buffered_ring_collection<Ring> traversed_rings;
segment_identifier current_segment_id;
+ // Specificly for offsetted rings around points
+ // but also for large joins with many points
+ typedef geometry::sections<robust_box_type, 2> sections_type;
+ sections_type monotonic_sections;
+
+
RobustPolicy const& m_robust_policy;
struct redundant_turn
@@ -378,7 +431,7 @@ struct buffered_piece_collection
}
}
- inline void classify_turns()
+ inline void classify_turns(bool linear)
{
for (typename boost::range_iterator<turn_vector_type>::type it =
boost::begin(m_turns); it != boost::end(m_turns); ++it)
@@ -387,6 +440,10 @@ struct buffered_piece_collection
{
it->location = inside_buffer;
}
+ if (it->count_on_original_boundary > 0 && ! linear)
+ {
+ it->location = inside_buffer;
+ }
if (it->count_within_near_offsetted > 0)
{
// Within can have in rare cases a rounding issue. We don't discard this
@@ -394,31 +451,40 @@ struct buffered_piece_collection
// will never start a new ring from this type of points.
it->selectable_start = false;
}
-
}
}
- inline void check_remaining_points(int factor)
+ template <typename DistanceStrategy>
+ inline void check_remaining_points(DistanceStrategy const& distance_strategy)
{
- // TODO: use partition
+ // Check if a turn is inside any of the originals
+
+ turn_in_original_visitor<turn_vector_type> visitor(m_turns);
+ geometry::partition
+ <
+ robust_box_type,
+ turn_get_box, turn_in_original_ovelaps_box,
+ original_get_box, original_ovelaps_box,
+ include_turn_policy, detail::partition::include_all_policy
+ >::apply(m_turns, robust_originals, visitor);
+
+ bool const deflate = distance_strategy.negative();
for (typename boost::range_iterator<turn_vector_type>::type it =
boost::begin(m_turns); it != boost::end(m_turns); ++it)
{
- if (it->location == location_ok)
+ buffer_turn_info_type& turn = *it;
+ if (turn.location == location_ok)
{
- int code = -1;
- for (std::size_t i = 0; i < robust_polygons.size(); i++)
+ if (deflate && turn.count_in_original <= 0)
{
- if (geometry::covered_by(it->robust_point, robust_polygons[i]))
- {
- code = 1;
- break;
- }
+ // For deflate: it is not in original, discard
+ turn.location = location_discard;
}
- if (code * factor == 1)
+ else if (! deflate && turn.count_in_original > 0)
{
- it->location = inside_original;
+ // For inflate: it is in original, discard
+ turn.location = location_discard;
}
}
}
@@ -474,6 +540,7 @@ struct buffered_piece_collection
// Take into account for the box (intersection points should fall inside,
// but in theory they can be one off because of rounding
geometry::expand(pc.robust_envelope, it->robust_point);
+ geometry::expand(pc.robust_offsetted_envelope, it->robust_point);
}
}
@@ -502,9 +569,10 @@ struct buffered_piece_collection
{
int const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
BOOST_ASSERT
- (
- index_in_vector > 0 && index_in_vector < pc.offsetted_count
- );
+ (
+ index_in_vector > 0
+ && index_in_vector < pc.offsetted_count
+ );
pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point);
pc.offsetted_count++;
@@ -517,25 +585,132 @@ struct buffered_piece_collection
BOOST_ASSERT(assert_indices_in_robust_rings());
}
+ template <std::size_t Dimension>
+ static inline void determine_monotonicity(piece& pc,
+ robust_point_type const& current,
+ robust_point_type const& next)
+ {
+ if (geometry::get<Dimension>(current) >= geometry::get<Dimension>(next))
+ {
+ pc.is_monotonic_increasing[Dimension] = false;
+ }
+ if (geometry::get<Dimension>(current) <= geometry::get<Dimension>(next))
+ {
+ pc.is_monotonic_decreasing[Dimension] = false;
+ }
+ }
+
+ static inline void determine_properties(piece& pc)
+ {
+ pc.is_monotonic_increasing[0] = true;
+ pc.is_monotonic_increasing[1] = true;
+ pc.is_monotonic_decreasing[0] = true;
+ pc.is_monotonic_decreasing[1] = true;
+
+ if (pc.offsetted_count < 2)
+ {
+ return;
+ }
+
+ 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++)
+ {
+ determine_monotonicity<0>(pc, *current, *next);
+ determine_monotonicity<1>(pc, *current, *next);
+ current = next;
+ ++next;
+ }
+
+ }
+
+ void determine_properties()
+ {
+ for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
+ it != boost::end(m_pieces);
+ ++it)
+ {
+ determine_properties(*it);
+ }
+ }
+
+ inline void reverse_negative_robust_rings()
+ {
+ for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
+ it != boost::end(m_pieces);
+ ++it)
+ {
+ piece& pc = *it;
+ if (geometry::area(pc.robust_ring) < 0)
+ {
+ // Rings can be ccw:
+ // - in a concave piece
+ // - in a line-buffer with a negative buffer-distance
+ std::reverse(pc.robust_ring.begin(), pc.robust_ring.end());
+ }
+ }
+ }
+
+ inline void prepare_buffered_point_piece(piece& pc)
+ {
+ // create monotonic sections in y-dimension
+ typedef boost::mpl::vector_c<std::size_t, 1> dimensions;
+ geometry::sectionalize<false, dimensions>(pc.robust_ring,
+ detail::no_rescale_policy(), pc.sections);
+
+ // TODO (next phase) determine min/max radius
+ }
+
+ inline void prepare_buffered_point_pieces()
+ {
+ for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
+ it != boost::end(m_pieces);
+ ++it)
+ {
+ if (it->type == geometry::strategy::buffer::buffered_point)
+ {
+ prepare_buffered_point_piece(*it);
+ }
+ }
+ }
+
inline void get_turns()
{
+ for(typename boost::range_iterator<sections_type>::type it
+ = boost::begin(monotonic_sections);
+ it != boost::end(monotonic_sections);
+ ++it)
+ {
+ enlarge_box(it->bounding_box, 1);
+ }
+
{
// Calculate the turns
piece_turn_visitor
<
+ piece_vector_type,
buffered_ring_collection<buffered_ring<Ring> >,
turn_vector_type,
RobustPolicy
- > visitor(offsetted_rings, m_turns, m_robust_policy);
+ > visitor(m_pieces, offsetted_rings, m_turns, m_robust_policy);
geometry::partition
<
- model::box<robust_point_type>, piece_get_box, piece_ovelaps_box
- >::apply(m_pieces, visitor);
+ robust_box_type,
+ detail::section::get_section_box,
+ detail::section::overlaps_section_box
+ >::apply(monotonic_sections, visitor);
}
insert_rescaled_piece_turns();
+ reverse_negative_robust_rings();
+
+ determine_properties();
+
+ prepare_buffered_point_pieces();
+
{
// Check if it is inside any of the pieces
turn_in_piece_visitor
@@ -545,16 +720,12 @@ struct buffered_piece_collection
geometry::partition
<
- model::box<robust_point_type>,
+ robust_box_type,
turn_get_box, turn_ovelaps_box,
piece_get_box, piece_ovelaps_box
>::apply(m_turns, m_pieces, visitor);
}
-
- classify_turns();
-
- //get_occupation();
}
inline void start_new_ring()
@@ -571,7 +742,38 @@ struct buffered_piece_collection
m_first_piece_index = boost::size(m_pieces);
}
- inline void finish_ring(bool is_interior = false)
+ inline void update_closing_point()
+ {
+ BOOST_ASSERT(! offsetted_rings.empty());
+ buffered_ring<Ring>& added = offsetted_rings.back();
+ if (! boost::empty(added))
+ {
+ range::back(added) = range::front(added);
+ }
+ }
+
+ inline void update_last_point(point_type const& p,
+ buffered_ring<Ring>& ring)
+ {
+ // For the first point of a new piece, and there were already
+ // points in the offsetted ring, for some piece types the first point
+ // is a duplicate of the last point of the previous piece.
+
+ // TODO: disable that, that point should not be added
+
+ // 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);
+ if (! ring.empty()
+ && current_segment_id.segment_index
+ == m_pieces.back().first_seg_id.segment_index)
+ {
+ ring.back() = p;
+ }
+ }
+
+ inline void finish_ring(bool is_interior = false, bool has_interiors = false)
{
if (m_first_piece_index == -1)
{
@@ -588,41 +790,50 @@ struct buffered_piece_collection
}
m_first_piece_index = -1;
- if (!current_robust_ring.empty())
+ update_closing_point();
+
+ if (! current_robust_ring.empty())
{
- BOOST_ASSERT(geometry::equals(current_robust_ring.front(), current_robust_ring.back()));
+ BOOST_ASSERT
+ (
+ geometry::equals(current_robust_ring.front(),
+ current_robust_ring.back())
+ );
- if (is_interior)
- {
- if (!robust_polygons.empty())
- {
- robust_polygons.back().inners().push_back(current_robust_ring);
- }
- }
- else
- {
- robust_polygons.resize(robust_polygons.size() + 1);
- robust_polygons.back().outer() = current_robust_ring;
- }
+ robust_originals.push_back(
+ robust_original(current_robust_ring,
+ is_interior, has_interiors));
}
}
+ inline void set_current_ring_concave()
+ {
+ BOOST_ASSERT(boost::size(offsetted_rings) > 0);
+ offsetted_rings.back().has_concave = true;
+ }
+
inline int add_point(point_type const& p)
{
- BOOST_ASSERT
- (
- boost::size(offsetted_rings) > 0
- );
+ BOOST_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++;
- offsetted_rings.back().push_back(p);
- return offsetted_rings.back().size();
+ current_ring.push_back(p);
+ return current_ring.size();
}
//-------------------------------------------------------------------------
- inline piece& create_piece(strategy::buffer::piece_type type, bool decrease_segment_index_by_one)
+ inline piece& create_piece(strategy::buffer::piece_type type,
+ bool decrease_segment_index_by_one)
{
+ if (type == strategy::buffer::buffered_concave)
+ {
+ offsetted_rings.back().has_concave = true;
+ }
+
piece pc;
pc.type = type;
pc.index = boost::size(m_pieces);
@@ -634,6 +845,7 @@ struct buffered_piece_collection
std::size_t const n = boost::size(offsetted_rings.back());
pc.first_seg_id.segment_index = decrease_segment_index_by_one ? n - 1 : n;
+ pc.last_segment_index = pc.first_seg_id.segment_index;
m_pieces.push_back(pc);
return m_pieces.back();
@@ -641,6 +853,18 @@ struct buffered_piece_collection
inline void init_rescale_piece(piece& pc, std::size_t helper_points_size)
{
+ if (pc.first_seg_id.segment_index < 0)
+ {
+ // This indicates an error situation: an earlier piece was empty
+ // It currently does not happen
+ // std::cout << "EMPTY " << pc.type << " " << pc.index << " " << pc.first_seg_id.multi_index << std::endl;
+ pc.offsetted_count = 0;
+ return;
+ }
+
+ BOOST_ASSERT(pc.first_seg_id.multi_index >= 0);
+ BOOST_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);
@@ -674,16 +898,65 @@ struct buffered_piece_collection
return rob_point;
}
+ // TODO: this is shared with sectionalize, move to somewhere else (assign?)
+ template <typename Box, typename Value>
+ inline void enlarge_box(Box& box, Value value)
+ {
+ geometry::set<0, 0>(box, geometry::get<0, 0>(box) - value);
+ geometry::set<0, 1>(box, geometry::get<0, 1>(box) - value);
+ geometry::set<1, 0>(box, geometry::get<1, 0>(box) + value);
+ geometry::set<1, 1>(box, geometry::get<1, 1>(box) + value);
+ }
+
inline void calculate_robust_envelope(piece& pc)
{
+ if (pc.offsetted_count == 0)
+ {
+ return;
+ }
+
geometry::detail::envelope::envelope_range::apply(pc.robust_ring,
pc.robust_envelope);
+
+ geometry::assign_inverse(pc.robust_offsetted_envelope);
+ for (int i = 0; i < pc.offsetted_count; i++)
+ {
+ geometry::expand(pc.robust_offsetted_envelope, pc.robust_ring[i]);
+ }
+
+ // Take roundings into account, enlarge boxes with 1 integer
+ enlarge_box(pc.robust_envelope, 1);
+ enlarge_box(pc.robust_offsetted_envelope, 1);
+ }
+
+ inline void sectionalize(piece& pc)
+ {
+
+ buffered_ring<Ring> const& ring = offsetted_rings.back();
+
+ typedef geometry::detail::sectionalize::sectionalize_part
+ <
+ point_type,
+ boost::mpl::vector_c<std::size_t, 0, 1> // x,y dimension
+ > sectionalizer;
+
+ // Create a ring-identifier. The source-index is the piece index
+ // The multi_index is as in this collection (the ring), but not used here
+ // The ring_index is not used
+ ring_identifier ring_id(pc.index, pc.first_seg_id.multi_index, -1);
+
+ sectionalizer::apply(monotonic_sections,
+ boost::begin(ring) + pc.first_seg_id.segment_index,
+ boost::begin(ring) + pc.last_segment_index,
+ m_robust_policy,
+ ring_id, 10);
}
inline void finish_piece(piece& pc)
{
init_rescale_piece(pc, 0u);
calculate_robust_envelope(pc);
+ sectionalize(pc);
}
inline void finish_piece(piece& pc,
@@ -692,10 +965,16 @@ struct buffered_piece_collection
const point_type& point3)
{
init_rescale_piece(pc, 3u);
+ if (pc.offsetted_count == 0)
+ {
+ return;
+ }
+
add_helper_point(pc, point1);
robust_point_type mid_point = add_helper_point(pc, point2);
add_helper_point(pc, point3);
calculate_robust_envelope(pc);
+ sectionalize(pc);
current_robust_ring.push_back(mid_point);
}
@@ -711,6 +990,7 @@ struct buffered_piece_collection
robust_point_type mid_point2 = add_helper_point(pc, point2);
robust_point_type mid_point1 = add_helper_point(pc, point3);
add_helper_point(pc, point4);
+ sectionalize(pc);
calculate_robust_envelope(pc);
// Add mid-points in other order to current helper_ring
@@ -730,10 +1010,7 @@ struct buffered_piece_collection
template <typename Range>
inline void add_range_to_piece(piece& pc, Range const& range, bool add_front)
{
- if (boost::size(range) == 0u)
- {
- return;
- }
+ BOOST_ASSERT(boost::size(range) != 0u);
typename Range::const_iterator it = boost::begin(range);
@@ -753,10 +1030,15 @@ struct buffered_piece_collection
template <typename Range>
- inline void add_piece(strategy::buffer::piece_type type, Range const& range, bool decrease_segment_index_by_one)
+ inline void add_piece(strategy::buffer::piece_type type, Range const& range,
+ bool decrease_segment_index_by_one)
{
piece& pc = create_piece(type, decrease_segment_index_by_one);
- add_range_to_piece(pc, range, offsetted_rings.back().empty());
+
+ if (boost::size(range) > 0u)
+ {
+ add_range_to_piece(pc, range, offsetted_rings.back().empty());
+ }
finish_piece(pc);
}
@@ -772,13 +1054,14 @@ struct buffered_piece_collection
}
template <typename Range>
- inline void add_piece(strategy::buffer::piece_type type, point_type const& p, Range const& range)
+ inline void add_piece(strategy::buffer::piece_type type,
+ point_type const& p, Range const& range)
{
piece& pc = create_piece(type, true);
- add_range_to_piece(pc, range, offsetted_rings.back().empty());
- if (boost::size(range) > 0)
+ if (boost::size(range) > 0u)
{
+ add_range_to_piece(pc, range, offsetted_rings.back().empty());
finish_piece(pc, range.back(), p, range.front());
}
else
@@ -788,8 +1071,11 @@ struct buffered_piece_collection
}
template <typename EndcapStrategy, typename Range>
- inline void add_endcap(EndcapStrategy const& strategy, Range const& range, point_type const& end_point)
+ inline void add_endcap(EndcapStrategy const& strategy, Range const& range,
+ point_type const& end_point)
{
+ boost::ignore_unused(strategy);
+
if (range.empty())
{
return;
@@ -842,6 +1128,80 @@ struct buffered_piece_collection
}
}
+ inline bool point_coveredby_original(point_type const& point)
+ {
+ robust_point_type any_point;
+ geometry::recalculate(any_point, point, m_robust_policy);
+
+ int count_in_original = 0;
+
+ // Check of the robust point of this outputted ring is in
+ // any of the robust original rings
+ // This can go quadratic if the input has many rings, and there
+ // are many untouched deflated rings around
+ for (typename std::vector<robust_original>::const_iterator it
+ = robust_originals.begin();
+ it != robust_originals.end();
+ ++it)
+ {
+ robust_original const& original = *it;
+ if (detail::disjoint::disjoint_point_box(any_point,
+ original.m_box))
+ {
+ continue;
+ }
+
+ int const geometry_code
+ = detail::within::point_in_geometry(any_point,
+ original.m_ring);
+
+ if (geometry_code == -1)
+ {
+ // Outside, continue
+ continue;
+ }
+
+ // Apply for possibly nested interior rings
+ if (original.m_is_interior)
+ {
+ count_in_original--;
+ }
+ else if (original.m_has_interiors)
+ {
+ count_in_original++;
+ }
+ else
+ {
+ // Exterior ring without interior rings
+ return true;
+ }
+ }
+ return count_in_original > 0;
+ }
+
+ // For a deflate, all rings around inner rings which are untouched
+ // (no intersections/turns) and which are OUTSIDE the original should
+ // be discarded
+ inline void discard_nonintersecting_deflated_rings()
+ {
+ for(typename buffered_ring_collection<buffered_ring<Ring> >::iterator it
+ = boost::begin(offsetted_rings);
+ it != boost::end(offsetted_rings);
+ ++it)
+ {
+ buffered_ring<Ring>& ring = *it;
+ if (! ring.has_intersections()
+ && boost::size(ring) > 0u
+ && geometry::area(ring) < 0)
+ {
+ if (! point_coveredby_original(geometry::range::front(ring)))
+ {
+ ring.is_untouched_outside_original = true;
+ }
+ }
+ }
+ }
+
inline void block_turns()
{
// To fix left-turn issues like #rt_u13
@@ -876,7 +1236,8 @@ struct buffered_piece_collection
typedef detail::overlay::traverse
<
false, false,
- buffered_ring_collection<buffered_ring<Ring> >, buffered_ring_collection<buffered_ring<Ring > >,
+ buffered_ring_collection<buffered_ring<Ring> >,
+ buffered_ring_collection<buffered_ring<Ring > >,
backtrack_for_buffer
> traverser;
@@ -914,16 +1275,20 @@ struct buffered_piece_collection
std::map<ring_identifier, properties> selected;
- // Select all rings which do not have any self-intersection (other ones should be traversed)
+ // Select all rings which do not have any self-intersection
+ // Inner rings, for deflate, which do not have intersections, and
+ // which are outside originals, are skipped
+ // (other ones should be traversed)
int index = 0;
for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
it != boost::end(offsetted_rings);
++it, ++index)
{
- if (! it->has_intersections())
+ if (! it->has_intersections()
+ && ! it->is_untouched_outside_original)
{
ring_identifier id(0, index, -1);
- selected[id] = properties(*it, true);
+ selected[id] = properties(*it);
}
}
@@ -935,7 +1300,7 @@ struct buffered_piece_collection
++it, ++index)
{
ring_identifier id(2, index, -1);
- selected[id] = properties(*it, true);
+ selected[id] = properties(*it);
}
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 03ec598c90..9ea8bc1e85 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp
@@ -43,12 +43,16 @@ struct buffered_ring_collection_tag : polygonal_tag, multi_tag
template <typename Ring>
struct buffered_ring : public Ring
{
+ bool has_concave;
bool has_accepted_intersections;
bool has_discarded_intersections;
+ bool is_untouched_outside_original;
inline buffered_ring()
- : has_accepted_intersections(false)
+ : has_concave(false)
+ , has_accepted_intersections(false)
, has_discarded_intersections(false)
+ , is_untouched_outside_original(false)
{}
inline bool discarded() const
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
index 395921ccaa..6a3daa282e 100644
--- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -16,6 +16,7 @@
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#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>
namespace boost { namespace geometry
@@ -27,32 +28,16 @@ namespace detail { namespace buffer
{
-struct piece_get_box
-{
- template <typename Box, typename Piece>
- static inline void apply(Box& total, Piece const& piece)
- {
- geometry::expand(total, piece.robust_envelope);
- }
-};
-
-struct piece_ovelaps_box
-{
- template <typename Box, typename Piece>
- static inline bool apply(Box const& box, Piece const& piece)
- {
- return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);
- }
-};
-
template
<
+ typename Pieces,
typename Rings,
typename Turns,
typename RobustPolicy
>
class piece_turn_visitor
{
+ Pieces const& m_pieces;
Rings const& m_rings;
Turns& m_turns;
RobustPolicy const& m_robust_policy;
@@ -69,6 +54,17 @@ class piece_turn_visitor
|| piece1.index == piece2.right_index;
}
+ template <typename Piece>
+ inline bool is_on_same_convex_ring(Piece const& piece1, Piece const& piece2) const
+ {
+ if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
+ {
+ return false;
+ }
+
+ return ! m_rings[piece1.first_seg_id.multi_index].has_concave;
+ }
+
template <typename Range, typename Iterator>
inline void move_to_next_point(Range const& range, Iterator& next) const
{
@@ -93,46 +89,110 @@ class piece_turn_visitor
return result;
}
- template <typename Piece>
- inline void calculate_turns(Piece const& piece1, Piece const& piece2)
+ 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)
+ {
+ for(; it_begin != it_beyond
+ && it_begin + 1 != it_beyond
+ && detail::section::preceding<Dimension>(dir, *(it_begin + 1),
+ other_bounding_box, m_robust_policy);
+ ++it_begin, index++)
+ {}
+ }
+
+ template <std::size_t Dimension, typename Iterator, typename Box>
+ inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
+ int dir, Box const& other_bounding_box)
+ {
+ while (it_beyond != it_begin
+ && it_beyond - 1 != it_begin
+ && it_beyond - 2 != it_begin)
+ {
+ if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
+ other_bounding_box, m_robust_policy))
+ {
+ --it_beyond;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+
+ template <typename Piece, typename Section>
+ inline void calculate_turns(Piece const& piece1, Piece const& piece2,
+ Section const& section1, Section const& section2)
{
typedef typename boost::range_value<Rings const>::type ring_type;
typedef typename boost::range_value<Turns const>::type turn_type;
typedef typename boost::range_iterator<ring_type const>::type iterator;
- segment_identifier seg_id1 = piece1.first_seg_id;
- segment_identifier seg_id2 = piece2.first_seg_id;
-
- if (seg_id1.segment_index < 0 || seg_id2.segment_index < 0)
+ int const piece1_first_index = piece1.first_seg_id.segment_index;
+ int const piece2_first_index = piece2.first_seg_id.segment_index;
+ if (piece1_first_index < 0 || piece2_first_index < 0)
{
return;
}
- ring_type const& ring1 = m_rings[seg_id1.multi_index];
- iterator it1_first = boost::begin(ring1) + seg_id1.segment_index;
- iterator it1_last = boost::begin(ring1) + piece1.last_segment_index;
-
- ring_type const& ring2 = m_rings[seg_id2.multi_index];
- iterator it2_first = boost::begin(ring2) + seg_id2.segment_index;
- iterator it2_last = boost::begin(ring2) + piece2.last_segment_index;
+ // 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;
+
+ // 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;
+
+ // get geometry and iterators over these sections
+ ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
+ iterator it1_first = boost::begin(ring1) + sec1_first_index;
+ iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
+
+ ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index];
+ iterator it2_first = boost::begin(ring2) + sec2_first_index;
+ 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;
+ move_begin_iterator<0>(it1_first, it1_beyond, index1,
+ section1.directions[0], section2.bounding_box);
+ move_end_iterator<0>(it1_first, it1_beyond,
+ section1.directions[0], section2.bounding_box);
+ move_begin_iterator<1>(it1_first, it1_beyond, index1,
+ section1.directions[1], section2.bounding_box);
+ move_end_iterator<1>(it1_first, it1_beyond,
+ section1.directions[1], section2.bounding_box);
+
+ int 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,
+ section2.directions[0], section1.bounding_box);
+ move_begin_iterator<1>(it2_first, it2_beyond, index2,
+ section2.directions[1], section1.bounding_box);
+ move_end_iterator<1>(it2_first, it2_beyond,
+ section2.directions[1], section1.bounding_box);
turn_type the_model;
the_model.operations[0].piece_index = piece1.index;
the_model.operations[0].seg_id = piece1.first_seg_id;
+ the_model.operations[0].seg_id.segment_index = index1; // override
iterator it1 = it1_first;
for (iterator prev1 = it1++;
- it1 != it1_last;
+ it1 != it1_beyond;
prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
{
the_model.operations[1].piece_index = piece2.index;
the_model.operations[1].seg_id = piece2.first_seg_id;
+ the_model.operations[1].seg_id.segment_index = index2; // override
iterator next1 = next_point(ring1, it1);
iterator it2 = it2_first;
for (iterator prev2 = it2++;
- it2 != it2_last;
+ it2 != it2_beyond;
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
{
iterator next2 = next_point(ring2, it2);
@@ -158,26 +218,36 @@ class piece_turn_visitor
public:
- piece_turn_visitor(Rings const& ring_collection,
+ piece_turn_visitor(Pieces const& pieces,
+ Rings const& ring_collection,
Turns& turns,
RobustPolicy const& robust_policy)
- : m_rings(ring_collection)
+ : m_pieces(pieces)
+ , m_rings(ring_collection)
, m_turns(turns)
, m_robust_policy(robust_policy)
{}
- template <typename Piece>
- inline void apply(Piece const& piece1, Piece const& piece2,
+ template <typename Section>
+ inline void apply(Section const& section1, Section const& section2,
bool first = true)
{
boost::ignore_unused_variable_warning(first);
- if ( is_adjacent(piece1, piece2)
- || detail::disjoint::disjoint_box_box(piece1.robust_envelope,
- piece2.robust_envelope))
+
+ typedef typename boost::range_value<Pieces const>::type piece_type;
+ piece_type const& piece1 = m_pieces[section1.ring_id.source_index];
+ piece_type const& piece2 = m_pieces[section2.ring_id.source_index];
+
+ if ( piece1.index == piece2.index
+ || is_adjacent(piece1, piece2)
+ || is_on_same_convex_ring(piece1, piece2)
+ || detail::disjoint::disjoint_box_box(section1.bounding_box,
+ section2.bounding_box) )
{
return;
}
- calculate_turns(piece1, piece2);
+
+ calculate_turns(piece1, piece2, section1, section2);
}
};
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_input.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_input.hpp
deleted file mode 100644
index 2b1c33d291..0000000000
--- a/boost/geometry/algorithms/detail/buffer/turn_in_input.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_INPUT_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_INPUT_HPP
-
-#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace buffer
-{
-
-// Checks if an turn/intersection point is inside (or covered by) the input geometry
-
-template <typename Tag>
-struct turn_in_input
-{
-};
-
-template <>
-struct turn_in_input<polygon_tag>
-{
- template <typename Point, typename Geometry>
- static inline int apply(Point const& point, Geometry const& geometry)
- {
- return geometry::covered_by(point, geometry) ? 1 : -1;
- }
-};
-
-template <>
-struct turn_in_input<linestring_tag>
-{
- template <typename Point, typename Geometry>
- static inline int apply(Point const& , Geometry const& )
- {
- return 0;
- }
-};
-
-template <>
-struct turn_in_input<point_tag>
-{
- template <typename Point, typename Geometry>
- static inline int apply(Point const& , Geometry const& )
- {
- return 0;
- }
-};
-
-template <>
-struct turn_in_input<multi_polygon_tag>
-{
- template <typename Point, typename Geometry>
- static inline int apply(Point const& point, Geometry const& geometry)
- {
- return geometry::covered_by(point, geometry) ? 1 : -1;
- }
-};
-
-template <>
-struct turn_in_input<multi_linestring_tag>
-{
- template <typename Point, typename Geometry>
- static inline int apply(Point const& , Geometry const& )
- {
- return 0;
- }
-};
-
-template <>
-struct turn_in_input<multi_point_tag>
-{
- template <typename Point, typename Geometry>
- static inline int apply(Point const& , Geometry const& )
- {
- return 0;
- }
-};
-
-
-}} // namespace detail::buffer
-#endif // DOXYGEN_NO_DETAIL
-
-
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_INPUT_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
new file mode 100644
index 0000000000..05fc6df8ff
--- /dev/null
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
@@ -0,0 +1,268 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
+
+
+#include <boost/core/ignore_unused.hpp>
+
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
+#include <boost/geometry/strategies/buffer.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace buffer
+{
+
+struct original_get_box
+{
+ template <typename Box, typename Original>
+ static inline void apply(Box& total, Original const& original)
+ {
+ geometry::expand(total, original.m_box);
+ }
+};
+
+struct original_ovelaps_box
+{
+ template <typename Box, typename Original>
+ static inline bool apply(Box const& box, Original const& original)
+ {
+ return ! detail::disjoint::disjoint_box_box(box, original.m_box);
+ }
+};
+
+struct include_turn_policy
+{
+ template <typename Turn>
+ static inline bool apply(Turn const& turn)
+ {
+ return turn.location == location_ok;
+ }
+};
+
+struct turn_in_original_ovelaps_box
+{
+ template <typename Box, typename Turn>
+ static inline bool apply(Box const& box, Turn const& turn)
+ {
+ if (turn.location != location_ok || turn.within_original)
+ {
+ // Skip all points already processed
+ return false;
+ }
+
+ return ! geometry::detail::disjoint::disjoint_point_box(
+ turn.robust_point, box);
+ }
+};
+
+//! Check if specified is in range of specified iterators
+//! Return value of strategy (true if we can bail out)
+template
+<
+ typename Strategy,
+ typename State,
+ typename Point,
+ typename Iterator
+>
+inline bool point_in_range(Strategy& strategy, State& state,
+ Point const& point, Iterator begin, Iterator end)
+{
+ boost::ignore_unused(strategy);
+
+ Iterator it = begin;
+ for (Iterator previous = it++; it != end; ++previous, ++it)
+ {
+ if (! strategy.apply(point, *previous, *it, state))
+ {
+ // We're probably on the boundary
+ return false;
+ }
+ }
+ return true;
+}
+
+template
+<
+ typename Strategy,
+ typename State,
+ typename Point,
+ typename CoordinateType,
+ typename Iterator
+>
+inline bool point_in_section(Strategy& strategy, State& state,
+ Point const& point, CoordinateType const& point_y,
+ Iterator begin, Iterator end,
+ int direction)
+{
+ if (direction == 0)
+ {
+ // Not a monotonic section, or no change in Y-direction
+ return point_in_range(strategy, state, point, begin, end);
+ }
+
+ // We're in a monotonic section in y-direction
+ Iterator it = begin;
+
+ for (Iterator previous = it++; it != end; ++previous, ++it)
+ {
+ // Depending on sections.direction we can quit for this section
+ CoordinateType const previous_y = geometry::get<1>(*previous);
+
+ if (direction == 1 && point_y < previous_y)
+ {
+ // Section goes upwards, y increases, point is is below section
+ return true;
+ }
+ else if (direction == -1 && point_y > previous_y)
+ {
+ // Section goes downwards, y decreases, point is above section
+ return true;
+ }
+
+ if (! strategy.apply(point, *previous, *it, state))
+ {
+ // We're probably on the boundary
+ return false;
+ }
+ }
+ return true;
+}
+
+
+template <typename Point, typename Original>
+inline int point_in_original(Point const& point, Original const& original)
+{
+ typedef strategy::within::winding<Point> strategy_type;
+
+ typename strategy_type::state_type state;
+ strategy_type strategy;
+
+ if (boost::size(original.m_sections) == 0
+ || boost::size(original.m_ring) - boost::size(original.m_sections) < 16)
+ {
+ // There are no sections, or it does not profit to walk over sections
+ // instead of over points. Boundary of 16 is arbitrary but can influence
+ // performance
+ point_in_range(strategy, state, point,
+ original.m_ring.begin(), original.m_ring.end());
+ return strategy.result(state);
+ }
+
+ typedef typename Original::sections_type sections_type;
+ typedef typename boost::range_iterator<sections_type const>::type iterator_type;
+ typedef typename boost::range_value<sections_type const>::type section_type;
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ coordinate_type const point_y = geometry::get<1>(point);
+
+ // Walk through all monotonic sections of this original
+ for (iterator_type it = boost::begin(original.m_sections);
+ it != boost::end(original.m_sections);
+ ++it)
+ {
+ section_type const& section = *it;
+
+ if (! section.duplicate
+ && section.begin_index < section.end_index
+ && point_y >= geometry::get<min_corner, 1>(section.bounding_box)
+ && point_y <= geometry::get<max_corner, 1>(section.bounding_box))
+ {
+ // y-coordinate of point overlaps with section
+ if (! point_in_section(strategy, state, point, point_y,
+ boost::begin(original.m_ring) + section.begin_index,
+ boost::begin(original.m_ring) + section.end_index + 1,
+ section.directions[0]))
+ {
+ // We're probably on the boundary
+ break;
+ }
+ }
+ }
+
+ return strategy.result(state);
+}
+
+
+template <typename Turns>
+class turn_in_original_visitor
+{
+public:
+ turn_in_original_visitor(Turns& turns)
+ : m_mutable_turns(turns)
+ {}
+
+ template <typename Turn, typename Original>
+ inline void apply(Turn const& turn, Original const& original, bool first = true)
+ {
+ boost::ignore_unused_variable_warning(first);
+
+ if (turn.location != location_ok || turn.within_original)
+ {
+ // Skip all points already processed
+ return;
+ }
+
+ if (geometry::disjoint(turn.robust_point, original.m_box))
+ {
+ // Skip all disjoint
+ return;
+ }
+
+ int const code = point_in_original(turn.robust_point, original);
+
+ if (code == -1)
+ {
+ return;
+ }
+
+ Turn& mutable_turn = m_mutable_turns[turn.turn_index];
+
+ if (code == 0)
+ {
+ // On border of original: always discard
+ mutable_turn.location = location_discard;
+ }
+
+ // Point is inside an original ring
+ if (original.m_is_interior)
+ {
+ mutable_turn.count_in_original--;
+ }
+ else if (original.m_has_interiors)
+ {
+ mutable_turn.count_in_original++;
+ }
+ else
+ {
+ // It is an exterior ring and there are no interior rings.
+ // Then we are completely ready with this turn
+ mutable_turn.within_original = true;
+ mutable_turn.count_in_original = 1;
+ }
+ }
+
+private :
+ Turns& m_mutable_turns;
+};
+
+
+}} // namespace detail::buffer
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
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 c02f56de3f..8803efdec9 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
@@ -9,19 +9,23 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
+
+#include <boost/core/ignore_unused.hpp>
+
#include <boost/range.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#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/geometries/linestring.hpp>
-#include <boost/geometry/algorithms/comparable_distance.hpp>
namespace boost { namespace geometry
{
@@ -31,6 +35,33 @@ namespace boost { namespace geometry
namespace detail { namespace buffer
{
+struct piece_get_box
+{
+ template <typename Box, typename Piece>
+ static inline void apply(Box& total, Piece const& piece)
+ {
+ geometry::expand(total, piece.robust_envelope);
+ }
+};
+
+struct piece_ovelaps_box
+{
+ template <typename Box, typename Piece>
+ static inline bool apply(Box const& box, Piece const& piece)
+ {
+ if (piece.type == strategy::buffer::buffered_flat_end
+ || piece.type == strategy::buffer::buffered_concave)
+ {
+ // Turns cannot be inside a flat end (though they can be on border)
+ // Neither we need to check if they are inside concave helper pieces
+
+ // Skip all pieces not used as soon as possible
+ return false;
+ }
+
+ return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);
+ }
+};
struct turn_get_box
{
@@ -46,96 +77,422 @@ struct turn_ovelaps_box
template <typename Box, typename Turn>
static inline bool apply(Box const& box, Turn const& turn)
{
- return ! dispatch::disjoint
- <
- typename Turn::robust_point_type,
- Box
- >::apply(turn.robust_point, box);
+ return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box);
}
};
-template <typename Turns, typename Pieces>
-class turn_in_piece_visitor
+
+enum analyse_result
{
- Turns& m_turns; // because partition is currently operating on const input only
- Pieces const& m_pieces; // to check for piece-type
+ analyse_unknown,
+ analyse_continue,
+ analyse_disjoint,
+ analyse_within,
+ analyse_on_original_boundary,
+ analyse_on_offsetted,
+ analyse_near_offsetted
+};
- typedef boost::long_long_type calculation_type;
+template <typename Point>
+inline bool in_box(Point const& previous,
+ Point const& current, Point const& point)
+{
+ // Get its box (TODO: this can be prepared-on-demand later)
+ typedef geometry::model::box<Point> box_type;
+ box_type box;
+ geometry::assign_inverse(box);
+ geometry::expand(box, previous);
+ geometry::expand(box, current);
+
+ return geometry::covered_by(point, box);
+}
+
+template <typename Point, typename Turn>
+inline analyse_result check_segment(Point const& previous,
+ Point const& current, Turn const& turn,
+ bool from_monotonic)
+{
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Point>::type
+ >::type side_strategy;
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ coordinate_type const twice_area
+ = side_strategy::template side_value
+ <
+ coordinate_type,
+ coordinate_type
+ >(previous, current, turn.robust_point);
- template <typename Point>
- static inline bool projection_on_segment(Point const& subject, Point const& p, Point const& q)
+ if (twice_area == 0)
{
- typedef Point vector_type;
- typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+ // Collinear, only on segment if it is covered by its bbox
+ if (in_box(previous, current, turn.robust_point))
+ {
+ return analyse_on_offsetted;
+ }
+ }
+ else if (twice_area < 0)
+ {
+ // It is in the triangle right-of the segment where the
+ // segment is the hypothenusa. Check if it is close
+ // (within rounding-area)
+ if (twice_area * twice_area < geometry::comparable_distance(previous, current)
+ && in_box(previous, current, turn.robust_point))
+ {
+ return analyse_near_offsetted;
+ }
+ else if (from_monotonic)
+ {
+ return analyse_within;
+ }
+ }
+ else if (twice_area > 0 && from_monotonic)
+ {
+ // Left of segment
+ return analyse_disjoint;
+ }
+
+ // Not monotonic, on left or right side: continue analysing
+ return analyse_continue;
+}
- vector_type v = q;
- vector_type w = subject;
- subtract_point(v, p);
- subtract_point(w, p);
- coordinate_type const zero = coordinate_type();
- coordinate_type const c1 = dot_product(w, v);
+class analyse_turn_wrt_point_piece
+{
+public :
+ template <typename Turn, typename Piece>
+ static inline analyse_result apply(Turn const& turn, Piece const& piece)
+ {
+ typedef typename Piece::section_type section_type;
+ typedef typename Turn::robust_point_type point_type;
+ typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
- if (c1 < zero)
+ coordinate_type const point_y = geometry::get<1>(turn.robust_point);
+
+ typedef strategy::within::winding<point_type> strategy_type;
+
+ typename strategy_type::state_type state;
+ strategy_type strategy;
+ boost::ignore_unused(strategy);
+
+ for (std::size_t s = 0; s < piece.sections.size(); s++)
{
- return false;
+ section_type const& section = piece.sections[s];
+ // If point within vertical range of monotonic section:
+ if (! section.duplicate
+ && section.begin_index < section.end_index
+ && 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++)
+ {
+ point_type const& previous = piece.robust_ring[i - 1];
+ point_type const& current = piece.robust_ring[i];
+
+ analyse_result code = check_segment(previous, current, turn, false);
+ if (code != analyse_continue)
+ {
+ return code;
+ }
+
+ // 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);
+ }
+ }
}
- coordinate_type const c2 = dot_product(v, v);
- if (c2 < c1)
+
+ int const code = strategy.result(state);
+ if (code == 1)
{
- return false;
+ return analyse_within;
+ }
+ else if (code == -1)
+ {
+ return analyse_disjoint;
}
- return true;
+ // Should normally not occur - on-segment is covered
+ return analyse_unknown;
}
- template <typename Point, typename Piece>
- inline bool on_offsetted(Point const& point, Piece const& piece) const
+};
+
+class analyse_turn_wrt_piece
+{
+ template <typename Point, typename Turn>
+ static inline analyse_result check_helper_segment(Point const& s1,
+ Point const& s2, Turn const& turn,
+ bool is_original,
+ Point const& offsetted)
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type side_strategy;
- geometry::equal_to<Point> comparator;
+
+ switch(side_strategy::apply(s1, s2, turn.robust_point))
+ {
+ case 1 :
+ return analyse_disjoint; // left of segment
+ case 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))
+ {
+ // It is on the segment
+ if (! is_original
+ && geometry::comparable_distance(turn.robust_point, offsetted) <= 1)
+ {
+ // It is close to the offsetted-boundary, take
+ // any rounding-issues into account
+ return analyse_near_offsetted;
+ }
+
+ // 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;
+ }
+ break;
+ }
+
+ // right of segment
+ return analyse_continue;
+ }
+
+ template <typename Turn, typename Piece>
+ static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)
+ {
+ typedef typename Turn::robust_point_type point_type;
+ geometry::equal_to<point_type> comparator;
+
+ point_type points[4];
+
+ int helper_count = piece.robust_ring.size() - piece.offsetted_count;
+ if (helper_count == 4)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ points[i] = piece.robust_ring[piece.offsetted_count + i];
+ }
+ }
+ else if (helper_count == 3)
+ {
+ // Triangular piece, assign points but assign second twice
+ for (int i = 0; i < 4; i++)
+ {
+ int index = i < 2 ? i : i - 1;
+ points[i] = piece.robust_ring[piece.offsetted_count + index];
+ }
+ }
+ else
+ {
+ // Some pieces (e.g. around points) do not have helper segments.
+ // Others should have 3 (join) or 4 (side)
+ return analyse_continue;
+ }
+
+ // First check point-equality
+ point_type const& point = turn.robust_point;
+ if (comparator(point, points[0]) || comparator(point, points[3]))
+ {
+ return analyse_on_offsetted;
+ }
+ if (comparator(point, points[1]) || comparator(point, points[2]))
+ {
+ return analyse_on_original_boundary;
+ }
+
+ // Right side of the piece
+ analyse_result result
+ = check_helper_segment(points[0], points[1], turn,
+ false, points[0]);
+ if (result != analyse_continue)
+ {
+ return result;
+ }
+
+ // Left side of the piece
+ result = check_helper_segment(points[2], points[3], turn,
+ false, points[3]);
+ if (result != analyse_continue)
+ {
+ return result;
+ }
+
+ if (! comparator(points[1], points[2]))
+ {
+ // Side of the piece at side of original geometry
+ result = check_helper_segment(points[1], points[2], turn,
+ true, point);
+ if (result != analyse_continue)
+ {
+ return result;
+ }
+ }
+
+ // We are within the \/ or |_| shaped piece, where the top is the
+ // offsetted ring.
+ if (! geometry::covered_by(point, piece.robust_offsetted_envelope))
+ {
+ // Not in offsetted-area. This makes a cheap check possible
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<point_type>::type
+ >::type side_strategy;
+
+ switch(side_strategy::apply(points[3], points[0], point))
+ {
+ case 1 : return analyse_disjoint;
+ case -1 : return analyse_within;
+ case 0 : return analyse_disjoint;
+ }
+ }
+
+ return analyse_continue;
+ }
+
+ template <typename Turn, typename Piece, typename Compare>
+ static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare)
+ {
+ typedef typename Piece::piece_robust_ring_type ring_type;
+ typedef typename ring_type::const_iterator it_type;
+ it_type end = piece.robust_ring.begin() + piece.offsetted_count;
+ it_type it = std::lower_bound(piece.robust_ring.begin(),
+ end,
+ turn.robust_point,
+ compare);
+
+ if (it != end
+ && it != piece.robust_ring.begin())
+ {
+ // iterator points to point larger than point
+ // w.r.t. specified direction, and prev points to a point smaller
+ // We now know if it is inside/outside
+ it_type prev = it - 1;
+ return check_segment(*prev, *it, turn, true);
+ }
+ return analyse_continue;
+ }
+
+public :
+ template <typename Turn, typename Piece>
+ static inline analyse_result apply(Turn const& turn, Piece const& piece)
+ {
+ typedef typename Turn::robust_point_type point_type;
+ analyse_result code = check_helper_segments(turn, piece);
+ if (code != analyse_continue)
+ {
+ return code;
+ }
+
+ geometry::equal_to<point_type> comparator;
+
+ if (piece.offsetted_count > 8)
+ {
+ // If the offset contains some points and is monotonic, we try
+ // to avoid walking all points linearly.
+ // We try it only once.
+ if (piece.is_monotonic_increasing[0])
+ {
+ code = check_monotonic(turn, piece, geometry::less<point_type, 0>());
+ if (code != analyse_continue) return code;
+ }
+ else if (piece.is_monotonic_increasing[1])
+ {
+ code = check_monotonic(turn, piece, geometry::less<point_type, 1>());
+ if (code != analyse_continue) return code;
+ }
+ else if (piece.is_monotonic_decreasing[0])
+ {
+ code = check_monotonic(turn, piece, geometry::greater<point_type, 0>());
+ if (code != analyse_continue) return code;
+ }
+ else if (piece.is_monotonic_decreasing[1])
+ {
+ code = check_monotonic(turn, piece, geometry::greater<point_type, 1>());
+ if (code != analyse_continue) return code;
+ }
+ }
+
+ // 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++)
{
- Point const& previous = piece.robust_ring[i - 1];
- Point const& current = piece.robust_ring[i];
+ point_type const& previous = piece.robust_ring[i - 1];
+ point_type const& current = piece.robust_ring[i];
- // The robust ring contains duplicates, avoid applying side on them (will be 0)
+ // The robust ring can contain duplicates
+ // (on which any side or side-value would return 0)
if (! comparator(previous, current))
{
- int const side = side_strategy::apply(previous, current, point);
- if (side == 0)
+ code = check_segment(previous, current, turn, false);
+ if (code != analyse_continue)
{
- // Collinear, check if projection falls on it
- if (projection_on_segment(point, previous, current))
- {
- return true;
- }
+ return code;
}
}
}
- return false;
+
+ return analyse_unknown;
}
- template <typename Point, typename Piece>
- static inline
- calculation_type comparable_distance_from_offsetted(Point const& point,
- Piece const& piece)
+};
+
+
+template <typename Turns, typename Pieces>
+class turn_in_piece_visitor
+{
+ Turns& m_turns; // because partition is currently operating on const input only
+ Pieces const& m_pieces; // to check for piece-type
+
+ template <typename Operation, typename Piece>
+ inline bool skip(Operation const& op, Piece const& piece) const
{
- // TODO: pass subrange to dispatch to avoid making copy
- geometry::model::linestring<Point> ls;
- std::copy(piece.robust_ring.begin(),
- piece.robust_ring.begin() + piece.offsetted_count,
- std::back_inserter(ls));
- typename default_comparable_distance_result<Point, Point>::type
- const comp = geometry::comparable_distance(point, ls);
-
- return static_cast<calculation_type>(comp);
+ if (op.piece_index == piece.index)
+ {
+ return true;
+ }
+ Piece const& pc = m_pieces[op.piece_index];
+ if (pc.left_index == piece.index || pc.right_index == piece.index)
+ {
+ if (pc.type == strategy::buffer::buffered_flat_end)
+ {
+ // If it is a flat end, don't compare against its neighbor:
+ // it will always be located on one of the helper segments
+ return true;
+ }
+ if (pc.type == strategy::buffer::buffered_concave)
+ {
+ // If it is concave, the same applies: the IP will be
+ // located on one of the helper segments
+ return true;
+ }
+ }
+
+ return false;
}
+
public:
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces)
@@ -157,81 +514,55 @@ public:
if (piece.type == strategy::buffer::buffered_flat_end
|| piece.type == strategy::buffer::buffered_concave)
{
- // Turns cannot be inside a flat end (though they can be on border)
- // Neither we need to check if they are inside concave helper pieces
+ // Turns cannot be located within flat-end or concave pieces
return;
}
- bool neighbour = false;
- for (int i = 0; i < 2; i++)
- {
- // Don't compare against one of the two source-pieces
- if (turn.operations[i].piece_index == piece.index)
- {
- return;
- }
-
- typename boost::range_value<Pieces>::type const& pc
- = m_pieces[turn.operations[i].piece_index];
- if (pc.left_index == piece.index
- || pc.right_index == piece.index)
- {
- if (pc.type == strategy::buffer::buffered_flat_end)
- {
- // If it is a flat end, don't compare against its neighbor:
- // it will always be located on one of the helper segments
- return;
- }
- neighbour = true;
- }
- }
-
- int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
-
- if (geometry_code == -1)
+ if (! geometry::covered_by(turn.robust_point, piece.robust_envelope))
{
+ // Easy check: if the turn is not in the envelope, we can safely return
return;
}
- if (geometry_code == 0 && neighbour)
+
+ if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
{
return;
}
+ // TODO: mutable_piece to make some on-demand preparations in analyse
+ 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];
- if (geometry_code == 0)
+ switch(analyse_code)
{
- // If it is on the border and they are not neighbours, it should be
- // on the offsetted ring
-
- if (! on_offsetted(turn.robust_point, piece))
- {
- // It is on the border but not on the offsetted ring.
- // Then it is somewhere on the helper-segments
- // Classify it as "within"
- geometry_code = 1;
- mutable_turn.count_on_helper++; // can still become "near_offsetted"
- }
- else
- {
+ case analyse_disjoint :
+ return;
+ case analyse_on_offsetted :
mutable_turn.count_on_offsetted++; // value is not used anymore
- }
+ return;
+ case analyse_on_original_boundary :
+ mutable_turn.count_on_original_boundary++;
+ return;
+ case analyse_within :
+ mutable_turn.count_within++;
+ return;
+ case analyse_near_offsetted :
+ mutable_turn.count_within_near_offsetted++;
+ return;
+ default :
+ break;
}
+ // TODO: this point_in_geometry is a performance-bottleneck here and
+ // will be replaced completely by extending analyse_piece functionality
+ int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
+
if (geometry_code == 1)
{
- calculation_type const distance
- = comparable_distance_from_offsetted(turn.robust_point, piece);
- if (distance >= 4)
- {
- // This is too far from the border, it counts as "really within"
- mutable_turn.count_within++;
- }
- else
- {
- // Other points count as still "on border" because they might be
- // travelled through, but not used as starting point
- mutable_turn.count_within_near_offsetted++;
- }
+ mutable_turn.count_within++;
}
}
};
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 c7558b4ff1..04fa9ee86b 100644
--- a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
@@ -63,8 +63,7 @@ private:
>::apply(geometry, *it_min, strategy);
// check if other elements in the range are closer
- RangeIterator it = first;
- for (++it; it != last; ++it)
+ for (RangeIterator it = ++first; it != last; ++it)
{
Distance dist = dispatch::distance
<
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 90248767ec..ceba59b41a 100644
--- a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
@@ -60,6 +60,7 @@ private:
BOOST_ASSERT( queries_first != queries_last );
Distance const zero = Distance(0);
+ dist_min = zero;
// create -- packing algorithm
rtree_type rt(rtree_first, rtree_last);
diff --git a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
index 1a57c8f4b3..c443a54e58 100644
--- a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
@@ -232,13 +232,13 @@ struct comparable_distance
template
<
- BOOST_VARIANT_ENUM_PARAMS(typename A),
- BOOST_VARIANT_ENUM_PARAMS(typename B)
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct comparable_distance
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)>
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
@@ -246,8 +246,8 @@ struct comparable_distance
<
typename comparable_distance_result
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
>
@@ -279,12 +279,12 @@ struct comparable_distance
template <typename Strategy>
static inline typename comparable_distance_result
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)> const& geometry2,
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
diff --git a/boost/geometry/algorithms/detail/course.hpp b/boost/geometry/algorithms/detail/course.hpp
index e1a74c0fee..37424941bd 100644
--- a/boost/geometry/algorithms/detail/course.hpp
+++ b/boost/geometry/algorithms/detail/course.hpp
@@ -14,10 +14,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/access.hpp>
-#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/algorithms/detail/azimuth.hpp>
namespace boost { namespace geometry
{
@@ -27,25 +24,12 @@ namespace detail
{
/// Calculate course (bearing) between two points.
+///
+/// NOTE: left for convenience and temporary backward compatibility
template <typename ReturnType, typename Point1, typename Point2>
inline ReturnType course(Point1 const& p1, Point2 const& p2)
{
- // http://williams.best.vwh.net/avform.htm#Crs
- ReturnType dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
- ReturnType cos_p2lat = cos(get_as_radian<1>(p2));
-
- // An optimization which should kick in often for Boxes
- //if ( math::equals(dlon, ReturnType(0)) )
- //if ( get<0>(p1) == get<0>(p2) )
- //{
- // return - sin(get_as_radian<1>(p1)) * cos_p2lat);
- //}
-
- // "An alternative formula, not requiring the pre-computation of d"
- // In the formula below dlon is used as "d"
- return atan2(sin(dlon) * cos_p2lat,
- cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
- - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
+ return azimuth<ReturnType>(p1, p2);
}
} // namespace detail
diff --git a/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
index ccff9799fd..84671f257e 100644
--- a/boost/geometry/algorithms/detail/disjoint/box_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/box_box.hpp
@@ -74,7 +74,7 @@ struct box_box<Box1, Box2, DimensionCount, DimensionCount>
/*!
- \brief Internal utility function to detect of boxes are disjoint
+ \brief Internal utility function to detect if boxes are disjoint
\note Is used from other algorithms, declared separately
to avoid circular references
*/
diff --git a/boost/geometry/algorithms/detail/disjoint/implementation.hpp b/boost/geometry/algorithms/detail/disjoint/implementation.hpp
index 0c8079b8e4..d482c4a5a9 100644
--- a/boost/geometry/algorithms/detail/disjoint/implementation.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/implementation.hpp
@@ -26,6 +26,7 @@
#include <boost/geometry/algorithms/detail/disjoint/linear_areal.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
diff --git a/boost/geometry/algorithms/detail/disjoint/interface.hpp b/boost/geometry/algorithms/detail/disjoint/interface.hpp
index ec9057ba0d..96d6881296 100644
--- a/boost/geometry/algorithms/detail/disjoint/interface.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/interface.hpp
@@ -23,8 +23,8 @@
#include <cstddef>
-#include <boost/variant/static_visitor.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>
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
index eefd351b8d..6a48b684a1 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2014.
-// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-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
@@ -31,16 +31,20 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
-#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
@@ -48,25 +52,59 @@
namespace boost { namespace geometry
{
-
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
+template <typename Geometry1, typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>
+struct disjoint_no_intersections_policy
+{
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ {
+ typedef typename point_type<Geometry1>::type point1_type;
+ point1_type p;
+ geometry::point_on_border(p, g1);
+ return !geometry::covered_by(p, g2);
+ }
+};
-template<typename Geometry1, typename Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
+{
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ {
+ // TODO: use partition or rtree on g2
+ typedef typename boost::range_iterator<Geometry1 const>::type iterator;
+ for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
+ {
+ typedef typename boost::range_value<Geometry1 const>::type value_type;
+ if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
+ ::apply(*it, g2) )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+
+template<typename Geometry1, typename Geometry2,
+ typename NoIntersectionsPolicy
+ = disjoint_no_intersections_policy<Geometry1, Geometry2> >
struct disjoint_linear_areal
{
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
{
// if there are intersections - return false
if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2) )
+ {
return false;
+ }
- typedef typename point_type<Geometry1>::type point1_type;
- point1_type p;
- geometry::point_on_border(p, g1);
- return !geometry::covered_by(p, g2);
+ return NoIntersectionsPolicy::apply(g1, g2);
}
};
@@ -88,38 +126,28 @@ template <typename Segment, typename Polygon>
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
{
private:
- template <typename RingIterator>
- static inline bool check_interior_rings(RingIterator first,
- RingIterator beyond,
- Segment const& segment)
- {
- for (RingIterator it = first; it != beyond; ++it)
- {
- if ( !disjoint_range_segment_or_box
- <
- typename std::iterator_traits
- <
- RingIterator
- >::value_type,
- closure<Polygon>::value,
- Segment
- >::apply(*it, segment) )
- {
- return false;
- }
- }
- return true;
- }
-
-
template <typename InteriorRings>
static inline
bool check_interior_rings(InteriorRings const& interior_rings,
Segment const& segment)
{
- return check_interior_rings(boost::begin(interior_rings),
- boost::end(interior_rings),
- segment);
+ typedef typename boost::range_value<InteriorRings>::type ring_type;
+
+ typedef unary_disjoint_geometry_to_query_geometry
+ <
+ Segment,
+ disjoint_range_segment_or_box
+ <
+ ring_type, closure<ring_type>::value, Segment
+ >
+ > unary_predicate_type;
+
+ return check_iterator_range
+ <
+ unary_predicate_type
+ >::apply(boost::begin(interior_rings),
+ boost::end(interior_rings),
+ unary_predicate_type(segment));
}
@@ -155,7 +183,7 @@ struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
static inline
bool apply(Segment const& segment, MultiPolygon const& multipolygon)
{
- return disjoint_multirange_segment_or_box
+ return multirange_constant_size_geometry
<
MultiPolygon, Segment
>::apply(multipolygon, segment);
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
index ad84d7191d..91f985edb8 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
@@ -98,11 +98,10 @@ struct assign_disjoint_policy
typename Info,
typename Point1,
typename Point2,
- typename IntersectionInfo,
- typename DirInfo
+ typename IntersectionInfo
>
static inline void apply(Info& , Point1 const& , Point2 const&,
- IntersectionInfo const&, DirInfo const&)
+ IntersectionInfo const&)
{}
};
@@ -115,28 +114,42 @@ struct disjoint_linear
{
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::no_rescale_policy rescale_policy_type;
+ typedef typename geometry::segment_ratio_type
+ <
+ point_type, rescale_policy_type
+ >::type segment_ratio_type;
typedef overlay::turn_info
- <
- point_type,
- typename segment_ratio_type<point_type, rescale_policy_type>::type
- > turn_info;
- std::deque<turn_info> turns;
+ <
+ point_type,
+ segment_ratio_type,
+ typename detail::get_turns::turn_operation_type
+ <
+ Geometry1, Geometry2, segment_ratio_type
+ >::type
+ > turn_info_type;
- static const bool reverse1 = overlay::do_reverse<geometry::point_order<Geometry1>::value>::value; // should be false
- static const bool reverse2 = overlay::do_reverse<geometry::point_order<Geometry2>::value>::value; // should be false
+ std::deque<turn_info_type> turns;
// Specify two policies:
// 1) Stop at any intersection
// 2) In assignment, include also degenerate points (which are normally skipped)
- disjoint_interrupt_policy policy;
- rescale_policy_type robust_policy;
- geometry::get_turns
+ disjoint_interrupt_policy interrupt_policy;
+ dispatch::get_turns
<
- reverse1, reverse2,
- assign_disjoint_policy
- >(geometry1, geometry2, robust_policy, turns, policy);
+ typename geometry::tag<Geometry1>::type,
+ typename geometry::tag<Geometry2>::type,
+ Geometry1,
+ Geometry2,
+ overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, // should be false
+ overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, // should be false
+ detail::get_turns::get_turn_info_type
+ <
+ Geometry1, Geometry2, assign_disjoint_policy
+ >
+ >::apply(0, geometry1, 1, geometry2,
+ rescale_policy_type(), turns, interrupt_policy);
- return !policy.has_intersections;
+ return !interrupt_policy.has_intersections;
}
};
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
index d181726e2e..8d82f7c911 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp
@@ -32,6 +32,7 @@
#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
@@ -44,34 +45,6 @@ namespace detail { namespace disjoint
{
-template <typename MultiRange, typename SegmentOrBox>
-struct disjoint_multirange_segment_or_box
-{
- static inline
- bool apply(MultiRange const& multirange, SegmentOrBox const& segment_or_box)
- {
- typedef typename boost::range_iterator
- <
- MultiRange const
- >::type const_iterator;
-
- for (const_iterator it = boost::begin(multirange);
- it != boost::end(multirange); ++it)
- {
- if ( !dispatch::disjoint
- <
- typename boost::range_value<MultiRange>::type,
- SegmentOrBox
- >::apply(*it, segment_or_box) )
- {
- return false;
- }
- }
- return true;
- }
-};
-
-
template
<
typename Range,
@@ -160,7 +133,7 @@ template <typename MultiLinestring, typename SegmentOrBox>
struct disjoint_linear_segment_or_box
<
MultiLinestring, SegmentOrBox, multi_linestring_tag
- > : disjoint_multirange_segment_or_box<MultiLinestring, SegmentOrBox>
+ > : multirange_constant_size_geometry<MultiLinestring, SegmentOrBox>
{};
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
new file mode 100644
index 0000000000..7d1bb05242
--- /dev/null
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
@@ -0,0 +1,162 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
+
+#include <algorithm>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/check_iterator_range.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>
+#include <boost/geometry/algorithms/detail/relate/less.hpp>
+
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint
+{
+
+template<typename MultiPoint1, typename MultiPoint2>
+class multipoint_multipoint
+{
+private:
+ template <typename Iterator>
+ class unary_disjoint_predicate
+ : detail::relate::less
+ {
+ private:
+ typedef detail::relate::less base_type;
+
+ public:
+ unary_disjoint_predicate(Iterator first, Iterator last)
+ : base_type(), m_first(first), m_last(last)
+ {}
+
+ template <typename Point>
+ inline bool apply(Point const& point) const
+ {
+ return !std::binary_search(m_first,
+ m_last,
+ point,
+ static_cast<base_type const&>(*this));
+ }
+
+ private:
+ Iterator m_first, m_last;
+ };
+
+public:
+ static inline bool apply(MultiPoint1 const& multipoint1,
+ MultiPoint2 const& multipoint2)
+ {
+ BOOST_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
+
+ typedef typename boost::range_value<MultiPoint1>::type point1_type;
+
+ std::vector<point1_type> points1(boost::begin(multipoint1),
+ boost::end(multipoint1));
+
+ std::sort(points1.begin(), points1.end(), detail::relate::less());
+
+ typedef unary_disjoint_predicate
+ <
+ typename std::vector<point1_type>::const_iterator
+ > predicate_type;
+
+ return check_iterator_range
+ <
+ predicate_type
+ >::apply(boost::begin(multipoint2),
+ boost::end(multipoint2),
+ predicate_type(points1.begin(), points1.end()));
+ }
+};
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template<typename Point, typename MultiPoint, std::size_t DimensionCount>
+struct disjoint
+ <
+ Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false
+ > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Point>
+{};
+
+
+template<typename MultiPoint, typename Segment, std::size_t DimensionCount>
+struct disjoint
+ <
+ MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false
+ > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Segment>
+{};
+
+
+template<typename MultiPoint, typename Box, std::size_t DimensionCount>
+struct disjoint
+ <
+ MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false
+ > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Box>
+{};
+
+
+template<typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount>
+struct disjoint
+ <
+ MultiPoint1, MultiPoint2, DimensionCount,
+ multi_point_tag, multi_point_tag, false
+ >
+{
+ static inline bool apply(MultiPoint1 const& multipoint1,
+ MultiPoint2 const& multipoint2)
+ {
+ if ( boost::size(multipoint2) < boost::size(multipoint1) )
+ {
+ return detail::disjoint::multipoint_multipoint
+ <
+ MultiPoint2, MultiPoint1
+ >::apply(multipoint2, multipoint1);
+ }
+
+ return detail::disjoint::multipoint_multipoint
+ <
+ MultiPoint1, MultiPoint2
+ >::apply(multipoint1, multipoint2);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
new file mode 100644
index 0000000000..78a683e46e
--- /dev/null
+++ b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
@@ -0,0 +1,85 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint
+{
+
+
+template <typename Geometry, typename BinaryPredicate>
+class unary_disjoint_geometry_to_query_geometry
+{
+public:
+ unary_disjoint_geometry_to_query_geometry(Geometry const& geometry)
+ : m_geometry(geometry)
+ {}
+
+ template <typename QueryGeometry>
+ inline bool apply(QueryGeometry const& query_geometry) const
+ {
+ return BinaryPredicate::apply(query_geometry, m_geometry);
+ }
+
+private:
+ Geometry const& m_geometry;
+};
+
+
+template<typename MultiRange, typename ConstantSizeGeometry>
+struct multirange_constant_size_geometry
+{
+ static inline bool apply(MultiRange const& multirange,
+ ConstantSizeGeometry const& constant_size_geometry)
+ {
+ typedef unary_disjoint_geometry_to_query_geometry
+ <
+ ConstantSizeGeometry,
+ dispatch::disjoint
+ <
+ typename boost::range_value<MultiRange>::type,
+ ConstantSizeGeometry
+ >
+ > unary_predicate_type;
+
+ return detail::check_iterator_range
+ <
+ unary_predicate_type
+ >::apply(boost::begin(multirange), boost::end(multirange),
+ unary_predicate_type(constant_size_geometry));
+ }
+
+ static inline bool apply(ConstantSizeGeometry const& constant_size_geometry,
+ MultiRange const& multirange)
+ {
+ return apply(multirange, constant_size_geometry);
+ }
+};
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
index ea6609a153..12213db056 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_box.hpp
@@ -70,8 +70,21 @@ struct point_box<Point, Box, DimensionCount, DimensionCount>
}
};
+/*!
+ \brief Internal utility function to detect if point/box are disjoint
+ */
+template <typename Point, typename Box>
+inline bool disjoint_point_box(Point const& point, Box const& box)
+{
+ return detail::disjoint::point_box
+ <
+ Point, Box,
+ 0, dimension<Point>::type::value
+ >::apply(point, box);
+}
+
-}} // namespace detail::equals
+}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
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 04d1095cba..57257dbdcc 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
@@ -35,6 +35,8 @@
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -215,7 +217,7 @@ public:
// consider all distances of the points in the geometry to the
// segment or box
- comparable_return_type cd_min1;
+ 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();
@@ -246,7 +248,7 @@ public:
// consider all distances of the points in the segment or box to the
// segments of the geometry
- comparable_return_type cd_min2;
+ comparable_return_type cd_min2(0);
segment_iterator_type sit_min;
typename std::vector<segment_or_box_point>::const_iterator it_min;
@@ -271,7 +273,7 @@ public:
}
}
- if (is_comparable<Strategy>::value)
+ if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
{
return (std::min)(cd_min1, cd_min2);
}
diff --git a/boost/geometry/algorithms/detail/distance/interface.hpp b/boost/geometry/algorithms/detail/distance/interface.hpp
index 9b377f524b..fa8cbd69ee 100644
--- a/boost/geometry/algorithms/detail/distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/distance/interface.hpp
@@ -260,13 +260,13 @@ struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template
<
- BOOST_VARIANT_ENUM_PARAMS(typename A),
- BOOST_VARIANT_ENUM_PARAMS(typename B)
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct distance
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)>
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
@@ -274,8 +274,8 @@ struct distance
<
typename distance_result
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
>
@@ -304,12 +304,12 @@ struct distance
template <typename Strategy>
static inline typename distance_result
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(A)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(B)> const& geometry2,
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
diff --git a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
index 5f2c6e34fb..ccd3aa462e 100644
--- a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
+++ b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
@@ -18,7 +18,7 @@
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
-#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -113,16 +113,16 @@ template <typename MultiPoint, typename Areal, typename Strategy>
class multipoint_to_areal
{
private:
- struct within_areal
+ struct not_covered_by_areal
{
- within_areal(Areal const& areal)
+ not_covered_by_areal(Areal const& areal)
: m_areal(areal)
{}
template <typename Point>
inline bool apply(Point const& point) const
{
- return geometry::within(point, m_areal);
+ return !geometry::covered_by(point, m_areal);
}
Areal const& m_areal;
@@ -140,27 +140,26 @@ public:
Areal const& areal,
Strategy const& strategy)
{
- within_areal predicate(areal);
+ not_covered_by_areal predicate(areal);
if (check_iterator_range
<
- within_areal, false
+ not_covered_by_areal, false
>::apply(boost::begin(multipoint),
boost::end(multipoint),
predicate))
{
- return 0;
+ return detail::distance::point_or_segment_range_to_geometry_rtree
+ <
+ typename boost::range_iterator<MultiPoint const>::type,
+ Areal,
+ Strategy
+ >::apply(boost::begin(multipoint),
+ boost::end(multipoint),
+ areal,
+ strategy);
}
-
- return detail::distance::point_or_segment_range_to_geometry_rtree
- <
- typename boost::range_iterator<MultiPoint const>::type,
- Areal,
- Strategy
- >::apply(boost::begin(multipoint),
- boost::end(multipoint),
- areal,
- strategy);
+ return 0;
}
static inline return_type apply(Areal const& areal,
diff --git a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
index f64a3e9fca..79d9adb703 100644
--- a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
@@ -28,6 +28,7 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/calculation_type.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/distance.hpp>
@@ -151,7 +152,7 @@ public:
}
}
- if (is_comparable<Strategy>::value)
+ if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
{
return cd[imin];
}
diff --git a/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp b/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp
index 2dcde64946..bdf056d76e 100644
--- a/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp
+++ b/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp
@@ -18,6 +18,8 @@
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/condition.hpp>
+
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
@@ -96,7 +98,7 @@ public:
std::size_t imin = std::distance(boost::addressof(d[0]),
std::min_element(d, d + 4));
- if (is_comparable<Strategy>::value)
+ if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
{
return d[imin];
}
diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
index 5bcb5ffaa0..dc1cd74900 100644
--- a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
+++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
@@ -17,7 +17,6 @@
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
@@ -28,7 +27,7 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/math.hpp>
-
+#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
@@ -159,7 +158,7 @@ struct range_collect_vectors
if ( collected_count > 1 )
{
typedef typename boost::range_iterator<Collection>::type c_iterator;
- c_iterator first = collection.begin() + c_old_size;
+ c_iterator first = range::pos(collection, c_old_size);
if ( first->same_direction(collection.back()) )
{
diff --git a/boost/geometry/algorithms/detail/flattening.hpp b/boost/geometry/algorithms/detail/flattening.hpp
new file mode 100644
index 0000000000..8ed5fd9a89
--- /dev/null
+++ b/boost/geometry/algorithms/detail/flattening.hpp
@@ -0,0 +1,69 @@
+// Boost.Geometry
+
+// Copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace detail_dispatch
+{
+
+template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct flattening
+ : not_implemented<Tag>
+{};
+
+template <typename ResultType, typename Geometry>
+struct flattening<ResultType, Geometry, srs_sphere_tag>
+{
+ static inline ResultType apply(Geometry const& /*geometry*/)
+ {
+ return ResultType(0);
+ }
+};
+
+template <typename ResultType, typename Geometry>
+struct flattening<ResultType, Geometry, srs_spheroid_tag>
+{
+ static inline ResultType apply(Geometry const& geometry)
+ {
+ return ResultType(get_radius<0>(geometry) - get_radius<2>(geometry))
+ / ResultType(get_radius<0>(geometry));
+ }
+};
+
+} // namespace detail_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename ResultType, typename Geometry>
+ResultType flattening(Geometry const& geometry)
+{
+ return detail_dispatch::flattening<ResultType, Geometry>::apply(geometry);
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp
index 323ab7c850..d57535e61f 100644
--- a/boost/geometry/algorithms/detail/intersection/interface.hpp
+++ b/boost/geometry/algorithms/detail/intersection/interface.hpp
@@ -223,8 +223,8 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename A), BOOST_VARIANT_ENUM_PARAMS(typename B)>
-struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(A)>, variant<BOOST_VARIANT_ENUM_PARAMS(B)> >
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
+struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
template <typename GeometryOut>
struct visitor: static_visitor<bool>
@@ -255,8 +255,8 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(A)>, variant<BOOST_VARIANT
template <typename GeometryOut>
static inline bool
apply(
- const variant<BOOST_VARIANT_ENUM_PARAMS(A)>& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(B)>& geometry2,
+ 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);
diff --git a/boost/geometry/algorithms/detail/is_simple/areal.hpp b/boost/geometry/algorithms/detail/is_simple/areal.hpp
index 9a1a16507a..623632c44e 100644
--- a/boost/geometry/algorithms/detail/is_simple/areal.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/areal.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
@@ -19,6 +19,7 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
+#include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
@@ -38,11 +39,12 @@ struct is_simple_ring
{
static inline bool apply(Ring const& ring)
{
+ simplicity_failure_policy policy;
return
!detail::is_valid::has_duplicates
<
Ring, geometry::closure<Ring>::value
- >::apply(ring);
+ >::apply(ring, policy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp b/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
index 75c37c68f8..196d89b925 100644
--- a/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.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
@@ -18,6 +18,8 @@
#include <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/range.hpp>
@@ -26,7 +28,8 @@
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/equals.hpp>
-#endif
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#endif // BOOST_GEOMETRY_TEST_DEBUG
namespace boost { namespace geometry
@@ -37,39 +40,67 @@ namespace detail { namespace is_simple
#ifdef BOOST_GEOMETRY_TEST_DEBUG
-template <typename MultiLinestring>
-inline void debug_print_boundary_points(MultiLinestring const& multilinestring)
+template <typename Linear, typename Tag = typename tag<Linear>::type>
+struct debug_boundary_points_printer
+ : not_implemented<Linear>
+{};
+
+template <typename Linestring>
+struct debug_boundary_points_printer<Linestring, linestring_tag>
{
- typedef typename point_type<MultiLinestring>::type point_type;
- typedef std::vector<point_type> point_vector;
+ static inline void apply(Linestring const& linestring)
+ {
+ std::cout << "boundary points: ";
+ std::cout << " " << geometry::dsv(range::front(linestring));
+ std::cout << " " << geometry::dsv(range::back(linestring));
+ std::cout << std::endl << std::endl;
+ }
+};
- point_vector boundary_points;
- for (typename boost::range_iterator<MultiLinestring const>::type it
- = boost::begin(multilinestring);
- it != boost::end(multilinestring); ++it)
+template <typename MultiLinestring>
+struct debug_boundary_points_printer<MultiLinestring, multi_linestring_tag>
+{
+ static inline void apply(MultiLinestring const& multilinestring)
{
- if ( boost::size(*it) > 1
- && !geometry::equals(range::front(*it), range::back(*it)) )
+ typedef typename point_type<MultiLinestring>::type point_type;
+ typedef std::vector<point_type> point_vector;
+
+ point_vector boundary_points;
+ for (typename boost::range_iterator<MultiLinestring const>::type it
+ = boost::begin(multilinestring);
+ it != boost::end(multilinestring); ++it)
{
- boundary_points.push_back( range::front(*it) );
- boundary_points.push_back( range::back(*it) );
+ if ( boost::size(*it) > 1
+ && !geometry::equals(range::front(*it), range::back(*it)) )
+ {
+ boundary_points.push_back( range::front(*it) );
+ boundary_points.push_back( range::back(*it) );
+ }
}
- }
- std::sort(boundary_points.begin(), boundary_points.end(),
- geometry::less<point_type>());
+ std::sort(boundary_points.begin(), boundary_points.end(),
+ geometry::less<point_type>());
- std::cout << "boundary points: ";
- for (typename point_vector::const_iterator pit = boundary_points.begin();
- pit != boundary_points.end(); ++pit)
- {
- std::cout << " " << geometry::dsv(*pit);
+ std::cout << "boundary points: ";
+ for (typename point_vector::const_iterator
+ pit = boundary_points.begin();
+ pit != boundary_points.end(); ++pit)
+ {
+ std::cout << " " << geometry::dsv(*pit);
+ }
+ std::cout << std::endl << std::endl;
}
- std::cout << std::endl << std::endl;
+};
+
+
+template <typename Linear>
+inline void debug_print_boundary_points(Linear const& linear)
+{
+ debug_boundary_points_printer<Linear>::apply(linear);
}
#else
-template <typename MultiLinestring>
-inline void debug_print_boundary_points(MultiLinestring const&)
+template <typename Linear>
+inline void debug_print_boundary_points(Linear const&)
{
}
#endif // BOOST_GEOMETRY_TEST_DEBUG
diff --git a/boost/geometry/algorithms/detail/is_simple/failure_policy.hpp b/boost/geometry/algorithms/detail/is_simple/failure_policy.hpp
new file mode 100644
index 0000000000..6504edd1d5
--- /dev/null
+++ b/boost/geometry/algorithms/detail/is_simple/failure_policy.hpp
@@ -0,0 +1,53 @@
+// 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_IS_SIMPLE_FAILURE_POLICY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP
+
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace is_simple
+{
+
+
+struct simplicity_failure_policy
+{
+ template <validity_failure_type Failure>
+ static inline bool apply()
+ {
+ return Failure == no_failure;
+ }
+
+ template <validity_failure_type Failure, typename Data>
+ static inline bool apply(Data const&)
+ {
+ return apply<Failure>();
+ }
+
+ template <validity_failure_type Failure, typename Data1, typename Data2>
+ static inline bool apply(Data1 const&, Data2 const&)
+ {
+ return apply<Failure>();
+ }
+};
+
+
+}} // namespace detail::is_simple
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP
diff --git a/boost/geometry/algorithms/detail/is_simple/interface.hpp b/boost/geometry/algorithms/detail/is_simple/interface.hpp
index 4239664ed1..fd84826970 100644
--- a/boost/geometry/algorithms/detail/is_simple/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/interface.hpp
@@ -10,8 +10,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP
-#include <boost/variant/static_visitor.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>
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index f2efcb309d..4f3e875eef 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/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.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -19,6 +19,7 @@
#include <boost/geometry/core/closure.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/util/range.hpp>
@@ -29,8 +30,10 @@
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
+#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/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
@@ -40,6 +43,7 @@
#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
#include <boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp>
+#include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp>
#include <boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp>
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
@@ -54,108 +58,211 @@ namespace detail { namespace is_simple
{
-template <typename Linestring, bool CheckSelfIntersections = true>
-struct is_simple_linestring
+template <typename Turn>
+inline bool check_segment_indices(Turn const& turn,
+ signed_index_type last_index)
{
- static inline bool apply(Linestring const& linestring)
+ return
+ (turn.operations[0].seg_id.segment_index == 0
+ && turn.operations[1].seg_id.segment_index == last_index)
+ ||
+ (turn.operations[0].seg_id.segment_index == 0
+ && turn.operations[1].seg_id.segment_index == last_index);
+}
+
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+class is_acceptable_turn
+ : not_implemented<Geometry>
+{};
+
+template <typename Linestring>
+class is_acceptable_turn<Linestring, linestring_tag>
+{
+public:
+ is_acceptable_turn(Linestring const& linestring)
+ : m_linestring(linestring)
+ , m_is_closed(geometry::equals(range::front(linestring),
+ range::back(linestring)))
+ {}
+
+ template <typename Turn>
+ inline bool apply(Turn const& turn) const
{
- return !detail::is_valid::has_duplicates
- <
- Linestring, closed
- >::apply(linestring)
- && !detail::is_valid::has_spikes
- <
- Linestring, closed
- >::apply(linestring)
- && !(CheckSelfIntersections && geometry::intersects(linestring));
+ BOOST_ASSERT(boost::size(m_linestring) > 1);
+ return m_is_closed
+ && turn.method == overlay::method_none
+ && check_segment_indices(turn, boost::size(m_linestring) - 2)
+ && turn.operations[0].fraction.is_zero();
}
-};
-
+private:
+ Linestring const& m_linestring;
+ bool const m_is_closed;
+};
template <typename MultiLinestring>
-class is_simple_multilinestring
+class is_acceptable_turn<MultiLinestring, multi_linestring_tag>
{
private:
- class is_acceptable_turn
+ typedef typename boost::range_value<MultiLinestring>::type linestring_type;
+ typedef is_acceptable_turn<linestring_type> base_type;
+
+ template <typename Point, typename Linestring>
+ static inline bool is_boundary_point_of(Point const& point,
+ Linestring const& linestring)
{
- private:
- template <typename Point, typename Linestring>
- static inline bool is_boundary_point_of(Point const& point,
- Linestring const& linestring)
- {
- BOOST_ASSERT( boost::size(linestring) > 1 );
- return
- !geometry::equals(range::front(linestring),
- range::back(linestring))
- &&
- ( geometry::equals(point, range::front(linestring))
- || geometry::equals(point, range::back(linestring)) );
- }
+ BOOST_ASSERT(boost::size(linestring) > 1);
+ return
+ ! geometry::equals(range::front(linestring),
+ range::back(linestring))
+ &&
+ (geometry::equals(point, range::front(linestring))
+ || geometry::equals(point, range::back(linestring)));
+ }
+
+ template <typename Turn, typename Linestring>
+ static inline bool is_closing_point_of(Turn const& turn,
+ Linestring const& linestring)
+ {
+ BOOST_ASSERT(boost::size(linestring) > 1);
+ return
+ turn.method == overlay::method_none
+ &&
+ check_segment_indices(turn, boost::size(linestring) - 2)
+ &&
+ geometry::equals(range::front(linestring), range::back(linestring))
+ &&
+ turn.operations[0].fraction.is_zero();
+ ;
+ }
+
+ template <typename Linestring1, typename Linestring2>
+ static inline bool have_same_boundary_points(Linestring1 const& ls1,
+ Linestring2 const& ls2)
+ {
+ return
+ geometry::equals(range::front(ls1), range::front(ls2))
+ ?
+ geometry::equals(range::back(ls1), range::back(ls2))
+ :
+ (geometry::equals(range::front(ls1), range::back(ls2))
+ &&
+ geometry::equals(range::back(ls1), range::front(ls2)))
+ ;
+ }
+
+public:
+ is_acceptable_turn(MultiLinestring const& multilinestring)
+ : m_multilinestring(multilinestring)
+ {}
+
+ template <typename Turn>
+ inline bool apply(Turn const& turn) const
+ {
+ linestring_type const& ls1 =
+ range::at(m_multilinestring, turn.operations[0].seg_id.multi_index);
- template <typename Linestring1, typename Linestring2>
- static inline bool have_same_boundary_points(Linestring1 const& ls1,
- Linestring2 const& ls2)
+ linestring_type const& ls2 =
+ range::at(m_multilinestring, turn.operations[1].seg_id.multi_index);
+
+ if (turn.operations[0].seg_id.multi_index
+ == turn.operations[1].seg_id.multi_index)
{
- return
- geometry::equals(range::front(ls1), range::front(ls2))
- ?
- geometry::equals(range::back(ls1), range::back(ls2))
- :
- (geometry::equals(range::front(ls1), range::back(ls2))
- &&
- geometry::equals(range::back(ls1), range::front(ls2))
- )
- ;
+ return is_closing_point_of(turn, ls1);
}
- public:
- is_acceptable_turn(MultiLinestring const& multilinestring)
- : m_multilinestring(multilinestring)
- {}
+ return
+ is_boundary_point_of(turn.point, ls1)
+ && is_boundary_point_of(turn.point, ls2)
+ &&
+ ( boost::size(ls1) != 2
+ || boost::size(ls2) != 2
+ || ! have_same_boundary_points(ls1, ls2) );
+ }
- template <typename Turn>
- inline bool apply(Turn const& turn) const
- {
- typedef typename boost::range_value
+private:
+ MultiLinestring const& m_multilinestring;
+};
+
+
+template <typename Linear>
+inline bool has_self_intersections(Linear const& linear)
+{
+ typedef typename point_type<Linear>::type point_type;
+
+ // compute self turns
+ typedef detail::overlay::turn_info
+ <
+ point_type,
+ geometry::segment_ratio
<
- MultiLinestring
- >::type linestring;
-
- linestring const& ls1 =
- range::at(m_multilinestring,
- turn.operations[0].seg_id.multi_index);
-
- linestring const& ls2 =
- range::at(m_multilinestring,
- turn.operations[1].seg_id.multi_index);
-
- return
- is_boundary_point_of(turn.point, ls1)
- && is_boundary_point_of(turn.point, ls2)
- &&
- ( boost::size(ls1) != 2
- || boost::size(ls2) != 2
- || !have_same_boundary_points(ls1, ls2) );
- }
+ typename geometry::coordinate_type<point_type>::type
+ >
+ > turn_info;
- private:
- MultiLinestring const& m_multilinestring;
- };
+ std::deque<turn_info> turns;
+ typedef detail::overlay::get_turn_info
+ <
+ detail::disjoint::assign_disjoint_policy
+ > turn_policy;
-public:
- static inline bool apply(MultiLinestring const& multilinestring)
+ is_acceptable_turn<Linear> predicate(linear);
+ detail::overlay::predicate_based_interrupt_policy
+ <
+ is_acceptable_turn<Linear>
+ > interrupt_policy(predicate);
+
+ detail::self_get_turn_points::get_turns
+ <
+ turn_policy
+ >::apply(linear,
+ detail::no_rescale_policy(),
+ turns,
+ interrupt_policy);
+
+ detail::is_valid::debug_print_turns(turns.begin(), turns.end());
+ debug_print_boundary_points(linear);
+
+ return interrupt_policy.has_intersections;
+}
+
+
+template <typename Linestring, bool CheckSelfIntersections = true>
+struct is_simple_linestring
+{
+ static inline bool apply(Linestring const& linestring)
{
- typedef typename boost::range_value<MultiLinestring>::type linestring;
- typedef typename point_type<MultiLinestring>::type point_type;
- typedef point_type point;
+ simplicity_failure_policy policy;
+ return ! detail::is_valid::has_duplicates
+ <
+ Linestring, closed
+ >::apply(linestring, policy)
+ && ! detail::is_valid::has_spikes
+ <
+ Linestring, closed
+ >::apply(linestring, policy)
+ && ! (CheckSelfIntersections && has_self_intersections(linestring));
+ }
+};
+template <typename MultiLinestring>
+struct is_simple_multilinestring
+{
+ static inline bool apply(MultiLinestring const& multilinestring)
+ {
// check each of the linestrings for simplicity
- if ( !detail::check_iterator_range
+ // but do not compute self-intersections yet; these will be
+ // computed for the entire multilinestring
+ if ( ! detail::check_iterator_range
<
- is_simple_linestring<linestring>,
+ is_simple_linestring
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ false // do not compute self-intersections
+ >,
false // do not allow empty multilinestring
>::apply(boost::begin(multilinestring),
boost::end(multilinestring))
@@ -164,44 +271,8 @@ public:
return false;
}
-
- // compute self turns
- typedef detail::overlay::turn_info
- <
- point_type,
- geometry::segment_ratio
- <
- typename geometry::coordinate_type<point>::type
- >
- > turn_info;
-
- std::deque<turn_info> turns;
-
- typedef detail::overlay::get_turn_info
- <
- detail::disjoint::assign_disjoint_policy
- > turn_policy;
-
- is_acceptable_turn predicate(multilinestring);
- detail::overlay::predicate_based_interrupt_policy
- <
- is_acceptable_turn
- > interrupt_policy(predicate);
-
- detail::self_get_turn_points::get_turns
- <
- turn_policy
- >::apply(multilinestring,
- detail::no_rescale_policy(),
- turns,
- interrupt_policy);
-
- detail::is_valid::debug_print_turns(turns.begin(), turns.end());
- debug_print_boundary_points(multilinestring);
-
- return !interrupt_policy.has_intersections;
+ return ! has_self_intersections(multilinestring);
}
-
};
diff --git a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
index d996eb64e9..71c9e6ba90 100644
--- a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/multipoint.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
@@ -21,6 +21,7 @@
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>
+#include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp>
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
@@ -48,7 +49,11 @@ struct is_simple_multipoint
std::sort(boost::begin(mp), boost::end(mp),
geometry::less<typename point_type<MultiPoint>::type>());
- return !detail::is_valid::has_duplicates<MultiPoint, closed>::apply(mp);
+ simplicity_failure_policy policy;
+ return !detail::is_valid::has_duplicates
+ <
+ MultiPoint, closed
+ >::apply(mp, policy);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/box.hpp b/boost/geometry/algorithms/detail/is_valid/box.hpp
index f82b3f9bf1..139502af78 100644
--- a/boost/geometry/algorithms/detail/is_valid/box.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/box.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 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
@@ -16,6 +16,7 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
@@ -30,15 +31,22 @@ namespace detail { namespace is_valid
template <typename Box, std::size_t I>
struct has_valid_corners
{
- static inline bool apply(Box const& box)
+ template <typename VisitPolicy>
+ static inline bool apply(Box const& box, VisitPolicy& visitor)
{
- if ( geometry::get<geometry::max_corner, I-1>(box)
- <=
- geometry::get<geometry::min_corner, I-1>(box) )
+ if (math::equals(geometry::get<geometry::min_corner, I-1>(box),
+ geometry::get<geometry::max_corner, I-1>(box)))
{
- return false;
+ return
+ visitor.template apply<failure_wrong_topological_dimension>();
}
- return has_valid_corners<Box, I-1>::apply(box);
+ else if (geometry::get<geometry::min_corner, I-1>(box)
+ >
+ geometry::get<geometry::max_corner, I-1>(box))
+ {
+ return visitor.template apply<failure_wrong_corner_order>();
+ }
+ return has_valid_corners<Box, I-1>::apply(box, visitor);
}
};
@@ -46,9 +54,10 @@ struct has_valid_corners
template <typename Box>
struct has_valid_corners<Box, 0>
{
- static inline bool apply(Box const&)
+ template <typename VisitPolicy>
+ static inline bool apply(Box const&, VisitPolicy& visitor)
{
- return true;
+ return visitor.template apply<no_failure>();
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp b/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp
index 6824921b63..ab99a9921b 100644
--- a/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/debug_print_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.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -25,33 +25,47 @@ namespace detail { namespace is_valid
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
+template <typename Turn>
+inline void debug_print_turn(Turn const& turn)
+{
+ std::cout << " ["
+ << geometry::method_char(turn.method)
+ << ","
+ << geometry::operation_char(turn.operations[0].operation)
+ << "/"
+ << geometry::operation_char(turn.operations[1].operation)
+ << " {"
+ << turn.operations[0].seg_id.multi_index
+ << ", "
+ << turn.operations[1].seg_id.multi_index
+ << "} {"
+ << turn.operations[0].seg_id.ring_index
+ << ", "
+ << turn.operations[1].seg_id.ring_index
+ << "} {"
+ << turn.operations[0].seg_id.segment_index
+ << ", "
+ << turn.operations[1].seg_id.segment_index
+ << "} "
+ << geometry::dsv(turn.point)
+ << "]";
+}
+
template <typename TurnIterator>
inline void debug_print_turns(TurnIterator first, TurnIterator beyond)
{
std::cout << "turns:";
for (TurnIterator tit = first; tit != beyond; ++tit)
{
- std::cout << " ["
- << geometry::method_char(tit->method)
- << ","
- << geometry::operation_char(tit->operations[0].operation)
- << "/"
- << geometry::operation_char(tit->operations[1].operation)
- << " {"
- << tit->operations[0].seg_id.multi_index
- << ", "
- << tit->operations[1].seg_id.multi_index
- << "} {"
- << tit->operations[0].seg_id.ring_index
- << ", "
- << tit->operations[1].seg_id.ring_index
- << "} "
- << geometry::dsv(tit->point)
- << "]";
+ debug_print_turn(*tit);
}
std::cout << std::endl << std::endl;
}
#else
+template <typename Turn>
+inline void debug_print_turn(Turn const&)
+{}
+
template <typename TurnIterator>
inline void debug_print_turns(TurnIterator, TurnIterator)
{}
diff --git a/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp b/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp
index 6f1c263646..a10e0fe596 100644
--- a/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp
@@ -50,8 +50,8 @@ struct debug_validity_phase<Polygon, polygon_tag>
std::cout << "computing and analyzing turns..." << std::endl;
break;
case 4:
- std::cout << "checking if holes are inside the exterior ring..."
- << std::endl;
+ std::cout << "checking if interior rings are inside "
+ << "the exterior ring..." << std::endl;
break;
case 5:
std::cout << "checking connectivity of interior..." << std::endl;
diff --git a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp b/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
index dd0922bb2b..5878841e70 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_duplicates.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
@@ -15,8 +15,10 @@
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/policies/is_valid/default_policy.hpp>
#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
namespace boost { namespace geometry
@@ -30,7 +32,8 @@ namespace detail { namespace is_valid
template <typename Range, closure_selector Closure>
struct has_duplicates
{
- static inline bool apply(Range const& range)
+ template <typename VisitPolicy>
+ static inline bool apply(Range const& range, VisitPolicy& visitor)
{
typedef typename closeable_view<Range const, Closure>::type view_type;
typedef typename boost::range_iterator<view_type const>::type iterator;
@@ -39,7 +42,7 @@ struct has_duplicates
if ( boost::size(view) < 2 )
{
- return false;
+ return ! visitor.template apply<no_failure>();
}
geometry::equal_to<typename boost::range_value<Range>::type> equal;
@@ -50,10 +53,10 @@ struct has_duplicates
{
if ( equal(*it, *next) )
{
- return true;
+ return ! visitor.template apply<failure_duplicate_points>(*it);
}
}
- return false;
+ return ! visitor.template apply<no_failure>();
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
index 9b95017482..090c026e8b 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_spikes.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,15 +13,22 @@
#include <algorithm>
#include <boost/range.hpp>
+#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/policies/is_valid/default_policy.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
+#include <boost/geometry/io/dsv/write.hpp>
namespace boost { namespace geometry
@@ -60,7 +67,7 @@ struct not_equal_to
template <typename OtherPoint>
inline bool operator()(OtherPoint const& other) const
{
- return !geometry::equals(other, m_point);
+ return ! geometry::equals(other, m_point);
}
};
@@ -69,13 +76,17 @@ struct not_equal_to
template <typename Range, closure_selector Closure>
struct has_spikes
{
- static inline bool apply(Range const& range)
+ template <typename VisitPolicy>
+ static inline bool apply(Range const& range, VisitPolicy& visitor)
{
typedef not_equal_to<typename point_type<Range>::type> not_equal;
typedef typename closeable_view<Range const, Closure>::type view_type;
typedef typename boost::range_iterator<view_type const>::type iterator;
+ bool const is_linear
+ = boost::is_same<typename tag<Range>::type, linestring_tag>::value;
+
view_type const view(range);
iterator prev = boost::begin(view);
@@ -85,7 +96,7 @@ struct has_spikes
{
// the range has only one distinct point, so it
// cannot have a spike
- return false;
+ return ! visitor.template apply<no_failure>();
}
iterator next = std::find_if(cur, boost::end(view), not_equal(*cur));
@@ -93,7 +104,7 @@ struct has_spikes
{
// the range has only two distinct points, so it
// cannot have a spike
- return false;
+ return ! visitor.template apply<no_failure>();
}
while ( next != boost::end(view) )
@@ -102,7 +113,8 @@ struct has_spikes
*next,
*cur) )
{
- return true;
+ return
+ ! visitor.template apply<failure_spikes>(is_linear, *cur);
}
prev = cur;
cur = next;
@@ -120,10 +132,18 @@ struct has_spikes
not_equal(range::back(view)));
iterator next =
std::find_if(cur, boost::end(view), not_equal(*cur));
- return detail::point_is_spike_or_equal(*prev, *next, *cur);
+ if (detail::point_is_spike_or_equal(*prev, *next, *cur))
+ {
+ return
+ ! visitor.template apply<failure_spikes>(is_linear, *cur);
+ }
+ else
+ {
+ return ! visitor.template apply<no_failure>();
+ }
}
- return false;
+ return ! visitor.template apply<no_failure>();
}
};
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 220a67bcd1..ecbc4782b2 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
@@ -1,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,6 +10,11 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/policies/predicate_based_interrupt_policy.hpp>
@@ -22,7 +27,6 @@
#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp>
-
namespace boost { namespace geometry
{
@@ -64,8 +68,10 @@ public:
> turn_type;
// returns true if all turns are valid
- template <typename Turns>
- static inline bool apply(Geometry const& geometry, Turns& turns)
+ template <typename Turns, typename VisitPolicy>
+ static inline bool apply(Geometry const& geometry,
+ Turns& turns,
+ VisitPolicy& visitor)
{
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
@@ -80,7 +86,23 @@ public:
turns,
interrupt_policy);
- return !interrupt_policy.has_intersections;
+ if (interrupt_policy.has_intersections)
+ {
+ BOOST_ASSERT(! boost::empty(turns));
+ return visitor.template apply<failure_self_intersections>(turns);
+ }
+ else
+ {
+ return visitor.template apply<no_failure>();
+ }
+ }
+
+ // returns true if all turns are valid
+ template <typename VisitPolicy>
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
+ {
+ std::vector<turn_type> turns;
+ return apply(geometry, turns, visitor);
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp
index 4b232fd436..f83b09c437 100644
--- a/boost/geometry/algorithms/detail/is_valid/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/interface.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,13 +10,19 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP
-#include <boost/variant/static_visitor.hpp>
+#include <sstream>
+#include <string>
+
#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/is_valid.hpp>
+#include <boost/geometry/policies/is_valid/default_policy.hpp>
+#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
+#include <boost/geometry/policies/is_valid/failure_type_policy.hpp>
namespace boost { namespace geometry
@@ -28,48 +34,123 @@ namespace resolve_variant {
template <typename Geometry>
struct is_valid
{
- static inline bool apply(Geometry const& geometry)
+ template <typename VisitPolicy>
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
{
concept::check<Geometry const>();
- return dispatch::is_valid<Geometry>::apply(geometry);
+ return dispatch::is_valid<Geometry>::apply(geometry, visitor);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
+ template <typename VisitPolicy>
struct visitor : boost::static_visitor<bool>
{
+ visitor(VisitPolicy& policy) : m_policy(policy) {}
+
template <typename Geometry>
bool operator()(Geometry const& geometry) const
{
- return is_valid<Geometry>::apply(geometry);
+ return is_valid<Geometry>::apply(geometry, m_policy);
}
+
+ VisitPolicy& m_policy;
};
+ template <typename VisitPolicy>
static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ VisitPolicy& policy_visitor)
{
- return boost::apply_visitor(visitor(), geometry);
+ return boost::apply_visitor(visitor<VisitPolicy>(policy_visitor),
+ geometry);
}
};
} // namespace resolve_variant
+// Undocumented for now
+template <typename Geometry, typename VisitPolicy>
+inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
+{
+ return resolve_variant::is_valid<Geometry>::apply(geometry, visitor);
+}
+
+
/*!
\brief \brief_check{is valid (in the OGC sense)}
\ingroup is_valid
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
-\return \return_check{is valid (in the OGC sense)}
+\return \return_check{is valid (in the OGC sense);
+ furthermore, the following geometries are considered valid:
+ multi-geometries with no elements,
+ linear geometries containing spikes,
+ areal geometries with duplicate (consecutive) points}
\qbk{[include reference/algorithms/is_valid.qbk]}
*/
template <typename Geometry>
inline bool is_valid(Geometry const& geometry)
{
- return resolve_variant::is_valid<Geometry>::apply(geometry);
+ is_valid_default_policy<> policy_visitor;
+ return is_valid(geometry, policy_visitor);
+}
+
+
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\param failure An enumeration value indicating that the geometry is
+ valid or not, and if not valid indicating the reason why
+\return \return_check{is valid (in the OGC sense);
+ furthermore, the following geometries are considered valid:
+ multi-geometries with no elements,
+ linear geometries containing spikes,
+ areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with failure value}
+\qbk{[include reference/algorithms/is_valid_with_failure.qbk]}
+*/
+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);
+ failure = policy_visitor.failure();
+ return result;
+}
+
+
+/*!
+\brief \brief_check{is valid (in the OGC sense)}
+\ingroup is_valid
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\param message A string containing a message stating if the geometry
+ is valid or not, and if not valid a reason why
+\return \return_check{is valid (in the OGC sense);
+ furthermore, the following geometries are considered valid:
+ multi-geometries with no elements,
+ linear geometries containing spikes,
+ areal geometries with duplicate (consecutive) points}
+
+\qbk{distinguish,with message}
+\qbk{[include reference/algorithms/is_valid_with_message.qbk]}
+*/
+template <typename Geometry>
+inline bool is_valid(Geometry const& geometry, std::string& message)
+{
+ std::ostringstream stream;
+ failing_reason_policy<> policy_visitor(stream);
+ bool result = is_valid(geometry, policy_visitor);
+ message = stream.str();
+ return result;
}
diff --git a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
index f9d926770e..0d80d6f6c0 100644
--- a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.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
@@ -72,6 +72,16 @@ template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_acceptable_turn
{};
+template <typename Ring>
+struct is_acceptable_turn<Ring, ring_tag>
+{
+ template <typename Turn>
+ static inline bool apply(Turn const&)
+ {
+ return false;
+ }
+};
+
template <typename Polygon>
class is_acceptable_turn<Polygon, polygon_tag>
{
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index 244df9b035..69243563ec 100644
--- a/boost/geometry/algorithms/detail/is_valid/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 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
@@ -21,6 +21,7 @@
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
#include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
@@ -36,11 +37,18 @@ namespace detail { namespace is_valid
{
-template <typename Linestring, bool AllowSpikes>
+template <typename Linestring>
struct is_valid_linestring
{
- static inline bool apply(Linestring const& linestring)
+ template <typename VisitPolicy>
+ static inline bool apply(Linestring const& linestring,
+ VisitPolicy& visitor)
{
+ if (boost::size(linestring) < 2)
+ {
+ return visitor.template apply<failure_few_points>();
+ }
+
std::size_t num_distinct = detail::num_distinct_consecutive_points
<
Linestring,
@@ -49,14 +57,17 @@ struct is_valid_linestring
not_equal_to<typename point_type<Linestring>::type>
>::apply(linestring);
- if ( num_distinct < 2u )
+ if (num_distinct < 2u)
{
- return false;
+ return
+ visitor.template apply<failure_wrong_topological_dimension>();
}
- return num_distinct == 2u
- || AllowSpikes
- || !has_spikes<Linestring, closed>::apply(linestring);
+ if (num_distinct == 2u)
+ {
+ return visitor.template apply<no_failure>();
+ }
+ return ! has_spikes<Linestring, closed>::apply(linestring, visitor);
}
};
@@ -84,9 +95,11 @@ namespace dispatch
// By default, spikes are disallowed
//
// Reference: OGC 06-103r4 (6.1.6.1)
-template <typename Linestring, bool AllowSpikes>
-struct is_valid<Linestring, linestring_tag, AllowSpikes>
- : detail::is_valid::is_valid_linestring<Linestring, AllowSpikes>
+template <typename Linestring, bool AllowEmptyMultiGeometries>
+struct is_valid
+ <
+ Linestring, linestring_tag, AllowEmptyMultiGeometries
+ > : detail::is_valid::is_valid_linestring<Linestring>
{};
@@ -96,21 +109,47 @@ struct is_valid<Linestring, linestring_tag, AllowSpikes>
// are on the boundaries of both elements.
//
// Reference: OGC 06-103r4 (6.1.8.1; Fig. 9)
-template <typename MultiLinestring, bool AllowSpikes>
-struct is_valid<MultiLinestring, multi_linestring_tag, AllowSpikes>
+template <typename MultiLinestring, bool AllowEmptyMultiGeometries>
+class is_valid
+ <
+ MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries
+ >
{
- static inline bool apply(MultiLinestring const& multilinestring)
+private:
+ template <typename VisitPolicy>
+ struct per_linestring
+ {
+ per_linestring(VisitPolicy& policy) : m_policy(policy) {}
+
+ template <typename Linestring>
+ inline bool apply(Linestring const& linestring) const
+ {
+ return detail::is_valid::is_valid_linestring
+ <
+ Linestring
+ >::apply(linestring, m_policy);
+ }
+
+ VisitPolicy& m_policy;
+ };
+
+public:
+ template <typename VisitPolicy>
+ static inline bool apply(MultiLinestring const& multilinestring,
+ VisitPolicy& visitor)
{
+ if (AllowEmptyMultiGeometries && boost::empty(multilinestring))
+ {
+ return visitor.template apply<no_failure>();
+ }
+
return detail::check_iterator_range
<
- detail::is_valid::is_valid_linestring
- <
- typename boost::range_value<MultiLinestring>::type,
- AllowSpikes
- >,
- false // do not allow empty multilinestring
+ per_linestring<VisitPolicy>,
+ false // do not check for empty multilinestring (done above)
>::apply(boost::begin(multilinestring),
- boost::end(multilinestring));
+ boost::end(multilinestring),
+ per_linestring<VisitPolicy>(visitor));
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 3d0ebb5f82..9362bfca0e 100644
--- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 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
@@ -25,6 +25,7 @@
#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
@@ -49,12 +50,11 @@ namespace detail { namespace is_valid
{
-template <typename MultiPolygon, bool AllowDuplicates>
+template <typename MultiPolygon, bool AllowEmptyMultiGeometries>
class is_valid_multipolygon
: is_valid_polygon
<
typename boost::range_value<MultiPolygon>::type,
- AllowDuplicates,
true // check only the validity of rings
>
{
@@ -62,18 +62,23 @@ private:
typedef is_valid_polygon
<
typename boost::range_value<MultiPolygon>::type,
- AllowDuplicates,
true
> base;
- template <typename PolygonIterator, typename TurnIterator>
+ template
+ <
+ typename PolygonIterator,
+ typename TurnIterator,
+ typename VisitPolicy
+ >
static inline
bool are_polygon_interiors_disjoint(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
- TurnIterator turns_beyond)
+ TurnIterator turns_beyond,
+ VisitPolicy& visitor)
{
// collect all polygons that have turns
std::set<signed_index_type> multi_indices;
@@ -89,22 +94,29 @@ private:
for (PolygonIterator it = polygons_first; it != polygons_beyond;
++it, ++multi_index)
{
- if ( multi_indices.find(multi_index) == multi_indices.end() )
+ if (multi_indices.find(multi_index) == multi_indices.end())
{
polygon_iterators.push_back(it);
}
}
- typename base::item_visitor visitor;
+ typename base::item_visitor_type item_visitor;
geometry::partition
<
geometry::model::box<typename point_type<MultiPolygon>::type>,
typename base::expand_box,
typename base::overlaps_box
- >::apply(polygon_iterators, visitor);
+ >::apply(polygon_iterators, item_visitor);
- return !visitor.items_overlap;
+ if (item_visitor.items_overlap)
+ {
+ return visitor.template apply<failure_intersecting_interiors>();
+ }
+ else
+ {
+ return visitor.template apply<no_failure>();
+ }
}
@@ -132,11 +144,17 @@ private:
template <typename Predicate>
struct has_property_per_polygon
{
- template <typename PolygonIterator, typename TurnIterator>
+ template
+ <
+ typename PolygonIterator,
+ typename TurnIterator,
+ typename VisitPolicy
+ >
static inline bool apply(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
- TurnIterator turns_beyond)
+ TurnIterator turns_beyond,
+ VisitPolicy& visitor)
{
signed_index_type multi_index = 0;
for (PolygonIterator it = polygons_first; it != polygons_beyond;
@@ -157,9 +175,10 @@ private:
turns_beyond,
turns_beyond);
- if ( !Predicate::apply(*it,
+ if (! Predicate::apply(*it,
filtered_turns_first,
- filtered_turns_beyond) )
+ filtered_turns_beyond,
+ visitor))
{
return false;
}
@@ -170,49 +189,82 @@ private:
- template <typename PolygonIterator, typename TurnIterator>
+ template
+ <
+ typename PolygonIterator,
+ typename TurnIterator,
+ typename VisitPolicy
+ >
static inline bool have_holes_inside(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
- TurnIterator turns_beyond)
+ TurnIterator turns_beyond,
+ VisitPolicy& visitor)
{
return has_property_per_polygon
<
typename base::has_holes_inside
>::apply(polygons_first, polygons_beyond,
- turns_first, turns_beyond);
+ turns_first, turns_beyond, visitor);
}
- template <typename PolygonIterator, typename TurnIterator>
+ template
+ <
+ typename PolygonIterator,
+ typename TurnIterator,
+ typename VisitPolicy
+ >
static inline bool have_connected_interior(PolygonIterator polygons_first,
PolygonIterator polygons_beyond,
TurnIterator turns_first,
- TurnIterator turns_beyond)
+ TurnIterator turns_beyond,
+ VisitPolicy& visitor)
{
return has_property_per_polygon
<
typename base::has_connected_interior
>::apply(polygons_first, polygons_beyond,
- turns_first, turns_beyond);
+ turns_first, turns_beyond, visitor);
}
+ template <typename VisitPolicy>
+ struct per_polygon
+ {
+ per_polygon(VisitPolicy& policy) : m_policy(policy) {}
+
+ template <typename Polygon>
+ inline bool apply(Polygon const& polygon) const
+ {
+ return base::apply(polygon, m_policy);
+ }
+
+ VisitPolicy& m_policy;
+ };
public:
- static inline bool apply(MultiPolygon const& multipolygon)
+ template <typename VisitPolicy>
+ static inline bool apply(MultiPolygon const& multipolygon,
+ VisitPolicy& visitor)
{
typedef debug_validity_phase<MultiPolygon> debug_phase;
+ if (AllowEmptyMultiGeometries && boost::empty(multipolygon))
+ {
+ return visitor.template apply<no_failure>();
+ }
+
// check validity of all polygons ring
debug_phase::apply(1);
- if ( !detail::check_iterator_range
+ if (! detail::check_iterator_range
<
- base,
- false // do not allow empty multi-polygons
+ per_polygon<VisitPolicy>,
+ false // do not check for empty multipolygon (done above)
>::apply(boost::begin(multipolygon),
- boost::end(multipolygon)) )
+ boost::end(multipolygon),
+ per_polygon<VisitPolicy>(visitor)))
{
return false;
}
@@ -224,10 +276,11 @@ public:
typedef has_valid_self_turns<MultiPolygon> has_valid_turns;
std::deque<typename has_valid_turns::turn_type> turns;
- bool has_invalid_turns = !has_valid_turns::apply(multipolygon, turns);
+ bool has_invalid_turns =
+ ! has_valid_turns::apply(multipolygon, turns, visitor);
debug_print_turns(turns.begin(), turns.end());
- if ( has_invalid_turns )
+ if (has_invalid_turns)
{
return false;
}
@@ -237,10 +290,11 @@ public:
// exterior and not one inside the other
debug_phase::apply(3);
- if ( !have_holes_inside(boost::begin(multipolygon),
+ if (! have_holes_inside(boost::begin(multipolygon),
boost::end(multipolygon),
turns.begin(),
- turns.end()) )
+ turns.end(),
+ visitor))
{
return false;
}
@@ -249,10 +303,11 @@ public:
// check that each polygon's interior is connected
debug_phase::apply(4);
- if ( !have_connected_interior(boost::begin(multipolygon),
+ if (! have_connected_interior(boost::begin(multipolygon),
boost::end(multipolygon),
turns.begin(),
- turns.end()) )
+ turns.end(),
+ visitor))
{
return false;
}
@@ -263,7 +318,8 @@ public:
return are_polygon_interiors_disjoint(boost::begin(multipolygon),
boost::end(multipolygon),
turns.begin(),
- turns.end());
+ turns.end(),
+ visitor);
}
};
@@ -282,9 +338,14 @@ namespace dispatch
// that the MultiPolygon is also valid.
//
// Reference (for validity of MultiPolygons): OGC 06-103r4 (6.1.14)
-template <typename MultiPolygon, bool AllowSpikes, bool AllowDuplicates>
-struct is_valid<MultiPolygon, multi_polygon_tag, AllowSpikes, AllowDuplicates>
- : detail::is_valid::is_valid_multipolygon<MultiPolygon, AllowDuplicates>
+template <typename MultiPolygon, bool AllowEmptyMultiGeometries>
+struct is_valid
+ <
+ MultiPolygon, multi_polygon_tag, AllowEmptyMultiGeometries
+ > : detail::is_valid::is_valid_multipolygon
+ <
+ MultiPolygon, AllowEmptyMultiGeometries
+ >
{};
diff --git a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
index 8a4818ef15..8e5ebaadcc 100644
--- a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 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
@@ -14,6 +14,7 @@
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
@@ -30,9 +31,10 @@ namespace dispatch
template <typename Point>
struct is_valid<Point, point_tag>
{
- static inline bool apply(Point const&)
+ template <typename VisitPolicy>
+ static inline bool apply(Point const&, VisitPolicy& visitor)
{
- return true;
+ return visitor.template apply<no_failure>();
}
};
@@ -42,12 +44,24 @@ struct is_valid<Point, point_tag>
// (have identical coordinate values in X and Y)
//
// Reference: OGC 06-103r4 (6.1.5)
-template <typename MultiPoint>
-struct is_valid<MultiPoint, multi_point_tag>
+template <typename MultiPoint, bool AllowEmptyMultiGeometries>
+struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries>
{
- static inline bool apply(MultiPoint const& multipoint)
+ template <typename VisitPolicy>
+ static inline bool apply(MultiPoint const& multipoint,
+ VisitPolicy& visitor)
{
- return boost::size(multipoint) > 0;
+ if (AllowEmptyMultiGeometries || boost::size(multipoint) > 0)
+ {
+ // we allow empty multi-geometries, so an empty multipoint
+ // is considered valid
+ return visitor.template apply<no_failure>();
+ }
+ else
+ {
+ // we do not allow an empty multipoint
+ return visitor.template apply<failure_few_points>();
+ }
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index 3a91999208..17eefd226f 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.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
@@ -26,6 +26,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>
@@ -36,6 +37,7 @@
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
@@ -62,51 +64,58 @@ namespace detail { namespace is_valid
{
-template
-<
- typename Polygon,
- bool AllowDuplicates,
- bool CheckRingValidityOnly = false
->
+template <typename Polygon, bool CheckRingValidityOnly = false>
class is_valid_polygon
{
protected:
typedef debug_validity_phase<Polygon> debug_phase;
+ template <typename VisitPolicy>
+ struct per_ring
+ {
+ per_ring(VisitPolicy& policy) : m_policy(policy) {}
+
+ template <typename Ring>
+ inline bool apply(Ring const& ring) const
+ {
+ return detail::is_valid::is_valid_ring
+ <
+ Ring, false, true
+ >::apply(ring, m_policy);
+ }
+ VisitPolicy& m_policy;
+ };
- template <typename InteriorRings>
- static bool has_valid_interior_rings(InteriorRings const& interior_rings)
+ template <typename InteriorRings, typename VisitPolicy>
+ static bool has_valid_interior_rings(InteriorRings const& interior_rings,
+ VisitPolicy& visitor)
{
return
detail::check_iterator_range
<
- detail::is_valid::is_valid_ring
- <
- typename boost::range_value<InteriorRings>::type,
- AllowDuplicates,
- false, // do not check self-intersections
- true // indicate that the ring is interior
- >
+ per_ring<VisitPolicy>,
+ true // allow for empty interior ring range
>::apply(boost::begin(interior_rings),
- boost::end(interior_rings));
+ boost::end(interior_rings),
+ per_ring<VisitPolicy>(visitor));
}
struct has_valid_rings
{
- static inline bool apply(Polygon const& polygon)
+ template <typename VisitPolicy>
+ static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
{
typedef typename ring_type<Polygon>::type ring_type;
// check validity of exterior ring
debug_phase::apply(1);
- if ( !detail::is_valid::is_valid_ring
+ if (! detail::is_valid::is_valid_ring
<
ring_type,
- AllowDuplicates,
false // do not check self intersections
- >::apply(exterior_ring(polygon)) )
+ >::apply(exterior_ring(polygon), visitor))
{
return false;
}
@@ -114,12 +123,13 @@ protected:
// check validity of interior rings
debug_phase::apply(2);
- return has_valid_interior_rings(geometry::interior_rings(polygon));
+ return has_valid_interior_rings(geometry::interior_rings(polygon),
+ visitor);
}
};
- // structs from partition -- start
+ // structs for partition -- start
struct expand_box
{
template <typename Box, typename Iterator>
@@ -135,24 +145,24 @@ protected:
template <typename Box, typename Iterator>
static inline bool apply(Box const& box, Iterator const& it)
{
- return !geometry::disjoint(*it, box);
+ return ! geometry::disjoint(*it, box);
}
};
- struct item_visitor
+ struct item_visitor_type
{
bool items_overlap;
- item_visitor() : items_overlap(false) {}
+ item_visitor_type() : items_overlap(false) {}
template <typename Item1, typename Item2>
inline void apply(Item1 const& item1, Item2 const& item2)
{
- if ( !items_overlap
- && (geometry::within(*points_begin(*item1), *item2)
- || geometry::within(*points_begin(*item2), *item1))
- )
+ if (! items_overlap
+ && (geometry::within(*points_begin(*item1), *item2)
+ || geometry::within(*points_begin(*item2), *item1))
+ )
{
items_overlap = true;
}
@@ -165,27 +175,29 @@ protected:
<
typename RingIterator,
typename ExteriorRing,
- typename TurnIterator
+ typename TurnIterator,
+ typename VisitPolicy
>
static inline bool are_holes_inside(RingIterator rings_first,
RingIterator rings_beyond,
ExteriorRing const& exterior_ring,
TurnIterator turns_first,
- TurnIterator turns_beyond)
+ TurnIterator turns_beyond,
+ VisitPolicy& visitor)
{
// collect the interior ring indices that have turns with the
// exterior ring
std::set<signed_index_type> ring_indices;
for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)
{
- if ( tit->operations[0].seg_id.ring_index == -1 )
+ if (tit->operations[0].seg_id.ring_index == -1)
{
- BOOST_ASSERT( tit->operations[1].seg_id.ring_index != -1 );
+ BOOST_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 )
+ else if (tit->operations[1].seg_id.ring_index == -1)
{
- BOOST_ASSERT( tit->operations[0].seg_id.ring_index != -1 );
+ BOOST_ASSERT(tit->operations[0].seg_id.ring_index != -1);
ring_indices.insert(tit->operations[0].seg_id.ring_index);
}
}
@@ -196,10 +208,10 @@ protected:
{
// do not examine interior rings that have turns with the
// exterior ring
- if ( ring_indices.find(ring_index) == ring_indices.end()
- && !geometry::covered_by(range::front(*it), exterior_ring) )
+ if (ring_indices.find(ring_index) == ring_indices.end()
+ && ! geometry::covered_by(range::front(*it), exterior_ring))
{
- return false;
+ return visitor.template apply<failure_interior_rings_outside>();
}
}
@@ -216,7 +228,7 @@ protected:
for (RingIterator it = rings_first; it != rings_beyond;
++it, ++ring_index)
{
- if ( ring_indices.find(ring_index) == ring_indices.end() )
+ if (ring_indices.find(ring_index) == ring_indices.end())
{
ring_iterators.push_back(it);
}
@@ -224,47 +236,59 @@ protected:
// call partition to check is interior rings are disjoint from
// each other
- item_visitor visitor;
+ item_visitor_type item_visitor;
geometry::partition
<
geometry::model::box<typename point_type<Polygon>::type>,
expand_box,
overlaps_box
- >::apply(ring_iterators, visitor);
+ >::apply(ring_iterators, item_visitor);
- return !visitor.items_overlap;
+ if (item_visitor.items_overlap)
+ {
+ return visitor.template apply<failure_nested_interior_rings>();
+ }
+ else
+ {
+ return visitor.template apply<no_failure>();
+ }
}
template
<
typename InteriorRings,
typename ExteriorRing,
- typename TurnIterator
+ typename TurnIterator,
+ typename VisitPolicy
>
static inline bool are_holes_inside(InteriorRings const& interior_rings,
ExteriorRing const& exterior_ring,
TurnIterator first,
- TurnIterator beyond)
+ TurnIterator beyond,
+ VisitPolicy& visitor)
{
return are_holes_inside(boost::begin(interior_rings),
boost::end(interior_rings),
exterior_ring,
first,
- beyond);
+ beyond,
+ visitor);
}
struct has_holes_inside
{
- template <typename TurnIterator>
+ template <typename TurnIterator, typename VisitPolicy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
- TurnIterator beyond)
+ TurnIterator beyond,
+ VisitPolicy& visitor)
{
return are_holes_inside(geometry::interior_rings(polygon),
geometry::exterior_ring(polygon),
first,
- beyond);
+ beyond,
+ visitor);
}
};
@@ -273,10 +297,11 @@ protected:
struct has_connected_interior
{
- template <typename TurnIterator>
+ template <typename TurnIterator, typename VisitPolicy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
- TurnIterator beyond)
+ TurnIterator beyond,
+ VisitPolicy& visitor)
{
typedef typename std::iterator_traits
<
@@ -299,19 +324,27 @@ protected:
debug_print_complement_graph(std::cout, g);
- return !g.has_cycles();
+ if (g.has_cycles())
+ {
+ return visitor.template apply<failure_disconnected_interior>();
+ }
+ else
+ {
+ return visitor.template apply<no_failure>();
+ }
}
};
public:
- static inline bool apply(Polygon const& polygon)
+ template <typename VisitPolicy>
+ static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
{
- if ( !has_valid_rings::apply(polygon) )
+ if (! has_valid_rings::apply(polygon, visitor))
{
return false;
}
- if ( CheckRingValidityOnly )
+ if (BOOST_GEOMETRY_CONDITION(CheckRingValidityOnly))
{
return true;
}
@@ -322,10 +355,11 @@ public:
typedef has_valid_self_turns<Polygon> has_valid_turns;
std::deque<typename has_valid_turns::turn_type> turns;
- bool has_invalid_turns = !has_valid_turns::apply(polygon, turns);
+ bool has_invalid_turns
+ = ! has_valid_turns::apply(polygon, turns, visitor);
debug_print_turns(turns.begin(), turns.end());
- if ( has_invalid_turns )
+ if (has_invalid_turns)
{
return false;
}
@@ -333,7 +367,9 @@ public:
// check if all interior rings are inside the exterior ring
debug_phase::apply(4);
- if ( !has_holes_inside::apply(polygon, turns.begin(), turns.end()) )
+ if (! has_holes_inside::apply(polygon,
+ turns.begin(), turns.end(),
+ visitor))
{
return false;
}
@@ -343,7 +379,8 @@ public:
return has_connected_interior::apply(polygon,
turns.begin(),
- turns.end());
+ turns.end(),
+ visitor);
}
};
@@ -361,9 +398,11 @@ namespace dispatch
// A Polygon is always a simple geometric object provided that it is valid.
//
// Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1)
-template <typename Polygon, bool AllowSpikes, bool AllowDuplicates>
-struct is_valid<Polygon, polygon_tag, AllowSpikes, AllowDuplicates>
- : detail::is_valid::is_valid_polygon<Polygon, AllowDuplicates>
+template <typename Polygon, bool AllowEmptyMultiGeometries>
+struct is_valid
+ <
+ Polygon, polygon_tag, AllowEmptyMultiGeometries
+ > : detail::is_valid::is_valid_polygon<Polygon>
{};
diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp
index c88df79b05..c663a96d28 100644
--- a/boost/geometry/algorithms/detail/is_valid/ring.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 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,6 +10,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP
+#include <deque>
+
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_order.hpp>
@@ -19,16 +21,22 @@
#include <boost/geometry/algorithms/equals.hpp>
-#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
+#include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>
+#include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp>
#include <boost/geometry/strategies/area.hpp>
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#include <boost/geometry/io/dsv/write.hpp>
+#endif
+
namespace boost { namespace geometry
{
@@ -42,18 +50,27 @@ namespace detail { namespace is_valid
template <typename Ring, closure_selector Closure /* open */>
struct is_topologically_closed
{
- static inline bool apply(Ring const&)
+ template <typename VisitPolicy>
+ static inline bool apply(Ring const&, VisitPolicy& visitor)
{
- return true;
+ return visitor.template apply<no_failure>();
}
};
template <typename Ring>
struct is_topologically_closed<Ring, closed>
{
- static inline bool apply(Ring const& ring)
+ template <typename VisitPolicy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor)
{
- return geometry::equals(range::front(ring), range::back(ring));
+ if (geometry::equals(range::front(ring), range::back(ring)))
+ {
+ return visitor.template apply<no_failure>();
+ }
+ else
+ {
+ return visitor.template apply<failure_not_closed>();
+ }
}
};
@@ -92,7 +109,8 @@ struct is_properly_oriented
typedef typename default_area_result<Ring>::type area_result_type;
- static inline bool apply(Ring const& ring)
+ template <typename VisitPolicy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor)
{
typename ring_area_predicate
<
@@ -101,7 +119,14 @@ struct is_properly_oriented
// Check area
area_result_type const zero = area_result_type();
- return predicate(ring_area_type::apply(ring, strategy_type()), zero);
+ if (predicate(ring_area_type::apply(ring, strategy_type()), zero))
+ {
+ return visitor.template apply<no_failure>();
+ }
+ else
+ {
+ return visitor.template apply<failure_wrong_orientation>();
+ }
}
};
@@ -110,41 +135,60 @@ struct is_properly_oriented
template
<
typename Ring,
- bool AllowDuplicates,
bool CheckSelfIntersections = true,
bool IsInteriorRing = false
>
struct is_valid_ring
{
- static inline bool apply(Ring const& ring)
+ template <typename VisitPolicy>
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor)
{
// return invalid if any of the following condition holds:
// (a) the ring's size is below the minimal one
- // (b) the ring is not topologically closed
- // (c) the ring has spikes
- // (d) the ring has duplicate points (if AllowDuplicates is false)
- // (e) the boundary of the ring has self-intersections
- // (f) the order of the points is inconsistent with the defined order
+ // (b) the ring consists of at most two distinct points
+ // (c) the ring is not topologically closed
+ // (d) the ring has spikes
+ // (e) the ring has duplicate points (if AllowDuplicates is false)
+ // (f) the boundary of the ring has self-intersections
+ // (g) the order of the points is inconsistent with the defined order
//
// Note: no need to check if the area is zero. If this is the
// case, then the ring must have at least two spikes, which is
// checked by condition (c).
closure_selector const closure = geometry::closure<Ring>::value;
+ typedef typename closeable_view<Ring const, closure>::type view_type;
+
+ if (boost::size(ring)
+ < core_detail::closure::minimum_ring_size<closure>::value)
+ {
+ return visitor.template apply<failure_few_points>();
+ }
+
+ view_type const view(ring);
+ if (detail::num_distinct_consecutive_points
+ <
+ view_type, 4u, true,
+ not_equal_to<typename point_type<Ring>::type>
+ >::apply(view)
+ < 4u)
+ {
+ return
+ visitor.template apply<failure_wrong_topological_dimension>();
+ }
return
- ( boost::size(ring)
- >= core_detail::closure::minimum_ring_size<closure>::value )
- && is_topologically_closed<Ring, closure>::apply(ring)
- && (AllowDuplicates || !has_duplicates<Ring, closure>::apply(ring))
- && !has_spikes<Ring, closure>::apply(ring)
- && !(CheckSelfIntersections && geometry::intersects(ring))
- && is_properly_oriented<Ring, IsInteriorRing>::apply(ring);
+ is_topologically_closed<Ring, closure>::apply(ring, visitor)
+ && ! has_duplicates<Ring, closure>::apply(ring, visitor)
+ && ! has_spikes<Ring, closure>::apply(ring, visitor)
+ && (! CheckSelfIntersections
+ || has_valid_self_turns<Ring>::apply(ring, visitor))
+ && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor);
}
};
-}} // namespace dispatch
+}} // namespace detail::is_valid
#endif // DOXYGEN_NO_DETAIL
@@ -158,9 +202,11 @@ namespace dispatch
// 6.1.7.1, for the definition of LinearRing)
//
// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)
-template <typename Ring, bool AllowSpikes, bool AllowDuplicates>
-struct is_valid<Ring, ring_tag, AllowSpikes, AllowDuplicates>
- : detail::is_valid::is_valid_ring<Ring, AllowDuplicates>
+template <typename Ring, bool AllowEmptyMultiGeometries>
+struct is_valid
+ <
+ Ring, ring_tag, AllowEmptyMultiGeometries
+ > : detail::is_valid::is_valid_ring<Ring>
{};
diff --git a/boost/geometry/algorithms/detail/is_valid/segment.hpp b/boost/geometry/algorithms/detail/is_valid/segment.hpp
index 486289dabe..0b60890dc0 100644
--- a/boost/geometry/algorithms/detail/is_valid/segment.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/segment.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 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
@@ -15,6 +15,7 @@
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
@@ -40,13 +41,22 @@ namespace dispatch
template <typename Segment>
struct is_valid<Segment, segment_tag>
{
- static inline bool apply(Segment const& segment)
+ template <typename VisitPolicy>
+ static inline bool apply(Segment const& segment, VisitPolicy& 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]);
- return !geometry::equals(p[0], p[1]);
+ if(! geometry::equals(p[0], p[1]))
+ {
+ return visitor.template apply<no_failure>();
+ }
+ else
+ {
+ return
+ visitor.template apply<failure_wrong_topological_dimension>();
+ }
}
};
diff --git a/boost/geometry/algorithms/detail/not.hpp b/boost/geometry/algorithms/detail/not.hpp
index abc3a4e168..43e71e2e37 100644
--- a/boost/geometry/algorithms/detail/not.hpp
+++ b/boost/geometry/algorithms/detail/not.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.
@@ -32,10 +37,12 @@ namespace detail
\param geometry2 \param_geometry
\return Negation of the result of the policy
*/
-template <typename Geometry1, typename Geometry2, typename Policy>
+template <typename Policy>
struct not_
{
- static inline bool apply(Geometry1 const &geometry1, Geometry2 const& geometry2)
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
{
return ! Policy::apply(geometry1, geometry2);
}
diff --git a/boost/geometry/algorithms/detail/occupation_info.hpp b/boost/geometry/algorithms/detail/occupation_info.hpp
index d90f3cf7cf..002c946170 100644
--- a/boost/geometry/algorithms/detail/occupation_info.hpp
+++ b/boost/geometry/algorithms/detail/occupation_info.hpp
@@ -57,6 +57,12 @@ class occupation_info
public :
typedef std::vector<AngleInfo> collection_type;
+ int count;
+
+ inline occupation_info()
+ : count(0)
+ {}
+
template <typename RobustPoint>
inline void add(RobustPoint const& incoming_point,
RobustPoint const& outgoing_point,
diff --git a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
index d44db17ad3..285edfdd6c 100644
--- a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
+++ b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
@@ -20,6 +20,7 @@
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
@@ -42,7 +43,7 @@ inline bool points_equal_or_close(Point1 const& point1,
return true;
}
- if (! RobustPolicy::enabled)
+ if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled))
{
return false;
}
@@ -127,7 +128,7 @@ inline void clean_closing_dups_and_spikes(Range& range,
iterator_type first = boost::begin(range);
iterator_type second = first + 1;
iterator_type ultimate = boost::end(range) - 1;
- if (closed)
+ if (BOOST_GEOMETRY_CONDITION(closed))
{
ultimate--;
}
@@ -137,7 +138,7 @@ inline void clean_closing_dups_and_spikes(Range& range,
if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy))
{
range::erase(range, first);
- if (closed)
+ if (BOOST_GEOMETRY_CONDITION(closed))
{
// Remove closing last point
range::resize(range, boost::size(range) - 1);
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index 67b48cc471..178f3825d7 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -18,11 +18,6 @@
#include <boost/geometry/geometries/box.hpp>
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
-# include <boost/timer.hpp>
-#endif
-
-
namespace boost { namespace geometry
{
@@ -186,11 +181,6 @@ inline void assign_parents(Geometry1 const& geometry1,
typedef std::vector<helper> vector_type;
typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- boost::timer timer;
-#endif
-
-
std::size_t count_total = ring_map.size();
std::size_t count_positive = 0;
std::size_t index_positive = 0; // only used if count_positive>0
@@ -226,10 +216,6 @@ inline void assign_parents(Geometry1 const& geometry1,
}
}
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << " ap: created helper vector: " << timer.elapsed() << std::endl;
-#endif
-
if (! check_for_orientation)
{
if (count_positive == count_total)
@@ -272,11 +258,6 @@ inline void assign_parents(Geometry1 const& geometry1,
<
box_type, ring_info_helper_get_box, ring_info_helper_ovelaps_box
>::apply(vector, visitor);
-
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << " ap: quadradic loop: " << timer.elapsed() << std::endl;
- std::cout << " ap: check_for_orientation " << check_for_orientation << std::endl;
-#endif
}
if (check_for_orientation)
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
index 20a6d7f48d..13e0a5a51e 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
@@ -11,6 +11,7 @@
#include <boost/array.hpp>
+#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
@@ -21,8 +22,7 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/range.hpp>
-#include <boost/geometry/views/closeable_view.hpp>
-#include <boost/geometry/views/reversible_view.hpp>
+#include <boost/geometry/views/detail/normalized_view.hpp>
namespace boost { namespace geometry
@@ -37,41 +37,24 @@ namespace detail { namespace copy_segments
template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>
struct copy_segment_point_range
{
- typedef typename closeable_view
- <
- Range const,
- closure<Range>::value
- >::type cview_type;
-
- typedef typename reversible_view
- <
- cview_type const,
- Reverse ? iterate_reverse : iterate_forward
- >::type rview_type;
-
static inline bool apply(Range const& range,
SegmentIdentifier const& seg_id, bool second,
PointOut& point)
{
+ detail::normalized_view<Range const> view(range);
+
+ signed_index_type const n = boost::size(view);
signed_index_type index = seg_id.segment_index;
if (second)
{
index++;
- if (index >= int(boost::size(range)))
+ if (index >= n)
{
index = 0;
}
}
- // Exception?
- if (index >= int(boost::size(range)))
- {
- return false;
- }
-
- cview_type cview(range);
- rview_type view(cview);
-
+ BOOST_ASSERT(index >= 0 && index < n);
geometry::convert(*(boost::begin(view) + index), point);
return true;
@@ -323,6 +306,8 @@ 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);
+
if (seg_id.source_index == 0)
{
return dispatch::copy_segment_point
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
index 9484479b45..7ed93f542a 100644
--- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -56,13 +56,13 @@ struct indexed_turn_operation
TurnOperation const* subject;
inline indexed_turn_operation(std::size_t ti, std::size_t oi,
- TurnOperation const& s,
+ TurnOperation const& sub,
segment_identifier const& oid)
: turn_index(ti)
, operation_index(oi)
, discarded(false)
, other_seg_id(&oid)
- , subject(&s)
+ , subject(boost::addressof(sub))
{}
};
@@ -114,6 +114,12 @@ private :
typedef typename geometry::point_type<Geometry1>::type point_type;
+ inline bool default_order(Indexed const& left, Indexed const& right) const
+ {
+ // We've nothing to sort on. Take the indexes
+ return left.turn_index < right.turn_index;
+ }
+
inline bool consider_relative_order(Indexed const& left,
Indexed const& right) const
{
@@ -148,7 +154,12 @@ private :
// If they both turn left: the most left as last
// If they both turn right: this is not relevant, but take also here most left
- return side_rj_s < side_sj_r;
+ if (side_rj_s != side_sj_r)
+ {
+ return side_rj_s < side_sj_r;
+ }
+
+ return default_order(left, right);
}
public :
@@ -157,30 +168,32 @@ public :
// but to the "indexed_turn_operation"
inline bool operator()(Indexed const& left, Indexed const& right) const
{
- segment_identifier const& sl = left.subject->seg_id;
- segment_identifier const& sr = right.subject->seg_id;
+ if (! (left.subject->seg_id == right.subject->seg_id))
+ {
+ return left.subject->seg_id < right.subject->seg_id;
+ }
+
+ // Both left and right are located on the SAME segment.
- if (sl == sr)
+ if (! (left.subject->fraction == right.subject->fraction))
{
- // Both left and right are located on the SAME segment.
- if (left.subject->fraction == right.subject->fraction)
- {
- // First check "real" intersection (crosses)
- // -> distance zero due to precision, solve it by sorting
- if (m_turn_points[left.turn_index].method == method_crosses
- && m_turn_points[right.turn_index].method == method_crosses)
- {
- return consider_relative_order(left, right);
- }
+ return left.subject->fraction < right.subject->fraction;
+ }
- // If that is not the case, cluster it later on.
- // Indicate that this is necessary.
- *m_clustered = true;
- }
+
+ // First check "real" intersection (crosses)
+ // -> distance zero due to precision, solve it by sorting
+ if (m_turn_points[left.turn_index].method == method_crosses
+ && m_turn_points[right.turn_index].method == method_crosses)
+ {
+ return consider_relative_order(left, right);
}
- return sl == sr
- ? left.subject->fraction < right.subject->fraction
- : sl < sr;
+
+ // If that is not the case, cluster it later on.
+ // Indicate that this is necessary.
+ *m_clustered = true;
+
+ return default_order(left, right);
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
index 85378e08b0..7bcc0b951e 100644
--- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
@@ -35,6 +35,23 @@
namespace boost { namespace geometry
{
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
+class inconsistent_turns_exception : public geometry::exception
+{
+public:
+
+ inline inconsistent_turns_exception() {}
+
+ virtual ~inconsistent_turns_exception() throw()
+ {}
+
+ virtual char const* what() const throw()
+ {
+ return "Boost.Geometry Inconsistent Turns exception";
+ }
+};
+#endif
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
@@ -304,7 +321,14 @@ public:
oit);
}
- BOOST_ASSERT( enter_count == 0 );
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
+ if (enter_count != 0)
+ {
+ throw inconsistent_turns_exception();
+ }
+#else
+ BOOST_ASSERT(enter_count == 0);
+#endif
return process_end(entered, linestring,
current_segment_id, current_piece,
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index 240b6de036..b3b1a06f68 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -2,6 +2,11 @@
// 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)
@@ -11,6 +16,8 @@
#include <boost/assert.hpp>
+#include <boost/core/ignore_unused.hpp>
+
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@@ -104,17 +111,19 @@ struct base_turn_handler
template <typename TurnInfo, typename IntersectionInfo>
static inline void assign_point(TurnInfo& ti,
method_type method,
- IntersectionInfo const& info, int index)
+ IntersectionInfo const& info, unsigned int index)
{
ti.method = method;
- BOOST_ASSERT(index >= 0 && unsigned(index) < info.count); // TODO remove this
+
+ BOOST_ASSERT(index < info.count);
+
geometry::convert(info.intersections[index], ti.point);
ti.operations[0].fraction = info.fractions[index].robust_ra;
ti.operations[1].fraction = info.fractions[index].robust_rb;
}
template <typename IntersectionInfo>
- static inline int non_opposite_to_index(IntersectionInfo const& info)
+ static inline unsigned int non_opposite_to_index(IntersectionInfo const& info)
{
return info.fractions[0].robust_rb < info.fractions[1].robust_rb
? 1 : 0;
@@ -132,7 +141,7 @@ struct touch_interior : public base_turn_handler
// Index: 0, P is the interior, Q is touching and vice versa
template
<
- int Index,
+ unsigned int Index,
typename Point1,
typename Point2,
typename IntersectionInfo,
@@ -155,8 +164,9 @@ struct touch_interior : public base_turn_handler
// 2) Important is: if q_k goes to LEFT, RIGHT, COLLINEAR
// and, if LEFT/COLL, if it is lying LEFT or RIGHT w.r.t. q_i
- static int const index_p = Index;
- static int const index_q = 1 - Index;
+ BOOST_STATIC_ASSERT(Index <= 1);
+ static unsigned int const index_p = Index;
+ static unsigned int const index_q = 1 - Index;
int const side_qi_p = dir_info.sides.template get<index_q, 0>();
int const side_qk_p = side.qk_wrt_p1();
@@ -166,7 +176,7 @@ struct touch_interior : public base_turn_handler
// Q crosses P from left->right or from right->left (test "ML1")
// Union: folow P (left->right) or Q (right->left)
// Intersection: other turn
- int index = side_qk_p == -1 ? index_p : index_q;
+ unsigned int index = side_qk_p == -1 ? index_p : index_q;
ti.operations[index].operation = operation_union;
ti.operations[1 - index].operation = operation_intersection;
return;
@@ -193,7 +203,7 @@ struct touch_interior : public base_turn_handler
// or Q turns right on the right side of P (test "MR2")
// Union: take left turn (Q if Q turns left, P if Q turns right)
// Intersection: other turn
- int index = side_qk_q == 1 ? index_q : index_p;
+ unsigned int index = side_qk_q == 1 ? index_q : index_p;
ti.operations[index].operation = operation_union;
ti.operations[1 - index].operation = operation_intersection;
}
@@ -215,10 +225,10 @@ struct touch_interior : public base_turn_handler
// Opposite direction, which is never travelled.
// If Q turns left, P continues for intersection
// If Q turns right, P continues for union
- ti.operations[Index].operation = side_qk_q == 1
+ ti.operations[index_p].operation = side_qk_q == 1
? operation_intersection
: operation_union;
- ti.operations[1 - Index].operation = operation_blocked;
+ ti.operations[index_q].operation = operation_blocked;
}
}
else
@@ -503,27 +513,25 @@ struct equal_opposite : public base_turn_handler
typename Point1,
typename Point2,
typename OutputIterator,
- typename IntersectionInfo,
- typename DirInfo
+ typename IntersectionInfo
>
static inline void apply(Point1 const& pi, Point2 const& qi,
/* by value: */ TurnInfo tp,
OutputIterator& out,
- IntersectionInfo const& intersection_info,
- DirInfo const& dir_info)
+ IntersectionInfo const& intersection_info)
{
// For equal-opposite segments, normally don't do anything.
if (AssignPolicy::include_opposite)
{
tp.method = method_equal;
- for (int i = 0; i < 2; i++)
+ for (unsigned int i = 0; i < 2; i++)
{
tp.operations[i].operation = operation_opposite;
}
- for (unsigned int i = 0; i < intersection_info.count; i++)
+ for (unsigned int i = 0; i < intersection_info.i_info().count; i++)
{
- assign_point(tp, method_none, intersection_info, i);
- AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ assign_point(tp, method_none, intersection_info.i_info(), i);
+ AssignPolicy::apply(tp, pi, qi, intersection_info);
*out++ = tp;
}
}
@@ -653,7 +661,7 @@ private :
template
<
- int Index,
+ unsigned int Index,
typename Point1,
typename Point2,
typename IntersectionInfo
@@ -663,8 +671,9 @@ private :
Point2 const& , Point2 const& , int side_rk_s,
TurnInfo& tp, IntersectionInfo const& intersection_info)
{
- boost::ignore_unused_variable_warning(handle_robustness);
- boost::ignore_unused_variable_warning(side_rk_s);
+ BOOST_STATIC_ASSERT(Index <= 1);
+
+ boost::ignore_unused(handle_robustness, side_rk_s);
operation_type blocked = operation_blocked;
switch(side_rk_r)
@@ -715,7 +724,6 @@ public:
typename Point2,
typename OutputIterator,
typename IntersectionInfo,
- typename DirInfo,
typename SidePolicy
>
static inline void apply(
@@ -727,10 +735,9 @@ public:
OutputIterator& out,
IntersectionInfo const& intersection_info,
- DirInfo const& dir_info,
SidePolicy const& side)
{
- apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, dir_info, side, empty_transformer);
+ apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, side, empty_transformer);
}
public:
@@ -740,7 +747,6 @@ public:
typename Point2,
typename OutputIterator,
typename IntersectionInfo,
- typename DirInfo,
typename SidePolicy,
typename TurnTransformer
>
@@ -752,50 +758,52 @@ public:
TurnInfo const& tp_model,
OutputIterator& out,
- IntersectionInfo const& intersection_info,
- DirInfo const& dir_info,
+ IntersectionInfo const& info,
SidePolicy const& side,
TurnTransformer turn_transformer,
bool const is_pk_valid = true, bool const is_qk_valid = true)
{
TurnInfo tp = tp_model;
+ int const p_arrival = info.d_info().arrival[0];
+ int const q_arrival = info.d_info().arrival[1];
+
// If P arrives within Q, there is a turn dependent on P
- if ( dir_info.arrival[0] == 1
+ if ( p_arrival == 1
&& is_pk_valid
- && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, intersection_info) )
+ && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) )
{
turn_transformer(tp);
- AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ AssignPolicy::apply(tp, pi, qi, info);
*out++ = tp;
}
// If Q arrives within P, there is a turn dependent on Q
- if ( dir_info.arrival[1] == 1
+ if ( q_arrival == 1
&& is_qk_valid
- && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, intersection_info) )
+ && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) )
{
turn_transformer(tp);
- AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ AssignPolicy::apply(tp, pi, qi, info);
*out++ = tp;
}
if (AssignPolicy::include_opposite)
{
// Handle cases not yet handled above
- if ((dir_info.arrival[1] == -1 && dir_info.arrival[0] == 0)
- || (dir_info.arrival[0] == -1 && dir_info.arrival[1] == 0))
+ if ((q_arrival == -1 && p_arrival == 0)
+ || (p_arrival == -1 && q_arrival == 0))
{
- for (int i = 0; i < 2; i++)
+ for (unsigned int i = 0; i < 2; i++)
{
tp.operations[i].operation = operation_opposite;
}
- for (unsigned int i = 0; i < intersection_info.count; i++)
+ for (unsigned int i = 0; i < info.i_info().count; i++)
{
- assign_point(tp, method_collinear, intersection_info, i);
- AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ assign_point(tp, method_collinear, info.i_info(), i);
+ AssignPolicy::apply(tp, pi, qi, info);
*out++ = tp;
}
}
@@ -833,7 +841,7 @@ struct crosses : public base_turn_handler
// Intersection: take Q
// Otherwise: vice versa
int const side_qi_p1 = dir_info.sides.template get<1, 0>();
- int const index = side_qi_p1 == 1 ? 0 : 1;
+ unsigned int const index = side_qi_p1 == 1 ? 0 : 1;
ti.operations[index].operation = operation_union;
ti.operations[1 - index].operation = operation_intersection;
}
@@ -867,10 +875,9 @@ struct assign_null_policy
typename Info,
typename Point1,
typename Point2,
- typename IntersectionInfo,
- typename DirInfo
+ typename IntersectionInfo
>
- static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&, DirInfo const&)
+ static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&)
{}
};
@@ -933,7 +940,7 @@ struct get_turn_info
&& inters.i_info().count > 0)
{
only_convert::apply(tp, inters.i_info());
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
break;
@@ -968,7 +975,7 @@ struct get_turn_info
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
}
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
break;
@@ -976,7 +983,7 @@ struct get_turn_info
{
crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, inters.i_info(), inters.d_info());
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
break;
@@ -985,7 +992,7 @@ struct get_turn_info
// Both touch (both arrive there)
touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, inters.i_info(), inters.d_info(), inters.sides());
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
break;
@@ -997,7 +1004,7 @@ struct get_turn_info
// or collinear-and-ending at intersection point
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, inters.i_info(), inters.d_info(), inters.sides());
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
else
@@ -1007,7 +1014,7 @@ struct get_turn_info
TurnInfo,
AssignPolicy
>::apply(pi, qi,
- tp, out, inters.i_info(), inters.d_info());
+ tp, out, inters);
}
}
break;
@@ -1032,7 +1039,7 @@ struct get_turn_info
tp, inters.i_info(), inters.d_info(), inters.sides());
}
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
else
@@ -1042,7 +1049,7 @@ struct get_turn_info
TurnInfo,
AssignPolicy
>::apply(pi, pj, pk, qi, qj, qk,
- tp, out, inters.i_info(), inters.d_info(), inters.sides());
+ tp, out, inters, inters.sides());
}
}
break;
@@ -1052,7 +1059,7 @@ struct get_turn_info
if (AssignPolicy::include_degenerate)
{
only_convert::apply(tp, inters.i_info());
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
}
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 ca1b9d9d0c..4a3cacbedd 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
@@ -290,7 +290,7 @@ struct get_turn_info_for_endpoint
linear_intersections::ip_info const& ip_info,
TurnInfo const& tp_model,
IntersectionInfo const& inters,
- int ip_index,
+ unsigned int ip_index,
OutputIterator out)
{
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR
@@ -396,7 +396,7 @@ struct get_turn_info_for_endpoint
RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2,
bool first1, bool last1, bool first2, bool last2,
bool ip_i2, bool ip_j2, TurnInfo const& tp_model,
- IntersectionInfo const& inters, int ip_index,
+ IntersectionInfo const& inters, unsigned int ip_index,
operation_type & op1, operation_type & op2)
{
boost::ignore_unused_variable_warning(i2);
@@ -535,7 +535,7 @@ struct get_turn_info_for_endpoint
typename OutputIterator>
static inline void assign(Point1 const& pi, Point2 const& qi,
IntersectionResult const& result,
- int ip_index,
+ unsigned int ip_index,
method_type method,
operation_type op0, operation_type op1,
turn_position pos0, turn_position pos1,
@@ -585,7 +585,9 @@ struct get_turn_info_for_endpoint
}
}
- AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ // TODO: this should get an intersection_info, which is unavailable here
+ // Because the assign_null policy accepts any structure, we pass the result instead for now
+ AssignPolicy::apply(tp, pi, qi, result);
*out++ = tp;
}
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 eead0d719b..e0d75108b9 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015.
+// Modifications copyright (c) 2013-2015 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
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 873567bbf5..71946543ee 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
@@ -2,18 +2,20 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 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)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#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/util/condition.hpp>
+
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp>
@@ -28,6 +30,8 @@ namespace detail { namespace overlay {
template<typename AssignPolicy>
struct get_turn_info_linear_areal
{
+ // Currently only Linear spikes are handled
+ // Areal spikes are ignored
static const bool handle_spikes = true;
template
@@ -122,7 +126,7 @@ struct get_turn_info_linear_areal
calculate_spike_operation(tp.operations[0].operation,
inters, is_p_last);
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
@@ -135,7 +139,7 @@ struct get_turn_info_linear_areal
replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
break;
@@ -220,9 +224,9 @@ struct get_turn_info_linear_areal
inters, is_p_last);
// TODO: move this into the append_xxx and call for each turn?
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
- if ( ! handle_spikes
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ignore_spike
|| ! append_opposite_spikes<append_touches>( // for 'i' or 'c' i???
tp, inters, is_p_last, is_q_last, out) )
@@ -256,10 +260,10 @@ struct get_turn_info_linear_areal
transformer(tp);
// TODO: move this into the append_xxx and call for each turn?
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
// conditionally handle spikes
- if ( ! handle_spikes
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,
method_touch, append_equal, out) )
{
@@ -273,7 +277,7 @@ struct get_turn_info_linear_areal
TurnInfo,
AssignPolicy
>::apply(pi, qi,
- tp, out, inters.i_info(), inters.d_info());
+ tp, out, inters);
}
}
}
@@ -319,10 +323,10 @@ struct get_turn_info_linear_areal
transformer(tp);
// TODO: move this into the append_xxx and call for each turn?
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
// conditionally handle spikes
- if ( ! handle_spikes
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,
method_replace, version, out) )
{
@@ -336,7 +340,7 @@ struct get_turn_info_linear_areal
turn_transformer_ec<false> transformer(method_touch_interior);
// conditionally handle spikes
- if ( handle_spikes )
+ if ( BOOST_GEOMETRY_CONDITION(handle_spikes) )
{
append_opposite_spikes<append_collinear_opposite>(
tp, inters, is_p_last, is_q_last, out);
@@ -351,8 +355,9 @@ struct get_turn_info_linear_areal
TurnInfo,
AssignPolicy
>::apply(pi, pj, pk, qi, qj, qk,
- tp, out, inters.i_info(), inters.d_info(),
- inters.sides(), transformer);
+ tp, out, inters,
+ inters.sides(), transformer,
+ !is_p_last, true); // qk is always valid
}
}
}
@@ -360,7 +365,7 @@ struct get_turn_info_linear_areal
case '0' :
{
// degenerate points
- if (AssignPolicy::include_degenerate)
+ if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) )
{
only_convert::apply(tp, inters.i_info());
@@ -376,7 +381,7 @@ struct get_turn_info_linear_areal
}
// tp.operations[1].position = position_middle;
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
}
@@ -408,20 +413,37 @@ struct get_turn_info_linear_areal
if ( is_p_spike )
{
- bool going_in = false, going_out = false;
-
int const pk_q1 = inters.sides().pk_wrt_q1();
- int const pk_q2 = inters.sides().pk_wrt_q2();
+
+ bool going_in = pk_q1 < 0; // Pk on the right
+ bool going_out = pk_q1 > 0; // Pk on the left
- if ( inters.sides().qk_wrt_q1() <= 0 ) // Q turning R or C
+ int const qk_q1 = inters.sides().qk_wrt_q1();
+
+ // special cases
+ if ( qk_q1 < 0 ) // Q turning R
{
- going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both
- going_out = pk_q1 > 0 || pk_q2 > 0; // Pk on the left of one of them
+ // spike on the edge point
+ // if it's already known that the spike is going out this musn't be checked
+ if ( ! going_out
+ && equals::equals_point_point(inters.rpj(), inters.rqj()) )
+ {
+ int const pk_q2 = inters.sides().pk_wrt_q2();
+ going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both
+ going_out = pk_q1 > 0 || pk_q2 > 0; // Pk on the left of one of them
+ }
}
- else
+ else if ( qk_q1 > 0 ) // Q turning L
{
- going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them
- going_out = pk_q1 > 0 && pk_q2 > 0; // Pk on the left of both
+ // spike on the edge point
+ // if it's already known that the spike is going in this musn't be checked
+ if ( ! going_in
+ && equals::equals_point_point(inters.rpj(), inters.rqj()) )
+ {
+ int const pk_q2 = inters.sides().pk_wrt_q2();
+ going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them
+ going_out = pk_q1 > 0 && pk_q2 > 0; // Pk on the left of both
+ }
}
if ( going_in )
@@ -461,10 +483,16 @@ struct get_turn_info_linear_areal
&& inters.is_spike_p();
// TODO: throw an exception for spike in Areal?
- /*bool is_q_spike = tp.operations[1].operation == spike_op
- && ! is_q_last
- && inters.is_spike_q();*/
+ /*bool is_q_spike = tp.operations[1].operation == operation_continue
+ && inters.is_spike_q();
+ // both are collinear spikes on the same IP, we can just follow both
+ if ( is_p_spike && is_q_spike )
+ {
+ return false;
+ }
+ // spike on Linear - it's turning back on the boundary of Areal
+ else*/
if ( is_p_spike )
{
tp.method = method;
@@ -477,7 +505,18 @@ struct get_turn_info_linear_areal
return true;
}
-
+ // spike on Areal - Linear is going outside
+ /*else if ( is_q_spike )
+ {
+ tp.method = method;
+ tp.operations[0].operation = operation_union;
+ tp.operations[1].operation = operation_continue;
+ *out++ = tp;
+ *out++ = tp;
+
+ return true;
+ }*/
+
return false;
}
@@ -492,48 +531,71 @@ struct get_turn_info_linear_areal
bool is_p_last, bool /*is_q_last*/,
OutIt out)
{
- bool is_p_spike = ( Version == append_touches ?
+ static const bool is_version_touches = (Version == append_touches);
+
+ bool is_p_spike = ( is_version_touches ?
( tp.operations[0].operation == operation_continue
|| tp.operations[0].operation == operation_intersection ) : // i ???
true )
&& ! is_p_last
&& inters.is_spike_p();
+
// TODO: throw an exception for spike in Areal?
- /*bool is_q_spike = ( Version == append_touches ?
- ( tp.operations[1].operation == operation_continue
- || tp.operations[1].operation == operation_intersection ) :
- true )
- && ! is_q_last
- && inters.is_spike_q();*/
+ /*bool is_q_spike = ( ( Version == append_touches
+ && tp.operations[1].operation == operation_continue )
+ || ( Version == append_collinear_opposite
+ && tp.operations[1].operation == operation_none ) )
+ && inters.is_spike_q();
- if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) )
+ if ( is_p_spike && is_q_spike )
{
- if ( Version == append_touches )
- {
- tp.operations[0].is_collinear = true;
- //tp.operations[1].is_collinear = false;
- tp.method = method_touch;
- }
- else
+ // u/u or nothing?
+ return false;
+ }
+ else*/
+ if ( is_p_spike )
+ {
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches)
+ || inters.d_info().arrival[0] == 1 )
{
- tp.operations[0].is_collinear = true;
- //tp.operations[1].is_collinear = false;
-
- BOOST_ASSERT(inters.i_info().count > 1);
- base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1);
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches) )
+ {
+ tp.operations[0].is_collinear = true;
+ //tp.operations[1].is_collinear = false;
+ tp.method = method_touch;
+ }
+ else
+ {
+ tp.operations[0].is_collinear = true;
+ //tp.operations[1].is_collinear = false;
- AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters.i_info(), inters.d_info());
- }
+ BOOST_ASSERT(inters.i_info().count > 1);
+ base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1);
- tp.operations[0].operation = operation_blocked;
+ AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters);
+ }
+
+ tp.operations[0].operation = operation_blocked;
+ tp.operations[1].operation = operation_continue; // boundary
+ *out++ = tp;
+ tp.operations[0].operation = operation_continue; // boundary
+ //tp.operations[1].operation = operation_continue; // boundary
+ *out++ = tp;
+
+ return true;
+ }
+ }
+ /*else if ( is_q_spike )
+ {
+ tp.operations[0].is_collinear = true;
+ tp.method = is_version_touches ? method_touch : method_touch_interior;
+ tp.operations[0].operation = operation_continue;
tp.operations[1].operation = operation_continue; // boundary
*out++ = tp;
- tp.operations[0].operation = operation_continue; // boundary
- //tp.operations[1].operation = operation_continue; // boundary
*out++ = tp;
return true;
- }
+ }*/
return false;
}
@@ -587,7 +649,7 @@ struct get_turn_info_linear_areal
operation_type & op1 = turn.operations[1].operation;
// NOTE: probably only if methods are WRT IPs, not segments!
- if ( IsFront
+ if ( BOOST_GEOMETRY_CONDITION(IsFront)
|| op0 == operation_intersection || op0 == operation_union
|| op1 == operation_intersection || op1 == operation_union )
{
@@ -666,7 +728,9 @@ struct get_turn_info_linear_areal
// ANALYSE AND ASSIGN FIRST
// IP on the first point of Linear Geometry
- if ( EnableFirst && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication
+ bool was_first_point_handled = false;
+ if ( BOOST_GEOMETRY_CONDITION(EnableFirst)
+ && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication
{
TurnInfo tp = tp_model;
tp.operations[0].position = position_front;
@@ -735,14 +799,16 @@ struct get_turn_info_linear_areal
// here is_p_first_ip == true
tp.operations[0].is_collinear = false;
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
+
+ was_first_point_handled = true;
}
// ANALYSE AND ASSIGN LAST
// IP on the last point of Linear Geometry
- if ( EnableLast
+ if ( BOOST_GEOMETRY_CONDITION(EnableLast)
&& is_p_last
&& ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication
{
@@ -783,13 +849,14 @@ struct get_turn_info_linear_areal
// equals<> or collinear<> will assign the second point,
// we'd like to assign the first one
- int ip_index = ip_count > 1 ? 1 : 0;
+ unsigned int ip_index = ip_count > 1 ? 1 : 0;
base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index);
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
- return true;
+ // don't ignore the first IP if the segment is opposite
+ return !( opposite && ip_count > 1 ) || was_first_point_handled;
}
// don't ignore anything for now
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 4f0384877f..1ec88e54a0 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015.
+// Modifications copyright (c) 2013-2015 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
@@ -17,6 +17,8 @@
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
@@ -120,7 +122,7 @@ struct get_turn_info_linear_linear
tp.operations[0].operation,
tp.operations[1].operation);
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
}
@@ -132,7 +134,7 @@ struct get_turn_info_linear_linear
replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
break;
@@ -260,9 +262,9 @@ struct get_turn_info_linear_linear
tp.operations[1].operation);
// TODO: move this into the append_xxx and call for each turn?
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
- if ( ! handle_spikes
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ! append_opposite_spikes<append_touches>(tp, inters,
is_p_last, is_q_last,
out) )
@@ -293,18 +295,24 @@ struct get_turn_info_linear_linear
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, inters.i_info(), inters.d_info(), inters.sides());
+ operation_type spike_op
+ = ( tp.operations[0].operation != operation_continue
+ || tp.operations[1].operation != operation_continue ) ?
+ operation_union :
+ operation_continue;
+
// transform turn
turn_transformer_ec transformer(method_touch);
transformer(tp);
// TODO: move this into the append_xxx and call for each turn?
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
// conditionally handle spikes
- if ( ! handle_spikes
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ! append_collinear_spikes(tp, inters,
is_p_last, is_q_last,
- method_touch, operation_union,
+ method_touch, spike_op,
out) )
{
*out++ = tp; // no spikes
@@ -318,7 +326,7 @@ struct get_turn_info_linear_linear
<
TurnInfo,
AssignPolicy
- >::apply(pi, qi, tp, out, inters.i_info(), inters.d_info());
+ >::apply(pi, qi, tp, out, inters);
}
}
}
@@ -351,7 +359,11 @@ struct get_turn_info_linear_linear
tp, inters.i_info(), inters.d_info(), inters.sides());
method_replace = method_touch;
- spike_op = operation_union;
+ if ( tp.operations[0].operation != operation_continue
+ || tp.operations[1].operation != operation_continue )
+ {
+ spike_op = operation_union;
+ }
}
else
{
@@ -367,10 +379,10 @@ struct get_turn_info_linear_linear
transformer(tp);
// TODO: move this into the append_xxx and call for each turn?
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
// conditionally handle spikes
- if ( ! handle_spikes
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ! append_collinear_spikes(tp, inters,
is_p_last, is_q_last,
method_replace, spike_op,
@@ -386,7 +398,7 @@ struct get_turn_info_linear_linear
turn_transformer_ec transformer(method_touch_interior);
// conditionally handle spikes
- if ( handle_spikes )
+ if ( BOOST_GEOMETRY_CONDITION(handle_spikes) )
{
append_opposite_spikes<append_collinear_opposite>(tp, inters,
is_p_last, is_q_last,
@@ -402,7 +414,7 @@ struct get_turn_info_linear_linear
TurnInfo,
AssignPolicy
>::apply(pi, pj, pk, qi, qj, qk,
- tp, out, inters.i_info(), inters.d_info(), inters.sides(),
+ tp, out, inters, inters.sides(),
transformer, !is_p_last, !is_q_last);
}
}
@@ -411,7 +423,7 @@ struct get_turn_info_linear_linear
case '0' :
{
// degenerate points
- if (AssignPolicy::include_degenerate)
+ if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) )
{
only_convert::apply(tp, inters.i_info());
@@ -437,7 +449,7 @@ struct get_turn_info_linear_linear
tp.operations[1].position = position_back;
}
- AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, pi, qi, inters);
*out++ = tp;
}
}
@@ -478,6 +490,14 @@ struct get_turn_info_linear_linear
if ( is_p_spike && is_q_spike )
{
+ if ( tp.method == method_equal
+ && tp.operations[0].operation == operation_continue
+ && tp.operations[1].operation == operation_continue )
+ {
+ // treat both non-opposite collinear spikes as no-spikes
+ return false;
+ }
+
tp.method = method;
tp.operations[0].operation = operation_blocked;
tp.operations[1].operation = operation_blocked;
@@ -527,13 +547,15 @@ struct get_turn_info_linear_linear
bool is_p_last, bool is_q_last,
OutIt out)
{
- bool is_p_spike = ( Version == append_touches ?
+ static const bool is_version_touches = (Version == append_touches);
+
+ bool is_p_spike = ( is_version_touches ?
( tp.operations[0].operation == operation_continue
|| tp.operations[0].operation == operation_intersection ) :
true )
&& ! is_p_last
&& inters.is_spike_p();
- bool is_q_spike = ( Version == append_touches ?
+ bool is_q_spike = ( is_version_touches ?
( tp.operations[1].operation == operation_continue
|| tp.operations[1].operation == operation_intersection ) :
true )
@@ -542,9 +564,11 @@ struct get_turn_info_linear_linear
bool res = false;
- if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) )
+ if ( is_p_spike
+ && ( BOOST_GEOMETRY_CONDITION(is_version_touches)
+ || inters.d_info().arrival[0] == 1 ) )
{
- if ( Version == append_touches )
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches) )
{
tp.operations[0].is_collinear = true;
tp.operations[1].is_collinear = false;
@@ -560,8 +584,7 @@ struct get_turn_info_linear_linear
base_turn_handler::assign_point(tp, method_touch_interior,
inters.i_info(), 1);
- AssignPolicy::apply(tp, inters.pi(), inters.qi(),
- inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters);
}
tp.operations[0].operation = operation_blocked;
@@ -574,9 +597,11 @@ struct get_turn_info_linear_linear
res = true;
}
- if ( is_q_spike && ( Version == append_touches || inters.d_info().arrival[1] == 1 ) )
+ if ( is_q_spike
+ && ( BOOST_GEOMETRY_CONDITION(is_version_touches)
+ || inters.d_info().arrival[1] == 1 ) )
{
- if ( Version == append_touches )
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches) )
{
tp.operations[0].is_collinear = false;
tp.operations[1].is_collinear = true;
@@ -591,8 +616,7 @@ struct get_turn_info_linear_linear
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0);
- AssignPolicy::apply(tp, inters.pi(), inters.qi(),
- inters.i_info(), inters.d_info());
+ AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters);
}
tp.operations[0].operation = operation_intersection;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
index a96538c43a..a5d8f3f023 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -54,6 +54,7 @@
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
+#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>
@@ -62,8 +63,7 @@
#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
-
-#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
# include <sstream>
@@ -229,7 +229,7 @@ public :
// section 2: [--------------]
// section 1: |----|---|---|---|---|
for (prev1 = it1++, next1++;
- it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);
+ it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);
++prev1, ++it1, ++index1, ++next1, ++ndi1)
{
ever_circling_iterator<range1_iterator> nd_next1(
@@ -247,7 +247,7 @@ public :
next2++;
for (prev2 = it2++, next2++;
- it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);
+ it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);
++prev2, ++it2, ++index2, ++next2, ++ndi2)
{
bool skip = same_source;
@@ -299,8 +299,8 @@ public :
if (InterruptPolicy::enabled)
{
if (interrupt_policy.apply(
- std::make_pair(boost::begin(turns) + size_before,
- boost::end(turns))))
+ std::make_pair(range::pos(turns, size_before),
+ boost::end(turns))))
{
return false;
}
@@ -318,25 +318,6 @@ private :
typedef typename model::referring_segment<point1_type const> segment1_type;
typedef typename model::referring_segment<point2_type const> segment2_type;
-
- template <size_t Dim, typename Point, typename Box, typename RobustPolicy>
- static inline bool preceding(int dir, Point const& point, Box const& box, RobustPolicy const& robust_policy)
- {
- typename robust_point_type<Point, RobustPolicy>::type robust_point;
- geometry::recalculate(robust_point, point, robust_policy);
- return (dir == 1 && get<Dim>(robust_point) < get<min_corner, Dim>(box))
- || (dir == -1 && get<Dim>(robust_point) > get<max_corner, Dim>(box));
- }
-
- template <size_t Dim, typename Point, typename Box, typename RobustPolicy>
- static inline bool exceeding(int dir, Point const& point, Box const& box, RobustPolicy const& robust_policy)
- {
- typename robust_point_type<Point, RobustPolicy>::type robust_point;
- geometry::recalculate(robust_point, point, robust_policy);
- return (dir == 1 && get<Dim>(robust_point) > get<max_corner, Dim>(box))
- || (dir == -1 && get<Dim>(robust_point) < get<min_corner, Dim>(box));
- }
-
template <typename Iterator, typename RangeIterator, typename Section, typename RobustPolicy>
static inline void advance_to_non_duplicate_next(Iterator& next,
RangeIterator const& it, Section const& section, RobustPolicy const& robust_policy)
@@ -387,7 +368,7 @@ private :
// Mimic section-iterator:
// Skip to point such that section interects other box
prev = it++;
- for(; it != end && preceding<0>(dir, *it, other_bounding_box, robust_policy);
+ for(; it != end && detail::section::preceding<0>(dir, *it, other_bounding_box, robust_policy);
prev = it++, index++, ndi++)
{}
// Go back one step because we want to start completely preceding
@@ -395,24 +376,6 @@ private :
}
};
-struct get_section_box
-{
- template <typename Box, typename InputItem>
- static inline void apply(Box& total, InputItem const& item)
- {
- geometry::expand(total, item.bounding_box);
- }
-};
-
-struct ovelaps_section_box
-{
- template <typename Box, typename InputItem>
- static inline bool apply(Box const& box, InputItem const& item)
- {
- return ! detail::disjoint::disjoint_box_box(box, item.bounding_box);
- }
-};
-
template
<
typename Geometry1, typename Geometry2,
@@ -496,12 +459,15 @@ public:
point_type, RobustPolicy
>::type
> box_type;
- typedef typename geometry::sections<box_type, 2> sections_type;
+ typedef geometry::sections<box_type, 2> sections_type;
sections_type sec1, sec2;
+ typedef boost::mpl::vector_c<std::size_t, 0, 1> dimensions;
- geometry::sectionalize<Reverse1>(geometry1, robust_policy, true, sec1, 0);
- geometry::sectionalize<Reverse2>(geometry2, robust_policy, true, sec2, 1);
+ geometry::sectionalize<Reverse1, dimensions>(geometry1, robust_policy,
+ sec1, 0);
+ geometry::sectionalize<Reverse2, dimensions>(geometry2, robust_policy,
+ sec2, 1);
// ... and then partition them, intersecting overlapping sections in visitor method
section_visitor
@@ -513,7 +479,9 @@ public:
geometry::partition
<
- box_type, get_section_box, ovelaps_section_box
+ box_type,
+ detail::section::get_section_box,
+ detail::section::overlaps_section_box
>::apply(sec1, sec2, visitor);
}
};
@@ -556,7 +524,8 @@ struct get_turns_cs
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
- int multi_index = -1, int ring_index = -1)
+ signed_index_type multi_index = -1,
+ signed_index_type ring_index = -1)
{
if ( boost::size(range) <= 1)
{
@@ -569,7 +538,8 @@ struct get_turns_cs
cview_type cview(range);
view_type view(cview);
- typename boost::range_size<view_type>::type segments_count1 = boost::size(view) - 1;
+ typedef typename boost::range_size<view_type>::type size_type;
+ size_type segments_count1 = boost::size(view) - 1;
iterator_type it = boost::begin(view);
@@ -582,7 +552,7 @@ struct get_turns_cs
//char previous_side[2] = {0, 0};
- int index = 0;
+ signed_index_type index = 0;
for (iterator_type prev = it++;
it != boost::end(view);
@@ -621,7 +591,7 @@ struct get_turns_cs
bp[0], bp[1], bp[2], bp[3],
// NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes
index == 0,
- unsigned(index) == segments_count1,
+ size_type(index) == segments_count1,
robust_policy,
turns, interrupt_policy);
// Future performance enhancement:
@@ -726,7 +696,7 @@ struct get_turns_polygon_cs
int source_id2, Box const& box,
RobustPolicy const& robust_policy,
Turns& turns, InterruptPolicy& interrupt_policy,
- int multi_index = -1)
+ signed_index_type multi_index = -1)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
@@ -744,7 +714,7 @@ struct get_turns_polygon_cs
turns, interrupt_policy,
multi_index, -1);
- int i = 0;
+ signed_index_type i = 0;
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -783,7 +753,7 @@ struct get_turns_multi_polygon_cs
Multi const
>::type iterator_type;
- int i = 0;
+ signed_index_type i = 0;
for (iterator_type it = boost::begin(multi);
it != boost::end(multi);
++it, ++i)
diff --git a/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp b/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp
index 085933dd7a..277a223d47 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp
@@ -28,6 +28,11 @@
#include <boost/geometry/geometries/segment.hpp>
+// TODO: the approach below should be completely replaced by the new
+// get_left_turns, to keep the outgoing vector which has open space one of its
+// sides.
+
+
namespace boost { namespace geometry
{
@@ -76,6 +81,12 @@ private :
RobustPolicy
>::type robust_point_type;
+ inline bool default_order(Indexed const& left, Indexed const& right) const
+ {
+ // We've nothing to sort on. Take the indexes
+ return left.turn_index < right.turn_index;
+ }
+
// Still necessary in some situations,
// for example #case_102_multi, #case_107_multi, #case_recursive_boxes_3
inline void get_situation_map(Indexed const& left, Indexed const& right,
@@ -336,7 +347,7 @@ private :
#endif
//debug_consider(0, left, right, header, false, "-> return", ret);
- return left.turn_index < right.turn_index;
+ return default_order(left, right);
}
@@ -369,11 +380,17 @@ private :
// Both located at same side (#58, pie_21_7_21_0_3)
if (side_ri_p * side_si_p == 1 && side_si_r != 0)
{
- // Take the most left one
if (left.subject->operation == operation_union
&& right.subject->operation == operation_union)
{
- bool ret = side_si_r == 1;
+ int const side_ri_s = m_strategy.apply(si, sj, ri);
+ if (side_si_r == side_ri_s)
+ {
+ return default_order(left, right);
+ }
+
+ // Take the most left one
+ bool const ret = side_si_r == 1;
//debug_consider(0, left, right, header, false, "same side", ret);
return ret;
}
@@ -407,6 +424,12 @@ private :
// One coming from left (#90, #94, #95)
if (side_si_r != 0 && (side_ri_p != 0 || side_si_p != 0))
{
+ int const side_ri_s = m_strategy.apply(si, sj, ri);
+ if (side_si_r == side_ri_s)
+ {
+ return default_order(left, right);
+ }
+
bool ret = false;
#if BOOST_GEOMETRY_HANDLE_TANGENCIES_WITH_OVERLAP_INFO
@@ -464,7 +487,7 @@ private :
return ! consider_iu_iu(right, left, header, true);
}
- return left.turn_index < right.turn_index;
+ return default_order(left, right);
}
inline bool consider_ii(Indexed const& left, Indexed const& right,
@@ -488,19 +511,17 @@ private :
bool const ret = side_si_r != 1;
return ret;
}
- return left.turn_index < right.turn_index;
+ return default_order(left, right);
}
public :
inline bool operator()(Indexed const& left, Indexed const& right) const
{
- bool const default_order = left.turn_index < right.turn_index;
-
if ((m_turn_points[left.turn_index].discarded || left.discarded)
&& (m_turn_points[right.turn_index].discarded || right.discarded))
{
- return default_order;
+ return default_order(left, right);
}
else if (m_turn_points[left.turn_index].discarded || left.discarded)
{
@@ -525,7 +546,7 @@ public :
// uu/uu, Order is arbitrary
// Note: uu/uu is discarded now before so this point will
// not be reached.
- return default_order;
+ return default_order(left, right);
}
else if (m_turn_points[left.turn_index].combination(operation_intersection, operation_union)
&& m_turn_points[right.turn_index].combination(operation_intersection, operation_union))
@@ -587,7 +608,7 @@ public :
<< std::endl;
#endif
- return default_order;
+ return default_order(left, right);
}
};
@@ -708,7 +729,7 @@ inline void handle_cluster(Iterator begin_cluster, Iterator end_cluster,
for_operation, geometry1, geometry2, strategy);
- // Then sort this range (discard rows will be ordered first and will be removed in enrich_assign)
+ // Then sort this range (discarded rows will be ordered first and will be removed in enrich_assign)
std::sort(begin_cluster, end_cluster,
sort_in_cluster
<
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index a13a627456..3101de8c35 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -43,9 +43,9 @@
#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
-
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
-#include <boost/foreach.hpp>
+#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
+#include <boost/geometry/io/wkt/wkt.hpp>
#endif
namespace boost { namespace geometry
@@ -254,9 +254,10 @@ struct intersection_of_linestring_with_areal
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
int index = 0;
- BOOST_FOREACH(turn_info const& turn, turns)
+ for(typename std::deque<turn_info>::const_iterator
+ it = turns.begin(); it != turns.end(); ++it)
{
- debug_follow(turn, turn.operations[0], index++);
+ debug_follow(*it, it->operations[0], index++);
}
#endif
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index 3a7a7a7f3e..d4ebcf296b 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -144,11 +144,10 @@ protected:
typename Info,
typename Point1,
typename Point2,
- typename IntersectionInfo,
- typename DirInfo
+ typename IntersectionInfo
>
static inline void apply(Info& , Point1 const& , Point2 const& ,
- IntersectionInfo const& , DirInfo const& )
+ IntersectionInfo const& )
{
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 44b5a0df3c..a2f52848d1 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -44,10 +44,6 @@
# include <boost/geometry/io/dsv/write.hpp>
#endif
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
-# include <boost/timer.hpp>
-#endif
-
namespace boost { namespace geometry
{
@@ -57,19 +53,10 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
-// Skip for assemble process
-template <typename TurnInfo>
-inline bool skip(TurnInfo const& turn_info)
-{
- return (turn_info.discarded || turn_info.both(operation_union))
- && ! turn_info.any_blocked()
- && ! turn_info.both(operation_intersection)
- ;
-}
-
-template <typename TurnPoints, typename Map>
-inline void map_turns(Map& map, TurnPoints const& turn_points)
+template <typename TurnPoints, typename TurnInfoMap>
+inline void get_ring_turn_info(TurnInfoMap& turn_info_map,
+ TurnPoints const& turn_points)
{
typedef typename boost::range_value<TurnPoints>::type turn_point_type;
typedef typename turn_point_type::container_type container_type;
@@ -79,20 +66,32 @@ inline void map_turns(Map& map, TurnPoints const& turn_points)
it != boost::end(turn_points);
++it)
{
- if (! skip(*it))
+ typename boost::range_value<TurnPoints>::type const& turn_info = *it;
+ bool both_uu = turn_info.both(operation_union);
+ bool skip = (turn_info.discarded || both_uu)
+ && ! turn_info.any_blocked()
+ && ! turn_info.both(operation_intersection)
+ ;
+
+ for (typename boost::range_iterator<container_type const>::type
+ op_it = boost::begin(turn_info.operations);
+ op_it != boost::end(turn_info.operations);
+ ++op_it)
{
- for (typename boost::range_iterator<container_type const>::type
- op_it = boost::begin(it->operations);
- op_it != boost::end(it->operations);
- ++op_it)
+ ring_identifier ring_id
+ (
+ op_it->seg_id.source_index,
+ op_it->seg_id.multi_index,
+ op_it->seg_id.ring_index
+ );
+
+ if (! skip)
{
- ring_identifier ring_id
- (
- op_it->seg_id.source_index,
- op_it->seg_id.multi_index,
- op_it->seg_id.ring_index
- );
- map[ring_id]++;
+ turn_info_map[ring_id].has_normal_turn = true;
+ }
+ else if (both_uu)
+ {
+ turn_info_map[ring_id].has_uu_turn = true;
}
}
}
@@ -137,10 +136,10 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
#endif
- std::map<ring_identifier, int> empty;
+ std::map<ring_identifier, ring_turn_info> empty;
std::map<ring_identifier, properties> all_of_one_of_them;
- select_rings<Direction>(geometry1, geometry2, empty, all_of_one_of_them, false);
+ select_rings<Direction>(geometry1, geometry2, empty, all_of_one_of_them);
ring_container_type rings;
assign_parents(geometry1, geometry2, rings, all_of_one_of_them);
return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
@@ -193,10 +192,6 @@ struct overlay
container_type turn_points;
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- boost::timer timer;
-#endif
-
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "get turns" << std::endl;
#endif
@@ -207,10 +202,6 @@ std::cout << "get turns" << std::endl;
detail::overlay::assign_null_policy
>(geometry1, geometry2, robust_policy, turn_points, policy);
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << "get_turns: " << timer.elapsed() << std::endl;
-#endif
-
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
@@ -223,11 +214,6 @@ std::cout << "enrich" << std::endl;
robust_policy,
side_strategy);
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << "enrich_intersection_points: " << timer.elapsed() << std::endl;
-#endif
-
-
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "traverse" << std::endl;
#endif
@@ -245,27 +231,18 @@ std::cout << "traverse" << std::endl;
turn_points, rings
);
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << "traverse: " << timer.elapsed() << std::endl;
-#endif
-
-
- std::map<ring_identifier, int> map;
- map_turns(map, turn_points);
-
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << "map_turns: " << timer.elapsed() << std::endl;
-#endif
-
- typedef ring_properties<typename geometry::point_type<GeometryOut>::type> properties;
-
- std::map<ring_identifier, properties> selected;
- select_rings<Direction>(geometry1, geometry2, map, selected, ! turn_points.empty());
+ std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
+ get_ring_turn_info(turn_info_per_ring, turn_points);
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << "select_rings: " << timer.elapsed() << std::endl;
-#endif
+ typedef ring_properties
+ <
+ typename geometry::point_type<GeometryOut>::type
+ > properties;
+ // Select all rings which are NOT touched by any intersection point
+ std::map<ring_identifier, properties> selected_ring_properties;
+ select_rings<Direction>(geometry1, geometry2, turn_info_per_ring,
+ selected_ring_properties);
// Add rings created during traversal
{
@@ -275,24 +252,15 @@ std::cout << "traverse" << std::endl;
it != boost::end(rings);
++it)
{
- selected[id] = properties(*it, true);
- selected[id].reversed = ReverseOut;
+ selected_ring_properties[id] = properties(*it);
+ selected_ring_properties[id].reversed = ReverseOut;
id.multi_index++;
}
}
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << "add traversal rings: " << timer.elapsed() << std::endl;
-#endif
-
-
- assign_parents(geometry1, geometry2, rings, selected);
-
-#ifdef BOOST_GEOMETRY_TIME_OVERLAY
- std::cout << "assign_parents: " << timer.elapsed() << std::endl;
-#endif
+ assign_parents(geometry1, geometry2, rings, selected_ring_properties);
- return add_rings<GeometryOut>(selected, geometry1, geometry2, rings, out);
+ return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
index a6088694da..b469052c84 100644
--- a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
+++ b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
@@ -33,8 +33,7 @@ struct ring_properties
Point point;
area_type area;
- // Filled by "update_selection_map"
- int within_code;
+ // Filled by "update_ring_selection"
bool reversed;
// Filled/used by "assign_rings"
@@ -45,21 +44,22 @@ struct ring_properties
inline ring_properties()
: area(area_type())
- , within_code(-1)
, reversed(false)
, discarded(false)
, parent_area(-1)
{}
template <typename RingOrBox>
- inline ring_properties(RingOrBox const& ring_or_box, bool midpoint)
- : within_code(-1)
- , reversed(false)
+ inline ring_properties(RingOrBox const& ring_or_box)
+ : reversed(false)
, discarded(false)
, parent_area(-1)
{
this->area = geometry::area(ring_or_box);
- geometry::point_on_border(this->point, ring_or_box, midpoint);
+ // 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);
}
inline area_type get_area() const
diff --git a/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
index 385658a190..d18e012b2d 100644
--- a/boost/geometry/algorithms/detail/overlay/select_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// Use, modification and distribution is subject to the Boost Software License,
@@ -20,7 +20,6 @@
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
-#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
@@ -34,6 +33,18 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
+struct ring_turn_info
+{
+ bool has_uu_turn;
+ bool has_normal_turn;
+ bool within_other;
+
+ ring_turn_info()
+ : has_uu_turn(false)
+ , has_normal_turn(false)
+ , within_other(false)
+ {}
+};
namespace dispatch
{
@@ -45,41 +56,41 @@ namespace dispatch
template <typename Box>
struct select_rings<box_tag, Box>
{
- template <typename Geometry, typename Map>
+ template <typename Geometry, typename RingPropertyMap>
static inline void apply(Box const& box, Geometry const& ,
- ring_identifier const& id, Map& map, bool midpoint)
+ ring_identifier const& id, RingPropertyMap& ring_properties)
{
- map[id] = typename Map::mapped_type(box, midpoint);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(box);
}
- template <typename Map>
+ template <typename RingPropertyMap>
static inline void apply(Box const& box,
- ring_identifier const& id, Map& map, bool midpoint)
+ ring_identifier const& id, RingPropertyMap& ring_properties)
{
- map[id] = typename Map::mapped_type(box, midpoint);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(box);
}
};
template <typename Ring>
struct select_rings<ring_tag, Ring>
{
- template <typename Geometry, typename Map>
+ template <typename Geometry, typename RingPropertyMap>
static inline void apply(Ring const& ring, Geometry const& ,
- ring_identifier const& id, Map& map, bool midpoint)
+ ring_identifier const& id, RingPropertyMap& ring_properties)
{
if (boost::size(ring) > 0)
{
- map[id] = typename Map::mapped_type(ring, midpoint);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
}
}
- template <typename Map>
+ template <typename RingPropertyMap>
static inline void apply(Ring const& ring,
- ring_identifier const& id, Map& map, bool midpoint)
+ ring_identifier const& id, RingPropertyMap& ring_properties)
{
if (boost::size(ring) > 0)
{
- map[id] = typename Map::mapped_type(ring, midpoint);
+ ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
}
}
};
@@ -88,14 +99,14 @@ namespace dispatch
template <typename Polygon>
struct select_rings<polygon_tag, Polygon>
{
- template <typename Geometry, typename Map>
+ template <typename Geometry, typename RingPropertyMap>
static inline void apply(Polygon const& polygon, Geometry const& geometry,
- ring_identifier id, Map& map, bool midpoint)
+ ring_identifier id, RingPropertyMap& ring_properties)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring;
- per_ring::apply(exterior_ring(polygon), geometry, id, map, midpoint);
+ per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties);
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -103,18 +114,18 @@ namespace dispatch
it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
- per_ring::apply(*it, geometry, id, map, midpoint);
+ per_ring::apply(*it, geometry, id, ring_properties);
}
}
- template <typename Map>
+ template <typename RingPropertyMap>
static inline void apply(Polygon const& polygon,
- ring_identifier id, Map& map, bool midpoint)
+ ring_identifier id, RingPropertyMap& ring_properties)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring;
- per_ring::apply(exterior_ring(polygon), id, map, midpoint);
+ per_ring::apply(exterior_ring(polygon), id, ring_properties);
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -122,7 +133,7 @@ namespace dispatch
it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
- per_ring::apply(*it, id, map, midpoint);
+ per_ring::apply(*it, id, ring_properties);
}
}
};
@@ -130,9 +141,9 @@ namespace dispatch
template <typename Multi>
struct select_rings<multi_polygon_tag, Multi>
{
- template <typename Geometry, typename Map>
+ template <typename Geometry, typename RingPropertyMap>
static inline void apply(Multi const& multi, Geometry const& geometry,
- ring_identifier id, Map& map, bool midpoint)
+ ring_identifier id, RingPropertyMap& ring_properties)
{
typedef typename boost::range_iterator
<
@@ -145,7 +156,7 @@ namespace dispatch
for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it)
{
id.ring_index = -1;
- per_polygon::apply(*it, geometry, id, map, midpoint);
+ per_polygon::apply(*it, geometry, id, ring_properties);
id.multi_index++;
}
}
@@ -161,14 +172,12 @@ struct decide
template<>
struct decide<overlay_union>
{
- template <typename Code>
- static bool include(ring_identifier const& , Code const& code)
+ static bool include(ring_identifier const& , ring_turn_info const& info)
{
- return code.within_code * -1 == 1;
+ return info.has_uu_turn || ! info.within_other;
}
- template <typename Code>
- static bool reversed(ring_identifier const& , Code const& )
+ static bool reversed(ring_identifier const& , ring_turn_info const& )
{
return false;
}
@@ -177,31 +186,43 @@ struct decide<overlay_union>
template<>
struct decide<overlay_difference>
{
- template <typename Code>
- static bool include(ring_identifier const& id, Code const& code)
+ static bool include(ring_identifier const& id, ring_turn_info const& info)
{
- bool is_first = id.source_index == 0;
- return code.within_code * -1 * (is_first ? 1 : -1) == 1;
+ // Difference: A - B
+
+ // If this is A (source_index=0) and there is only a u/u turn,
+ // then the ring is inside B
+ // If this is B (source_index=1) and there is only a u/u turn,
+ // then the ring is NOT inside A
+
+ // If this is A and the ring is within the other geometry,
+ // then we should NOT include it.
+ // If this is B then we SHOULD include it.
+
+ bool const is_first = id.source_index == 0;
+ bool const within_other = info.within_other
+ || (is_first && info.has_uu_turn);
+ return is_first ? ! within_other : within_other;
}
- template <typename Code>
- static bool reversed(ring_identifier const& id, Code const& code)
+ static bool reversed(ring_identifier const& id, ring_turn_info const& info)
{
- return include(id, code) && id.source_index == 1;
+ // Difference: A - B
+ // If this is B, and the ring is included, it should be reversed afterwards
+
+ return id.source_index == 1 && include(id, info);
}
};
template<>
struct decide<overlay_intersection>
{
- template <typename Code>
- static bool include(ring_identifier const& , Code const& code)
+ static bool include(ring_identifier const& , ring_turn_info const& info)
{
- return code.within_code * 1 == 1;
+ return ! info.has_uu_turn && info.within_other;
}
- template <typename Code>
- static bool reversed(ring_identifier const& , Code const& )
+ static bool reversed(ring_identifier const& , ring_turn_info const& )
{
return false;
}
@@ -211,61 +232,60 @@ struct decide<overlay_intersection>
template
<
overlay_type OverlayType,
- typename Geometry1, typename Geometry2,
- typename IntersectionMap, typename SelectionMap
+ typename Geometry1,
+ typename Geometry2,
+ typename TurnInfoMap,
+ typename RingPropertyMap
>
-inline void update_selection_map(Geometry1 const& geometry1,
+inline void update_ring_selection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- IntersectionMap const& intersection_map,
- SelectionMap const& map_with_all, SelectionMap& selection_map)
+ TurnInfoMap const& turn_info_map,
+ RingPropertyMap const& all_ring_properties,
+ RingPropertyMap& selected_ring_properties)
{
- selection_map.clear();
+ selected_ring_properties.clear();
- for (typename SelectionMap::const_iterator it = boost::begin(map_with_all);
- it != boost::end(map_with_all);
+ for (typename RingPropertyMap::const_iterator it = boost::begin(all_ring_properties);
+ it != boost::end(all_ring_properties);
++it)
{
- /*
- int union_code = it->second.within_code * -1;
- bool is_first = it->first.source_index == 0;
- std::cout << it->first << " " << it->second.area
- << ": " << it->second.within_code
- << " union: " << union_code
- << " intersection: " << (it->second.within_code * 1)
- << " G1-G2: " << (union_code * (is_first ? 1 : -1))
- << " G2-G1: " << (union_code * (is_first ? -1 : 1))
- << " -> " << (decide<OverlayType>::include(it->first, it->second) ? "INC" : "")
- << decide<OverlayType>::reverse(it->first, it->second)
- << std::endl;
- */
-
- bool found = intersection_map.find(it->first) != intersection_map.end();
- if (! found)
+ ring_identifier const& id = it->first;
+
+ ring_turn_info info;
+
+ typename TurnInfoMap::const_iterator tcit = turn_info_map.find(id);
+ if (tcit != turn_info_map.end())
{
- ring_identifier const id = it->first;
- typename SelectionMap::mapped_type properties = it->second; // Copy by value
+ info = tcit->second; // Copy by value
+ }
- // Calculate the "within code" (previously this was done earlier but is
- // much efficienter here - it can be even more efficient doing it all at once,
- // using partition, TODO)
- // So though this is less elegant than before, it avoids many unused point-in-poly calculations
+ if (info.has_normal_turn)
+ {
+ // There are normal turns on this ring. It should be traversed, we
+ // don't include the original ring
+ continue;
+ }
+
+ if (! info.has_uu_turn)
+ {
+ // Check if the ring is within the other geometry, by taking
+ // a point lying on the ring
switch(id.source_index)
{
case 0 :
- properties.within_code
- = geometry::within(properties.point, geometry2) ? 1 : -1;
+ info.within_other = geometry::within(it->second.point, geometry2);
break;
case 1 :
- properties.within_code
- = geometry::within(properties.point, geometry1) ? 1 : -1;
+ info.within_other = geometry::within(it->second.point, geometry1);
break;
}
+ }
- if (decide<OverlayType>::include(id, properties))
- {
- properties.reversed = decide<OverlayType>::reversed(id, properties);
- selection_map[id] = properties;
- }
+ if (decide<OverlayType>::include(id, info))
+ {
+ typename RingPropertyMap::mapped_type properties = it->second; // Copy by value
+ properties.reversed = decide<OverlayType>::reversed(id, info);
+ selected_ring_properties[id] = properties;
}
}
}
@@ -277,44 +297,47 @@ inline void update_selection_map(Geometry1 const& geometry1,
template
<
overlay_type OverlayType,
- typename Geometry1, typename Geometry2,
- typename IntersectionMap, typename SelectionMap
+ typename Geometry1,
+ typename Geometry2,
+ typename RingTurnInfoMap,
+ typename RingPropertyMap
>
inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
- IntersectionMap const& intersection_map,
- SelectionMap& selection_map, bool midpoint)
+ RingTurnInfoMap const& turn_info_per_ring,
+ RingPropertyMap& selected_ring_properties)
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
- SelectionMap map_with_all;
+ RingPropertyMap all_ring_properties;
dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
- ring_identifier(0, -1, -1), map_with_all, midpoint);
+ ring_identifier(0, -1, -1), all_ring_properties);
dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,
- ring_identifier(1, -1, -1), map_with_all, midpoint);
+ ring_identifier(1, -1, -1), all_ring_properties);
- update_selection_map<OverlayType>(geometry1, geometry2, intersection_map,
- map_with_all, selection_map);
+ update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring,
+ all_ring_properties, selected_ring_properties);
}
template
<
overlay_type OverlayType,
typename Geometry,
- typename IntersectionMap, typename SelectionMap
+ typename RingTurnInfoMap,
+ typename RingPropertyMap
>
inline void select_rings(Geometry const& geometry,
- IntersectionMap const& intersection_map,
- SelectionMap& selection_map, bool midpoint)
+ RingTurnInfoMap const& turn_info_per_ring,
+ RingPropertyMap& selected_ring_properties)
{
typedef typename geometry::tag<Geometry>::type tag;
- SelectionMap map_with_all;
+ RingPropertyMap all_ring_properties;
dispatch::select_rings<tag, Geometry>::apply(geometry,
- ring_identifier(0, -1, -1), map_with_all, midpoint);
+ ring_identifier(0, -1, -1), all_ring_properties);
- update_selection_map<OverlayType>(geometry, geometry, intersection_map,
- map_with_all, selection_map);
+ update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring,
+ all_ring_properties, selected_ring_properties);
}
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
index 8dffeae283..b1f984ffe1 100644
--- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
@@ -23,9 +23,12 @@
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -96,7 +99,7 @@ struct self_section_visitor
m_rescale_policy,
m_turns, m_interrupt_policy);
}
- if (m_interrupt_policy.has_intersections)
+ if (BOOST_GEOMETRY_CONDITION(m_interrupt_policy.has_intersections))
{
// TODO: we should give partition an interrupt policy.
// Now we throw, and catch below, to stop the partition loop.
@@ -121,15 +124,19 @@ struct get_turns
{
typedef model::box
<
- typename geometry::point_type<Geometry>::type
+ typename geometry::robust_point_type
+ <
+ typename geometry::point_type<Geometry>::type,
+ RobustPolicy
+ >::type
> box_type;
- typedef typename geometry::sections
- <
- box_type, 1
- > sections_type;
+
+ typedef geometry::sections<box_type, 1> sections_type;
+
+ typedef boost::mpl::vector_c<std::size_t, 0> dimensions;
sections_type sec;
- geometry::sectionalize<false>(geometry, robust_policy, false, sec);
+ geometry::sectionalize<false, dimensions>(geometry, robust_policy, sec);
self_section_visitor
<
@@ -142,8 +149,8 @@ struct get_turns
geometry::partition
<
box_type,
- detail::get_turns::get_section_box,
- detail::get_turns::ovelaps_section_box
+ detail::section::get_section_box,
+ detail::section::overlaps_section_box
>::apply(sec, visitor);
}
catch(self_ip_exception const& )
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
index a44d5637bc..25a34ba2ec 100644
--- a/boost/geometry/algorithms/detail/partition.hpp
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -10,7 +10,6 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
#include <vector>
-#include <boost/assert.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
@@ -24,7 +23,7 @@ namespace detail { namespace partition
typedef std::vector<std::size_t> index_vector_type;
template <int Dimension, typename Box>
-void divide_box(Box const& box, Box& lower_box, Box& upper_box)
+inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
{
typedef typename coordinate_type<Box>::type ctype;
@@ -79,20 +78,39 @@ inline void divide_into_subsets(Box const& lower_box,
}
else
{
- // Is nowhere! Should not occur!
- BOOST_ASSERT(false);
+ // Is nowhere. That is (since 1.58) possible, it might be
+ // skipped by the OverlapsPolicy to enhance performance
}
}
}
+template <typename ExpandPolicy, typename Box, typename InputCollection>
+inline void expand_with_elements(Box& total,
+ InputCollection const& collection,
+ index_vector_type const& input)
+{
+ typedef boost::range_iterator<index_vector_type const>::type it_type;
+ for(it_type it = boost::begin(input); it != boost::end(input); ++it)
+ {
+ ExpandPolicy::apply(total, collection[*it]);
+ }
+}
+
+
// Match collection with itself
template <typename InputCollection, typename Policy>
inline void handle_one(InputCollection const& collection,
index_vector_type const& input,
Policy& policy)
{
+ if (boost::size(input) == 0)
+ {
+ return;
+ }
+
typedef boost::range_iterator<index_vector_type const>::type
index_iterator_type;
+
// Quadratic behaviour at lowest level (lowest quad, or all exceeding)
for(index_iterator_type it1 = boost::begin(input);
it1 != boost::end(input);
@@ -118,6 +136,11 @@ inline void handle_two(
InputCollection2 const& collection2, index_vector_type const& input2,
Policy& policy)
{
+ if (boost::size(input1) == 0 || boost::size(input2) == 0)
+ {
+ return;
+ }
+
typedef boost::range_iterator
<
index_vector_type const
@@ -136,43 +159,116 @@ inline void handle_two(
}
}
+inline bool recurse_ok(index_vector_type 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,
+ 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,
+ std::size_t min_elements, std::size_t level)
+{
+ return boost::size(input1) >= min_elements
+ && recurse_ok(input2, input3, min_elements, level);
+}
+
+template
+<
+ int Dimension,
+ typename Box,
+ typename OverlapsPolicy1,
+ typename OverlapsPolicy2,
+ typename ExpandPolicy1,
+ typename ExpandPolicy2,
+ typename VisitBoxPolicy
+>
+class partition_two_collections;
+
+
template
<
int Dimension,
typename Box,
typename OverlapsPolicy,
+ typename ExpandPolicy,
typename VisitBoxPolicy
>
class partition_one_collection
{
typedef std::vector<std::size_t> index_vector_type;
- typedef typename coordinate_type<Box>::type ctype;
- typedef partition_one_collection
+
+ template <typename InputCollection>
+ static inline Box get_new_box(InputCollection const& collection,
+ index_vector_type const& input)
+ {
+ Box box;
+ geometry::assign_inverse(box);
+ expand_with_elements<ExpandPolicy>(box, collection, input);
+ return box;
+ }
+
+ template <typename InputCollection, typename Policy>
+ static inline void next_level(Box const& box,
+ InputCollection const& collection,
+ index_vector_type 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
<
1 - Dimension,
Box,
OverlapsPolicy,
+ ExpandPolicy,
VisitBoxPolicy
- > sub_divide;
+ >::apply(box, collection, input,
+ level + 1, min_elements, policy, box_policy);
+ }
+ else
+ {
+ handle_one(collection, input, policy);
+ }
+ }
+ // Function to switch to two collections if there are geometries exceeding
+ // the separation line
template <typename InputCollection, typename Policy>
- static inline void next_level(Box const& box,
+ static inline void next_level2(Box const& box,
InputCollection const& collection,
- index_vector_type const& input,
- int level, std::size_t min_elements,
+ index_vector_type const& input1,
+ index_vector_type const& input2,
+ std::size_t level, std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
- if (boost::size(input) > 0)
+
+ if (recurse_ok(input1, input2, min_elements, level))
{
- if (std::size_t(boost::size(input)) > min_elements && level < 100)
- {
- sub_divide::apply(box, collection, input, level + 1,
- min_elements, policy, box_policy);
- }
- else
- {
- handle_one(collection, input, policy);
- }
+ partition_two_collections
+ <
+ 1 - Dimension,
+ Box,
+ OverlapsPolicy, OverlapsPolicy,
+ ExpandPolicy, ExpandPolicy,
+ VisitBoxPolicy
+ >::apply(box, collection, input1, collection, input2,
+ level + 1, min_elements, policy, box_policy);
+ }
+ else
+ {
+ handle_two(collection, input1, collection, input2, policy);
}
}
@@ -181,7 +277,7 @@ public :
static inline void apply(Box const& box,
InputCollection const& collection,
index_vector_type const& input,
- int level,
+ std::size_t level,
std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
@@ -196,11 +292,20 @@ public :
if (boost::size(exceeding) > 0)
{
- // All what is not fitting a partition should be combined
- // with each other, and with all which is fitting.
- handle_one(collection, exceeding, policy);
- handle_two(collection, exceeding, collection, lower, policy);
- handle_two(collection, exceeding, collection, upper, policy);
+ // Get the box of exceeding-only
+ Box exceeding_box = get_new_box(collection, 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);
}
// Recursively call operation both parts
@@ -217,20 +322,13 @@ template
typename Box,
typename OverlapsPolicy1,
typename OverlapsPolicy2,
+ typename ExpandPolicy1,
+ typename ExpandPolicy2,
typename VisitBoxPolicy
>
class partition_two_collections
{
typedef std::vector<std::size_t> index_vector_type;
- typedef typename coordinate_type<Box>::type ctype;
- typedef partition_two_collections
- <
- 1 - Dimension,
- Box,
- OverlapsPolicy1,
- OverlapsPolicy2,
- VisitBoxPolicy
- > sub_divide;
template
<
@@ -243,25 +341,50 @@ class partition_two_collections
index_vector_type const& input1,
InputCollection2 const& collection2,
index_vector_type const& input2,
- int level, std::size_t min_elements,
+ std::size_t level, std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
- if (boost::size(input1) > 0 && boost::size(input2) > 0)
- {
- if (std::size_t(boost::size(input1)) > min_elements
- && std::size_t(boost::size(input2)) > min_elements
- && level < 100)
- {
- sub_divide::apply(box, collection1, input1, collection2,
- input2, level + 1, min_elements,
- policy, box_policy);
- }
- else
- {
- box_policy.apply(box, level + 1);
- handle_two(collection1, input1, collection2, input2, policy);
- }
- }
+ partition_two_collections
+ <
+ 1 - Dimension,
+ Box,
+ OverlapsPolicy1,
+ OverlapsPolicy2,
+ ExpandPolicy1,
+ ExpandPolicy2,
+ VisitBoxPolicy
+ >::apply(box, collection1, input1, collection2, 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)
+ {
+ Box box;
+ geometry::assign_inverse(box);
+ expand_with_elements<ExpandPolicy>(box, collection, 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)
+ {
+ Box box = get_new_box<ExpandPolicy1>(collection1, input1);
+ expand_with_elements<ExpandPolicy2>(box, collection2, input2);
+ return box;
}
public :
@@ -274,7 +397,7 @@ public :
static inline void apply(Box const& box,
InputCollection1 const& collection1, index_vector_type const& input1,
InputCollection2 const& collection2, index_vector_type const& input2,
- int level,
+ std::size_t level,
std::size_t min_elements,
Policy& policy, VisitBoxPolicy& box_policy)
{
@@ -293,36 +416,100 @@ public :
if (boost::size(exceeding1) > 0)
{
// All exceeding from 1 with 2:
- handle_two(collection1, exceeding1, collection2, exceeding2,
- policy);
+
+ 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);
+ }
+ else
+ {
+ handle_two(collection1, exceeding1, collection2, exceeding2,
+ policy);
+ }
// All exceeding from 1 with lower and upper of 2:
- handle_two(collection1, exceeding1, collection2, lower2, policy);
- handle_two(collection1, exceeding1, collection2, upper2, policy);
+
+ // (Check sizes of all three collections 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);
+ }
+ else
+ {
+ handle_two(collection1, exceeding1, collection2, lower2, policy);
+ handle_two(collection1, exceeding1, collection2, upper2, policy);
+ }
}
+
if (boost::size(exceeding2) > 0)
{
// All exceeding from 2 with lower and upper of 1:
- handle_two(collection1, lower1, collection2, exceeding2, policy);
- handle_two(collection1, upper1, collection2, exceeding2, policy);
+ 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);
+ }
+ else
+ {
+ handle_two(collection1, lower1, collection2, exceeding2, policy);
+ handle_two(collection1, upper1, collection2, exceeding2, policy);
+ }
}
- next_level(lower_box, collection1, lower1, collection2, lower2, level,
- min_elements, policy, box_policy);
- next_level(upper_box, collection1, upper1, collection2, upper2, level,
- min_elements, policy, box_policy);
+ if (recurse_ok(lower1, lower2, min_elements, level))
+ {
+ next_level(lower_box, collection1, lower1, collection2, lower2, level,
+ min_elements, policy, box_policy);
+ }
+ else
+ {
+ handle_two(collection1, lower1, collection2, lower2, policy);
+ }
+ if (recurse_ok(upper1, upper2, min_elements, level))
+ {
+ next_level(upper_box, collection1, upper1, collection2, upper2, level,
+ min_elements, policy, box_policy);
+ }
+ else
+ {
+ handle_two(collection1, upper1, collection2, upper2, policy);
+ }
}
};
-}} // namespace detail::partition
-
struct visit_no_policy
{
template <typename Box>
- static inline void apply(Box const&, int )
+ static inline void apply(Box const&, std::size_t )
{}
};
+struct include_all_policy
+{
+ template <typename Item>
+ static inline bool apply(Item const&)
+ {
+ return true;
+ }
+};
+
+
+}} // namespace detail::partition
+
template
<
typename Box,
@@ -330,13 +517,15 @@ template
typename OverlapsPolicy1,
typename ExpandPolicy2 = ExpandPolicy1,
typename OverlapsPolicy2 = OverlapsPolicy1,
- typename VisitBoxPolicy = visit_no_policy
+ typename IncludePolicy1 = detail::partition::include_all_policy,
+ typename IncludePolicy2 = detail::partition::include_all_policy,
+ typename VisitBoxPolicy = detail::partition::visit_no_policy
>
class partition
{
typedef std::vector<std::size_t> index_vector_type;
- template <typename ExpandPolicy, typename InputCollection>
+ template <typename ExpandPolicy, typename IncludePolicy, typename InputCollection>
static inline void expand_to_collection(InputCollection const& collection,
Box& total, index_vector_type& index_vector)
{
@@ -346,8 +535,11 @@ class partition
it != boost::end(collection);
++it, ++index)
{
- ExpandPolicy::apply(total, *it);
- index_vector.push_back(index);
+ if (IncludePolicy::apply(*it))
+ {
+ ExpandPolicy::apply(total, *it);
+ index_vector.push_back(index);
+ }
}
}
@@ -356,7 +548,7 @@ public :
static inline void apply(InputCollection const& collection,
VisitPolicy& visitor,
std::size_t min_elements = 16,
- VisitBoxPolicy box_visitor = visit_no_policy()
+ VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()
)
{
if (std::size_t(boost::size(collection)) > min_elements)
@@ -364,12 +556,14 @@ public :
index_vector_type index_vector;
Box total;
assign_inverse(total);
- expand_to_collection<ExpandPolicy1>(collection, total, index_vector);
+ expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection,
+ total, index_vector);
detail::partition::partition_one_collection
<
0, Box,
OverlapsPolicy1,
+ ExpandPolicy1,
VisitBoxPolicy
>::apply(total, collection, index_vector, 0, min_elements,
visitor, box_visitor);
@@ -403,7 +597,7 @@ public :
InputCollection2 const& collection2,
VisitPolicy& visitor,
std::size_t min_elements = 16,
- VisitBoxPolicy box_visitor = visit_no_policy()
+ VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()
)
{
if (std::size_t(boost::size(collection1)) > min_elements
@@ -412,12 +606,15 @@ public :
index_vector_type index_vector1, index_vector2;
Box total;
assign_inverse(total);
- expand_to_collection<ExpandPolicy1>(collection1, total, index_vector1);
- expand_to_collection<ExpandPolicy2>(collection2, total, index_vector2);
+ expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection1,
+ total, index_vector1);
+ expand_to_collection<ExpandPolicy2, IncludePolicy2>(collection2,
+ total, index_vector2);
detail::partition::partition_two_collections
<
- 0, Box, OverlapsPolicy1, OverlapsPolicy2, VisitBoxPolicy
+ 0, Box, OverlapsPolicy1, OverlapsPolicy2,
+ ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy
>::apply(total,
collection1, index_vector1,
collection2, index_vector2,
diff --git a/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp b/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
index cd3acb5ba4..9db1ef8e0c 100644
--- a/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
+++ b/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp
@@ -17,6 +17,7 @@
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
@@ -91,7 +92,7 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point,
return true;
}
- if (! RobustPolicy::enabled)
+ if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled))
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
index 31d206ac99..2859841de4 100644
--- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
@@ -2,19 +2,21 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 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)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP
#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
@@ -197,7 +199,7 @@ struct areal_areal
// The result should be FFFFFFFFF
relate::set<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
// get and analyse turns
@@ -207,17 +209,17 @@ struct areal_areal
interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
no_turns_aa_pred<Geometry2, Result, false> pred1(geometry2, result);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
no_turns_aa_pred<Geometry1, Result, true> pred2(geometry1, result);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
if ( turns.empty() )
@@ -242,7 +244,7 @@ struct areal_areal
turns_analyser<turn_type, 0> analyser;
analyse_each_turn(result, analyser, turns.begin(), turns.end());
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
}
@@ -257,7 +259,7 @@ struct areal_areal
uncertain_rings_analyser<0, Result, Geometry1, Geometry2> rings_analyser(result, geometry1, geometry2);
analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end());
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
}
}
@@ -281,7 +283,7 @@ struct areal_areal
turns_analyser<turn_type, 1> analyser;
analyse_each_turn(result, analyser, turns.begin(), turns.end());
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
}
@@ -549,7 +551,7 @@ struct areal_areal
{
analyser.apply(res, it);
- if ( res.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(res.interrupt) )
return;
}
@@ -573,8 +575,7 @@ struct areal_areal
{
// check which relations must be analysed
- if ( ! may_update<interior, interior, '2', transpose_result>(m_result)
- && ! may_update<boundary, interior, '1', transpose_result>(m_result) )
+ if ( ! may_update<interior, interior, '2', transpose_result>(m_result) )
{
m_flags |= 1;
}
@@ -595,7 +596,7 @@ struct areal_areal
inline void no_turns(segment_identifier const& seg_id)
{
// if those flags are set nothing will change
- if ( (m_flags & 3) == 3 )
+ if ( m_flags == 7 )
{
return;
}
@@ -614,15 +615,18 @@ struct areal_areal
// to know which other single geometries should be checked
// TODO: optimize! e.g. use spatial index
- // O(N) - running it in a loop would gives O(NM)
+ // 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);
if ( pig > 0 )
{
- update<boundary, interior, '1', transpose_result>(m_result);
update<interior, interior, '2', transpose_result>(m_result);
m_flags |= 1;
+
+ update<boundary, interior, '1', transpose_result>(m_result);
+ update<exterior, interior, '2', transpose_result>(m_result);
+ m_flags |= 4;
}
else
{
@@ -696,12 +700,6 @@ struct areal_areal
update<boundary, exterior, '1', transpose_result>(m_result);
update<interior, exterior, '2', transpose_result>(m_result);
m_flags |= 2;
-
- // not necessary since this will be checked in the next iteration
- // but increases the pruning strength
- // WARNING: this is not reflected in flags
- update<exterior, boundary, '1', transpose_result>(m_result);
- update<exterior, interior, '2', transpose_result>(m_result);
}
interrupt = m_flags == 7 || m_result.interrupt; // interrupt if the result won't be changed in the future
@@ -795,7 +793,8 @@ struct areal_areal
{
segment_identifier const& seg_id = turn.operations[OpId].seg_id;
- int count = boost::numeric_cast<int>(
+ signed_index_type
+ count = boost::numeric_cast<signed_index_type>(
geometry::num_interior_rings(
detail::single_geometry(analyser.geometry, seg_id)));
@@ -803,7 +802,10 @@ struct areal_areal
}
template <typename Analyser, typename Turn>
- static inline void for_no_turns_rings(Analyser & analyser, Turn const& turn, int first, int last)
+ static inline void for_no_turns_rings(Analyser & analyser,
+ Turn const& turn,
+ signed_index_type first,
+ signed_index_type last)
{
segment_identifier seg_id = turn.operations[OpId].seg_id;
diff --git a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
index 78fa03798d..2c44b009e7 100644
--- a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
+++ b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
@@ -14,6 +14,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
//#include <boost/geometry/algorithms/detail/sub_range.hpp>
@@ -98,9 +99,9 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
std::vector<bool> detected_intersections(count, false);
for ( TurnIt it = first ; it != last ; ++it )
{
- int multi_index = it->operations[OpId].seg_id.multi_index;
+ signed_index_type multi_index = it->operations[OpId].seg_id.multi_index;
BOOST_ASSERT(multi_index >= 0);
- std::size_t index = static_cast<std::size_t>(multi_index);
+ std::size_t const index = static_cast<std::size_t>(multi_index);
BOOST_ASSERT(index < count);
detected_intersections[index] = true;
}
@@ -116,8 +117,8 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
if ( *it == false )
{
found = true;
- bool cont = pred(range::at(geometry,
- std::distance(detected_intersections.begin(), it)));
+ std::size_t const index = std::size_t(std::distance(detected_intersections.begin(), it));
+ bool cont = pred(range::at(geometry, index));
if ( !cont )
break;
}
@@ -375,14 +376,14 @@ static inline bool is_ip_on_boundary(IntersectionPoint const& ip,
bool res = false;
// IP on the last point of the linestring
- if ( (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
+ if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
&& operation_info.position == overlay::position_back )
{
// check if this point is a boundary
res = boundary_checker.template is_endpoint_boundary<boundary_back>(ip);
}
// IP on the last point of the linestring
- else if ( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
+ else if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
&& operation_info.position == overlay::position_front )
{
// check if this point is a boundary
diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
index 3159ab329d..7d85a1d9a1 100644
--- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
@@ -2,21 +2,23 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 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)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
@@ -193,6 +195,33 @@ struct linear_areal
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
+
+ template <typename Geometry>
+ struct is_multi
+ : boost::is_base_of
+ <
+ multi_tag,
+ typename tag<Geometry>::type
+ >
+ {};
+
+ template <typename Geom1, typename Geom2>
+ struct multi_turn_info
+ : turns::get_turns<Geom1, Geom2>::turn_info
+ {
+ multi_turn_info() : priority(0) {}
+ int priority; // single-geometry sorting priority
+ };
+
+ template <typename Geom1, typename Geom2>
+ struct turn_info_type
+ : boost::mpl::if_c
+ <
+ is_multi<Geometry2>::value,
+ multi_turn_info<Geom1, Geom2>,
+ typename turns::get_turns<Geom1, Geom2>::turn_info
+ >
+ {};
template <typename Result>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)
@@ -202,17 +231,17 @@ struct linear_areal
// The result should be FFFFFFFFF
relate::set<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
// get and analyse turns
- typedef typename turns::get_turns<Geometry1, Geometry2>::turn_info turn_type;
+ typedef typename turn_info_type<Geometry1, Geometry2>::type turn_type;
std::vector<turn_type> turns;
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
boundary_checker<Geometry1> boundary_checker1(geometry1);
@@ -224,12 +253,12 @@ struct linear_areal
TransposeResult
> pred1(geometry2, result, boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
no_turns_la_areal_pred<Result, !TransposeResult> pred2(result);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
if ( turns.empty() )
@@ -238,14 +267,11 @@ struct linear_areal
// This is set here because in the case if empty Areal geometry were passed
// those shouldn't be set
relate::set<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
{
- // for different multi or same ring id: x, u, i, c
- // for same multi and different ring id: c, i, u, x
- typedef turns::less<0, turns::less_op_linear_areal<0> > less;
- std::sort(turns.begin(), turns.end(), less());
+ sort_dispatch(turns.begin(), turns.end(), is_multi<Geometry2>());
turns_analyser<turn_type> analyser;
analyse_each_turn(result, analyser,
@@ -253,7 +279,7 @@ struct linear_areal
geometry1, geometry2,
boundary_checker1);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
}
@@ -297,7 +323,7 @@ struct linear_areal
// if there was some previous ring
if ( prev_seg_id_ptr != NULL )
{
- int const next_ring_index = prev_seg_id_ptr->ring_index + 1;
+ signed_index_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
BOOST_ASSERT(next_ring_index >= 0);
// if one of the last rings of previous single geometry was ommited
@@ -368,7 +394,7 @@ struct linear_areal
// if there was some previous ring
if ( prev_seg_id_ptr != NULL )
{
- int const next_ring_index = prev_seg_id_ptr->ring_index + 1;
+ signed_index_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
BOOST_ASSERT(next_ring_index >= 0);
// if one of the last rings of previous single geometry was ommited
@@ -383,6 +409,127 @@ struct linear_areal
}
}
+ template <typename It, typename Pred, typename Comp>
+ static void for_each_equal_range(It first, It last, Pred pred, Comp comp)
+ {
+ if ( first == last )
+ return;
+
+ It first_equal = first;
+ It prev = first;
+ for ( ++first ; ; ++first, ++prev )
+ {
+ if ( first == last || !comp(*prev, *first) )
+ {
+ pred(first_equal, first);
+ first_equal = first;
+ }
+
+ if ( first == last )
+ break;
+ }
+ }
+
+ struct same_ip
+ {
+ template <typename Turn>
+ bool operator()(Turn const& left, Turn const& right) const
+ {
+ return left.operations[0].seg_id == right.operations[0].seg_id
+ && left.operations[0].fraction == right.operations[0].fraction;
+ }
+ };
+
+ struct same_ip_and_multi_index
+ {
+ template <typename Turn>
+ bool operator()(Turn const& left, Turn const& right) const
+ {
+ return same_ip()(left, right)
+ && left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index;
+ }
+ };
+
+ template <typename OpToPriority>
+ struct set_turns_group_priority
+ {
+ template <typename TurnIt>
+ void operator()(TurnIt first, TurnIt last) const
+ {
+ BOOST_ASSERT(first != last);
+ static OpToPriority op_to_priority;
+ // find the operation with the least priority
+ int least_priority = op_to_priority(first->operations[0]);
+ for ( TurnIt it = first + 1 ; it != last ; ++it )
+ {
+ int priority = op_to_priority(it->operations[0]);
+ if ( priority < least_priority )
+ least_priority = priority;
+ }
+ // set the least priority for all turns of the group
+ for ( TurnIt it = first ; it != last ; ++it )
+ {
+ it->priority = least_priority;
+ }
+ }
+ };
+
+ template <typename SingleLess>
+ struct sort_turns_group
+ {
+ struct less
+ {
+ template <typename Turn>
+ bool operator()(Turn const& left, Turn const& right) const
+ {
+ return left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index ?
+ SingleLess()(left, right) :
+ left.priority < right.priority;
+ }
+ };
+
+ template <typename TurnIt>
+ void operator()(TurnIt first, TurnIt last) const
+ {
+ std::sort(first, last, less());
+ }
+ };
+
+ template <typename TurnIt>
+ static void sort_dispatch(TurnIt first, TurnIt last, boost::true_type const& /*is_multi*/)
+ {
+ // sort turns by Linear seg_id, then by fraction, then by other multi_index
+ typedef turns::less<0, turns::less_other_multi_index<0> > less;
+ std::sort(first, last, less());
+
+ // For the same IP and multi_index - the same other's single geometry
+ // set priorities as the least operation found for the whole single geometry
+ // so e.g. single geometries containing 'u' will always be before those only containing 'i'
+ typedef turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
+ for_each_equal_range(first, last,
+ set_turns_group_priority<op_to_int_xuic>(), // least operation in xuic order
+ same_ip_and_multi_index()); // other's multi_index
+
+ // When priorities for single geometries are set now sort turns for the same IP
+ // if multi_index is the same sort them according to the single-less
+ // else use priority of the whole single-geometry set earlier
+ typedef turns::less<0, turns::less_op_linear_areal_single<0> > single_less;
+ for_each_equal_range(first, last,
+ sort_turns_group<single_less>(),
+ same_ip());
+ }
+
+ template <typename TurnIt>
+ static void sort_dispatch(TurnIt first, TurnIt last, boost::false_type const& /*is_multi*/)
+ {
+ // sort turns by Linear seg_id, then by fraction, then
+ // for same ring id: x, u, i, c
+ // for different ring id: c, i, u, x
+ typedef turns::less<0, turns::less_op_linear_areal_single<0> > less;
+ std::sort(first, last, less());
+ }
+
+
// interrupt policy which may be passed to get_turns to interrupt the analysis
// based on the info in the passed result/mask
template <typename Areal, typename Result>
@@ -458,6 +605,8 @@ struct linear_areal
, m_boundary_counter(0)
, m_interior_detected(false)
, m_first_interior_other_id_ptr(NULL)
+ , m_first_from_unknown(false)
+ , m_first_from_unknown_boundary_detected(false)
{}
template <typename Result,
@@ -485,6 +634,11 @@ struct linear_areal
const bool first_in_range = m_seg_watcher.update(seg_id);
+ // TODO: should apply() for the post-last ip be called if first_in_range ?
+ // this would unify how last points in ranges are handled
+ // possibly replacing parts of the code below
+ // e.g. for is_multi and m_interior_detected
+
// handle possible exit
bool fake_enter_detected = false;
if ( m_exit_watcher.get_exit_operation() == overlay::operation_union )
@@ -495,8 +649,24 @@ struct linear_areal
{
m_exit_watcher.reset_detected_exit();
- // not the last IP
update<interior, exterior, '1', TransposeResult>(res);
+
+ // next single geometry
+ if ( first_in_range && m_previous_turn_ptr )
+ {
+ // NOTE: similar code is in the post-last-ip-apply()
+ 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);
+
+ // if there is a boundary on the last point
+ if ( prev_back_b )
+ {
+ update<boundary, exterior, '0', TransposeResult>(res);
+ }
+ }
}
// fake exit point, reset state
else if ( op == overlay::operation_intersection
@@ -508,9 +678,12 @@ struct linear_areal
}
else if ( m_exit_watcher.get_exit_operation() == overlay::operation_blocked )
{
- // ignore multiple BLOCKs
- if ( op == overlay::operation_blocked )
+ // ignore multiple BLOCKs for this same single geometry1
+ if ( op == overlay::operation_blocked
+ && seg_id.multi_index == m_previous_turn_ptr->operations[op_id].seg_id.multi_index )
+ {
return;
+ }
if ( ( op == overlay::operation_intersection
|| op == overlay::operation_continue )
@@ -522,11 +695,39 @@ struct linear_areal
m_exit_watcher.reset_detected_exit();
}
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )
+ && m_first_from_unknown )
+ {
+ // 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
+ // then we know that the LineString is outside
+ // Similar with the u/u turns, if it was the first one it doesn't mean that the
+ // Linestring came from the exterior
+ if ( ( m_previous_operation == overlay::operation_blocked
+ && ( op != overlay::operation_blocked // operation different than block
+ || seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) ) // or the next single-geometry
+ || ( m_previous_operation == overlay::operation_union
+ && ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )
+ )
+ {
+ update<interior, exterior, '1', TransposeResult>(res);
+ if ( m_first_from_unknown_boundary_detected )
+ {
+ update<boundary, exterior, '0', TransposeResult>(res);
+ }
+
+ m_first_from_unknown = false;
+ m_first_from_unknown_boundary_detected = false;
+ }
+ }
+
// NOTE: THE WHOLE m_interior_detected HANDLING IS HERE BECAUSE WE CAN'T EFFICIENTLY SORT TURNS (CORRECTLY)
// BECAUSE THE SAME IP MAY BE REPRESENTED BY TWO SEGMENTS WITH DIFFERENT DISTANCES
// IT WOULD REQUIRE THE CALCULATION OF MAX DISTANCE
// TODO: WE COULD GET RID OF THE TEST IF THE DISTANCES WERE NORMALIZED
+// UPDATE: THEY SHOULD BE NORMALIZED NOW
+
// TODO: THIS IS POTENTIALLY ERROREOUS!
// THIS ALGORITHM DEPENDS ON SOME SPECIFIC SEQUENCE OF OPERATIONS
// IT WOULD GIVE WRONG RESULTS E.G.
@@ -540,6 +741,30 @@ struct linear_areal
{
update<interior, interior, '1', TransposeResult>(res);
m_interior_detected = false;
+
+ // 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;
+
+ 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);
+ }
+ }
+
+ // The exit_watcher is reset below
+ // m_exit_watcher.reset();
+ }
}
// fake interior overlap
else if ( op == overlay::operation_continue )
@@ -560,10 +785,20 @@ struct linear_areal
}
}
+ // NOTE: If post-last-ip apply() was called this wouldn't be needed
+ if ( first_in_range )
+ {
+ m_exit_watcher.reset();
+ m_boundary_counter = 0;
+ m_first_from_unknown = false;
+ m_first_from_unknown_boundary_detected = false;
+ }
+
// i/u, c/u
if ( op == overlay::operation_intersection
|| op == overlay::operation_continue ) // operation_boundary/operation_boundary_intersection
{
+ bool const first_point = first_in_range || m_first_from_unknown;
bool no_enters_detected = m_exit_watcher.is_outside();
m_exit_watcher.enter(*it);
@@ -592,7 +827,7 @@ struct linear_areal
{
// don't add to the count for all met boundaries
// only if this is the "new" boundary
- if ( first_in_range || !it->operations[op_id].is_collinear )
+ if ( first_point || !it->operations[op_id].is_collinear )
++m_boundary_counter;
update<interior, boundary, '1', TransposeResult>(res);
@@ -619,7 +854,7 @@ struct linear_areal
&& it->operations[op_id].position != overlay::position_front )
{
// TODO: calculate_from_inside() is only needed if the current Linestring is not closed
- bool const from_inside = first_in_range
+ bool const from_inside = first_point
&& calculate_from_inside(geometry,
other_geometry,
*it);
@@ -630,7 +865,7 @@ struct linear_areal
update<interior, exterior, '1', TransposeResult>(res);
// if it's the first IP then the first point is outside
- if ( first_in_range )
+ if ( first_point )
{
bool const front_b = is_endpoint_on_boundary<boundary_front>(
range::front(sub_range(geometry, seg_id)),
@@ -647,6 +882,12 @@ struct linear_areal
}
}
}
+
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value ) )
+ {
+ m_first_from_unknown = false;
+ m_first_from_unknown_boundary_detected = false;
+ }
}
// u/u, x/u
else if ( op == overlay::operation_union || op == overlay::operation_blocked )
@@ -709,7 +950,11 @@ struct linear_areal
if ( it->operations[op_id].position != overlay::position_front )
{
// TODO: calculate_from_inside() is only needed if the current Linestring is not closed
- bool const first_from_inside = first_in_range
+ // NOTE: this is not enough for MultiPolygon and operation_blocked
+ // For LS/MultiPolygon multiple x/u turns may be generated
+ // the first checked Polygon may be the one which LS is outside for.
+ bool const first_point = first_in_range || m_first_from_unknown;
+ bool const first_from_inside = first_point
&& calculate_from_inside(geometry,
other_geometry,
*it);
@@ -719,14 +964,26 @@ struct linear_areal
// notify the exit_watcher that we started inside
m_exit_watcher.enter(*it);
+ // and reset unknown flags since we know that we started inside
+ m_first_from_unknown = false;
+ m_first_from_unknown_boundary_detected = false;
}
else
{
- update<interior, exterior, '1', TransposeResult>(res);
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )
+ /*&& ( op == overlay::operation_blocked
+ || op == overlay::operation_union )*/ ) // if we're here it's u or x
+ {
+ m_first_from_unknown = true;
+ }
+ else
+ {
+ update<interior, exterior, '1', TransposeResult>(res);
+ }
}
// first IP on the last segment point - this means that the first point is outside or inside
- if ( first_in_range && ( !this_b || op_blocked ) )
+ if ( first_point && ( !this_b || op_blocked ) )
{
bool const front_b = is_endpoint_on_boundary<boundary_front>(
range::front(sub_range(geometry, seg_id)),
@@ -736,9 +993,23 @@ struct linear_areal
if ( front_b )
{
if ( first_from_inside )
+ {
update<boundary, interior, '0', TransposeResult>(res);
+ }
else
- update<boundary, exterior, '0', TransposeResult>(res);
+ {
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )
+ /*&& ( op == overlay::operation_blocked
+ || op == overlay::operation_union )*/ ) // if we're here it's u or x
+ {
+ BOOST_ASSERT(m_first_from_unknown);
+ m_first_from_unknown_boundary_detected = true;
+ }
+ else
+ {
+ update<boundary, exterior, '0', TransposeResult>(res);
+ }
+ }
}
}
}
@@ -774,6 +1045,23 @@ struct linear_areal
boost::ignore_unused(first, last);
//BOOST_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
+ // then we know that the LineString is outside
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )
+ && m_first_from_unknown )
+ {
+ update<interior, exterior, '1', TransposeResult>(res);
+ if ( m_first_from_unknown_boundary_detected )
+ {
+ update<boundary, exterior, '0', TransposeResult>(res);
+ }
+
+ // done below
+ //m_first_from_unknown = false;
+ //m_first_from_unknown_boundary_detected = false;
+ }
+
// here, the possible exit is the real one
// we know that we entered and now we exit
if ( /*m_exit_watcher.get_exit_operation() == overlay::operation_union // THIS CHECK IS REDUNDANT
@@ -822,12 +1110,37 @@ struct linear_areal
}
}
- BOOST_ASSERT_MSG(m_previous_operation != overlay::operation_continue,
- "Unexpected operation! Probably the error in get_turns(L,A) or relate(L,A)");
+ // 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,
+ // "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
+ // When a Linestring is going in on a collinear spike
+ // the turn is not generated for the entry
+ // So assume it's the former
+ if ( m_previous_operation == overlay::operation_continue )
+ {
+ update<interior, exterior, '1', TransposeResult>(res);
+
+ 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);
+
+ // if there is a boundary on the last point
+ if ( prev_back_b )
+ {
+ update<boundary, exterior, '0', TransposeResult>(res);
+ }
+ }
// Reset exit watcher before the analysis of the next Linestring
m_exit_watcher.reset();
m_boundary_counter = 0;
+ m_first_from_unknown = false;
+ m_first_from_unknown_boundary_detected = false;
}
// check if the passed turn's segment of Linear geometry arrived
@@ -852,8 +1165,8 @@ struct linear_areal
BOOST_ASSERT(s2 > 2);
std::size_t const seg_count2 = s2 - 1;
- std::size_t const p_seg_ij = turn.operations[op_id].seg_id.segment_index;
- std::size_t const q_seg_ij = turn.operations[other_op_id].seg_id.segment_index;
+ 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);
@@ -876,7 +1189,7 @@ struct linear_areal
// TODO: the following function should return immediately, however the worst case complexity is O(N)
// It would be good to replace it with some O(1) mechanism
range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),
- boost::begin(range2) + q_seg_jk,
+ range::pos(range2, q_seg_jk),
boost::end(range2));
// Will this sequence of points be always correct?
@@ -945,6 +1258,8 @@ struct linear_areal
unsigned m_boundary_counter;
bool m_interior_detected;
const segment_identifier * m_first_interior_other_id_ptr;
+ bool m_first_from_unknown;
+ bool m_first_from_unknown_boundary_detected;
};
// call analyser.apply() for each turn in range
@@ -971,7 +1286,7 @@ struct linear_areal
geometry, other_geometry,
boundary_checker);
- if ( res.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
return;
}
@@ -1017,8 +1332,8 @@ struct linear_areal
if ( first == last )
return last;
- int const multi_index = first->operations[1].seg_id.multi_index;
- int const ring_index = first->operations[1].seg_id.ring_index;
+ 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;
fun(*first);
++first;
diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
index 263c82de56..20a22c3018 100644
--- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015.
+// Modifications copyright (c) 2013-2015 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
@@ -16,6 +16,7 @@
#include <boost/core/ignore_unused.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
@@ -117,7 +118,7 @@ struct linear_linear
{
// The result should be FFFFFFFFF
relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
// get and analyse turns
@@ -133,19 +134,19 @@ struct linear_linear
detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> >
>::apply(turns, geometry1, geometry2, interrupt_policy);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
boundary_checker<Geometry1> boundary_checker1(geometry1);
disjoint_linestring_pred<Result, boundary_checker<Geometry1>, false> pred1(result, boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
boundary_checker<Geometry2> boundary_checker2(geometry2);
disjoint_linestring_pred<Result, boundary_checker<Geometry2>, true> pred2(result, boundary_checker2);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
if ( turns.empty() )
@@ -171,7 +172,7 @@ struct linear_linear
boundary_checker1, boundary_checker2);
}
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
if ( may_update<interior, interior, '1', true>(result)
@@ -250,6 +251,7 @@ struct linear_linear
: m_previous_turn_ptr(NULL)
, m_previous_operation(overlay::operation_none)
, m_degenerated_turn_ptr(NULL)
+ , m_collinear_spike_exit(false)
{}
template <typename Result,
@@ -383,7 +385,8 @@ struct linear_linear
// if we didn't enter in the past, we were outside
if ( was_outside
&& ! fake_enter_detected
- && it->operations[op_id].position != overlay::position_front )
+ && it->operations[op_id].position != overlay::position_front
+ && ! m_collinear_spike_exit )
{
update<interior, exterior, '1', transpose_result>(res);
@@ -402,6 +405,8 @@ struct linear_linear
}
}
}
+
+ m_collinear_spike_exit = false;
}
// u/i, u/u, u/x, x/i, x/u, x/x
else if ( op == overlay::operation_union || op == overlay::operation_blocked )
@@ -418,6 +423,11 @@ struct linear_linear
if ( !was_outside && is_collinear )
{
m_exit_watcher.exit(*it, false);
+ // if the position is not set to back it must be a spike
+ if ( it->operations[op_id].position != overlay::position_back )
+ {
+ m_collinear_spike_exit = true;
+ }
}
bool const op_blocked = op == overlay::operation_blocked;
@@ -456,6 +466,7 @@ struct linear_linear
// if we are truly outside
if ( was_outside
&& it->operations[op_id].position != overlay::position_front
+ && ! m_collinear_spike_exit
/*&& !is_collinear*/ )
{
update<interior, exterior, '1', transpose_result>(res);
@@ -526,6 +537,7 @@ struct linear_linear
&& ( !this_b || op_blocked )
&& was_outside
&& it->operations[op_id].position != overlay::position_front
+ && ! m_collinear_spike_exit
/*&& !is_collinear*/ )
{
bool const front_b = is_endpoint_on_boundary<boundary_front>(
@@ -607,6 +619,10 @@ struct linear_linear
m_previous_turn_ptr = NULL;
m_previous_operation = overlay::operation_none;
m_degenerated_turn_ptr = NULL;
+
+ // actually if this is set to true here there is some error
+ // in get_turns_ll or relate_ll, an assert could be checked here
+ m_collinear_spike_exit = false;
}
template <typename Result,
@@ -724,6 +740,7 @@ struct linear_linear
const TurnInfo * m_previous_turn_ptr;
overlay::operation_type m_previous_operation;
const TurnInfo * m_degenerated_turn_ptr;
+ bool m_collinear_spike_exit;
};
template <typename Result,
@@ -750,7 +767,7 @@ struct linear_linear
geometry, other_geometry,
boundary_checker, other_boundary_checker);
- if ( res.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
return;
}
diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
index 86c236d357..62ab100919 100644
--- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 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)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
@@ -20,6 +20,8 @@
#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -54,7 +56,7 @@ struct point_geometry
set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
- if ( result.interrupt )
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
// the point is on the boundary
diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp
index 1bcb5275d2..e26bda67f2 100644
--- a/boost/geometry/algorithms/detail/relate/result.hpp
+++ b/boost/geometry/algorithms/detail/relate/result.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 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)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP
@@ -24,6 +24,7 @@
#include <boost/mpl/vector_c.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/util/condition.hpp>
// TEMP - move this header to geometry/detail
#include <boost/geometry/index/detail/tuples.hpp>
@@ -235,17 +236,17 @@ struct interrupt_dispatch<Mask, true>
static inline bool apply(Mask const& mask)
{
char m = mask.template get<F1, F2>();
- return check<V>(m);
+ return check_element<V>(m);
}
template <char V>
- static inline bool check(char m)
+ static inline bool check_element(char m)
{
- if ( V >= '0' && V <= '9' )
+ if ( BOOST_GEOMETRY_CONDITION(V >= '0' && V <= '9') )
{
return m == 'F' || ( m < V && m >= '0' && m <= '9' );
}
- else if ( V == 'T' )
+ else if ( BOOST_GEOMETRY_CONDITION(V == 'T') )
{
return m == 'F';
}
@@ -394,7 +395,7 @@ inline bool may_update(Mask const& mask, Matrix const& matrix)
::template apply<F1, F2, D>(mask, matrix);
}
-// check()
+// check_matrix()
template <typename Mask>
struct check_dispatch
@@ -485,7 +486,7 @@ struct check_dispatch< boost::tuples::cons<Head, Tail> >
};
template <typename Mask, typename Matrix>
-inline bool check(Mask const& mask, Matrix const& matrix)
+inline bool check_matrix(Mask const& mask, Matrix const& matrix)
{
return check_dispatch<Mask>::apply(mask, matrix);
}
@@ -546,7 +547,7 @@ public:
result_type result() const
{
return !interrupt
- && check(m_mask, static_cast<base_t const&>(*this));
+ && check_matrix(m_mask, static_cast<base_t const&>(*this));
}
template <field F1, field F2, char D>
@@ -964,7 +965,7 @@ struct static_check_dispatch<StaticMask, true>
};
template <typename StaticMask>
-struct static_check
+struct static_check_matrix
{
template <typename Matrix>
static inline bool apply(Matrix const& matrix)
@@ -997,7 +998,7 @@ public:
result_type result() const
{
return (!Interrupt || !interrupt)
- && static_check<StaticMask>::
+ && static_check_matrix<StaticMask>::
apply(static_cast<base_t const&>(*this));
}
diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp
index a2e56a8882..636c9756d8 100644
--- a/boost/geometry/algorithms/detail/relate/turns.hpp
+++ b/boost/geometry/algorithms/detail/relate/turns.hpp
@@ -1,16 +1,17 @@
// 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.
-// 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
// 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_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
@@ -19,8 +20,12 @@
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
+
#include <boost/type_traits/is_base_of.hpp>
+
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
@@ -35,10 +40,16 @@ struct assign_policy
// GET_TURNS
-template <typename Geometry1,
- typename Geometry2,
- typename GetTurnPolicy
- = detail::get_turns::get_turn_info_type<Geometry1, Geometry2, assign_policy<> > >
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename GetTurnPolicy = detail::get_turns::get_turn_info_type
+ <
+ Geometry1, Geometry2, assign_policy<>
+ >,
+ typename RobustPolicy = detail::no_rescale_policy
+>
struct get_turns
{
typedef typename geometry::point_type<Geometry1>::type point1_type;
@@ -46,11 +57,14 @@ struct get_turns
typedef overlay::turn_info
<
point1_type,
- typename segment_ratio_type<point1_type, detail::no_rescale_policy>::type,
+ typename segment_ratio_type<point1_type, RobustPolicy>::type,
typename detail::get_turns::turn_operation_type
<
Geometry1, Geometry2,
- typename segment_ratio_type<point1_type, detail::no_rescale_policy>::type
+ typename segment_ratio_type
+ <
+ point1_type, RobustPolicy
+ >::type
>::type
> turn_info;
@@ -73,6 +87,12 @@ struct get_turns
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);
+
+
dispatch::get_turns
<
typename geometry::tag<Geometry1>::type,
@@ -83,7 +103,7 @@ struct get_turns
reverse2,
GetTurnPolicy
>::apply(0, geometry1, 1, geometry2,
- detail::no_rescale_policy(), turns, interrupt_policy);
+ robust_policy, turns, interrupt_policy);
}
};
@@ -125,7 +145,7 @@ struct less_op_linear_linear
{};
template <std::size_t OpId>
-struct less_op_linear_areal
+struct less_op_linear_areal_single
{
template <typename Turn>
inline bool operator()(Turn const& left, Turn const& right) const
@@ -137,27 +157,19 @@ struct less_op_linear_areal
segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
- if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index )
- {
- typedef typename Turn::turn_operation_type operation_type;
- operation_type const& left_operation = left.operations[OpId];
- operation_type const& right_operation = right.operations[OpId];
+ typedef typename Turn::turn_operation_type operation_type;
+ operation_type const& left_operation = left.operations[OpId];
+ operation_type const& right_operation = right.operations[OpId];
- if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
- {
- return op_to_int_xuic(left_operation)
- < op_to_int_xuic(right_operation);
- }
- else
- {
- return op_to_int_xiuc(left_operation)
- < op_to_int_xiuc(right_operation);
- }
+ if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
+ {
+ return op_to_int_xuic(left_operation)
+ < op_to_int_xuic(right_operation);
}
else
{
- //return op_to_int_xuic(left.operations[OpId]) < op_to_int_xuic(right.operations[OpId]);
- return left_other_seg_id.multi_index < right_other_seg_id.multi_index;
+ return op_to_int_xiuc(left_operation)
+ < op_to_int_xiuc(right_operation);
}
}
};
@@ -217,6 +229,19 @@ struct less_op_areal_areal
}
};
+template <std::size_t OpId>
+struct less_other_multi_index
+{
+ static const std::size_t other_op_id = (OpId + 1) % 2;
+
+ template <typename Turn>
+ inline bool operator()(Turn const& left, Turn const& right) const
+ {
+ return left.operations[other_op_id].seg_id.multi_index
+ < right.operations[other_op_id].seg_id.multi_index;
+ }
+};
+
// sort turns by G1 - source_index == 0 by:
// seg_id -> distance -> operation
template <std::size_t OpId = 0,
diff --git a/boost/geometry/algorithms/detail/sections/range_by_section.hpp b/boost/geometry/algorithms/detail/sections/range_by_section.hpp
index 63feb12a71..d139a3fdd2 100644
--- a/boost/geometry/algorithms/detail/sections/range_by_section.hpp
+++ b/boost/geometry/algorithms/detail/sections/range_by_section.hpp
@@ -58,7 +58,8 @@ struct full_section_polygon
{
return section.ring_id.ring_index < 0
? geometry::exterior_ring(polygon)
- : range::at(geometry::interior_rings(polygon), section.ring_id.ring_index);
+ : range::at(geometry::interior_rings(polygon),
+ static_cast<std::size_t>(section.ring_id.ring_index));
}
};
@@ -74,13 +75,15 @@ struct full_section_multi
static inline typename ring_return_type<MultiGeometry const>::type apply(
MultiGeometry const& multi, Section const& section)
{
+ typedef typename boost::range_size<MultiGeometry>::type size_type;
+
BOOST_ASSERT
(
section.ring_id.multi_index >= 0
- && section.ring_id.multi_index < int(boost::size(multi))
+ && size_type(section.ring_id.multi_index) < boost::size(multi)
);
- return Policy::apply(range::at(multi, section.ring_id.multi_index), section);
+ return Policy::apply(range::at(multi, size_type(section.ring_id.multi_index)), section);
}
};
diff --git a/boost/geometry/algorithms/detail/sections/section_box_policies.hpp b/boost/geometry/algorithms/detail/sections/section_box_policies.hpp
new file mode 100644
index 0000000000..cf06700306
--- /dev/null
+++ b/boost/geometry/algorithms/detail/sections/section_box_policies.hpp
@@ -0,0 +1,49 @@
+// 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_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP
+
+
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace section
+{
+
+struct get_section_box
+{
+ template <typename Box, typename Section>
+ static inline void apply(Box& total, Section const& section)
+ {
+ geometry::expand(total, section.bounding_box);
+ }
+};
+
+struct overlaps_section_box
+{
+ template <typename Box, typename Section>
+ static inline bool apply(Box const& box, Section const& section)
+ {
+ return ! detail::disjoint::disjoint_box_box(box, section.bounding_box);
+ }
+};
+
+
+}} // namespace detail::section
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP
diff --git a/boost/geometry/algorithms/detail/sections/section_functions.hpp b/boost/geometry/algorithms/detail/sections/section_functions.hpp
new file mode 100644
index 0000000000..ba1cf931b2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/sections/section_functions.hpp
@@ -0,0 +1,66 @@
+// 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_DETAIL_SECTIONS_FUNCTIONS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_FUNCTIONS_HPP
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/algorithms/detail/recalculate.hpp>
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace section
+{
+
+template
+<
+ std::size_t Dimension,
+ typename Point,
+ typename RobustBox,
+ typename RobustPolicy
+>
+static inline bool preceding(int dir, Point const& point,
+ RobustBox const& robust_box,
+ RobustPolicy const& robust_policy)
+{
+ typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
+ geometry::recalculate(robust_point, point, robust_policy);
+ return (dir == 1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box))
+ || (dir == -1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box));
+}
+
+template
+<
+ std::size_t Dimension,
+ typename Point,
+ typename RobustBox,
+ typename RobustPolicy
+>
+static inline bool exceeding(int dir, Point const& point,
+ RobustBox const& robust_box,
+ RobustPolicy const& robust_policy)
+{
+ typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
+ geometry::recalculate(robust_point, point, robust_policy);
+ return (dir == 1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box))
+ || (dir == -1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box));
+}
+
+
+}} // namespace detail::section
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_FUNCTIONS_HPP
diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
index 250577c0c2..a744ea0a34 100644
--- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp
+++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
@@ -8,6 +8,9 @@
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013, 2014 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.
@@ -15,8 +18,6 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
@@ -25,7 +26,9 @@
#include <boost/concept/requires.hpp>
#include <boost/mpl/assert.hpp>
+#include <boost/mpl/vector_c.hpp>
#include <boost/range.hpp>
+#include <boost/static_assert.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/expand.hpp>
@@ -63,12 +66,15 @@ namespace boost { namespace geometry
\tparam DimensionCount number of dimensions for this section
\ingroup sectionalize
*/
-template <typename Box, std::size_t DimensionCount>
+template
+<
+ typename Box,
+ std::size_t DimensionCount
+>
struct section
{
typedef Box box_type;
-
- int id; // might be obsolete now, BSG 14-03-2011 TODO decide about this
+ static std::size_t const dimension_count = DimensionCount;
int directions[DimensionCount];
ring_identifier ring_id;
@@ -85,8 +91,7 @@ struct section
bool is_non_duplicate_last;
inline section()
- : id(-1)
- , begin_index(-1)
+ : begin_index(-1)
, end_index(-1)
, count(0)
, range_count(0)
@@ -122,75 +127,83 @@ struct sections : std::vector<section<Box, DimensionCount> >
namespace detail { namespace sectionalize
{
-template <std::size_t Dimension, std::size_t DimensionCount>
+template
+<
+ typename DimensionVector,
+ std::size_t Index,
+ std::size_t Count
+>
struct get_direction_loop
{
+ typedef typename boost::mpl::at_c<DimensionVector, Index>::type dimension;
+
template <typename Segment>
static inline void apply(Segment const& seg,
- int directions[DimensionCount])
+ int directions[Count])
{
typedef typename coordinate_type<Segment>::type coordinate_type;
+
coordinate_type const diff =
- geometry::get<1, Dimension>(seg) - geometry::get<0, Dimension>(seg);
+ geometry::get<1, dimension::value>(seg)
+ - geometry::get<0, dimension::value>(seg);
coordinate_type zero = coordinate_type();
- directions[Dimension] = diff > zero ? 1 : diff < zero ? -1 : 0;
+ directions[Index] = diff > zero ? 1 : diff < zero ? -1 : 0;
get_direction_loop
- <
- Dimension + 1, DimensionCount
- >::apply(seg, directions);
+ <
+ DimensionVector,
+ Index + 1,
+ Count
+ >::apply(seg, directions);
}
};
-template <std::size_t DimensionCount>
-struct get_direction_loop<DimensionCount, DimensionCount>
+template <typename DimensionVector, std::size_t Count>
+struct get_direction_loop<DimensionVector, Count, Count>
{
template <typename Segment>
- static inline void apply(Segment const&, int [DimensionCount])
+ static inline void apply(Segment const&, int [Count])
{}
};
-template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+//! Copy one static array to another
+template <typename T, std::size_t Index, std::size_t Count>
struct copy_loop
{
- static inline void apply(T const source[DimensionCount],
- T target[DimensionCount])
+ static inline void apply(T const source[Count], T target[Count])
{
- target[Dimension] = source[Dimension];
- copy_loop<T, Dimension + 1, DimensionCount>::apply(source, target);
+ target[Index] = source[Index];
+ copy_loop<T, Index + 1, Count>::apply(source, target);
}
};
-template <typename T, std::size_t DimensionCount>
-struct copy_loop<T, DimensionCount, DimensionCount>
+template <typename T, std::size_t Count>
+struct copy_loop<T, Count, Count>
{
- static inline void apply(T const [DimensionCount], T [DimensionCount])
+ static inline void apply(T const [Count], T [Count])
{}
};
-template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+//! Compare two static arrays
+template <typename T, std::size_t Index, std::size_t Count>
struct compare_loop
{
- static inline bool apply(T const source[DimensionCount],
- T const target[DimensionCount])
+ static inline bool apply(T const array1[Count], T const array2[Count])
{
- bool const not_equal = target[Dimension] != source[Dimension];
-
- return not_equal
+ return array1[Index] != array2[Index]
? false
: compare_loop
<
- T, Dimension + 1, DimensionCount
- >::apply(source, target);
+ T, Index + 1, Count
+ >::apply(array1, array2);
}
};
-template <typename T, std::size_t DimensionCount>
-struct compare_loop<T, DimensionCount, DimensionCount>
+template <typename T, std::size_t Count>
+struct compare_loop<T, Count, Count>
{
- static inline bool apply(T const [DimensionCount],
- T const [DimensionCount])
+ static inline bool apply(T const [Count], T const [Count])
{
return true;
@@ -215,9 +228,9 @@ struct check_duplicate_loop
}
return check_duplicate_loop
- <
+ <
Dimension + 1, DimensionCount
- >::apply(seg);
+ >::apply(seg);
}
};
@@ -231,20 +244,21 @@ struct check_duplicate_loop<DimensionCount, DimensionCount>
}
};
-template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+//! Assign a value to a static array
+template <typename T, std::size_t Index, std::size_t Count>
struct assign_loop
{
- static inline void apply(T dims[DimensionCount], int const value)
+ static inline void apply(T dims[Count], int const value)
{
- dims[Dimension] = value;
- assign_loop<T, Dimension + 1, DimensionCount>::apply(dims, value);
+ dims[Index] = value;
+ assign_loop<T, Index + 1, Count>::apply(dims, value);
}
};
-template <typename T, std::size_t DimensionCount>
-struct assign_loop<T, DimensionCount, DimensionCount>
+template <typename T, std::size_t Count>
+struct assign_loop<T, Count, Count>
{
- static inline void apply(T [DimensionCount], int const)
+ static inline void apply(T [Count], int const)
{
}
};
@@ -253,35 +267,42 @@ struct assign_loop<T, DimensionCount, DimensionCount>
template
<
typename Point,
- std::size_t DimensionCount
+ typename DimensionVector
>
struct sectionalize_part
{
+ static const std::size_t dimension_count
+ = boost::mpl::size<DimensionVector>::value;
+
template
<
- typename Range, // Can be closeable_view
+ typename Iterator,
typename RobustPolicy,
typename Sections
>
static inline void apply(Sections& sections,
- Range const& range,
+ Iterator begin, Iterator end,
RobustPolicy const& robust_policy,
- bool make_rescaled_boxes,
ring_identifier ring_id,
std::size_t max_count)
{
boost::ignore_unused_variable_warning(robust_policy);
- boost::ignore_unused_variable_warning(make_rescaled_boxes);
- typedef model::referring_segment<Point const> segment_type;
typedef typename boost::range_value<Sections>::type section_type;
- typedef model::segment
- <
- typename robust_point_type<Point, RobustPolicy>::type
- > robust_segment_type;
- typedef typename boost::range_iterator<Range const>::type iterator_type;
+ BOOST_STATIC_ASSERT
+ (
+ (static_cast<int>(section_type::dimension_count)
+ == static_cast<int>(boost::mpl::size<DimensionVector>::value))
+ );
- if ( boost::empty(range) )
+ typedef typename geometry::robust_point_type
+ <
+ Point,
+ RobustPolicy
+ >::type robust_point_type;
+
+ std::size_t const count = std::distance(begin, end);
+ if (count == 0)
{
return;
}
@@ -293,21 +314,24 @@ struct sectionalize_part
bool mark_first_non_duplicated = true;
std::size_t last_non_duplicate_index = sections.size();
- iterator_type it = boost::begin(range);
+ Iterator it = begin;
+ robust_point_type previous_robust_point;
+ geometry::recalculate(previous_robust_point, *it, robust_policy);
- for(iterator_type previous = it++;
- it != boost::end(range);
+ for(Iterator previous = it++;
+ it != end;
++previous, ++it, index++)
{
- segment_type segment(*previous, *it);
- robust_segment_type robust_segment;
- geometry::recalculate(robust_segment, segment, robust_policy);
+ robust_point_type current_robust_point;
+ geometry::recalculate(current_robust_point, *it, robust_policy);
+ model::referring_segment<robust_point_type> robust_segment(
+ previous_robust_point, current_robust_point);
- int direction_classes[DimensionCount] = {0};
+ int direction_classes[dimension_count] = {0};
get_direction_loop
- <
- 0, DimensionCount
- >::apply(robust_segment, direction_classes);
+ <
+ DimensionVector, 0, dimension_count
+ >::apply(robust_segment, direction_classes);
// if "dir" == 0 for all point-dimensions, it is duplicate.
// Those sections might be omitted, if wished, lateron
@@ -317,7 +341,7 @@ struct sectionalize_part
{
// Recheck because ALL dimensions should be checked,
// not only first one.
- // (DimensionCount might be < dimension<P>::value)
+ // (dimension_count might be < dimension<P>::value)
if (check_duplicate_loop
<
0, geometry::dimension<Point>::type::value
@@ -332,21 +356,20 @@ struct sectionalize_part
// Actual value is not important as long as it is not -1,0,1
assign_loop
<
- int, 0, DimensionCount
+ int, 0, dimension_count
>::apply(direction_classes, -99);
}
}
if (section.count > 0
- && (!compare_loop
+ && (! compare_loop
<
- int, 0, DimensionCount
+ int, 0, dimension_count
>::apply(direction_classes, section.directions)
- || section.count > max_count
- )
+ || section.count > max_count)
)
{
- if ( !section.duplicate )
+ if (! section.duplicate)
{
last_non_duplicate_index = sections.size();
}
@@ -361,9 +384,9 @@ struct sectionalize_part
section.ring_id = ring_id;
section.duplicate = duplicate;
section.non_duplicate_index = ndi;
- section.range_count = boost::size(range);
+ section.range_count = count;
- if ( mark_first_non_duplicated && !duplicate )
+ if (mark_first_non_duplicated && ! duplicate)
{
section.is_non_duplicate_first = true;
mark_first_non_duplicated = false;
@@ -371,25 +394,26 @@ struct sectionalize_part
copy_loop
<
- int, 0, DimensionCount
+ int, 0, dimension_count
>::apply(direction_classes, section.directions);
- expand_box(*previous, robust_policy, section);
+ geometry::expand(section.bounding_box, previous_robust_point);
}
- expand_box(*it, robust_policy, section);
+ geometry::expand(section.bounding_box, current_robust_point);
section.end_index = index + 1;
section.count++;
if (! duplicate)
{
ndi++;
}
+ previous_robust_point = current_robust_point;
}
// Add last section if applicable
if (section.count > 0)
{
- if ( !section.duplicate )
+ if (! section.duplicate)
{
last_non_duplicate_index = sections.size();
}
@@ -397,30 +421,21 @@ struct sectionalize_part
sections.push_back(section);
}
- if ( last_non_duplicate_index < sections.size()
- && !sections[last_non_duplicate_index].duplicate )
+ if (last_non_duplicate_index < sections.size()
+ && ! sections[last_non_duplicate_index].duplicate)
{
sections[last_non_duplicate_index].is_non_duplicate_last = true;
}
}
-
- template <typename InputPoint, typename RobustPolicy, typename Section>
- static inline void expand_box(InputPoint const& point,
- RobustPolicy const& robust_policy,
- Section& section)
- {
- typename geometry::point_type<typename Section::box_type>::type robust_point;
- geometry::recalculate(robust_point, point, robust_policy);
- geometry::expand(section.bounding_box, robust_point);
- }
};
template
<
- closure_selector Closure, bool Reverse,
+ closure_selector Closure,
+ bool Reverse,
typename Point,
- std::size_t DimensionCount
+ typename DimensionVector
>
struct sectionalize_range
{
@@ -432,13 +447,12 @@ struct sectionalize_range
>
static inline void apply(Range const& range,
RobustPolicy const& robust_policy,
- bool make_rescaled_boxes,
Sections& sections,
ring_identifier ring_id,
std::size_t max_count)
{
- typedef typename closeable_view<Range const, Closure>::type cview_type;
- typedef typename reversible_view
+ typedef typename closeable_view<Range const, Closure>::type cview_type;
+ typedef typename reversible_view
<
cview_type const,
Reverse ? iterate_reverse : iterate_forward
@@ -460,15 +474,16 @@ struct sectionalize_range
return;
}
- sectionalize_part<Point, DimensionCount>
- ::apply(sections, view, robust_policy, make_rescaled_boxes, ring_id, max_count);
+ sectionalize_part<Point, DimensionVector>::apply(sections,
+ boost::begin(view), boost::end(view),
+ robust_policy, ring_id, max_count);
}
};
template
<
bool Reverse,
- std::size_t DimensionCount
+ typename DimensionVector
>
struct sectionalize_polygon
{
@@ -480,20 +495,18 @@ struct sectionalize_polygon
>
static inline void apply(Polygon const& poly,
RobustPolicy const& robust_policy,
- bool make_rescaled_boxes,
Sections& sections,
ring_identifier ring_id, std::size_t max_count)
{
typedef typename point_type<Polygon>::type point_type;
- //typedef typename ring_type<Polygon>::type ring_type;
typedef sectionalize_range
- <
+ <
closure<Polygon>::value, Reverse,
- point_type, DimensionCount
- > per_range;
+ point_type, DimensionVector
+ > per_range;
ring_id.ring_index = -1;
- per_range::apply(exterior_ring(poly), robust_policy, make_rescaled_boxes, sections, ring_id, max_count);
+ per_range::apply(exterior_ring(poly), robust_policy, sections, ring_id, max_count);
ring_id.ring_index++;
typename interior_return_type<Polygon const>::type
@@ -501,15 +514,12 @@ struct sectionalize_polygon
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
{
- per_range::apply(*it, robust_policy, make_rescaled_boxes, sections, ring_id, max_count);
+ per_range::apply(*it, robust_policy, sections, ring_id, max_count);
}
}
};
-template
-<
- std::size_t DimensionCount
->
+template <typename DimensionVector>
struct sectionalize_box
{
template
@@ -520,7 +530,6 @@ struct sectionalize_box
>
static inline void apply(Box const& box,
RobustPolicy const& robust_policy,
- bool make_rescaled_boxes,
Sections& sections,
ring_identifier const& ring_id, std::size_t max_count)
{
@@ -547,16 +556,16 @@ struct sectionalize_box
points.push_back(ll);
sectionalize_range
- <
+ <
closed, false,
- point_type,
- DimensionCount
- >::apply(points, robust_policy, make_rescaled_boxes, sections,
- ring_id, max_count);
+ point_type,
+ DimensionVector
+ >::apply(points, robust_policy, sections,
+ ring_id, max_count);
}
};
-template <std::size_t DimensionCount, typename Policy>
+template <typename DimensionVector, typename Policy>
struct sectionalize_multi
{
template
@@ -567,7 +576,6 @@ struct sectionalize_multi
>
static inline void apply(MultiGeometry const& multi,
RobustPolicy const& robust_policy,
- bool make_rescaled_boxes,
Sections& sections, ring_identifier ring_id, std::size_t max_count)
{
ring_id.multi_index = 0;
@@ -576,25 +584,12 @@ struct sectionalize_multi
it != boost::end(multi);
++it, ++ring_id.multi_index)
{
- Policy::apply(*it, robust_policy, make_rescaled_boxes, sections, ring_id, max_count);
+ Policy::apply(*it, robust_policy, sections, ring_id, max_count);
}
}
};
template <typename Sections>
-inline void set_section_unique_ids(Sections& sections)
-{
- // Set ID's.
- int index = 0;
- for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);
- it != boost::end(sections);
- ++it)
- {
- it->id = index++;
- }
-}
-
-template <typename Sections>
inline void enlarge_sections(Sections& sections)
{
// Robustness issue. Increase sections a tiny bit such that all points are really within (and not on border)
@@ -631,7 +626,7 @@ template
typename Tag,
typename Geometry,
bool Reverse,
- std::size_t DimensionCount
+ typename DimensionVector
>
struct sectionalize
{
@@ -646,29 +641,29 @@ template
<
typename Box,
bool Reverse,
- std::size_t DimensionCount
+ typename DimensionVector
>
-struct sectionalize<box_tag, Box, Reverse, DimensionCount>
- : detail::sectionalize::sectionalize_box<DimensionCount>
+struct sectionalize<box_tag, Box, Reverse, DimensionVector>
+ : detail::sectionalize::sectionalize_box<DimensionVector>
{};
template
<
typename LineString,
- std::size_t DimensionCount
+ typename DimensionVector
>
struct sectionalize
<
linestring_tag,
LineString,
false,
- DimensionCount
+ DimensionVector
>
: detail::sectionalize::sectionalize_range
<
closed, false,
typename point_type<LineString>::type,
- DimensionCount
+ DimensionVector
>
{};
@@ -676,14 +671,14 @@ template
<
typename Ring,
bool Reverse,
- std::size_t DimensionCount
+ typename DimensionVector
>
-struct sectionalize<ring_tag, Ring, Reverse, DimensionCount>
+struct sectionalize<ring_tag, Ring, Reverse, DimensionVector>
: detail::sectionalize::sectionalize_range
<
geometry::closure<Ring>::value, Reverse,
typename point_type<Ring>::type,
- DimensionCount
+ DimensionVector
>
{};
@@ -691,12 +686,12 @@ template
<
typename Polygon,
bool Reverse,
- std::size_t DimensionCount
+ typename DimensionVector
>
-struct sectionalize<polygon_tag, Polygon, Reverse, DimensionCount>
+struct sectionalize<polygon_tag, Polygon, Reverse, DimensionVector>
: detail::sectionalize::sectionalize_polygon
<
- Reverse, DimensionCount
+ Reverse, DimensionVector
>
{};
@@ -704,16 +699,16 @@ template
<
typename MultiPolygon,
bool Reverse,
- std::size_t DimensionCount
+ typename DimensionVector
>
-struct sectionalize<multi_polygon_tag, MultiPolygon, Reverse, DimensionCount>
+struct sectionalize<multi_polygon_tag, MultiPolygon, Reverse, DimensionVector>
: detail::sectionalize::sectionalize_multi
<
- DimensionCount,
+ DimensionVector,
detail::sectionalize::sectionalize_polygon
<
Reverse,
- DimensionCount
+ DimensionVector
>
>
@@ -723,17 +718,17 @@ template
<
typename MultiLinestring,
bool Reverse,
- std::size_t DimensionCount
+ typename DimensionVector
>
-struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionCount>
+struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVector>
: detail::sectionalize::sectionalize_multi
<
- DimensionCount,
+ DimensionVector,
detail::sectionalize::sectionalize_range
<
closed, false,
typename point_type<MultiLinestring>::type,
- DimensionCount
+ DimensionVector
>
>
@@ -750,54 +745,61 @@ struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionCou
\tparam Sections type of sections to create
\param geometry geometry to create sections from
\param robust_policy policy to handle robustness issues
- \param enlarge_secion_boxes if true, boxes are enlarged a tiny bit to be sure
- they really contain all geometries (w.r.t. robustness)
\param sections structure with sections
\param source_index index to assign to the ring_identifiers
+ \param max_count maximal number of points per section
+ (defaults to 10, this seems to give the fastest results)
+
*/
-template<bool Reverse, typename Geometry, typename Sections, typename RobustPolicy>
+template
+<
+ bool Reverse,
+ typename DimensionVector,
+ typename Geometry,
+ typename Sections,
+ typename RobustPolicy
+>
inline void sectionalize(Geometry const& geometry,
RobustPolicy const& robust_policy,
- bool enlarge_secion_boxes,
Sections& sections,
- int source_index = 0)
+ int source_index = 0,
+ std::size_t max_count = 10)
{
concept::check<Geometry const>();
+ typedef typename boost::range_value<Sections>::type section_type;
+
+ // Compiletime check for point type of section boxes
+ // and point type related to robust policy
+ typedef typename geometry::coordinate_type
+ <
+ typename section_type::box_type
+ >::type ctype1;
+ typedef typename geometry::coordinate_type
+ <
+ typename geometry::robust_point_type
+ <
+ typename geometry::point_type<Geometry>::type,
+ RobustPolicy
+ >::type
+ >::type ctype2;
+
+ BOOST_MPL_ASSERT((boost::is_same<ctype1, ctype2>));
+
+
sections.clear();
ring_identifier ring_id;
ring_id.source_index = source_index;
- // A maximum of 10 segments per section seems to give the fastest results
dispatch::sectionalize
<
typename tag<Geometry>::type,
Geometry,
Reverse,
- Sections::value
- >::apply(geometry, robust_policy, enlarge_secion_boxes, sections, ring_id, 10);
-
- detail::sectionalize::set_section_unique_ids(sections);
- if (! enlarge_secion_boxes)
- {
- detail::sectionalize::enlarge_sections(sections);
- }
-}
-
-
-#if defined(BOOST_GEOMETRY_UNIT_TEST_SECTIONALIZE)
-// Backwards compatibility
-template<bool Reverse, typename Geometry, typename Sections>
-inline void sectionalize(Geometry const& geometry,
- Sections& sections,
- int source_index = 0)
-{
- return geometry::sectionalize<Reverse>(geometry, detail::no_rescale_policy(),
- false, sections,
- source_index);
+ DimensionVector
+ >::apply(geometry, robust_policy, sections, ring_id, max_count);
}
-#endif
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/single_geometry.hpp b/boost/geometry/algorithms/detail/single_geometry.hpp
index c65ff8bf84..f38295ada6 100644
--- a/boost/geometry/algorithms/detail/single_geometry.hpp
+++ b/boost/geometry/algorithms/detail/single_geometry.hpp
@@ -55,7 +55,8 @@ struct single_geometry<Geometry, true>
static inline return_type apply(Geometry & g, Id const& id)
{
BOOST_ASSERT(id.multi_index >= 0);
- return range::at(g, id.multi_index);
+ 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 a68f31362a..eda3ce58ba 100644
--- a/boost/geometry/algorithms/detail/sub_range.hpp
+++ b/boost/geometry/algorithms/detail/sub_range.hpp
@@ -44,7 +44,7 @@ struct sub_range<Geometry, Tag, false>
template <typename Geometry>
struct sub_range<Geometry, polygon_tag, false>
{
- typedef typename geometry::ring_type<Geometry>::type & return_type;
+ typedef typename geometry::ring_return_type<Geometry>::type return_type;
template <typename Id> static inline
return_type apply(Geometry & geometry, Id const& id)
@@ -55,7 +55,11 @@ struct sub_range<Geometry, polygon_tag, false>
}
else
{
- std::size_t ri = static_cast<std::size_t>(id.ring_index);
+ typedef typename boost::range_size
+ <
+ typename geometry::interior_type<Geometry>::type
+ >::type size_type;
+ size_type const ri = static_cast<size_type>(id.ring_index);
return range::at(geometry::interior_rings(geometry), ri);
}
}
@@ -81,7 +85,9 @@ struct sub_range<Geometry, Tag, true>
return_type apply(Geometry & geometry, Id const& id)
{
BOOST_ASSERT(0 <= id.multi_index);
- return sub_sub_range::apply(range::at(geometry, id.multi_index), id);
+ 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);
}
};
diff --git a/boost/geometry/algorithms/detail/turns/print_turns.hpp b/boost/geometry/algorithms/detail/turns/print_turns.hpp
index b339e11c94..9d4e45c41f 100644
--- a/boost/geometry/algorithms/detail/turns/print_turns.hpp
+++ b/boost/geometry/algorithms/detail/turns/print_turns.hpp
@@ -10,9 +10,9 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_PRINT_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_PRINT_TURNS_HPP
+#include <algorithm>
#include <iostream>
-#include <boost/foreach.hpp>
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
@@ -27,21 +27,16 @@ namespace boost { namespace geometry
namespace detail { namespace turns
{
-
-
-template <typename Geometry1, typename Geometry2, typename Turns>
-static inline void print_turns(Geometry1 const& g1,
- Geometry2 const& g2,
- Turns const& turns)
+struct turn_printer
{
- typedef typename boost::range_value<Turns>::type turn_info;
+ turn_printer(std::ostream & os)
+ : index(0)
+ , out(os)
+ {}
- std::cout << geometry::wkt(g1) << std::endl;
- std::cout << geometry::wkt(g2) << std::endl;
- int index = 0;
- BOOST_FOREACH(turn_info const& turn, turns)
+ template <typename Turn>
+ void operator()(Turn const& turn)
{
- std::ostream& out = std::cout;
out << index
<< ": " << geometry::method_char(turn.method);
@@ -81,8 +76,22 @@ static inline void print_turns(Geometry1 const& g1,
out << ' ' << geometry::dsv(turn.point) << ' ';
++index;
- std::cout << std::endl;
+ out << std::endl;
}
+
+ int index;
+ std::ostream & out;
+};
+
+template <typename Geometry1, typename Geometry2, typename Turns>
+static inline void print_turns(Geometry1 const& g1,
+ Geometry2 const& g2,
+ Turns const& turns)
+{
+ std::cout << geometry::wkt(g1) << std::endl;
+ std::cout << geometry::wkt(g2) << std::endl;
+
+ std::for_each(boost::begin(turns), boost::end(turns), turn_printer(std::cout));
}
diff --git a/boost/geometry/algorithms/detail/vincenty_direct.hpp b/boost/geometry/algorithms/detail/vincenty_direct.hpp
new file mode 100644
index 0000000000..775687cfdb
--- /dev/null
+++ b/boost/geometry/algorithms/detail/vincenty_direct.hpp
@@ -0,0 +1,190 @@
+// 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_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_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>
+
+
+#ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS
+#define BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS 1000
+#endif
+
+
+namespace boost { namespace geometry { namespace detail
+{
+
+/*!
+\brief The solution of the direct problem of geodesics on latlong coordinates, after Vincenty, 1975
+\author See
+ - http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
+ - http://www.icsm.gov.au/gda/gdav2.3.pdf
+\author Adapted from various implementations to get it close to the original document
+ - http://www.movable-type.co.uk/scripts/LatLongVincenty.html
+ - http://exogen.case.edu/projects/geopy/source/geopy.distance.html
+ - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
+
+*/
+template <typename CT>
+class vincenty_direct
+{
+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)
+ {
+ if ( math::equals(distance, Dist(0)) || distance < Dist(0) )
+ {
+ is_distance_zero = true;
+ return;
+ }
+
+ CT const radius_a = CT(get_radius<0>(spheroid));
+ CT const radius_b = CT(get_radius<2>(spheroid));
+ flattening = geometry::detail::flattening<CT>(spheroid);
+
+ sin_azimuth12 = sin(azimuth12);
+ cos_azimuth12 = cos(azimuth12);
+
+ // U: reduced latitude, defined by tan U = (1-f) tan phi
+ 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);
+
+ sin_alpha = cos_U1 * sin_azimuth12; // (2)
+ sin_alpha_sqr = math::sqr(sin_alpha);
+ 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;
+ CT const A = CT(1) + (u_sqr/CT(16384)) * (CT(4096) + u_sqr*(CT(-768) + u_sqr*(CT(320) - u_sqr*CT(175)))); // (3)
+ 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 previous_sigma;
+
+ int counter = 0; // robustness
+
+ do
+ {
+ previous_sigma = sigma;
+
+ CT const two_sigma_m = CT(2) * sigma1 + sigma; // (5)
+
+ sin_sigma = sin(sigma);
+ cos_sigma = cos(sigma);
+ CT const sin_sigma_sqr = math::sqr(sin_sigma);
+ cos_2sigma_m = cos(two_sigma_m);
+ cos_2sigma_m_sqr = math::sqr(cos_2sigma_m);
+
+ CT const delta_sigma = B * sin_sigma * (cos_2sigma_m
+ + (B/CT(4)) * ( cos_sigma * (CT(-1) + CT(2)*cos_2sigma_m_sqr)
+ - (B/CT(6) * cos_2sigma_m * (CT(-3)+CT(4)*sin_sigma_sqr) * (CT(-3)+CT(4)*cos_2sigma_m_sqr)) )); // (6)
+
+ sigma = s_div_bA + delta_sigma; // (7)
+
+ ++counter; // robustness
+
+ } 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;
+ }
+
+ 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)
+
+ return lon1 + L;
+ }
+
+ inline CT azimuth21() const
+ {
+ // NOTE: signs of X and Y are different than in the original paper
+ return is_distance_zero ?
+ 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
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP
diff --git a/boost/geometry/algorithms/detail/vincenty_inverse.hpp b/boost/geometry/algorithms/detail/vincenty_inverse.hpp
new file mode 100644
index 0000000000..861452af00
--- /dev/null
+++ b/boost/geometry/algorithms/detail/vincenty_inverse.hpp
@@ -0,0 +1,218 @@
+// 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_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_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>
+
+
+#ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS
+#define BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS 1000
+#endif
+
+
+namespace boost { namespace geometry { namespace detail
+{
+
+/*!
+\brief The solution of the inverse problem of geodesics on latlong coordinates, after Vincenty, 1975
+\author See
+ - http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
+ - http://www.icsm.gov.au/gda/gdav2.3.pdf
+\author Adapted from various implementations to get it close to the original document
+ - http://www.movable-type.co.uk/scripts/LatLongVincenty.html
+ - http://exogen.case.edu/projects/geopy/source/geopy.distance.html
+ - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
+
+*/
+template <typename CT>
+class vincenty_inverse
+{
+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)
+ {
+ if (math::equals(lat1, lat2) && math::equals(lon1, lon2))
+ {
+ is_result_zero = true;
+ return;
+ }
+
+ CT const c1 = 1;
+ CT const c2 = 2;
+ CT const c3 = 3;
+ CT const c4 = 4;
+ CT const c16 = 16;
+ CT const c_e_12 = CT(1e-12);
+
+ CT const pi = geometry::math::pi<CT>();
+ CT const two_pi = c2 * pi;
+
+ // lambda: difference in longitude on an auxiliary sphere
+ CT L = lon2 - lon1;
+ CT lambda = L;
+
+ 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 flattening = geometry::detail::flattening<CT>(spheroid);
+
+ // U: reduced latitude, defined by tan U = (1-f) tan phi
+ CT const one_min_f = c1 - flattening;
+ CT const tan_U1 = one_min_f * tan(lat1); // above (1)
+ CT const tan_U2 = one_min_f * tan(lat2); // above (1)
+
+ // calculate sin U and cos U using trigonometric identities
+ 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;
+ // sin = tan / sqrt(1 + tan^2)
+ sin_U1 = tan_U1 / temp_den_U1;
+ sin_U2 = tan_U2 / temp_den_U2;
+
+ // calculate sin U and cos U directly
+ //CT const U1 = atan(tan_U1);
+ //CT const U2 = atan(tan_U2);
+ //cos_U1 = cos(U1);
+ //cos_U2 = cos(U2);
+ //sin_U1 = tan_U1 * cos_U1; // sin(U1);
+ //sin_U2 = tan_U2 * cos_U2; // sin(U2);
+
+ CT previous_lambda;
+
+ int counter = 0; // robustness
+
+ do
+ {
+ previous_lambda = lambda; // (13)
+ sin_lambda = sin(lambda);
+ cos_lambda = cos(lambda);
+ sin_sigma = math::sqrt(math::sqr(cos_U2 * sin_lambda) + math::sqr(cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda)); // (14)
+ CT cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)
+ sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)
+ cos2_alpha = c1 - math::sqr(sin_alpha);
+ cos2_sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)
+
+ CT C = flattening/c16 * cos2_alpha * (c4 + flattening * (c4 - c3 * cos2_alpha)); // (10)
+ sigma = atan2(sin_sigma, cos_sigma); // (16)
+ lambda = L + (c1 - C) * flattening * sin_alpha *
+ (sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-c1 + c2 * math::sqr(cos2_sigma_m)))); // (11)
+
+ ++counter; // robustness
+
+ } 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 )
+ {
+ 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)
+
+ 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)
+ }
+
+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;
+};
+
+}}} // namespace boost::geometry::detail
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
index 6f1c1816cb..e7486f0e45 100644
--- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 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.
@@ -21,6 +21,7 @@
#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>
@@ -35,6 +36,7 @@
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
namespace boost { namespace geometry {
@@ -58,7 +60,7 @@ inline T check_result_type(T result)
template <typename Point, typename Range, typename Strategy> inline
int point_in_range(Point const& point, Range const& range, Strategy const& strategy)
{
- boost::ignore_unused_variable_warning(strategy);
+ boost::ignore_unused(strategy);
typedef typename boost::range_iterator<Range const>::type iterator_type;
typename Strategy::state_type state;
@@ -147,7 +149,7 @@ struct point_in_geometry<Point2, point_tag>
template <typename Point1, typename Strategy> static inline
int apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
{
- boost::ignore_unused_variable_warning(strategy);
+ boost::ignore_unused(strategy);
return strategy.apply(point1, point2) ? 1 : -1;
}
};
@@ -158,6 +160,8 @@ struct point_in_geometry<Segment, segment_tag>
template <typename Point, typename Strategy> static inline
int apply(Point const& point, Segment const& segment, Strategy const& strategy)
{
+ boost::ignore_unused(strategy);
+
typedef typename geometry::point_type<Segment>::type point_type;
point_type p0, p1;
// TODO: don't copy points
@@ -194,11 +198,11 @@ struct point_in_geometry<Linestring, linestring_tag>
return -1; // exterior
// if the linestring doesn't have a boundary
- if ( detail::equals::equals_point_point(*boost::begin(linestring), *(--boost::end(linestring))) )
+ if (detail::equals::equals_point_point(range::front(linestring), range::back(linestring)))
return 1; // interior
// else if the point is equal to the one of the terminal points
- else if ( detail::equals::equals_point_point(point, *boost::begin(linestring))
- || detail::equals::equals_point_point(point, *(--boost::end(linestring))) )
+ else if (detail::equals::equals_point_point(point, range::front(linestring))
+ || detail::equals::equals_point_point(point, range::back(linestring)))
return 0; // boundary
else
return 1; // interior
@@ -207,7 +211,7 @@ struct point_in_geometry<Linestring, linestring_tag>
// throw an exception here?
/*else if ( count == 1 )
{
- if ( detail::equals::equals_point_point(point, *boost::begin(linestring)) )
+ if ( detail::equals::equals_point_point(point, range::front(linestring)) )
return 1;
}*/
@@ -333,8 +337,8 @@ struct point_in_geometry<Geometry, multi_linestring_tag>
if ( boost::size(*it) < 2 )
continue;
- point_type const& front = *boost::begin(*it);
- point_type const& back = *(--boost::end(*it));
+ point_type const& front = range::front(*it);
+ point_type const& back = range::back(*it);
// is closed_ring - no boundary
if ( detail::equals::equals_point_point(front, back) )
diff --git a/boost/geometry/algorithms/dispatch/is_valid.hpp b/boost/geometry/algorithms/dispatch/is_valid.hpp
index 266bab9181..5d8108655c 100644
--- a/boost/geometry/algorithms/dispatch/is_valid.hpp
+++ b/boost/geometry/algorithms/dispatch/is_valid.hpp
@@ -27,10 +27,8 @@ template
<
typename Geometry,
typename Tag = typename tag<Geometry>::type,
- // for linear geometries: determines if spikes are allowed
- bool AllowSpikes = true,
- // for areal geometries: determines if duplicate points are allowed
- bool AllowDuplicates = true
+ // for multi-geometries: determines if empty multi-geometries are allowed
+ bool AllowEmptyMultiGeometries = true
>
struct is_valid
: not_implemented<Geometry>
diff --git a/boost/geometry/algorithms/envelope.hpp b/boost/geometry/algorithms/envelope.hpp
index e06ed71e81..bd1ea9cb7a 100644
--- a/boost/geometry/algorithms/envelope.hpp
+++ b/boost/geometry/algorithms/envelope.hpp
@@ -18,8 +18,9 @@
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.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>
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp
index c6b718da1b..7c709c808d 100644
--- a/boost/geometry/algorithms/equals.hpp
+++ b/boost/geometry/algorithms/equals.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.
-// 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -26,6 +27,10 @@
#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/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/geometry_id.hpp>
@@ -50,8 +55,6 @@
#include <boost/geometry/views/detail/indexed_point_view.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/apply_visitor.hpp>
namespace boost { namespace geometry
{
@@ -234,8 +237,6 @@ template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
: geometry::detail::not_
<
- P1,
- P2,
detail::disjoint::point_point<P1, P2, 0, DimensionCount>
>
{};
diff --git a/boost/geometry/algorithms/expand.hpp b/boost/geometry/algorithms/expand.hpp
index 19e40aa2d0..9dc0a48e06 100644
--- a/boost/geometry/algorithms/expand.hpp
+++ b/boost/geometry/algorithms/expand.hpp
@@ -20,6 +20,10 @@
#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>
@@ -29,9 +33,6 @@
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/policies/compare.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/apply_visitor.hpp>
-
namespace boost { namespace geometry
{
diff --git a/boost/geometry/algorithms/length.hpp b/boost/geometry/algorithms/length.hpp
index 6cbec5303e..fad17ade46 100644
--- a/boost/geometry/algorithms/length.hpp
+++ b/boost/geometry/algorithms/length.hpp
@@ -4,10 +4,11 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 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
+// 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.
@@ -22,6 +23,7 @@
#include <iterator>
#include <boost/concept_check.hpp>
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/mpl/fold.hpp>
@@ -69,6 +71,7 @@ struct segment_length
static inline typename default_length_result<Segment>::type apply(
Segment const& segment, Strategy const& strategy)
{
+ boost::ignore_unused(strategy);
typedef typename point_type<Segment>::type point_type;
point_type p1, p2;
geometry::detail::assign_point_from_index<0>(segment, p1);
@@ -92,7 +95,7 @@ struct range_length
static inline return_type apply(
Range const& range, Strategy const& strategy)
{
- boost::ignore_unused_variable_warning(strategy);
+ boost::ignore_unused(strategy);
typedef typename closeable_view<Range const, Closure>::type view_type;
typedef typename boost::range_iterator
<
diff --git a/boost/geometry/algorithms/not_implemented.hpp b/boost/geometry/algorithms/not_implemented.hpp
index cd40a2772f..9c416074ed 100644
--- a/boost/geometry/algorithms/not_implemented.hpp
+++ b/boost/geometry/algorithms/not_implemented.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// 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.
@@ -17,6 +22,7 @@
#include <boost/mpl/assert.hpp>
+#include <boost/mpl/identity.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -87,7 +93,7 @@ template <> struct tag_to_term<multi_point_tag> { typedef info::MULT
template <> struct tag_to_term<multi_linestring_tag> { typedef info::MULTI_LINESTRING type; };
template <> struct tag_to_term<multi_polygon_tag> { typedef info::MULTI_POLYGON type; };
template <> struct tag_to_term<geometry_collection_tag> { typedef info::GEOMETRY_COLLECTION type; };
-template <int D> struct tag_to_term<mpl::int_<D> > { typedef info::DIMENSION<D> type; };
+template <int D> struct tag_to_term<boost::mpl::int_<D> > { typedef info::DIMENSION<D> type; };
}
@@ -103,9 +109,18 @@ struct not_implemented
: nyi::not_implemented_tag,
nyi::not_implemented_error
<
- typename mpl::identity<typename nyi::tag_to_term<Term1>::type>::type,
- typename mpl::identity<typename nyi::tag_to_term<Term2>::type>::type,
- typename mpl::identity<typename nyi::tag_to_term<Term3>::type>::type
+ typename boost::mpl::identity
+ <
+ typename nyi::tag_to_term<Term1>::type
+ >::type,
+ typename boost::mpl::identity
+ <
+ typename nyi::tag_to_term<Term2>::type
+ >::type,
+ typename boost::mpl::identity
+ <
+ typename nyi::tag_to_term<Term3>::type
+ >::type
>
{};
diff --git a/boost/geometry/algorithms/num_geometries.hpp b/boost/geometry/algorithms/num_geometries.hpp
index d37d0bfabe..8144c22ab0 100644
--- a/boost/geometry/algorithms/num_geometries.hpp
+++ b/boost/geometry/algorithms/num_geometries.hpp
@@ -23,8 +23,9 @@
#include <cstddef>
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.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>
diff --git a/boost/geometry/algorithms/num_interior_rings.hpp b/boost/geometry/algorithms/num_interior_rings.hpp
index e198b37a75..04b4eb2a7c 100644
--- a/boost/geometry/algorithms/num_interior_rings.hpp
+++ b/boost/geometry/algorithms/num_interior_rings.hpp
@@ -24,8 +24,8 @@
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/tag.hpp>
diff --git a/boost/geometry/algorithms/num_points.hpp b/boost/geometry/algorithms/num_points.hpp
index 4c2ad3b08c..214fe9c8b0 100644
--- a/boost/geometry/algorithms/num_points.hpp
+++ b/boost/geometry/algorithms/num_points.hpp
@@ -26,8 +26,8 @@
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
diff --git a/boost/geometry/algorithms/num_segments.hpp b/boost/geometry/algorithms/num_segments.hpp
index cbb5685967..08af226caf 100644
--- a/boost/geometry/algorithms/num_segments.hpp
+++ b/boost/geometry/algorithms/num_segments.hpp
@@ -17,8 +17,8 @@
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
diff --git a/boost/geometry/algorithms/perimeter.hpp b/boost/geometry/algorithms/perimeter.hpp
index 0ec153c1f4..1b5ccacf9c 100644
--- a/boost/geometry/algorithms/perimeter.hpp
+++ b/boost/geometry/algorithms/perimeter.hpp
@@ -20,8 +20,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
#include <boost/range/metafunctions.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/length.hpp>
diff --git a/boost/geometry/algorithms/remove_spikes.hpp b/boost/geometry/algorithms/remove_spikes.hpp
index e62ea9fe3d..a96a2c29d0 100644
--- a/boost/geometry/algorithms/remove_spikes.hpp
+++ b/boost/geometry/algorithms/remove_spikes.hpp
@@ -16,8 +16,9 @@
#include <boost/range.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -26,11 +27,15 @@
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/tags.hpp>
+
#include <boost/geometry/geometries/concepts/check.hpp>
+
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/util/condition.hpp>
+
/*
Remove spikes from a ring/polygon.
@@ -94,7 +99,7 @@ struct range_remove_spikes
}
// For a closed-polygon, remove closing point, this makes checking first point(s) easier and consistent
- if (geometry::closure<Range>::value == geometry::closed)
+ if ( BOOST_GEOMETRY_CONDITION(geometry::closure<Range>::value == geometry::closed) )
{
cleaned.pop_back();
}
@@ -127,7 +132,7 @@ struct range_remove_spikes
}
// Close if necessary
- if (geometry::closure<Range>::value == geometry::closed)
+ if ( BOOST_GEOMETRY_CONDITION(geometry::closure<Range>::value == geometry::closed) )
{
cleaned.push_back(cleaned.front());
}
diff --git a/boost/geometry/algorithms/reverse.hpp b/boost/geometry/algorithms/reverse.hpp
index 17b23ffdfb..578771bfe3 100644
--- a/boost/geometry/algorithms/reverse.hpp
+++ b/boost/geometry/algorithms/reverse.hpp
@@ -19,8 +19,9 @@
#include <boost/range.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
diff --git a/boost/geometry/algorithms/simplify.hpp b/boost/geometry/algorithms/simplify.hpp
index 101b1324e1..0047546718 100644
--- a/boost/geometry/algorithms/simplify.hpp
+++ b/boost/geometry/algorithms/simplify.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.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -16,9 +16,11 @@
#include <cstddef>
+#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -32,6 +34,7 @@
#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
#include <boost/geometry/strategies/concepts/simplify_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/convert.hpp>
@@ -52,6 +55,8 @@ struct simplify_range_insert
static inline void apply(Range const& range, OutputIterator out,
Distance const& max_distance, Strategy const& strategy)
{
+ boost::ignore_unused(strategy);
+
if (boost::size(range) <= 2 || max_distance < 0)
{
std::copy(boost::begin(range), boost::end(range), out);
diff --git a/boost/geometry/algorithms/touches.hpp b/boost/geometry/algorithms/touches.hpp
index a06071d428..48334d7255 100644
--- a/boost/geometry/algorithms/touches.hpp
+++ b/boost/geometry/algorithms/touches.hpp
@@ -23,6 +23,10 @@
#include <deque>
+#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/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
@@ -32,9 +36,6 @@
#include <boost/geometry/algorithms/num_geometries.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/relate/relate.hpp>
diff --git a/boost/geometry/algorithms/transform.hpp b/boost/geometry/algorithms/transform.hpp
index 1d6e8d0a35..357263a4ea 100644
--- a/boost/geometry/algorithms/transform.hpp
+++ b/boost/geometry/algorithms/transform.hpp
@@ -20,8 +20,9 @@
#include <boost/range.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/assign.hpp>
diff --git a/boost/geometry/algorithms/validity_failure_type.hpp b/boost/geometry/algorithms/validity_failure_type.hpp
new file mode 100644
index 0000000000..42de99c585
--- /dev/null
+++ b/boost/geometry/algorithms/validity_failure_type.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_VALIDITY_FAILURE_TYPE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_VALIDITY_FAILURE_TYPE_HPP
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+\brief Enumerates the possible validity failure types for a geometry
+\ingroup enum
+\details The enumeration validity_failure_type enumerates the possible
+ reasons for which a geometry may be found as invalid by the
+ is_valid algorithm.
+ Besides the values that indicate invalidity, there is an
+ additional value (no_failure) that indicates validity.
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.is_valid The is_valid
+algorithm taking a reference to validity_failure_type as second argument]
+}
+*/
+enum validity_failure_type
+{
+ /// The geometry is valid
+ ///
+ no_failure = 0,
+ /// The geometry has a very small number of points, e.g., less
+ /// than 2 for linestrings, less than 3 for open rings, a closed
+ /// multi-polygon that contains a polygon with less than 4 points, etc.
+ /// (applies to linestrings, rings, polygons, multi-linestrings
+ /// and multi-polygons)
+ failure_few_points = 10,
+ /// The topological dimension of the geometry is smaller than its
+ /// dimension, e.g., a linestring with 3 identical points, an open
+ /// polygon with an interior ring consisting of 3 collinear points, etc.
+ /// (applies to linear and areal geometries, including segments
+ /// and boxes)
+ failure_wrong_topological_dimension = 11,
+ /// The geometry contains spikes
+ /// (applies to linear and areal geometries)
+ failure_spikes = 12,
+ /// The geometry has (consecutive) duplicate points
+ /// (applies to areal geometries only)
+ failure_duplicate_points = 13,
+ /// The geometry is defined as closed, the starting/ending points
+ /// are not equal
+ /// (applies to areal geometries only)
+ failure_not_closed = 20, // for areal geometries
+ /// The geometry has invalid self-intersections.
+ /// (applies to areal geometries only)
+ failure_self_intersections = 21, // for areal geometries
+ /// The actual orientation of the geometry is different from the one defined
+ /// (applies to areal geometries only)
+ failure_wrong_orientation = 22, // for areal geometries
+ /// The geometry contains interior rings that lie outside the exterior ring
+ /// (applies to polygons and multi-polygons only)
+ failure_interior_rings_outside = 30, // for (multi-)polygons
+ /// The geometry has nested interior rings
+ /// (applies to polygons and multi-polygons only)
+ failure_nested_interior_rings = 31, // for (multi-)polygons
+ /// The interior of the geometry is disconnected
+ /// (applies to polygons and multi-polygons only)
+ failure_disconnected_interior = 32, // for (multi-)polygons
+ /// The multi-polygon contains polygons whose interiors are not disjoint
+ /// (applies to multi-polygons only)
+ failure_intersecting_interiors = 40, // for multi-polygons
+ /// The top-right corner of the box is lexicographically smaller
+ /// than its bottom-left corner
+ /// (applies to boxes only)
+ failure_wrong_corner_order = 50 // for boxes
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_VALIDITY_FAILURE_TYPE_HPP
diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp
index f66b1ed1c6..9f2b6fedf7 100644
--- a/boost/geometry/algorithms/within.hpp
+++ b/boost/geometry/algorithms/within.hpp
@@ -24,8 +24,9 @@
#include <boost/concept_check.hpp>
#include <boost/range.hpp>
-#include <boost/variant/static_visitor.hpp>
+
#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/make.hpp>
diff --git a/boost/geometry/core/cs.hpp b/boost/geometry/core/cs.hpp
index cf6c56b53c..301fb6b76f 100644
--- a/boost/geometry/core/cs.hpp
+++ b/boost/geometry/core/cs.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-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -16,7 +21,8 @@
#include <cstddef>
-#include <boost/type_traits.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/integral_constant.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -45,6 +51,35 @@ struct degree {};
struct radian {};
+#ifndef DOXYGEN_NO_DETAIL
+namespace core_detail
+{
+
+template <typename DegreeOrRadian>
+struct coordinate_system_units
+{
+ BOOST_MPL_ASSERT_MSG
+ ((false),
+ COORDINATE_SYSTEM_UNITS_MUST_BE_DEGREES_OR_RADIANS,
+ (types<DegreeOrRadian>));
+};
+
+template <>
+struct coordinate_system_units<geometry::degree>
+{
+ typedef geometry::degree units;
+};
+
+template <>
+struct coordinate_system_units<geometry::radian>
+{
+ typedef geometry::radian units;
+};
+
+} // namespace core_detail
+#endif // DOXYGEN_NO_DETAIL
+
+
namespace cs
{
@@ -73,7 +108,10 @@ known as lat,long or lo,la or phi,lambda
template<typename DegreeOrRadian>
struct geographic
{
- typedef DegreeOrRadian units;
+ typedef typename core_detail::coordinate_system_units
+ <
+ DegreeOrRadian
+ >::units units;
};
@@ -99,7 +137,10 @@ struct geographic
template<typename DegreeOrRadian>
struct spherical
{
- typedef DegreeOrRadian units;
+ typedef typename core_detail::coordinate_system_units
+ <
+ DegreeOrRadian
+ >::units units;
};
@@ -116,7 +157,10 @@ struct spherical
template<typename DegreeOrRadian>
struct spherical_equatorial
{
- typedef DegreeOrRadian units;
+ typedef typename core_detail::coordinate_system_units
+ <
+ DegreeOrRadian
+ >::units units;
};
@@ -131,7 +175,10 @@ struct spherical_equatorial
template<typename DegreeOrRadian>
struct polar
{
- typedef DegreeOrRadian units;
+ typedef typename core_detail::coordinate_system_units
+ <
+ DegreeOrRadian
+ >::units units;
};
diff --git a/boost/geometry/core/interior_type.hpp b/boost/geometry/core/interior_type.hpp
index 02328372f0..e6c4537e41 100644
--- a/boost/geometry/core/interior_type.hpp
+++ b/boost/geometry/core/interior_type.hpp
@@ -86,7 +86,7 @@ struct interior_return_type<polygon_tag, Polygon>
{
typedef typename boost::remove_const<Polygon>::type nc_polygon_type;
- typedef typename mpl::if_
+ typedef typename boost::mpl::if_
<
boost::is_const<Polygon>,
typename traits::interior_const_type<nc_polygon_type>::type,
diff --git a/boost/geometry/core/radius.hpp b/boost/geometry/core/radius.hpp
new file mode 100644
index 0000000000..ee6d5d246f
--- /dev/null
+++ b/boost/geometry/core/radius.hpp
@@ -0,0 +1,250 @@
+// 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.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// 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_RADIUS_HPP
+#define BOOST_GEOMETRY_CORE_RADIUS_HPP
+
+
+#include <cstddef>
+
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+ \brief Traits class to get/set radius of a circle/sphere/(ellipse)
+ \details the radius access meta-functions give read/write access to the radius of a circle or a sphere,
+ or to the major/minor axis or an ellipse, or to one of the 3 equatorial radii of an ellipsoid.
+
+ It should be specialized per geometry, in namespace core_dispatch. Those specializations should
+ forward the call via traits to the geometry class, which could be specified by the user.
+
+ There is a corresponding generic radius_get and radius_set function
+ \par Geometries:
+ - n-sphere (circle,sphere)
+ - upcoming ellipse
+ \par Specializations should provide:
+ - inline static T get(Geometry const& geometry)
+ - inline static void set(Geometry& geometry, T const& radius)
+ \ingroup traits
+*/
+template <typename Geometry, std::size_t Dimension>
+struct radius_access {};
+
+
+/*!
+ \brief Traits class indicating the type (double,float,...) of the radius of a circle or a sphere
+ \par Geometries:
+ - n-sphere (circle,sphere)
+ - upcoming ellipse
+ \par Specializations should provide:
+ - typedef T type (double,float,int,etc)
+ \ingroup traits
+*/
+template <typename Geometry>
+struct radius_type {};
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct radius_type
+{
+ //typedef core_dispatch_specialization_required type;
+};
+
+/*!
+ \brief radius access meta-functions, used by concept n-sphere and upcoming ellipse.
+*/
+template <typename Tag,
+ typename Geometry,
+ std::size_t Dimension,
+ typename IsPointer>
+struct radius_access
+{
+ //static inline CoordinateType get(Geometry const& ) {}
+ //static inline void set(Geometry& g, CoordinateType const& value) {}
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Metafunction to get the type of radius of a circle / sphere / ellipse / etc.
+ \ingroup access
+ \tparam Geometry the type of geometry
+*/
+template <typename Geometry>
+struct radius_type
+{
+ typedef typename core_dispatch::radius_type
+ <
+ typename tag<Geometry>::type,
+ typename util::bare_type<Geometry>::type
+ >::type type;
+};
+
+/*!
+ \brief Function to get radius of a circle / sphere / ellipse / etc.
+ \return radius The radius for a given axis
+ \ingroup access
+ \param geometry the geometry to get the radius from
+ \tparam I index of the axis
+*/
+template <std::size_t I, typename Geometry>
+inline typename radius_type<Geometry>::type get_radius(Geometry const& geometry)
+{
+ return core_dispatch::radius_access
+ <
+ typename tag<Geometry>::type,
+ typename util::bare_type<Geometry>::type,
+ I,
+ typename boost::is_pointer<Geometry>::type
+ >::get(geometry);
+}
+
+/*!
+ \brief Function to set the radius of a circle / sphere / ellipse / etc.
+ \ingroup access
+ \tparam I index of the axis
+ \param geometry the geometry to change
+ \param radius the radius to set
+*/
+template <std::size_t I, typename Geometry>
+inline void set_radius(Geometry& geometry,
+ typename radius_type<Geometry>::type const& radius)
+{
+ core_dispatch::radius_access
+ <
+ typename tag<Geometry>::type,
+ typename util::bare_type<Geometry>::type,
+ I,
+ typename boost::is_pointer<Geometry>::type
+ >::set(geometry, radius);
+}
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Tag, typename Geometry, std::size_t Dimension>
+struct radius_access
+{
+ static inline typename radius_type<Geometry>::type get(Geometry const& geometry)
+ {
+ return traits::radius_access<Geometry, Dimension>::get(geometry);
+ }
+ static inline void set(Geometry& geometry,
+ typename radius_type<Geometry>::type const& value)
+ {
+ traits::radius_access<Geometry, Dimension>::set(geometry, value);
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag,
+ typename Geometry,
+ std::size_t Dimension>
+struct radius_access<Tag, Geometry, Dimension, boost::true_type>
+{
+ typedef typename geometry::radius_type<Geometry>::type radius_type;
+
+ static inline radius_type get(const Geometry * geometry)
+ {
+ return radius_access
+ <
+ Tag,
+ Geometry,
+ Dimension,
+ typename boost::is_pointer<Geometry>::type
+ >::get(*geometry);
+ }
+
+ static inline void set(Geometry * geometry, radius_type const& value)
+ {
+ return radius_access
+ <
+ Tag,
+ Geometry,
+ Dimension,
+ typename boost::is_pointer<Geometry>::type
+ >::set(*geometry, value);
+ }
+};
+
+
+template <typename Geometry>
+struct radius_type<srs_sphere_tag, Geometry>
+{
+ typedef typename traits::radius_type<Geometry>::type type;
+};
+
+template <typename Geometry, std::size_t Dimension>
+struct radius_access<srs_sphere_tag, Geometry, Dimension, boost::false_type>
+ : detail::radius_access<srs_sphere_tag, Geometry, Dimension>
+{
+ BOOST_STATIC_ASSERT(Dimension == 0);
+ //BOOST_STATIC_ASSERT(Dimension < 3);
+};
+
+template <typename Geometry>
+struct radius_type<srs_spheroid_tag, Geometry>
+{
+ typedef typename traits::radius_type<Geometry>::type type;
+};
+
+template <typename Geometry, std::size_t Dimension>
+struct radius_access<srs_spheroid_tag, Geometry, Dimension, boost::false_type>
+ : detail::radius_access<srs_spheroid_tag, Geometry, Dimension>
+{
+ BOOST_STATIC_ASSERT(Dimension == 0 || Dimension == 2);
+ //BOOST_STATIC_ASSERT(Dimension < 3);
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_RADIUS_HPP
diff --git a/boost/geometry/core/ring_type.hpp b/boost/geometry/core/ring_type.hpp
index fe551f060f..c007931126 100644
--- a/boost/geometry/core/ring_type.hpp
+++ b/boost/geometry/core/ring_type.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.
@@ -95,7 +100,7 @@ struct ring_return_type<polygon_tag, Polygon>
{
typedef typename boost::remove_const<Polygon>::type nc_polygon_type;
- typedef typename mpl::if_
+ typedef typename boost::mpl::if_
<
boost::is_const<Polygon>,
typename traits::ring_const_type<nc_polygon_type>::type,
@@ -110,7 +115,7 @@ struct ring_return_type<multi_linestring_tag, MultiLinestring>
typedef typename ring_return_type
<
linestring_tag,
- typename mpl::if_
+ typename boost::mpl::if_
<
boost::is_const<MultiLinestring>,
typename boost::range_value<MultiLinestring>::type const,
@@ -126,7 +131,7 @@ struct ring_return_type<multi_polygon_tag, MultiPolygon>
typedef typename ring_return_type
<
polygon_tag,
- typename mpl::if_
+ typename boost::mpl::if_
<
boost::is_const<MultiPolygon>,
typename boost::range_value<MultiPolygon>::type const,
diff --git a/boost/geometry/core/srs.hpp b/boost/geometry/core/srs.hpp
new file mode 100644
index 0000000000..bf1b4e28a5
--- /dev/null
+++ b/boost/geometry/core/srs.hpp
@@ -0,0 +1,195 @@
+// 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.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// 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_SRS_HPP
+#define BOOST_GEOMETRY_CORE_SRS_HPP
+
+
+#include <cstddef>
+
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace srs
+{
+
+/*!
+ \brief Defines spheroid radius values for use in geographical CS calculations
+ \note See http://en.wikipedia.org/wiki/Figure_of_the_Earth
+ and http://en.wikipedia.org/wiki/World_Geodetic_System#A_new_World_Geodetic_System:_WGS84
+*/
+template <typename RadiusType>
+class spheroid
+{
+public:
+ spheroid(RadiusType const& a, RadiusType const& b)
+ : m_a(a)
+ , m_b(b)
+ {}
+
+ spheroid()
+ : m_a(RadiusType(6378137.0))
+ , m_b(RadiusType(6356752.314245))
+ {}
+
+ template <std::size_t I>
+ RadiusType get_radius() const
+ {
+ BOOST_STATIC_ASSERT(I < 3);
+
+ return I < 2 ? m_a : m_b;
+ }
+
+ template <std::size_t I>
+ void set_radius(RadiusType const& radius)
+ {
+ BOOST_STATIC_ASSERT(I < 3);
+
+ (I < 2 ? m_a : m_b) = radius;
+ }
+
+private:
+ RadiusType m_a, m_b; // equatorial radius, polar radius
+};
+
+} // namespace srs
+
+// Traits specializations for spheroid
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename RadiusType>
+struct tag< srs::spheroid<RadiusType> >
+{
+ typedef srs_spheroid_tag type;
+};
+
+template <typename RadiusType>
+struct radius_type< srs::spheroid<RadiusType> >
+{
+ typedef RadiusType type;
+};
+
+template <typename RadiusType, std::size_t Dimension>
+struct radius_access<srs::spheroid<RadiusType>, Dimension>
+{
+ typedef srs::spheroid<RadiusType> spheroid_type;
+
+ static inline RadiusType get(spheroid_type const& s)
+ {
+ return s.template get_radius<Dimension>();
+ }
+
+ static inline void set(spheroid_type& s, RadiusType const& value)
+ {
+ s.template set_radius<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+namespace srs
+{
+
+/*!
+ \brief Defines sphere radius value for use in spherical CS calculations
+*/
+template <typename RadiusType>
+class sphere
+{
+public:
+ explicit sphere(RadiusType const& r)
+ : m_r(r)
+ {}
+ sphere()
+ : m_r(RadiusType((2.0 * 6378137.0 + 6356752.314245) / 3.0))
+ {}
+
+ template <std::size_t I>
+ RadiusType get_radius() const
+ {
+ BOOST_STATIC_ASSERT(I < 3);
+
+ return m_r;
+ }
+
+ template <std::size_t I>
+ void set_radius(RadiusType const& radius)
+ {
+ BOOST_STATIC_ASSERT(I < 3);
+
+ m_r = radius;
+ }
+
+private:
+ RadiusType m_r; // radius
+};
+
+} // namespace srs
+
+// Traits specializations for sphere
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename RadiusType>
+struct tag< srs::sphere<RadiusType> >
+{
+ typedef srs_sphere_tag type;
+};
+
+template <typename RadiusType>
+struct radius_type< srs::sphere<RadiusType> >
+{
+ typedef RadiusType type;
+};
+
+template <typename RadiusType, std::size_t Dimension>
+struct radius_access<srs::sphere<RadiusType>, Dimension>
+{
+ typedef srs::sphere<RadiusType> sphere_type;
+
+ static inline RadiusType get(sphere_type const& s)
+ {
+ return s.template get_radius<Dimension>();
+ }
+
+ static inline void set(sphere_type& s, RadiusType const& value)
+ {
+ s.template set_radius<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_SRS_HPP
diff --git a/boost/geometry/core/tags.hpp b/boost/geometry/core/tags.hpp
index 160477b8c4..5d6acb1878 100644
--- a/boost/geometry/core/tags.hpp
+++ b/boost/geometry/core/tags.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -37,6 +42,14 @@ struct spherical_equatorial_tag : spherical_tag {};
struct geographic_tag : spherical_tag {};
+// Tags defining coordinate systems reference models
+
+/// For reference spheroid defining parameters of geographical coordinate system
+struct srs_spheroid_tag {};
+
+/// For reference sphere defining parameters of spherical coordinate system
+struct srs_sphere_tag : srs_spheroid_tag {};
+
// Tags defining tag hierarchy
diff --git a/boost/geometry/geometries/adapted/boost_fusion.hpp b/boost/geometry/geometries/adapted/boost_fusion.hpp
index a9aba916a5..2f3594e4e7 100644
--- a/boost/geometry/geometries/adapted/boost_fusion.hpp
+++ b/boost/geometry/geometries/adapted/boost_fusion.hpp
@@ -1,7 +1,12 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2011-2012 Akira Takahashi
-// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2011-2015 Akira Takahashi
+// 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
@@ -13,23 +18,24 @@
#include <cstddef>
+#include <boost/core/enable_if.hpp>
+
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/tag_of.hpp>
#include <boost/fusion/include/front.hpp>
#include <boost/fusion/include/at.hpp>
-#include <boost/utility/enable_if.hpp>
-
#include <boost/fusion/mpl.hpp>
-#include <boost/mpl/front.hpp>
+
+#include <boost/mpl/and.hpp>
#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/size.hpp>
+
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/mpl/placeholders.hpp>
-#include <boost/mpl/and.hpp>
-#include <boost/mpl/front.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -65,7 +71,7 @@ struct is_coordinate_size : boost::mpl::bool_<
template<typename Sequence>
struct is_fusion_sequence
- : mpl::and_<boost::fusion::traits::is_sequence<Sequence>,
+ : boost::mpl::and_<boost::fusion::traits::is_sequence<Sequence>,
fusion_adapt_detail::is_coordinate_size<Sequence>,
fusion_adapt_detail::all_same<Sequence> >
{};
diff --git a/boost/geometry/geometries/concepts/point_concept.hpp b/boost/geometry/geometries/concepts/point_concept.hpp
index 1e1b31e61f..db49771129 100644
--- a/boost/geometry/geometries/concepts/point_concept.hpp
+++ b/boost/geometry/geometries/concepts/point_concept.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -17,6 +22,7 @@
#include <cstddef>
#include <boost/concept_check.hpp>
+#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -24,7 +30,6 @@
-
namespace boost { namespace geometry { namespace concept
{
@@ -46,6 +51,9 @@ The point concept is defined as following:
with two functions:
- \b get to get a coordinate value
- \b set to set a coordinate value (this one is not checked for ConstPoint)
+- for non-Cartesian coordinate systems, the coordinate system's units
+ must either be boost::geometry::degree or boost::geometry::radian
+
\par Example:
@@ -90,8 +98,12 @@ class Point
typedef typename coordinate_type<Geometry>::type ctype;
typedef typename coordinate_system<Geometry>::type csystem;
- enum { ccount = dimension<Geometry>::value };
+ // The following enum is used to fully instantiate the coordinate
+ // system class; this is needed in order to check the units passed
+ // to it for non-Cartesian coordinate systems.
+ enum { cs_check = sizeof(csystem) };
+ enum { ccount = dimension<Geometry>::value };
template <typename P, std::size_t Dimension, std::size_t DimensionCount>
struct dimension_checker
@@ -139,8 +151,12 @@ class ConstPoint
typedef typename coordinate_type<Geometry>::type ctype;
typedef typename coordinate_system<Geometry>::type csystem;
- enum { ccount = dimension<Geometry>::value };
+ // The following enum is used to fully instantiate the coordinate
+ // system class; this is needed in order to check the units passed
+ // to it for non-Cartesian coordinate systems.
+ enum { cs_check = sizeof(csystem) };
+ enum { ccount = dimension<Geometry>::value };
template <typename P, std::size_t Dimension, std::size_t DimensionCount>
struct dimension_checker
@@ -149,7 +165,7 @@ class ConstPoint
{
const P* p = 0;
ctype coord(geometry::get<Dimension>(*p));
- boost::ignore_unused_variable_warning(coord);
+ boost::ignore_unused(coord);
dimension_checker<P, Dimension+1, DimensionCount>::apply();
}
};
diff --git a/boost/geometry/geometries/linestring.hpp b/boost/geometry/geometries/linestring.hpp
index 38bc3d4c49..68dc87a3cf 100644
--- a/boost/geometry/geometries/linestring.hpp
+++ b/boost/geometry/geometries/linestring.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -25,6 +26,12 @@
#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
{
@@ -68,6 +75,30 @@ public :
inline linestring(Iterator begin, Iterator end)
: base_type(begin, end)
{}
+
+#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+ /// \constructor_initializer_list{linestring}
+ inline linestring(std::initializer_list<Point> l)
+ : base_type(l.begin(), l.end())
+ {}
+
+// Commented out for now in order to support Boost.Assign
+// Without this assignment operator first the object should be created
+// from initializer list, then it should be moved.
+//// Without this workaround in MSVC the assignment operator is ambiguous
+//#ifndef BOOST_MSVC
+// /// \assignment_initializer_list{linestring}
+// inline linestring & operator=(std::initializer_list<Point> l)
+// {
+// base_type::assign(l.begin(), l.end());
+// return *this;
+// }
+//#endif
+
+#endif
+#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/multi_linestring.hpp b/boost/geometry/geometries/multi_linestring.hpp
index 2ba8e7196b..195a58139c 100644
--- a/boost/geometry/geometries/multi_linestring.hpp
+++ b/boost/geometry/geometries/multi_linestring.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -22,6 +23,12 @@
#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
{
@@ -50,6 +57,39 @@ template
class multi_linestring : public Container<LineString, Allocator<LineString> >
{
BOOST_CONCEPT_ASSERT( (concept::Linestring<LineString>) );
+
+#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+
+ typedef Container<LineString, Allocator<LineString> > base_type;
+
+public:
+ /// \constructor_default{multi_linestring}
+ multi_linestring()
+ : 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())
+ {}
+
+// Commented out for now in order to support Boost.Assign
+// Without this assignment operator first the object should be created
+// from initializer list, then it shoudl be moved.
+//// Without this workaround in MSVC the assignment operator is ambiguous
+//#ifndef BOOST_MSVC
+// /// \assignment_initializer_list{multi_linestring}
+// inline multi_linestring & operator=(std::initializer_list<LineString> l)
+// {
+// base_type::assign(l.begin(), l.end());
+// return *this;
+// }
+//#endif
+
+#endif
+#endif
};
diff --git a/boost/geometry/geometries/multi_point.hpp b/boost/geometry/geometries/multi_point.hpp
index d0a782a1de..a5e64bb91c 100644
--- a/boost/geometry/geometries/multi_point.hpp
+++ b/boost/geometry/geometries/multi_point.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -22,6 +23,12 @@
#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
{
@@ -66,6 +73,30 @@ public :
inline multi_point(Iterator begin, Iterator end)
: base_type(begin, end)
{}
+
+#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+ /// \constructor_initializer_list{multi_point}
+ inline multi_point(std::initializer_list<Point> l)
+ : base_type(l.begin(), l.end())
+ {}
+
+// Commented out for now in order to support Boost.Assign
+// Without this assignment operator first the object should be created
+// from initializer list, then it shoudl be moved.
+//// Without this workaround in MSVC the assignment operator is ambiguous
+//#ifndef BOOST_MSVC
+// /// \assignment_initializer_list{multi_point}
+// inline multi_point & operator=(std::initializer_list<Point> l)
+// {
+// base_type::assign(l.begin(), l.end());
+// return *this;
+// }
+//#endif
+
+#endif
+#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/multi_polygon.hpp b/boost/geometry/geometries/multi_polygon.hpp
index 228074cd34..51fcf235f8 100644
--- a/boost/geometry/geometries/multi_polygon.hpp
+++ b/boost/geometry/geometries/multi_polygon.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -22,6 +23,13 @@
#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
{
@@ -48,6 +56,39 @@ template
class multi_polygon : public Container<Polygon, Allocator<Polygon> >
{
BOOST_CONCEPT_ASSERT( (concept::Polygon<Polygon>) );
+
+#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+
+ typedef Container<Polygon, Allocator<Polygon> > base_type;
+
+public:
+ /// \constructor_default{multi_polygon}
+ multi_polygon()
+ : 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())
+ {}
+
+// Commented out for now in order to support Boost.Assign
+// Without this assignment operator first the object should be created
+// from initializer list, then it shoudl be moved.
+//// Without this workaround in MSVC the assignment operator is ambiguous
+//#ifndef BOOST_MSVC
+// /// \assignment_initializer_list{multi_polygon}
+// inline multi_polygon & operator=(std::initializer_list<Polygon> l)
+// {
+// base_type::assign(l.begin(), l.end());
+// return *this;
+// }
+//#endif
+
+#endif
+#endif
};
diff --git a/boost/geometry/geometries/point.hpp b/boost/geometry/geometries/point.hpp
index a25340c463..056c7d5d02 100644
--- a/boost/geometry/geometries/point.hpp
+++ b/boost/geometry/geometries/point.hpp
@@ -1,8 +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-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -23,7 +29,6 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
-#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
@@ -38,6 +43,37 @@ namespace boost { namespace geometry
namespace model
{
+namespace detail
+{
+
+template <std::size_t DimensionCount, std::size_t Index>
+struct array_assign
+{
+ template <typename T>
+ static inline void apply(T values[], T const& value)
+ {
+ values[Index] = value;
+ }
+};
+
+// Specialization avoiding assigning element [2] for only 2 dimensions
+template <> struct array_assign<2, 2>
+{
+ template <typename T> static inline void apply(T [], T const& ) {}
+};
+
+// Specialization avoiding assigning elements for (rarely used) points in 1 dim
+template <> struct array_assign<1, 1>
+{
+ template <typename T> static inline void apply(T [], T const& ) {}
+};
+
+template <> struct array_assign<1, 2>
+{
+ template <typename T> static inline void apply(T [], T const& ) {}
+};
+
+}
/*!
\brief Basic point class, having coordinates defined in a neutral way
\details Defines a neutral point class, fulfilling the Point Concept.
@@ -64,18 +100,43 @@ template
>
class point
{
+private:
+ // The following enum is used to fully instantiate the
+ // CoordinateSystem class and check the correctness of the units
+ // passed for non-Cartesian coordinate systems.
+ enum { cs_check = sizeof(CoordinateSystem) };
+
public:
/// @brief Default constructor, no initialization
inline point()
- {}
+ {
+ BOOST_STATIC_ASSERT(DimensionCount >= 1);
+ }
+
+ /// @brief Constructor to set one value
+ explicit inline point(CoordinateType const& v0)
+ {
+ 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());
+ }
+
+ /// @brief Constructor to set two values
+ inline point(CoordinateType const& v0, CoordinateType const& v1)
+ {
+ 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());
+ }
- /// @brief Constructor to set one, two or three values
- explicit inline point(CoordinateType const& v0, CoordinateType const& v1 = 0, CoordinateType const& v2 = 0)
+ /// @brief Constructor to set three values
+ inline point(CoordinateType const& v0, CoordinateType const& v1,
+ CoordinateType const& v2)
{
- if (DimensionCount >= 1) m_values[0] = v0;
- if (DimensionCount >= 2) m_values[1] = v1;
- if (DimensionCount >= 3) m_values[2] = v2;
+ 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);
}
/// @brief Get a coordinate
diff --git a/boost/geometry/geometries/polygon.hpp b/boost/geometry/geometries/polygon.hpp
index ec8d1ec38f..5f2e87a11d 100644
--- a/boost/geometry/geometries/polygon.hpp
+++ b/boost/geometry/geometries/polygon.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -26,6 +27,13 @@
#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
{
@@ -83,6 +91,46 @@ public:
inline ring_type& outer() { return m_outer; }
inline inner_container_type & inners() { return m_inners; }
+#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+
+ /// \constructor_default{polygon}
+ inline polygon()
+ : m_outer()
+ , 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())
+ , m_inners(l.size() > 0 ? l.begin() + 1 : l.begin(), l.end())
+ {}
+
+// Commented out for now in order to support Boost.Assign
+// Without this assignment operator first the object should be created
+// from initializer list, then it shoudl be moved.
+//// Without this workaround in MSVC the assignment operator is ambiguous
+//#ifndef BOOST_MSVC
+// /// \assignment_initializer_list{polygon}
+// inline polygon & operator=(std::initializer_list<ring_type> l)
+// {
+// if ( l.size() > 0 )
+// {
+// m_outer = *l.begin();
+// m_inners.assign(l.begin() + 1, l.end());
+// }
+// else
+// {
+// m_outer.clear();
+// m_inners.clear();
+// }
+// return *this;
+// }
+//#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 998619785a..502c95d759 100644
--- a/boost/geometry/geometries/ring.hpp
+++ b/boost/geometry/geometries/ring.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -26,6 +27,12 @@
#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
{
@@ -72,6 +79,30 @@ public :
inline ring(Iterator begin, Iterator end)
: base_type(begin, end)
{}
+
+#ifdef BOOST_GEOMETRY_EXPERIMENTAL_ENABLE_INITIALIZER_LIST
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
+ /// \constructor_initializer_list{ring}
+ inline ring(std::initializer_list<Point> l)
+ : base_type(l.begin(), l.end())
+ {}
+
+// Commented out for now in order to support Boost.Assign
+// Without this assignment operator first the object should be created
+// from initializer list, then it shoudl be moved.
+//// Without this workaround in MSVC the assignment operator is ambiguous
+//#ifndef BOOST_MSVC
+// /// \assignment_initializer_list{ring}
+// inline ring & operator=(std::initializer_list<Point> l)
+// {
+// base_type::assign(l.begin(), l.end());
+// return *this;
+// }
+//#endif
+
+#endif
+#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/variant.hpp b/boost/geometry/geometries/variant.hpp
index 9db11d5a82..881eab9c8b 100644
--- a/boost/geometry/geometries/variant.hpp
+++ b/boost/geometry/geometries/variant.hpp
@@ -16,6 +16,7 @@
#include <boost/variant/variant_fwd.hpp>
+#include <boost/mpl/front.hpp>
namespace boost { namespace geometry {
@@ -23,7 +24,11 @@ namespace boost { namespace geometry {
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct point_type<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
- : point_type<T0>
+ : point_type<
+ typename boost::mpl::front<
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
+ >::type
+ >
{};
diff --git a/boost/geometry/geometry.hpp b/boost/geometry/geometry.hpp
index 110f0e60ff..8d34a0e4ef 100644
--- a/boost/geometry/geometry.hpp
+++ b/boost/geometry/geometry.hpp
@@ -1,8 +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.
@@ -25,6 +31,7 @@
#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/srs.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -34,9 +41,9 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
-
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
diff --git a/boost/geometry/index/detail/algorithms/is_valid.hpp b/boost/geometry/index/detail/algorithms/is_valid.hpp
index d85ac56d69..676eec2d2a 100644
--- a/boost/geometry/index/detail/algorithms/is_valid.hpp
+++ b/boost/geometry/index/detail/algorithms/is_valid.hpp
@@ -80,6 +80,9 @@ struct is_valid<Indexable, segment_tag>
template <typename Indexable>
inline bool is_valid(Indexable const& b)
{
+ // CONSIDER: detection of NaNs
+ // e.g. by comparison of b with copy of b
+
return dispatch::is_valid<Indexable>::apply(b);
}
diff --git a/boost/geometry/index/detail/assert.hpp b/boost/geometry/index/detail/assert.hpp
index 22af315bc8..311f37f640 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-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,20 +11,11 @@
#include <boost/assert.hpp>
+#ifndef BOOST_GEOMETRY_INDEX_ASSERT
+
#define BOOST_GEOMETRY_INDEX_ASSERT(CONDITION, TEXT_MSG) \
BOOST_ASSERT_MSG(CONDITION, TEXT_MSG)
-// TODO - change it to something like:
-// BOOST_ASSERT((CONDITION) && (TEXT_MSG))
-
-#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
-
-#define BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(PARAM)
-
-#else
-
-#define BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(PARAM) PARAM
-
-#endif
+#endif // BOOST_GEOMETRY_INDEX_ASSERT
#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 572368e273..0cd882fc94 100644
--- a/boost/geometry/index/detail/bounded_view.hpp
+++ b/boost/geometry/index/detail/bounded_view.hpp
@@ -155,7 +155,7 @@ struct indexed_access<index::detail::bounded_view<Segment, Box, Tag, box_tag>,
//static inline void set(box_type & b, coordinate_type const& value)
//{
- // BOOST_ASSERT(false);
+ // BOOST_GEOMETRY_INDEX_ASSERT(false, "unable to modify a box through view");
//}
};
@@ -173,7 +173,7 @@ struct indexed_access<index::detail::bounded_view<Segment, Box, Tag, box_tag>,
//static inline void set(box_type & b, coordinate_type const& value)
//{
- // BOOST_ASSERT(false);
+ // BOOST_GEOMETRY_INDEX_ASSERT(false, "unable to modify a box through view");
//}
};
diff --git a/boost/geometry/index/detail/distance_predicates.hpp b/boost/geometry/index/detail/distance_predicates.hpp
index 3e057290a6..9a9371df95 100644
--- a/boost/geometry/index/detail/distance_predicates.hpp
+++ b/boost/geometry/index/detail/distance_predicates.hpp
@@ -3,7 +3,7 @@
// Spatial index distance predicates, calculators and checkers
// used in nearest query - specialized for envelopes
//
-// 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
@@ -104,13 +104,13 @@ struct calculate_distance
// this handles nearest() with default Point parameter, to_nearest() and bounds
template <typename PointRelation, typename Indexable, typename Tag>
-struct calculate_distance< nearest<PointRelation>, Indexable, Tag >
+struct calculate_distance< predicates::nearest<PointRelation>, Indexable, Tag >
{
typedef detail::relation<PointRelation> relation;
typedef typename relation::value_type point_type;
typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
- static inline bool apply(nearest<PointRelation> const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::nearest<PointRelation> const& p, Indexable const& i, result_type & result)
{
result = geometry::comparable_distance(relation::value(p.point_or_relation), i);
return true;
@@ -118,12 +118,12 @@ struct calculate_distance< nearest<PointRelation>, Indexable, Tag >
};
template <typename Point, typename Indexable>
-struct calculate_distance< nearest< to_centroid<Point> >, Indexable, value_tag>
+struct calculate_distance< predicates::nearest< to_centroid<Point> >, Indexable, value_tag>
{
typedef Point point_type;
typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
- static inline bool apply(nearest< to_centroid<Point> > const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::nearest< to_centroid<Point> > const& p, Indexable const& i, result_type & result)
{
result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i);
return true;
@@ -131,12 +131,12 @@ struct calculate_distance< nearest< to_centroid<Point> >, Indexable, value_tag>
};
template <typename Point, typename Indexable>
-struct calculate_distance< nearest< to_furthest<Point> >, Indexable, value_tag>
+struct calculate_distance< predicates::nearest< to_furthest<Point> >, Indexable, value_tag>
{
typedef Point point_type;
typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;
- static inline bool apply(nearest< to_furthest<Point> > const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::nearest< to_furthest<Point> > const& p, Indexable const& i, result_type & result)
{
result = index::detail::comparable_distance_far(p.point_or_relation.value, i);
return true;
@@ -144,13 +144,13 @@ struct calculate_distance< nearest< to_furthest<Point> >, Indexable, value_tag>
};
template <typename SegmentOrLinestring, typename Indexable, typename Tag>
-struct calculate_distance< path<SegmentOrLinestring>, Indexable, Tag>
+struct calculate_distance< predicates::path<SegmentOrLinestring>, Indexable, Tag>
{
typedef typename index::detail::default_path_intersection_distance_type<
Indexable, SegmentOrLinestring
>::type result_type;
- static inline bool apply(path<SegmentOrLinestring> const& p, Indexable const& i, result_type & result)
+ static inline bool apply(predicates::path<SegmentOrLinestring> const& p, Indexable const& i, result_type & result)
{
return index::detail::path_intersection(i, p.geometry, result);
}
diff --git a/boost/geometry/index/detail/exception.hpp b/boost/geometry/index/detail/exception.hpp
index c3ea0e1923..e2090533e7 100644
--- a/boost/geometry/index/detail/exception.hpp
+++ b/boost/geometry/index/detail/exception.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry Index
//
-// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2014 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,10 +9,14 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP
+#include <boost/core/no_exceptions_support.hpp>
+
#ifndef BOOST_NO_EXCEPTIONS
#include <stdexcept>
+#include <boost/throw_exception.hpp>
#else
#include <cstdlib>
+#include <boost/geometry/index/detail/assert.hpp>
#endif
namespace boost { namespace geometry { namespace index { namespace detail {
@@ -21,47 +25,58 @@ namespace boost { namespace geometry { namespace index { namespace detail {
inline void throw_runtime_error(const char * str)
{
- throw std::runtime_error(str);
+ BOOST_THROW_EXCEPTION(std::runtime_error(str));
}
inline void throw_logic_error(const char * str)
{
- throw std::logic_error(str);
+ BOOST_THROW_EXCEPTION(std::logic_error(str));
}
inline void throw_invalid_argument(const char * str)
{
- throw std::invalid_argument(str);
+ BOOST_THROW_EXCEPTION(std::invalid_argument(str));
}
inline void throw_length_error(const char * str)
{
- throw std::length_error(str);
+ BOOST_THROW_EXCEPTION(std::length_error(str));
+}
+
+inline void throw_out_of_range(const char * str)
+{
+ BOOST_THROW_EXCEPTION(std::out_of_range(str));
}
#else
inline void throw_runtime_error(const char * str)
{
- BOOST_ASSERT_MSG(!"runtime_error thrown", str);
+ BOOST_GEOMETRY_INDEX_ASSERT(!"runtime_error thrown", str);
std::abort();
}
inline void throw_logic_error(const char * str)
{
- BOOST_ASSERT_MSG(!"logic_error thrown", str);
+ BOOST_GEOMETRY_INDEX_ASSERT(!"logic_error thrown", str);
std::abort();
}
inline void throw_invalid_argument(const char * str)
{
- BOOST_ASSERT_MSG(!"invalid_argument thrown", str);
+ BOOST_GEOMETRY_INDEX_ASSERT(!"invalid_argument thrown", str);
std::abort();
}
inline void throw_length_error(const char * str)
{
- BOOST_ASSERT_MSG(!"length_error thrown", str);
+ BOOST_GEOMETRY_INDEX_ASSERT(!"length_error thrown", str);
+ std::abort();
+}
+
+inline void throw_out_of_range(const char * str)
+{
+ BOOST_GEOMETRY_INDEX_ASSERT(!"out_of_range thrown", str);
std::abort();
}
diff --git a/boost/geometry/index/detail/predicates.hpp b/boost/geometry/index/detail/predicates.hpp
index b92256649a..60f80207d8 100644
--- a/boost/geometry/index/detail/predicates.hpp
+++ b/boost/geometry/index/detail/predicates.hpp
@@ -2,7 +2,7 @@
//
// Spatial query predicates definition and checks.
//
-// Copyright (c) 2011-2013 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
@@ -16,6 +16,8 @@
namespace boost { namespace geometry { namespace index { namespace detail {
+namespace predicates {
+
// ------------------------------------------------------------------ //
// predicates
// ------------------------------------------------------------------ //
@@ -92,6 +94,8 @@ struct path
unsigned count;
};
+} // namespace predicates
+
// ------------------------------------------------------------------ //
// predicate_check
// ------------------------------------------------------------------ //
@@ -108,20 +112,20 @@ struct predicate_check
// ------------------------------------------------------------------ //
template <typename Fun>
-struct predicate_check<satisfies<Fun, false>, value_tag>
+struct predicate_check<predicates::satisfies<Fun, false>, value_tag>
{
template <typename Value, typename Indexable>
- static inline bool apply(satisfies<Fun, false> const& p, Value const& v, Indexable const&)
+ static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const&)
{
return p.fun(v);
}
};
template <typename Fun>
-struct predicate_check<satisfies<Fun, true>, value_tag>
+struct predicate_check<predicates::satisfies<Fun, true>, value_tag>
{
template <typename Value, typename Indexable>
- static inline bool apply(satisfies<Fun, true> const& p, Value const& v, Indexable const&)
+ static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const&)
{
return !p.fun(v);
}
@@ -136,7 +140,7 @@ struct spatial_predicate_call
};
template <>
-struct spatial_predicate_call<contains_tag>
+struct spatial_predicate_call<predicates::contains_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -146,7 +150,7 @@ struct spatial_predicate_call<contains_tag>
};
template <>
-struct spatial_predicate_call<covered_by_tag>
+struct spatial_predicate_call<predicates::covered_by_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -156,7 +160,7 @@ struct spatial_predicate_call<covered_by_tag>
};
template <>
-struct spatial_predicate_call<covers_tag>
+struct spatial_predicate_call<predicates::covers_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -166,7 +170,7 @@ struct spatial_predicate_call<covers_tag>
};
template <>
-struct spatial_predicate_call<disjoint_tag>
+struct spatial_predicate_call<predicates::disjoint_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -176,7 +180,7 @@ struct spatial_predicate_call<disjoint_tag>
};
template <>
-struct spatial_predicate_call<intersects_tag>
+struct spatial_predicate_call<predicates::intersects_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -186,7 +190,7 @@ struct spatial_predicate_call<intersects_tag>
};
template <>
-struct spatial_predicate_call<overlaps_tag>
+struct spatial_predicate_call<predicates::overlaps_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -196,7 +200,7 @@ struct spatial_predicate_call<overlaps_tag>
};
template <>
-struct spatial_predicate_call<touches_tag>
+struct spatial_predicate_call<predicates::touches_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -206,7 +210,7 @@ struct spatial_predicate_call<touches_tag>
};
template <>
-struct spatial_predicate_call<within_tag>
+struct spatial_predicate_call<predicates::within_tag>
{
template <typename G1, typename G2>
static inline bool apply(G1 const& g1, G2 const& g2)
@@ -219,9 +223,9 @@ struct spatial_predicate_call<within_tag>
// spatial predicate
template <typename Geometry, typename Tag>
-struct predicate_check<spatial_predicate<Geometry, Tag, false>, value_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, value_tag>
{
- typedef spatial_predicate<Geometry, Tag, false> Pred;
+ typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
@@ -232,9 +236,9 @@ struct predicate_check<spatial_predicate<Geometry, Tag, false>, value_tag>
// negated spatial predicate
template <typename Geometry, typename Tag>
-struct predicate_check<spatial_predicate<Geometry, Tag, true>, value_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value_tag>
{
- typedef spatial_predicate<Geometry, Tag, true> Pred;
+ typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
@@ -246,20 +250,20 @@ struct predicate_check<spatial_predicate<Geometry, Tag, true>, value_tag>
// ------------------------------------------------------------------ //
template <typename DistancePredicates>
-struct predicate_check<nearest<DistancePredicates>, value_tag>
+struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
{
template <typename Value, typename Box>
- static inline bool apply(nearest<DistancePredicates> const&, Value const&, Box const&)
+ static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
{
return true;
}
};
template <typename Linestring>
-struct predicate_check<path<Linestring>, value_tag>
+struct predicate_check<predicates::path<Linestring>, value_tag>
{
template <typename Value, typename Box>
- static inline bool apply(path<Linestring> const&, Value const&, Box const&)
+ static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)
{
return true;
}
@@ -270,10 +274,10 @@ struct predicate_check<path<Linestring>, value_tag>
// ------------------------------------------------------------------ //
template <typename Fun, bool Negated>
-struct predicate_check<satisfies<Fun, Negated>, bounds_tag>
+struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>
{
template <typename Value, typename Box>
- static bool apply(satisfies<Fun, Negated> const&, Value const&, Box const&)
+ static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&)
{
return true;
}
@@ -295,53 +299,53 @@ struct predicate_check<satisfies<Fun, Negated>, bounds_tag>
// spatial predicate - default
template <typename Geometry, typename Tag>
-struct predicate_check<spatial_predicate<Geometry, Tag, false>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, bounds_tag>
{
- typedef spatial_predicate<Geometry, Tag, false> Pred;
+ typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
{
- return spatial_predicate_call<intersects_tag>::apply(i, p.geometry);
+ return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
}
};
// spatial predicate - contains
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, contains_tag, false>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, false>, bounds_tag>
{
- typedef spatial_predicate<Geometry, contains_tag, false> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
{
- return spatial_predicate_call<contains_tag>::apply(i, p.geometry);
+ return spatial_predicate_call<predicates::contains_tag>::apply(i, p.geometry);
}
};
// spatial predicate - covers
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, covers_tag, false>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, false>, bounds_tag>
{
- typedef spatial_predicate<Geometry, covers_tag, false> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
{
- return spatial_predicate_call<covers_tag>::apply(i, p.geometry);
+ return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);
}
};
// spatial predicate - disjoint
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, disjoint_tag, false>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false>, bounds_tag>
{
- typedef spatial_predicate<Geometry, disjoint_tag, false> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
{
- return !spatial_predicate_call<covered_by_tag>::apply(i, p.geometry);
+ return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
}
};
@@ -359,9 +363,9 @@ struct predicate_check<spatial_predicate<Geometry, disjoint_tag, false>, bounds_
// negated spatial predicate - default
template <typename Geometry, typename Tag>
-struct predicate_check<spatial_predicate<Geometry, Tag, true>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bounds_tag>
{
- typedef spatial_predicate<Geometry, Tag, true> Pred;
+ typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
@@ -372,9 +376,9 @@ struct predicate_check<spatial_predicate<Geometry, Tag, true>, bounds_tag>
// negated spatial predicate - contains
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, contains_tag, true>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, true>, bounds_tag>
{
- typedef spatial_predicate<Geometry, contains_tag, true> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& , Value const&, Indexable const& )
@@ -385,9 +389,9 @@ struct predicate_check<spatial_predicate<Geometry, contains_tag, true>, bounds_t
// negated spatial predicate - covers
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, covers_tag, true>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, true>, bounds_tag>
{
- typedef spatial_predicate<Geometry, covers_tag, true> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& , Value const&, Indexable const& )
@@ -398,22 +402,22 @@ struct predicate_check<spatial_predicate<Geometry, covers_tag, true>, bounds_tag
// negated spatial predicate - intersects
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, intersects_tag, true>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::intersects_tag, true>, bounds_tag>
{
- typedef spatial_predicate<Geometry, intersects_tag, true> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
{
- return !spatial_predicate_call<covered_by_tag>::apply(i, p.geometry);
+ return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);
}
};
// negated spatial predicate - overlaps
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, overlaps_tag, true>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true>, bounds_tag>
{
- typedef spatial_predicate<Geometry, overlaps_tag, true> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& , Value const&, Indexable const& )
@@ -424,34 +428,34 @@ struct predicate_check<spatial_predicate<Geometry, overlaps_tag, true>, bounds_t
// negated spatial predicate - touches
template <typename Geometry>
-struct predicate_check<spatial_predicate<Geometry, touches_tag, true>, bounds_tag>
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touches_tag, true>, bounds_tag>
{
- typedef spatial_predicate<Geometry, touches_tag, true> Pred;
+ typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;
template <typename Value, typename Indexable>
static inline bool apply(Pred const& p, Value const&, Indexable const& i)
{
- return !spatial_predicate_call<intersects_tag>::apply(i, p.geometry);
+ return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
}
};
// ------------------------------------------------------------------ //
template <typename DistancePredicates>
-struct predicate_check<nearest<DistancePredicates>, bounds_tag>
+struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
{
template <typename Value, typename Box>
- static inline bool apply(nearest<DistancePredicates> const&, Value const&, Box const&)
+ static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)
{
return true;
}
};
template <typename Linestring>
-struct predicate_check<path<Linestring>, bounds_tag>
+struct predicate_check<predicates::path<Linestring>, bounds_tag>
{
template <typename Value, typename Box>
- static inline bool apply(path<Linestring> const&, Value const&, Box const&)
+ static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)
{
return true;
}
@@ -697,13 +701,13 @@ struct predicates_is_distance
};
template <typename DistancePredicates>
-struct predicates_is_distance< nearest<DistancePredicates> >
+struct predicates_is_distance< predicates::nearest<DistancePredicates> >
{
static const unsigned value = 1;
};
template <typename Linestring>
-struct predicates_is_distance< path<Linestring> >
+struct predicates_is_distance< predicates::path<Linestring> >
{
static const unsigned value = 1;
};
diff --git a/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
index 05a64c7b72..a10b046c0d 100644
--- a/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
@@ -149,7 +149,7 @@ struct find_greatest_normalized_separation
// highest_low - lowest_high
separation = difference<separation_type>(lowest_high, highest_low);
- // BOOST_ASSERT(0 <= width);
+ // BOOST_GEOMETRY_INDEX_ASSERT(0 <= width);
if ( std::numeric_limits<coordinate_type>::epsilon() < width )
separation /= width;
diff --git a/boost/geometry/index/detail/rtree/node/auto_deallocator.hpp b/boost/geometry/index/detail/rtree/node/auto_deallocator.hpp
deleted file mode 100644
index dd55c6d76c..0000000000
--- a/boost/geometry/index/detail/rtree/node/auto_deallocator.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Boost.Geometry Index
-//
-// R-tree auto deallocator
-//
-// Copyright (c) 2011-2013 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_NODE_AUTO_DEALLOCATOR_HPP
-#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_AUTO_DEALLOCATOR_HPP
-
-namespace boost { namespace geometry { namespace index {
-
-namespace detail { namespace rtree {
-
-template <typename Alloc>
-class auto_deallocator
-{
- auto_deallocator(auto_deallocator const&);
- auto_deallocator & operator=(auto_deallocator const&);
-public:
- typedef typename Alloc::pointer pointer;
- inline auto_deallocator(Alloc & a, pointer p) : m_alloc(a), m_ptr(p) {}
- inline ~auto_deallocator() { if ( m_ptr ) boost::container::allocator_traits<Alloc>::deallocate(m_alloc, m_ptr, 1); }
- inline void release() { m_ptr = 0; }
- inline pointer ptr() { return m_ptr; }
-private:
- Alloc & m_alloc;
- pointer m_ptr;
-};
-
-}} // namespace detail::rtree
-
-}}} // namespace boost::geometry::index
-
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_AUTO_DEALLOCATOR_HPP
diff --git a/boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp b/boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp
deleted file mode 100644
index 43dff56bcb..0000000000
--- a/boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// Boost.Geometry Index
-//
-// R-tree nodes weak visitor and nodes base type
-//
-// Copyright (c) 2011-2014 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_NODE_WEAK_VISITOR_HPP
-#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP
-
-namespace boost { namespace geometry { namespace index {
-
-namespace detail { namespace rtree {
-
-// empty visitor
-template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>
-struct weak_visitor {};
-
-// node
-
-template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
-struct weak_node {};
-
-// nodes variants forward declarations
-
-template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
-struct weak_internal_node;
-
-template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
-struct weak_leaf;
-
-// nodes conversion
-
-template <typename Derived, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
-inline Derived & get(weak_node<Value, Parameters, Box, Allocators, Tag> & n)
-{
- return static_cast<Derived&>(n);
-}
-
-// apply visitor
-
-template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
-inline void apply_visitor(Visitor & v,
- raw_node<Value, Parameters, Box, Allocators, Tag> & n,
- bool is_internal_node)
-{
- BOOST_GEOMETRY_INDEX_ASSERT(&n, "null ptr");
- if ( is_internal_node )
- {
- typedef raw_internal_node<Value, Parameters, Box, Allocators, Tag> internal_node;
- v(get<internal_node>(n));
- }
- else
- {
- typedef raw_leaf<Value, Parameters, Box, Allocators, Tag> leaf;
- v(get<leaf>(n));
- }
-}
-
-}} // namespace detail::rtree
-
-}}} // namespace boost::geometry::index
-
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node.hpp b/boost/geometry/index/detail/rtree/node/node.hpp
index a632ece66a..528d473170 100644
--- a/boost/geometry/index/detail/rtree/node/node.hpp
+++ b/boost/geometry/index/detail/rtree/node/node.hpp
@@ -2,7 +2,7 @@
//
// R-tree nodes
//
-// 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
@@ -16,8 +16,8 @@
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
-#include <boost/geometry/index/detail/rtree/node/auto_deallocator.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp>
//#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
//#include <boost/geometry/index/detail/rtree/node/weak_dynamic.hpp>
@@ -27,7 +27,7 @@
#include <boost/geometry/index/detail/rtree/node/variant_dynamic.hpp>
#include <boost/geometry/index/detail/rtree/node/variant_static.hpp>
-#include <boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp>
+#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
#include <boost/geometry/algorithms/expand.hpp>
@@ -70,11 +70,11 @@ struct destroy_element
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
- typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
inline static void apply(typename internal_node::elements_type::value_type & element, Allocators & allocators)
{
- node_auto_ptr dummy(element.second, allocators);
+ subtree_destroyer dummy(element.second, allocators);
element.second = 0;
}
@@ -108,11 +108,11 @@ private:
inline static void apply_dispatch(It first, It last, Allocators & allocators,
boost::mpl::bool_<false> const& /*is_range_of_values*/)
{
- typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
for ( ; first != last ; ++first )
{
- node_auto_ptr dummy(first->second, allocators);
+ subtree_destroyer dummy(first->second, allocators);
first->second = 0;
}
}
diff --git a/boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp b/boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp
new file mode 100644
index 0000000000..2d08d89ef7
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp
@@ -0,0 +1,48 @@
+// Boost.Geometry Index
+//
+// R-tree scoped deallocator
+//
+// 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_NODE_SCOPED_DEALLOCATOR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Alloc>
+class scoped_deallocator
+{
+ scoped_deallocator(scoped_deallocator const&);
+ scoped_deallocator & operator=(scoped_deallocator const&);
+public:
+ typedef typename Alloc::pointer pointer;
+ inline scoped_deallocator(pointer p, Alloc & a)
+ : m_ptr(p), m_alloc(a)
+ {}
+ inline ~scoped_deallocator()
+ {
+ if ( m_ptr )
+ {
+ boost::container::allocator_traits<Alloc>::deallocate(m_alloc, m_ptr, 1);
+ }
+ }
+ inline void release()
+ {
+ m_ptr = 0;
+ }
+private:
+ pointer m_ptr;
+ Alloc & m_alloc;
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp b/boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp
index c19e123b62..3376068eed 100644
--- a/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp
+++ b/boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp
@@ -1,15 +1,15 @@
// Boost.Geometry Index
//
-// R-tree node auto ptr
+// R-tree subtree scoped destroyer
//
-// Copyright (c) 2011-2013 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
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP
-#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_HPP
#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
@@ -17,31 +17,29 @@ namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
-// TODO - change the name to node_scoped_ptr
-
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
-class node_auto_ptr
+class subtree_destroyer
{
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
typedef typename Allocators::node_pointer pointer;
- node_auto_ptr(node_auto_ptr const&);
- node_auto_ptr & operator=(node_auto_ptr const&);
+ subtree_destroyer(subtree_destroyer const&);
+ subtree_destroyer & operator=(subtree_destroyer const&);
public:
- node_auto_ptr(pointer ptr, Allocators & allocators)
+ subtree_destroyer(pointer ptr, Allocators & allocators)
: m_ptr(ptr)
, m_allocators(allocators)
{}
- ~node_auto_ptr()
+ ~subtree_destroyer()
{
reset();
}
void reset(pointer ptr = 0)
{
- if ( m_ptr )
+ if ( m_ptr && m_ptr != ptr )
{
detail::rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(m_ptr, m_allocators);
detail::rtree::apply_visitor(del_v, *m_ptr);
@@ -78,4 +76,4 @@ private:
}}} // namespace boost::geometry::index
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_HPP
diff --git a/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp b/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
index f13dd10360..8e052e5216 100644
--- a/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
+++ b/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
@@ -96,7 +96,8 @@ class allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>
typename node<
Value, Parameters, Box,
allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>,
- node_variant_dynamic_tag>::type
+ node_variant_dynamic_tag
+ >::type
>::other
{
typedef typename Allocator::template rebind<
@@ -180,7 +181,7 @@ struct create_variant_node
if ( 0 == p )
throw_runtime_error("boost::geometry::index::rtree node creation failed");
- auto_deallocator<AllocNode> deallocator(alloc_node, p);
+ scoped_deallocator<AllocNode> deallocator(p, alloc_node);
Al::construct(alloc_node, boost::addressof(*p), Node(alloc_node)); // implicit cast to Variant
diff --git a/boost/geometry/index/detail/rtree/node/variant_static.hpp b/boost/geometry/index/detail/rtree/node/variant_static.hpp
index f6e9761b2d..174ceb7e7f 100644
--- a/boost/geometry/index/detail/rtree/node/variant_static.hpp
+++ b/boost/geometry/index/detail/rtree/node/variant_static.hpp
@@ -79,7 +79,7 @@ struct visitor<Value, Parameters, Box, Allocators, node_variant_static_tag, IsVi
// allocators
template <typename Allocator, typename Value, typename Parameters, typename Box>
-struct allocators<Allocator, Value, Parameters, Box, node_variant_static_tag>
+class allocators<Allocator, Value, Parameters, Box, node_variant_static_tag>
: public Allocator::template rebind<
typename node<
Value, Parameters, Box,
@@ -153,40 +153,6 @@ public:
node_allocator_type const& node_allocator() const { return *this; }
};
-// create_node
-
-template <typename Allocators, typename Value, typename Parameters, typename Box>
-struct create_node<
- Allocators,
- variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>
->
-{
- static inline typename Allocators::node_pointer
- apply(Allocators & allocators)
- {
- return create_variant_node<
- typename Allocators::node_pointer,
- variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>
- >::apply(allocators.node_allocator());
- }
-};
-
-template <typename Allocators, typename Value, typename Parameters, typename Box>
-struct create_node<
- Allocators,
- variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>
->
-{
- static inline typename Allocators::node_pointer
- apply(Allocators & allocators)
- {
- return create_variant_node<
- typename Allocators::node_pointer,
- variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>
- >::apply(allocators.node_allocator());
- }
-};
-
}} // namespace detail::rtree
}}} // namespace boost::geometry::index
diff --git a/boost/geometry/index/detail/rtree/node/variant_visitor.hpp b/boost/geometry/index/detail/rtree/node/variant_visitor.hpp
index ffd67039d2..e272f9e1d9 100644
--- a/boost/geometry/index/detail/rtree/node/variant_visitor.hpp
+++ b/boost/geometry/index/detail/rtree/node/variant_visitor.hpp
@@ -11,7 +11,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_VISITOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_VISITOR_HPP
-#include <boost/variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/get.hpp>
+#include <boost/variant/variant.hpp>
namespace boost { namespace geometry { namespace index {
diff --git a/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp b/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
index b828b35f45..d49e347826 100644
--- a/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
+++ b/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
@@ -197,7 +197,7 @@ struct create_weak_node
if ( 0 == p )
throw_runtime_error("boost::geometry::index::rtree node creation failed");
- auto_deallocator<AllocNode> deallocator(alloc_node, p);
+ scoped_deallocator<AllocNode> deallocator(p, alloc_node);
Al::construct(alloc_node, boost::addressof(*p), alloc_node);
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
index 46bf357fc4..b7be41ab2b 100644
--- a/boost/geometry/index/detail/rtree/pack_create.hpp
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -2,7 +2,7 @@
//
// R-tree initial packing
//
-// Copyright (c) 2011-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
@@ -122,7 +122,7 @@ class pack
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
typedef typename Allocators::node_pointer node_pointer;
- typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
typedef typename Allocators::size_type size_type;
typedef typename geometry::point_type<Box>::type point_type;
@@ -161,10 +161,21 @@ public:
geometry::assign_inverse(hint_box);
for ( ; first != last ; ++first )
{
- geometry::expand(hint_box, translator(*first));
+ // NOTE: support for iterators not returning true references adapted
+ // to Geometry concept and default translator returning true reference
+ // An alternative would be to dereference the iterator and translate
+ // in one expression each time the indexable was needed.
+ typename std::iterator_traits<InIt>::reference in_ref = *first;
+ typename Translator::result_type indexable = translator(in_ref);
+
+ // NOTE: added for consistency with insert()
+ // 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);
point_type pt;
- geometry::centroid(translator(*first), pt);
+ geometry::centroid(indexable, pt);
entries.push_back(std::make_pair(pt, first));
}
@@ -187,17 +198,19 @@ private:
internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts,
parameters_type const& parameters, Translator const& translator, Allocators & allocators)
{
- BOOST_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count);
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count,
+ "unexpected parameters");
if ( subtree_counts.maxc <= 1 )
{
// ROOT or LEAF
- BOOST_ASSERT(values_count <= parameters.get_max_elements());
+ BOOST_GEOMETRY_INDEX_ASSERT(values_count <= parameters.get_max_elements(),
+ "too big number of elements");
// if !root check m_parameters.get_min_elements() <= count
// create new leaf node
node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)
- node_auto_ptr auto_remover(n, allocators);
+ subtree_destroyer auto_remover(n, allocators);
leaf & l = rtree::get<leaf>(*n);
// reserve space for values
@@ -207,8 +220,11 @@ private:
geometry::assign_inverse(elements_box);
for ( ; first != last ; ++first )
{
- rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
+ // 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)));
+ rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
}
auto_remover.release();
@@ -222,7 +238,7 @@ private:
// create new internal node
node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)
- node_auto_ptr auto_remover(n, allocators);
+ subtree_destroyer auto_remover(n, allocators);
internal_node & in = rtree::get<internal_node>(*n);
// reserve space for values
@@ -248,9 +264,11 @@ private:
internal_elements & elements, Box & elements_box,
parameters_type const& parameters, Translator const& translator, Allocators & allocators)
{
- BOOST_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count);
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count,
+ "unexpected parameters");
- BOOST_ASSERT_MSG( subtree_counts.minc <= values_count, "too small number of elements");
+ BOOST_GEOMETRY_INDEX_ASSERT(subtree_counts.minc <= values_count,
+ "too small number of elements");
// only one packet
if ( values_count <= subtree_counts.maxc )
@@ -262,7 +280,7 @@ private:
// in case if push_back() do throw here
// and even if this is not probable (previously reserved memory, nonthrowing pairs copy)
// this case is also tested by exceptions test.
- node_auto_ptr auto_remover(el.second, allocators);
+ subtree_destroyer auto_remover(el.second, allocators);
// this container should have memory allocated, reserve() called outside
elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't
auto_remover.release();
@@ -343,7 +361,7 @@ private:
{
if ( subtree_counts.minc <= r ) // e.g. 10 <= 2 == false
{
- //BOOST_ASSERT_MSG(0 < n, "unexpected value");
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value");
median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((2+1)/2) * 25 which would be ok, but not in all cases
}
else // r < subtree_counts.second // e.g. 2 < 10 == true
@@ -354,7 +372,7 @@ private:
if ( r == 0 ) // e.g. false
{
// n can't be equal to 0 because then there wouldn't be any element in the other node
- //BOOST_ASSERT_MSG(0 < n, "unexpected value");
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value");
median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((1+1)/2) * 25 which would be ok, but not in all cases
}
else
diff --git a/boost/geometry/index/detail/rtree/query_iterators.hpp b/boost/geometry/index/detail/rtree/query_iterators.hpp
index 8366fca191..74000d03ef 100644
--- a/boost/geometry/index/detail/rtree/query_iterators.hpp
+++ b/boost/geometry/index/detail/rtree/query_iterators.hpp
@@ -2,7 +2,7 @@
//
// R-tree query iterators
//
-// Copyright (c) 2011-2013 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
@@ -11,9 +11,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
-#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_VIRTUAL
-//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_FUNCTION
-//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
+#include <boost/scoped_ptr.hpp>
+
//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
@@ -29,27 +28,27 @@ struct end_query_iterator
reference operator*() const
{
- BOOST_ASSERT_MSG(false, "iterator not dereferencable");
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
pointer p(0);
return *p;
}
const value_type * operator->() const
{
- BOOST_ASSERT_MSG(false, "iterator not dereferencable");
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");
const value_type * p = 0;
return p;
}
end_query_iterator & operator++()
{
- BOOST_ASSERT_MSG(false, "iterator not incrementable");
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
return *this;
}
end_query_iterator operator++(int)
{
- BOOST_ASSERT_MSG(false, "iterator not incrementable");
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");
return *this;
}
@@ -197,9 +196,6 @@ inline bool operator!=(L const& l, R const& r)
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
-#if defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_VIRTUAL) || defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_FUNCTION)
-
-#if defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_VIRTUAL)
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
@@ -246,73 +242,7 @@ public:
virtual bool equals(base_t const& r) const
{
const query_iterator_wrapper * p = dynamic_cast<const query_iterator_wrapper *>(boost::addressof(r));
- BOOST_ASSERT_MSG(p, "those iterators can't be compared");
- return m_iterator == p->m_iterator;
- }
-
-private:
- Iterator m_iterator;
-};
-
-#elif defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_FUNCTION)
-
-#include <boost/function.hpp>
-#include <boost/bind.hpp>
-
-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 Value value_type;
- typedef typename Allocators::const_reference reference;
- typedef typename Allocators::difference_type difference_type;
- typedef typename Allocators::const_pointer pointer;
-
- virtual ~query_iterator_base() {}
-
- boost::function<query_iterator_base*()> clone;
- boost::function<bool()> is_end;
- boost::function<reference()> dereference;
- boost::function<void()> increment;
- boost::function<bool(query_iterator_base const&)> equals;
-};
-
-template <typename Value, typename Allocators, typename Iterator>
-class query_iterator_wrapper
- : public query_iterator_base<Value, Allocators>
-{
- typedef query_iterator_base<Value, Allocators> base_t;
-
-public:
- typedef std::input_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;
-
- explicit query_iterator_wrapper(Iterator const& it)
- : m_iterator(it)
- {
- base_t::clone = boost::bind(&query_iterator_wrapper::clone_, this);
- base_t::is_end = boost::bind(&query_iterator_wrapper::is_end_, this);
- base_t::dereference = boost::bind(&query_iterator_wrapper::dereference_, this);
- base_t::increment = boost::bind(&query_iterator_wrapper::increment_, this);
- base_t::equals = boost::bind(&query_iterator_wrapper::equals_, this, _1);
- }
-
-private:
- base_t * clone_() const { return new query_iterator_wrapper(m_iterator); }
-
- bool is_end_() const { return m_iterator == end_query_iterator<Value, Allocators>(); }
- reference dereference_() const { return *m_iterator; }
- void increment_() { ++m_iterator; }
- bool equals_(base_t const& r) const
- {
- const query_iterator_wrapper * p = dynamic_cast<const query_iterator_wrapper *>(boost::addressof(r));
- BOOST_ASSERT_MSG(p, "those iterators can't be compared");
+ BOOST_GEOMETRY_INDEX_ASSERT(p, "iterators can't be compared");
return m_iterator == p->m_iterator;
}
@@ -320,13 +250,12 @@ private:
Iterator m_iterator;
};
-#endif
template <typename Value, typename Allocators>
class query_iterator
{
typedef query_iterator_base<Value, Allocators> iterator_base;
- typedef std::auto_ptr<iterator_base> iterator_ptr;
+ typedef boost::scoped_ptr<iterator_base> iterator_ptr;
public:
typedef std::input_iterator_tag iterator_category;
@@ -353,21 +282,24 @@ public:
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
query_iterator & operator=(query_iterator const& o)
{
- m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
+ if ( this != boost::addressof(o) )
+ {
+ m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
+ }
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
query_iterator(query_iterator && o)
- : m_ptr(o.m_ptr.get())
+ : m_ptr(0)
{
- o.m_ptr.release();
+ m_ptr.swap(o.m_ptr);
}
query_iterator & operator=(query_iterator && o)
{
if ( this != boost::addressof(o) )
{
- m_ptr.reset(o.m_ptr.get());
- o.m_ptr.release();
+ m_ptr.swap(o.m_ptr);
+ o.m_ptr.reset();
}
return *this;
}
@@ -378,20 +310,23 @@ private:
public:
query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
{
- m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
+ if ( this != boost::addressof(o) )
+ {
+ m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
+ }
return *this;
}
query_iterator(BOOST_RV_REF(query_iterator) o)
- : m_ptr(o.m_ptr.get())
+ : m_ptr(0)
{
- o.m_ptr.release();
+ m_ptr.swap(o.m_ptr);
}
query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
{
if ( this != boost::addressof(o) )
{
- m_ptr.reset(o.m_ptr.get());
- o.m_ptr.release();
+ m_ptr.swap(o.m_ptr);
+ o.m_ptr.reset();
}
return *this;
}
@@ -444,156 +379,4 @@ private:
}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
-#elif defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE)
-
-#include <boost/type_erasure/any.hpp>
-#include <boost/type_erasure/operators.hpp>
-#include <boost/type_erasure/is_empty.hpp>
-
-namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
-
-template<typename T, typename Value, typename Allocators>
-struct single_pass_iterator_concept :
- ::boost::mpl::vector<
- ::boost::type_erasure::copy_constructible<T>,
- ::boost::type_erasure::equality_comparable<T>,
- ::boost::type_erasure::dereferenceable<typename Allocators::const_reference, T>,
- ::boost::type_erasure::assignable<T>,
- ::boost::type_erasure::incrementable<T>,
- ::boost::type_erasure::equality_comparable<T, end_query_iterator<Value, Allocators> >,
- ::boost::type_erasure::relaxed // default ctor
- >
-{};
-
-template <typename Value, typename Allocators>
-struct single_pass_iterator_type
-{
- typedef ::boost::type_erasure::any<
- single_pass_iterator_concept<
- ::boost::type_erasure::_self, Value, Allocators
- >
- > type;
-};
-
-}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
-
-namespace boost { namespace type_erasure {
-
-template<typename T, typename Value, typename Allocators, typename Base>
-struct concept_interface<
- ::boost::geometry::index::detail::rtree::single_pass_iterator_concept<
- T, Value, Allocators
- >, Base, T>
- : Base
-{
- typedef Value value_type;
- typedef typename Allocators::const_reference reference;
- typedef typename Allocators::const_pointer pointer;
- typedef typename Allocators::difference_type difference_type;
- typedef ::std::input_iterator_tag iterator_category;
-};
-
-}} // boost::type_erasure
-
-namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
-
-template <typename Value, typename Allocators>
-class query_iterator
-{
-public:
- typedef std::input_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;
-
-private:
- typedef typename rtree::single_pass_iterator_type<Value, Allocators>::type iterator_type;
-
-public:
-
- query_iterator() {}
-
- template <typename It>
- query_iterator(It const& it)
- : m_iterator(it)
- {}
-
- query_iterator(end_query_iterator<Value, Allocators> const& /*it*/)
- {}
-
-#ifdef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
-private:
- BOOST_COPYABLE_AND_MOVABLE(query_iterator)
-public:
- query_iterator(query_iterator const& o)
- : m_iterator(o.m_iterator)
- {}
- query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
- {
- m_iterator = o.m_iterator;
- return *this;
- }
- query_iterator(BOOST_RV_REF(query_iterator) o)
- : m_iterator(boost::move(o.m_iterator))
- {}
- query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
- {
- if ( this != boost::addressof(o) )
- {
- m_iterator = boost::move(o.m_iterator);
- }
- return *this;
- }
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
-
- reference operator*() const
- {
- return *m_iterator;
- }
-
- const value_type * operator->() const
- {
- return boost::addressof(*m_iterator);
- }
-
- query_iterator & operator++()
- {
- ++m_iterator;
- return *this;
- }
-
- query_iterator operator++(int)
- {
- query_iterator temp = *this;
- ++m_iterator;
- return temp;
- }
-
- friend bool operator==(query_iterator const& l, query_iterator const& r)
- {
- if ( !::boost::type_erasure::is_empty(l.m_iterator) )
- {
- if ( !::boost::type_erasure::is_empty(r.m_iterator) )
- return l.m_iterator == r.m_iterator;
- else
- return l.m_iterator == end_query_iterator<Value, Allocators>();
- }
- else
- {
- if ( !::boost::type_erasure::is_empty(r.m_iterator) )
- return r.m_iterator == end_query_iterator<Value, Allocators>();
- else
- return true;
- }
- }
-
-private:
- iterator_type m_iterator;
-};
-
-}}}}}} // namespace boost::geometry::index::detail::rtree::iterators
-
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
-
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
diff --git a/boost/geometry/index/detail/rtree/rstar/insert.hpp b/boost/geometry/index/detail/rtree/rstar/insert.hpp
index e544d6dd1e..ce92140872 100644
--- a/boost/geometry/index/detail/rtree/rstar/insert.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/insert.hpp
@@ -472,8 +472,9 @@ public:
, m_relative_level(relative_level), m_allocators(allocators)
{}
- inline void operator()(internal_node & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(n))
+ inline void operator()(internal_node & n)
{
+ boost::ignore_unused(n);
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");
// Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
@@ -498,8 +499,9 @@ public:
}
}
- inline void operator()(leaf & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(n))
+ inline void operator()(leaf & n)
{
+ boost::ignore_unused(n);
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");
// Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
diff --git a/boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp b/boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp
new file mode 100644
index 0000000000..10a1bec6ad
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp
@@ -0,0 +1,110 @@
+// Boost.Geometry Index
+//
+// R-tree nodes elements numbers validating 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_UTILITIES_ARE_COUNTS_OK_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP
+
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
+
+namespace visitors {
+
+template <typename Value, typename Options, typename Box, typename Allocators>
+class are_counts_ok
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ 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 Options::parameters_type parameters_type;
+
+public:
+ inline are_counts_ok(parameters_type const& parameters)
+ : result(true), m_current_level(0), m_parameters(parameters)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // root internal node shouldn't contain 0 elements
+ if ( elements.empty()
+ || !check_count(elements) )
+ {
+ result = false;
+ return;
+ }
+
+ size_t current_level_backup = m_current_level;
+ ++m_current_level;
+
+ for ( typename elements_type::const_iterator it = elements.begin();
+ it != elements.end() && result == true ;
+ ++it)
+ {
+ rtree::apply_visitor(*this, *it->second);
+ }
+
+ m_current_level = current_level_backup;
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // empty leaf in non-root node
+ if ( ( m_current_level > 0 && elements.empty() )
+ || !check_count(elements) )
+ {
+ result = false;
+ }
+ }
+
+ bool result;
+
+private:
+ template <typename Elements>
+ bool check_count(Elements const& elements)
+ {
+ // root may contain count < min but should never contain count > max
+ return elements.size() <= m_parameters.get_max_elements()
+ && ( elements.size() >= m_parameters.get_min_elements()
+ || m_current_level == 0 );
+ }
+
+ size_t m_current_level;
+ parameters_type const& m_parameters;
+};
+
+} // namespace visitors
+
+template <typename Rtree> inline
+bool are_counts_ok(Rtree const& tree)
+{
+ typedef utilities::view<Rtree> RTV;
+ RTV rtv(tree);
+
+ visitors::are_counts_ok<
+ typename RTV::value_type,
+ typename RTV::options_type,
+ typename RTV::box_type,
+ typename RTV::allocators_type
+ > v(tree.parameters());
+
+ rtv.apply_visitor(v);
+
+ return v.result;
+}
+
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/copy.hpp b/boost/geometry/index/detail/rtree/visitors/copy.hpp
index 8fc25ac803..86ffc99caf 100644
--- a/boost/geometry/index/detail/rtree/visitors/copy.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/copy.hpp
@@ -2,7 +2,7 @@
//
// R-tree deep copying visitor implementation
//
-// Copyright (c) 2011-2013 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
@@ -24,7 +24,7 @@ public:
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 rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
typedef typename Allocators::node_pointer node_pointer;
explicit inline copy(Allocators & allocators)
@@ -35,7 +35,7 @@ public:
inline void operator()(internal_node & n)
{
node_pointer raw_new_node = rtree::create_node<Allocators, internal_node>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
- node_auto_ptr new_node(raw_new_node, m_allocators);
+ subtree_destroyer new_node(raw_new_node, m_allocators);
typedef typename rtree::elements_type<internal_node>::type elements_type;
elements_type & elements = rtree::elements(n);
@@ -48,7 +48,7 @@ public:
rtree::apply_visitor(*this, *it->second); // MAY THROW (V, E: alloc, copy, N: alloc)
// for exception safety
- node_auto_ptr auto_result(result, m_allocators);
+ subtree_destroyer auto_result(result, m_allocators);
elements_dst.push_back( rtree::make_ptr_pair(it->first, result) ); // MAY THROW, STRONG (E: alloc, copy)
@@ -62,7 +62,7 @@ public:
inline void operator()(leaf & l)
{
node_pointer raw_new_node = rtree::create_node<Allocators, leaf>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
- node_auto_ptr new_node(raw_new_node, m_allocators);
+ subtree_destroyer new_node(raw_new_node, m_allocators);
typedef typename rtree::elements_type<leaf>::type elements_type;
elements_type & elements = rtree::elements(l);
diff --git a/boost/geometry/index/detail/rtree/visitors/destroy.hpp b/boost/geometry/index/detail/rtree/visitors/destroy.hpp
index 62722b97a8..b4a800eac2 100644
--- a/boost/geometry/index/detail/rtree/visitors/destroy.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/destroy.hpp
@@ -2,7 +2,7 @@
//
// R-tree destroying visitor implementation
//
-// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2014 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
@@ -51,8 +51,9 @@ public:
rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, node_to_destroy);
}
- inline void operator()(leaf & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(l))
+ inline void operator()(leaf & l)
{
+ boost::ignore_unused(l);
BOOST_GEOMETRY_INDEX_ASSERT(&l == &rtree::get<leaf>(*m_current_node), "invalid pointers");
rtree::destroy_node<Allocators, leaf>::apply(m_allocators, m_current_node);
diff --git a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
index 342cc4bbc3..fc0929e9ed 100644
--- a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
@@ -344,7 +344,7 @@ public:
, next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
{
- BOOST_ASSERT_MSG(0 < max_count(), "k must be greather than 0");
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0");
}
const_reference dereference() const
@@ -399,7 +399,7 @@ public:
}
// if node is further than the furthest neighbour, following nodes also will be further
- BOOST_ASSERT_MSG(neighbors.size() <= max_count(), "unexpected neighbours count");
+ BOOST_GEOMETRY_INDEX_ASSERT(neighbors.size() <= max_count(), "unexpected neighbours count");
if ( max_count() <= neighbors.size() &&
is_node_prunable(neighbors.back().first, branches[current_branch].first) )
{
@@ -426,10 +426,10 @@ public:
friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
{
- BOOST_ASSERT_MSG(l.current_neighbor != r.current_neighbor ||
- (std::numeric_limits<size_type>::max)() == l.current_neighbor ||
- l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,
- "not corresponding iterators");
+ BOOST_GEOMETRY_INDEX_ASSERT(l.current_neighbor != r.current_neighbor ||
+ (std::numeric_limits<size_type>::max)() == l.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/insert.hpp b/boost/geometry/index/detail/rtree/visitors/insert.hpp
index 388b3193f6..e697c065e1 100644
--- a/boost/geometry/index/detail/rtree/visitors/insert.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/insert.hpp
@@ -2,7 +2,7 @@
//
// R-tree inserting visitor implementation
//
-// Copyright (c) 2011-2013 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
@@ -115,7 +115,7 @@ protected:
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
- typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
public:
typedef index::detail::varray<
@@ -133,8 +133,8 @@ public:
{
// TODO - consider creating nodes always with sufficient memory allocated
- // create additional node, use auto ptr for automatic destruction on exception
- node_auto_ptr second_node(rtree::create_node<Allocators, Node>::apply(allocators), allocators); // MAY THROW, STRONG (N: alloc)
+ // create additional node, use auto destroyer for automatic destruction on exception
+ subtree_destroyer second_node(rtree::create_node<Allocators, Node>::apply(allocators), allocators); // MAY THROW, STRONG (N: alloc)
// create reference to the newly created node
Node & n2 = rtree::get<Node>(*second_node);
@@ -232,7 +232,7 @@ protected:
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
- typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
typedef typename Allocators::node_pointer node_pointer;
typedef typename Allocators::size_type size_type;
@@ -340,7 +340,7 @@ protected:
// Implement template <node_tag> struct node_element_type or something like that
// for exception safety
- node_auto_ptr additional_node_ptr(additional_nodes[0].second, m_allocators);
+ subtree_destroyer additional_node_ptr(additional_nodes[0].second, m_allocators);
// node is not the root - just add the new node
if ( !m_traverse_data.current_is_root() )
@@ -356,7 +356,7 @@ protected:
BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*m_root_node), "node should be the root");
// create new root and add nodes
- node_auto_ptr new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)
+ subtree_destroyer new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)
BOOST_TRY
{
@@ -365,7 +365,7 @@ protected:
}
BOOST_CATCH(...)
{
- // clear new root to not delete in the ~node_auto_ptr() potentially stored old root node
+ // clear new root to not delete in the ~subtree_destroyer() potentially stored old root node
rtree::elements(rtree::get<internal_node>(*new_root)).clear();
BOOST_RETHROW // RETHROW
}
diff --git a/boost/geometry/index/detail/rtree/visitors/is_leaf.hpp b/boost/geometry/index/detail/rtree/visitors/is_leaf.hpp
index 6d21afd99e..dd2159c71e 100644
--- a/boost/geometry/index/detail/rtree/visitors/is_leaf.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/is_leaf.hpp
@@ -2,7 +2,7 @@
//
// R-tree leaf node checking visitor implementation
//
-// Copyright (c) 2011-2013 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
@@ -21,9 +21,13 @@ struct is_leaf : public rtree::visitor<Value, typename Options::parameters_type,
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;
+ is_leaf()
+ : result(false)
+ {}
+
inline void operator()(internal_node const&)
{
- result = false;
+ // result = false;
}
inline void operator()(leaf const&)
diff --git a/boost/geometry/index/detail/rtree/visitors/remove.hpp b/boost/geometry/index/detail/rtree/visitors/remove.hpp
index d4890a368b..494d5a019e 100644
--- a/boost/geometry/index/detail/rtree/visitors/remove.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/remove.hpp
@@ -2,7 +2,7 @@
//
// R-tree removing visitor 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
@@ -30,7 +30,7 @@ class remove
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
- typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
typedef typename Allocators::node_pointer node_pointer;
typedef typename Allocators::size_type size_type;
@@ -152,7 +152,7 @@ public:
// if value was removed
if ( m_is_value_removed )
{
- BOOST_ASSERT_MSG(0 < m_parameters.get_min_elements(), "min number of elements is too small");
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_parameters.get_min_elements(), "min number of elements is too small");
// calc underflow
m_is_underflow = elements.size() < m_parameters.get_min_elements();
@@ -222,6 +222,13 @@ private:
return elements.size() < m_parameters.get_min_elements();
}
+ static inline bool is_leaf(node const& n)
+ {
+ visitors::is_leaf<Value, Options, Box, Allocators> ilv;
+ rtree::apply_visitor(ilv, n);
+ return ilv.result;
+ }
+
void reinsert_removed_nodes_elements()
{
typename UnderflowNodes::reverse_iterator it = m_underflowed_nodes.rbegin();
@@ -232,9 +239,11 @@ private:
// begin with levels closer to the root
for ( ; it != m_underflowed_nodes.rend() ; ++it )
{
- is_leaf<Value, Options, Box, Allocators> ilv;
- rtree::apply_visitor(ilv, *it->second);
- if ( ilv.result )
+ // it->first is an index of a level of a node, not children
+ // counted from the leafs level
+ bool const node_is_leaf = it->first == 1;
+ BOOST_GEOMETRY_INDEX_ASSERT(node_is_leaf == is_leaf(*it->second), "unexpected condition");
+ if ( node_is_leaf )
{
reinsert_node_elements(rtree::get<leaf>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
@@ -255,7 +264,7 @@ private:
// destroy current and remaining nodes
for ( ; it != m_underflowed_nodes.rend() ; ++it )
{
- node_auto_ptr dummy(it->second, m_allocators);
+ subtree_destroyer dummy(it->second, m_allocators);
}
//m_underflowed_nodes.clear();
diff --git a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
index 0a43111ac4..f00189fe77 100644
--- a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
@@ -2,7 +2,7 @@
//
// R-tree spatial query visitor implementation
//
-// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2014 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
@@ -116,7 +116,7 @@ public:
const_reference dereference() const
{
- BOOST_ASSERT_MSG(m_values, "not dereferencable");
+ BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");
return *m_current;
}
diff --git a/boost/geometry/index/detail/serialization.hpp b/boost/geometry/index/detail/serialization.hpp
index 34036e3904..550a37565b 100644
--- a/boost/geometry/index/detail/serialization.hpp
+++ b/boost/geometry/index/detail/serialization.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
@@ -353,7 +353,7 @@ class load
typedef typename Options::parameters_type parameters_type;
typedef typename Allocators::node_pointer node_pointer;
- typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
typedef typename Allocators::size_type size_type;
public:
@@ -385,7 +385,7 @@ private:
if ( current_level < leafs_level )
{
node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)
- node_auto_ptr auto_remover(n, allocators);
+ subtree_destroyer auto_remover(n, allocators);
internal_node & in = rtree::get<internal_node>(*n);
elements_type & elements = rtree::elements(in);
@@ -408,7 +408,7 @@ private:
BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value");
node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)
- node_auto_ptr auto_remover(n, allocators);
+ subtree_destroyer auto_remover(n, allocators);
leaf & l = rtree::get<leaf>(*n);
typedef typename rtree::elements_type<leaf>::type elements_type;
@@ -537,7 +537,7 @@ void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsig
typedef typename options_type::parameters_type parameters_type;
typedef typename allocators_type::node_pointer node_pointer;
- typedef detail::rtree::node_auto_ptr<value_type, options_type, translator_type, box_type, allocators_type> node_auto_ptr;
+ typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;
view tree(rt);
@@ -554,7 +554,7 @@ void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsig
n = detail::rtree::load<value_type, options_type, translator_type, box_type, allocators_type>
::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators()); // MAY THROW
- node_auto_ptr remover(n, tree.members().allocators());
+ subtree_destroyer remover(n, tree.members().allocators());
if ( loaded_values_count != values_count )
BOOST_THROW_EXCEPTION(std::runtime_error("unexpected number of values")); // TODO change exception type
remover.release();
@@ -564,7 +564,7 @@ void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsig
tree.members().values_count = values_count;
tree.members().leafs_level = leafs_level;
- node_auto_ptr remover(tree.members().root, tree.members().allocators());
+ subtree_destroyer remover(tree.members().root, tree.members().allocators());
tree.members().root = n;
}
diff --git a/boost/geometry/index/detail/varray.hpp b/boost/geometry/index/detail/varray.hpp
index 63577e64a7..1b084aafdb 100644
--- a/boost/geometry/index/detail/varray.hpp
+++ b/boost/geometry/index/detail/varray.hpp
@@ -1,6 +1,6 @@
// Boost.Container varray
//
-// Copyright (c) 2012-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2013 Andrew Hundt.
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -13,7 +13,10 @@
// TODO - REMOVE/CHANGE
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
-#include <boost/container/detail/preprocessor.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
#include <boost/config.hpp>
#include <boost/swap.hpp>
@@ -32,12 +35,11 @@
#include <boost/iterator/iterator_concepts.hpp>
#include <boost/geometry/index/detail/assert.hpp>
+#include <boost/geometry/index/detail/exception.hpp>
-#include <boost/geometry/index/detail/assert.hpp>
#include <boost/geometry/index/detail/varray_detail.hpp>
#include <boost/concept_check.hpp>
-#include <boost/throw_exception.hpp>
/*!
\defgroup varray_non_member varray non-member functions
@@ -79,12 +81,8 @@ struct checker
static inline void throw_out_of_bounds(Varray const& v, size_type i)
{
-//#ifndef BOOST_NO_EXCEPTIONS
if ( v.size() <= i )
- BOOST_THROW_EXCEPTION(std::out_of_range("index out of bounds"));
-//#else // BOOST_NO_EXCEPTIONS
-// BOOST_GEOMETRY_INDEX_ASSERT(i < v.size(), "index out of bounds");
-//#endif // BOOST_NO_EXCEPTIONS
+ throw_out_of_range("index out of bounds");
::boost::ignore_unused_variable_warning(v);
::boost::ignore_unused_variable_warning(i);
@@ -920,9 +918,9 @@ public:
difference_type n = std::distance(first, last);
//TODO - add invalid range check?
- //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 <= n, "invalid range");
//TODO - add this->size() check?
- //BOOST_ASSERT_MSG(n <= this->size(), "invalid range");
+ //BOOST_GEOMETRY_INDEX_ASSERT(n <= this->size(), "invalid range");
sv::move(last, this->end(), first); // may throw
sv::destroy(this->end() - n, this->end());
@@ -984,7 +982,7 @@ public:
}
#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
-#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! @pre <tt>size() < capacity()</tt>
//!
//! @brief Inserts a Value constructed with
@@ -1065,27 +1063,23 @@ public:
return position;
}
-#else // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED
+#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ #define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ void emplace_back(BOOST_MOVE_UREF##N) \
{ \
typedef typename vt::disable_trivial_init dti; \
\
errh::check_capacity(*this, m_size + 1); /*may throw*/\
\
- namespace sv = varray_detail; \
- sv::construct(dti(), this->end() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ namespace sv = varray_detail; \
+ sv::construct(dti(), this->end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
++m_size; /*update end*/ \
} \
- //
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
-
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(iterator position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace(iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
{ \
typedef typename vt::disable_trivial_init dti; \
namespace sv = varray_detail; \
@@ -1095,7 +1089,7 @@ public:
\
if ( position == this->end() ) \
{ \
- sv::construct(dti(), position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ sv::construct(dti(), position BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
++m_size; /*update end*/ \
} \
else \
@@ -1104,24 +1098,24 @@ public:
/* TODO - should move be used only if it's nonthrowing? */ \
\
value_type & r = *(this->end() - 1); \
- sv::construct(dti(), this->end(), boost::move(r)); /*may throw*/\
+ sv::construct(dti(), this->end(), boost::move(r)); /*may throw*/\
++m_size; /*update end*/ \
sv::move_backward(position, this->end() - 2, this->end() - 1); /*may throw*/\
\
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> temp_storage; \
value_type * val_p = static_cast<value_type *>(temp_storage.address()); \
- sv::construct(dti(), val_p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ sv::construct(dti(), val_p BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
sv::scoped_destructor<value_type> d(val_p); \
sv::assign(position, ::boost::move(*val_p)); /*may throw*/\
} \
\
return position; \
} \
- //
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
+
+ BOOST_MOVE_ITERATE_0TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE)
+ #undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE
-#endif // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED
+#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
//! @brief Removes all elements from the container.
@@ -1614,7 +1608,8 @@ private:
// Linear O(N).
void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::true_type const& /*use_memop*/)
{
- //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la));
+ //BOOST_GEOMETRY_INDEX_ASSERT(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la),
+ // "incompatible ranges");
namespace sv = varray_detail;
for (; first_sm != last_sm ; ++first_sm, ++first_la)
@@ -1639,7 +1634,8 @@ private:
// Linear O(N).
void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::false_type const& /*use_memop*/)
{
- //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la));
+ //BOOST_GEOMETRY_INDEX_ASSERT(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la),
+ // "incompatible ranges");
namespace sv = varray_detail;
for (; first_sm != last_sm ; ++first_sm, ++first_la)
@@ -1961,7 +1957,7 @@ public:
errh::check_iterator_end_eq(*this, first);
errh::check_iterator_end_eq(*this, last);
- //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 <= n, "invalid range");
}
// basic
diff --git a/boost/geometry/index/detail/varray_detail.hpp b/boost/geometry/index/detail/varray_detail.hpp
index 962d4d8288..31b77c40fe 100644
--- a/boost/geometry/index/detail/varray_detail.hpp
+++ b/boost/geometry/index/detail/varray_detail.hpp
@@ -2,7 +2,7 @@
//
// varray details
//
-// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2013 Andrew Hundt.
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -39,9 +39,13 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/core/addressof.hpp>
#include <boost/iterator/iterator_traits.hpp>
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+
// TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
#if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
@@ -618,22 +622,22 @@ void construct(DisableTrivialInit const&,
// !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0
// which means that version with one parameter may take V const& v
-#define BOOST_PP_LOCAL_MACRO(n) \
-template <typename DisableTrivialInit, typename I, typename P BOOST_PP_ENUM_TRAILING_PARAMS(n, typename P) > \
+#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT(N) \
+template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
inline \
void construct(DisableTrivialInit const&, \
I pos, \
- BOOST_CONTAINER_PP_PARAM(P, p) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ BOOST_FWD_REF(P) p \
+ BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
{ \
typedef typename boost::iterator_value<I>::type V; \
new \
(static_cast<void*>(boost::addressof(*pos))) \
- V(p, BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); /*may throw*/ \
+ V(boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/ \
} \
-//
-#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
-#include BOOST_PP_LOCAL_ITERATE()
+
+BOOST_MOVE_ITERATE_1TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT)
+#undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT
#endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
diff --git a/boost/geometry/index/equal_to.hpp b/boost/geometry/index/equal_to.hpp
index 5fbaa8209f..b0cf098f1d 100644
--- a/boost/geometry/index/equal_to.hpp
+++ b/boost/geometry/index/equal_to.hpp
@@ -24,6 +24,15 @@ struct equals
}
};
+template <typename Geometry, typename Tag>
+struct equals<Geometry *, Tag>
+{
+ inline static bool apply(const Geometry * g1, const Geometry * g2)
+ {
+ return g1 == g2;
+ }
+};
+
template <typename T>
struct equals<T, void>
{
diff --git a/boost/geometry/index/parameters.hpp b/boost/geometry/index/parameters.hpp
index fd6df716ee..2b94907686 100644
--- a/boost/geometry/index/parameters.hpp
+++ b/boost/geometry/index/parameters.hpp
@@ -70,8 +70,7 @@ inline size_t default_rstar_reinserted_elements_d_calc(size_t max_elements, size
\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.
*/
template <size_t MaxElements,
- size_t MinElements = detail::default_min_elements_s<MaxElements>::value
->
+ size_t MinElements = detail::default_min_elements_s<MaxElements>::value>
struct linear
{
BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),
diff --git a/boost/geometry/index/predicates.hpp b/boost/geometry/index/predicates.hpp
index 10033abff8..3bb1bf4d87 100644
--- a/boost/geometry/index/predicates.hpp
+++ b/boost/geometry/index/predicates.hpp
@@ -2,7 +2,7 @@
//
// Spatial query predicates
//
-// 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
@@ -43,10 +43,15 @@ bgi::query(spatial_index, bgi::contains(box), std::back_inserter(result));
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::contains_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::contains_tag, false>
contains(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::contains_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::contains_tag,
+ false
+ >(g);
}
/*!
@@ -68,10 +73,15 @@ bgi::query(spatial_index, bgi::covered_by(box), std::back_inserter(result));
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::covered_by_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::covered_by_tag, false>
covered_by(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::covered_by_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::covered_by_tag,
+ false
+ >(g);
}
/*!
@@ -93,10 +103,15 @@ bgi::query(spatial_index, bgi::covers(box), std::back_inserter(result));
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::covers_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::covers_tag, false>
covers(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::covers_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::covers_tag,
+ false
+ >(g);
}
/*!
@@ -118,10 +133,15 @@ bgi::query(spatial_index, bgi::disjoint(box), std::back_inserter(result));
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::disjoint_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::disjoint_tag, false>
disjoint(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::disjoint_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::disjoint_tag,
+ false
+ >(g);
}
/*!
@@ -145,10 +165,15 @@ bgi::query(spatial_index, bgi::intersects(polygon), std::back_inserter(result));
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::intersects_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::intersects_tag, false>
intersects(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::intersects_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::intersects_tag,
+ false
+ >(g);
}
/*!
@@ -170,10 +195,15 @@ bgi::query(spatial_index, bgi::overlaps(box), std::back_inserter(result));
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::overlaps_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::overlaps_tag, false>
overlaps(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::overlaps_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::overlaps_tag,
+ false
+ >(g);
}
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
@@ -192,10 +222,15 @@ returns true.
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::touches_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::touches_tag, false>
touches(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::touches_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::touches_tag,
+ false
+ >(g);
}
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
@@ -219,10 +254,15 @@ bgi::query(spatial_index, bgi::within(box), std::back_inserter(result));
\param g The Geometry object.
*/
template <typename Geometry> inline
-detail::spatial_predicate<Geometry, detail::within_tag, false>
+detail::predicates::spatial_predicate<Geometry, detail::predicates::within_tag, false>
within(Geometry const& g)
{
- return detail::spatial_predicate<Geometry, detail::within_tag, false>(g);
+ return detail::predicates::spatial_predicate
+ <
+ Geometry,
+ detail::predicates::within_tag,
+ false
+ >(g);
}
/*!
@@ -259,10 +299,10 @@ std::back_inserter(result));
\param pred The unary predicate function or function object.
*/
template <typename UnaryPredicate> inline
-detail::satisfies<UnaryPredicate, false>
+detail::predicates::satisfies<UnaryPredicate, false>
satisfies(UnaryPredicate const& pred)
{
- return detail::satisfies<UnaryPredicate, false>(pred);
+ return detail::predicates::satisfies<UnaryPredicate, false>(pred);
}
/*!
@@ -289,10 +329,10 @@ Only one \c nearest() predicate may be used in a query.
\param k The maximum number of values to return.
*/
template <typename Geometry> inline
-detail::nearest<Geometry>
+detail::predicates::nearest<Geometry>
nearest(Geometry const& geometry, unsigned k)
{
- return detail::nearest<Geometry>(geometry, k);
+ return detail::predicates::nearest<Geometry>(geometry, k);
}
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
@@ -319,15 +359,15 @@ Only one distance predicate (\c nearest() or \c path()) may be used in a query.
\param k The maximum number of values to return.
*/
template <typename SegmentOrLinestring> inline
-detail::path<SegmentOrLinestring>
+detail::predicates::path<SegmentOrLinestring>
path(SegmentOrLinestring const& linestring, unsigned k)
{
- return detail::path<SegmentOrLinestring>(linestring, k);
+ return detail::predicates::path<SegmentOrLinestring>(linestring, k);
}
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
-namespace detail {
+namespace detail { namespace predicates {
// operator! generators
@@ -378,7 +418,7 @@ operator&&(boost::tuples::cons<Head, Tail> const& t, Pred const& p)
>::apply(t, p);
}
-} // namespace detail
+}} // namespace detail::predicates
}}} // namespace boost::geometry::index
diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp
index 503f47b89f..9d5d57d059 100644
--- a/boost/geometry/index/rtree.hpp
+++ b/boost/geometry/index/rtree.hpp
@@ -3,7 +3,7 @@
// R-tree implementation
//
// Copyright (c) 2008 Federico J. Fernandez.
-// 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
@@ -96,12 +96,13 @@ namespace boost { namespace geometry { namespace index {
/*!
\brief The R-tree spatial index.
-This is self-balancing spatial index capable to store various types of Values and balancing algorithms.
+This is self-balancing spatial index capable to store various types of Values
+and balancing algorithms.
\par Parameters
The user must pass a type defining the Parameters which will
-be used in rtree creation process. This type is used e.g. to specify balancing algorithm
-with specific parameters like min and max number of elements in node.
+be used in rtree creation process. This type is used e.g. to specify balancing
+algorithm with specific parameters like min and max number of elements in node.
\par
Predefined algorithms with compile-time parameters are:
@@ -116,23 +117,31 @@ Predefined algorithms with run-time parameters are:
\li \c boost::geometry::index::dynamic_rstar.
\par IndexableGetter
-The object of IndexableGetter type translates from Value to Indexable each time r-tree requires it. Which means that this
-operation is done for each Value access. Therefore the IndexableGetter should return the Indexable by
-const reference instead of a value. Default one can translate all types adapted to Point, Box or Segment
-concepts (called Indexables). It also handles <tt>std::pair<Indexable, T></tt> and
-<tt>boost::tuple<Indexable, ...></tt>. For example, if <tt>std::pair<Box, int></tt> is stored in the
-container, the default IndexableGetter translates from <tt>std::pair<Box, int> const&</tt> to <tt>Box const&</tt>.
+The object of IndexableGetter type translates from Value to Indexable each time
+r-tree requires it. This means that this operation is done for each Value
+access. Therefore the IndexableGetter should return the Indexable by
+a reference type. The Indexable should not be calculated since it could harm
+the performance. The default IndexableGetter can translate all types adapted
+to Point, Box or Segment concepts (called Indexables). Furthermore, it can
+handle <tt>std::pair<Indexable, T></tt>, <tt>boost::tuple<Indexable, ...></tt>
+and <tt>std::tuple<Indexable, ...></tt> when possible. For example, for Value
+of type <tt>std::pair<Box, int></tt>, the default IndexableGetter translates
+from <tt>std::pair<Box, int> const&</tt> to <tt>Box const&</tt>.
\par EqualTo
-The object of EqualTo type compares Values and returns <tt>true</tt> if they're equal. It's similar to <tt>std::equal_to<></tt>.
-The default EqualTo returns the result of <tt>boost::geometry::equals()</tt> for types adapted to some Geometry concept
-defined in Boost.Geometry and the result of operator= for other types. Components of Pairs and Tuples are compared left-to-right.
+The object of EqualTo type compares Values and returns <tt>true</tt> if they
+are equal. It's similar to <tt>std::equal_to<></tt>. The default EqualTo
+returns the result of <tt>boost::geometry::equals()</tt> for types adapted to
+some Geometry concept defined in Boost.Geometry and the result of
+<tt>operator==</tt> for other types. Components of Pairs and Tuples are
+compared left-to-right.
\tparam Value The type of objects stored in the container.
\tparam Parameters Compile-time parameters.
\tparam IndexableGetter The function object extracting Indexable from Value.
\tparam EqualTo The function object comparing objects of type Value.
-\tparam Allocator The allocator used to allocate/deallocate memory, construct/destroy nodes and Values.
+\tparam Allocator The allocator used to allocate/deallocate memory,
+ construct/destroy nodes and Values.
*/
template <
typename Value,
@@ -188,7 +197,7 @@ private:
typedef typename allocators_type::node_pointer node_pointer;
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
- typedef detail::rtree::node_auto_ptr<value_type, options_type, translator_type, box_type, allocators_type> node_auto_ptr;
+ typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;
friend class detail::rtree::utilities::view<rtree>;
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
@@ -1088,6 +1097,8 @@ public:
template <typename ValueOrIndexable>
size_type count(ValueOrIndexable const& vori) const
{
+ // the input should be convertible to Value or Indexable type
+
enum { as_val = 0, as_ind, dont_know };
typedef boost::mpl::int_
<
@@ -1113,15 +1124,9 @@ public:
indexable_type
>::type value_or_indexable;
- if ( !m_members.root )
- return 0;
-
- detail::rtree::visitors::count<value_or_indexable, value_type, options_type, translator_type, box_type, allocators_type>
- count_v(vori, m_members.translator());
-
- detail::rtree::apply_visitor(count_v, *m_members.root);
-
- return count_v.found_count;
+ // NOTE: If an object of convertible but not the same type is passed
+ // into the function, here a temporary will be created.
+ return this->template raw_count<value_or_indexable>(vori);
}
/*!
@@ -1239,6 +1244,7 @@ private:
inline void raw_insert(value_type const& value)
{
BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");
+ // CONSIDER: alternative - ignore invalid indexable or throw an exception
BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(m_members.translator()(value)), "Indexable is invalid");
detail::rtree::visitors::insert<
@@ -1356,7 +1362,7 @@ private:
dst.m_members.parameters() = src.m_members.parameters();
}
- // TODO use node_auto_ptr
+ // TODO use subtree_destroyer
if ( dst.m_members.root )
{
detail::rtree::visitors::destroy<value_type, options_type, translator_type, box_type, allocators_type>
@@ -1492,6 +1498,33 @@ private:
return distance_v.finish();
}
+
+ /*!
+ \brief Count elements corresponding to value or indexable.
+
+ \par Exception-safety
+ strong
+ */
+ template <typename ValueOrIndexable>
+ size_type raw_count(ValueOrIndexable const& vori) const
+ {
+ if ( !m_members.root )
+ return 0;
+
+ detail::rtree::visitors::count
+ <
+ ValueOrIndexable,
+ value_type,
+ options_type,
+ translator_type,
+ box_type,
+ allocators_type
+ > count_v(vori, m_members.translator());
+
+ detail::rtree::apply_visitor(count_v, *m_members.root);
+
+ return count_v.found_count;
+ }
struct members_holder
: public translator_type
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp
index 748eecdbe6..2415f21a69 100644
--- a/boost/geometry/io/wkt/read.hpp
+++ b/boost/geometry/io/wkt/read.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -29,6 +34,7 @@
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/append.hpp>
#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -38,6 +44,7 @@
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -98,7 +105,9 @@ namespace detail { namespace wkt
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-template <typename Point, std::size_t Dimension, std::size_t DimensionCount>
+template <typename Point,
+ std::size_t Dimension = 0,
+ std::size_t DimensionCount = geometry::dimension<Point>::value>
struct parsing_assigner
{
static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
@@ -208,12 +217,7 @@ struct container_inserter
while (it != end && *it != ")")
{
- parsing_assigner
- <
- Point,
- 0,
- dimension<Point>::value
- >::apply(it, end, point, wkt);
+ parsing_assigner<Point>::apply(it, end, point, wkt);
out = point;
++out;
if (it != end && *it == ",")
@@ -227,35 +231,94 @@ struct container_inserter
};
+template <typename Geometry,
+ closure_selector Closure = closure<Geometry>::value>
+struct stateful_range_appender
+{
+ typedef typename geometry::point_type<Geometry>::type point_type;
+
+ // NOTE: Geometry is a reference
+ inline void append(Geometry geom, point_type const& point, bool)
+ {
+ geometry::append(geom, point);
+ }
+};
+
+template <typename Geometry>
+struct stateful_range_appender<Geometry, open>
+{
+ typedef typename geometry::point_type<Geometry>::type point_type;
+ typedef typename boost::range_size
+ <
+ typename util::bare_type<Geometry>::type
+ >::type size_type;
+
+ BOOST_STATIC_ASSERT(( boost::is_same
+ <
+ typename tag<Geometry>::type,
+ ring_tag
+ >::value ));
+
+ inline stateful_range_appender()
+ : pt_index(0)
+ {}
+
+ // NOTE: Geometry is a reference
+ inline void append(Geometry geom, point_type const& point, bool is_next_expected)
+ {
+ bool should_append = true;
+
+ if (pt_index == 0)
+ {
+ first_point = point;
+ //should_append = true;
+ }
+ else
+ {
+ // NOTE: if there is not enough Points, they're always appended
+ should_append
+ = is_next_expected
+ || pt_index < core_detail::closure::minimum_ring_size<open>::value
+ || !detail::equals::equals_point_point(point, first_point);
+ }
+ ++pt_index;
+
+ if (should_append)
+ {
+ geometry::append(geom, point);
+ }
+ }
+
+private:
+ size_type pt_index;
+ point_type first_point;
+};
+
// Geometry is a value-type or reference-type
template <typename Geometry>
struct container_appender
{
- typedef typename geometry::point_type
- <
- typename boost::remove_reference<Geometry>::type
- >::type point_type;
+ 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)
+ std::string const& wkt, Geometry out)
{
handle_open_parenthesis(it, end, wkt);
- point_type point;
+ stateful_range_appender<Geometry> appender;
// Parse points until closing parenthesis
-
while (it != end && *it != ")")
{
- parsing_assigner
- <
- point_type,
- 0,
- dimension<point_type>::value
- >::apply(it, end, point, wkt);
-
- geometry::append(out, point);
- if (it != end && *it == ",")
+ point_type point;
+
+ parsing_assigner<point_type>::apply(it, end, point, wkt);
+
+ bool const is_next_expected = it != end && *it == ",";
+
+ appender.append(out, point, is_next_expected);
+
+ if (is_next_expected)
{
++it;
}
@@ -276,7 +339,7 @@ struct point_parser
std::string const& wkt, P& point)
{
handle_open_parenthesis(it, end, wkt);
- parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt);
+ parsing_assigner<P>::apply(it, end, point, wkt);
handle_close_parenthesis(it, end, wkt);
}
};
@@ -512,7 +575,7 @@ struct noparenthesis_point_parser
static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
std::string const& wkt, P& point)
{
- parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt);
+ parsing_assigner<P>::apply(it, end, point, wkt);
}
};
@@ -617,7 +680,7 @@ struct box_parser
}
check_end(it, end, wkt);
- int index = 0;
+ unsigned int index = 0;
std::size_t n = boost::size(points);
if (n == 2)
{
diff --git a/boost/geometry/io/wkt/write.hpp b/boost/geometry/io/wkt/write.hpp
index 6c1a2e153e..add40e2551 100644
--- a/boost/geometry/io/wkt/write.hpp
+++ b/boost/geometry/io/wkt/write.hpp
@@ -20,6 +20,7 @@
#include <boost/array.hpp>
#include <boost/range.hpp>
+
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
diff --git a/boost/geometry/iterators/closing_iterator.hpp b/boost/geometry/iterators/closing_iterator.hpp
index a9f67d4788..e263f3aafb 100644
--- a/boost/geometry/iterators/closing_iterator.hpp
+++ b/boost/geometry/iterators/closing_iterator.hpp
@@ -42,12 +42,14 @@ struct closing_iterator
boost::random_access_traversal_tag
>
{
+ typedef typename boost::range_difference<Range>::type difference_type;
+
/// Constructor including the range it is based on
explicit inline closing_iterator(Range& range)
: m_range(&range)
, m_iterator(boost::begin(range))
, m_end(boost::end(range))
- , m_size(boost::size(range))
+ , m_size(static_cast<difference_type>(boost::size(range)))
, m_index(0)
{}
@@ -56,8 +58,8 @@ struct closing_iterator
: m_range(&range)
, m_iterator(boost::end(range))
, m_end(boost::end(range))
- , m_size(boost::size(range))
- , m_index(m_size + 1)
+ , m_size(static_cast<difference_type>(boost::size(range)))
+ , m_index((m_size == 0) ? 0 : m_size + 1)
{}
/// Default constructor
@@ -67,18 +69,6 @@ struct closing_iterator
, m_index(0)
{}
- inline closing_iterator<Range>& operator=(closing_iterator<Range> const& source)
- {
- m_range = source.m_range;
- m_iterator = source.m_iterator;
- m_end = source.m_end;
- m_size = source.m_size;
- m_index = source.m_index;
- return *this;
- }
-
- typedef std::ptrdiff_t difference_type;
-
private:
friend class boost::iterator_core_access;
diff --git a/boost/geometry/iterators/concatenate_iterator.hpp b/boost/geometry/iterators/concatenate_iterator.hpp
index 20112b4c4c..5c4ae0af1e 100644
--- a/boost/geometry/iterators/concatenate_iterator.hpp
+++ b/boost/geometry/iterators/concatenate_iterator.hpp
@@ -89,36 +89,6 @@ public:
(types<OtherIt1, OtherIt2>));
}
- template
- <
- typename OtherIt1,
- typename OtherIt2,
- typename OtherValue,
- typename OtherReference
- >
- concatenate_iterator operator=(concatenate_iterator
- <
- OtherIt1,
- OtherIt2,
- OtherValue,
- OtherReference
- > const& other)
- {
- static const bool are_conv
- = boost::is_convertible<OtherIt1, Iterator1>::value
- && boost::is_convertible<OtherIt2, Iterator2>::value;
-
- BOOST_MPL_ASSERT_MSG((are_conv),
- NOT_CONVERTIBLE,
- (types<OtherIt1, OtherIt2>));
-
- m_it1 = other.m_it1;
- m_end1 = other.m_end1;
- m_begin2 = other.m_begin2;
- m_it2 = other.m_it2;
- return *this;
- }
-
private:
friend class boost::iterator_core_access;
diff --git a/boost/geometry/iterators/detail/segment_iterator/range_segment_iterator.hpp b/boost/geometry/iterators/detail/segment_iterator/range_segment_iterator.hpp
index d79fda84d9..e65b12b459 100644
--- a/boost/geometry/iterators/detail/segment_iterator/range_segment_iterator.hpp
+++ b/boost/geometry/iterators/detail/segment_iterator/range_segment_iterator.hpp
@@ -100,23 +100,36 @@ class range_segment_iterator
Reference
>
{
+ static inline bool has_less_than_two_elements(Range const& r)
+ {
+ return boost::size(r) < ((closure<Range>::value == open) ? 1u : 2u);
+ }
+
public:
typedef typename range_iterator_type<Range>::type iterator_type;
// default constructor
range_segment_iterator()
- : m_it()
+ : m_it(), m_has_less_than_two_elements(false)
{}
// for begin
range_segment_iterator(Range& r)
: m_it(range_iterator_begin<Range>::apply(r))
+ , m_has_less_than_two_elements(has_less_than_two_elements(r))
{}
// for end
range_segment_iterator(Range& r, bool)
- : m_it(--range_iterator_end<Range>::apply(r))
- {}
+ : m_it(range_iterator_end<Range>::apply(r))
+ , m_has_less_than_two_elements(has_less_than_two_elements(r))
+ {
+ if (! m_has_less_than_two_elements)
+ {
+ // the range consists of at least two items
+ --m_it;
+ }
+ }
template
<
@@ -143,33 +156,6 @@ public:
BOOST_MPL_ASSERT_MSG((are_conv), NOT_CONVERTIBLE, (types<OtherRange>));
}
- template
- <
- typename OtherRange,
- typename OtherValue,
- typename OtherReference
- >
- range_segment_iterator operator=(range_segment_iterator
- <
- OtherRange,
- OtherValue,
- OtherReference
- > const& other)
- {
- typedef typename range_segment_iterator
- <
- OtherRange, OtherValue, OtherReference
- >::iterator_type other_iterator_type;
-
- static const bool are_conv
- = boost::is_convertible<other_iterator_type, iterator_type>::value;
-
- BOOST_MPL_ASSERT_MSG((are_conv), NOT_CONVERTIBLE, (types<OtherRange>));
-
- m_it = other.m_it;
- return *this;
- }
-
private:
friend class boost::iterator_core_access;
@@ -178,6 +164,11 @@ private:
inline Reference dereference() const
{
+ if (m_has_less_than_two_elements)
+ {
+ return Reference(*m_it, *m_it);
+ }
+
iterator_type next(m_it);
++next;
return Reference(*m_it, *next);
@@ -211,6 +202,7 @@ private:
private:
iterator_type m_it;
+ bool m_has_less_than_two_elements;
};
diff --git a/boost/geometry/iterators/ever_circling_iterator.hpp b/boost/geometry/iterators/ever_circling_iterator.hpp
index 50b20480cd..cfb588b79f 100644
--- a/boost/geometry/iterators/ever_circling_iterator.hpp
+++ b/boost/geometry/iterators/ever_circling_iterator.hpp
@@ -119,15 +119,6 @@ struct ever_circling_range_iterator
, m_index(0)
{}
- inline ever_circling_range_iterator<Range>& operator=(ever_circling_range_iterator<Range> const& source)
- {
- m_range = source.m_range;
- m_iterator = source.m_iterator;
- m_size = source.m_size;
- m_index = source.m_index;
- return *this;
- }
-
typedef std::ptrdiff_t difference_type;
private:
diff --git a/boost/geometry/iterators/flatten_iterator.hpp b/boost/geometry/iterators/flatten_iterator.hpp
index 078079dc2c..07450afbea 100644
--- a/boost/geometry/iterators/flatten_iterator.hpp
+++ b/boost/geometry/iterators/flatten_iterator.hpp
@@ -107,42 +107,15 @@ public:
(types<OtherOuterIterator, OtherInnerIterator>));
}
- template
- <
- typename OtherOuterIterator,
- typename OtherInnerIterator,
- typename OtherValue,
- typename OtherAccessInnerBegin,
- typename OtherAccessInnerEnd,
- typename OtherReference
- >
- flatten_iterator operator=(flatten_iterator
- <
- OtherOuterIterator,
- OtherInnerIterator,
- OtherValue,
- OtherAccessInnerBegin,
- OtherAccessInnerEnd,
- OtherReference
- > const& other)
+ flatten_iterator& operator=(flatten_iterator const& other)
{
- static const bool are_conv
- = boost::is_convertible
- <
- OtherOuterIterator, OuterIterator
- >::value
- && boost::is_convertible
- <
- OtherInnerIterator, InnerIterator
- >::value;
-
- BOOST_MPL_ASSERT_MSG((are_conv),
- NOT_CONVERTIBLE,
- (types<OtherOuterIterator, OtherInnerIterator>));
-
m_outer_it = other.m_outer_it;
m_outer_end = other.m_outer_end;
- m_inner_it = other.m_inner_it;
+ // avoid assigning an iterator having singular value
+ if ( other.m_outer_it != other.m_outer_end )
+ {
+ m_inner_it = other.m_inner_it;
+ }
return *this;
}
@@ -162,8 +135,8 @@ private:
static inline bool empty(OuterIterator outer_it)
{
- return
- AccessInnerBegin::apply(*outer_it) == AccessInnerEnd::apply(*outer_it);
+ return AccessInnerBegin::apply(*outer_it)
+ == AccessInnerEnd::apply(*outer_it);
}
inline void advance_through_empty()
diff --git a/boost/geometry/iterators/point_iterator.hpp b/boost/geometry/iterators/point_iterator.hpp
index 075339aa58..5971cfcef0 100644
--- a/boost/geometry/iterators/point_iterator.hpp
+++ b/boost/geometry/iterators/point_iterator.hpp
@@ -11,6 +11,7 @@
#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>
#include <boost/range.hpp>
@@ -245,33 +246,26 @@ struct points_end<MultiPolygon, multi_polygon_tag>
// MK:: need to add doc here
template <typename Geometry>
class point_iterator
- : public detail::point_iterator::iterator_type<Geometry>::type
+ : public boost::iterator_adaptor
+ <
+ point_iterator<Geometry>,
+ typename detail::point_iterator::iterator_type<Geometry>::type
+ >
{
private:
- typedef typename detail::point_iterator::iterator_type<Geometry>::type base;
-
- inline base* base_ptr()
- {
- return this;
- }
-
- inline base const* base_ptr() const
- {
- return this;
- }
-
template <typename OtherGeometry> friend class point_iterator;
template <typename G> friend inline point_iterator<G> points_begin(G&);
template <typename G> friend inline point_iterator<G> points_end(G&);
- inline point_iterator(base const& base_it) : base(base_it) {}
+ inline point_iterator(typename point_iterator::base_type const& base_it)
+ : point_iterator::iterator_adaptor_(base_it) {}
public:
inline point_iterator() {}
template <typename OtherGeometry>
inline point_iterator(point_iterator<OtherGeometry> const& other)
- : base(*other.base_ptr())
+ : point_iterator::iterator_adaptor_(other.base())
{
static const bool is_conv
= boost::is_convertible<
diff --git a/boost/geometry/iterators/point_reverse_iterator.hpp b/boost/geometry/iterators/point_reverse_iterator.hpp
index 1c2ac0169d..b464c5f22a 100644
--- a/boost/geometry/iterators/point_reverse_iterator.hpp
+++ b/boost/geometry/iterators/point_reverse_iterator.hpp
@@ -27,17 +27,7 @@ class point_reverse_iterator
: public std::reverse_iterator<point_iterator<Geometry> >
{
private:
- typedef std::reverse_iterator<point_iterator<Geometry> > base;
-
- inline base* base_ptr()
- {
- return this;
- }
-
- inline base const* base_ptr() const
- {
- return this;
- }
+ typedef std::reverse_iterator<point_iterator<Geometry> > base_type;
template <typename OtherGeometry> friend class point_reverse_iterator;
template <typename G>
@@ -46,7 +36,8 @@ private:
template <typename G>
friend inline point_reverse_iterator<G> points_rend(G&);
- inline point_reverse_iterator(base const& base_it) : base(base_it) {}
+ inline point_reverse_iterator(base_type const& base_it)
+ : base_type(base_it) {}
public:
inline point_reverse_iterator() {}
@@ -54,7 +45,7 @@ public:
template <typename OtherGeometry>
inline
point_reverse_iterator(point_reverse_iterator<OtherGeometry> const& other)
- : base(*other.base_ptr())
+ : base_type(other.base())
{
static const bool is_conv = boost::is_convertible
<
diff --git a/boost/geometry/iterators/segment_iterator.hpp b/boost/geometry/iterators/segment_iterator.hpp
index 206d7fc503..71aff39c43 100644
--- a/boost/geometry/iterators/segment_iterator.hpp
+++ b/boost/geometry/iterators/segment_iterator.hpp
@@ -272,6 +272,16 @@ private:
inline segment_iterator(base const& base_it) : base(base_it) {}
public:
+ // The following typedef is needed for this iterator to be
+ // bidirectional.
+ // Normally we would not have to define this. However, due to the
+ // fact that the value type of the iterator is not a reference,
+ // the iterator_facade framework (used to define the base class of
+ // this iterator) degrades automatically the iterator's category
+ // to input iterator. With the following typedef we recover the
+ // correct iterator category.
+ typedef std::bidirectional_iterator_tag iterator_category;
+
inline segment_iterator() {}
template <typename OtherGeometry>
@@ -291,6 +301,32 @@ public:
NOT_CONVERTIBLE,
(segment_iterator<OtherGeometry>));
}
+
+ inline segment_iterator& operator++() // prefix
+ {
+ base::operator++();
+ return *this;
+ }
+
+ inline segment_iterator& operator--() // prefix
+ {
+ base::operator--();
+ return *this;
+ }
+
+ inline segment_iterator operator++(int) // postfix
+ {
+ segment_iterator copy(*this);
+ base::operator++();
+ return copy;
+ }
+
+ inline segment_iterator operator--(int) // postfix
+ {
+ segment_iterator copy(*this);
+ base::operator--();
+ return copy;
+ }
};
diff --git a/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp
deleted file mode 100644
index c780c4cd9a..0000000000
--- a/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp
+++ /dev/null
@@ -1,16 +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_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
-#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
-
-
-#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
-
-
-#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
diff --git a/boost/geometry/policies/is_valid/default_policy.hpp b/boost/geometry/policies/is_valid/default_policy.hpp
new file mode 100644
index 0000000000..c1bd347e11
--- /dev/null
+++ b/boost/geometry/policies/is_valid/default_policy.hpp
@@ -0,0 +1,59 @@
+// 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_POLICIES_IS_VALID_DEFAULT_POLICY_HPP
+#define BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP
+
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+template <bool AllowDuplicates = true, bool AllowSpikes = true>
+class is_valid_default_policy
+{
+protected:
+ static inline bool is_valid(validity_failure_type failure)
+ {
+ return failure == no_failure
+ || (AllowDuplicates && failure == failure_duplicate_points);
+ }
+
+ static inline bool is_valid(validity_failure_type failure, bool is_linear)
+ {
+ return is_valid(failure)
+ || (is_linear && AllowSpikes && failure == failure_spikes);
+ }
+
+public:
+ template <validity_failure_type Failure>
+ static inline bool apply()
+ {
+ return is_valid(Failure);
+ }
+
+ template <validity_failure_type Failure, typename Data>
+ static inline bool apply(Data const&)
+ {
+ return is_valid(Failure);
+ }
+
+ template <validity_failure_type Failure, typename Data1, typename Data2>
+ static inline bool apply(Data1 const& data1, Data2 const&)
+ {
+ return is_valid(Failure, data1);
+ }
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP
diff --git a/boost/geometry/policies/is_valid/failing_reason_policy.hpp b/boost/geometry/policies/is_valid/failing_reason_policy.hpp
new file mode 100644
index 0000000000..b99803bead
--- /dev/null
+++ b/boost/geometry/policies/is_valid/failing_reason_policy.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_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
+#define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
+
+#include <sstream>
+
+#include <boost/geometry/io/dsv/write.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>
+
+
+namespace boost { namespace geometry
+{
+
+
+inline char const* validity_failure_type_message(validity_failure_type failure)
+{
+ switch (failure)
+ {
+ case no_failure:
+ return "Geometry is valid";
+ case failure_few_points:
+ return "Geometry has too few points";
+ case failure_wrong_topological_dimension:
+ return "Geometry has wrong topological dimension";
+ case failure_not_closed:
+ return "Geometry is defined as closed but is open";
+ case failure_spikes:
+ return "Geometry has spikes";
+ case failure_self_intersections:
+ return "Geometry has invalid self-intersections";
+ case failure_wrong_orientation:
+ return "Geometry has wrong orientation";
+ case failure_interior_rings_outside:
+ return "Geometry has interior rings defined outside the outer boundary";
+ case failure_nested_interior_rings:
+ return "Geometry has nested interior rings";
+ case failure_disconnected_interior:
+ return "Geometry has disconnected interior";
+ case failure_intersecting_interiors:
+ return "Multi-polygon has intersecting interiors";
+ case failure_duplicate_points:
+ return "Geometry has duplicate (consecutive) points";
+ case failure_wrong_corner_order:
+ return "Box has corners in wrong order";
+ default: // to avoid -Wreturn-type warning
+ return "";
+ }
+}
+
+
+template <bool AllowDuplicates = true, bool AllowSpikes = true>
+class failing_reason_policy
+{
+private:
+ static inline
+ validity_failure_type transform_failure_type(validity_failure_type failure)
+ {
+ if (AllowDuplicates && failure == failure_duplicate_points)
+ {
+ return no_failure;
+ }
+ return failure;
+ }
+
+ static inline
+ validity_failure_type transform_failure_type(validity_failure_type failure,
+ bool is_linear)
+ {
+ if (is_linear && AllowSpikes && failure == failure_spikes)
+ {
+ return no_failure;
+ }
+ return transform_failure_type(failure);
+ }
+
+ inline void set_failure_message(validity_failure_type failure)
+ {
+ m_oss.str("");
+ m_oss.clear();
+ m_oss << validity_failure_type_message(failure);
+ }
+
+ template
+ <
+ validity_failure_type Failure,
+ typename Data1,
+ typename Data2 = Data1,
+ typename Dummy = void
+ >
+ struct process_data
+ {
+ static inline void apply(std::ostringstream&, Data1 const&)
+ {
+ }
+
+ static inline void apply(std::ostringstream&,
+ Data1 const&,
+ Data2 const&)
+ {
+ }
+ };
+
+ template <typename SpikePoint>
+ struct process_data<failure_spikes, bool, SpikePoint>
+ {
+ static inline void apply(std::ostringstream& oss,
+ bool is_linear,
+ SpikePoint const& spike_point)
+ {
+ if (is_linear && AllowSpikes)
+ {
+ return;
+ }
+
+ oss << ". A spike point was found with apex at "
+ << geometry::dsv(spike_point);
+ }
+ };
+
+ template <typename Turns>
+ struct process_data<failure_self_intersections, Turns>
+ {
+ static inline
+ void apply_to_segment_identifier(std::ostringstream& oss,
+ segment_identifier seg_id)
+ {
+ oss << "{" << seg_id.source_index
+ << ", " << seg_id.multi_index
+ << ", " << seg_id.ring_index
+ << ", " << seg_id.segment_index
+ << "}";
+ }
+
+ static inline void apply(std::ostringstream& oss,
+ Turns const& turns)
+ {
+ typedef typename boost::range_value<Turns>::type turn_type;
+ turn_type const& turn = range::front(turns);
+ oss << ". A self-intersection point was found at "
+ << geometry::dsv(turn.point);
+
+ oss << "; method: " << method_char(turn.method)
+ << "; operations: "
+ << operation_char(turn.operations[0].operation)
+ << "/"
+ << operation_char(turn.operations[1].operation)
+ << "; segment IDs {source, multi, ring, segment}: ";
+ apply_to_segment_identifier(oss, turn.operations[0].seg_id);
+ oss << "/";
+ apply_to_segment_identifier(oss, turn.operations[1].seg_id);
+ }
+ };
+
+ template <typename Point>
+ struct process_data<failure_duplicate_points, Point>
+ {
+ static inline void apply(std::ostringstream& oss,
+ Point const& point)
+ {
+ if (AllowDuplicates)
+ {
+ return;
+ }
+ oss << ". Duplicate points were found near point "
+ << geometry::dsv(point);
+ }
+ };
+
+public:
+ failing_reason_policy(std::ostringstream& oss)
+ : m_oss(oss)
+ {}
+
+ template <validity_failure_type Failure>
+ inline bool apply()
+ {
+ validity_failure_type const failure = transform_failure_type(Failure);
+ set_failure_message(failure);
+ return failure == no_failure;
+ }
+
+ template <validity_failure_type Failure, typename Data>
+ inline bool apply(Data const& data)
+ {
+ validity_failure_type const failure = transform_failure_type(Failure);
+ set_failure_message(failure);
+ process_data<Failure, Data>::apply(m_oss, data);
+ return failure == no_failure;
+ }
+
+ template <validity_failure_type Failure, typename Data1, typename Data2>
+ inline bool apply(Data1 const& data1, Data2 const& data2)
+ {
+ validity_failure_type const failure
+ = transform_failure_type(Failure, data1);
+ set_failure_message(failure);
+ process_data<Failure, Data1, Data2>::apply(m_oss, data1, data2);
+ return failure == no_failure;
+ }
+
+private:
+ std::ostringstream& m_oss;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
diff --git a/boost/geometry/policies/is_valid/failure_type_policy.hpp b/boost/geometry/policies/is_valid/failure_type_policy.hpp
new file mode 100644
index 0000000000..9fb569e283
--- /dev/null
+++ b/boost/geometry/policies/is_valid/failure_type_policy.hpp
@@ -0,0 +1,83 @@
+// 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_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP
+#define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP
+
+#include <boost/geometry/algorithms/validity_failure_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+// policy that simply keeps (and can return) the failure type
+template <bool AllowDuplicates = true, bool AllowSpikes = true>
+class failure_type_policy
+{
+private:
+ static inline
+ validity_failure_type transform_failure_type(validity_failure_type failure)
+ {
+ if (AllowDuplicates && failure == failure_duplicate_points)
+ {
+ return no_failure;
+ }
+ return failure;
+ }
+
+ static inline
+ validity_failure_type transform_failure_type(validity_failure_type failure,
+ bool is_linear)
+ {
+ if (is_linear && AllowSpikes && failure == failure_spikes)
+ {
+ return no_failure;
+ }
+ return transform_failure_type(failure);
+ }
+
+public:
+ failure_type_policy()
+ : m_failure(no_failure)
+ {}
+
+ template <validity_failure_type Failure>
+ inline bool apply()
+ {
+ m_failure = transform_failure_type(Failure);
+ return m_failure == no_failure;
+ }
+
+ template <validity_failure_type Failure, typename Data>
+ inline bool apply(Data const&)
+ {
+ return apply<Failure>();
+ }
+
+ template <validity_failure_type Failure, typename Data1, typename Data2>
+ inline bool apply(Data1 const& data1, Data2 const&)
+ {
+ m_failure = transform_failure_type(Failure, data1);
+ return m_failure == no_failure;
+ }
+
+ validity_failure_type failure() const
+ {
+ return m_failure;
+ }
+
+private:
+ validity_failure_type m_failure;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP
diff --git a/boost/geometry/policies/relate/direction.hpp b/boost/geometry/policies/relate/direction.hpp
index 02fed94b10..2c903bd79f 100644
--- a/boost/geometry/policies/relate/direction.hpp
+++ b/boost/geometry/policies/relate/direction.hpp
@@ -206,22 +206,51 @@ struct segments_direction
}
}
+ static inline int arrival_from_position_value(int /*v_from*/, int v_to)
+ {
+ return v_to == 2 ? 1
+ : v_to == 1 || v_to == 3 ? 0
+ //: v_from >= 1 && v_from <= 3 ? -1
+ : -1;
+
+ // NOTE: this should be an equivalent of the above for the other order
+ /* (v_from < 3 && v_to > 3) || (v_from > 3 && v_to < 3) ? 1
+ : v_from == 3 || v_to == 3 ? 0
+ : -1;*/
+ }
+
+ static inline void analyse_position_value(int pos_val,
+ int & in_segment_count,
+ int & on_end_count,
+ int & outside_segment_count)
+ {
+ if ( pos_val == 1 || pos_val == 3 )
+ {
+ on_end_count++;
+ }
+ else if ( pos_val == 2 )
+ {
+ in_segment_count++;
+ }
+ else
+ {
+ outside_segment_count++;
+ }
+ }
+
template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
- Segment1 const& , Segment2 const&,
- Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
- Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
+ Segment1 const& , Segment2 const& , bool opposite,
+ int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,
+ Ratio const& /*ra_from_wrt_b*/, Ratio const& /*ra_to_wrt_b*/,
+ Ratio const& /*rb_from_wrt_a*/, Ratio const& /*rb_to_wrt_a*/)
{
- // If segments are opposite, the ratio of the FROM w.r.t. the other
- // is larger than the ratio of the TO w.r.t. the other
- bool const opposite = ra_to_wrt_b < ra_from_wrt_b;
-
return_type r('c', opposite);
// IMPORTANT: the order of conditions is different as in intersection_points.hpp
// We assign A in 0 and B in 1
- r.arrival[0] = arrival_value(ra_from_wrt_b, ra_to_wrt_b);
- r.arrival[1] = arrival_value(rb_from_wrt_a, rb_to_wrt_a);
+ r.arrival[0] = arrival_from_position_value(a1_wrt_b, a2_wrt_b);
+ r.arrival[1] = arrival_from_position_value(b1_wrt_a, b2_wrt_a);
// Analyse them
int a_in_segment_count = 0;
@@ -230,13 +259,13 @@ struct segments_direction
int b_in_segment_count = 0;
int b_on_end_count = 0;
int b_outside_segment_count = 0;
- analyze(ra_from_wrt_b,
+ analyse_position_value(a1_wrt_b,
a_in_segment_count, a_on_end_count, a_outside_segment_count);
- analyze(ra_to_wrt_b,
+ analyse_position_value(a2_wrt_b,
a_in_segment_count, a_on_end_count, a_outside_segment_count);
- analyze(rb_from_wrt_a,
+ analyse_position_value(b1_wrt_a,
b_in_segment_count, b_on_end_count, b_outside_segment_count);
- analyze(rb_to_wrt_a,
+ analyse_position_value(b2_wrt_a,
b_in_segment_count, b_on_end_count, b_outside_segment_count);
if (a_on_end_count == 1
diff --git a/boost/geometry/policies/relate/intersection_points.hpp b/boost/geometry/policies/relate/intersection_points.hpp
index aa2f697a2a..082dc4ca7f 100644
--- a/boost/geometry/policies/relate/intersection_points.hpp
+++ b/boost/geometry/policies/relate/intersection_points.hpp
@@ -19,6 +19,7 @@
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/util/promote_integral.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/math.hpp>
@@ -60,12 +61,24 @@ struct segments_intersection_points
// denominator. In case of integer this results in an integer
// division.
BOOST_ASSERT(ratio.denominator() != 0);
- set<0>(point, boost::numeric_cast<coordinate_type>(
- get<0, 0>(segment)
- + ratio.numerator() * dx / ratio.denominator()));
- set<1>(point, boost::numeric_cast<coordinate_type>(
- get<0, 1>(segment)
- + ratio.numerator() * dy / ratio.denominator()));
+
+ typedef typename promote_integral<coordinate_type>::type promoted_type;
+
+ promoted_type const numerator
+ = boost::numeric_cast<promoted_type>(ratio.numerator());
+ promoted_type const denominator
+ = boost::numeric_cast<promoted_type>(ratio.denominator());
+ promoted_type const dx_promoted = boost::numeric_cast<promoted_type>(dx);
+ promoted_type const dy_promoted = boost::numeric_cast<promoted_type>(dy);
+
+ set<0>(point, get<0, 0>(segment) + boost::numeric_cast
+ <
+ coordinate_type
+ >(numerator * dx_promoted / denominator));
+ set<1>(point, get<0, 1>(segment) + boost::numeric_cast
+ <
+ coordinate_type
+ >(numerator * dy_promoted / denominator));
}
@@ -100,19 +113,20 @@ struct segments_intersection_points
template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
- Segment1 const& a, Segment2 const& b,
+ Segment1 const& a, Segment2 const& b, bool /*opposite*/,
+ int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,
Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
{
return_type result;
- int index = 0, count_a = 0, count_b = 0;
+ unsigned int index = 0, count_a = 0, count_b = 0;
Ratio on_a[2];
// The conditions "index < 2" are necessary for non-robust handling,
// if index would be 2 this indicate an (currently uncatched) error
// IMPORTANT: the order of conditions is different as in direction.hpp
- if (ra_from_wrt_b.on_segment()
+ if (a1_wrt_b >= 1 && a1_wrt_b <= 3 // ra_from_wrt_b.on_segment()
&& index < 2)
{
// a1--------->a2
@@ -126,7 +140,7 @@ struct segments_intersection_points
index++;
count_a++;
}
- if (rb_from_wrt_a.in_segment()
+ if (b1_wrt_a == 2 //rb_from_wrt_a.in_segment()
&& index < 2)
{
// We take the first intersection point of B
@@ -143,7 +157,7 @@ struct segments_intersection_points
count_b++;
}
- if (ra_to_wrt_b.on_segment()
+ if (a2_wrt_b >= 1 && a2_wrt_b <= 3 //ra_to_wrt_b.on_segment()
&& index < 2)
{
// Similarly, second IP (here a2)
@@ -155,7 +169,7 @@ struct segments_intersection_points
index++;
count_a++;
}
- if (rb_to_wrt_a.in_segment()
+ if (b2_wrt_a == 2 // rb_to_wrt_a.in_segment()
&& index < 2)
{
detail::assign_point_from_index<1>(b, result.intersections[index]);
diff --git a/boost/geometry/policies/relate/tupled.hpp b/boost/geometry/policies/relate/tupled.hpp
index 6da9095c4e..4b65432f20 100644
--- a/boost/geometry/policies/relate/tupled.hpp
+++ b/boost/geometry/policies/relate/tupled.hpp
@@ -47,13 +47,22 @@ struct segments_tupled
template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
- Segment1 const& segment1, Segment2 const& segment2,
- Ratio const& ra1, Ratio const& ra2, Ratio const& rb1, Ratio const& rb2)
+ Segment1 const& segment1, Segment2 const& segment2,
+ bool opposite,
+ int pa1, int pa2, int pb1, int pb2,
+ Ratio const& ra1, Ratio const& ra2,
+ Ratio const& rb1, Ratio const& rb2)
{
return boost::make_tuple
(
- Policy1::segments_collinear(segment1, segment2, ra1, ra2, rb1, rb2),
- Policy2::segments_collinear(segment1, segment2, ra1, ra2, rb1, rb2)
+ Policy1::segments_collinear(segment1, segment2,
+ opposite,
+ pa1, pa2, pb1, pb2,
+ ra1, ra2, rb1, rb2),
+ Policy2::segments_collinear(segment1, segment2,
+ opposite,
+ pa1, pa2, pb1, pb2,
+ ra1, ra2, rb1, rb2)
);
}
diff --git a/boost/geometry/policies/robustness/get_rescale_policy.hpp b/boost/geometry/policies/robustness/get_rescale_policy.hpp
index ed7c1eb94c..52570995f6 100644
--- a/boost/geometry/policies/robustness/get_rescale_policy.hpp
+++ b/boost/geometry/policies/robustness/get_rescale_policy.hpp
@@ -1,9 +1,14 @@
// 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.
+
+// 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
@@ -41,35 +46,52 @@ namespace boost { namespace geometry
namespace detail { namespace get_rescale_policy
{
-template <typename Point, typename RobustPoint, typename Geometry, typename Factor>
-static inline void init_rescale_policy(Geometry const& geometry,
- Point& min_point,
- RobustPoint& min_robust_point,
- Factor& factor)
+template
+<
+ typename Box,
+ typename Point,
+ typename RobustPoint,
+ typename Factor
+>
+inline void scale_box_to_integer_range(Box const& box,
+ Point& min_point,
+ RobustPoint& min_robust_point,
+ Factor& factor)
{
- // Get bounding boxes
- model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);
-
- // Scale this to integer-range
+ // Scale box to integer-range
typedef typename promote_floating_point
<
typename geometry::coordinate_type<Point>::type
>::type num_type;
- num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(env));
+ 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()) ? 1
+ factor = math::equals(diff, num_type()) || diff >= range ? 1
: boost::numeric_cast<num_type>(
boost::numeric_cast<boost::long_long_type>(half + range / diff));
+ BOOST_ASSERT(factor >= 1);
+
// Assign input/output minimal points
- detail::assign_point_from_index<0>(env, min_point);
+ detail::assign_point_from_index<0>(box, min_point);
num_type const two = 2;
boost::long_long_type const min_coordinate
= boost::numeric_cast<boost::long_long_type>(-range / two);
assign_values(min_robust_point, min_coordinate, min_coordinate);
}
+template <typename Point, typename RobustPoint, typename Geometry, typename Factor>
+static inline void init_rescale_policy(Geometry const& geometry,
+ Point& min_point,
+ RobustPoint& min_robust_point,
+ Factor& factor)
+{
+ // Get bounding boxes
+ model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);
+
+ scale_box_to_integer_range(env, min_point, min_robust_point, factor);
+}
+
template <typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, typename Factor>
static inline void init_rescale_policy(Geometry1 const& geometry1,
Geometry2 const& geometry2,
@@ -82,25 +104,7 @@ static inline void init_rescale_policy(Geometry1 const& geometry1,
model::box<Point> env2 = geometry::return_envelope<model::box<Point> >(geometry2);
geometry::expand(env, env2);
- // TODO: merge this with implementation above
- // Scale this to integer-range
- typedef typename promote_floating_point
- <
- typename geometry::coordinate_type<Point>::type
- >::type num_type;
- num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(env));
- 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()) ? 1
- : boost::numeric_cast<num_type>(
- boost::numeric_cast<boost::long_long_type>(half + range / diff));
-
- // Assign input/output minimal points
- detail::assign_point_from_index<0>(env, min_point);
- num_type const two = 2;
- boost::long_long_type const min_coordinate
- = boost::numeric_cast<boost::long_long_type>(-range / two);
- assign_values(min_robust_point, min_coordinate, min_coordinate);
+ scale_box_to_integer_range(env, min_point, min_robust_point, factor);
}
diff --git a/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp b/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp
index 7b7cd1890f..446d2f02cd 100644
--- a/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp
+++ b/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp
@@ -9,6 +9,8 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP
+#include <boost/core/ignore_unused.hpp>
+
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
@@ -79,6 +81,8 @@ public :
inline NumericType max_distance(JoinStrategy const& join_strategy,
EndStrategy const& end_strategy) const
{
+ boost::ignore_unused(join_strategy, end_strategy);
+
NumericType const left = geometry::math::abs(m_left);
NumericType const right = geometry::math::abs(m_right);
NumericType const dist = (std::max)(left, right);
diff --git a/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp b/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp
index bc0c46f644..73bd21ac73 100644
--- a/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp
+++ b/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp
@@ -9,6 +9,9 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP
+
+#include <boost/core/ignore_unused.hpp>
+
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
@@ -76,6 +79,8 @@ public :
inline NumericType max_distance(JoinStrategy const& join_strategy,
EndStrategy const& end_strategy) const
{
+ boost::ignore_unused(join_strategy, end_strategy);
+
NumericType const dist = geometry::math::abs(m_distance);
return (std::max)(join_strategy.max_distance(dist),
end_strategy.max_distance(dist));
diff --git a/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
index a960a6f1f9..1d59e13cf6 100644
--- a/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
+++ b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
@@ -364,7 +364,7 @@ private:
// count describes a closed case but comparison with min size of closed
// gives the result compatible also with open
// here core_detail::closure::minimum_ring_size<closed> could be used
- if ( count < 4 )
+ if (count < 4)
{
// there should be only one missing
*out++ = *boost::begin(first);
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
index f4ed7a634f..641533fc6a 100644
--- a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
@@ -73,7 +73,7 @@ struct winding_side_equal
PointOfSegment ss1, ss2;
set<1-D>(ss1, get<1-D>(se));
set<1-D>(ss2, get<1-D>(se));
- if ( count > 0 ) // UP
+ if (count > 0) // UP
{
set<D>(ss1, 0);
set<D>(ss2, 1);
@@ -127,7 +127,7 @@ struct winding_side_between
set<1-D>(ss1, get<1-D>(s1));
set<1-D>(ss2, get<1-D>(s1));
- if ( count > 0 ) // UP
+ if (count > 0) // UP
{
set<D>(ss1, 0);
set<D>(ss2, 1);
@@ -140,9 +140,9 @@ struct winding_side_between
int const seg_side = strategy_side_type::apply(ss1, ss2, s2);
- if ( seg_side != 0 ) // segment not vertical
+ if (seg_side != 0) // segment not vertical
{
- if ( strategy_side_type::apply(ss1, ss2, point) == -seg_side ) // point on the opposite side than s2
+ if (strategy_side_type::apply(ss1, ss2, point) == -seg_side) // point on the opposite side than s2
{
return -seg_side;
}
@@ -151,7 +151,7 @@ struct winding_side_between
set<1-D>(ss1, get<1-D>(s2));
set<1-D>(ss2, get<1-D>(s2));
- if ( strategy_side_type::apply(ss1, ss2, point) == seg_side ) // point behind s2
+ if (strategy_side_type::apply(ss1, ss2, point) == seg_side) // point behind s2
{
return seg_side;
}
@@ -308,7 +308,7 @@ public :
if (count != 0)
{
int side = 0;
- if ( count == 1 || count == -1 )
+ if (count == 1 || count == -1)
{
side = winding_side_equal<cs_t>
::template apply<1>(point, eq1 ? s1 : s2, count);
diff --git a/boost/geometry/strategies/agnostic/relate.hpp b/boost/geometry/strategies/agnostic/relate.hpp
index 318047fadb..9e8753251d 100644
--- a/boost/geometry/strategies/agnostic/relate.hpp
+++ b/boost/geometry/strategies/agnostic/relate.hpp
@@ -20,10 +20,9 @@ namespace boost { namespace geometry
namespace strategy { namespace relate
{
-template <typename StaticMask>
+template <typename Geometry1, typename Geometry2, typename StaticMask>
struct relate
{
- template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return detail::relate::relate<StaticMask>(geometry1, geometry2);
@@ -44,13 +43,23 @@ namespace services
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>
{
- typedef strategy::relate::relate<detail::relate::static_mask_within> type;
+ typedef strategy::relate::relate
+ <
+ Geometry1,
+ Geometry2,
+ detail::relate::static_mask_within
+ > type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>
{
- typedef strategy::relate::relate<detail::relate::static_mask_within> type;
+ typedef strategy::relate::relate
+ <
+ Geometry1,
+ Geometry2,
+ detail::relate::static_mask_within
+ > type;
};
@@ -71,13 +80,23 @@ namespace strategy { namespace covered_by { namespace services
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>
{
- typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
+ typedef strategy::relate::relate
+ <
+ Geometry1,
+ Geometry2,
+ detail::relate::static_mask_covered_by
+ > type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>
struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>
{
- typedef strategy::relate::relate<detail::relate::static_mask_covered_by> type;
+ typedef strategy::relate::relate
+ <
+ Geometry1,
+ Geometry2,
+ detail::relate::static_mask_covered_by
+ > type;
};
diff --git a/boost/geometry/strategies/agnostic/side_by_azimuth.hpp b/boost/geometry/strategies/agnostic/side_by_azimuth.hpp
new file mode 100644
index 0000000000..14c69a0597
--- /dev/null
+++ b/boost/geometry/strategies/agnostic/side_by_azimuth.hpp
@@ -0,0 +1,87 @@
+// 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/agnostic/simplify_douglas_peucker.hpp b/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp
index 8ad3bbc50d..99e7d9b50f 100644
--- a/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp
+++ b/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 1995, 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 1995, 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 1995 Maarten Hilferink, 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.
@@ -15,6 +20,9 @@
#include <cstddef>
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
+#include <iostream>
+#endif
#include <vector>
#include <boost/range.hpp>
@@ -23,10 +31,7 @@
#include <boost/geometry/strategies/distance.hpp>
-
-//#define GL_DEBUG_DOUGLAS_PEUCKER
-
-#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
#include <boost/geometry/io/dsv/write.hpp>
#endif
@@ -126,7 +131,7 @@ namespace detail
// because we want to consider a candidate point in between
if (size <= 2)
{
-#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
if (begin != end)
{
std::cout << "ignore between " << dsv(begin->p)
@@ -140,7 +145,7 @@ namespace detail
iterator_type last = end - 1;
-#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
std::cout << "find between " << dsv(begin->p)
<< " and " << dsv(last->p)
<< " size=" << size << std::endl;
@@ -155,7 +160,7 @@ namespace detail
{
distance_type dist = ps_distance_strategy.apply(it->p, begin->p, last->p);
-#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
std::cout << "consider " << dsv(it->p)
<< " at " << double(dist)
<< ((dist > max_dist) ? " maybe" : " no")
@@ -173,7 +178,7 @@ namespace detail
// and handle segments in between recursively
if ( less()(max_dist, md) )
{
-#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
std::cout << "use " << dsv(candidate->p) << std::endl;
#endif
@@ -193,6 +198,10 @@ namespace detail
OutputIterator out,
distance_type max_distance) const
{
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
+ std::cout << "max distance: " << max_distance
+ << std::endl << std::endl;
+#endif
distance_strategy_type strategy;
// Copy coordinates, a vector of references to all points
@@ -228,8 +237,6 @@ namespace detail
}
};
-
-
}
#endif // DOXYGEN_NO_DETAIL
@@ -269,18 +276,28 @@ public :
PointDistanceStrategy
>::distance_type distance_type;
- typedef distance_type return_type;
-
template <typename Range, typename OutputIterator>
static inline OutputIterator apply(Range const& range,
OutputIterator out,
- distance_type max_distance)
+ distance_type const& max_distance)
{
- return detail::douglas_peucker
+ namespace services = strategy::distance::services;
+
+ typedef typename services::comparable_type
<
- Point,
PointDistanceStrategy
- >().apply(range, out, max_distance);
+ >::type comparable_distance_strategy_type;
+
+ return detail::douglas_peucker
+ <
+ Point, comparable_distance_strategy_type
+ >().apply(range, out,
+ services::result_from_distance
+ <
+ comparable_distance_strategy_type, Point, Point
+ >::apply(comparable_distance_strategy_type(),
+ max_distance)
+ );
}
};
diff --git a/boost/geometry/strategies/cartesian/buffer_end_round.hpp b/boost/geometry/strategies/cartesian/buffer_end_round.hpp
index 74780d6165..a233f1c4be 100644
--- a/boost/geometry/strategies/cartesian/buffer_end_round.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_end_round.hpp
@@ -95,8 +95,9 @@ public :
//! \brief Constructs the strategy
//! \param points_per_circle points which would be used for a full circle
+ //! (if points_per_circle is smaller than 4, it is internally set to 4)
explicit inline end_round(std::size_t points_per_circle = 90)
- : m_points_per_circle(points_per_circle)
+ : m_points_per_circle((points_per_circle < 4u) ? 4u : points_per_circle)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -106,7 +107,7 @@ public :
inline void apply(Point const& penultimate_point,
Point const& perp_left_point,
Point const& ultimate_point,
- Point const& ,
+ Point const& perp_right_point,
buffer_side_selector side,
DistanceStrategy const& distance,
RangeOut& range_out) const
@@ -142,6 +143,13 @@ public :
set<1>(shifted_point, get<1>(ultimate_point) + dist_half_diff * sin(alpha));
generate_points(shifted_point, alpha, (dist_left + dist_right) / two, range_out);
}
+
+ if (m_points_per_circle % 2 == 1)
+ {
+ // For a half circle, if the number of points is not even,
+ // we should insert the end point too, to generate a full cap
+ range_out.push_back(perp_right_point);
+ }
}
template <typename NumericType>
diff --git a/boost/geometry/strategies/cartesian/buffer_join_miter.hpp b/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
index 8fcf3b996c..99ec80527f 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
@@ -35,6 +35,8 @@ namespace strategy { namespace buffer
their length. The miter is not changed to a bevel form (as done in some
other software), it is just adapted to the specified miter_limit but keeps
its miter form.
+ If the buffer distance is 5.0, and the miter limit is 2.0, generated points
+ will be located at a distance of at most 10.0 (2*5) units.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
diff --git a/boost/geometry/strategies/cartesian/buffer_join_round.hpp b/boost/geometry/strategies/cartesian/buffer_join_round.hpp
index 9e467c85a0..9ec51cd1ec 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_round.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_round.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
@@ -9,6 +9,8 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
+#include <algorithm>
+
#include <boost/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
@@ -69,34 +71,38 @@ private :
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
- PromotedType dx1 = get<0>(perp1) - get<0>(vertex);
- PromotedType dy1 = get<1>(perp1) - get<1>(vertex);
- PromotedType dx2 = get<0>(perp2) - get<0>(vertex);
- PromotedType dy2 = get<1>(perp2) - get<1>(vertex);
+ PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
+ PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
+ PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
+ PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
- BOOST_ASSERT(buffer_distance != 0);
+ PromotedType const two = 2.0;
+ PromotedType const two_pi = two * geometry::math::pi<PromotedType>();
- dx1 /= buffer_distance;
- dy1 /= buffer_distance;
- dx2 /= buffer_distance;
- dy2 /= buffer_distance;
+ PromotedType const angle1 = atan2(dy1, dx1);
+ PromotedType angle2 = atan2(dy2, dx2);
+ while (angle2 > angle1)
+ {
+ angle2 -= two_pi;
+ }
+ PromotedType const angle_diff = angle1 - angle2;
- PromotedType angle_diff = acos(dx1 * dx2 + dy1 * dy2);
+ // Divide the angle into an integer amount of steps to make it
+ // visually correct also for a low number of points / circle
- PromotedType two = 2.0;
- PromotedType steps = m_points_per_circle;
- int n = boost::numeric_cast<int>(steps * angle_diff
- / (two * geometry::math::pi<PromotedType>()));
+ // If a full circle is divided into 3 parts (e.g. angle is 125),
+ // the one point in between must still be generated
+ // The calculation below:
+ // - 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
- if (n <= 1)
- {
- return;
- }
+ int const n = (std::max)(static_cast<int>(
+ ceil(m_points_per_circle * angle_diff / two_pi)), 1);
- PromotedType const angle1 = atan2(dy1, dx1);
- PromotedType diff = angle_diff / PromotedType(n);
+ 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)
{
Point p;
diff --git a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
index f64a82d8fc..86ebc43c9c 100644
--- a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
@@ -1,5 +1,12 @@
// 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
// http://www.boost.org/LICENSE_1_0.txt)
@@ -45,9 +52,10 @@ class point_circle
{
public :
//! \brief Constructs the strategy
- //! \param count number of points for the created circle
+ //! \param count number of points for the created circle (if count
+ //! is smaller than 3, count is internally set to 3)
explicit point_circle(std::size_t count = 90)
- : m_count(count)
+ : m_count((count < 3u) ? 3u : count)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
diff --git a/boost/geometry/strategies/cartesian/cart_intersect.hpp b/boost/geometry/strategies/cartesian/cart_intersect.hpp
index 66af2d2e9c..a7bd385226 100644
--- a/boost/geometry/strategies/cartesian/cart_intersect.hpp
+++ b/boost/geometry/strategies/cartesian/cart_intersect.hpp
@@ -1,7 +1,13 @@
// 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-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by 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
@@ -194,7 +200,11 @@ struct relate_cartesian_segments
get<1>(robust_b1) - get<1>(robust_a1),
robust_db0, robust_db);
- if (robust_da0 == 0)
+ math::detail::equals_factor_policy<robust_coordinate_type>
+ policy(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b);
+ robust_coordinate_type const zero = 0;
+ if (math::detail::equals_by_policy(robust_da0, zero, policy)
+ || math::detail::equals_by_policy(robust_db0, zero, policy))
{
// If this is the case, no rescaling is done for FP precision.
// We set it to collinear, but it indicates a robustness issue.
@@ -211,25 +221,31 @@ struct relate_cartesian_segments
if (collinear)
{
- bool const collinear_use_first
- = geometry::math::abs(robust_dx_a) + geometry::math::abs(robust_dx_b)
- >= geometry::math::abs(robust_dy_a) + geometry::math::abs(robust_dy_b);
-
- // Degenerate cases: segments of single point, lying on other segment, are not disjoint
- // This situation is collinear too
-
- if (collinear_use_first)
+ std::pair<bool, bool> const collinear_use_first
+ = is_x_more_significant(geometry::math::abs(robust_dx_a),
+ geometry::math::abs(robust_dy_a),
+ geometry::math::abs(robust_dx_b),
+ geometry::math::abs(robust_dy_b),
+ a_is_point, b_is_point);
+
+ if (collinear_use_first.second)
{
- return relate_collinear<0, ratio_type>(a, b,
- robust_a1, robust_a2, robust_b1, robust_b2,
- a_is_point, b_is_point);
- }
- else
- {
- // Y direction contains larger segments (maybe dx is zero)
- return relate_collinear<1, ratio_type>(a, b,
- robust_a1, robust_a2, robust_b1, robust_b2,
- a_is_point, b_is_point);
+ // Degenerate cases: segments of single point, lying on other segment, are not disjoint
+ // This situation is collinear too
+
+ if (collinear_use_first.first)
+ {
+ return relate_collinear<0, ratio_type>(a, b,
+ robust_a1, robust_a2, robust_b1, robust_b2,
+ a_is_point, b_is_point);
+ }
+ else
+ {
+ // Y direction contains larger segments (maybe dx is zero)
+ return relate_collinear<1, ratio_type>(a, b,
+ robust_a1, robust_a2, robust_b1, robust_b2,
+ a_is_point, b_is_point);
+ }
}
}
@@ -237,6 +253,40 @@ struct relate_cartesian_segments
}
private:
+ // first is true if x is more significant
+ // second is true if the more significant difference is not 0
+ template <typename RobustCoordinateType>
+ static inline std::pair<bool, bool>
+ is_x_more_significant(RobustCoordinateType const& abs_robust_dx_a,
+ RobustCoordinateType const& abs_robust_dy_a,
+ RobustCoordinateType const& abs_robust_dx_b,
+ RobustCoordinateType const& abs_robust_dy_b,
+ 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");
+
+ // for degenerated segments the second is always true because this function
+ // shouldn't be called if both segments were degenerated
+
+ if (a_is_point)
+ {
+ return std::make_pair(abs_robust_dx_b >= abs_robust_dy_b, true);
+ }
+ else if (b_is_point)
+ {
+ return std::make_pair(abs_robust_dx_a >= abs_robust_dy_a, true);
+ }
+ else
+ {
+ RobustCoordinateType const min_dx = (std::min)(abs_robust_dx_a, abs_robust_dx_b);
+ RobustCoordinateType const min_dy = (std::min)(abs_robust_dy_a, abs_robust_dy_b);
+ return min_dx == min_dy ?
+ std::make_pair(true, min_dx > RobustCoordinateType(0)) :
+ std::make_pair(min_dx > min_dy, true);
+ }
+ }
+
template
<
std::size_t Dimension,
@@ -319,17 +369,58 @@ private:
RobustType const length_a = oa_2 - oa_1; // no abs, see above
RobustType const length_b = ob_2 - ob_1;
- RatioType const ra_from(oa_1 - ob_1, length_b);
- RatioType const ra_to(oa_2 - ob_1, length_b);
- RatioType const rb_from(ob_1 - oa_1, length_a);
- RatioType const rb_to(ob_2 - oa_1, length_a);
+ RatioType ra_from(oa_1 - ob_1, length_b);
+ RatioType ra_to(oa_2 - ob_1, length_b);
+ RatioType rb_from(ob_1 - oa_1, length_a);
+ RatioType rb_to(ob_2 - oa_1, length_a);
+
+ // use absolute measure to detect endpoints intersection
+ // NOTE: it'd be possible to calculate bx_wrt_a using ax_wrt_b values
+ int const a1_wrt_b = position_value(oa_1, ob_1, ob_2);
+ int const a2_wrt_b = position_value(oa_2, ob_1, ob_2);
+ int const b1_wrt_a = position_value(ob_1, oa_1, oa_2);
+ int const b2_wrt_a = position_value(ob_2, oa_1, oa_2);
+
+ // fix the ratios if necessary
+ // CONSIDER: fixing ratios also in other cases, if they're inconsistent
+ // e.g. if ratio == 1 or 0 (so IP at the endpoint)
+ // but position value indicates that the IP is in the middle of the segment
+ // because one of the segments is very long
+ // In such case the ratios could be moved into the middle direction
+ // by some small value (e.g. EPS+1ULP)
+ if (a1_wrt_b == 1)
+ {
+ ra_from.assign(0, 1);
+ rb_from.assign(0, 1);
+ }
+ else if (a1_wrt_b == 3)
+ {
+ ra_from.assign(1, 1);
+ rb_to.assign(0, 1);
+ }
+
+ if (a2_wrt_b == 1)
+ {
+ ra_to.assign(0, 1);
+ rb_from.assign(1, 1);
+ }
+ else if (a2_wrt_b == 3)
+ {
+ ra_to.assign(1, 1);
+ rb_to.assign(1, 1);
+ }
- if ((ra_from.left() && ra_to.left()) || (ra_from.right() && ra_to.right()))
+ if ((a1_wrt_b < 1 && a2_wrt_b < 1) || (a1_wrt_b > 3 && a2_wrt_b > 3))
+ //if ((ra_from.left() && ra_to.left()) || (ra_from.right() && ra_to.right()))
{
return Policy::disjoint();
}
- return Policy::segments_collinear(a, b, ra_from, ra_to, rb_from, rb_to);
+ bool const opposite = math::sign(length_a) != math::sign(length_b);
+
+ return Policy::segments_collinear(a, b, opposite,
+ a1_wrt_b, a2_wrt_b, b1_wrt_a, b2_wrt_a,
+ ra_from, ra_to, rb_from, rb_to);
}
/// Relate segments where one is degenerate
@@ -351,8 +442,32 @@ private:
// b1/b2 (4..4)
// Ratio: (4-2)/(6-2)
RatioType const ratio(d - s1, s2 - s1);
+
+ if (!ratio.on_segment())
+ {
+ return Policy::disjoint();
+ }
+
return Policy::one_degenerate(degenerate_segment, ratio, a_degenerate);
}
+
+ template <typename ProjCoord1, typename ProjCoord2>
+ static inline int position_value(ProjCoord1 const& ca1,
+ ProjCoord2 const& cb1,
+ ProjCoord2 const& cb2)
+ {
+ // S1x 0 1 2 3 4
+ // S2 |---------->
+ return math::equals(ca1, cb1) ? 1
+ : math::equals(ca1, cb2) ? 3
+ : cb1 < cb2 ?
+ ( ca1 < cb1 ? 0
+ : ca1 > cb2 ? 4
+ : 2 )
+ : ( ca1 > cb1 ? 0
+ : ca1 < cb2 ? 4
+ : 2 );
+ }
};
diff --git a/boost/geometry/strategies/cartesian/centroid_average.hpp b/boost/geometry/strategies/cartesian/centroid_average.hpp
index 76e2f7144c..c12f6e2024 100644
--- a/boost/geometry/strategies/cartesian/centroid_average.hpp
+++ b/boost/geometry/strategies/cartesian/centroid_average.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 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.
@@ -15,6 +20,8 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
+#include <cstddef>
+
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
@@ -46,7 +53,7 @@ private :
class sum
{
friend class average;
- int count;
+ std::size_t count;
PointCentroid centroid;
public :
@@ -68,10 +75,15 @@ public :
state.count++;
}
- static inline void result(sum const& state, PointCentroid& centroid)
+ static inline bool result(sum const& state, PointCentroid& centroid)
{
centroid = state.centroid;
- divide_value(centroid, state.count);
+ if ( state.count > 0 )
+ {
+ divide_value(centroid, state.count);
+ return true;
+ }
+ return false;
}
};
diff --git a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
index f199fb80e5..0357f17e7a 100644
--- a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
+++ b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 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.
@@ -15,6 +20,8 @@
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
+#include <cstddef>
+
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits.hpp>
@@ -143,7 +150,7 @@ private :
class sums
{
friend class bashein_detmer;
- int count;
+ std::size_t count;
calculation_type sum_a2;
calculation_type sum_x;
calculation_type sum_y;
diff --git a/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
index 5d589ffc86..77443d46a9 100644
--- a/boost/geometry/strategies/cartesian/side_by_triangle.hpp
+++ b/boost/geometry/strategies/cartesian/side_by_triangle.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.
@@ -22,6 +27,9 @@
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/algorithms/detail/relate/less.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+
namespace boost { namespace geometry
{
@@ -38,6 +46,24 @@ namespace strategy { namespace side
template <typename CalculationType = void>
class side_by_triangle
{
+ template <typename Policy>
+ struct eps_policy
+ {
+ eps_policy() {}
+ template <typename Type>
+ eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
+ : policy(a, b, c, d)
+ {}
+ Policy policy;
+ };
+
+ struct eps_empty
+ {
+ eps_empty() {}
+ template <typename Type>
+ eps_empty(Type const&, Type const&, Type const&, Type const&) {}
+ };
+
public :
// Template member function, because it is not always trivial
@@ -47,23 +73,34 @@ public :
// Types can be all three different. Therefore it is
// not implemented (anymore) as "segment"
- template <typename coordinate_type, typename promoted_type, typename P1, typename P2, typename P>
- static inline promoted_type side_value(P1 const& p1, P2 const& p2, P const& p)
+ template
+ <
+ typename CoordinateType,
+ typename PromotedType,
+ typename P1,
+ typename P2,
+ typename P,
+ typename EpsPolicy
+ >
+ static inline
+ PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
{
- coordinate_type const x = get<0>(p);
- coordinate_type const y = get<1>(p);
+ CoordinateType const x = get<0>(p);
+ CoordinateType const y = get<1>(p);
- coordinate_type const sx1 = get<0>(p1);
- coordinate_type const sy1 = get<1>(p1);
- coordinate_type const sx2 = get<0>(p2);
- coordinate_type const sy2 = get<1>(p2);
+ CoordinateType const sx1 = get<0>(p1);
+ CoordinateType const sy1 = get<1>(p1);
+ CoordinateType const sx2 = get<0>(p2);
+ CoordinateType const sy2 = get<1>(p2);
- promoted_type const dx = sx2 - sx1;
- promoted_type const dy = sy2 - sy1;
- promoted_type const dpx = x - sx1;
- promoted_type const dpy = y - sy1;
+ PromotedType const dx = sx2 - sx1;
+ PromotedType const dy = sy2 - sy1;
+ PromotedType const dpx = x - sx1;
+ PromotedType const dpy = y - sy1;
- return geometry::detail::determinant<promoted_type>
+ eps_policy = EpsPolicy(dx, dy, dpx, dpy);
+
+ return geometry::detail::determinant<PromotedType>
(
dx, dy,
dpx, dpy
@@ -71,9 +108,99 @@ public :
}
+ template
+ <
+ typename CoordinateType,
+ typename PromotedType,
+ typename P1,
+ typename P2,
+ typename P
+ >
+ static inline
+ PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
+ {
+ eps_empty dummy;
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
+ }
+
+
+ template
+ <
+ typename CoordinateType,
+ typename PromotedType,
+ bool AreAllIntegralCoordinates
+ >
+ struct compute_side_value
+ {
+ template <typename P1, typename P2, typename P, typename EpsPolicy>
+ static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
+ {
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
+ }
+ };
+
+ template <typename CoordinateType, typename PromotedType>
+ struct compute_side_value<CoordinateType, PromotedType, false>
+ {
+ template <typename P1, typename P2, typename P, typename EpsPolicy>
+ static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
+ {
+ // For robustness purposes, first check if any two points are
+ // the same; in this case simply return that the points are
+ // collinear
+ if (geometry::detail::equals::equals_point_point(p1, p2)
+ || geometry::detail::equals::equals_point_point(p1, p)
+ || geometry::detail::equals::equals_point_point(p2, p))
+ {
+ return PromotedType(0);
+ }
+
+ // The side_by_triangle strategy computes the signed area of
+ // the point triplet (p1, p2, p); as such it is (in theory)
+ // invariant under cyclic permutations of its three arguments.
+ //
+ // In the context of numerical errors that arise in
+ // floating-point computations, and in order to make the strategy
+ // consistent with respect to cyclic permutations of its three
+ // arguments, we cyclically permute them so that the first
+ // argument is always the lexicographically smallest point.
+
+ geometry::detail::relate::less less;
+ if (less(p, p1))
+ {
+ if (less(p, p2))
+ {
+ // p is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
+ }
+ else
+ {
+ // p2 is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
+ }
+ }
+
+ if (less(p1, p2))
+ {
+ // p1 is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
+ }
+ else
+ {
+ // p2 is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
+ }
+ }
+ };
+
+
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
+ typedef typename coordinate_type<P1>::type coordinate_type1;
+ typedef typename coordinate_type<P2>::type coordinate_type2;
+ typedef typename coordinate_type<P>::type coordinate_type3;
+
typedef typename boost::mpl::if_c
<
boost::is_void<CalculationType>::type::value,
@@ -81,10 +208,9 @@ public :
<
typename select_most_precise
<
- typename coordinate_type<P1>::type,
- typename coordinate_type<P2>::type
+ coordinate_type1, coordinate_type2
>::type,
- typename coordinate_type<P>::type
+ coordinate_type3
>::type,
CalculationType
>::type coordinate_type;
@@ -96,10 +222,19 @@ public :
double
>::type promoted_type;
- promoted_type const s = side_value<coordinate_type, promoted_type>(p1, p2, p);
- promoted_type const zero = promoted_type();
+ bool const are_all_integral_coordinates =
+ boost::is_integral<coordinate_type1>::value
+ && boost::is_integral<coordinate_type2>::value
+ && boost::is_integral<coordinate_type3>::value;
- return math::equals(s, zero) ? 0
+ eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;
+ promoted_type s = compute_side_value
+ <
+ coordinate_type, promoted_type, are_all_integral_coordinates
+ >::apply(p1, p2, p, epsp);
+
+ promoted_type const zero = promoted_type();
+ return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
: s > zero ? 1
: -1;
}
diff --git a/boost/geometry/strategies/cartesian/side_of_intersection.hpp b/boost/geometry/strategies/cartesian/side_of_intersection.hpp
new file mode 100644
index 0000000000..39487676c1
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/side_of_intersection.hpp
@@ -0,0 +1,119 @@
+// 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_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP
+
+
+#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace side
+{
+
+// 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; there are no divisions
+// It can be used for either integer (rescaled) points, and also for FP
+class side_of_intersection
+{
+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>
+ static inline T side_value(Segment const& a, Segment const& b,
+ Segment const& c)
+ {
+ // The first point of the three segments is reused several times
+ T const ax = get<0, 0>(a);
+ T const ay = get<0, 1>(a);
+ T const bx = get<0, 0>(b);
+ T const by = get<0, 1>(b);
+ T const cx = get<0, 0>(c);
+ T const cy = get<0, 1>(c);
+
+ T const dx_a = get<1, 0>(a) - ax;
+ T const dy_a = get<1, 1>(a) - ay;
+
+ T const dx_b = get<1, 0>(b) - bx;
+ T const dy_b = get<1, 1>(b) - by;
+
+ T const dx_c = get<1, 0>(c) - cx;
+ T const dy_c = get<1, 1>(c) - cy;
+
+ // Cramer's rule: d (see cart_intersect.hpp)
+ T const d = geometry::detail::determinant<T>
+ (
+ dx_a, dy_a,
+ dx_b, dy_b
+ );
+
+ T const zero = T();
+ 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;
+ }
+
+ // Cramer's rule: da (see cart_intersect.hpp)
+ T const da = geometry::detail::determinant<T>
+ (
+ dx_b, dy_b,
+ ax - bx, ay - by
+ );
+
+ // 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>
+ (
+ dx_c * d, dy_c * d,
+ d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
+ );
+
+ // Note: result / (d * d)
+ // is identical to the side_value of side_by_triangle
+ // Therefore, the sign is always the same as that result, and the
+ // resulting side (left,right,collinear) is the same
+
+ return result;
+
+ }
+
+ template <typename Segment>
+ static inline int apply(Segment const& a, Segment const& b, Segment const& c)
+ {
+ typedef typename geometry::coordinate_type<Segment>::type coordinate_type;
+ coordinate_type const s = side_value<coordinate_type>(a, b, c);
+ coordinate_type const zero = coordinate_type();
+ return math::equals(s, zero) ? 0
+ : s > zero ? 1
+ : -1;
+ }
+
+};
+
+
+}} // namespace strategy::side
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP
diff --git a/boost/geometry/strategies/comparable_distance_result.hpp b/boost/geometry/strategies/comparable_distance_result.hpp
index a258ddb9b4..5ba9b1603d 100644
--- a/boost/geometry/strategies/comparable_distance_result.hpp
+++ b/boost/geometry/strategies/comparable_distance_result.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
@@ -91,9 +91,9 @@ struct comparable_distance_result
// A set of all variant type combinations that are compatible and
// implemented
typedef typename util::combine_if<
- typename mpl::vector1<Geometry1>,
+ typename boost::mpl::vector1<Geometry1>,
typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
- mpl::always<mpl::true_>
+ boost::mpl::always<boost::mpl::true_>
>::type possible_input_types;
// The (possibly variant) result type resulting from these combinations
@@ -101,11 +101,11 @@ struct comparable_distance_result
typename transform_variant<
possible_input_types,
resolve_strategy::comparable_distance_result<
- mpl::first<mpl::_>,
- mpl::second<mpl::_>,
+ boost::mpl::first<boost::mpl::_>,
+ boost::mpl::second<boost::mpl::_>,
Strategy
>,
- mpl::back_inserter<mpl::vector0<> >
+ boost::mpl::back_inserter<boost::mpl::vector0<> >
>::type
>::type type;
};
@@ -144,7 +144,7 @@ struct comparable_distance_result
<
typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
- mpl::always<mpl::true_>
+ boost::mpl::always<boost::mpl::true_>
>::type possible_input_types;
// The (possibly variant) result type resulting from these combinations
@@ -152,11 +152,11 @@ struct comparable_distance_result
typename transform_variant<
possible_input_types,
resolve_strategy::comparable_distance_result<
- mpl::first<mpl::_>,
- mpl::second<mpl::_>,
+ boost::mpl::first<boost::mpl::_>,
+ boost::mpl::second<boost::mpl::_>,
Strategy
>,
- mpl::back_inserter<mpl::vector0<> >
+ boost::mpl::back_inserter<boost::mpl::vector0<> >
>::type
>::type type;
};
diff --git a/boost/geometry/strategies/concepts/distance_concept.hpp b/boost/geometry/strategies/concepts/distance_concept.hpp
index a0cbbd21ed..6e75fa95a6 100644
--- a/boost/geometry/strategies/concepts/distance_concept.hpp
+++ b/boost/geometry/strategies/concepts/distance_concept.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-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -19,6 +24,8 @@
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/util/parameter_type_of.hpp>
@@ -26,13 +33,15 @@
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/strategies/tags.hpp>
+
namespace boost { namespace geometry { namespace concept
{
/*!
- \brief Checks strategy for point-segment-distance
+ \brief Checks strategy for point-point or point-box or box-box distance
\ingroup distance
*/
template <typename Strategy, typename Point1, typename Point2>
@@ -57,7 +66,7 @@ private :
ApplyMethod, 1
>::type ptype2;
- // 2) must define meta-function return_type
+ // 2) must define meta-function "return_type"
typedef typename strategy::distance::services::return_type
<
Strategy, ptype1, ptype2
@@ -75,6 +84,16 @@ private :
Strategy
>::type tag;
+ static const bool is_correct_strategy_tag =
+ boost::is_same<tag, strategy_tag_distance_point_point>::value
+ || boost::is_same<tag, strategy_tag_distance_point_box>::value
+ || boost::is_same<tag, strategy_tag_distance_box_box>::value;
+
+ BOOST_MPL_ASSERT_MSG
+ ((is_correct_strategy_tag),
+ INCORRECT_STRATEGY_TAG,
+ (types<tag>));
+
// 5) must implement apply with arguments
Strategy* str = 0;
ptype1 *p1 = 0;
@@ -111,7 +130,7 @@ public :
/*!
- \brief Checks strategy for point-segment-distance
+ \brief Checks strategy for point-segment distance
\ingroup strategy_concepts
*/
template <typename Strategy, typename Point, typename PointOfSegment>
@@ -125,6 +144,7 @@ private :
template <typename ApplyMethod>
static void apply(ApplyMethod)
{
+ // 1) inspect and define both arguments of apply
typedef typename parameter_type_of
<
ApplyMethod, 0
@@ -135,10 +155,28 @@ private :
ApplyMethod, 1
>::type sptype;
- // must define meta-function return_type
- typedef typename strategy::distance::services::return_type<Strategy, ptype, sptype>::type rtype;
+ namespace services = strategy::distance::services;
+ // 2) must define meta-function "tag"
+ typedef typename services::tag<Strategy>::type tag;
+ BOOST_MPL_ASSERT_MSG
+ ((boost::is_same
+ <
+ tag, strategy_tag_distance_point_segment
+ >::value),
+ INCORRECT_STRATEGY_TAG,
+ (types<tag>));
+ // 3) must define meta-function "return_type"
+ typedef typename services::return_type
+ <
+ Strategy, ptype, sptype
+ >::type rtype;
+
+ // 4) must define meta-function "comparable_type"
+ typedef typename services::comparable_type<Strategy>::type ctype;
+
+ // 5) must implement apply with arguments
Strategy *str = 0;
ptype *p = 0;
sptype *sp1 = 0;
@@ -146,8 +184,16 @@ private :
rtype r = str->apply(*p, *sp1, *sp2);
- boost::ignore_unused_variable_warning(str);
- boost::ignore_unused_variable_warning(r);
+ // 6) must define (meta-)struct "get_comparable" with apply
+ ctype cstrategy = services::get_comparable<Strategy>::apply(*str);
+
+ // 7) must define (meta-)struct "result_from_distance" with apply
+ r = services::result_from_distance
+ <
+ Strategy, ptype, sptype
+ >::apply(*str, rtype(1.0));
+
+ boost::ignore_unused(str, r, cstrategy);
}
};
diff --git a/boost/geometry/strategies/distance_result.hpp b/boost/geometry/strategies/distance_result.hpp
index 185a511464..e4f326d3ee 100644
--- a/boost/geometry/strategies/distance_result.hpp
+++ b/boost/geometry/strategies/distance_result.hpp
@@ -1,13 +1,13 @@
// 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) 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) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2015.
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -100,14 +100,14 @@ struct distance_result
// A set of all variant type combinations that are compatible and
// implemented
typedef typename util::combine_if<
- typename mpl::vector1<Geometry1>,
+ typename boost::mpl::vector1<Geometry1>,
typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
// Here we want should remove most of the combinations that
// are not valid, mostly to limit the size of the resulting MPL set.
// But is_implementedn is not ready for prime time
//
- // util::is_implemented2<mpl::_1, mpl::_2, dispatch::distance<mpl::_1, mpl::_2> >
- mpl::always<mpl::true_>
+ // util::is_implemented2<boost::mpl::_1, boost::mpl::_2, dispatch::distance<boost::mpl::_1, boost::mpl::_2> >
+ boost::mpl::always<boost::mpl::true_>
>::type possible_input_types;
// The (possibly variant) result type resulting from these combinations
@@ -115,11 +115,11 @@ struct distance_result
typename transform_variant<
possible_input_types,
resolve_strategy::distance_result<
- mpl::first<mpl::_>,
- mpl::second<mpl::_>,
+ boost::mpl::first<boost::mpl::_>,
+ boost::mpl::second<boost::mpl::_>,
Strategy
>,
- mpl::back_inserter<mpl::vector0<> >
+ boost::mpl::back_inserter<boost::mpl::vector0<> >
>::type
>::type type;
};
@@ -163,8 +163,8 @@ struct distance_result
// resulting MPL vector.
// But is_implemented is not ready for prime time
//
- // util::is_implemented2<mpl::_1, mpl::_2, dispatch::distance<mpl::_1, mpl::_2> >
- mpl::always<mpl::true_>
+ // util::is_implemented2<boost::mpl::_1, boost::mpl::_2, dispatch::distance<boost::mpl::_1, boost::mpl::_2> >
+ boost::mpl::always<boost::mpl::true_>
>::type possible_input_types;
// The (possibly variant) result type resulting from these combinations
@@ -172,11 +172,11 @@ struct distance_result
typename transform_variant<
possible_input_types,
resolve_strategy::distance_result<
- mpl::first<mpl::_>,
- mpl::second<mpl::_>,
+ boost::mpl::first<boost::mpl::_>,
+ boost::mpl::second<boost::mpl::_>,
Strategy
>,
- mpl::back_inserter<mpl::vector0<> >
+ boost::mpl::back_inserter<boost::mpl::vector0<> >
>::type
>::type type;
};
diff --git a/boost/geometry/strategies/geographic/distance_andoyer.hpp b/boost/geometry/strategies/geographic/distance_andoyer.hpp
new file mode 100644
index 0000000000..64de8c1a41
--- /dev/null
+++ b/boost/geometry/strategies/geographic/distance_andoyer.hpp
@@ -0,0 +1,224 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/radius.hpp>
+#include <boost/geometry/core/srs.hpp>
+
+#include <boost/geometry/algorithms/detail/flattening.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance
+{
+
+
+/*!
+\brief Point-point distance approximation taking flattening into account
+\ingroup distance
+\tparam Spheroid The reference spheroid model
+\tparam CalculationType \tparam_calculation
+\author After Andoyer, 19xx, republished 1950, republished by Meeus, 1999
+\note Although not so well-known, the approximation is very good: in all cases the results
+are about the same as Vincenty. In my (Barend's) testcases the results didn't differ more than 6 m
+\see http://nacc.upc.es/tierra/node16.html
+\see http://sci.tech-archive.net/Archive/sci.geo.satellite-nav/2004-12/2724.html
+\see http://home.att.net/~srschmitt/great_circle_route.html (implementation)
+\see http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115 (implementation)
+\see http://futureboy.homeip.net/frinksamp/navigation.frink (implementation)
+\see http://www.voidware.com/earthdist.htm (implementation)
+*/
+template
+<
+ typename Spheroid,
+ typename CalculationType = void
+>
+class andoyer
+{
+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 andoyer()
+ : m_spheroid()
+ {}
+
+ explicit inline andoyer(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 calc<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)
+ );
+ }
+
+ inline Spheroid const& model() const
+ {
+ return m_spheroid;
+ }
+
+private :
+ template <typename CT, typename T>
+ inline CT calc(T const& lon1,
+ T const& lat1,
+ T const& lon2,
+ T const& lat2) const
+ {
+ CT const G = (lat1 - lat2) / 2.0;
+ CT const lambda = (lon1 - lon2) / 2.0;
+
+ if (geometry::math::equals(lambda, 0.0)
+ && geometry::math::equals(G, 0.0))
+ {
+ return 0.0;
+ }
+
+ CT const F = (lat1 + lat2) / 2.0;
+
+ CT const sinG2 = math::sqr(sin(G));
+ CT const cosG2 = math::sqr(cos(G));
+ CT const sinF2 = math::sqr(sin(F));
+ CT const cosF2 = math::sqr(cos(F));
+ CT const sinL2 = math::sqr(sin(lambda));
+ CT const cosL2 = math::sqr(cos(lambda));
+
+ CT const S = sinG2 * cosL2 + cosF2 * sinL2;
+ CT const C = cosG2 * cosL2 + sinF2 * sinL2;
+
+ CT const c0 = 0;
+ CT const c1 = 1;
+ CT const c2 = 2;
+ CT const c3 = 3;
+
+ if (geometry::math::equals(S, c0) || geometry::math::equals(C, c0))
+ {
+ return c0;
+ }
+
+ CT const radius_a = CT(get_radius<0>(m_spheroid));
+ CT const flattening = geometry::detail::flattening<CT>(m_spheroid);
+
+ CT const omega = atan(math::sqrt(S / C));
+ CT const r3 = c3 * math::sqrt(S * C) / omega; // not sure if this is r or greek nu
+ CT const D = c2 * omega * radius_a;
+ CT const H1 = (r3 - c1) / (c2 * C);
+ CT const H2 = (r3 + c1) / (c2 * S);
+
+ return D * (c1 + flattening * (H1 * sinF2 * cosG2 - H2 * cosF2 * sinG2) );
+ }
+
+ Spheroid m_spheroid;
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Spheroid, typename CalculationType>
+struct tag<andoyer<Spheroid, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>
+struct return_type<andoyer<Spheroid, CalculationType>, P1, P2>
+ : andoyer<Spheroid, CalculationType>::template calculation_type<P1, P2>
+{};
+
+
+template <typename Spheroid, typename CalculationType>
+struct comparable_type<andoyer<Spheroid, CalculationType> >
+{
+ typedef andoyer<Spheroid, CalculationType> type;
+};
+
+
+template <typename Spheroid, typename CalculationType>
+struct get_comparable<andoyer<Spheroid, CalculationType> >
+{
+ static inline andoyer<Spheroid, CalculationType> apply(andoyer<Spheroid, CalculationType> const& input)
+ {
+ return input;
+ }
+};
+
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>
+struct result_from_distance<andoyer<Spheroid, CalculationType>, P1, P2>
+{
+ template <typename T>
+ static inline typename return_type<andoyer<Spheroid, CalculationType>, P1, P2>::type
+ apply(andoyer<Spheroid, CalculationType> const& , T const& value)
+ {
+ return value;
+ }
+};
+
+
+template <typename Point1, typename Point2>
+struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
+{
+ typedef strategy::distance::andoyer
+ <
+ srs::spheroid
+ <
+ typename select_coordinate_type<Point1, Point2>::type
+ >
+ > type;
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
diff --git a/boost/geometry/strategies/geographic/distance_vincenty.hpp b/boost/geometry/strategies/geographic/distance_vincenty.hpp
new file mode 100644
index 0000000000..56dd14bbdc
--- /dev/null
+++ b/boost/geometry/strategies/geographic/distance_vincenty.hpp
@@ -0,0 +1,161 @@
+// 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_GEOGRAPHIC_VINCENTY_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance
+{
+
+/*!
+\brief Distance calculation formulae on latlong coordinates, after Vincenty, 1975
+\ingroup distance
+\tparam Spheroid The reference spheroid model
+\tparam CalculationType \tparam_calculation
+\author See
+ - http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
+ - http://www.icsm.gov.au/gda/gdav2.3.pdf
+\author Adapted from various implementations to get it close to the original document
+ - http://www.movable-type.co.uk/scripts/LatLongVincenty.html
+ - http://exogen.case.edu/projects/geopy/source/geopy.distance.html
+ - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
+
+*/
+template
+<
+ typename Spheroid,
+ typename CalculationType = void
+>
+class vincenty
+{
+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 vincenty()
+ : m_spheroid()
+ {}
+
+ explicit inline vincenty(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::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();
+ }
+
+ 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<vincenty<Spheroid, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>
+struct return_type<vincenty<Spheroid, CalculationType>, P1, P2>
+ : vincenty<Spheroid, CalculationType>::template calculation_type<P1, P2>
+{};
+
+
+template <typename Spheroid, typename CalculationType>
+struct comparable_type<vincenty<Spheroid, CalculationType> >
+{
+ typedef vincenty<Spheroid, CalculationType> type;
+};
+
+
+template <typename Spheroid, typename CalculationType>
+struct get_comparable<vincenty<Spheroid, CalculationType> >
+{
+ static inline vincenty<Spheroid, CalculationType> apply(vincenty<Spheroid, CalculationType> const& input)
+ {
+ return input;
+ }
+};
+
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>
+struct result_from_distance<vincenty<Spheroid, CalculationType>, P1, P2 >
+{
+ template <typename T>
+ static inline typename return_type<vincenty<Spheroid, CalculationType>, P1, P2>::type
+ apply(vincenty<Spheroid, CalculationType> const& , T const& value)
+ {
+ return value;
+ }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+// We might add a vincenty-like strategy also for point-segment distance, but to calculate the projected point is not trivial
+
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP
diff --git a/boost/geometry/strategies/geographic/mapping_ssf.hpp b/boost/geometry/strategies/geographic/mapping_ssf.hpp
new file mode 100644
index 0000000000..3beedc7809
--- /dev/null
+++ b/boost/geometry/strategies/geographic/mapping_ssf.hpp
@@ -0,0 +1,185 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// 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_MAPPING_SSF_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP
+
+
+#include <boost/core/ignore_unused.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/spherical/ssf.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace side
+{
+
+
+// An enumeration type defining types of mapping of geographical
+// latitude to spherical latitude.
+// See: http://en.wikipedia.org/wiki/Great_ellipse
+// http://en.wikipedia.org/wiki/Latitude#Auxiliary_latitudes
+enum mapping_type { mapping_geodetic, mapping_reduced, mapping_geocentric };
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Spheroid, mapping_type Mapping>
+struct mapper
+{
+ explicit inline mapper(Spheroid const& /*spheroid*/) {}
+
+ template <typename CalculationType>
+ static inline CalculationType const& apply(CalculationType const& lat)
+ {
+ return lat;
+ }
+};
+
+template <typename Spheroid>
+struct mapper<Spheroid, mapping_reduced>
+{
+ typedef typename promote_floating_point
+ <
+ typename radius_type<Spheroid>::type
+ >::type fraction_type;
+
+ explicit inline mapper(Spheroid const& spheroid)
+ {
+ fraction_type const a = geometry::get_radius<0>(spheroid);
+ fraction_type const b = geometry::get_radius<2>(spheroid);
+ b_div_a = b / a;
+ }
+
+ template <typename CalculationType>
+ inline CalculationType apply(CalculationType const& lat) const
+ {
+ return atan(static_cast<CalculationType>(b_div_a) * tan(lat));
+ }
+
+ fraction_type b_div_a;
+};
+
+template <typename Spheroid>
+struct mapper<Spheroid, mapping_geocentric>
+{
+ typedef typename promote_floating_point
+ <
+ typename radius_type<Spheroid>::type
+ >::type fraction_type;
+
+ explicit inline mapper(Spheroid const& spheroid)
+ {
+ fraction_type const a = geometry::get_radius<0>(spheroid);
+ fraction_type const b = geometry::get_radius<2>(spheroid);
+ sqr_b_div_a = b / a;
+ sqr_b_div_a *= sqr_b_div_a;
+ }
+
+ template <typename CalculationType>
+ inline CalculationType apply(CalculationType const& lat) const
+ {
+ return atan(static_cast<CalculationType>(sqr_b_div_a) * tan(lat));
+ }
+
+ fraction_type sqr_b_div_a;
+};
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Check at which side of a geographical segment a point lies
+ left of segment (> 0), right of segment (< 0), on segment (0).
+ The check is performed by mapping the geographical coordinates
+ to spherical coordinates and using spherical_side_formula.
+\ingroup strategies
+\tparam Spheroid The reference spheroid model
+\tparam Mapping The type of mapping of geographical to spherical latitude
+\tparam CalculationType \tparam_calculation
+ */
+template <typename Spheroid,
+ mapping_type Mapping = mapping_geodetic,
+ typename CalculationType = void>
+class mapping_spherical_side_formula
+{
+
+public :
+ inline mapping_spherical_side_formula()
+ : m_mapper(Spheroid())
+ {}
+
+ explicit inline mapping_spherical_side_formula(Spheroid const& spheroid)
+ : m_mapper(spheroid)
+ {}
+
+ 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 calculation_type;
+
+ calculation_type lon1 = get_as_radian<0>(p1);
+ calculation_type lat1 = m_mapper.template apply<calculation_type>(get_as_radian<1>(p1));
+ calculation_type lon2 = get_as_radian<0>(p2);
+ calculation_type lat2 = m_mapper.template apply<calculation_type>(get_as_radian<1>(p2));
+ calculation_type lon = get_as_radian<0>(p);
+ calculation_type lat = m_mapper.template apply<calculation_type>(get_as_radian<1>(p));
+
+ return detail::spherical_side_formula(lon1, lat1, lon2, lat2, lon, lat);
+ }
+
+private:
+ side::detail::mapper<Spheroid, Mapping> const m_mapper;
+};
+
+// The specialization for geodetic latitude which can be used directly
+template <typename Spheroid,
+ typename CalculationType>
+class mapping_spherical_side_formula<Spheroid, mapping_geodetic, CalculationType>
+{
+
+public :
+ inline mapping_spherical_side_formula() {}
+ explicit inline mapping_spherical_side_formula(Spheroid const& /*spheroid*/) {}
+
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ return spherical_side_formula<CalculationType>::apply(p1, p2, p);
+ }
+};
+
+}} // namespace strategy::side
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP
diff --git a/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp
index a40f03dbaf..486c7effbd 100644
--- a/boost/geometry/strategies/spherical/distance_cross_track.hpp
+++ b/boost/geometry/strategies/spherical/distance_cross_track.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// 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,15 +14,17 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
+#include <algorithm>
#include <boost/config.hpp>
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/is_void.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/course.hpp>
@@ -25,39 +32,297 @@
#include <boost/geometry/strategies/concepts/distance_concept.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
# include <boost/geometry/io/dsv/write.hpp>
#endif
-
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
-/*!
-\brief Strategy functor for distance point to segment calculation
-\ingroup strategies
-\details Class which calculates the distance of a point to a segment, for points on a sphere or globe
-\see http://williams.best.vwh.net/avform.htm
-\tparam CalculationType \tparam_calculation
-\tparam Strategy underlying point-point distance strategy, defaults to haversine
-\qbk{
-[heading See also]
-[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
-}
+namespace comparable
+{
+/*
+ Given a spherical segment AB and a point D, we are interested in
+ computing the distance of D from AB. This is usually known as the
+ cross track distance.
+
+ If the projection (along great circles) of the point D lies inside
+ the segment AB, then the distance (cross track error) XTD is given
+ by the formula (see http://williams.best.vwh.net/avform.htm#XTE):
+
+ XTD = asin( sin(dist_AD) * sin(crs_AD-crs_AB) )
+
+ where dist_AD is the great circle distance between the points A and
+ B, and crs_AD, crs_AB is the course (bearing) between the points A,
+ D and A, B, respectively.
+
+ If the point D does not project inside the arc AB, then the distance
+ of D from AB is the minimum of the two distances dist_AD and dist_BD.
+
+ Our reference implementation for this procedure is listed below
+ (this was the old Boost.Geometry implementation of the cross track distance),
+ where:
+ * The member variable m_strategy is the underlying haversine strategy.
+ * p stands for the point D.
+ * sp1 stands for the segment endpoint A.
+ * sp2 stands for the segment endpoint B.
+
+ ================= reference implementation -- start =================
+
+ return_type d1 = m_strategy.apply(sp1, p);
+ return_type d3 = m_strategy.apply(sp1, sp2);
+
+ if (geometry::math::equals(d3, 0.0))
+ {
+ // "Degenerate" segment, return either d1 or d2
+ return d1;
+ }
+
+ return_type d2 = m_strategy.apply(sp2, p);
+
+ return_type crs_AD = geometry::detail::course<return_type>(sp1, p);
+ return_type crs_AB = geometry::detail::course<return_type>(sp1, sp2);
+ return_type crs_BA = crs_AB - geometry::math::pi<return_type>();
+ return_type crs_BD = geometry::detail::course<return_type>(sp2, p);
+ return_type d_crs1 = crs_AD - crs_AB;
+ return_type d_crs2 = crs_BD - crs_BA;
+
+ // d1, d2, d3 are in principle not needed, only the sign matters
+ return_type projection1 = cos( d_crs1 ) * d1 / d3;
+ return_type projection2 = cos( d_crs2 ) * d2 / d3;
+
+ if (projection1 > 0.0 && projection2 > 0.0)
+ {
+ return_type XTD
+ = radius() * math::abs( asin( sin( d1 / radius() ) * sin( d_crs1 ) ));
+
+ // Return shortest distance, projected point on segment sp1-sp2
+ return return_type(XTD);
+ }
+ else
+ {
+ // Return shortest distance, project either on point sp1 or sp2
+ return return_type( (std::min)( d1 , d2 ) );
+ }
+
+ ================= reference implementation -- end =================
+
+
+ Motivation
+ ----------
+ In what follows we develop a comparable version of the cross track
+ distance strategy, that meets the following goals:
+ * It is more efficient than the original cross track strategy (less
+ operations and less calls to mathematical functions).
+ * Distances using the comparable cross track strategy can not only
+ be compared with other distances using the same strategy, but also with
+ distances computed with the comparable version of the haversine strategy.
+ * It can serve as the basis for the computation of the cross track distance,
+ as it is more efficient to compute its comparable version and
+ transform that to the actual cross track distance, rather than
+ follow/use the reference implementation listed above.
+
+ Major idea
+ ----------
+ The idea here is to use the comparable haversine strategy to compute
+ the distances d1, d2 and d3 in the above listing. Once we have done
+ that we need also to make sure that instead of returning XTD (as
+ computed above) that we return a distance CXTD that is compatible
+ with the comparable haversine distance. To achieve this CXTD must satisfy
+ the relation:
+ XTD = 2 * R * asin( sqrt(XTD) )
+ where R is the sphere's radius.
+
+ Below we perform the mathematical analysis that show how to compute CXTD.
+
+
+ Mathematical analysis
+ ---------------------
+ Below we use the following trigonometric identities:
+ sin(2 * x) = 2 * sin(x) * cos(x)
+ cos(asin(x)) = sqrt(1 - x^2)
+
+ Observation:
+ The distance d1 needed when the projection of the point D is within the
+ segment must be the true distance. However, comparable::haversine<>
+ returns a comparable distance instead of the one needed.
+ To remedy this, we implicitly compute what is needed.
+ More precisely, we need to compute sin(true_d1):
+
+ sin(true_d1) = sin(2 * asin(sqrt(d1)))
+ = 2 * sin(asin(sqrt(d1)) * cos(asin(sqrt(d1)))
+ = 2 * sqrt(d1) * sqrt(1-(sqrt(d1))^2)
+ = 2 * sqrt(d1 - d1 * d1)
+ This relation is used below.
+
+ As we mentioned above the goal is to find CXTD (named "a" below for
+ brevity) such that ("b" below stands for "d1", and "c" for "d_crs1"):
+
+ 2 * R * asin(sqrt(a)) == R * asin(2 * sqrt(b-b^2) * sin(c))
+
+ Analysis:
+ 2 * R * asin(sqrt(a)) == R * asin(2 * sqrt(b-b^2) * sin(c))
+ <=> 2 * asin(sqrt(a)) == asin(sqrt(b-b^2) * sin(c))
+ <=> sin(2 * asin(sqrt(a))) == 2 * sqrt(b-b^2) * sin(c)
+ <=> 2 * sin(asin(sqrt(a))) * cos(asin(sqrt(a))) == 2 * sqrt(b-b^2) * sin(c)
+ <=> 2 * sqrt(a) * sqrt(1-a) == 2 * sqrt(b-b^2) * sin(c)
+ <=> sqrt(a) * sqrt(1-a) == sqrt(b-b^2) * sin(c)
+ <=> sqrt(a-a^2) == sqrt(b-b^2) * sin(c)
+ <=> a-a^2 == (b-b^2) * (sin(c))^2
+
+ Consider the quadratic equation: x^2-x+p^2 == 0,
+ where p = sqrt(b-b^2) * sin(c); its discriminant is:
+ d = 1 - 4 * p^2 = 1 - 4 * (b-b^2) * (sin(c))^2
+
+ The two solutions are:
+ a_1 = (1 - sqrt(d)) / 2
+ a_2 = (1 + sqrt(d)) / 2
+
+ Which one to choose?
+ "a" refers to the distance (on the unit sphere) of D from the
+ supporting great circle Circ(A,B) of the segment AB.
+ The two different values for "a" correspond to the lengths of the two
+ arcs delimited D and the points of intersection of Circ(A,B) and the
+ great circle perperdicular to Circ(A,B) passing through D.
+ Clearly, the value we want is the smallest among these two distances,
+ hence the root we must choose is the smallest root among the two.
+
+ So the answer is:
+ CXTD = ( 1 - sqrt(1 - 4 * (b-b^2) * (sin(c))^2) ) / 2
+
+ Therefore, in order to implement the comparable version of the cross
+ track strategy we need to:
+ (1) Use the comparable version of the haversine strategy instead of
+ the non-comparable one.
+ (2) Instead of return XTD when D projects inside the segment AB, we
+ need to return CXTD, given by the following formula:
+ CXTD = ( 1 - sqrt(1 - 4 * (d1-d1^2) * (sin(d_crs1))^2) ) / 2;
+
+
+ Complexity Analysis
+ -------------------
+ In the analysis that follows we refer to the actual implementation below.
+ In particular, instead of computing CXTD as above, we use the more
+ efficient (operation-wise) computation of CXTD shown here:
+
+ return_type sin_d_crs1 = sin(d_crs1);
+ return_type d1_x_sin = d1 * sin_d_crs1;
+ return_type d = d1_x_sin * (sin_d_crs1 - d1_x_sin);
+ return d / (0.5 + math::sqrt(0.25 - d));
+
+ Notice that instead of computing:
+ 0.5 - 0.5 * sqrt(1 - 4 * d) = 0.5 - sqrt(0.25 - d)
+ we use the following formula instead:
+ d / (0.5 + sqrt(0.25 - d)).
+ This is done for numerical robustness. The expression 0.5 - sqrt(0.25 - x)
+ has large numerical errors for values of x close to 0 (if using doubles
+ the error start to become large even when d is as large as 0.001).
+ To remedy that, we re-write 0.5 - sqrt(0.25 - x) as:
+ 0.5 - sqrt(0.25 - d)
+ = (0.5 - sqrt(0.25 - d) * (0.5 - sqrt(0.25 - d)) / (0.5 + sqrt(0.25 - d)).
+ The numerator is the difference of two squares:
+ (0.5 - sqrt(0.25 - d) * (0.5 - sqrt(0.25 - d))
+ = 0.5^2 - (sqrt(0.25 - d))^ = 0.25 - (0.25 - d) = d,
+ which gives the expression we use.
+
+ For the complexity analysis, we distinguish between two cases:
+ (A) The distance is realized between the point D and an
+ endpoint of the segment AB
+
+ Gains:
+ Since we are using comparable::haversine<> which is called
+ 3 times, we gain:
+ -> 3 calls to sqrt
+ -> 3 calls to asin
+ -> 6 multiplications
+
+ Loses: None
+
+ So the net gain is:
+ -> 6 function calls (sqrt/asin)
+ -> 6 arithmetic operations
+
+ If we use comparable::cross_track<> to compute
+ cross_track<> we need to account for a call to sqrt, a call
+ to asin and 2 multiplications. In this case the net gain is:
+ -> 4 function calls (sqrt/asin)
+ -> 4 arithmetic operations
+
+
+ (B) The distance is realized between the point D and an
+ interior point of the segment AB
+
+ Gains:
+ Since we are using comparable::haversine<> which is called
+ 3 times, we gain:
+ -> 3 calls to sqrt
+ -> 3 calls to asin
+ -> 6 multiplications
+ Also we gain the operations used to compute XTD:
+ -> 2 calls to sin
+ -> 1 call to asin
+ -> 1 call to abs
+ -> 2 multiplications
+ -> 1 division
+ So the total gains are:
+ -> 9 calls to sqrt/sin/asin
+ -> 1 call to abs
+ -> 8 multiplications
+ -> 1 division
+
+ Loses:
+ To compute a distance compatible with comparable::haversine<>
+ we need to perform a few more operations, namely:
+ -> 1 call to sin
+ -> 1 call to sqrt
+ -> 2 multiplications
+ -> 1 division
+ -> 1 addition
+ -> 2 subtractions
+
+ So roughly speaking the net gain is:
+ -> 8 fewer function calls and 3 fewer arithmetic operations
+
+ If we were to implement cross_track directly from the
+ comparable version (much like what haversine<> does using
+ comparable::haversine<>) we need additionally
+ -> 2 function calls (asin/sqrt)
+ -> 2 multiplications
+
+ So it pays off to re-implement cross_track<> to use
+ comparable::cross_track<>; in this case the net gain would be:
+ -> 6 function calls
+ -> 1 arithmetic operation
+
+ Summary/Conclusion
+ ------------------
+ Following the mathematical and complexity analysis above, the
+ comparable cross track strategy (as implemented below) satisfies
+ all the goal mentioned in the beginning:
+ * It is more efficient than its non-comparable counter-part.
+ * Comparable distances using this new strategy can also be compared
+ with comparable distances computed with the comparable haversine
+ strategy.
+ * It turns out to be more efficient to compute the actual cross
+ track distance XTD by first computing CXTD, and then computing
+ XTD by means of the formula:
+ XTD = 2 * R * asin( sqrt(CXTD) )
*/
+
template
<
typename CalculationType = void,
- typename Strategy = haversine<double, CalculationType>
+ typename Strategy = comparable::haversine<double, CalculationType>
>
class cross_track
{
@@ -106,6 +371,14 @@ 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;
+#endif
+
// http://williams.best.vwh.net/avform.htm#XTE
return_type d1 = m_strategy.apply(sp1, p);
return_type d3 = m_strategy.apply(sp1, sp2);
@@ -129,25 +402,34 @@ public :
return_type projection1 = cos( d_crs1 ) * d1 / d3;
return_type projection2 = cos( d_crs2 ) * d2 / d3;
-#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;
-#endif
-
- if(projection1 > 0.0 && projection2 > 0.0)
+ if (projection1 > 0.0 && projection2 > 0.0)
{
- return_type XTD = radius() * geometry::math::abs( asin( sin( d1 / radius() ) * sin( d_crs1 ) ));
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+ return_type XTD = radius() * geometry::math::abs( asin( sin( d1 ) * sin( d_crs1 ) ));
- #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Projection ON the segment" << std::endl;
- std::cout << "XTD: " << XTD << " d1: " << d1 << " d2: " << d2 << std::endl;
+ std::cout << "XTD: " << XTD
+ << " d1: " << (d1 * radius())
+ << " d2: " << (d2 * radius())
+ << std::endl;
#endif
-
- // Return shortest distance, projected point on segment sp1-sp2
- return return_type(XTD);
+ return_type const half(0.5);
+ return_type const quarter(0.25);
+
+ return_type sin_d_crs1 = sin(d_crs1);
+ /*
+ This is the straightforward obvious way to continue:
+
+ return_type discriminant
+ = 1.0 - 4.0 * (d1 - d1 * d1) * sin_d_crs1 * sin_d_crs1;
+ return 0.5 - 0.5 * math::sqrt(discriminant);
+
+ Below we optimize the number of arithmetic operations
+ and account for numerical robustness:
+ */
+ return_type d1_x_sin = d1 * sin_d_crs1;
+ return_type d = d1_x_sin * (sin_d_crs1 - d1_x_sin);
+ return d / (half + math::sqrt(quarter - d));
}
else
{
@@ -164,6 +446,95 @@ public :
{ return m_strategy.radius(); }
private :
+ Strategy m_strategy;
+};
+
+} // namespace comparable
+
+
+/*!
+\brief Strategy functor for distance point to segment calculation
+\ingroup strategies
+\details Class which calculates the distance of a point to a segment, for points on a sphere or globe
+\see http://williams.best.vwh.net/avform.htm
+\tparam CalculationType \tparam_calculation
+\tparam Strategy underlying point-point distance strategy, defaults to haversine
+
+\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>
+>
+class cross_track
+{
+public :
+ template <typename Point, typename PointOfSegment>
+ struct return_type
+ : promote_floating_point
+ <
+ typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type
+ >
+ {};
+
+ inline cross_track()
+ {}
+
+ explicit inline cross_track(typename Strategy::radius_type const& r)
+ : m_strategy(r)
+ {}
+
+ inline cross_track(Strategy const& s)
+ : m_strategy(s)
+ {}
+
+
+ // It might be useful in the future
+ // to overload constructor with strategy info.
+ // crosstrack(...) {}
+
+
+ template <typename Point, typename PointOfSegment>
+ inline typename return_type<Point, PointOfSegment>::type
+ apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const
+ {
+
+#if !defined(BOOST_MSVC)
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::PointDistanceStrategy<Strategy, Point, PointOfSegment>)
+ );
+#endif
+ typedef typename return_type<Point, PointOfSegment>::type return_type;
+ typedef cross_track<CalculationType, Strategy> this_type;
+
+ typedef typename services::comparable_type
+ <
+ this_type
+ >::type comparable_type;
+
+ comparable_type cstrategy
+ = services::get_comparable<this_type>::apply(m_strategy);
+
+ return_type const a = cstrategy.apply(p, sp1, sp2);
+ return_type const c = return_type(2.0) * asin(math::sqrt(a));
+ return c * radius();
+ }
+
+ inline typename Strategy::radius_type radius() const
+ { return m_strategy.radius(); }
+
+private :
Strategy m_strategy;
};
@@ -190,8 +561,10 @@ struct return_type<cross_track<CalculationType, Strategy>, P, PS>
template <typename CalculationType, typename Strategy>
struct comparable_type<cross_track<CalculationType, Strategy> >
{
- // There is no shortcut, so the strategy itself is its comparable type
- typedef cross_track<CalculationType, Strategy> type;
+ typedef comparable::cross_track
+ <
+ CalculationType, typename comparable_type<Strategy>::type
+ > type;
};
@@ -207,7 +580,8 @@ struct get_comparable<cross_track<CalculationType, Strategy> >
cross_track<CalculationType, Strategy>
>::type comparable_type;
public :
- static inline comparable_type apply(cross_track<CalculationType, Strategy> const& strategy)
+ static inline comparable_type
+ apply(cross_track<CalculationType, Strategy> const& strategy)
{
return comparable_type(strategy.radius());
}
@@ -218,21 +592,95 @@ template
<
typename CalculationType,
typename Strategy,
- typename P, typename PS
+ typename P,
+ typename PS
>
struct result_from_distance<cross_track<CalculationType, Strategy>, P, PS>
{
private :
- typedef typename cross_track<CalculationType, Strategy>::template return_type<P, PS> return_type;
+ typedef typename cross_track
+ <
+ CalculationType, Strategy
+ >::template return_type<P, PS>::type return_type;
public :
template <typename T>
- static inline return_type apply(cross_track<CalculationType, Strategy> const& , T const& distance)
+ static inline return_type
+ apply(cross_track<CalculationType, Strategy> const& , T const& distance)
{
return distance;
}
};
+// Specializations for comparable::cross_track
+template <typename RadiusType, typename CalculationType>
+struct tag<comparable::cross_track<RadiusType, CalculationType> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
+
+
+template
+<
+ typename RadiusType,
+ typename CalculationType,
+ typename P,
+ typename PS
+>
+struct return_type<comparable::cross_track<RadiusType, CalculationType>, P, PS>
+ : comparable::cross_track
+ <
+ RadiusType, CalculationType
+ >::template return_type<P, PS>
+{};
+
+
+template <typename RadiusType, typename CalculationType>
+struct comparable_type<comparable::cross_track<RadiusType, CalculationType> >
+{
+ typedef comparable::cross_track<RadiusType, CalculationType> type;
+};
+
+
+template <typename RadiusType, typename CalculationType>
+struct get_comparable<comparable::cross_track<RadiusType, CalculationType> >
+{
+private :
+ typedef comparable::cross_track<RadiusType, CalculationType> this_type;
+public :
+ static inline this_type apply(this_type const& input)
+ {
+ return input;
+ }
+};
+
+
+template
+<
+ typename RadiusType,
+ typename CalculationType,
+ typename P,
+ typename PS
+>
+struct result_from_distance
+ <
+ comparable::cross_track<RadiusType, CalculationType>, P, PS
+ >
+{
+private :
+ typedef comparable::cross_track<RadiusType, CalculationType> strategy_type;
+ typedef typename return_type<strategy_type, P, PS>::type return_type;
+public :
+ template <typename T>
+ static inline return_type apply(strategy_type const& strategy,
+ T const& distance)
+ {
+ return_type const s
+ = sin( (distance / strategy.radius()) / return_type(2.0) );
+ return s * s;
+ }
+};
+
/*
@@ -309,17 +757,8 @@ struct default_strategy
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
}} // namespace strategy::distance
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-
-
-#endif
-
-
}} // namespace boost::geometry
-
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
diff --git a/boost/geometry/strategies/spherical/distance_haversine.hpp b/boost/geometry/strategies/spherical/distance_haversine.hpp
index 8db29c5157..8b32056f3e 100644
--- a/boost/geometry/strategies/spherical/distance_haversine.hpp
+++ b/boost/geometry/strategies/spherical/distance_haversine.hpp
@@ -158,7 +158,7 @@ public :
typedef typename calculation_type<Point1, Point2>::type calculation_type;
calculation_type const a = comparable_type::apply(p1, p2);
calculation_type const c = calculation_type(2.0) * asin(math::sqrt(a));
- return m_radius * c;
+ return calculation_type(m_radius) * c;
}
/*!
diff --git a/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/boost/geometry/strategies/spherical/side_by_cross_track.hpp
index c4c5f24eeb..3f7be05557 100644
--- a/boost/geometry/strategies/spherical/side_by_cross_track.hpp
+++ b/boost/geometry/strategies/spherical/side_by_cross_track.hpp
@@ -2,6 +2,11 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,18 +14,15 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_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/course.hpp>
-#include <boost/geometry/util/select_coordinate_type.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>
@@ -47,27 +49,19 @@ public :
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
- typedef typename boost::mpl::if_c
+ typedef typename promote_floating_point
<
- boost::is_void<CalculationType>::type::value,
- typename select_most_precise
+ typename select_calculation_type_alt
<
- typename select_most_precise
- <
- typename coordinate_type<P1>::type,
- typename coordinate_type<P2>::type
- >::type,
- typename coordinate_type<P>::type
- >::type,
- CalculationType
- >::type coordinate_type;
-
- boost::ignore_unused<coordinate_type>();
-
- double d1 = 0.001; // m_strategy.apply(sp1, p);
- double crs_AD = geometry::detail::course<double>(p1, p);
- double crs_AB = geometry::detail::course<double>(p1, p2);
- double XTD = asin(sin(d1) * sin(crs_AD - crs_AB));
+ CalculationType,
+ P1, P2, P
+ >::type
+ >::type calc_t;
+
+ calc_t d1 = 0.001; // m_strategy.apply(sp1, p);
+ calc_t crs_AD = geometry::detail::course<calc_t>(p1, p);
+ calc_t crs_AB = geometry::detail::course<calc_t>(p1, p2);
+ calc_t XTD = asin(sin(d1) * sin(crs_AD - crs_AB));
return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1;
}
diff --git a/boost/geometry/strategies/spherical/ssf.hpp b/boost/geometry/strategies/spherical/ssf.hpp
index 41562950fd..81f3205e90 100644
--- a/boost/geometry/strategies/spherical/ssf.hpp
+++ b/boost/geometry/strategies/spherical/ssf.hpp
@@ -16,8 +16,9 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
-#include <boost/geometry/util/select_coordinate_type.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>
@@ -30,6 +31,43 @@ namespace boost { namespace geometry
namespace strategy { namespace side
{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename T>
+int spherical_side_formula(T const& lambda1, T const& delta1,
+ T const& lambda2, T const& delta2,
+ T const& lambda, T const& delta)
+{
+ // Create temporary points (vectors) on unit a sphere
+ T const cos_delta1 = cos(delta1);
+ T const c1x = cos_delta1 * cos(lambda1);
+ T const c1y = cos_delta1 * sin(lambda1);
+ T const c1z = sin(delta1);
+
+ T const cos_delta2 = cos(delta2);
+ T const c2x = cos_delta2 * cos(lambda2);
+ T const c2y = cos_delta2 * sin(lambda2);
+ T const c2z = sin(delta2);
+
+ // (Third point is converted directly)
+ T const cos_delta = cos(delta);
+
+ // Apply the "Spherical Side Formula" as presented on my blog
+ T const dist
+ = (c1y * c2z - c1z * c2y) * cos_delta * cos(lambda)
+ + (c1z * c2x - c1x * c2z) * cos_delta * sin(lambda)
+ + (c1x * c2y - c1y * c2x) * sin(delta);
+
+ T zero = T();
+ return dist > zero ? 1
+ : dist < zero ? -1
+ : 0;
+}
+
+}
+#endif // DOXYGEN_NO_DETAIL
/*!
\brief Check at which side of a Great Circle segment a point lies
@@ -45,60 +83,25 @@ public :
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
- typedef typename boost::mpl::if_c
+ typedef typename promote_floating_point
<
- boost::is_void<CalculationType>::type::value,
-
- // Select at least a double...
- typename select_most_precise
+ typename select_calculation_type_alt
<
- typename select_most_precise
- <
- typename select_most_precise
- <
- typename coordinate_type<P1>::type,
- typename coordinate_type<P2>::type
- >::type,
- typename coordinate_type<P>::type
- >::type,
- double
- >::type,
- CalculationType
- >::type coordinate_type;
-
- // Convenient shortcuts
- typedef coordinate_type ct;
- ct const lambda1 = get_as_radian<0>(p1);
- ct const delta1 = get_as_radian<1>(p1);
- ct const lambda2 = get_as_radian<0>(p2);
- ct const delta2 = get_as_radian<1>(p2);
- ct const lambda = get_as_radian<0>(p);
- ct const delta = get_as_radian<1>(p);
-
- // Create temporary points (vectors) on unit a sphere
- ct const cos_delta1 = cos(delta1);
- ct const c1x = cos_delta1 * cos(lambda1);
- ct const c1y = cos_delta1 * sin(lambda1);
- ct const c1z = sin(delta1);
-
- ct const cos_delta2 = cos(delta2);
- ct const c2x = cos_delta2 * cos(lambda2);
- ct const c2y = cos_delta2 * sin(lambda2);
- ct const c2z = sin(delta2);
-
- // (Third point is converted directly)
- ct const cos_delta = cos(delta);
-
- // Apply the "Spherical Side Formula" as presented on my blog
- ct const dist
- = (c1y * c2z - c1z * c2y) * cos_delta * cos(lambda)
- + (c1z * c2x - c1x * c2z) * cos_delta * sin(lambda)
- + (c1x * c2y - c1y * c2x) * sin(delta);
-
- ct zero = ct();
- return dist > zero ? 1
- : dist < zero ? -1
- : 0;
+ CalculationType,
+ P1, P2, P
+ >::type
+ >::type calculation_type;
+
+ calculation_type const lambda1 = get_as_radian<0>(p1);
+ calculation_type const delta1 = get_as_radian<1>(p1);
+ calculation_type const lambda2 = get_as_radian<0>(p2);
+ calculation_type const delta2 = get_as_radian<1>(p2);
+ calculation_type const lambda = get_as_radian<0>(p);
+ calculation_type const delta = get_as_radian<1>(p);
+
+ return detail::spherical_side_formula(lambda1, delta1,
+ lambda2, delta2,
+ lambda, delta);
}
};
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
index afc5d7046f..bf436dba2b 100644
--- a/boost/geometry/strategies/strategies.hpp
+++ b/boost/geometry/strategies/strategies.hpp
@@ -63,6 +63,9 @@
#include <boost/geometry/strategies/spherical/compare_circular.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
+#include <boost/geometry/strategies/geographic/distance_andoyer.hpp>
+#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
+
#include <boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp>
#include <boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp>
#include <boost/geometry/strategies/agnostic/hull_graham_andrew.hpp>
diff --git a/boost/geometry/util/combine_if.hpp b/boost/geometry/util/combine_if.hpp
index 6d8d932a1c..cfc3449267 100644
--- a/boost/geometry/util/combine_if.hpp
+++ b/boost/geometry/util/combine_if.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
+// 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.
@@ -36,16 +41,16 @@ namespace util
\ingroup utility
\par Example
\code
- typedef mpl::vector<mpl::int_<0>, mpl::int_<1> > types;
+ typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<1> > types;
typedef combine_if<types, types, always<true_> >::type combinations;
- typedef mpl::vector<
- pair<mpl::int_<1>, mpl::int_<1> >,
- pair<mpl::int_<1>, mpl::int_<0> >,
- pair<mpl::int_<0>, mpl::int_<1> >,
- pair<mpl::int_<0>, mpl::int_<0> >
+ typedef boost::mpl::vector<
+ pair<boost::mpl::int_<1>, boost::mpl::int_<1> >,
+ pair<boost::mpl::int_<1>, boost::mpl::int_<0> >,
+ pair<boost::mpl::int_<0>, boost::mpl::int_<1> >,
+ pair<boost::mpl::int_<0>, boost::mpl::int_<0> >
> result_types;
- BOOST_MPL_ASSERT(( mpl::equal<combinations, result_types> ));
+ BOOST_MPL_ASSERT(( boost::mpl::equal<combinations, result_types> ));
\endcode
*/
template <typename Sequence1, typename Sequence2, typename Pred>
@@ -56,18 +61,29 @@ struct combine_if
template <typename Result, typename T>
struct apply
{
- typedef typename mpl::fold<Sequence2, Result,
- mpl::if_
+ typedef typename boost::mpl::fold<Sequence2, Result,
+ boost::mpl::if_
<
- mpl::bind<typename mpl::lambda<Pred>::type, T, mpl::_2>,
- mpl::insert<mpl::_1, mpl::pair<T, mpl::_2> >,
- mpl::_1
+ boost::mpl::bind
+ <
+ typename boost::mpl::lambda<Pred>::type,
+ T,
+ boost::mpl::_2
+ >,
+ boost::mpl::insert
+ <
+ boost::mpl::_1, boost::mpl::pair<T, boost::mpl::_2>
+ >,
+ boost::mpl::_1
>
>::type type;
};
};
- typedef typename mpl::fold<Sequence1, mpl::set0<>, combine>::type type;
+ typedef typename boost::mpl::fold
+ <
+ Sequence1, boost::mpl::set0<>, combine
+ >::type type;
};
diff --git a/boost/geometry/util/compress_variant.hpp b/boost/geometry/util/compress_variant.hpp
index a94cf28894..363385965d 100644
--- a/boost/geometry/util/compress_variant.hpp
+++ b/boost/geometry/util/compress_variant.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.
@@ -36,28 +41,31 @@ namespace detail
template <typename Variant>
struct unique_types:
- mpl::fold<
- typename mpl::reverse_fold<
+ boost::mpl::fold<
+ typename boost::mpl::reverse_fold<
typename Variant::types,
- mpl::set<>,
- mpl::insert<
- mpl::placeholders::_1,
- mpl::placeholders::_2
+ boost::mpl::set<>,
+ boost::mpl::insert<
+ boost::mpl::placeholders::_1,
+ boost::mpl::placeholders::_2
>
>::type,
- mpl::vector<>,
- mpl::push_back<mpl::placeholders::_1, mpl::placeholders::_2>
+ boost::mpl::vector<>,
+ boost::mpl::push_back
+ <
+ boost::mpl::placeholders::_1, boost::mpl::placeholders::_2
+ >
>
{};
template <typename Types>
struct variant_or_single:
- mpl::if_<
- mpl::equal_to<
- mpl::size<Types>,
- mpl::int_<1>
+ boost::mpl::if_<
+ boost::mpl::equal_to<
+ boost::mpl::size<Types>,
+ boost::mpl::int_<1>
>,
- typename mpl::front<Types>::type,
+ typename boost::mpl::front<Types>::type,
typename make_variant_over<Types>::type
>
{};
@@ -75,8 +83,8 @@ struct variant_or_single:
\code
typedef variant<int, float, int, long> variant_type;
typedef compress_variant<variant_type>::type compressed;
- typedef mpl::vector<int, float, long> result_types;
- BOOST_MPL_ASSERT(( mpl::equal<compressed::types, result_types> ));
+ typedef boost::mpl::vector<int, float, long> result_types;
+ BOOST_MPL_ASSERT(( boost::mpl::equal<compressed::types, result_types> ));
typedef variant<int, int, int> one_type_variant_type;
typedef compress_variant<one_type_variant_type>::type single_type;
diff --git a/boost/geometry/util/condition.hpp b/boost/geometry/util/condition.hpp
new file mode 100644
index 0000000000..aea4ad3ad1
--- /dev/null
+++ b/boost/geometry/util/condition.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_UTIL_CONDITION_HPP
+#define BOOST_GEOMETRY_UTIL_CONDITION_HPP
+
+
+#include <boost/config.hpp>
+
+
+// The macro defined in this file allows to suppress the MSVC
+// compiler warning C4127: conditional expression is constant
+
+#ifdef BOOST_MSVC
+
+// NOTE: The code commented out below contains an alternative implementation
+// of a macro using a free function. It was left here in case if in the future
+// version of MSVC for the code currently used in the macro implementation
+// the warning was generated.
+
+//#ifndef DOXYGEN_NO_DETAIL
+//namespace boost { namespace geometry { namespace detail {
+//BOOST_FORCEINLINE bool condition(bool const b) { return b; }
+//}}} // boost::geometry::detail
+//#endif // DOXYGEN_NO_DETAIL
+//#define BOOST_GEOMETRY_CONDITION(CONDITION) boost::geometry::detail::condition(CONDITION)
+
+#define BOOST_GEOMETRY_CONDITION(CONDITION) ((void)0, (CONDITION))
+
+#else
+
+#define BOOST_GEOMETRY_CONDITION(CONDITION) (CONDITION)
+
+#endif
+
+
+#endif // BOOST_GEOMETRY_UTIL_CONDITION_HPP
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
index 22c02168ad..4042f4e4cd 100644
--- a/boost/geometry/util/math.hpp
+++ b/boost/geometry/util/math.hpp
@@ -1,11 +1,11 @@
// 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) 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.
-// 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
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,7 +23,12 @@
#include <cmath>
#include <limits>
+#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/numeric/conversion/cast.hpp>
#include <boost/type_traits/is_fundamental.hpp>
@@ -40,11 +45,104 @@ namespace math
namespace detail
{
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2)
+{
+ return (std::max)(v1, v2);
+}
+
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2, T const& v3)
+{
+ return (std::max)(greatest(v1, v2), v3);
+}
+
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
+{
+ return (std::max)(greatest(v1, v2, v3), v4);
+}
+
+template <typename T>
+inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
+{
+ return (std::max)(greatest(v1, v2, v3, v4), v5);
+}
+
+
+template <typename T,
+ bool IsFloatingPoint = boost::is_floating_point<T>::value>
+struct abs
+{
+ static inline T apply(T const& value)
+ {
+ T const zero = T();
+ return value < zero ? -value : value;
+ }
+};
+
+template <typename T>
+struct abs<T, true>
+{
+ static inline T apply(T const& value)
+ {
+ return fabs(value);
+ }
+};
+
+
+struct equals_default_policy
+{
+ template <typename T>
+ static inline T apply(T const& a, T const& b)
+ {
+ // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
+ return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
+ }
+};
+
+template <typename T,
+ bool IsFloatingPoint = boost::is_floating_point<T>::value>
+struct equals_factor_policy
+{
+ equals_factor_policy()
+ : factor(1) {}
+ explicit equals_factor_policy(T const& v)
+ : factor(greatest(abs<T>::apply(v), T(1)))
+ {}
+ equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
+ : factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
+ abs<T>::apply(v2), abs<T>::apply(v3),
+ T(1)))
+ {}
+
+ T const& apply(T const&, T const&) const
+ {
+ return factor;
+ }
+
+ T factor;
+};
+
+template <typename T>
+struct equals_factor_policy<T, false>
+{
+ equals_factor_policy() {}
+ explicit equals_factor_policy(T const&) {}
+ equals_factor_policy(T const& , T const& , T const& , T const& ) {}
+
+ static inline T apply(T const&, T const&)
+ {
+ return T(1);
+ }
+};
-template <typename Type, bool IsFloatingPoint>
+template <typename Type,
+ bool IsFloatingPoint = boost::is_floating_point<Type>::value>
struct equals
{
- static inline bool apply(Type const& a, Type const& b)
+ template <typename Policy>
+ static inline bool apply(Type const& a, Type const& b, Policy const&)
{
return a == b;
}
@@ -53,25 +151,31 @@ struct equals
template <typename Type>
struct equals<Type, true>
{
- static inline Type get_max(Type const& a, Type const& b, Type const& c)
+ template <typename Policy>
+ static inline bool apply(Type const& a, Type const& b, Policy const& policy)
{
- return (std::max)((std::max)(a, b), c);
- }
+ boost::ignore_unused(policy);
- static inline bool apply(Type const& a, Type const& b)
- {
if (a == b)
{
return true;
}
- // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17,
- // FUTURE: replace by some boost tool or boost::test::close_at_tolerance
- return std::abs(a - b) <= std::numeric_limits<Type>::epsilon() * get_max(std::abs(a), std::abs(b), 1.0);
+ return abs<Type>::apply(a - b) <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
}
};
-template <typename Type, bool IsFloatingPoint>
+template <typename T1, typename T2, typename Policy>
+inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
+{
+ return detail::equals
+ <
+ typename select_most_precise<T1, T2>::type
+ >::apply(a, b, policy);
+}
+
+template <typename Type,
+ bool IsFloatingPoint = boost::is_floating_point<Type>::value>
struct smaller
{
static inline bool apply(Type const& a, Type const& b)
@@ -85,7 +189,7 @@ struct smaller<Type, true>
{
static inline bool apply(Type const& a, Type const& b)
{
- if (equals<Type, true>::apply(a, b))
+ if (equals<Type, true>::apply(a, b, equals_default_policy()))
{
return false;
}
@@ -94,8 +198,11 @@ struct smaller<Type, true>
};
-template <typename Type, bool IsFloatingPoint>
-struct equals_with_epsilon : public equals<Type, IsFloatingPoint> {};
+template <typename Type,
+ bool IsFloatingPoint = boost::is_floating_point<Type>::value>
+struct equals_with_epsilon
+ : public equals<Type, IsFloatingPoint>
+{};
template
<
@@ -120,28 +227,52 @@ struct square_root
}
};
-template <>
-struct square_root<float, true>
+template <typename FundamentalFP>
+struct square_root_for_fundamental_fp
{
- typedef float return_type;
+ typedef FundamentalFP return_type;
- static inline float apply(float const& value)
+ static inline FundamentalFP apply(FundamentalFP const& value)
{
- // for float use std::sqrt
+#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
+ // This is a workaround for some 32-bit platforms.
+ // For some of those platforms it has been reported that
+ // std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
+ // For those platforms we need to define the macro
+ // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
+ // to std::sqrt is checked appropriately before passed to std::sqrt
+ if (boost::math::isfinite(value))
+ {
+ return std::sqrt(value);
+ }
+ else if (boost::math::isinf(value) && value < 0)
+ {
+ return -std::numeric_limits<FundamentalFP>::quiet_NaN();
+ }
+ return value;
+#else
+ // for fundamental floating point numbers use std::sqrt
return std::sqrt(value);
+#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
}
};
template <>
-struct square_root<long double, true>
+struct square_root<float, true>
+ : square_root_for_fundamental_fp<float>
{
- typedef long double return_type;
+};
- static inline long double apply(long double const& value)
- {
- // for long double use std::sqrt
- return std::sqrt(value);
- }
+template <>
+struct square_root<double, true>
+ : square_root_for_fundamental_fp<double>
+{
+};
+
+template <>
+struct square_root<long double, true>
+ : square_root_for_fundamental_fp<long double>
+{
};
template <typename T>
@@ -156,7 +287,10 @@ struct square_root<T, true>
// Note: in C++98 the only other possibility is double;
// in C++11 there are also overloads for integral types;
// this specialization works for those as well.
- return std::sqrt(boost::numeric_cast<double>(value));
+ return square_root_for_fundamental_fp
+ <
+ double
+ >::apply(boost::numeric_cast<double>(value));
}
};
@@ -240,44 +374,36 @@ inline T relaxed_epsilon(T const& factor)
template <typename T1, typename T2>
inline bool equals(T1 const& a, T2 const& b)
{
- typedef typename select_most_precise<T1, T2>::type select_type;
return detail::equals
<
- select_type,
- boost::is_floating_point<select_type>::type::value
- >::apply(a, b);
+ typename select_most_precise<T1, T2>::type
+ >::apply(a, b, detail::equals_default_policy());
}
template <typename T1, typename T2>
inline bool equals_with_epsilon(T1 const& a, T2 const& b)
{
- typedef typename select_most_precise<T1, T2>::type select_type;
return detail::equals_with_epsilon
<
- select_type,
- boost::is_floating_point<select_type>::type::value
- >::apply(a, b);
+ typename select_most_precise<T1, T2>::type
+ >::apply(a, b, detail::equals_default_policy());
}
template <typename T1, typename T2>
inline bool smaller(T1 const& a, T2 const& b)
{
- typedef typename select_most_precise<T1, T2>::type select_type;
return detail::smaller
<
- select_type,
- boost::is_floating_point<select_type>::type::value
+ typename select_most_precise<T1, T2>::type
>::apply(a, b);
}
template <typename T1, typename T2>
inline bool larger(T1 const& a, T2 const& b)
{
- typedef typename select_most_precise<T1, T2>::type select_type;
return detail::smaller
<
- select_type,
- boost::is_floating_point<select_type>::type::value
+ typename select_most_precise<T1, T2>::type
>::apply(b, a);
}
@@ -336,8 +462,7 @@ sqrt(T const& value)
template<typename T>
inline T abs(T const& value)
{
- T const zero = T();
- return value < zero ? -value : value;
+ return detail::abs<T>::apply(value);
}
/*!
@@ -356,12 +481,11 @@ static inline int sign(T const& 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
- just casted.
+ casted.
*/
template <typename Result, typename T>
inline Result round(T const& v)
{
- // NOTE: boost::round() could be used instead but it throws in some situations
return detail::round<Result, T>::apply(v);
}
diff --git a/boost/geometry/util/promote_integral.hpp b/boost/geometry/util/promote_integral.hpp
new file mode 100644
index 0000000000..6b23403be3
--- /dev/null
+++ b/boost/geometry/util/promote_integral.hpp
@@ -0,0 +1,318 @@
+// 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_PROMOTE_INTEGRAL_HPP
+#define BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
+
+// For now deactivate the use of multiprecision integers
+// TODO: activate it later
+#define BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
+
+#include <climits>
+#include <cstddef>
+
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/list.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/size_t.hpp>
+
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
+#include <boost/multiprecision/cpp_int.hpp>
+#endif
+
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace promote_integral
+{
+
+// meta-function that returns the bit size of a type
+template
+<
+ typename T,
+ bool IsFundamental = boost::is_fundamental<T>::type::value
+>
+struct bit_size
+{};
+
+
+// for fundamental types, just return CHAR_BIT * sizeof(T)
+template <typename T>
+struct bit_size<T, true>
+ : boost::mpl::size_t<(CHAR_BIT * sizeof(T))>
+{};
+
+
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
+// partial specialization for cpp_int
+template
+<
+ unsigned MinSize,
+ unsigned MaxSize,
+ boost::multiprecision::cpp_integer_type SignType,
+ boost::multiprecision::cpp_int_check_type Checked,
+ typename Allocator,
+ boost::multiprecision::expression_template_option ExpressionTemplates
+>
+struct bit_size
+ <
+ boost::multiprecision::number
+ <
+ boost::multiprecision::cpp_int_backend
+ <
+ MinSize, MaxSize, SignType, Checked, Allocator
+ >,
+ ExpressionTemplates
+ >,
+ false
+ > : boost::mpl::size_t<MaxSize>
+{};
+#endif // BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
+
+
+template
+<
+ typename T,
+ typename Iterator,
+ typename EndIterator,
+ std::size_t MinSize
+>
+struct promote_to_larger
+{
+ typedef typename boost::mpl::deref<Iterator>::type current_type;
+
+ typedef typename boost::mpl::if_c
+ <
+ (bit_size<current_type>::type::value >= MinSize),
+ current_type,
+ typename promote_to_larger
+ <
+ T,
+ typename boost::mpl::next<Iterator>::type,
+ EndIterator,
+ MinSize
+ >::type
+ >::type type;
+};
+
+// The following specialization is required to finish the loop over
+// all list elements
+template <typename T, typename EndIterator, std::size_t MinSize>
+struct promote_to_larger<T, EndIterator, EndIterator, MinSize>
+{
+ // if promotion fails, keep the number T
+ // (and cross fingers that overflow will not occur)
+ typedef T type;
+};
+
+}} // namespace detail::promote_integral
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+/*!
+ \brief Meta-function to define an integral type with size
+ than is (roughly) twice the bit size of T
+ \ingroup utility
+ \details
+ This meta-function tries to promote the fundamental integral type T
+ to a another integral type with size (roughly) twice the bit size of T.
+
+ To do this, two times the bit size of T is tested against the bit sizes of:
+ short, int, long, boost::long_long_type, boost::int128_t
+ and the one that first matches is chosen.
+
+ For unsigned types the bit size of T is tested against the bit
+ sizes of the types above, if T is promoted to a signed type, or
+ the bit sizes of
+ unsigned short, unsigned int, unsigned long, std::size_t,
+ boost::ulong_long_type, boost::uint128_t
+ if T is promoted to an unsigned type.
+
+ By default an unsigned type is promoted to a signed type.
+ This behavior is controlled by the PromoteUnsignedToUnsigned
+ boolean template parameter, whose default value is "false".
+ To promote an unsigned type to an unsigned type set the value of
+ this template parameter to "true".
+
+ If the macro BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is not
+ defined, boost's multiprecision integer cpp_int<> is used as a
+ last resort.
+
+ If BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is defined and an
+ appropriate type cannot be detected, the input type is returned as is.
+
+ Finally, if the passed type is either a floating-point type or a
+ user-defined type it is returned as is.
+
+ \note boost::long_long_type and boost::ulong_long_type are
+ considered only if the macro BOOST_HAS_LONG_LONG is defined
+
+ \note boost::int128_type and boost::uint128_type are considered
+ only if the macros BOOST_HAS_INT128 and BOOST_GEOMETRY_ENABLE_INT128
+ are defined
+*/
+template
+<
+ typename T,
+ bool PromoteUnsignedToUnsigned = false,
+ bool UseCheckedInteger = false,
+ bool IsIntegral = boost::is_integral<T>::type::value
+>
+class promote_integral
+{
+private:
+ static bool const is_unsigned = boost::is_unsigned<T>::type::value;
+
+ typedef detail::promote_integral::bit_size<T> bit_size_type;
+
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
+ // Define the proper check policy for the multiprecision integer
+ typedef typename boost::mpl::if_c
+ <
+ UseCheckedInteger,
+ boost::integral_constant
+ <
+ boost::multiprecision::cpp_int_check_type,
+ boost::multiprecision::checked
+ >,
+ boost::integral_constant
+ <
+ boost::multiprecision::cpp_int_check_type,
+ boost::multiprecision::unchecked
+ >
+ >::type check_policy_type;
+
+ // Meta-function to get the multiprecision integer type for the
+ // given size and sign type (signed/unsigned)
+ template
+ <
+ unsigned int Size,
+ boost::multiprecision::cpp_integer_type SignType
+ >
+ struct multiprecision_integer_type
+ {
+ typedef boost::multiprecision::number
+ <
+ boost::multiprecision::cpp_int_backend
+ <
+ Size,
+ Size,
+ SignType,
+ check_policy_type::value,
+ void
+ >
+ > type;
+ };
+#endif
+
+ // Define the minimum size (in bits) needed for the promoted type
+ // If T is the input type and P the promoted type, then the
+ // minimum number of bits for P are (below b stands for the number
+ // of bits of T):
+ // * if T is unsigned and P is unsigned: 2 * b
+ // * if T is signed and P is signed: 2 * b - 1
+ // * if T is unsigned and P is signed: 2 * b + 1
+ typedef typename boost::mpl::if_c
+ <
+ (PromoteUnsignedToUnsigned && is_unsigned),
+ boost::mpl::size_t<(2 * bit_size_type::value)>,
+ typename boost::mpl::if_c
+ <
+ is_unsigned,
+ boost::mpl::size_t<(2 * bit_size_type::value + 1)>,
+ boost::mpl::size_t<(2 * bit_size_type::value - 1)>
+ >::type
+ >::type min_bit_size_type;
+
+ // Define the list of signed integral types we are going to use
+ // for promotion
+ typedef boost::mpl::list
+ <
+ short, int, long
+#if defined(BOOST_HAS_LONG_LONG)
+ , boost::long_long_type
+#endif
+#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
+ , boost::int128_type
+#endif
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
+ , typename multiprecision_integer_type
+ <
+ min_bit_size_type::value,
+ boost::multiprecision::signed_magnitude
+ >::type
+#endif
+ > signed_integral_types;
+
+ // Define the list of unsigned integral types we are going to use
+ // for promotion
+ typedef boost::mpl::list
+ <
+ unsigned short, unsigned int, unsigned long, std::size_t
+#if defined(BOOST_HAS_LONG_LONG)
+ , boost::ulong_long_type
+#endif
+#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
+ , boost::uint128_type
+#endif
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
+ , typename multiprecision_integer_type
+ <
+ min_bit_size_type::value,
+ boost::multiprecision::unsigned_magnitude
+ >::type
+#endif
+ > unsigned_integral_types;
+
+ // Define the list of integral types that will be used for
+ // promotion (depending in whether we was to promote unsigned to
+ // unsigned or not)
+ typedef typename boost::mpl::if_c
+ <
+ (is_unsigned && PromoteUnsignedToUnsigned),
+ unsigned_integral_types,
+ signed_integral_types
+ >::type integral_types;
+
+public:
+ typedef typename detail::promote_integral::promote_to_larger
+ <
+ T,
+ typename boost::mpl::begin<integral_types>::type,
+ typename boost::mpl::end<integral_types>::type,
+ min_bit_size_type::value
+ >::type type;
+};
+
+
+template <typename T, bool PromoteUnsignedToUnsigned, bool UseCheckedInteger>
+class promote_integral
+ <
+ T, PromoteUnsignedToUnsigned, UseCheckedInteger, false
+ >
+{
+public:
+ typedef T type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
diff --git a/boost/geometry/util/range.hpp b/boost/geometry/util/range.hpp
index fe3502f978..cf69413411 100644
--- a/boost/geometry/util/range.hpp
+++ b/boost/geometry/util/range.hpp
@@ -2,15 +2,15 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014.
-// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 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)
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
#define BOOST_GEOMETRY_UTIL_RANGE_HPP
@@ -30,20 +30,63 @@
namespace boost { namespace geometry { namespace range {
-// NOTE: For SinglePassRanges at could iterate over all elements until the i-th element is met.
+namespace detail {
+
+// NOTE: For SinglePassRanges pos could iterate over all elements until the i-th element was met.
+
+template <typename RandomAccessRange>
+struct pos
+{
+ typedef typename boost::range_iterator<RandomAccessRange>::type iterator;
+ typedef typename boost::range_size<RandomAccessRange>::type size_type;
+ typedef typename boost::range_difference<RandomAccessRange>::type difference_type;
+
+ static inline iterator apply(RandomAccessRange & rng, size_type i)
+ {
+ BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));
+ return boost::begin(rng) + static_cast<difference_type>(i);
+ }
+};
+
+} // namespace detail
+
+/*!
+\brief Short utility to conveniently return an iterator of a RandomAccessRange.
+\ingroup utility
+*/
+template <typename RandomAccessRange>
+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));
+ return detail::pos<RandomAccessRange const>::apply(rng, i);
+}
+
+/*!
+\brief Short utility to conveniently return an iterator of a RandomAccessRange.
+\ingroup utility
+*/
+template <typename RandomAccessRange>
+inline typename boost::range_iterator<RandomAccessRange>::type
+pos(RandomAccessRange & rng,
+ typename boost::range_size<RandomAccessRange>::type i)
+{
+ BOOST_ASSERT(i <= boost::size(rng));
+ return detail::pos<RandomAccessRange>::apply(rng, i);
+}
/*!
\brief Short utility to conveniently return an element of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
-inline typename boost::range_value<RandomAccessRange const>::type const&
+inline typename boost::range_reference<RandomAccessRange const>::type
at(RandomAccessRange const& rng,
typename boost::range_size<RandomAccessRange const>::type i)
{
- BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange const> ));
BOOST_ASSERT(i < boost::size(rng));
- return *(boost::begin(rng) + i);
+ return * detail::pos<RandomAccessRange const>::apply(rng, i);
}
/*!
@@ -51,13 +94,12 @@ at(RandomAccessRange const& rng,
\ingroup utility
*/
template <typename RandomAccessRange>
-inline typename boost::range_value<RandomAccessRange>::type &
+inline typename boost::range_reference<RandomAccessRange>::type
at(RandomAccessRange & rng,
typename boost::range_size<RandomAccessRange>::type i)
{
- BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));
BOOST_ASSERT(i < boost::size(rng));
- return *(boost::begin(rng) + i);
+ return * detail::pos<RandomAccessRange>::apply(rng, i);
}
/*!
@@ -65,7 +107,7 @@ at(RandomAccessRange & rng,
\ingroup utility
*/
template <typename Range>
-inline typename boost::range_value<Range>::type const&
+inline typename boost::range_reference<Range const>::type
front(Range const& rng)
{
BOOST_ASSERT(!boost::empty(rng));
@@ -77,7 +119,7 @@ front(Range const& rng)
\ingroup utility
*/
template <typename Range>
-inline typename boost::range_value<Range>::type &
+inline typename boost::range_reference<Range>::type
front(Range & rng)
{
BOOST_ASSERT(!boost::empty(rng));
@@ -91,12 +133,12 @@ front(Range & rng)
\ingroup utility
*/
template <typename BidirectionalRange>
-inline typename boost::range_value<BidirectionalRange>::type const&
+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));
- return *(--boost::end(rng));
+ return *(boost::rbegin(rng));
}
/*!
@@ -104,12 +146,12 @@ back(BidirectionalRange const& rng)
\ingroup utility
*/
template <typename BidirectionalRange>
-inline typename boost::range_value<BidirectionalRange>::type &
+inline typename boost::range_reference<BidirectionalRange>::type
back(BidirectionalRange & rng)
{
- BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange> ));
+ BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));
BOOST_ASSERT(!boost::empty(rng));
- return *(--boost::end(rng));
+ return *(boost::rbegin(rng));
}
diff --git a/boost/geometry/util/select_calculation_type.hpp b/boost/geometry/util/select_calculation_type.hpp
index 4946c45e84..0e3faf229b 100644
--- a/boost/geometry/util/select_calculation_type.hpp
+++ b/boost/geometry/util/select_calculation_type.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -50,6 +55,28 @@ struct select_calculation_type
>::type type;
};
+// alternative version supporting more than 2 Geometries
+
+template <typename CalculationType,
+ typename Geometry1,
+ typename Geometry2 = void,
+ typename Geometry3 = void>
+struct select_calculation_type_alt
+{
+ typedef typename
+ boost::mpl::if_
+ <
+ boost::is_void<CalculationType>,
+ typename select_coordinate_type
+ <
+ Geometry1,
+ Geometry2,
+ Geometry3
+ >::type,
+ CalculationType
+ >::type type;
+};
+
}} // namespace boost::geometry
diff --git a/boost/geometry/util/select_coordinate_type.hpp b/boost/geometry/util/select_coordinate_type.hpp
index 8309da42b7..12a6b72a73 100644
--- a/boost/geometry/util/select_coordinate_type.hpp
+++ b/boost/geometry/util/select_coordinate_type.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -28,16 +33,35 @@ namespace boost { namespace geometry
of two geometries
\ingroup utility
*/
-template <typename T1, typename T2>
+template <typename T1, typename T2 = void, typename T3 = void>
struct select_coordinate_type
{
typedef typename select_most_precise
<
typename coordinate_type<T1>::type,
+ typename coordinate_type<T2>::type,
+ typename coordinate_type<T3>::type
+ >::type type;
+};
+
+template <typename T1, typename T2>
+struct select_coordinate_type<T1, T2, void>
+{
+ typedef typename select_most_precise
+ <
+ typename coordinate_type<T1>::type,
typename coordinate_type<T2>::type
>::type type;
};
+template <typename T1>
+struct select_coordinate_type<T1, void, void>
+{
+ typedef typename select_most_precise
+ <
+ typename coordinate_type<T1>::type
+ >::type type;
+};
}} // namespace boost::geometry
diff --git a/boost/geometry/util/select_most_precise.hpp b/boost/geometry/util/select_most_precise.hpp
index d55fdbfd98..b5b1388cf8 100644
--- a/boost/geometry/util/select_most_precise.hpp
+++ b/boost/geometry/util/select_most_precise.hpp
@@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -113,9 +118,19 @@ struct select_floating_point<false, true, T1, T2>
\note If both types are non-fundamental, the result is indeterminate and
currently the first one is chosen.
*/
-template <typename T1, typename T2>
+template <typename T1, typename T2 = void, typename T3 = void>
struct select_most_precise
{
+ typedef typename select_most_precise
+ <
+ typename select_most_precise<T1, T2>::type,
+ T3
+ >::type type;
+};
+
+template <typename T1, typename T2>
+struct select_most_precise<T1, T2, void>
+{
static const bool second_larger = sizeof(T2) > sizeof(T1);
static const bool one_not_fundamental = !
(boost::is_fundamental<T1>::type::value
@@ -155,7 +170,11 @@ struct select_most_precise
>::type type;
};
-
+template <typename T1>
+struct select_most_precise<T1, void, void>
+{
+ typedef T1 type;
+};
}} // namespace boost::geometry
diff --git a/boost/geometry/util/transform_variant.hpp b/boost/geometry/util/transform_variant.hpp
index 9e4a7aa152..f0836bcbf2 100644
--- a/boost/geometry/util/transform_variant.hpp
+++ b/boost/geometry/util/transform_variant.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.
@@ -31,7 +36,7 @@ namespace boost { namespace geometry
\ingroup utility
\par Example
\code
- typedef mpl::vector<int, float, long> types;
+ typedef boost::mpl::vector<int, float, long> types;
typedef transform_variant<types, add_pointer<_> > transformed;
typedef variant<int*, float*, long*> result;
BOOST_MPL_ASSERT(( equal<result, transformed> ));
@@ -40,7 +45,7 @@ namespace boost { namespace geometry
template <typename Sequence, typename Op, typename In = boost::mpl::na>
struct transform_variant:
make_variant_over<
- typename mpl::transform<
+ typename boost::mpl::transform<
Sequence,
Op,
In
@@ -65,7 +70,7 @@ struct transform_variant:
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Op>
struct transform_variant<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Op, boost::mpl::na> :
make_variant_over<
- typename mpl::transform<
+ typename boost::mpl::transform<
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
Op
>::type
diff --git a/boost/geometry/views/detail/normalized_view.hpp b/boost/geometry/views/detail/normalized_view.hpp
index d50ffe48c8..1e9cda9ce2 100644
--- a/boost/geometry/views/detail/normalized_view.hpp
+++ b/boost/geometry/views/detail/normalized_view.hpp
@@ -28,6 +28,7 @@
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/util/order_as_direction.hpp>
namespace boost { namespace geometry {