diff options
Diffstat (limited to 'boost/geometry/algorithms/detail')
119 files changed, 7775 insertions, 1748 deletions
diff --git a/boost/geometry/algorithms/detail/andoyer_inverse.hpp b/boost/geometry/algorithms/detail/andoyer_inverse.hpp new file mode 100644 index 0000000000..eb8485b8e1 --- /dev/null +++ b/boost/geometry/algorithms/detail/andoyer_inverse.hpp @@ -0,0 +1,163 @@ +// Boost.Geometry + +// Copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP + + +#include <boost/math/constants/constants.hpp> + +#include <boost/geometry/core/radius.hpp> +#include <boost/geometry/core/srs.hpp> + +#include <boost/geometry/util/condition.hpp> +#include <boost/geometry/util/math.hpp> + +#include <boost/geometry/algorithms/detail/flattening.hpp> +#include <boost/geometry/algorithms/detail/result_inverse.hpp> + + +namespace boost { namespace geometry { namespace detail +{ + +/*! +\brief The solution of the inverse problem of geodesics on latlong coordinates, + Forsyth-Andoyer-Lambert type approximation with first order terms. +\author See + - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965 + http://www.dtic.mil/docs/citations/AD0627893 + - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970 + http://www.dtic.mil/docs/citations/AD703541 +*/ + +template <typename CT, bool EnableDistance, bool EnableAzimuth> +struct andoyer_inverse +{ + typedef result_inverse<CT> result_type; + + template <typename T1, typename T2, typename Spheroid> + static inline result_type apply(T1 const& lon1, + T1 const& lat1, + T2 const& lon2, + T2 const& lat2, + Spheroid const& spheroid) + { + result_type result; + + // coordinates in radians + + if ( math::equals(lon1, lon2) + && math::equals(lat1, lat2) ) + { + result.set(CT(0), CT(0)); + return result; + } + + CT const pi_half = math::pi<CT>() / CT(2); + + if ( math::equals(math::abs(lat1), pi_half) + && math::equals(math::abs(lat2), pi_half) ) + { + result.set(CT(0), CT(0)); + return result; + } + + CT const dlon = lon2 - lon1; + CT const sin_dlon = sin(dlon); + CT const cos_dlon = cos(dlon); + CT const sin_lat1 = sin(lat1); + CT const cos_lat1 = cos(lat1); + CT const sin_lat2 = sin(lat2); + CT const cos_lat2 = cos(lat2); + + // H,G,T = infinity if cos_d = 1 or cos_d = -1 + // lat1 == +-90 && lat2 == +-90 + // lat1 == lat2 && lon1 == lon2 + CT const cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon; + CT const d = acos(cos_d); + CT const sin_d = sin(d); + + // just in case since above lat1 and lat2 is checked + // the check below is equal to cos_d == 1 || cos_d == -1 || d == 0 + if ( math::equals(sin_d, CT(0)) ) + { + result.set(CT(0), CT(0)); + return result; + } + + // if the function returned before this place + // and endpoints were on the poles +-90 deg + // in this case the azimuth could either be 0 or +-pi + + CT const f = detail::flattening<CT>(spheroid); + + if ( BOOST_GEOMETRY_CONDITION(EnableDistance) ) + { + CT const K = math::sqr(sin_lat1-sin_lat2); + CT const L = math::sqr(sin_lat1+sin_lat2); + CT const three_sin_d = CT(3) * sin_d; + // H or G = infinity if cos_d = 1 or cos_d = -1 + CT const H = (d+three_sin_d)/(CT(1)-cos_d); + CT const G = (d-three_sin_d)/(CT(1)+cos_d); + + // for e.g. lat1=-90 && lat2=90 here we have G*L=INF*0 + CT const dd = -(f/CT(4))*(H*K+G*L); + + CT const a = get_radius<0>(spheroid); + + result.distance = a * (d + dd); + } + else + { + result.distance = CT(0); + } + + if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) ) + { + CT A = CT(0); + CT U = CT(0); + if ( ! math::equals(cos_lat2, CT(0)) ) + { + CT const tan_lat2 = sin_lat2/cos_lat2; + CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon; + A = atan2(sin_dlon, M); + CT const sin_2A = sin(CT(2)*A); + U = (f/CT(2))*math::sqr(cos_lat1)*sin_2A; + } + + CT V = CT(0); + if ( ! math::equals(cos_lat1, CT(0)) ) + { + CT const tan_lat1 = sin_lat1/cos_lat1; + CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon; + CT const B = atan2(sin_dlon, N); + CT const sin_2B = sin(CT(2)*B); + V = (f/CT(2))*math::sqr(cos_lat2)*sin_2B; + } + + // infinity if sin_d = 0, so cos_d = 1 or cos_d = -1 + CT const T = d / sin_d; + CT const dA = V*T-U; + + result.azimuth = A - dA; + } + else + { + result.azimuth = CT(0); + } + + return result; + } +}; + +}}} // namespace boost::geometry::detail + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP diff --git a/boost/geometry/algorithms/detail/azimuth.hpp b/boost/geometry/algorithms/detail/azimuth.hpp index 7810b4814e..f0a8d65c86 100644 --- a/boost/geometry/algorithms/detail/azimuth.hpp +++ b/boost/geometry/algorithms/detail/azimuth.hpp @@ -49,10 +49,10 @@ struct azimuth<ReturnType, geographic_tag> template <typename P1, typename P2, typename Spheroid> static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid) { - return geometry::detail::vincenty_inverse<ReturnType> + return geometry::detail::vincenty_inverse<ReturnType, false, true> ( get_as_radian<0>(p1), get_as_radian<1>(p1), get_as_radian<0>(p2), get_as_radian<1>(p2), - spheroid ).azimuth12(); + spheroid ).azimuth; } template <typename P1, typename P2> diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 127e4c3fb2..b25bcc7fb5 100644 --- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -12,11 +12,12 @@ #include <cstddef> #include <iterator> + #include <boost/core/ignore_unused.hpp> #include <boost/numeric/conversion/cast.hpp> - #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> @@ -227,7 +228,7 @@ struct buffer_range typename EndStrategy, typename RobustPolicy > - static inline bool iterate(Collection& collection, + static inline strategy::buffer::result_code iterate(Collection& collection, Iterator begin, Iterator end, strategy::buffer::buffer_side_selector side, DistanceStrategy const& distance_strategy, @@ -266,7 +267,7 @@ struct buffer_range * pup: penultimate_point */ - bool result = false; + strategy::buffer::result_code result = strategy::buffer::result_no_output; bool first = true; Iterator it = begin; @@ -277,18 +278,25 @@ struct buffer_range for (Iterator prev = it++; it != end; ++it) { generated_side.clear(); - side_strategy.apply(*prev, *it, side, + strategy::buffer::result_code error_code + = side_strategy.apply(*prev, *it, side, distance_strategy, generated_side); - if (generated_side.empty()) + if (error_code == strategy::buffer::result_no_output) { // Because input is simplified, this is improbable, // but it can happen for degenerate geometries // Further handling of this side is skipped continue; } + else if (error_code == strategy::buffer::result_error_numerical) + { + return error_code; + } + + BOOST_GEOMETRY_ASSERT(! generated_side.empty()); - result = true; + result = strategy::buffer::result_normal; if (! first) { @@ -383,6 +391,7 @@ inline void buffer_point(Point const& point, Collection& collection, std::vector<OutputPointType> range_out; point_strategy.apply(point, distance_strategy, range_out); collection.add_piece(strategy::buffer::buffered_point, range_out, false); + collection.set_piece_center(point); collection.finish_ring(); } @@ -458,7 +467,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput> typename EndStrategy, typename RobustPolicy > - static inline bool iterate(Collection& collection, + static inline strategy::buffer::result_code iterate(Collection& collection, Iterator begin, Iterator end, strategy::buffer::buffer_side_selector side, DistanceStrategy const& distance_strategy, @@ -471,13 +480,14 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput> typedef detail::buffer::buffer_range<RingOutput> buffer_range; - bool result = buffer_range::iterate(collection, begin, end, + strategy::buffer::result_code result + = buffer_range::iterate(collection, begin, end, side, distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, first_p1, first_p2, last_p1, last_p2); // Generate closing join - if (result) + if (result == strategy::buffer::result_normal) { buffer_range::add_join(collection, *(end - 2), @@ -502,7 +512,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput> typename PointStrategy, typename RobustPolicy > - static inline void apply(RingInput const& ring, + static inline strategy::buffer::result_code apply(RingInput const& ring, Collection& collection, DistanceStrategy const& distance, SideStrategy const& side_strategy, @@ -514,7 +524,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput> RingInput simplified; detail::buffer::simplify_input(ring, distance, simplified); - bool has_output = false; + strategy::buffer::result_code code = strategy::buffer::result_no_output; std::size_t n = boost::size(simplified); std::size_t const min_points = core_detail::closure::minimum_ring_size @@ -528,21 +538,19 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput> if (distance.negative()) { // Walk backwards (rings will be reversed afterwards) - // It might be that this will be changed later. - // TODO: decide this. - has_output = iterate(collection, boost::rbegin(view), boost::rend(view), + code = iterate(collection, boost::rbegin(view), boost::rend(view), strategy::buffer::buffer_side_right, distance, side_strategy, join_strategy, end_strategy, robust_policy); } else { - has_output = iterate(collection, boost::begin(view), boost::end(view), + code = iterate(collection, boost::begin(view), boost::end(view), strategy::buffer::buffer_side_left, distance, side_strategy, join_strategy, end_strategy, robust_policy); } } - if (! has_output && n >= 1) + if (code == strategy::buffer::result_no_output && n >= 1) { // Use point_strategy to buffer degenerated ring detail::buffer::buffer_point<output_point_type> @@ -551,6 +559,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput> collection, distance, point_strategy ); } + return code; } }; @@ -576,7 +585,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon> typename EndStrategy, typename RobustPolicy > - static inline bool iterate(Collection& collection, + static inline strategy::buffer::result_code iterate(Collection& collection, Iterator begin, Iterator end, strategy::buffer::buffer_side_selector side, DistanceStrategy const& distance_strategy, @@ -601,27 +610,33 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon> else { std::vector<output_point_type> generated_side; - side_strategy.apply(ultimate_point, penultimate_point, + strategy::buffer::result_code code + = side_strategy.apply(ultimate_point, penultimate_point, strategy::buffer::buffer_side_right, distance_strategy, generated_side); - if (generated_side.empty()) + if (code != strategy::buffer::result_normal) { - return false; + // No output or numerical error + return code; } reverse_p1 = generated_side.front(); } output_point_type first_p2, last_p1, last_p2; - detail::buffer::buffer_range<output_ring_type>::iterate(collection, + strategy::buffer::result_code result + = detail::buffer::buffer_range<output_ring_type>::iterate(collection, begin, end, side, distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, first_p1, first_p2, last_p1, last_p2); - std::vector<output_point_type> range_out; - end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out); - collection.add_endcap(end_strategy, range_out, ultimate_point); - return true; + if (result == strategy::buffer::result_normal) + { + std::vector<output_point_type> range_out; + end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out); + collection.add_endcap(end_strategy, range_out, ultimate_point); + } + return result; } template @@ -634,7 +649,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon> typename PointStrategy, typename RobustPolicy > - static inline void apply(Linestring const& linestring, Collection& collection, + static inline strategy::buffer::result_code apply(Linestring const& linestring, Collection& collection, DistanceStrategy const& distance, SideStrategy const& side_strategy, JoinStrategy const& join_strategy, @@ -645,28 +660,29 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon> Linestring simplified; detail::buffer::simplify_input(linestring, distance, simplified); - bool has_output = false; + strategy::buffer::result_code code = strategy::buffer::result_no_output; std::size_t n = boost::size(simplified); if (n > 1) { collection.start_new_ring(); output_point_type first_p1; - has_output = iterate(collection, + code = iterate(collection, boost::begin(simplified), boost::end(simplified), strategy::buffer::buffer_side_left, distance, side_strategy, join_strategy, end_strategy, robust_policy, first_p1); - if (has_output) + if (code == strategy::buffer::result_normal) { - iterate(collection, boost::rbegin(simplified), boost::rend(simplified), + code = iterate(collection, + boost::rbegin(simplified), boost::rend(simplified), strategy::buffer::buffer_side_right, distance, side_strategy, join_strategy, end_strategy, robust_policy, first_p1); } collection.finish_ring(); } - if (! has_output && n >= 1) + if (code == strategy::buffer::result_no_output && n >= 1) { // Use point_strategy to buffer degenerated linestring detail::buffer::buffer_point<output_point_type> @@ -675,6 +691,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon> collection, distance, point_strategy ); } + return code; } }; @@ -718,9 +735,16 @@ private: for (Iterator it = begin; it != end; ++it) { collection.start_new_ring(); - policy::apply(*it, collection, distance, side_strategy, + strategy::buffer::result_code const code + = policy::apply(*it, collection, distance, side_strategy, join_strategy, end_strategy, point_strategy, robust_policy); + + if (code == strategy::buffer::result_error_numerical) + { + collection.abort_ring(); + return; + } collection.finish_ring(is_interior); } } @@ -774,11 +798,21 @@ public: { { collection.start_new_ring(); - policy::apply(exterior_ring(polygon), collection, + + strategy::buffer::result_code const code + = policy::apply(exterior_ring(polygon), collection, distance, side_strategy, join_strategy, end_strategy, point_strategy, robust_policy); - collection.finish_ring(false, geometry::num_interior_rings(polygon) > 0u); + + if (code == strategy::buffer::result_error_numerical) + { + collection.abort_ring(); + } + else + { + collection.finish_ring(false, geometry::num_interior_rings(polygon) > 0u); + } } apply_interior_rings(interior_rings(polygon), @@ -910,7 +944,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator collection.reverse(); } - if (distance_strategy.negative() && areal) + if (BOOST_GEOMETRY_CONDITION(distance_strategy.negative() && areal)) { collection.discard_nonintersecting_deflated_rings(); } diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index c5bb8acc05..255ac797dc 100644 --- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -9,6 +9,9 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP +#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) +# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION +#endif #include <cstddef> @@ -81,8 +84,8 @@ template <typename Point, typename SegmentRatio> struct buffer_turn_operation : public detail::overlay::traversal_turn_operation<Point, SegmentRatio> { - int piece_index; - int index_in_robust_ring; + signed_size_type piece_index; + signed_size_type index_in_robust_ring; inline buffer_turn_operation() : piece_index(-1) @@ -103,7 +106,7 @@ struct buffer_turn_info typedef Point point_type; typedef RobustPoint robust_point_type; - int turn_index; // TODO: this might go if partition can operate on non-const input + std::size_t turn_index; // TODO: this might go if partition can operate on non-const input RobustPoint robust_point; #if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) @@ -122,24 +125,30 @@ struct buffer_turn_info intersection_location_type location; - int count_within; +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + robust_point_type rob_pi, rob_pj, rob_qi, rob_qj; +#endif + + std::size_t count_within; bool within_original; - int count_on_original_boundary; - int count_in_original; // increased by +1 for in ext.ring, -1 for int.ring + std::size_t count_on_original_boundary; + signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring - int count_on_offsetted; - int count_on_helper; - int count_within_near_offsetted; + std::size_t count_on_offsetted; + std::size_t count_on_helper; +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + std::size_t count_within_near_offsetted; +#endif bool remove_on_multi; // Obsolete: - int count_on_occupied; - int count_on_multi; + std::size_t count_on_occupied; + std::size_t count_on_multi; inline buffer_turn_info() - : turn_index(-1) + : turn_index(0) , location(location_ok) , count_within(0) , within_original(false) @@ -147,7 +156,9 @@ struct buffer_turn_info , count_in_original(0) , count_on_offsetted(0) , count_on_helper(0) +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) , count_within_near_offsetted(0) +#endif , remove_on_multi(false) , count_on_occupied(0) , count_on_multi(0) diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index a501e3f197..545d89cb9b 100644 --- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -16,11 +16,14 @@ #include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/point_type.hpp> +#include <boost/geometry/algorithms/comparable_distance.hpp> #include <boost/geometry/algorithms/covered_by.hpp> #include <boost/geometry/algorithms/envelope.hpp> +#include <boost/geometry/algorithms/is_convex.hpp> #include <boost/geometry/strategies/buffer.hpp> @@ -126,6 +129,11 @@ struct buffered_piece_collection typedef geometry::model::ring<robust_point_type> robust_ring_type; typedef geometry::model::box<robust_point_type> robust_box_type; + typedef typename default_comparable_distance_result + < + robust_point_type + >::type robust_comparable_radius_type; + typedef typename strategy::side::services::default_strategy < typename cs_tag<point_type>::type @@ -159,7 +167,7 @@ struct buffered_piece_collection struct robust_turn { - int turn_index; + std::size_t turn_index; int operation_index; robust_point_type point; segment_identifier seg_id; @@ -172,10 +180,10 @@ struct buffered_piece_collection typedef geometry::section<robust_box_type, 1> section_type; strategy::buffer::piece_type type; - int index; + signed_size_type index; - int left_index; // points to previous piece of same ring - int right_index; // points to next piece of same ring + signed_size_type left_index; // points to previous piece of same ring + signed_size_type right_index; // points to next piece of same ring // The next two members (1, 2) form together a complete clockwise ring // for each piece (with one dupped point) @@ -183,21 +191,21 @@ struct buffered_piece_collection // 1: half, part of offsetted_rings segment_identifier first_seg_id; - int last_segment_index; // no segment-identifier - it is the same as first_seg_id - int offsetted_count; // part in robust_ring which is part of offsetted ring + signed_size_type last_segment_index; // no segment-identifier - it is the same as first_seg_id + signed_size_type offsetted_count; // part in robust_ring which is part of offsetted ring #if defined(BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS) // 2: half, not part of offsetted rings - part of robust ring std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end #endif + bool is_convex; bool is_monotonic_increasing[2]; // 0=x, 1=y bool is_monotonic_decreasing[2]; // 0=x, 1=y // Monotonic sections of pieces around points std::vector<section_type> sections; - // Robust representations // 3: complete ring robust_ring_type robust_ring; @@ -206,6 +214,27 @@ struct buffered_piece_collection robust_box_type robust_offsetted_envelope; std::vector<robust_turn> robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead + + robust_point_type robust_center; + robust_comparable_radius_type robust_min_comparable_radius; + robust_comparable_radius_type robust_max_comparable_radius; + + piece() + : type(strategy::buffer::piece_type_unknown) + , index(-1) + , left_index(-1) + , right_index(-1) + , last_segment_index(-1) + , offsetted_count(-1) + , is_convex(false) + , robust_min_comparable_radius(0) + , robust_max_comparable_radius(0) + { + is_monotonic_increasing[0] = false; + is_monotonic_increasing[1] = false; + is_monotonic_decreasing[0] = false; + is_monotonic_decreasing[1] = false; + } }; struct robust_original @@ -244,7 +273,7 @@ struct buffered_piece_collection piece_vector_type m_pieces; turn_vector_type m_turns; - int m_first_piece_index; + signed_size_type m_first_piece_index; buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index std::vector<robust_original> robust_originals; // robust representation of the original(s) @@ -444,6 +473,7 @@ struct buffered_piece_collection { it->location = inside_buffer; } +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) if (it->count_within_near_offsetted > 0) { // Within can have in rare cases a rounding issue. We don't discard this @@ -451,6 +481,7 @@ struct buffered_piece_collection // will never start a new ring from this type of points. it->selectable_start = false; } +#endif } } @@ -515,7 +546,7 @@ struct buffered_piece_collection { // Add rescaled turn points to corresponding pieces // (after this, each turn occurs twice) - int index = 0; + std::size_t index = 0; for (typename boost::range_iterator<turn_vector_type>::type it = boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index) { @@ -544,16 +575,16 @@ struct buffered_piece_collection } } +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) // Insert all rescaled turn-points into these rings, to form a // reliable integer-based ring. All turns can be compared (inside) to this // rings to see if they are inside. - for (typename piece_vector_type::iterator it = boost::begin(m_pieces); - it != boost::end(m_pieces); - ++it) + for (typename boost::range_iterator<piece_vector_type>::type + it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it) { piece& pc = *it; - int piece_segment_index = pc.first_seg_id.segment_index; + signed_size_type piece_segment_index = pc.first_seg_id.segment_index; if (! pc.robust_turns.empty()) { if (pc.robust_turns.size() > 1u) @@ -561,14 +592,14 @@ struct buffered_piece_collection std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less()); } // Walk through them, in reverse to insert at right index - int index_offset = pc.robust_turns.size() - 1; - for (typename std::vector<robust_turn>::const_reverse_iterator - rit = pc.robust_turns.rbegin(); - rit != pc.robust_turns.rend(); + signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1; + for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type + rit = boost::const_rbegin(pc.robust_turns); + rit != boost::const_rend(pc.robust_turns); ++rit, --index_offset) { - int const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index; - BOOST_ASSERT + signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index; + BOOST_GEOMETRY_ASSERT ( index_in_vector > 0 && index_in_vector < pc.offsetted_count @@ -582,7 +613,8 @@ struct buffered_piece_collection } } - BOOST_ASSERT(assert_indices_in_robust_rings()); + BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings()); +#endif } template <std::size_t Dimension> @@ -607,6 +639,8 @@ struct buffered_piece_collection pc.is_monotonic_decreasing[0] = true; pc.is_monotonic_decreasing[1] = true; + pc.is_convex = geometry::is_convex(pc.robust_ring); + if (pc.offsetted_count < 2) { return; @@ -615,14 +649,13 @@ struct buffered_piece_collection typename robust_ring_type::const_iterator current = pc.robust_ring.begin(); typename robust_ring_type::const_iterator next = current + 1; - for (int i = 1; i < pc.offsetted_count; i++) + for (signed_size_type i = 1; i < pc.offsetted_count; i++) { determine_monotonicity<0>(pc, *current, *next); determine_monotonicity<1>(pc, *current, *next); current = next; ++next; } - } void determine_properties() @@ -659,7 +692,31 @@ struct buffered_piece_collection geometry::sectionalize<false, dimensions>(pc.robust_ring, detail::no_rescale_policy(), pc.sections); - // TODO (next phase) determine min/max radius + // Determine min/max radius + typedef geometry::model::referring_segment<robust_point_type const> + robust_segment_type; + + typename robust_ring_type::const_iterator current = pc.robust_ring.begin(); + typename robust_ring_type::const_iterator next = current + 1; + + for (signed_size_type i = 1; i < pc.offsetted_count; i++) + { + robust_segment_type s(*current, *next); + robust_comparable_radius_type const d + = geometry::comparable_distance(pc.robust_center, s); + + if (i == 1 || d < pc.robust_min_comparable_radius) + { + pc.robust_min_comparable_radius = d; + } + if (i == 1 || d > pc.robust_max_comparable_radius) + { + pc.robust_max_comparable_radius = d; + } + + current = next; + ++next; + } } inline void prepare_buffered_point_pieces() @@ -730,7 +787,7 @@ struct buffered_piece_collection inline void start_new_ring() { - int const n = offsetted_rings.size(); + signed_size_type const n = static_cast<signed_size_type>(offsetted_rings.size()); current_segment_id.source_index = 0; current_segment_id.multi_index = n; current_segment_id.ring_index = -1; @@ -739,12 +796,35 @@ struct buffered_piece_collection offsetted_rings.resize(n + 1); current_robust_ring.clear(); - m_first_piece_index = boost::size(m_pieces); + m_first_piece_index = static_cast<signed_size_type>(boost::size(m_pieces)); + } + + inline void abort_ring() + { + // Remove all created pieces for this ring, sections, last offsetted + while (! m_pieces.empty() + && m_pieces.back().first_seg_id.multi_index + == current_segment_id.multi_index) + { + m_pieces.erase(m_pieces.end() - 1); + } + + while (! monotonic_sections.empty() + && monotonic_sections.back().ring_id.multi_index + == current_segment_id.multi_index) + { + monotonic_sections.erase(monotonic_sections.end() - 1); + } + + offsetted_rings.erase(offsetted_rings.end() - 1); + current_robust_ring.clear(); + + m_first_piece_index = -1; } inline void update_closing_point() { - BOOST_ASSERT(! offsetted_rings.empty()); + BOOST_GEOMETRY_ASSERT(! offsetted_rings.empty()); buffered_ring<Ring>& added = offsetted_rings.back(); if (! boost::empty(added)) { @@ -764,7 +844,7 @@ struct buffered_piece_collection // For now, it is made equal because due to numerical instability, // it can be a tiny bit off, possibly causing a self-intersection - BOOST_ASSERT(boost::size(m_pieces) > 0); + BOOST_GEOMETRY_ASSERT(boost::size(m_pieces) > 0); if (! ring.empty() && current_segment_id.segment_index == m_pieces.back().first_seg_id.segment_index) @@ -773,6 +853,13 @@ struct buffered_piece_collection } } + inline void set_piece_center(point_type const& center) + { + BOOST_GEOMETRY_ASSERT(! m_pieces.empty()); + geometry::recalculate(m_pieces.back().robust_center, center, + m_robust_policy); + } + inline void finish_ring(bool is_interior = false, bool has_interiors = false) { if (m_first_piece_index == -1) @@ -780,12 +867,12 @@ struct buffered_piece_collection return; } - if (m_first_piece_index < static_cast<int>(boost::size(m_pieces))) + if (m_first_piece_index < static_cast<signed_size_type>(boost::size(m_pieces))) { // If piece was added // Reassign left-of-first and right-of-last geometry::range::at(m_pieces, m_first_piece_index).left_index - = boost::size(m_pieces) - 1; + = static_cast<signed_size_type>(boost::size(m_pieces)) - 1; geometry::range::back(m_pieces).right_index = m_first_piece_index; } m_first_piece_index = -1; @@ -794,7 +881,7 @@ struct buffered_piece_collection if (! current_robust_ring.empty()) { - BOOST_ASSERT + BOOST_GEOMETRY_ASSERT ( geometry::equals(current_robust_ring.front(), current_robust_ring.back()) @@ -808,20 +895,20 @@ struct buffered_piece_collection inline void set_current_ring_concave() { - BOOST_ASSERT(boost::size(offsetted_rings) > 0); + BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0); offsetted_rings.back().has_concave = true; } - inline int add_point(point_type const& p) + inline signed_size_type add_point(point_type const& p) { - BOOST_ASSERT(boost::size(offsetted_rings) > 0); + BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0); buffered_ring<Ring>& current_ring = offsetted_rings.back(); update_last_point(p, current_ring); current_segment_id.segment_index++; current_ring.push_back(p); - return current_ring.size(); + return static_cast<signed_size_type>(current_ring.size()); } //------------------------------------------------------------------------- @@ -836,7 +923,7 @@ struct buffered_piece_collection piece pc; pc.type = type; - pc.index = boost::size(m_pieces); + pc.index = static_cast<signed_size_type>(boost::size(m_pieces)); pc.first_seg_id = current_segment_id; // Assign left/right (for first/last piece per ring they will be re-assigned later) @@ -862,11 +949,11 @@ struct buffered_piece_collection return; } - BOOST_ASSERT(pc.first_seg_id.multi_index >= 0); - BOOST_ASSERT(pc.last_segment_index >= 0); + BOOST_GEOMETRY_ASSERT(pc.first_seg_id.multi_index >= 0); + BOOST_GEOMETRY_ASSERT(pc.last_segment_index >= 0); pc.offsetted_count = pc.last_segment_index - pc.first_seg_id.segment_index; - BOOST_ASSERT(pc.offsetted_count >= 0); + BOOST_GEOMETRY_ASSERT(pc.offsetted_count >= 0); pc.robust_ring.reserve(pc.offsetted_count + helper_points_size); @@ -915,11 +1002,10 @@ struct buffered_piece_collection return; } - geometry::detail::envelope::envelope_range::apply(pc.robust_ring, - pc.robust_envelope); + geometry::envelope(pc.robust_ring, pc.robust_envelope); geometry::assign_inverse(pc.robust_offsetted_envelope); - for (int i = 0; i < pc.offsetted_count; i++) + for (signed_size_type i = 0; i < pc.offsetted_count; i++) { geometry::expand(pc.robust_offsetted_envelope, pc.robust_ring[i]); } @@ -1010,7 +1096,7 @@ struct buffered_piece_collection template <typename Range> inline void add_range_to_piece(piece& pc, Range const& range, bool add_front) { - BOOST_ASSERT(boost::size(range) != 0u); + BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u); typename Range::const_iterator it = boost::begin(range); @@ -1046,7 +1132,7 @@ struct buffered_piece_collection inline void add_side_piece(point_type const& p1, point_type const& p2, Range const& range, bool first) { - BOOST_ASSERT(boost::size(range) >= 2u); + BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u); piece& pc = create_piece(strategy::buffer::buffered_segment, ! first); add_range_to_piece(pc, range, first); @@ -1133,7 +1219,7 @@ struct buffered_piece_collection robust_point_type any_point; geometry::recalculate(any_point, point, m_robust_policy); - int count_in_original = 0; + signed_size_type count_in_original = 0; // Check of the robust point of this outputted ring is in // any of the robust original rings @@ -1279,7 +1365,7 @@ struct buffered_piece_collection // Inner rings, for deflate, which do not have intersections, and // which are outside originals, are skipped // (other ones should be traversed) - int index = 0; + signed_size_type index = 0; for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings); it != boost::end(offsetted_rings); ++it, ++index) @@ -1287,8 +1373,12 @@ struct buffered_piece_collection if (! it->has_intersections() && ! it->is_untouched_outside_original) { - ring_identifier id(0, index, -1); - selected[id] = properties(*it); + properties p = properties(*it); + if (p.valid) + { + ring_identifier id(0, index, -1); + selected[id] = p; + } } } @@ -1299,8 +1389,12 @@ struct buffered_piece_collection it != boost::end(traversed_rings); ++it, ++index) { - ring_identifier id(2, index, -1); - selected[id] = properties(*it); + properties p = properties(*it); + if (p.valid) + { + ring_identifier id(2, index, -1); + selected[id] = p; + } } detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true); diff --git a/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp b/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp index 9ea8bc1e85..19c91544ac 100644 --- a/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -14,11 +14,14 @@ #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/strategies/buffer.hpp> +#include <boost/geometry/algorithms/within.hpp> + #include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp> #include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp> #include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp> @@ -26,8 +29,6 @@ #include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> -#include <boost/geometry/multi/algorithms/within.hpp> - namespace boost { namespace geometry { @@ -225,7 +226,7 @@ struct get_ring<detail::buffer::buffered_ring_collection_tag> ring_identifier const& id, MultiGeometry const& multi_ring) { - BOOST_ASSERT + BOOST_GEOMETRY_ASSERT ( id.multi_index >= 0 && id.multi_index < int(boost::size(multi_ring)) diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index 6a3daa282e..3425ee6ffd 100644 --- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -17,6 +17,7 @@ #include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> #include <boost/geometry/algorithms/detail/sections/section_functions.hpp> +#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp> namespace boost { namespace geometry @@ -28,6 +29,34 @@ namespace detail { namespace buffer { +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) +struct buffer_assign_turn +{ + static bool const include_no_turn = false; + static bool const include_degenerate = false; + static bool const include_opposite = false; + + template + < + typename Info, + typename Point1, + typename Point2, + typename IntersectionInfo + > + static inline void apply(Info& info, + Point1 const& /*p1*/, + Point2 const& /*p2*/, + IntersectionInfo const& iinfo) + { + info.rob_pi = iinfo.rpi(); + info.rob_pj = iinfo.rpj(); + info.rob_qi = iinfo.rqi(); + info.rob_qj = iinfo.rqj(); + } + +}; +#endif + template < typename Pieces, @@ -91,7 +120,7 @@ class piece_turn_visitor template <std::size_t Dimension, typename Iterator, typename Box> inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond, - int& index, int dir, Box const& other_bounding_box) + signed_size_type& index, int dir, Box const& other_bounding_box) { for(; it_begin != it_beyond && it_begin + 1 != it_beyond @@ -129,20 +158,20 @@ class piece_turn_visitor typedef typename boost::range_value<Turns const>::type turn_type; typedef typename boost::range_iterator<ring_type const>::type iterator; - int const piece1_first_index = piece1.first_seg_id.segment_index; - int const piece2_first_index = piece2.first_seg_id.segment_index; + signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index; + signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index; if (piece1_first_index < 0 || piece2_first_index < 0) { return; } // Get indices of part of offsetted_rings for this monotonic section: - int const sec1_first_index = piece1_first_index + section1.begin_index; - int const sec2_first_index = piece2_first_index + section2.begin_index; + signed_size_type const sec1_first_index = piece1_first_index + section1.begin_index; + signed_size_type const sec2_first_index = piece2_first_index + section2.begin_index; // index of last point in section, beyond-end is one further - int const sec1_last_index = piece1_first_index + section1.end_index; - int const sec2_last_index = piece2_first_index + section2.end_index; + signed_size_type const sec1_last_index = piece1_first_index + section1.end_index; + signed_size_type const sec2_last_index = piece2_first_index + section2.end_index; // get geometry and iterators over these sections ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index]; @@ -154,7 +183,7 @@ class piece_turn_visitor iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1; // Set begin/end of monotonic ranges, in both x/y directions - int index1 = sec1_first_index; + signed_size_type index1 = sec1_first_index; move_begin_iterator<0>(it1_first, it1_beyond, index1, section1.directions[0], section2.bounding_box); move_end_iterator<0>(it1_first, it1_beyond, @@ -164,7 +193,7 @@ class piece_turn_visitor move_end_iterator<1>(it1_first, it1_beyond, section1.directions[1], section2.bounding_box); - int index2 = sec2_first_index; + signed_size_type index2 = sec2_first_index; move_begin_iterator<0>(it2_first, it2_beyond, index2, section2.directions[0], section1.bounding_box); move_end_iterator<0>(it2_first, it2_beyond, @@ -204,7 +233,11 @@ class piece_turn_visitor // and iterating in sync with them... typedef detail::overlay::get_turn_info < +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + buffer_assign_turn +#else detail::overlay::assign_null_policy +#endif > turn_policy; turn_policy::apply(*prev1, *it1, *next1, diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index 8803efdec9..0aca21ce88 100644 --- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -14,6 +14,8 @@ #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> + #include <boost/geometry/arithmetic/dot_product.hpp> #include <boost/geometry/algorithms/assign.hpp> #include <boost/geometry/algorithms/comparable_distance.hpp> @@ -25,6 +27,11 @@ #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> #include <boost/geometry/policies/compare.hpp> #include <boost/geometry/strategies/buffer.hpp> +#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp> + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) +#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp> +#endif namespace boost { namespace geometry @@ -89,8 +96,10 @@ enum analyse_result analyse_disjoint, analyse_within, analyse_on_original_boundary, - analyse_on_offsetted, - analyse_near_offsetted + analyse_on_offsetted +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + , analyse_near_offsetted +#endif }; template <typename Point> @@ -112,6 +121,31 @@ inline analyse_result check_segment(Point const& previous, Point const& current, Turn const& turn, bool from_monotonic) { + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + typedef geometry::model::referring_segment<Point const> segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); + segment_type const r(previous, current); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + if (side == 0) + { + return analyse_on_offsetted; + } + if (side == -1 && from_monotonic) + { + return analyse_within; + } + if (side == 1 && from_monotonic) + { + return analyse_disjoint; + } + return analyse_continue; + +#else + typedef typename strategy::side::services::default_strategy < typename cs_tag<Point>::type @@ -156,6 +190,7 @@ inline analyse_result check_segment(Point const& previous, // Not monotonic, on left or right side: continue analysing return analyse_continue; +#endif } @@ -169,14 +204,22 @@ public : typedef typename Turn::robust_point_type point_type; typedef typename geometry::coordinate_type<point_type>::type coordinate_type; - coordinate_type const point_y = geometry::get<1>(turn.robust_point); - +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + typedef geometry::model::referring_segment<point_type const> segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); +#else typedef strategy::within::winding<point_type> strategy_type; typename strategy_type::state_type state; strategy_type strategy; boost::ignore_unused(strategy); - +#endif + + BOOST_GEOMETRY_ASSERT(! piece.sections.empty()); + + coordinate_type const point_y = geometry::get<1>(turn.robust_point); + for (std::size_t s = 0; s < piece.sections.size(); s++) { section_type const& section = piece.sections[s]; @@ -186,11 +229,43 @@ public : && point_y >= geometry::get<min_corner, 1>(section.bounding_box) - 1 && point_y <= geometry::get<max_corner, 1>(section.bounding_box) + 1) { - for (int i = section.begin_index + 1; i <= section.end_index; i++) + for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++) { point_type const& previous = piece.robust_ring[i - 1]; point_type const& current = piece.robust_ring[i]; +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + + // First check if it is in range - if it is not, the + // expensive side_of_intersection does not need to be + // applied + coordinate_type y1 = geometry::get<1>(previous); + coordinate_type y2 = geometry::get<1>(current); + + if (y1 > y2) + { + std::swap(y1, y2); + } + + if (point_y >= y1 - 1 && point_y <= y2 + 1) + { + segment_type const r(previous, current); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + // Sections are monotonic in y-dimension + if (side == 1) + { + // Left on segment + return analyse_disjoint; + } + else if (side == 0) + { + // Collinear - TODO: check if really on segment + return analyse_on_offsetted; + } + } +#else analyse_result code = check_segment(previous, current, turn, false); if (code != analyse_continue) { @@ -200,10 +275,15 @@ public : // Get the state (to determine it is within), we don't have // to cover the on-segment case (covered above) strategy.apply(turn.robust_point, previous, current, state); +#endif } } } +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // It is nowhere outside, and not on segment, so it is within + return analyse_within; +#else int const code = strategy.result(state); if (code == 1) { @@ -216,6 +296,7 @@ public : // Should normally not occur - on-segment is covered return analyse_unknown; +#endif } }; @@ -228,6 +309,49 @@ class analyse_turn_wrt_piece bool is_original, Point const& offsetted) { + boost::ignore_unused(offsetted); +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + typedef geometry::model::referring_segment<Point const> segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); + segment_type const r(s1, s2); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + if (side == 1) + { + // left of segment + return analyse_disjoint; + } + else if (side == 0) + { + // If is collinear, either on segment or before/after + typedef geometry::model::box<Point> box_type; + + box_type box; + geometry::assign_inverse(box); + geometry::expand(box, s1); + geometry::expand(box, s2); + + if (geometry::covered_by(turn.robust_point, box)) + { + // Points on helper-segments are considered as within + // Points on original boundary are processed differently + return is_original + ? analyse_on_original_boundary + : analyse_within; + } + + // It is collinear but not on the segment. Because these + // segments are convex, it is outside + // Unless the offsetted ring is collinear or concave w.r.t. + // helper-segment but that scenario is not yet supported + return analyse_disjoint; + } + + // right of segment + return analyse_continue; +#else typedef typename strategy::side::services::default_strategy < typename cs_tag<Point>::type @@ -276,6 +400,7 @@ class analyse_turn_wrt_piece // right of segment return analyse_continue; +#endif } template <typename Turn, typename Piece> @@ -286,7 +411,8 @@ class analyse_turn_wrt_piece point_type points[4]; - int helper_count = piece.robust_ring.size() - piece.offsetted_count; + signed_size_type helper_count = static_cast<signed_size_type>(piece.robust_ring.size()) + - piece.offsetted_count; if (helper_count == 4) { for (int i = 0; i < 4; i++) @@ -436,7 +562,7 @@ public : // It is small or not monotonic, walk linearly through offset // TODO: this will be combined with winding strategy - for (int i = 1; i < piece.offsetted_count; i++) + for (signed_size_type i = 1; i < piece.offsetted_count; i++) { point_type const& previous = piece.robust_ring[i - 1]; point_type const& current = piece.robust_ring[i]; @@ -492,6 +618,61 @@ class turn_in_piece_visitor return false; } +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // NOTE: this function returns a side value in {-1, 0, 1} + template <typename Turn, typename Piece> + static inline int turn_in_convex_piece(Turn const& turn, + Piece const& piece) + { + typedef typename Turn::robust_point_type point_type; + typedef typename Piece::piece_robust_ring_type ring_type; + typedef geometry::model::referring_segment<point_type const> segment; + + segment const p(turn.rob_pi, turn.rob_pj); + segment const q(turn.rob_qi, turn.rob_qj); + + typedef typename boost::range_iterator<ring_type const>::type iterator_type; + iterator_type it = boost::begin(piece.robust_ring); + iterator_type end = boost::end(piece.robust_ring); + + // A robust ring is always closed, and always clockwise + for (iterator_type previous = it++; it != end; ++previous, ++it) + { + geometry::equal_to<point_type> comparator; + if (comparator(*previous, *it)) + { + // Points are the same + continue; + } + + segment r(*previous, *it); + + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + if (side == 1) + { + // IP is left of segment, so it is outside + return -1; // outside + } + else if (side == 0) + { + // IP is collinear with segment. TODO: we should analyze this further + // For now we use the fallback point + if (in_box(*previous, *it, turn.robust_point)) + { + return 0; + } + else + { + return -1; // outside + } + } + } + return 1; // inside + } +#endif + public: @@ -530,12 +711,37 @@ public: } // TODO: mutable_piece to make some on-demand preparations in analyse + Turn& mutable_turn = m_turns[turn.turn_index]; + + if (piece.type == geometry::strategy::buffer::buffered_point) + { + // Optimization for buffer around points: if distance from center + // is not between min/max radius, the result is clear + typedef typename default_comparable_distance_result + < + typename Turn::robust_point_type + >::type distance_type; + + distance_type const cd + = geometry::comparable_distance(piece.robust_center, + turn.robust_point); + + if (cd < piece.robust_min_comparable_radius) + { + mutable_turn.count_within++; + return; + } + if (cd > piece.robust_max_comparable_radius) + { + return; + } + } + analyse_result analyse_code = piece.type == geometry::strategy::buffer::buffered_point ? analyse_turn_wrt_point_piece::apply(turn, piece) : analyse_turn_wrt_piece::apply(turn, piece); - Turn& mutable_turn = m_turns[turn.turn_index]; switch(analyse_code) { case analyse_disjoint : @@ -549,16 +755,32 @@ public: case analyse_within : mutable_turn.count_within++; return; +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) case analyse_near_offsetted : mutable_turn.count_within_near_offsetted++; return; +#endif default : break; } - // TODO: this point_in_geometry is a performance-bottleneck here and - // will be replaced completely by extending analyse_piece functionality +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // We don't know (yet) + int geometry_code = 0; + if (piece.is_convex) + { + geometry_code = turn_in_convex_piece(turn, piece); + } + else + { + + // TODO: this point_in_geometry is a performance-bottleneck here and + // will be replaced completely by extending analyse_piece functionality + geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); + } +#else int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); +#endif if (geometry_code == 1) { diff --git a/boost/geometry/algorithms/detail/check_iterator_range.hpp b/boost/geometry/algorithms/detail/check_iterator_range.hpp index 09ea7f79a0..9bd1d7ae27 100644 --- a/boost/geometry/algorithms/detail/check_iterator_range.hpp +++ b/boost/geometry/algorithms/detail/check_iterator_range.hpp @@ -33,7 +33,7 @@ struct check_iterator_range { for (InputIterator it = first; it != beyond; ++it) { - if ( !Predicate::apply(*it) ) + if (! Predicate::apply(*it)) { return false; } @@ -54,7 +54,7 @@ struct check_iterator_range for (InputIterator it = first; it != beyond; ++it) { - if ( !predicate.apply(*it) ) + if (! predicate.apply(*it)) { return false; } diff --git a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp index 04fa9ee86b..4ac5ac6976 100644 --- a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp +++ b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp @@ -12,8 +12,7 @@ #include <iterator> -#include <boost/assert.hpp> - +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/util/math.hpp> @@ -49,7 +48,7 @@ private: RangeIterator& it_min, Distance& dist_min) { - BOOST_ASSERT( first != last ); + BOOST_GEOMETRY_ASSERT( first != last ); Distance const zero = Distance(0); diff --git a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp index 91be6b0ad0..df67890138 100644 --- a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp +++ b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp @@ -12,9 +12,9 @@ #include <utility> -#include <boost/assert.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/closure.hpp> #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/util/math.hpp> @@ -51,7 +51,7 @@ protected: iterator_type& it_min2, Distance& dist_min) { - BOOST_ASSERT( first != last ); + BOOST_GEOMETRY_ASSERT( first != last ); Distance const zero = Distance(0); @@ -162,7 +162,7 @@ private: iterator_type& it_min2, Distance& dist_min) { - BOOST_ASSERT( first != last ); + BOOST_GEOMETRY_ASSERT( first != last ); base_type::apply(point, first, last, strategy, it_min1, it_min2, dist_min); diff --git a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp index ceba59b41a..26b8684828 100644 --- a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp +++ b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp @@ -15,8 +15,7 @@ #include <iterator> #include <utility> -#include <boost/assert.hpp> - +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/algorithms/dispatch/distance.hpp> @@ -56,8 +55,8 @@ private: { typedef index::rtree<RTreeValueType, index::linear<8> > rtree_type; - BOOST_ASSERT( rtree_first != rtree_last ); - BOOST_ASSERT( queries_first != queries_last ); + BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last ); + BOOST_GEOMETRY_ASSERT( queries_first != queries_last ); Distance const zero = Distance(0); dist_min = zero; @@ -73,13 +72,13 @@ private: { std::size_t n = rt.query(index::nearest(*qit, 1), &t_v); - BOOST_ASSERT( n > 0 ); - // n above is unused outside BOOST_ASSERT, hence the call - // to boost::ignore_unused below + BOOST_GEOMETRY_ASSERT( n > 0 ); + // n above is unused outside BOOST_GEOMETRY_ASSERT, + // hence the call to boost::ignore_unused below // // however, t_v (initialized by the call to rt.query(...)) // is used below, which is why we cannot put the call to - // rt.query(...) inside BOOST_ASSERT + // rt.query(...) inside BOOST_GEOMETRY_ASSERT boost::ignore_unused(n); Distance dist = dispatch::distance diff --git a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp index c443a54e58..86eec4c036 100644 --- a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp +++ b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp @@ -164,7 +164,7 @@ struct comparable_distance Geometry2 const& geometry2, Strategy const& strategy) { - return apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); + return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); } }; @@ -225,7 +225,7 @@ struct comparable_distance boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, Strategy const& strategy) { - return apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); + return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); } }; @@ -287,7 +287,7 @@ struct comparable_distance boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, Strategy const& strategy) { - return apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); + return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); } }; @@ -353,7 +353,7 @@ comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2) concept::check<Geometry1 const>(); concept::check<Geometry2 const>(); - return comparable_distance(geometry1, geometry2, default_strategy()); + return geometry::comparable_distance(geometry1, geometry2, default_strategy()); } diff --git a/boost/geometry/algorithms/detail/disjoint/interface.hpp b/boost/geometry/algorithms/detail/disjoint/interface.hpp index 96d6881296..18c010731e 100644 --- a/boost/geometry/algorithms/detail/disjoint/interface.hpp +++ b/boost/geometry/algorithms/detail/disjoint/interface.hpp @@ -175,7 +175,7 @@ struct disjoint< */ template <typename Geometry1, typename Geometry2> inline bool disjoint(Geometry1 const& geometry1, - Geometry2 const& geometry2) + Geometry2 const& geometry2) { return resolve_variant::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2); } diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index 7d1bb05242..29e438e546 100644 --- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -13,10 +13,20 @@ #include <algorithm> #include <vector> -#include <boost/assert.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/geometries/box.hpp> + +#include <boost/geometry/iterators/segment_iterator.hpp> + +#include <boost/geometry/algorithms/envelope.hpp> +#include <boost/geometry/algorithms/expand.hpp> + #include <boost/geometry/algorithms/detail/check_iterator_range.hpp> +#include <boost/geometry/algorithms/detail/partition.hpp> #include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp> #include <boost/geometry/algorithms/detail/disjoint/point_point.hpp> #include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp> @@ -33,7 +43,8 @@ namespace boost { namespace geometry namespace detail { namespace disjoint { -template<typename MultiPoint1, typename MultiPoint2> + +template <typename MultiPoint1, typename MultiPoint2> class multipoint_multipoint { private: @@ -66,7 +77,7 @@ public: static inline bool apply(MultiPoint1 const& multipoint1, MultiPoint2 const& multipoint2) { - BOOST_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) ); + BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) ); typedef typename boost::range_value<MultiPoint1>::type point1_type; @@ -90,6 +101,98 @@ public: }; +template <typename MultiPoint, typename Linear> +class multipoint_linear +{ +private: + // structs for partition -- start + struct expand_box + { + template <typename Box, typename Geometry> + static inline void apply(Box& total, Geometry const& geometry) + { + geometry::expand(total, geometry::return_envelope<Box>(geometry)); + } + + }; + + struct overlaps_box + { + template <typename Box, typename Geometry> + static inline bool apply(Box const& box, Geometry const& geometry) + { + return ! dispatch::disjoint<Geometry, Box>::apply(geometry, box); + } + }; + + class item_visitor_type + { + public: + item_visitor_type() : m_intersection_found(false) {} + + template <typename Item1, typename Item2> + inline void apply(Item1 const& item1, Item2 const& item2) + { + if (! m_intersection_found + && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2)) + { + m_intersection_found = true; + } + } + + inline bool intersection_found() const { return m_intersection_found; } + + private: + bool m_intersection_found; + }; + // structs for partition -- end + + class segment_range + { + public: + typedef geometry::segment_iterator<Linear const> const_iterator; + typedef const_iterator iterator; + + segment_range(Linear const& linear) + : m_linear(linear) + {} + + const_iterator begin() const + { + return geometry::segments_begin(m_linear); + } + + const_iterator end() const + { + return geometry::segments_end(m_linear); + } + + private: + Linear const& m_linear; + }; + +public: + static inline bool apply(MultiPoint const& multipoint, Linear const& linear) + { + item_visitor_type visitor; + + geometry::partition + < + geometry::model::box<typename point_type<MultiPoint>::type>, + expand_box, + overlaps_box + >::apply(multipoint, segment_range(linear), visitor); + + return ! visitor.intersection_found(); + } + + static inline bool apply(Linear const& linear, MultiPoint const& multipoint) + { + return apply(multipoint, linear); + } +}; + + }} // namespace detail::disjoint #endif // DOXYGEN_NO_DETAIL @@ -101,7 +204,7 @@ namespace dispatch { -template<typename Point, typename MultiPoint, std::size_t DimensionCount> +template <typename Point, typename MultiPoint, std::size_t DimensionCount> struct disjoint < Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false @@ -109,7 +212,7 @@ struct disjoint {}; -template<typename MultiPoint, typename Segment, std::size_t DimensionCount> +template <typename MultiPoint, typename Segment, std::size_t DimensionCount> struct disjoint < MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false @@ -117,7 +220,7 @@ struct disjoint {}; -template<typename MultiPoint, typename Box, std::size_t DimensionCount> +template <typename MultiPoint, typename Box, std::size_t DimensionCount> struct disjoint < MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false @@ -125,7 +228,12 @@ struct disjoint {}; -template<typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount> +template +< + typename MultiPoint1, + typename MultiPoint2, + std::size_t DimensionCount +> struct disjoint < MultiPoint1, MultiPoint2, DimensionCount, @@ -151,6 +259,22 @@ struct disjoint }; +template <typename Linear, typename MultiPoint, std::size_t DimensionCount> +struct disjoint + < + Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false + > : detail::disjoint::multipoint_linear<MultiPoint, Linear> +{}; + + +template <typename MultiPoint, typename Linear, std::size_t DimensionCount> +struct disjoint + < + MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false + > : detail::disjoint::multipoint_linear<MultiPoint, Linear> +{}; + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp index a58bff41da..9ae43f73d0 100644 --- a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp +++ b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp @@ -1,12 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -21,8 +21,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP -#include <boost/geometry/geometries/segment.hpp> - #include <boost/geometry/algorithms/covered_by.hpp> #include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp> @@ -39,24 +37,13 @@ namespace detail { namespace disjoint { -template<typename Point, typename Geometry> -struct disjoint_point_linear -{ - static inline - bool apply(Point const& pt, Geometry const& g) - { - return !geometry::covered_by(pt, g); - } -}; - - -template <typename Geometry1, typename Geometry2> struct reverse_covered_by { + template <typename Geometry1, typename Geometry2> static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { - return !geometry::covered_by(geometry1, geometry2); + return ! geometry::covered_by(geometry1, geometry2); } }; @@ -74,30 +61,20 @@ namespace dispatch template<typename Point, typename Linear, std::size_t DimensionCount> struct disjoint<Point, Linear, DimensionCount, point_tag, linear_tag, false> - : public detail::disjoint::disjoint_point_linear<Point, Linear> + : detail::disjoint::reverse_covered_by {}; template <typename Point, typename Areal, std::size_t DimensionCount> struct disjoint<Point, Areal, DimensionCount, point_tag, areal_tag, false> - : detail::disjoint::reverse_covered_by<Point, Areal> + : detail::disjoint::reverse_covered_by {}; template<typename Point, typename Segment, std::size_t DimensionCount> struct disjoint<Point, Segment, DimensionCount, point_tag, segment_tag, false> -{ - static inline bool apply(Point const& point, Segment const& segment) - { - typedef geometry::model::referring_segment<Point const> other_segment; - - other_segment other(point, point); - return detail::disjoint::disjoint_segment - < - Segment, other_segment - >::apply(segment, other); - } -}; + : detail::disjoint::reverse_covered_by +{}; } // namespace dispatch diff --git a/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/boost/geometry/algorithms/detail/disjoint/point_point.hpp index b1d32bf95e..7580b7287b 100644 --- a/boost/geometry/algorithms/detail/disjoint/point_point.hpp +++ b/boost/geometry/algorithms/detail/disjoint/point_point.hpp @@ -1,12 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -23,11 +23,26 @@ #include <cstddef> +#include <boost/type_traits/is_same.hpp> + #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/tags.hpp> #include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/select_most_precise.hpp> + +#include <boost/geometry/strategies/strategy_transform.hpp> + +#include <boost/geometry/geometries/helper_geometry.hpp> + +#include <boost/geometry/algorithms/transform.hpp> + +#include <boost/geometry/algorithms/detail/normalize.hpp> #include <boost/geometry/algorithms/dispatch/disjoint.hpp> @@ -40,38 +55,146 @@ namespace boost { namespace geometry namespace detail { namespace disjoint { -template -< - typename Point1, typename Point2, - std::size_t Dimension, std::size_t DimensionCount -> -struct point_point + +template <std::size_t Dimension, std::size_t DimensionCount> +struct point_point_generic { + template <typename Point1, typename Point2> static inline bool apply(Point1 const& p1, Point2 const& p2) { if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2))) { return true; } - return point_point - < - Point1, Point2, - Dimension + 1, DimensionCount - >::apply(p1, p2); + return + point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2); } }; - -template <typename Point1, typename Point2, std::size_t DimensionCount> -struct point_point<Point1, Point2, DimensionCount, DimensionCount> +template <std::size_t DimensionCount> +struct point_point_generic<DimensionCount, DimensionCount> { - static inline bool apply(Point1 const& , Point2 const& ) + template <typename Point1, typename Point2> + static inline bool apply(Point1 const&, Point2 const&) { return false; } }; +class point_point_on_spheroid +{ +private: + template <typename Point1, typename Point2, bool SameUnits> + struct are_same_points + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename helper_geometry<Point1>::type helper_point_type1; + typedef typename helper_geometry<Point2>::type helper_point_type2; + + helper_point_type1 point1_normalized + = return_normalized<helper_point_type1>(point1); + helper_point_type2 point2_normalized + = return_normalized<helper_point_type2>(point2); + + return point_point_generic + < + 0, dimension<Point1>::value + >::apply(point1_normalized, point2_normalized); + } + }; + + template <typename Point1, typename Point2> + struct are_same_points<Point1, Point2, false> // points have different units + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename geometry::select_most_precise + < + typename fp_coordinate_type<Point1>::type, + typename fp_coordinate_type<Point2>::type + >::type calculation_type; + + typename helper_geometry + < + Point1, calculation_type, radian + >::type helper_point1, helper_point2; + + Point1 point1_normalized = return_normalized<Point1>(point1); + Point2 point2_normalized = return_normalized<Point2>(point2); + + geometry::transform(point1_normalized, helper_point1); + geometry::transform(point2_normalized, helper_point2); + + return point_point_generic + < + 0, dimension<Point1>::value + >::apply(helper_point1, helper_point2); + } + }; + +public: + template <typename Point1, typename Point2> + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + return are_same_points + < + Point1, + Point2, + boost::is_same + < + typename coordinate_system<Point1>::type::units, + typename coordinate_system<Point2>::type::units + >::value + >::apply(point1, point2); + } +}; + + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount, + typename CSTag1 = typename cs_tag<Point1>::type, + typename CSTag2 = CSTag1 +> +struct point_point + : point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag> +{}; + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_point + < + Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag + > : point_point_on_spheroid +{}; + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_point + < + Point1, Point2, Dimension, DimensionCount, geographic_tag + > : point_point_on_spheroid +{}; + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag> + : point_point_generic<Dimension, DimensionCount> +{}; + + /*! \brief Internal utility function to detect of points are disjoint \note To avoid circular references diff --git a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp index 57257dbdcc..d6de7cac91 100644 --- a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp +++ b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp @@ -185,10 +185,10 @@ public: Geometry const > segment_iterator_type; - typedef typename std::vector + typedef typename boost::range_const_iterator < - segment_or_box_point - >::const_iterator seg_or_box_iterator_type; + std::vector<segment_or_box_point> + >::type seg_or_box_const_iterator; typedef assign_new_min_iterator<SegmentOrBox> assign_new_value; @@ -219,8 +219,9 @@ public: // segment or box comparable_return_type cd_min1(0); point_iterator_type pit_min; - seg_or_box_iterator_type it_min1 = seg_or_box_points.begin(); - seg_or_box_iterator_type it_min2 = ++seg_or_box_points.begin(); + seg_or_box_const_iterator it_min1 = boost::const_begin(seg_or_box_points); + seg_or_box_const_iterator it_min2 = it_min1; + ++it_min2; bool first = true; for (point_iterator_type pit = points_begin(geometry); @@ -229,11 +230,11 @@ public: comparable_return_type cd; std::pair < - seg_or_box_iterator_type, seg_or_box_iterator_type + seg_or_box_const_iterator, seg_or_box_const_iterator > it_pair = point_to_point_range::apply(*pit, - seg_or_box_points.begin(), - seg_or_box_points.end(), + boost::const_begin(seg_or_box_points), + boost::const_end(seg_or_box_points), cstrategy, cd); @@ -250,12 +251,11 @@ public: // segments of the geometry comparable_return_type cd_min2(0); segment_iterator_type sit_min; - typename std::vector<segment_or_box_point>::const_iterator it_min; + seg_or_box_const_iterator it_min; first = true; - for (typename std::vector<segment_or_box_point>::const_iterator it - = seg_or_box_points.begin(); - it != seg_or_box_points.end(); ++it, first = false) + for (seg_or_box_const_iterator it = boost::const_begin(seg_or_box_points); + it != boost::const_end(seg_or_box_points); ++it, first = false) { comparable_return_type cd; segment_iterator_type sit diff --git a/boost/geometry/algorithms/detail/distance/interface.hpp b/boost/geometry/algorithms/detail/distance/interface.hpp index fa8cbd69ee..1e7cc433ef 100644 --- a/boost/geometry/algorithms/detail/distance/interface.hpp +++ b/boost/geometry/algorithms/detail/distance/interface.hpp @@ -198,7 +198,7 @@ struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> Geometry2 const& geometry2, Strategy const& strategy) { - return apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); + return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1); } }; @@ -253,7 +253,7 @@ struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2, Strategy const& strategy) { - return apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); + return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2); } }; @@ -312,7 +312,7 @@ struct distance boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, Strategy const& strategy) { - return apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); + return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2); } }; @@ -395,7 +395,7 @@ distance(Geometry1 const& geometry1, concept::check<Geometry1 const>(); concept::check<Geometry2 const>(); - return distance(geometry1, geometry2, default_strategy()); + return geometry::distance(geometry1, geometry2, default_strategy()); } }} // namespace boost::geometry diff --git a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp index 78189794a1..6e78bee694 100644 --- a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp +++ b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp @@ -13,8 +13,7 @@ #include <iterator> #include <utility> -#include <boost/assert.hpp> - +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/iterators/has_one_element.hpp> @@ -70,7 +69,7 @@ public: { namespace sds = strategy::distance::services; - BOOST_ASSERT( first != last ); + BOOST_GEOMETRY_ASSERT( first != last ); if ( geometry::has_one_element(first, last) ) { diff --git a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index 79d9adb703..783699ee0a 100644 --- a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -15,13 +15,13 @@ #include <functional> #include <vector> -#include <boost/assert.hpp> #include <boost/core/ignore_unused.hpp> #include <boost/mpl/if.hpp> #include <boost/numeric/conversion/cast.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/point_type.hpp> @@ -561,7 +561,7 @@ private: typedef compare_less_equal<ReturnType, true> less_equal; // assert that the segment has non-negative slope - BOOST_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1)) + BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1)) && geometry::get<1>(p0) < geometry::get<1>(p1)) || ( geometry::get<0>(p0) < geometry::get<0>(p1) @@ -617,7 +617,7 @@ private: typedef compare_less_equal<ReturnType, false> greater_equal; // assert that the segment has negative slope - BOOST_ASSERT( geometry::get<0>(p0) < geometry::get<0>(p1) + BOOST_GEOMETRY_ASSERT( geometry::get<0>(p0) < geometry::get<0>(p1) && geometry::get<1>(p0) > geometry::get<1>(p1) ); ReturnType result(0); @@ -665,7 +665,7 @@ public: PPStrategy const& pp_strategy, PSStrategy const& ps_strategy) { - BOOST_ASSERT( geometry::less<SegmentPoint>()(p0, p1) ); + BOOST_GEOMETRY_ASSERT( geometry::less<SegmentPoint>()(p0, p1) ); if (geometry::get<0>(p0) < geometry::get<0>(p1) && geometry::get<1>(p0) > geometry::get<1>(p1)) diff --git a/boost/geometry/algorithms/detail/envelope/box.hpp b/boost/geometry/algorithms/detail/envelope/box.hpp new file mode 100644 index 0000000000..3790262948 --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/box.hpp @@ -0,0 +1,167 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP + +#include <cstddef> + +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> +#include <boost/geometry/algorithms/detail/normalize.hpp> +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +< + std::size_t Index, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope_indexed_box +{ + template <typename BoxIn, typename BoxOut> + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in); + detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr); + + detail::conversion::point_to_point + < + detail::indexed_point_view<BoxIn const, Index>, + detail::indexed_point_view<BoxOut, Index>, + Dimension, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + +template +< + std::size_t Index, + std::size_t DimensionCount +> +struct envelope_indexed_box_on_spheroid +{ + template <typename BoxIn, typename BoxOut> + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + // transform() does not work with boxes of dimension higher + // than 2; to account for such boxes we transform the min/max + // points of the boxes using the indexed_point_view + detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in); + detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr); + + // first transform the units + transform_units(box_in_corner, mbr_corner); + + // now transform the remaining coordinates + detail::conversion::point_to_point + < + detail::indexed_point_view<BoxIn const, Index>, + detail::indexed_point_view<BoxOut, Index>, + 2, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + + +struct envelope_box +{ + template<typename BoxIn, typename BoxOut> + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + envelope_indexed_box + < + min_corner, 0, dimension<BoxIn>::value + >::apply(box_in, mbr); + + envelope_indexed_box + < + max_corner, 0, dimension<BoxIn>::value + >::apply(box_in, mbr); + } +}; + + +struct envelope_box_on_spheroid +{ + template <typename BoxIn, typename BoxOut> + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in); + + envelope_indexed_box_on_spheroid + < + min_corner, dimension<BoxIn>::value + >::apply(box_in_normalized, mbr); + + envelope_indexed_box_on_spheroid + < + max_corner, dimension<BoxIn>::value + >::apply(box_in_normalized, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template <typename Box, typename CS_Tag> +struct envelope<Box, box_tag, CS_Tag> + : detail::envelope::envelope_box +{}; + + +template <typename Box> +struct envelope<Box, box_tag, spherical_equatorial_tag> + : detail::envelope::envelope_box_on_spheroid +{}; + + +template <typename Box> +struct envelope<Box, box_tag, geographic_tag> + : detail::envelope::envelope_box_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP diff --git a/boost/geometry/algorithms/detail/envelope/implementation.hpp b/boost/geometry/algorithms/detail/envelope/implementation.hpp new file mode 100644 index 0000000000..c1dbf8e589 --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -0,0 +1,106 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP + +#include <boost/geometry/core/exterior_ring.hpp> +#include <boost/geometry/core/interior_rings.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/is_empty.hpp> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/linear.hpp> +#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp> +#include <boost/geometry/algorithms/detail/envelope/point.hpp> +#include <boost/geometry/algorithms/detail/envelope/range.hpp> +#include <boost/geometry/algorithms/detail/envelope/segment.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +struct envelope_polygon +{ + template <typename Polygon, typename Box> + static inline void apply(Polygon const& polygon, Box& mbr) + { + typename ring_return_type<Polygon const>::type ext_ring + = exterior_ring(polygon); + + if (geometry::is_empty(ext_ring)) + { + // if the exterior ring is empty, consider the interior rings + envelope_multi_range + < + envelope_range + >::apply(interior_rings(polygon), mbr); + } + else + { + // otherwise, consider only the exterior ring + envelope_range::apply(ext_ring, mbr); + } + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template <typename Ring> +struct envelope<Ring, ring_tag> + : detail::envelope::envelope_range +{}; + + +template <typename Polygon> +struct envelope<Polygon, polygon_tag> + : detail::envelope::envelope_polygon +{}; + + +template <typename MultiPolygon> +struct envelope<MultiPolygon, multi_polygon_tag> + : detail::envelope::envelope_multi_range + < + detail::envelope::envelope_polygon + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP diff --git a/boost/geometry/algorithms/detail/envelope/initialize.hpp b/boost/geometry/algorithms/detail/envelope/initialize.hpp new file mode 100644 index 0000000000..d8e252b53a --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/initialize.hpp @@ -0,0 +1,86 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP + +#include <cstddef> + +#include <boost/numeric/conversion/bounds.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_type.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + +template <std::size_t Dimension, std::size_t DimensionCount> +struct initialize_loop +{ + template <typename Box, typename CoordinateType> + static inline void apply(Box& box, + CoordinateType min_value, + CoordinateType max_value) + { + geometry::set<min_corner, Dimension>(box, min_value); + geometry::set<max_corner, Dimension>(box, max_value); + + initialize_loop + < + Dimension + 1, DimensionCount + >::apply(box, min_value, max_value); + } +}; + +template <std::size_t DimensionCount> +struct initialize_loop<DimensionCount, DimensionCount> +{ + template <typename Box, typename CoordinateType> + static inline void apply(Box&, CoordinateType, CoordinateType) + { + } +}; + + +template +< + typename Box, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension<Box>::value +> +struct initialize +{ + typedef typename coordinate_type<Box>::type coordinate_type; + + static inline void apply(Box& box, + coordinate_type min_value + = boost::numeric::bounds<coordinate_type>::highest(), + coordinate_type max_value + = boost::numeric::bounds<coordinate_type>::lowest()) + { + initialize_loop + < + Dimension, DimensionCount + >::apply(box, min_value, max_value); + } +}; + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp new file mode 100644 index 0000000000..997ac1b23e --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/interface.hpp @@ -0,0 +1,126 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP + +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> + +#include <boost/geometry/geometries/concepts/check.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +namespace resolve_variant +{ + +template <typename Geometry> +struct envelope +{ + template <typename Box> + static inline void apply(Geometry const& geometry, Box& box) + { + concept::check<Geometry const>(); + concept::check<Box>(); + + dispatch::envelope<Geometry>::apply(geometry, box); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Box> + struct visitor: boost::static_visitor<void> + { + Box& m_box; + + visitor(Box& box): m_box(box) {} + + template <typename Geometry> + void operator()(Geometry const& geometry) const + { + envelope<Geometry>::apply(geometry, m_box); + } + }; + + template <typename Box> + static inline void + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, + Box& box) + { + boost::apply_visitor(visitor<Box>(box), geometry); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc{envelope} +\ingroup envelope +\details \details_calc{envelope,\det_envelope}. +\tparam Geometry \tparam_geometry +\tparam Box \tparam_box +\param geometry \param_geometry +\param mbr \param_box \param_set{envelope} + +\qbk{[include reference/algorithms/envelope.qbk]} +\qbk{ +[heading Example] +[envelope] [envelope_output] +} +*/ +template<typename Geometry, typename Box> +inline void envelope(Geometry const& geometry, Box& mbr) +{ + resolve_variant::envelope<Geometry>::apply(geometry, mbr); +} + + +/*! +\brief \brief_calc{envelope} +\ingroup envelope +\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope} +\tparam Box \tparam_box +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\return \return_calc{envelope} + +\qbk{[include reference/algorithms/envelope.qbk]} +\qbk{ +[heading Example] +[return_envelope] [return_envelope_output] +} +*/ +template<typename Box, typename Geometry> +inline Box return_envelope(Geometry const& geometry) +{ + Box mbr; + resolve_variant::envelope<Geometry>::apply(geometry, mbr); + return mbr; +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP diff --git a/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp new file mode 100644 index 0000000000..47937bf740 --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp @@ -0,0 +1,78 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_system.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/geometry/algorithms/detail/normalize.hpp> + + +namespace boost { namespace geometry +{ + +namespace detail { namespace envelope +{ + + +struct intersects_antimeridian +{ + template <typename Units, typename CoordinateType> + static inline bool apply(CoordinateType const& lon1, + CoordinateType const& lat1, + CoordinateType const& lon2, + CoordinateType const& lat2) + { + typedef math::detail::constants_on_spheroid + < + CoordinateType, Units + > constants; + + return + math::equals(math::abs(lat1), constants::max_latitude()) + || + math::equals(math::abs(lat2), constants::max_latitude()) + || + math::larger(math::abs(lon1 - lon2), constants::half_period()); + } + + template <typename Segment> + static inline bool apply(Segment const& segment) + { + return apply(detail::indexed_point_view<Segment, 0>(segment), + detail::indexed_point_view<Segment, 1>(segment)); + } + + template <typename Point> + static inline bool apply(Point const& p1, Point const& p2) + { + Point p1_normalized = detail::return_normalized<Point>(p1); + Point p2_normalized = detail::return_normalized<Point>(p2); + + return apply + < + typename coordinate_system<Point>::type::units + >(geometry::get<0>(p1_normalized), + geometry::get<1>(p1_normalized), + geometry::get<0>(p2_normalized), + geometry::get<1>(p2_normalized)); + } +}; + + +}} // namespace detail::envelope + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP diff --git a/boost/geometry/algorithms/detail/envelope/linear.hpp b/boost/geometry/algorithms/detail/envelope/linear.hpp new file mode 100644 index 0000000000..49c3cf3135 --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/linear.hpp @@ -0,0 +1,96 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP + +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/iterators/segment_iterator.hpp> + +#include <boost/geometry/algorithms/detail/envelope/range.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +struct envelope_linestring_on_spheroid +{ + template <typename Linestring, typename Box> + static inline void apply(Linestring const& linestring, Box& mbr) + { + envelope_range::apply(geometry::segments_begin(linestring), + geometry::segments_end(linestring), + mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template <typename Linestring, typename CS_Tag> +struct envelope<Linestring, linestring_tag, CS_Tag> + : detail::envelope::envelope_range +{}; + +template <typename Linestring> +struct envelope<Linestring, linestring_tag, spherical_equatorial_tag> + : detail::envelope::envelope_linestring_on_spheroid +{}; + + +template <typename MultiLinestring, typename CS_Tag> +struct envelope + < + MultiLinestring, multi_linestring_tag, CS_Tag + > : detail::envelope::envelope_multi_range + < + detail::envelope::envelope_range + > +{}; + +template <typename MultiLinestring> +struct envelope + < + MultiLinestring, multi_linestring_tag, spherical_equatorial_tag + > : detail::envelope::envelope_multi_range_on_spheroid + < + detail::envelope::envelope_linestring_on_spheroid + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP diff --git a/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/boost/geometry/algorithms/detail/envelope/multipoint.hpp new file mode 100644 index 0000000000..210debfdba --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -0,0 +1,378 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP + +#include <cstddef> +#include <algorithm> +#include <utility> +#include <vector> + +#include <boost/algorithm/minmax_element.hpp> +#include <boost/range.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/range.hpp> + +#include <boost/geometry/geometries/helper_geometry.hpp> + +#include <boost/geometry/algorithms/detail/normalize.hpp> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/initialize.hpp> +#include <boost/geometry/algorithms/detail/envelope/range.hpp> +#include <boost/geometry/algorithms/detail/expand/point.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +class envelope_multipoint_on_spheroid +{ +private: + template <std::size_t Dim> + struct coordinate_less + { + template <typename Point> + inline bool operator()(Point const& point1, Point const& point2) const + { + return math::smaller(geometry::get<Dim>(point1), + geometry::get<Dim>(point2)); + } + }; + + template <typename Constants, typename MultiPoint, typename OutputIterator> + static inline void analyze_point_coordinates(MultiPoint const& multipoint, + bool& has_south_pole, + bool& has_north_pole, + OutputIterator oit) + { + typedef typename boost::range_value<MultiPoint>::type point_type; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; + + // analyze point coordinates: + // (1) normalize point coordinates + // (2) check if any point is the north or the south pole + // (3) put all non-pole points in a container + // + // notice that at this point in the algorithm, we have at + // least two points on the spheroid + has_south_pole = false; + has_north_pole = false; + + for (iterator_type it = boost::begin(multipoint); + it != boost::end(multipoint); + ++it) + { + point_type point = detail::return_normalized<point_type>(*it); + + if (math::equals(geometry::get<1>(point), + Constants::min_latitude())) + { + has_south_pole = true; + } + else if (math::equals(geometry::get<1>(point), + Constants::max_latitude())) + { + has_north_pole = true; + } + else + { + *oit++ = point; + } + } + } + + template <typename SortedRange, typename Value> + static inline Value maximum_gap(SortedRange const& sorted_range, + Value& max_gap_left, + Value& max_gap_right) + { + typedef typename boost::range_iterator + < + SortedRange const + >::type iterator_type; + + iterator_type it1 = boost::begin(sorted_range), it2 = it1; + ++it2; + max_gap_left = geometry::get<0>(*it1); + max_gap_right = geometry::get<0>(*it2); + + Value max_gap = max_gap_right - max_gap_left; + for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2) + { + Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1); + if (math::larger(gap, max_gap)) + { + max_gap_left = geometry::get<0>(*it1); + max_gap_right = geometry::get<0>(*it2); + max_gap = gap; + } + } + + return max_gap; + } + + template + < + typename Constants, + typename PointRange, + typename LongitudeLess, + typename CoordinateType + > + static inline void get_min_max_longitudes(PointRange& range, + LongitudeLess const& lon_less, + CoordinateType& lon_min, + CoordinateType& lon_max) + { + typedef typename boost::range_iterator + < + PointRange const + >::type iterator_type; + + // compute min and max longitude values + std::pair<iterator_type, iterator_type> min_max_longitudes + = boost::minmax_element(boost::begin(range), + boost::end(range), + lon_less); + + lon_min = geometry::get<0>(*min_max_longitudes.first); + lon_max = geometry::get<0>(*min_max_longitudes.second); + + // if the longitude span is "large" compute the true maximum gap + if (math::larger(lon_max - lon_min, Constants::half_period())) + { + std::sort(boost::begin(range), boost::end(range), lon_less); + + CoordinateType max_gap_left = 0, max_gap_right = 0; + CoordinateType max_gap + = maximum_gap(range, max_gap_left, max_gap_right); + + CoordinateType complement_gap + = Constants::period() + lon_min - lon_max; + + if (math::larger(max_gap, complement_gap)) + { + lon_min = max_gap_right; + lon_max = max_gap_left + Constants::period(); + } + } + } + + template + < + typename Constants, + typename Iterator, + typename LatitudeLess, + typename CoordinateType + > + static inline void get_min_max_latitudes(Iterator const first, + Iterator const last, + LatitudeLess const& lat_less, + bool has_south_pole, + bool has_north_pole, + CoordinateType& lat_min, + CoordinateType& lat_max) + { + if (has_south_pole && has_north_pole) + { + lat_min = Constants::min_latitude(); + lat_max = Constants::max_latitude(); + } + else if (has_south_pole) + { + lat_min = Constants::min_latitude(); + lat_max + = geometry::get<1>(*std::max_element(first, last, lat_less)); + } + else if (has_north_pole) + { + lat_min + = geometry::get<1>(*std::min_element(first, last, lat_less)); + lat_max = Constants::max_latitude(); + } + else + { + std::pair<Iterator, Iterator> min_max_latitudes + = boost::minmax_element(first, last, lat_less); + + lat_min = geometry::get<1>(*min_max_latitudes.first); + lat_max = geometry::get<1>(*min_max_latitudes.second); + } + } + +public: + template <typename MultiPoint, typename Box> + static inline void apply(MultiPoint const& multipoint, Box& mbr) + { + typedef typename point_type<MultiPoint>::type point_type; + typedef typename coordinate_type<MultiPoint>::type coordinate_type; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; + + typedef math::detail::constants_on_spheroid + < + coordinate_type, + typename coordinate_system<MultiPoint>::type::units + > constants; + + if (boost::empty(multipoint)) + { + initialize<Box, 0, dimension<Box>::value>::apply(mbr); + return; + } + + initialize<Box, 0, 2>::apply(mbr); + + if (boost::size(multipoint) == 1) + { + return dispatch::envelope + < + typename boost::range_value<MultiPoint>::type + >::apply(range::front(multipoint), mbr); + } + + // analyze the points and put the non-pole ones in the + // points vector + std::vector<point_type> points; + bool has_north_pole = false, has_south_pole = false; + + analyze_point_coordinates<constants>(multipoint, + has_south_pole, has_north_pole, + std::back_inserter(points)); + + coordinate_type lon_min, lat_min, lon_max, lat_max; + if (points.size() == 1) + { + // we have one non-pole point and at least one pole point + lon_min = geometry::get<0>(range::front(points)); + lon_max = geometry::get<0>(range::front(points)); + lat_min = has_south_pole + ? constants::min_latitude() + : constants::max_latitude(); + lat_max = has_north_pole + ? constants::max_latitude() + : constants::min_latitude(); + } + else if (points.empty()) + { + // all points are pole points + BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole); + lon_min = coordinate_type(0); + lon_max = coordinate_type(0); + lat_min = has_south_pole + ? constants::min_latitude() + : constants::max_latitude(); + lat_max = (has_north_pole) + ? constants::max_latitude() + : constants::min_latitude(); + } + else + { + get_min_max_longitudes<constants>(points, + coordinate_less<0>(), + lon_min, + lon_max); + + get_min_max_latitudes<constants>(points.begin(), + points.end(), + coordinate_less<1>(), + has_south_pole, + has_north_pole, + lat_min, + lat_max); + } + + typedef typename helper_geometry + < + Box, + coordinate_type, + typename coordinate_system<MultiPoint>::type::units + >::type helper_box_type; + + helper_box_type helper_mbr; + + geometry::set<min_corner, 0>(helper_mbr, lon_min); + geometry::set<min_corner, 1>(helper_mbr, lat_min); + geometry::set<max_corner, 0>(helper_mbr, lon_max); + geometry::set<max_corner, 1>(helper_mbr, lat_max); + + // now transform to output MBR (per index) + envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr); + envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr); + + // compute envelope for higher coordinates + iterator_type it = boost::begin(multipoint); + envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr); + + for (++it; it != boost::end(multipoint); ++it) + { + detail::expand::point_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + 2, dimension<Box>::value + >::apply(mbr, *it); + } + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template <typename MultiPoint, typename CSTag> +struct envelope<MultiPoint, multi_point_tag, CSTag> + : detail::envelope::envelope_range +{}; + +template <typename MultiPoint> +struct envelope<MultiPoint, multi_point_tag, spherical_equatorial_tag> + : detail::envelope::envelope_multipoint_on_spheroid +{}; + +template <typename MultiPoint> +struct envelope<MultiPoint, multi_point_tag, geographic_tag> + : detail::envelope::envelope_multipoint_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP diff --git a/boost/geometry/algorithms/detail/envelope/point.hpp b/boost/geometry/algorithms/detail/envelope/point.hpp new file mode 100644 index 0000000000..e914e7e8a0 --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/point.hpp @@ -0,0 +1,127 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP + +#include <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> +#include <boost/geometry/algorithms/detail/normalize.hpp> + +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template <std::size_t Dimension, std::size_t DimensionCount> +struct envelope_one_point +{ + template <std::size_t Index, typename Point, typename Box> + static inline void apply(Point const& point, Box& mbr) + { + detail::indexed_point_view<Box, Index> box_corner(mbr); + detail::conversion::point_to_point + < + Point, + detail::indexed_point_view<Box, Index>, + Dimension, + DimensionCount + >::apply(point, box_corner); + } + + template <typename Point, typename Box> + static inline void apply(Point const& point, Box& mbr) + { + apply<min_corner>(point, mbr); + apply<max_corner>(point, mbr); + } +}; + + +struct envelope_point_on_spheroid +{ + template<typename Point, typename Box> + static inline void apply(Point const& point, Box& mbr) + { + Point normalized_point = detail::return_normalized<Point>(point); + + typename point_type<Box>::type box_point; + + // transform units of input point to units of a box point + transform_units(normalized_point, box_point); + + geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point)); + geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point)); + + geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point)); + geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point)); + + envelope_one_point + < + 2, dimension<Point>::value + >::apply(normalized_point, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template <typename Point, typename CS_Tag> +struct envelope<Point, point_tag, CS_Tag> + : detail::envelope::envelope_one_point<0, dimension<Point>::value> +{}; + + +template <typename Point> +struct envelope<Point, point_tag, spherical_equatorial_tag> + : detail::envelope::envelope_point_on_spheroid +{}; + + +template <typename Point> +struct envelope<Point, point_tag, geographic_tag> + : detail::envelope::envelope_point_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp new file mode 100644 index 0000000000..63b518114b --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/range.hpp @@ -0,0 +1,179 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP + +#include <iterator> +#include <vector> + +#include <boost/range.hpp> + +#include <boost/geometry/core/coordinate_dimension.hpp> + +#include <boost/geometry/util/range.hpp> + +#include <boost/geometry/algorithms/is_empty.hpp> + +#include <boost/geometry/algorithms/detail/envelope/initialize.hpp> +#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> + +#include <boost/geometry/algorithms/detail/expand/box.hpp> +#include <boost/geometry/algorithms/detail/expand/point.hpp> +#include <boost/geometry/algorithms/detail/expand/segment.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +// implementation for simple ranges +struct envelope_range +{ + template <typename Iterator, typename Box> + static inline void apply(Iterator first, Iterator last, Box& mbr) + { + typedef typename std::iterator_traits<Iterator>::value_type value_type; + + // initialize MBR + initialize<Box, 0, dimension<Box>::value>::apply(mbr); + + Iterator it = first; + if (it != last) + { + // initialize box with first element in range + dispatch::envelope<value_type>::apply(*it, mbr); + + // consider now the remaining elements in the range (if any) + for (++it; it != last; ++it) + { + dispatch::expand<Box, value_type>::apply(mbr, *it); + } + } + } + + template <typename Range, typename Box> + static inline void apply(Range const& range, Box& mbr) + { + return apply(boost::begin(range), boost::end(range), mbr); + } +}; + + +// implementation for multi-ranges +template <typename EnvelopePolicy> +struct envelope_multi_range +{ + template <typename MultiRange, typename Box> + static inline void apply(MultiRange const& multirange, Box& mbr) + { + typedef typename boost::range_iterator + < + MultiRange const + >::type iterator_type; + + bool initialized = false; + for (iterator_type it = boost::begin(multirange); + it != boost::end(multirange); + ++it) + { + if (! geometry::is_empty(*it)) + { + if (initialized) + { + Box helper_mbr; + EnvelopePolicy::apply(*it, helper_mbr); + + dispatch::expand<Box, Box>::apply(mbr, helper_mbr); + } + else + { + // compute the initial envelope + EnvelopePolicy::apply(*it, mbr); + initialized = true; + } + } + } + + if (! initialized) + { + // if not already initialized, initialize MBR + initialize<Box, 0, dimension<Box>::value>::apply(mbr); + } + } +}; + + +// implementation for multi-range on a spheroid (longitude is periodic) +template <typename EnvelopePolicy> +struct envelope_multi_range_on_spheroid +{ + template <typename MultiRange, typename Box> + static inline void apply(MultiRange const& multirange, Box& mbr) + { + typedef typename boost::range_iterator + < + MultiRange const + >::type iterator_type; + + // due to the periodicity of longitudes we need to compute the boxes + // of all the single geometries and keep them in a container + std::vector<Box> boxes; + for (iterator_type it = boost::begin(multirange); + it != boost::end(multirange); + ++it) + { + if (! geometry::is_empty(*it)) + { + Box helper_box; + EnvelopePolicy::apply(*it, helper_box); + boxes.push_back(helper_box); + } + } + + // now we need to compute the envelope of the range of boxes + // (cannot be done in an incremental fashion as in the + // Cartesian coordinate system) + // if all single geometries are empty no boxes have been found + // and the MBR is simply initialized + if (! boxes.empty()) + { + envelope_range_of_boxes::apply(boxes, mbr); + } + else + { + initialize<Box, 0, dimension<Box>::value>::apply(mbr); + } + + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp new file mode 100644 index 0000000000..64bdb9b9cb --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -0,0 +1,326 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP + +#include <cstddef> + +#include <algorithm> +#include <vector> + +#include <boost/range.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> + +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/range.hpp> + +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> +#include <boost/geometry/algorithms/detail/max_interval_gap.hpp> +#include <boost/geometry/algorithms/detail/expand/indexed.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template <typename T> +class longitude_interval +{ + typedef T const& reference_type; + +public: + typedef T value_type; + typedef T difference_type; + + longitude_interval(T const& left, T const& right) + { + m_end[0] = left; + m_end[1] = right; + } + + template <std::size_t Index> + reference_type get() const + { + return m_end[Index]; + } + + difference_type length() const + { + return get<1>() - get<0>(); + } + +private: + T m_end[2]; +}; + + +template <typename Units> +struct envelope_range_of_longitudes +{ + template <std::size_t Index> + struct longitude_less + { + template <typename Interval> + inline bool operator()(Interval const& i1, Interval const& i2) const + { + return math::smaller(i1.template get<Index>(), + i2.template get<Index>()); + } + }; + + template <typename RangeOfLongitudeIntervals, typename Longitude> + static inline void apply(RangeOfLongitudeIntervals const& range, + Longitude& lon_min, Longitude& lon_max) + { + typedef typename math::detail::constants_on_spheroid + < + Longitude, Units + > constants; + + Longitude const zero = 0; + Longitude const period = constants::period(); + + lon_min = lon_max = zero; + + // the range of longitude intervals can be empty if all input boxes + // degenerate to the north or south pole (or combination of the two) + // in this case the initialization values for lon_min and + // lon_max are valid choices + if (! boost::empty(range)) + { + lon_min = std::min_element(boost::begin(range), + boost::end(range), + longitude_less<0>())->template get<0>(); + lon_max = std::max_element(boost::begin(range), + boost::end(range), + longitude_less<1>())->template get<1>(); + + if (math::larger(lon_max - lon_min, constants::half_period())) + { + Longitude max_gap_left, max_gap_right; + Longitude max_gap = geometry::maximum_gap(range, + max_gap_left, + max_gap_right); + + BOOST_GEOMETRY_ASSERT(! math::larger(lon_min, lon_max)); + BOOST_GEOMETRY_ASSERT + (! math::larger(lon_max, constants::max_longitude())); + BOOST_GEOMETRY_ASSERT + (! math::smaller(lon_min, constants::min_longitude())); + + BOOST_GEOMETRY_ASSERT + (! math::larger(max_gap_left, max_gap_right)); + BOOST_GEOMETRY_ASSERT + (! math::larger(max_gap_right, constants::max_longitude())); + BOOST_GEOMETRY_ASSERT + (! math::smaller(max_gap_left, constants::min_longitude())); + + if (math::larger(max_gap, zero)) + { + Longitude wrapped_gap = period + lon_min - lon_max; + if (math::larger(max_gap, wrapped_gap)) + { + lon_min = max_gap_right; + lon_max = max_gap_left + period; + } + } + } + } + } +}; + + +template <std::size_t Dimension, std::size_t DimensionCount> +struct envelope_range_of_boxes_by_expansion +{ + template <typename RangeOfBoxes, typename Box> + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) + { + typedef typename boost::range_value<RangeOfBoxes>::type box_type; + + typedef typename boost::range_iterator + < + RangeOfBoxes const + >::type iterator_type; + + // first initialize MBR + detail::indexed_point_view<Box, min_corner> mbr_min(mbr); + detail::indexed_point_view<Box, max_corner> mbr_max(mbr); + + detail::indexed_point_view<box_type const, min_corner> + first_box_min(range::front(range_of_boxes)); + + detail::indexed_point_view<box_type const, max_corner> + first_box_max(range::front(range_of_boxes)); + + detail::conversion::point_to_point + < + detail::indexed_point_view<box_type const, min_corner>, + detail::indexed_point_view<Box, min_corner>, + Dimension, + DimensionCount + >::apply(first_box_min, mbr_min); + + detail::conversion::point_to_point + < + detail::indexed_point_view<box_type const, max_corner>, + detail::indexed_point_view<Box, max_corner>, + Dimension, + DimensionCount + >::apply(first_box_max, mbr_max); + + // now expand using the remaining boxes + iterator_type it = boost::begin(range_of_boxes); + for (++it; it != boost::end(range_of_boxes); ++it) + { + detail::expand::indexed_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + min_corner, + Dimension, + DimensionCount + >::apply(mbr, *it); + + detail::expand::indexed_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + max_corner, + Dimension, + DimensionCount + >::apply(mbr, *it); + } + } + +}; + + +struct envelope_range_of_boxes +{ + template <std::size_t Index> + struct latitude_less + { + template <typename Box> + inline bool operator()(Box const& box1, Box const& box2) const + { + return math::smaller(geometry::get<Index, 1>(box1), + geometry::get<Index, 1>(box2)); + } + }; + + template <typename RangeOfBoxes, typename Box> + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) + { + // boxes in the range are assumed to be normalized already + + typedef typename boost::range_value<RangeOfBoxes>::type box_type; + typedef typename coordinate_type<box_type>::type coordinate_type; + typedef typename coordinate_system<box_type>::type::units units_type; + typedef typename boost::range_iterator + < + RangeOfBoxes const + >::type iterator_type; + + typedef math::detail::constants_on_spheroid + < + coordinate_type, units_type + > constants; + + typedef longitude_interval<coordinate_type> interval_type; + typedef std::vector<interval_type> interval_range_type; + + BOOST_GEOMETRY_ASSERT(! boost::empty(range_of_boxes)); + + iterator_type it_min = std::min_element(boost::begin(range_of_boxes), + boost::end(range_of_boxes), + latitude_less<min_corner>()); + iterator_type it_max = std::max_element(boost::begin(range_of_boxes), + boost::end(range_of_boxes), + latitude_less<max_corner>()); + + coordinate_type const min_longitude = constants::min_longitude(); + coordinate_type const max_longitude = constants::max_longitude(); + coordinate_type const period = constants::period(); + + interval_range_type intervals; + for (iterator_type it = boost::begin(range_of_boxes); + it != boost::end(range_of_boxes); + ++it) + { + coordinate_type lat_min = geometry::get<min_corner, 1>(*it); + coordinate_type lat_max = geometry::get<max_corner, 1>(*it); + if (math::equals(lat_min, constants::max_latitude()) + || math::equals(lat_max, constants::min_latitude())) + { + // if the box degenerates to the south or north pole + // just ignore it + continue; + } + + coordinate_type lon_left = geometry::get<min_corner, 0>(*it); + coordinate_type lon_right = geometry::get<max_corner, 0>(*it); + + if (math::larger(lon_right, max_longitude)) + { + intervals.push_back(interval_type(lon_left, max_longitude)); + intervals.push_back + (interval_type(min_longitude, lon_right - period)); + } + else + { + intervals.push_back(interval_type(lon_left, lon_right)); + } + } + + coordinate_type lon_min = 0; + coordinate_type lon_max = 0; + envelope_range_of_longitudes + < + units_type + >::apply(intervals, lon_min, lon_max); + + // do not convert units; conversion will be performed at a + // higher level + + // assign now the min/max longitude/latitude values + detail::indexed_point_view<Box, min_corner> mbr_min(mbr); + detail::indexed_point_view<Box, max_corner> mbr_max(mbr); + + geometry::set<0>(mbr_min, lon_min); + geometry::set<1>(mbr_min, geometry::get<min_corner, 1>(*it_min)); + geometry::set<0>(mbr_max, lon_max); + geometry::set<1>(mbr_max, geometry::get<max_corner, 1>(*it_max)); + + // what remains to be done is to compute the envelope range + // for the remaining dimensions (if any) + envelope_range_of_boxes_by_expansion + < + 2, dimension<Box>::value + >::apply(range_of_boxes, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp new file mode 100644 index 0000000000..570f0e1a43 --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -0,0 +1,386 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP + +#include <cstddef> +#include <utility> + +#include <boost/numeric/conversion/cast.hpp> + +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/point_type.hpp> +#include <boost/geometry/core/radian_access.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/geometry/geometries/helper_geometry.hpp> + +#include <boost/geometry/strategies/compare.hpp> + +#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp> +#include <boost/geometry/algorithms/detail/normalize.hpp> + +#include <boost/geometry/algorithms/detail/envelope/point.hpp> +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/algorithms/detail/expand/point.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template <std::size_t Dimension, std::size_t DimensionCount> +struct envelope_one_segment +{ + template<typename Point, typename Box> + static inline void apply(Point const& p1, Point const& p2, Box& mbr) + { + envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr); + detail::expand::point_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + Dimension, + DimensionCount + >::apply(mbr, p2); + } +}; + + +// Computes the MBR of a segment given by (lon1, lat1) and (lon2, +// lat2), and with azimuths a1 and a2 at the two endpoints of the +// segment. +// It is assumed that the spherical coordinates of the segment are +// normalized and in radians. +// The longitudes and latitudes of the endpoints are overridden by +// those of the box. +class compute_mbr_of_segment +{ +private: + // computes the azimuths of the segment with endpoints (lon1, lat1) + // and (lon2, lat2) + template <typename CalculationType> + static inline void azimuths(CalculationType const& lon1, + CalculationType const& lat1, + CalculationType const& lon2, + CalculationType const& lat2, + CalculationType& a1, + CalculationType& a2) + { + BOOST_GEOMETRY_ASSERT(math::smaller(lon1, lon2)); + + CalculationType dlon = lon2 - lon1; + CalculationType sin_dlon = sin(dlon); + CalculationType cos_dlon = cos(dlon); + CalculationType cos_lat1 = cos(lat1); + CalculationType cos_lat2 = cos(lat2); + CalculationType sin_lat1 = sin(lat1); + CalculationType sin_lat2 = sin(lat2); + + a1 = atan2(sin_dlon * cos_lat2, + cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon); + + a2 = atan2(-sin_dlon * cos_lat1, + cos_lat2 * sin_lat1 - sin_lat2 * cos_lat1 * cos_dlon); + a2 += math::pi<CalculationType>(); + } + + template <typename CalculationType> + static inline void swap(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + std::swap(lon1, lon2); + std::swap(lat1, lat2); + } + + template <typename CalculationType> + static inline bool contains_pi_half(CalculationType const& a1, + CalculationType const& a2) + { + // azimuths a1 and a2 are assumed to be in radians + BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2)); + + static CalculationType const pi_half = math::half_pi<CalculationType>(); + + return (a1 < a2) + ? (a1 < pi_half && pi_half < a2) + : (a1 > pi_half && pi_half > a2); + } + + template <typename CoordinateType> + static inline bool crosses_antimeridian(CoordinateType const& lon1, + CoordinateType const& lon2) + { + return math::larger(math::abs(lon1 - lon2), math::pi<CoordinateType>()); + } + + template <typename CalculationType> + static inline CalculationType max_latitude(CalculationType const& azimuth, + CalculationType const& latitude) + { + // azimuth and latitude are assumed to be in radians + return acos( math::abs(cos(latitude) * sin(azimuth)) ); + } + + template <typename CalculationType> + static inline void compute_box_corners(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2, + CalculationType const& a1, + CalculationType const& a2) + { + // coordinates are assumed to be in radians + BOOST_GEOMETRY_ASSERT(! math::larger(lon1, lon2)); + + if (math::equals(a1, a2)) + { + // the segment must lie on the equator; nothing to do + BOOST_GEOMETRY_ASSERT(math::equals(lat1, CalculationType(0))); + BOOST_GEOMETRY_ASSERT(math::equals(lat2, CalculationType(0))); + return; + } + + if (math::larger(lat1, lat2)) + { + std::swap(lat1, lat2); + } + + if (contains_pi_half(a1, a2)) + { + CalculationType mid_lat = lat1 + lat2; + if (mid_lat < 0) + { + // update using min latitude + CalculationType lat_min = -max_latitude(a1, lat1); + + if (math::larger(lat1, lat_min)) + { + lat1 = lat_min; + } + } + else if (mid_lat > 0) + { + // update using max latitude + CalculationType lat_max = max_latitude(a1, lat1); + + if (math::smaller(lat2, lat_max)) + { + lat2 = lat_max; + } + } + } + } + + template <typename CalculationType> + static inline void apply(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + CalculationType const half_pi = math::half_pi<CalculationType>(); + + bool is_pole1 = math::equals(math::abs(lat1), half_pi); + bool is_pole2 = math::equals(math::abs(lat2), half_pi); + + if (is_pole1 && is_pole2) + { + // both points are poles; nothing more to do: + // longitudes are already normalized to 0 + BOOST_GEOMETRY_ASSERT(lon1 == CalculationType(0) + && + lon2 == CalculationType(0)); + } + else if (is_pole1 && !is_pole2) + { + // first point is a pole, second point is not: + // make the longitude of the first point the same as that + // of the second point + lon1 = lon2; + } + else if (!is_pole1 && is_pole2) + { + // second point is a pole, first point is not: + // make the longitude of the second point the same as that + // of the first point + lon2 = lon1; + } + + if (math::equals(lon1, lon2)) + { + // segment lies on a meridian + if (math::larger(lat1, lat2)) + { + std::swap(lat1, lat2); + } + return; + } + + BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2); + + if (math::larger(lon1, lon2)) + { + swap(lon1, lat1, lon2, lat2); + } + + if (crosses_antimeridian(lon1, lon2)) + { + lon1 += math::two_pi<CalculationType>(); + swap(lon1, lat1, lon2, lat2); + } + + CalculationType a1 = 0, a2 = 0; + azimuths(lon1, lat1, lon2, lat2, a1, a2); + + compute_box_corners(lon1, lat1, lon2, lat2, a1, a2); + } + +public: + template <typename CalculationType, typename Box> + static inline void apply(CalculationType lon1, + CalculationType lat1, + CalculationType lon2, + CalculationType lat2, + Box& mbr) + { + typedef typename coordinate_type<Box>::type box_coordinate_type; + + typedef typename helper_geometry + < + Box, box_coordinate_type, radian + >::type helper_box_type; + + helper_box_type radian_mbr; + + apply(lon1, lat1, lon2, lat2); + + geometry::set + < + min_corner, 0 + >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1)); + + geometry::set + < + min_corner, 1 + >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1)); + + geometry::set + < + max_corner, 0 + >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2)); + + geometry::set + < + max_corner, 1 + >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2)); + + transform_units(radian_mbr, mbr); + } +}; + + +template <std::size_t DimensionCount> +struct envelope_segment_on_sphere +{ + template <typename Point, typename Box> + static inline void apply(Point const& p1, Point const& p2, Box& mbr) + { + // first compute the envelope range for the first two coordinates + Point p1_normalized = detail::return_normalized<Point>(p1); + Point p2_normalized = detail::return_normalized<Point>(p2); + + compute_mbr_of_segment::apply(geometry::get_as_radian<0>(p1_normalized), + geometry::get_as_radian<1>(p1_normalized), + geometry::get_as_radian<0>(p2_normalized), + geometry::get_as_radian<1>(p2_normalized), + mbr); + + // now compute the envelope range for coordinates of + // dimension 2 and higher + envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr); + } + + template <typename Segment, typename Box> + static inline void apply(Segment const& segment, Box& mbr) + { + typename point_type<Segment>::type p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + apply(p[0], p[1], mbr); + } +}; + + + +template <std::size_t DimensionCount, typename CS_Tag> +struct envelope_segment + : envelope_one_segment<0, DimensionCount> +{}; + + +template <std::size_t DimensionCount> +struct envelope_segment<DimensionCount, spherical_equatorial_tag> + : envelope_segment_on_sphere<DimensionCount> +{}; + + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template <typename Segment, typename CS_Tag> +struct envelope<Segment, segment_tag, CS_Tag> +{ + template <typename Box> + static inline void apply(Segment const& segment, Box& mbr) + { + typename point_type<Segment>::type p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + detail::envelope::envelope_segment + < + dimension<Segment>::value, CS_Tag + >::apply(p[0], p[1], mbr); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP diff --git a/boost/geometry/algorithms/detail/envelope/transform_units.hpp b/boost/geometry/algorithms/detail/envelope/transform_units.hpp new file mode 100644 index 0000000000..0c5382a47b --- /dev/null +++ b/boost/geometry/algorithms/detail/envelope/transform_units.hpp @@ -0,0 +1,103 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP + +#include <cstddef> + +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/strategies/strategy_transform.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> +#include <boost/geometry/views/detail/two_dimensional_view.hpp> + +#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/algorithms/transform.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +< + typename GeometryIn, + typename GeometryOut, + typename TagIn = typename tag<GeometryIn>::type, + typename TagOut = typename tag<GeometryOut>::type +> +struct transform_units_impl + : not_implemented<TagIn, TagOut> +{}; + +template <typename PointIn, typename PointOut> +struct transform_units_impl<PointIn, PointOut, point_tag, point_tag> +{ + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + detail::two_dimensional_view<PointIn const> view_in(point_in); + detail::two_dimensional_view<PointOut> view_out(point_out); + + geometry::transform(view_in, view_out); + } +}; + +template <typename BoxIn, typename BoxOut> +struct transform_units_impl<BoxIn, BoxOut, box_tag, box_tag> +{ + template <std::size_t Index> + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + typedef detail::indexed_point_view<BoxIn const, Index> view_in_type; + typedef detail::indexed_point_view<BoxOut, Index> view_out_type; + + view_in_type view_in(box_in); + view_out_type view_out(box_out); + + transform_units_impl + < + view_in_type, view_out_type + >::apply(view_in, view_out); + } + + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + apply<min_corner>(box_in, box_out); + apply<max_corner>(box_in, box_out); + } +}; + + +// Short utility to transform the units of the first two coordinates of +// geometry_in to the units of geometry_out +template <typename GeometryIn, typename GeometryOut> +inline void transform_units(GeometryIn const& geometry_in, + GeometryOut& geometry_out) +{ + transform_units_impl + < + GeometryIn, GeometryOut + >::apply(geometry_in, geometry_out); +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost:geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP diff --git a/boost/geometry/algorithms/detail/expand/box.hpp b/boost/geometry/algorithms/detail/expand/box.hpp new file mode 100644 index 0000000000..4c89e6f1d4 --- /dev/null +++ b/boost/geometry/algorithms/detail/expand/box.hpp @@ -0,0 +1,126 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP + +#include <cstddef> +#include <algorithm> + +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> + +#include <boost/geometry/algorithms/detail/expand/indexed.hpp> + +#include <boost/geometry/algorithms/dispatch/expand.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +struct box_on_spheroid +{ + template <typename BoxOut, typename BoxIn> + static inline void apply(BoxOut& box_out, BoxIn const& box_in) + { + // normalize both boxes and convert box-in to be of type of box-out + BoxOut mbrs[2]; + detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]); + detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]); + + // compute the envelope of the two boxes + detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Box + box -> new box containing two input boxes +template +< + typename BoxOut, typename BoxIn, + typename StrategyLess, typename StrategyGreater, + typename CSTagOut, typename CSTag +> +struct expand + < + BoxOut, BoxIn, + StrategyLess, StrategyGreater, + box_tag, box_tag, + CSTagOut, CSTag + > : detail::expand::expand_indexed + < + 0, dimension<BoxIn>::value, StrategyLess, StrategyGreater + > +{ + BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types<CSTagOut, CSTag>())); +}; + +template +< + typename BoxOut, typename BoxIn, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, BoxIn, + StrategyLess, StrategyGreater, + box_tag, box_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::expand::box_on_spheroid +{}; + +template +< + typename BoxOut, typename BoxIn, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, BoxIn, + StrategyLess, StrategyGreater, + box_tag, box_tag, + geographic_tag, geographic_tag + > : detail::expand::box_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP diff --git a/boost/geometry/algorithms/detail/expand/implementation.hpp b/boost/geometry/algorithms/detail/expand/implementation.hpp new file mode 100644 index 0000000000..95de1b5049 --- /dev/null +++ b/boost/geometry/algorithms/detail/expand/implementation.hpp @@ -0,0 +1,27 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP + +#include <boost/geometry/algorithms/detail/expand/point.hpp> +#include <boost/geometry/algorithms/detail/expand/segment.hpp> +#include <boost/geometry/algorithms/detail/expand/box.hpp> + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp new file mode 100644 index 0000000000..bdd6eb4506 --- /dev/null +++ b/boost/geometry/algorithms/detail/expand/indexed.hpp @@ -0,0 +1,144 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP + +#include <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/select_coordinate_type.hpp> + +#include <boost/geometry/strategies/compare.hpp> +#include <boost/geometry/policies/compare.hpp> + +#include <boost/geometry/algorithms/dispatch/expand.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t Index, + std::size_t Dimension, std::size_t DimensionCount +> +struct indexed_loop +{ + template <typename Box, typename Geometry> + static inline void apply(Box& box, Geometry const& source) + { + typedef typename strategy::compare::detail::select_strategy + < + StrategyLess, 1, Box, Dimension + >::type less_type; + + typedef typename strategy::compare::detail::select_strategy + < + StrategyGreater, -1, Box, Dimension + >::type greater_type; + + typedef typename select_coordinate_type + < + Box, + Geometry + >::type coordinate_type; + + less_type less; + greater_type greater; + + coordinate_type const coord = get<Index, Dimension>(source); + + if (less(coord, get<min_corner, Dimension>(box))) + { + set<min_corner, Dimension>(box, coord); + } + + if (greater(coord, get<max_corner, Dimension>(box))) + { + set<max_corner, Dimension>(box, coord); + } + + indexed_loop + < + StrategyLess, StrategyGreater, + Index, Dimension + 1, DimensionCount + >::apply(box, source); + } +}; + + +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t Index, std::size_t DimensionCount +> +struct indexed_loop + < + StrategyLess, StrategyGreater, + Index, DimensionCount, DimensionCount + > +{ + template <typename Box, typename Geometry> + static inline void apply(Box&, Geometry const&) {} +}; + + + +// Changes a box such that the other box is also contained by the box +template +< + std::size_t Dimension, std::size_t DimensionCount, + typename StrategyLess, typename StrategyGreater +> +struct expand_indexed +{ + template <typename Box, typename Geometry> + static inline void apply(Box& box, Geometry const& geometry) + { + indexed_loop + < + StrategyLess, StrategyGreater, + 0, Dimension, DimensionCount + >::apply(box, geometry); + + indexed_loop + < + StrategyLess, StrategyGreater, + 1, Dimension, DimensionCount + >::apply(box, geometry); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP diff --git a/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp new file mode 100644 index 0000000000..01936387a7 --- /dev/null +++ b/boost/geometry/algorithms/detail/expand/interface.hpp @@ -0,0 +1,128 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP + +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> + +#include <boost/geometry/geometries/concepts/check.hpp> + +#include <boost/geometry/algorithms/dispatch/expand.hpp> + + +namespace boost { namespace geometry +{ + + +namespace resolve_variant +{ + +template <typename Geometry> +struct expand +{ + template <typename Box> + static inline void apply(Box& box, Geometry const& geometry) + { + concept::check<Box>(); + concept::check<Geometry const>(); + concept::check_concepts_and_equal_dimensions<Box, Geometry const>(); + + dispatch::expand<Box, Geometry>::apply(box, geometry); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Box> + struct visitor: boost::static_visitor<void> + { + Box& m_box; + + visitor(Box& box) : m_box(box) {} + + template <typename Geometry> + void operator()(Geometry const& geometry) const + { + return expand<Geometry>::apply(m_box, geometry); + } + }; + + template <class Box> + static inline void + apply(Box& box, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry) + { + return boost::apply_visitor(visitor<Box>(box), geometry); + } +}; + +} // namespace resolve_variant + + +/*** +*! +\brief Expands a box using the extend (envelope) of another geometry (box, point) +\ingroup expand +\tparam Box type of the box +\tparam Geometry of second geometry, to be expanded with the box +\param box box to expand another geometry with, might be changed +\param geometry other geometry +\param strategy_less +\param strategy_greater +\note Strategy is currently ignored + * +template +< + typename Box, typename Geometry, + typename StrategyLess, typename StrategyGreater +> +inline void expand(Box& box, Geometry const& geometry, + StrategyLess const& strategy_less, + StrategyGreater const& strategy_greater) +{ + concept::check_concepts_and_equal_dimensions<Box, Geometry const>(); + + dispatch::expand<Box, Geometry>::apply(box, geometry); +} +***/ + + +/*! +\brief Expands a box using the bounding box (envelope) of another geometry (box, point) +\ingroup expand +\tparam Box type of the box +\tparam Geometry \tparam_geometry +\param box box to be expanded using another geometry, mutable +\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box + +\qbk{[include reference/algorithms/expand.qbk]} + */ +template <typename Box, typename Geometry> +inline void expand(Box& box, Geometry const& geometry) +{ + resolve_variant::expand<Geometry>::apply(box, geometry); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP diff --git a/boost/geometry/algorithms/detail/expand/point.hpp b/boost/geometry/algorithms/detail/expand/point.hpp new file mode 100644 index 0000000000..56b7f1c738 --- /dev/null +++ b/boost/geometry/algorithms/detail/expand/point.hpp @@ -0,0 +1,303 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP + +#include <cstddef> +#include <algorithm> + +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/select_coordinate_type.hpp> + +#include <boost/geometry/strategies/compare.hpp> +#include <boost/geometry/policies/compare.hpp> + +#include <boost/geometry/algorithms/detail/normalize.hpp> +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/algorithms/dispatch/expand.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_loop +{ + template <typename Box, typename Point> + static inline void apply(Box& box, Point const& source) + { + typedef typename strategy::compare::detail::select_strategy + < + StrategyLess, 1, Point, Dimension + >::type less_type; + + typedef typename strategy::compare::detail::select_strategy + < + StrategyGreater, -1, Point, Dimension + >::type greater_type; + + typedef typename select_coordinate_type + < + Point, Box + >::type coordinate_type; + + less_type less; + greater_type greater; + + coordinate_type const coord = get<Dimension>(source); + + if (less(coord, get<min_corner, Dimension>(box))) + { + set<min_corner, Dimension>(box, coord); + } + + if (greater(coord, get<max_corner, Dimension>(box))) + { + set<max_corner, Dimension>(box, coord); + } + + point_loop + < + StrategyLess, StrategyGreater, Dimension + 1, DimensionCount + >::apply(box, source); + } +}; + + +template +< + typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount +> +struct point_loop + < + StrategyLess, StrategyGreater, DimensionCount, DimensionCount + > +{ + template <typename Box, typename Point> + static inline void apply(Box&, Point const&) {} +}; + + +// implementation for the spherical equatorial and geographic coordinate systems +template +< + typename StrategyLess, + typename StrategyGreater, + std::size_t DimensionCount +> +struct point_loop_on_spheroid +{ + template <typename Box, typename Point> + static inline void apply(Box& box, Point const& point) + { + typedef typename point_type<Box>::type box_point_type; + typedef typename coordinate_type<Box>::type box_coordinate_type; + + typedef math::detail::constants_on_spheroid + < + box_coordinate_type, + typename coordinate_system<Box>::type::units + > constants; + + // normalize input point and input box + Point p_normalized = detail::return_normalized<Point>(point); + detail::normalize(box, box); + + // transform input point to be of the same type as the box point + box_point_type box_point; + detail::envelope::transform_units(p_normalized, box_point); + + box_coordinate_type p_lon = geometry::get<0>(box_point); + box_coordinate_type p_lat = geometry::get<1>(box_point); + + typename coordinate_type<Box>::type + b_lon_min = geometry::get<min_corner, 0>(box), + b_lat_min = geometry::get<min_corner, 1>(box), + b_lon_max = geometry::get<max_corner, 0>(box), + b_lat_max = geometry::get<max_corner, 1>(box); + + if (math::equals(math::abs(p_lat), constants::max_latitude())) + { + // the point of expansion is the either the north or the + // south pole; the only important coordinate here is the + // pole's latitude, as the longitude can be anything; + // we, thus, take into account the point's latitude only and return + geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min)); + geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max)); + return; + } + + if (math::equals(b_lat_min, b_lat_max) + && math::equals(math::abs(b_lat_min), constants::max_latitude())) + { + // the box degenerates to either the north or the south pole; + // the only important coordinate here is the pole's latitude, + // as the longitude can be anything; + // we thus take into account the box's latitude only and return + geometry::set<min_corner, 0>(box, p_lon); + geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min)); + geometry::set<max_corner, 0>(box, p_lon); + geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max)); + return; + } + + // update latitudes + b_lat_min = (std::min)(b_lat_min, p_lat); + b_lat_max = (std::max)(b_lat_max, p_lat); + + // update longitudes + if (math::smaller(p_lon, b_lon_min)) + { + box_coordinate_type p_lon_shifted = p_lon + constants::period(); + + if (math::larger(p_lon_shifted, b_lon_max)) + { + // here we could check using: ! math::larger(.., ..) + if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max)) + { + b_lon_min = p_lon; + } + else + { + b_lon_max = p_lon_shifted; + } + } + } + else if (math::larger(p_lon, b_lon_max)) + { + // in this case, and since p_lon is normalized in the range + // (-180, 180], we must have that b_lon_max <= 180 + if (b_lon_min < 0 + && math::larger(p_lon - b_lon_max, + constants::period() - p_lon + b_lon_min)) + { + b_lon_min = p_lon; + b_lon_max += constants::period(); + } + else + { + b_lon_max = p_lon; + } + } + + geometry::set<min_corner, 0>(box, b_lon_min); + geometry::set<min_corner, 1>(box, b_lat_min); + geometry::set<max_corner, 0>(box, b_lon_max); + geometry::set<max_corner, 1>(box, b_lat_max); + + point_loop + < + StrategyLess, StrategyGreater, 2, DimensionCount + >::apply(box, point); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Box + point -> new box containing also point +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater, + typename CSTagOut, typename CSTag +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + CSTagOut, CSTag + > : detail::expand::point_loop + < + StrategyLess, StrategyGreater, 0, dimension<Point>::value + > +{ + BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types<CSTagOut, CSTag>())); +}; + +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::expand::point_loop_on_spheroid + < + StrategyLess, StrategyGreater, dimension<Point>::value + > +{}; + +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + geographic_tag, geographic_tag + > : detail::expand::point_loop_on_spheroid + < + StrategyLess, StrategyGreater, dimension<Point>::value + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP diff --git a/boost/geometry/algorithms/detail/expand/segment.hpp b/boost/geometry/algorithms/detail/expand/segment.hpp new file mode 100644 index 0000000000..041c1e175f --- /dev/null +++ b/boost/geometry/algorithms/detail/expand/segment.hpp @@ -0,0 +1,115 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP + +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> +#include <boost/geometry/algorithms/detail/envelope/segment.hpp> + +#include <boost/geometry/algorithms/detail/expand/indexed.hpp> + +#include <boost/geometry/algorithms/dispatch/expand.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +struct segment_on_sphere +{ + template <typename Box, typename Segment> + static inline void apply(Box& box, Segment const& segment) + { + Box mbrs[2]; + + // compute the envelope of the segment + detail::envelope::envelope_segment_on_sphere + < + dimension<Segment>::value + >::apply(segment, mbrs[0]); + + // normalize the box + detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]); + + // compute the envelope of the two boxes + detail::envelope::envelope_range_of_boxes::apply(mbrs, box); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Box, typename Segment, + typename StrategyLess, typename StrategyGreater, + typename CSTagOut, typename CSTag +> +struct expand + < + Box, Segment, + StrategyLess, StrategyGreater, + box_tag, segment_tag, + CSTagOut, CSTag + > : detail::expand::expand_indexed + < + 0, dimension<Segment>::value, StrategyLess, StrategyGreater + > +{ + BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types<CSTagOut, CSTag>())); +}; + +template +< + typename Box, typename Segment, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + Box, Segment, + StrategyLess, StrategyGreater, + box_tag, segment_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::expand::segment_on_sphere +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP diff --git a/boost/geometry/algorithms/detail/get_left_turns.hpp b/boost/geometry/algorithms/detail/get_left_turns.hpp index 0fd243d8e3..95ab98c236 100644 --- a/boost/geometry/algorithms/detail/get_left_turns.hpp +++ b/boost/geometry/algorithms/detail/get_left_turns.hpp @@ -9,6 +9,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP +#include <boost/geometry/core/assert.hpp> + #include <boost/geometry/arithmetic/arithmetic.hpp> #include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> @@ -154,8 +156,8 @@ template <typename AngleCollection, typename Turns> inline void get_left_turns(AngleCollection const& sorted_angles, Turns& turns) { - std::set<int> good_incoming; - std::set<int> good_outgoing; + std::set<std::size_t> good_incoming; + std::set<std::size_t> good_outgoing; for (typename boost::range_iterator<AngleCollection const>::type it = sorted_angles.begin(); it != sorted_angles.end(); ++it) @@ -195,7 +197,7 @@ template <typename Point, typename AngleCollection> inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin) { // Assign same cluster_index for all turns in same direction - BOOST_ASSERT(boost::size(sorted) >= 4u); + BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u); angle_equal_to<Point> comparator(origin); typename boost::range_iterator<AngleCollection>::type it = sorted.begin(); @@ -218,7 +220,7 @@ inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& template <typename AngleCollection> inline void block_turns(AngleCollection& sorted, std::size_t cluster_size) { - BOOST_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0); + BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0); std::vector<std::pair<bool, bool> > directions; for (std::size_t i = 0; i < cluster_size; i++) @@ -242,14 +244,14 @@ inline void block_turns(AngleCollection& sorted, std::size_t cluster_size) for (typename boost::range_iterator<AngleCollection>::type it = sorted.begin(); it != sorted.end(); ++it) { - int cluster_index = it->cluster_index; - int previous_index = cluster_index - 1; + signed_size_type cluster_index = static_cast<signed_size_type>(it->cluster_index); + signed_size_type previous_index = cluster_index - 1; if (previous_index < 0) { previous_index = cluster_size - 1; } - int next_index = cluster_index + 1; - if (next_index >= static_cast<int>(cluster_size)) + signed_size_type next_index = cluster_index + 1; + if (next_index >= static_cast<signed_size_type>(cluster_size)) { next_index = 0; } diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp index d57535e61f..2af618d974 100644 --- a/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -120,7 +120,8 @@ struct intersection >::type rescale_policy_type; rescale_policy_type robust_policy - = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); + = geometry::get_rescale_policy<rescale_policy_type>(geometry1, + geometry2); typedef strategy_intersection < @@ -151,8 +152,8 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> visitor(Geometry2 const& geometry2, GeometryOut& geometry_out) - : m_geometry2(geometry2), - m_geometry_out(geometry_out) + : m_geometry2(geometry2) + , m_geometry_out(geometry_out) {} template <typename Geometry1> @@ -176,7 +177,7 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> Geometry2 const& geometry2, GeometryOut& geometry_out) { - return apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1); + return boost::apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1); } }; @@ -192,8 +193,8 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > visitor(Geometry1 const& geometry1, GeometryOut& geometry_out) - : m_geometry1(geometry1), - m_geometry_out(geometry_out) + : m_geometry1(geometry1) + , m_geometry_out(geometry_out) {} template <typename Geometry2> @@ -213,12 +214,11 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> > template <typename GeometryOut> static inline bool - apply( - Geometry1 const& geometry1, + apply(Geometry1 const& geometry1, const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2, GeometryOut& geometry_out) { - return apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2); + return boost::apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2); } }; @@ -232,12 +232,11 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIAN GeometryOut& m_geometry_out; visitor(GeometryOut& geometry_out) - : m_geometry_out(geometry_out) + : m_geometry_out(geometry_out) {} template <typename Geometry1, typename Geometry2> - result_type operator()( - Geometry1 const& geometry1, + result_type operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { return intersection @@ -254,12 +253,11 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIAN template <typename GeometryOut> static inline bool - apply( - const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1, + apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1, const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2, GeometryOut& geometry_out) { - return apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2); + return boost::apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2); } }; diff --git a/boost/geometry/algorithms/detail/intersection/multi.hpp b/boost/geometry/algorithms/detail/intersection/multi.hpp index b1f13862fc..88b49b0167 100644 --- a/boost/geometry/algorithms/detail/intersection/multi.hpp +++ b/boost/geometry/algorithms/detail/intersection/multi.hpp @@ -1,9 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014, Oracle and/or its affiliates. +// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -36,8 +36,6 @@ #include <boost/geometry/algorithms/envelope.hpp> #include <boost/geometry/algorithms/num_points.hpp> -// TODO: remove this after moving num_point from multi directory -#include <boost/geometry/multi/algorithms/num_points.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp index 4f3e875eef..0f77a49498 100644 --- a/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -13,9 +13,9 @@ #include <algorithm> #include <deque> -#include <boost/assert.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/point_type.hpp> @@ -33,7 +33,7 @@ #include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/algorithms/detail/check_iterator_range.hpp> -#include <boost/geometry/algorithms/detail/signed_index_type.hpp> +#include <boost/geometry/algorithms/detail/signed_size_type.hpp> #include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> @@ -60,7 +60,7 @@ namespace detail { namespace is_simple template <typename Turn> inline bool check_segment_indices(Turn const& turn, - signed_index_type last_index) + signed_size_type last_index) { return (turn.operations[0].seg_id.segment_index == 0 @@ -89,7 +89,7 @@ public: template <typename Turn> inline bool apply(Turn const& turn) const { - BOOST_ASSERT(boost::size(m_linestring) > 1); + BOOST_GEOMETRY_ASSERT(boost::size(m_linestring) > 1); return m_is_closed && turn.method == overlay::method_none && check_segment_indices(turn, boost::size(m_linestring) - 2) @@ -112,7 +112,7 @@ private: static inline bool is_boundary_point_of(Point const& point, Linestring const& linestring) { - BOOST_ASSERT(boost::size(linestring) > 1); + BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1); return ! geometry::equals(range::front(linestring), range::back(linestring)) @@ -125,7 +125,7 @@ private: static inline bool is_closing_point_of(Turn const& turn, Linestring const& linestring) { - BOOST_ASSERT(boost::size(linestring) > 1); + BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1); return turn.method == overlay::method_none && diff --git a/boost/geometry/algorithms/detail/is_valid/box.hpp b/boost/geometry/algorithms/detail/is_valid/box.hpp index 139502af78..e7a67252ba 100644 --- a/boost/geometry/algorithms/detail/is_valid/box.hpp +++ b/boost/geometry/algorithms/detail/is_valid/box.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -12,6 +13,8 @@ #include <cstddef> +#include <boost/core/ignore_unused.hpp> + #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> @@ -57,6 +60,8 @@ struct has_valid_corners<Box, 0> template <typename VisitPolicy> static inline bool apply(Box const&, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + return visitor.template apply<no_failure>(); } }; diff --git a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp index c59139a92e..f08e70242c 100644 --- a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp +++ b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp @@ -17,9 +17,9 @@ #include <utility> #include <vector> -#include <boost/assert.hpp> #include <boost/core/addressof.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/policies/compare.hpp> @@ -104,12 +104,12 @@ private: , m_parent_id(num_nodes, -1) {} - inline signed_index_type parent_id(vertex_handle v) const + inline signed_size_type parent_id(vertex_handle v) const { return m_parent_id[v->id()]; } - inline void set_parent_id(vertex_handle v, signed_index_type id) + inline void set_parent_id(vertex_handle v, signed_size_type id) { m_parent_id[v->id()] = id; } @@ -125,7 +125,7 @@ private: } private: std::vector<bool> m_visited; - std::vector<signed_index_type> m_parent_id; + std::vector<signed_size_type> m_parent_id; }; @@ -145,7 +145,7 @@ private: = m_neighbors[v->id()].begin(); nit != m_neighbors[v->id()].end(); ++nit) { - if ( static_cast<signed_index_type>((*nit)->id()) != data.parent_id(v) ) + if ( static_cast<signed_size_type>((*nit)->id()) != data.parent_id(v) ) { if ( data.visited(*nit) ) { @@ -153,7 +153,7 @@ private: } else { - data.set_parent_id(*nit, static_cast<signed_index_type>(v->id())); + data.set_parent_id(*nit, static_cast<signed_size_type>(v->id())); stack.push(*nit); } } @@ -173,7 +173,7 @@ public: // inserts a ring vertex in the graph and returns its handle // ring id's are zero-based (so the first interior ring has id 1) - inline vertex_handle add_vertex(signed_index_type id) + inline vertex_handle add_vertex(signed_size_type id) { return m_vertices.insert(vertex(static_cast<std::size_t>(id))).first; } @@ -197,8 +197,8 @@ public: inline void add_edge(vertex_handle v1, vertex_handle v2) { - BOOST_ASSERT( v1 != m_vertices.end() ); - BOOST_ASSERT( v2 != m_vertices.end() ); + BOOST_GEOMETRY_ASSERT( v1 != m_vertices.end() ); + BOOST_GEOMETRY_ASSERT( v2 != m_vertices.end() ); m_neighbors[v1->id()].insert(v2); m_neighbors[v2->id()].insert(v1); } diff --git a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp b/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp index 5878841e70..685a4aac35 100644 --- a/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp +++ b/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp @@ -10,6 +10,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP +#include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> #include <boost/geometry/core/closure.hpp> @@ -35,8 +36,13 @@ struct has_duplicates template <typename VisitPolicy> static inline bool apply(Range const& range, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + typedef typename closeable_view<Range const, Closure>::type view_type; - typedef typename boost::range_iterator<view_type const>::type iterator; + typedef typename boost::range_const_iterator + < + view_type const + >::type const_iterator; view_type view(range); @@ -47,9 +53,10 @@ struct has_duplicates geometry::equal_to<typename boost::range_value<Range>::type> equal; - iterator it = boost::begin(view); - iterator next = ++boost::begin(view); - for (; next != boost::end(view); ++it, ++next) + const_iterator it = boost::const_begin(view); + const_iterator next = it; + ++next; + for (; next != boost::const_end(view); ++it, ++next) { if ( equal(*it, *next) ) { diff --git a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index 090c026e8b..aa90e52db6 100644 --- a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -12,9 +12,11 @@ #include <algorithm> +#include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> #include <boost/type_traits/is_same.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> @@ -76,10 +78,23 @@ struct not_equal_to template <typename Range, closure_selector Closure> struct has_spikes { + template <typename Iterator> + static inline Iterator find_different_from_first(Iterator first, + Iterator last) + { + typedef not_equal_to<typename point_type<Range>::type> not_equal; + + BOOST_GEOMETRY_ASSERT(first != last); + + Iterator second = first; + ++second; + return std::find_if(second, last, not_equal(*first)); + } + template <typename VisitPolicy> static inline bool apply(Range const& range, VisitPolicy& visitor) { - typedef not_equal_to<typename point_type<Range>::type> not_equal; + boost::ignore_unused(visitor); typedef typename closeable_view<Range const, Closure>::type view_type; typedef typename boost::range_iterator<view_type const>::type iterator; @@ -91,23 +106,23 @@ struct has_spikes iterator prev = boost::begin(view); - iterator cur = std::find_if(prev, boost::end(view), not_equal(*prev)); - if ( cur == boost::end(view) ) + iterator cur = find_different_from_first(prev, boost::end(view)); + if (cur == boost::end(view)) { // the range has only one distinct point, so it // cannot have a spike return ! visitor.template apply<no_failure>(); } - iterator next = std::find_if(cur, boost::end(view), not_equal(*cur)); - if ( next == boost::end(view) ) + iterator next = find_different_from_first(cur, boost::end(view)); + if (next == boost::end(view)) { // the range has only two distinct points, so it // cannot have a spike return ! visitor.template apply<no_failure>(); } - while ( next != boost::end(view) ) + while (next != boost::end(view)) { if ( geometry::detail::point_is_spike_or_equal(*prev, *next, @@ -118,20 +133,19 @@ struct has_spikes } prev = cur; cur = next; - next = std::find_if(cur, boost::end(view), not_equal(*cur)); + next = find_different_from_first(cur, boost::end(view)); } - if ( geometry::equals(range::front(view), range::back(view)) ) + if (geometry::equals(range::front(view), range::back(view))) { iterator cur = boost::begin(view); typename boost::range_reverse_iterator < view_type const - >::type prev = std::find_if(boost::rbegin(view), - boost::rend(view), - not_equal(range::back(view))); - iterator next = - std::find_if(cur, boost::end(view), not_equal(*cur)); + >::type prev = find_different_from_first(boost::rbegin(view), + boost::rend(view)); + + iterator next = find_different_from_first(cur, boost::end(view)); if (detail::point_is_spike_or_equal(*prev, *next, *cur)) { return diff --git a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp index ecbc4782b2..0a81213743 100644 --- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp +++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp @@ -12,9 +12,10 @@ #include <vector> -#include <boost/assert.hpp> +#include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/policies/predicate_based_interrupt_policy.hpp> @@ -73,6 +74,8 @@ public: Turns& turns, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + rescale_policy_type robust_policy = geometry::get_rescale_policy<rescale_policy_type>(geometry); @@ -88,7 +91,7 @@ public: if (interrupt_policy.has_intersections) { - BOOST_ASSERT(! boost::empty(turns)); + BOOST_GEOMETRY_ASSERT(! boost::empty(turns)); return visitor.template apply<failure_self_intersections>(turns); } else diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp index f83b09c437..0ec13b1b38 100644 --- a/boost/geometry/algorithms/detail/is_valid/interface.hpp +++ b/boost/geometry/algorithms/detail/is_valid/interface.hpp @@ -97,7 +97,7 @@ template <typename Geometry> inline bool is_valid(Geometry const& geometry) { is_valid_default_policy<> policy_visitor; - return is_valid(geometry, policy_visitor); + return geometry::is_valid(geometry, policy_visitor); } @@ -121,7 +121,7 @@ template <typename Geometry> inline bool is_valid(Geometry const& geometry, validity_failure_type& failure) { failure_type_policy<> policy_visitor; - bool result = is_valid(geometry, policy_visitor); + bool result = geometry::is_valid(geometry, policy_visitor); failure = policy_visitor.failure(); return result; } @@ -148,7 +148,7 @@ inline bool is_valid(Geometry const& geometry, std::string& message) { std::ostringstream stream; failing_reason_policy<> policy_visitor(stream); - bool result = is_valid(geometry, policy_visitor); + bool result = geometry::is_valid(geometry, policy_visitor); message = stream.str(); return result; } diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp index 69243563ec..e30064faf0 100644 --- a/boost/geometry/algorithms/detail/is_valid/linear.hpp +++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -18,6 +19,7 @@ #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/tags.hpp> +#include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/range.hpp> #include <boost/geometry/algorithms/equals.hpp> @@ -138,7 +140,8 @@ public: static inline bool apply(MultiLinestring const& multilinestring, VisitPolicy& visitor) { - if (AllowEmptyMultiGeometries && boost::empty(multilinestring)) + if (BOOST_GEOMETRY_CONDITION( + AllowEmptyMultiGeometries && boost::empty(multilinestring))) { return visitor.template apply<no_failure>(); } diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index 9362bfca0e..0025445c2c 100644 --- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -13,6 +14,7 @@ #include <deque> #include <vector> +#include <boost/core/ignore_unused.hpp> #include <boost/iterator/filter_iterator.hpp> #include <boost/range.hpp> @@ -21,6 +23,7 @@ #include <boost/geometry/core/ring_type.hpp> #include <boost/geometry/core/tags.hpp> +#include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/range.hpp> #include <boost/geometry/geometries/box.hpp> @@ -80,8 +83,10 @@ private: TurnIterator turns_beyond, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + // collect all polygons that have turns - std::set<signed_index_type> multi_indices; + std::set<signed_size_type> multi_indices; for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit) { multi_indices.insert(tit->operations[0].seg_id.multi_index); @@ -90,7 +95,7 @@ private: // put polygon iterators without turns in a vector std::vector<PolygonIterator> polygon_iterators; - signed_index_type multi_index = 0; + signed_size_type multi_index = 0; for (PolygonIterator it = polygons_first; it != polygons_beyond; ++it, ++multi_index) { @@ -124,7 +129,7 @@ private: class has_multi_index { public: - has_multi_index(signed_index_type multi_index) + has_multi_index(signed_size_type multi_index) : m_multi_index(multi_index) {} @@ -136,7 +141,7 @@ private: } private: - signed_index_type const m_multi_index; + signed_size_type const m_multi_index; }; @@ -156,7 +161,7 @@ private: TurnIterator turns_beyond, VisitPolicy& visitor) { - signed_index_type multi_index = 0; + signed_size_type multi_index = 0; for (PolygonIterator it = polygons_first; it != polygons_beyond; ++it, ++multi_index) { @@ -250,7 +255,8 @@ public: { typedef debug_validity_phase<MultiPolygon> debug_phase; - if (AllowEmptyMultiGeometries && boost::empty(multipolygon)) + if (BOOST_GEOMETRY_CONDITION( + AllowEmptyMultiGeometries && boost::empty(multipolygon))) { return visitor.template apply<no_failure>(); } diff --git a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp index 8e5ebaadcc..e51ab74643 100644 --- a/boost/geometry/algorithms/detail/is_valid/pointlike.hpp +++ b/boost/geometry/algorithms/detail/is_valid/pointlike.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -10,6 +11,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP +#include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> #include <boost/geometry/core/tags.hpp> @@ -17,6 +19,8 @@ #include <boost/geometry/algorithms/validity_failure_type.hpp> #include <boost/geometry/algorithms/dispatch/is_valid.hpp> +#include <boost/geometry/util/condition.hpp> + namespace boost { namespace geometry { @@ -34,6 +38,7 @@ struct is_valid<Point, point_tag> template <typename VisitPolicy> static inline bool apply(Point const&, VisitPolicy& visitor) { + boost::ignore_unused(visitor); return visitor.template apply<no_failure>(); } }; @@ -51,7 +56,10 @@ struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries> static inline bool apply(MultiPoint const& multipoint, VisitPolicy& visitor) { - if (AllowEmptyMultiGeometries || boost::size(multipoint) > 0) + boost::ignore_unused(multipoint, visitor); + + if (BOOST_GEOMETRY_CONDITION( + AllowEmptyMultiGeometries || !boost::empty(multipoint))) { // we allow empty multi-geometries, so an empty multipoint // is considered valid diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp index 17eefd226f..6e87273aa1 100644 --- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -18,9 +18,10 @@ #include <set> #include <vector> -#include <boost/assert.hpp> +#include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/ring_type.hpp> @@ -185,24 +186,26 @@ protected: TurnIterator turns_beyond, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + // collect the interior ring indices that have turns with the // exterior ring - std::set<signed_index_type> ring_indices; + std::set<signed_size_type> ring_indices; for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit) { if (tit->operations[0].seg_id.ring_index == -1) { - BOOST_ASSERT(tit->operations[1].seg_id.ring_index != -1); + BOOST_GEOMETRY_ASSERT(tit->operations[1].seg_id.ring_index != -1); ring_indices.insert(tit->operations[1].seg_id.ring_index); } else if (tit->operations[1].seg_id.ring_index == -1) { - BOOST_ASSERT(tit->operations[0].seg_id.ring_index != -1); + BOOST_GEOMETRY_ASSERT(tit->operations[0].seg_id.ring_index != -1); ring_indices.insert(tit->operations[0].seg_id.ring_index); } } - signed_index_type ring_index = 0; + signed_size_type ring_index = 0; for (RingIterator it = rings_first; it != rings_beyond; ++it, ++ring_index) { @@ -303,6 +306,8 @@ protected: TurnIterator beyond, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + typedef typename std::iterator_traits < TurnIterator diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp index c663a96d28..c35e843418 100644 --- a/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -12,6 +13,8 @@ #include <deque> +#include <boost/core/ignore_unused.hpp> + #include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/point_order.hpp> @@ -53,6 +56,8 @@ struct is_topologically_closed template <typename VisitPolicy> static inline bool apply(Ring const&, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + return visitor.template apply<no_failure>(); } }; @@ -63,6 +68,8 @@ struct is_topologically_closed<Ring, closed> template <typename VisitPolicy> static inline bool apply(Ring const& ring, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + if (geometry::equals(range::front(ring), range::back(ring))) { return visitor.template apply<no_failure>(); @@ -112,6 +119,8 @@ struct is_properly_oriented template <typename VisitPolicy> static inline bool apply(Ring const& ring, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + typename ring_area_predicate < area_result_type, IsInteriorRing diff --git a/boost/geometry/algorithms/detail/is_valid/segment.hpp b/boost/geometry/algorithms/detail/is_valid/segment.hpp index 0b60890dc0..a93d2bfe9e 100644 --- a/boost/geometry/algorithms/detail/is_valid/segment.hpp +++ b/boost/geometry/algorithms/detail/is_valid/segment.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -10,6 +11,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP +#include <boost/core/ignore_unused.hpp> + #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/tags.hpp> @@ -44,6 +47,8 @@ struct is_valid<Segment, segment_tag> template <typename VisitPolicy> static inline bool apply(Segment const& segment, VisitPolicy& visitor) { + boost::ignore_unused(visitor); + typename point_type<Segment>::type p[2]; detail::assign_point_from_index<0>(segment, p[0]); detail::assign_point_from_index<1>(segment, p[1]); diff --git a/boost/geometry/algorithms/detail/max_interval_gap.hpp b/boost/geometry/algorithms/detail/max_interval_gap.hpp new file mode 100644 index 0000000000..e8a70a6b5f --- /dev/null +++ b/boost/geometry/algorithms/detail/max_interval_gap.hpp @@ -0,0 +1,278 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP + +#include <cstddef> +#include <queue> +#include <utility> +#include <vector> + +#include <boost/core/ref.hpp> +#include <boost/range.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/type_traits/remove_reference.hpp> + +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/algorithms/detail/sweep.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace max_interval_gap +{ + +// the class Interval must provide the following: +// * must define the type value_type +// * must define the type difference_type +// * must have the methods: +// value_type get<Index>() const +// difference_type length() const +// where an Index value of 0 (resp., 1) refers to the left (resp., +// right) endpoint of the interval + +template <typename Interval> +class sweep_event +{ +public: + typedef Interval interval_type; + typedef typename Interval::value_type time_type; + + sweep_event(Interval const& interval, bool start_event = true) + : m_interval(boost::cref(interval)) + , m_start_event(start_event) + {} + + inline bool is_start_event() const + { + return m_start_event; + } + + inline interval_type const& interval() const + { + return m_interval; + } + + inline time_type time() const + { + return (m_start_event) + ? interval().template get<0>() + : interval().template get<1>(); + } + + inline bool operator<(sweep_event const& other) const + { + if (! math::equals(time(), other.time())) + { + return time() < other.time(); + } + // a start-event is before an end-event with the same event time + return is_start_event() && ! other.is_start_event(); + } + +private: + boost::reference_wrapper<Interval const> m_interval; + bool m_start_event; +}; + +template <typename Event> +struct event_greater +{ + inline bool operator()(Event const& event1, Event const& event2) const + { + return event2 < event1; + } +}; + + +struct initialization_visitor +{ + template <typename Range, typename PriorityQueue, typename EventVisitor> + static inline void apply(Range const& range, + PriorityQueue& queue, + EventVisitor&) + { + BOOST_GEOMETRY_ASSERT(queue.empty()); + + // it is faster to build the queue directly from the entire + // range, rather than insert elements one after the other + PriorityQueue pq(boost::begin(range), boost::end(range)); + std::swap(pq, queue); + } +}; + + +template <typename Event> +class event_visitor +{ + typedef typename Event::time_type event_time_type; + typedef typename Event::interval_type::difference_type difference_type; + + typedef typename boost::remove_const + < + typename boost::remove_reference + < + event_time_type + >::type + >::type bare_time_type; + + +public: + event_visitor() + : m_overlap_count(0) + , m_max_gap_left(0) + , m_max_gap_right(0) + {} + + template <typename PriorityQueue> + inline void apply(Event const& event, PriorityQueue& queue) + { + if (event.is_start_event()) + { + ++m_overlap_count; + queue.push(Event(event.interval(), false)); + } + else + { + --m_overlap_count; + if (m_overlap_count == 0 && ! queue.empty()) + { + // we may have a gap + BOOST_GEOMETRY_ASSERT(queue.top().is_start_event()); + + event_time_type next_event_time + = queue.top().interval().template get<0>(); + difference_type gap = next_event_time - event.time(); + if (gap > max_gap()) + { + m_max_gap_left = event.time(); + m_max_gap_right = next_event_time; + } + } + } + } + + bare_time_type const& max_gap_left() const + { + return m_max_gap_left; + } + + bare_time_type const& max_gap_right() const + { + return m_max_gap_right; + } + + difference_type max_gap() const + { + return m_max_gap_right - m_max_gap_left; + } + +private: + std::size_t m_overlap_count; + bare_time_type m_max_gap_left, m_max_gap_right; +}; + +}} // namespace detail::max_interval_gap +#endif // DOXYGEN_NO_DETAIL + + +// Given a range of intervals I1, I2, ..., In, maximum_gap() returns +// the maximum length of an interval M that satisfies the following +// properties: +// +// 1. M.left >= min(I1, I2, ..., In) +// 2. M.right <= max(I1, I2, ..., In) +// 3. intersection(interior(M), Ik) is the empty set for all k=1, ..., n +// 4. length(M) is maximal +// +// where M.left and M.right denote the left and right extreme values +// for the interval M, and length(M) is equal to M.right - M.left. +// +// If M does not exist (or, alternatively, M is identified as the +// empty set), 0 is returned. +// +// The algorithm proceeds for performing a sweep: the left endpoints +// are inserted into a min-priority queue with the priority being the +// value of the endpoint. The sweep algorithm maintains an "overlap +// counter" that counts the number of overlaping intervals at any +// specific sweep-time value. +// There are two types of events encountered during the sweep: +// (a) a start event: the left endpoint of an interval is found. +// In this case the overlap count is increased by one and the +// right endpoint of the interval in inserted into the event queue +// (b) an end event: the right endpoint of an interval is found. +// In this case the overlap count is decreased by one. If the +// updated overlap count is 0, then we could expect to have a gap +// in-between intervals. This gap is measured as the (absolute) +// distance of the current interval right endpoint (being +// processed) to the upcoming left endpoint of the next interval +// to be processed (if such an interval exists). If the measured +// gap is greater than the current maximum gap, it is recorded. +// The initial maximum gap is initialized to 0. This value is returned +// if no gap is found during the sweeping procedure. + +template <typename RangeOfIntervals, typename T> +inline typename boost::range_value<RangeOfIntervals>::type::difference_type +maximum_gap(RangeOfIntervals const& range_of_intervals, + T& max_gap_left, T& max_gap_right) +{ + typedef typename boost::range_value<RangeOfIntervals>::type interval_type; + typedef detail::max_interval_gap::sweep_event<interval_type> event_type; + + // create a min-priority queue for the events + std::priority_queue + < + event_type, + std::vector<event_type>, + detail::max_interval_gap::event_greater<event_type> + > queue; + + // define initialization and event-process visitors + detail::max_interval_gap::initialization_visitor init_visitor; + detail::max_interval_gap::event_visitor<event_type> sweep_visitor; + + // perform the sweep + geometry::sweep(range_of_intervals, + queue, + init_visitor, + sweep_visitor); + + max_gap_left = sweep_visitor.max_gap_left(); + max_gap_right = sweep_visitor.max_gap_right(); + return sweep_visitor.max_gap(); +} + +template <typename RangeOfIntervals> +inline typename boost::range_value<RangeOfIntervals>::type::difference_type +maximum_gap(RangeOfIntervals const& range_of_intervals) +{ + typedef typename boost::remove_const + < + typename boost::remove_reference + < + typename boost::range_value + < + RangeOfIntervals + >::type::value_type + >::type + >::type value_type; + + value_type left, right; + + return maximum_gap(range_of_intervals, left, right); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP diff --git a/boost/geometry/algorithms/detail/normalize.hpp b/boost/geometry/algorithms/detail/normalize.hpp new file mode 100644 index 0000000000..913fe324b7 --- /dev/null +++ b/boost/geometry/algorithms/detail/normalize.hpp @@ -0,0 +1,294 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP + +#include <cstddef> + +#include <boost/numeric/conversion/cast.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> +#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace normalization +{ + + +struct do_nothing +{ + template <typename GeometryIn, typename GeometryOut> + static inline void apply(GeometryIn const&, GeometryOut&) + { + } +}; + + +template <std::size_t Dimension, std::size_t DimensionCount> +struct assign_loop +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<Dimension>(point_out, boost::numeric_cast + < + typename coordinate_type<PointOut>::type + >(geometry::get<Dimension>(point_in))); + + assign_loop + < + Dimension + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template <std::size_t DimensionCount> +struct assign_loop<DimensionCount, DimensionCount> +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + static inline void apply(CoordinateType const&, + CoordinateType const&, + PointIn const&, + PointOut&) + { + } +}; + +template <std::size_t DimensionCount> +struct assign_loop<0, DimensionCount> +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<0>(point_out, boost::numeric_cast + < + typename coordinate_type<PointOut>::type + >(longitude)); + + assign_loop + < + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template <std::size_t DimensionCount> +struct assign_loop<1, DimensionCount> +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<1>(point_out, boost::numeric_cast + < + typename coordinate_type<PointOut>::type + >(latitude)); + + assign_loop + < + 2, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template <typename PointIn, typename PointOut> +struct normalize_point +{ + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + typedef typename coordinate_type<PointIn>::type in_coordinate_type; + + in_coordinate_type longitude = geometry::get<0>(point_in); + in_coordinate_type latitude = geometry::get<1>(point_in); + + math::normalize_spheroidal_coordinates + < + typename coordinate_system<PointIn>::type::units, + in_coordinate_type + >(longitude, latitude); + + assign_loop + < + 0, dimension<PointIn>::value + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template <typename BoxIn, typename BoxOut> +class normalize_box +{ + template <typename UnitsIn, typename UnitsOut, typename CoordinateInType> + static inline void apply_to_coordinates(CoordinateInType& lon_min, + CoordinateInType& lat_min, + CoordinateInType& lon_max, + CoordinateInType& lat_max, + BoxIn const& box_in, + BoxOut& box_out) + { + detail::indexed_point_view<BoxOut, min_corner> p_min_out(box_out); + assign_loop + < + 0, dimension<BoxIn>::value + >::apply(lon_min, + lat_min, + detail::indexed_point_view + < + BoxIn const, min_corner + >(box_in), + p_min_out); + + detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out); + assign_loop + < + 0, dimension<BoxIn>::value + >::apply(lon_max, + lat_max, + detail::indexed_point_view + < + BoxIn const, max_corner + >(box_in), + p_max_out); + } + +public: + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + typedef typename coordinate_type<BoxIn>::type in_coordinate_type; + + in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in); + in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in); + in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in); + in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in); + + math::normalize_spheroidal_box_coordinates + < + typename coordinate_system<BoxIn>::type::units, + in_coordinate_type + >(lon_min, lat_min, lon_max, lat_max); + + apply_to_coordinates + < + typename coordinate_system<BoxIn>::type::units, + typename coordinate_system<BoxOut>::type::units + >(lon_min, lat_min, lon_max, lat_max, box_in, box_out); + } +}; + + +}} // namespace detail::normalization +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename GeometryIn, + typename GeometryOut, + typename TagIn = typename tag<GeometryIn>::type, + typename TagOut = typename tag<GeometryOut>::type, + typename CSTagIn = typename cs_tag<GeometryIn>::type, + typename CSTagOut = typename cs_tag<GeometryOut>::type +> +struct normalize : detail::normalization::do_nothing +{}; + + +template <typename PointIn, typename PointOut> +struct normalize + < + PointIn, PointOut, point_tag, point_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::normalization::normalize_point<PointIn, PointOut> +{}; + + +template <typename PointIn, typename PointOut> +struct normalize + < + PointIn, PointOut, point_tag, point_tag, geographic_tag, geographic_tag + > : detail::normalization::normalize_point<PointIn, PointOut> +{}; + + +template <typename BoxIn, typename BoxOut> +struct normalize + < + BoxIn, BoxOut, box_tag, box_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::normalization::normalize_box<BoxIn, BoxOut> +{}; + + +template <typename BoxIn, typename BoxOut> +struct normalize + < + BoxIn, BoxOut, box_tag, box_tag, geographic_tag, geographic_tag + > : detail::normalization::normalize_box<BoxIn, BoxOut> +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + +template <typename GeometryIn, typename GeometryOut> +inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out) +{ + dispatch::normalize + < + GeometryIn, GeometryOut + >::apply(geometry_in, geometry_out); +} + +template <typename GeometryOut, typename GeometryIn> +inline GeometryOut return_normalized(GeometryIn const& geometry_in) +{ + GeometryOut geometry_out; + detail::normalize(geometry_in, geometry_out); + return geometry_out; +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP diff --git a/boost/geometry/algorithms/detail/occupation_info.hpp b/boost/geometry/algorithms/detail/occupation_info.hpp index 002c946170..4048d59d75 100644 --- a/boost/geometry/algorithms/detail/occupation_info.hpp +++ b/boost/geometry/algorithms/detail/occupation_info.hpp @@ -12,6 +12,7 @@ #include <algorithm> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/point_type.hpp> @@ -36,7 +37,7 @@ struct angle_info typedef Point point_type; segment_identifier seg_id; - int turn_index; + std::size_t turn_index; int operation_index; std::size_t cluster_index; Point intersection_point; @@ -57,7 +58,7 @@ class occupation_info public : typedef std::vector<AngleInfo> collection_type; - int count; + std::size_t count; inline occupation_info() : count(0) @@ -67,7 +68,7 @@ public : inline void add(RobustPoint const& incoming_point, RobustPoint const& outgoing_point, RobustPoint const& intersection_point, - int turn_index, int operation_index, + std::size_t turn_index, int operation_index, segment_identifier const& seg_id) { geometry::equal_to<RobustPoint> comparator; @@ -125,11 +126,19 @@ private : }; template<typename Pieces> -inline void move_index(Pieces const& pieces, int& index, int& piece_index, int direction) +inline void move_index(Pieces const& pieces, signed_size_type& index, signed_size_type& piece_index, int direction) { - BOOST_ASSERT(direction == 1 || direction == -1); - BOOST_ASSERT(piece_index >= 0 && piece_index < static_cast<int>(boost::size(pieces)) ); - BOOST_ASSERT(index >= 0 && index < static_cast<int>(boost::size(pieces[piece_index].robust_ring))); + BOOST_GEOMETRY_ASSERT(direction == 1 || direction == -1); + BOOST_GEOMETRY_ASSERT( + piece_index >= 0 + && piece_index < static_cast<signed_size_type>(boost::size(pieces)) ); + BOOST_GEOMETRY_ASSERT( + index >= 0 + && index < static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring))); + + // NOTE: both index and piece_index must be in valid range + // this means that then they could be of type std::size_t + // if the code below was refactored index += direction; if (direction == -1 && index < 0) @@ -142,10 +151,10 @@ inline void move_index(Pieces const& pieces, int& index, int& piece_index, int d index = boost::size(pieces[piece_index].robust_ring) - 1; } if (direction == 1 - && index >= static_cast<int>(boost::size(pieces[piece_index].robust_ring))) + && index >= static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring))) { piece_index++; - if (piece_index >= static_cast<int>(boost::size(pieces))) + if (piece_index >= static_cast<signed_size_type>(boost::size(pieces))) { piece_index = 0; } @@ -176,8 +185,8 @@ inline void add_incoming_and_outgoing_angles( RobustPoint direction_points[2]; for (int i = 0; i < 2; i++) { - int index = turn.operations[operation_index].index_in_robust_ring; - int piece_index = turn.operations[operation_index].piece_index; + signed_size_type index = turn.operations[operation_index].index_in_robust_ring; + signed_size_type piece_index = turn.operations[operation_index].piece_index; while(comparator(pieces[piece_index].robust_ring[index], intersection_point)) { move_index(pieces, index, piece_index, i == 0 ? -1 : 1); diff --git a/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/boost/geometry/algorithms/detail/overlay/add_rings.hpp index 5ff0b57d6e..fcb240941f 100644 --- a/boost/geometry/algorithms/detail/overlay/add_rings.hpp +++ b/boost/geometry/algorithms/detail/overlay/add_rings.hpp @@ -9,6 +9,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP +#include <boost/range.hpp> + #include <boost/geometry/core/closure.hpp> #include <boost/geometry/algorithms/area.hpp> #include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp> diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index 178f3825d7..047eb4993e 100644 --- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -9,6 +9,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP +#include <boost/range.hpp> + #include <boost/geometry/algorithms/area.hpp> #include <boost/geometry/algorithms/envelope.hpp> #include <boost/geometry/algorithms/expand.hpp> diff --git a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp index 03be18e07a..25e442982b 100644 --- a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp +++ b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp @@ -12,12 +12,8 @@ #include <cstddef> - -#include <boost/assert.hpp> #include <boost/range.hpp> - - #include <boost/geometry/algorithms/detail/ring_identifier.hpp> diff --git a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp index fc4f657322..b1a25c9f5e 100644 --- a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp +++ b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp @@ -1,6 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -160,10 +165,12 @@ template typename OutputLinestring, typename OutputIterator, typename Range, + typename RobustPolicy, typename Box, typename Strategy > OutputIterator clip_range_with_box(Box const& b, Range const& range, + RobustPolicy const&, OutputIterator out, Strategy const& strategy) { if (boost::begin(range) == boost::end(range)) diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 13e0a5a51e..dbf3770357 100644 --- a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -11,10 +11,10 @@ #include <boost/array.hpp> -#include <boost/assert.hpp> #include <boost/mpl/assert.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/ring_type.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> @@ -43,8 +43,8 @@ struct copy_segment_point_range { detail::normalized_view<Range const> view(range); - signed_index_type const n = boost::size(view); - signed_index_type index = seg_id.segment_index; + signed_size_type const n = boost::size(view); + signed_size_type index = seg_id.segment_index; if (second) { index++; @@ -54,7 +54,7 @@ struct copy_segment_point_range } } - BOOST_ASSERT(index >= 0 && index < n); + BOOST_GEOMETRY_ASSERT(index >= 0 && index < n); geometry::convert(*(boost::begin(view) + index), point); return true; @@ -95,7 +95,7 @@ struct copy_segment_point_box SegmentIdentifier const& seg_id, bool second, PointOut& point) { - signed_index_type index = seg_id.segment_index; + signed_size_type index = seg_id.segment_index; if (second) { index++; @@ -123,7 +123,7 @@ struct copy_segment_point_multi PointOut& point) { - BOOST_ASSERT + BOOST_GEOMETRY_ASSERT ( seg_id.multi_index >= 0 && seg_id.multi_index < int(boost::size(multi)) @@ -306,7 +306,7 @@ inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geom concept::check<Geometry1 const>(); concept::check<Geometry2 const>(); - BOOST_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1); + BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1); if (seg_id.source_index == 0) { diff --git a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index ceeb1a3b8b..2eefa03c67 100644 --- a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -19,14 +19,11 @@ #include <vector> #include <boost/array.hpp> -#include <boost/assert.hpp> #include <boost/mpl/assert.hpp> #include <boost/range.hpp> #include <boost/type_traits/integral_constant.hpp> -#include <boost/geometry/core/tags.hpp> - -#include <boost/geometry/core/ring_type.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/ring_type.hpp> @@ -64,7 +61,7 @@ struct copy_segments_ring > static inline void apply(Ring const& ring, SegmentIdentifier const& seg_id, - signed_index_type to_index, + signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { @@ -93,10 +90,10 @@ struct copy_segments_ring // So we use the ever-circling iterator and determine when to step out - signed_index_type const from_index = seg_id.segment_index + 1; + signed_size_type const from_index = seg_id.segment_index + 1; // Sanity check - BOOST_ASSERT(from_index < static_cast<signed_index_type>(boost::size(view))); + BOOST_GEOMETRY_ASSERT(from_index < static_cast<signed_size_type>(boost::size(view))); ec_iterator it(boost::begin(view), boost::end(view), boost::begin(view) + from_index); @@ -104,12 +101,12 @@ struct copy_segments_ring // [2..4] -> 4 - 2 + 1 = 3 -> {2,3,4} -> OK // [4..2],size=6 -> 6 - 4 + 2 + 1 = 5 -> {4,5,0,1,2} -> OK // [1..1], travel the whole ring round - signed_index_type const count = from_index <= to_index + signed_size_type const count = from_index <= to_index ? to_index - from_index + 1 - : static_cast<signed_index_type>(boost::size(view)) + : static_cast<signed_size_type>(boost::size(view)) - from_index + to_index + 1; - for (signed_index_type i = 0; i < count; ++i, ++it) + for (signed_size_type i = 0; i < count; ++i, ++it) { detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy); } @@ -151,26 +148,26 @@ public: > static inline void apply(LineString const& ls, SegmentIdentifier const& seg_id, - signed_index_type to_index, + signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { - signed_index_type const from_index = seg_id.segment_index + 1; + signed_size_type const from_index = seg_id.segment_index + 1; // Sanity check if ( from_index > to_index || from_index < 0 - || to_index >= static_cast<signed_index_type>(boost::size(ls)) ) + || to_index >= static_cast<signed_size_type>(boost::size(ls)) ) { return; } - signed_index_type const count = to_index - from_index + 1; + signed_size_type const count = to_index - from_index + 1; typename boost::range_iterator<LineString const>::type it = boost::begin(ls) + from_index; - for (signed_index_type i = 0; i < count; ++i, ++it) + for (signed_size_type i = 0; i < count; ++i, ++it) { append_to_output(current_output, *it, robust_policy, boost::integral_constant<bool, RemoveSpikes>()); @@ -190,7 +187,7 @@ struct copy_segments_polygon > static inline void apply(Polygon const& polygon, SegmentIdentifier const& seg_id, - signed_index_type to_index, + signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { @@ -220,14 +217,14 @@ struct copy_segments_box > static inline void apply(Box const& box, SegmentIdentifier const& seg_id, - signed_index_type to_index, + signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { - signed_index_type index = seg_id.segment_index + 1; - BOOST_ASSERT(index < 5); + signed_size_type index = seg_id.segment_index + 1; + BOOST_GEOMETRY_ASSERT(index < 5); - signed_index_type const count = index <= to_index + signed_size_type const count = index <= to_index ? to_index - index + 1 : 5 - index + to_index + 1; @@ -238,7 +235,7 @@ struct copy_segments_box // (possibly cyclic) copy to output // (see comments in ring-version) - for (signed_index_type i = 0; i < count; i++, index++) + for (signed_size_type i = 0; i < count; i++, index++) { detail::overlay::append_no_dups_or_spikes(current_output, bp[index % 5], robust_policy); @@ -260,15 +257,15 @@ struct copy_segments_multi > static inline void apply(MultiGeometry const& multi_geometry, SegmentIdentifier const& seg_id, - signed_index_type to_index, + signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& current_output) { - BOOST_ASSERT + BOOST_GEOMETRY_ASSERT ( seg_id.multi_index >= 0 - && seg_id.multi_index < int(boost::size(multi_geometry)) + && static_cast<std::size_t>(seg_id.multi_index) < boost::size(multi_geometry) ); // Call the single-version @@ -348,7 +345,7 @@ template > inline void copy_segments(Geometry const& geometry, SegmentIdentifier const& seg_id, - signed_index_type to_index, + signed_size_type to_index, RobustPolicy const& robust_policy, RangeOut& range_out) { diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index 7ed93f542a..3f81c4dca9 100644 --- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -22,7 +22,6 @@ # define BOOST_GEOMETRY_DEBUG_IDENTIFIER #endif -#include <boost/assert.hpp> #include <boost/range.hpp> #include <boost/geometry/algorithms/detail/ring_identifier.hpp> @@ -358,14 +357,14 @@ inline void enrich_assign(Container& operations, = turn_points[it->turn_index].operations[it->operation_index]; prev_op.enriched.travels_to_ip_index - = static_cast<int>(it->turn_index); + = static_cast<signed_size_type>(it->turn_index); prev_op.enriched.travels_to_vertex_index = it->subject->seg_id.segment_index; if (! first && prev_op.seg_id.segment_index == op.seg_id.segment_index) { - prev_op.enriched.next_ip_index = static_cast<int>(it->turn_index); + prev_op.enriched.next_ip_index = static_cast<signed_size_type>(it->turn_index); } first = false; } diff --git a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp index ef32edeefa..5964f3ba44 100644 --- a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp +++ b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp @@ -37,13 +37,13 @@ struct enrichment_info // vertex to which is free travel after this IP, // so from "segment_index+1" to "travels_to_vertex_index", without IP-s, // can be -1 - signed_index_type travels_to_vertex_index; + signed_size_type travels_to_vertex_index; // same but now IP index, so "next IP index" but not on THIS segment - int travels_to_ip_index; + signed_size_type travels_to_ip_index; // index of next IP on this segment, -1 if there is no one - int next_ip_index; + signed_size_type next_ip_index; }; diff --git a/boost/geometry/algorithms/detail/overlay/follow.hpp b/boost/geometry/algorithms/detail/overlay/follow.hpp index acf38d09ab..22807b5140 100644 --- a/boost/geometry/algorithms/detail/overlay/follow.hpp +++ b/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -163,7 +163,7 @@ struct action_selector<overlay_intersection, RemoveSpikes> static inline void enter(LineStringOut& current_piece, LineString const& , segment_identifier& segment_id, - signed_index_type , Point const& point, + signed_size_type , Point const& point, Operation const& operation, RobustPolicy const& , OutputIterator& ) @@ -186,7 +186,7 @@ struct action_selector<overlay_intersection, RemoveSpikes> static inline void leave(LineStringOut& current_piece, LineString const& linestring, segment_identifier& segment_id, - signed_index_type index, Point const& point, + signed_size_type index, Point const& point, Operation const& , RobustPolicy const& robust_policy, OutputIterator& out) @@ -217,7 +217,7 @@ struct action_selector<overlay_intersection, RemoveSpikes> static inline void isolated_point(LineStringOut&, LineString const&, segment_identifier&, - signed_index_type, Point const& point, + signed_size_type, Point const& point, Operation const& , OutputIterator& out) { LineStringOut isolated_point_ls; @@ -268,7 +268,7 @@ struct action_selector<overlay_difference, RemoveSpikes> static inline void enter(LineStringOut& current_piece, LineString const& linestring, segment_identifier& segment_id, - signed_index_type index, Point const& point, + signed_size_type index, Point const& point, Operation const& operation, RobustPolicy const& robust_policy, OutputIterator& out) @@ -289,7 +289,7 @@ struct action_selector<overlay_difference, RemoveSpikes> static inline void leave(LineStringOut& current_piece, LineString const& linestring, segment_identifier& segment_id, - signed_index_type index, Point const& point, + signed_size_type index, Point const& point, Operation const& operation, RobustPolicy const& robust_policy, OutputIterator& out) @@ -309,7 +309,7 @@ struct action_selector<overlay_difference, RemoveSpikes> static inline void isolated_point(LineStringOut&, LineString const&, segment_identifier&, - signed_index_type, Point const&, + signed_size_type, Point const&, Operation const&, OutputIterator&) { } @@ -496,7 +496,7 @@ public : false, RemoveSpikes >::apply(linestring, current_segment_id, - static_cast<signed_index_type>(boost::size(linestring) - 1), + static_cast<signed_size_type>(boost::size(linestring) - 1), robust_policy, current_piece); } diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp index 7bcc0b951e..b2c3836712 100644 --- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp +++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp @@ -14,9 +14,9 @@ #include <algorithm> #include <iterator> -#include <boost/assert.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> @@ -142,7 +142,7 @@ static inline bool is_isolated_point(Turn const& turn, if ( turn.method == method_none ) { - BOOST_ASSERT( operation.operation == operation_continue ); + BOOST_GEOMETRY_ASSERT( operation.operation == operation_continue ); return true; } @@ -282,7 +282,7 @@ protected: false, false // do not reverse; do not remove spikes >::apply(linestring, current_segment_id, - static_cast<signed_index_type>(boost::size(linestring) - 1), + static_cast<signed_size_type>(boost::size(linestring) - 1), robust_policy, current_piece); } @@ -327,7 +327,7 @@ public: throw inconsistent_turns_exception(); } #else - BOOST_ASSERT(enter_count == 0); + BOOST_GEOMETRY_ASSERT(enter_count == 0); #endif return process_end(entered, linestring, @@ -404,7 +404,7 @@ protected: }; template <typename TurnIterator> - static inline signed_index_type get_multi_index(TurnIterator it) + static inline signed_size_type get_multi_index(TurnIterator it) { return boost::begin(it->operations)->seg_id.multi_index; } @@ -412,10 +412,10 @@ protected: class has_other_multi_id { private: - signed_index_type m_multi_id; + signed_size_type m_multi_id; public: - has_other_multi_id(signed_index_type multi_id) + has_other_multi_id(signed_size_type multi_id) : m_multi_id(multi_id) {} template <typename Turn> @@ -433,7 +433,7 @@ public: TurnIterator first, TurnIterator beyond, OutputIterator oit) { - BOOST_ASSERT( first != beyond ); + BOOST_GEOMETRY_ASSERT( first != beyond ); typedef copy_linestrings_in_range < @@ -446,7 +446,7 @@ public: // Iterate through all intersection points (they are // ordered along the each linestring) - signed_index_type current_multi_id = get_multi_index(first); + signed_size_type current_multi_id = get_multi_index(first); oit = copy_linestrings::apply(ls_first, ls_first + current_multi_id, @@ -463,7 +463,7 @@ public: oit = Base::apply(*(ls_first + current_multi_id), linear, per_ls_current, per_ls_next, oit); - signed_index_type next_multi_id(-1); + signed_size_type next_multi_id = -1; linestring_iterator ls_next = ls_beyond; if ( per_ls_next != beyond ) { diff --git a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index 63011c7d48..4668189924 100644 --- a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -12,6 +12,9 @@ #include <cstddef> +#include <boost/mpl/if.hpp> +#include <boost/range.hpp> + #include <boost/geometry/algorithms/convert.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp> diff --git a/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/boost/geometry/algorithms/detail/overlay/get_ring.hpp index 131d58d582..460c30def3 100644 --- a/boost/geometry/algorithms/detail/overlay/get_ring.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_ring.hpp @@ -10,9 +10,9 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP -#include <boost/assert.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/ring_type.hpp> @@ -82,7 +82,7 @@ struct get_ring<polygon_tag> ring_identifier const& id, Polygon const& polygon) { - BOOST_ASSERT + BOOST_GEOMETRY_ASSERT ( id.ring_index >= -1 && id.ring_index < int(boost::size(interior_rings(polygon))) @@ -102,7 +102,7 @@ struct get_ring<multi_polygon_tag> ring_identifier const& id, MultiPolygon const& multi_polygon) { - BOOST_ASSERT + BOOST_GEOMETRY_ASSERT ( id.multi_index >= 0 && id.multi_index < int(boost::size(multi_polygon)) diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index b3b1a06f68..717f0b47a9 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -15,10 +15,10 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP -#include <boost/assert.hpp> #include <boost/core/ignore_unused.hpp> #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/strategies/intersection.hpp> #include <boost/geometry/algorithms/convert.hpp> @@ -115,7 +115,7 @@ struct base_turn_handler { ti.method = method; - BOOST_ASSERT(index < info.count); + BOOST_GEOMETRY_ASSERT(index < info.count); geometry::convert(info.intersections[index], ti.point); ti.operations[0].fraction = info.fractions[index].robust_ra; @@ -597,7 +597,7 @@ struct collinear : public base_turn_handler int const arrival = dir_info.arrival[0]; // Should not be 0, this is checked before - BOOST_ASSERT(arrival != 0); + BOOST_GEOMETRY_ASSERT(arrival != 0); int const side_p = side.pk_wrt_p1(); int const side_q = side.qk_wrt_q1(); diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index 4a3cacbedd..0b3cb72747 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -14,6 +14,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> #include <boost/geometry/policies/robustness/no_rescale_policy.hpp> @@ -153,7 +154,7 @@ public: } else { - BOOST_ASSERT(result.template get<0>().count == 1); + BOOST_GEOMETRY_ASSERT(result.template get<0>().count == 1); ips[0].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last); ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last); @@ -297,10 +298,10 @@ struct get_turn_info_for_endpoint // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = result.template get<0>().intersections[ip_index]; - BOOST_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt)); - BOOST_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt)); - BOOST_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt)); - BOOST_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt)); #endif // TODO - calculate first/last only if needed @@ -412,8 +413,8 @@ struct get_turn_info_for_endpoint // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; - BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); - BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); #endif if ( ip_i2 ) { @@ -448,7 +449,7 @@ struct get_turn_info_for_endpoint } else { - BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union)); + BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union)); //op1 = operation_union; //op2 = operation_union; } @@ -463,8 +464,8 @@ struct get_turn_info_for_endpoint // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; - BOOST_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); - BOOST_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); #endif if ( ip_i2 ) { @@ -499,7 +500,7 @@ struct get_turn_info_for_endpoint } else { - BOOST_ASSERT(operations_combination(operations, operation_intersection, operation_union)); + BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union)); //op1 = operation_blocked; //op2 = operation_union; } @@ -560,7 +561,7 @@ struct get_turn_info_for_endpoint // NOTE: is_collinear is NOT set for the first endpoint // for which there is no preceding segment - //BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); + //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); if ( ! is_p_first_ip ) { tp.operations[0].is_collinear = op0 != operation_intersection diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index e0d75108b9..e4f8de42e1 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -42,7 +42,8 @@ template <typename PointP, typename PointQ, > struct side_calculator { - typedef boost::geometry::strategy::side::side_by_triangle<> side; // todo: get from coordinate system + // todo: get from coordinate system + typedef boost::geometry::strategy::side::side_by_triangle<> side; inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, Qi const& qi, Qj const& qj, Qk const& qk) @@ -71,8 +72,9 @@ struct robust_points { typedef typename geometry::robust_point_type < - Point1, RobustPolicy + Point1, RobustPolicy >::type robust_point1_type; + // TODO: define robust_point2_type using Point2? typedef robust_point1_type robust_point2_type; @@ -96,23 +98,23 @@ template <typename Point1, typename Point2, typename RobustPolicy> class intersection_info_base : private robust_points<Point1, Point2, RobustPolicy> { - typedef robust_points<Point1, Point2, RobustPolicy> base_t; + typedef robust_points<Point1, Point2, RobustPolicy> base; public: typedef Point1 point1_type; typedef Point2 point2_type; - typedef typename base_t::robust_point1_type robust_point1_type; - typedef typename base_t::robust_point2_type robust_point2_type; + typedef typename base::robust_point1_type robust_point1_type; + typedef typename base::robust_point2_type robust_point2_type; typedef side_calculator<robust_point1_type, robust_point2_type> side_calculator_type; intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, RobustPolicy const& robust_policy) - : base_t(pi, pj, pk, qi, qj, qk, robust_policy) - , m_side_calc(base_t::m_rpi, base_t::m_rpj, base_t::m_rpk, - base_t::m_rqi, base_t::m_rqj, base_t::m_rqk) + : base(pi, pj, pk, qi, qj, qk, robust_policy) + , m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk, + base::m_rqi, base::m_rqj, base::m_rqk) , m_pi(pi), m_pj(pj), m_pk(pk) , m_qi(qi), m_qj(qj), m_qk(qk) {} @@ -125,13 +127,13 @@ public: inline Point2 const& qj() const { return m_qj; } inline Point2 const& qk() const { return m_qk; } - inline robust_point1_type const& rpi() const { return base_t::m_rpi; } - inline robust_point1_type const& rpj() const { return base_t::m_rpj; } - inline robust_point1_type const& rpk() const { return base_t::m_rpk; } + inline robust_point1_type const& rpi() const { return base::m_rpi; } + inline robust_point1_type const& rpj() const { return base::m_rpj; } + inline robust_point1_type const& rpk() const { return base::m_rpk; } - inline robust_point2_type const& rqi() const { return base_t::m_rqi; } - inline robust_point2_type const& rqj() const { return base_t::m_rqj; } - inline robust_point2_type const& rqk() const { return base_t::m_rqk; } + inline robust_point2_type const& rqi() const { return base::m_rqi; } + inline robust_point2_type const& rqj() const { return base::m_rqj; } + inline robust_point2_type const& rqk() const { return base::m_rqk; } inline side_calculator_type const& sides() const { return m_side_calc; } @@ -187,11 +189,17 @@ private: }; -template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy> +template +< + typename Point1, + typename Point2, + typename TurnPoint, + typename RobustPolicy +> class intersection_info : public intersection_info_base<Point1, Point2, RobustPolicy> { - typedef intersection_info_base<Point1, Point2, RobustPolicy> base_t; + typedef intersection_info_base<Point1, Point2, RobustPolicy> base; typedef typename strategy_intersection < @@ -205,7 +213,7 @@ class intersection_info public: typedef model::referring_segment<Point1 const> segment_type1; typedef model::referring_segment<Point2 const> segment_type2; - typedef typename base_t::side_calculator_type side_calculator_type; + typedef typename base::side_calculator_type side_calculator_type; typedef typename strategy::return_type result_type; typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info @@ -214,10 +222,12 @@ public: intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk, Point2 const& qi, Point2 const& qj, Point2 const& qk, RobustPolicy const& robust_policy) - : base_t(pi, pj, pk, qi, qj, qk, robust_policy) + : base(pi, pj, pk, qi, qj, qk, robust_policy) , m_result(strategy::apply(segment_type1(pi, pj), segment_type2(qi, qj), - robust_policy)) + robust_policy, + base::rpi(), base::rpj(), + base::rqi(), base::rqj())) , m_robust_policy(robust_policy) {} @@ -228,19 +238,22 @@ public: // TODO: it's more like is_spike_ip_p inline bool is_spike_p() const { - if ( base_t::sides().pk_wrt_p1() == 0 ) + if (base::sides().pk_wrt_p1() == 0) { - if ( ! is_ip_j<0>() ) + if (! is_ip_j<0>()) + { return false; + } - int const qk_p1 = base_t::sides().qk_wrt_p1(); - int const qk_p2 = base_t::sides().qk_wrt_p2(); + int const qk_p1 = base::sides().qk_wrt_p1(); + int const qk_p2 = base::sides().qk_wrt_p2(); - if ( qk_p1 == -qk_p2 ) + if (qk_p1 == -qk_p2) { - if ( qk_p1 == 0 ) + if (qk_p1 == 0) { - return is_spike_of_collinear(base_t::pi(), base_t::pj(), base_t::pk()); + return is_spike_of_collinear(base::pi(), base::pj(), + base::pk()); } return true; @@ -253,19 +266,22 @@ public: // TODO: it's more like is_spike_ip_q inline bool is_spike_q() const { - if ( base_t::sides().qk_wrt_q1() == 0 ) + if (base::sides().qk_wrt_q1() == 0) { - if ( ! is_ip_j<1>() ) + if (! is_ip_j<1>()) + { return false; + } - int const pk_q1 = base_t::sides().pk_wrt_q1(); - int const pk_q2 = base_t::sides().pk_wrt_q2(); + int const pk_q1 = base::sides().pk_wrt_q1(); + int const pk_q2 = base::sides().pk_wrt_q2(); - if ( pk_q1 == -pk_q2 ) + if (pk_q1 == -pk_q2) { - if ( pk_q1 == 0 ) + if (pk_q1 == 0) { - return is_spike_of_collinear(base_t::qi(), base_t::qj(), base_t::qk()); + return is_spike_of_collinear(base::qi(), base::qj(), + base::qk()); } return true; @@ -277,9 +293,10 @@ public: private: template <typename Point> - inline bool is_spike_of_collinear(Point const& i, Point const& j, Point const& k) const + inline bool is_spike_of_collinear(Point const& i, Point const& j, + Point const& k) const { - typedef model::referring_segment<Point const> seg_t; + typedef model::referring_segment<Point const> seg; typedef strategy_intersection < @@ -289,7 +306,7 @@ private: typedef typename si::segment_intersection_strategy_type strategy; typename strategy::return_type result - = strategy::apply(seg_t(i, j), seg_t(j, k), m_robust_policy); + = strategy::apply(seg(i, j), seg(j, k), m_robust_policy); return result.template get<0>().count == 2; } @@ -300,9 +317,9 @@ private: int arrival = d_info().arrival[OpId]; bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0; - if ( same_dirs ) + if (same_dirs) { - if ( i_info().count == 2 ) + if (i_info().count == 2) { return arrival != -1; } diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 71946543ee..ccb42d4c92 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -14,6 +14,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP +#include <boost/geometry/core/assert.hpp> + #include <boost/geometry/util/condition.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> @@ -569,7 +571,7 @@ struct get_turn_info_linear_areal tp.operations[0].is_collinear = true; //tp.operations[1].is_collinear = false; - BOOST_ASSERT(inters.i_info().count > 1); + BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1); base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); @@ -816,7 +818,7 @@ struct get_turn_info_linear_areal if ( inters.i_info().count > 1 ) { - //BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); + //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); tp.operations[0].is_collinear = true; tp.operations[1].operation = opposite ? operation_continue : operation_union; } diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 1ec88e54a0..19f0859cbb 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -14,6 +14,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP +#include <boost/geometry/core/assert.hpp> + #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp> @@ -579,7 +581,7 @@ struct get_turn_info_linear_linear tp.operations[0].is_collinear = true; tp.operations[1].is_collinear = false; - BOOST_ASSERT(inters.i_info().count > 1); + BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1); base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); @@ -612,7 +614,7 @@ struct get_turn_info_linear_linear tp.operations[0].is_collinear = false; tp.operations[1].is_collinear = true; - BOOST_ASSERT(inters.i_info().count > 0); + BOOST_GEOMETRY_ASSERT(inters.i_info().count > 0); base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0); @@ -686,7 +688,7 @@ struct get_turn_info_linear_linear operation_type & op0 = turn.operations[0].operation; operation_type & op1 = turn.operations[1].operation; - BOOST_ASSERT(op0 != operation_blocked || op1 != operation_blocked ); + BOOST_GEOMETRY_ASSERT(op0 != operation_blocked || op1 != operation_blocked ); if ( op0 == operation_blocked ) { diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp index a5d8f3f023..098c7b5642 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -22,6 +22,7 @@ #include <boost/array.hpp> #include <boost/concept_check.hpp> #include <boost/mpl/if.hpp> +#include <boost/mpl/vector_c.hpp> #include <boost/range.hpp> #include <boost/geometry/core/access.hpp> @@ -142,7 +143,7 @@ class get_turns_in_sections template <typename Geometry, typename Section> static inline bool neighbouring(Section const& section, - int index1, int index2) + signed_size_type index1, signed_size_type index2) { // About n-2: // (square: range_count=5, indices 0,1,2,3 @@ -150,7 +151,7 @@ class get_turns_in_sections // Also tested for open polygons, and/or duplicates // About first condition: will be optimized by compiler (static) // It checks if it is areal (box,ring,(multi)polygon - int const n = int(section.range_count); + signed_size_type const n = static_cast<signed_size_type>(section.range_count); boost::ignore_unused_variable_warning(n); boost::ignore_unused_variable_warning(index1); @@ -207,8 +208,8 @@ public : int const dir1 = sec1.directions[0]; int const dir2 = sec2.directions[0]; - int index1 = sec1.begin_index; - int ndi1 = sec1.non_duplicate_index; + signed_size_type index1 = sec1.begin_index; + signed_size_type ndi1 = sec1.non_duplicate_index; bool const same_source = source_id1 == source_id2 @@ -236,8 +237,8 @@ public : begin_range_1, end_range_1, next1, true); advance_to_non_duplicate_next(nd_next1, it1, sec1, robust_policy); - int index2 = sec2.begin_index; - int ndi2 = sec2.non_duplicate_index; + signed_size_type index2 = sec2.begin_index; + signed_size_type ndi2 = sec2.non_duplicate_index; range2_iterator prev2, it2, end2; @@ -359,7 +360,7 @@ private : typename boost::range_iterator<Range const>::type& it, typename boost::range_iterator<Range const>::type& prev, typename boost::range_iterator<Range const>::type& end, - int& index, int& ndi, + signed_size_type& index, signed_size_type& ndi, int dir, Box const& other_bounding_box, RobustPolicy const& robust_policy) { it = boost::begin(range) + section.begin_index; @@ -524,8 +525,8 @@ struct get_turns_cs RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy, - signed_index_type multi_index = -1, - signed_index_type ring_index = -1) + signed_size_type multi_index = -1, + signed_size_type ring_index = -1) { if ( boost::size(range) <= 1) { @@ -552,7 +553,7 @@ struct get_turns_cs //char previous_side[2] = {0, 0}; - signed_index_type index = 0; + signed_size_type index = 0; for (iterator_type prev = it++; it != boost::end(view); @@ -696,7 +697,7 @@ struct get_turns_polygon_cs int source_id2, Box const& box, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy, - signed_index_type multi_index = -1) + signed_size_type multi_index = -1) { typedef typename geometry::ring_type<Polygon>::type ring_type; @@ -714,7 +715,7 @@ struct get_turns_polygon_cs turns, interrupt_policy, multi_index, -1); - signed_index_type i = 0; + signed_size_type i = 0; typename interior_return_type<Polygon const>::type rings = interior_rings(polygon); @@ -753,7 +754,7 @@ struct get_turns_multi_polygon_cs Multi const >::type iterator_type; - signed_index_type i = 0; + signed_size_type i = 0; for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it, ++i) diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 3101de8c35..af0731f5a9 100644 --- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -1,9 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -39,9 +39,11 @@ #include <boost/geometry/policies/robustness/get_rescale_policy.hpp> #include <boost/geometry/views/segment_view.hpp> +#include <boost/geometry/views/detail/boundary_view.hpp> #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp> #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp> +#include <boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp> #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp> @@ -283,7 +285,8 @@ namespace dispatch template < // real types - typename Geometry1, typename Geometry2, + typename Geometry1, + typename Geometry2, typename GeometryOut, overlay_type OverlayType, // orientation @@ -409,13 +412,13 @@ struct intersection_insert template <typename RobustPolicy, typename OutputIterator, typename Strategy> static inline OutputIterator apply(Linestring const& linestring, Box const& box, - RobustPolicy const& , + RobustPolicy const& robust_policy, OutputIterator out, Strategy const& ) { typedef typename point_type<GeometryOut>::type point_type; strategy::intersection::liang_barsky<Box, point_type> lb_strategy; return detail::intersection::clip_range_with_box - <GeometryOut>(box, linestring, out, lb_strategy); + <GeometryOut>(box, linestring, robust_policy, out, lb_strategy); } }; @@ -487,7 +490,7 @@ struct intersection_insert template <typename RobustPolicy, typename OutputIterator, typename Strategy> static inline OutputIterator apply(Segment const& segment, Box const& box, - RobustPolicy const& ,// TODO: propagate to clip_range_with_box + RobustPolicy const& robust_policy, OutputIterator out, Strategy const& ) { geometry::segment_view<Segment> range(segment); @@ -495,7 +498,7 @@ struct intersection_insert typedef typename point_type<GeometryOut>::type point_type; strategy::intersection::liang_barsky<Box, point_type> lb_strategy; return detail::intersection::clip_range_with_box - <GeometryOut>(box, range, out, lb_strategy); + <GeometryOut>(box, range, robust_policy, out, lb_strategy); } }; @@ -573,6 +576,46 @@ struct intersection_insert_reversed }; +// dispatch for intersection(areal, areal, linear) +template +< + typename Geometry1, typename Geometry2, + typename LinestringOut, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag1, typename Tag2 +> +struct intersection_insert + < + Geometry1, Geometry2, + LinestringOut, + overlay_intersection, + Reverse1, Reverse2, ReverseOut, + Tag1, Tag2, linestring_tag, + true, true, false + > +{ + template + < + typename RobustPolicy, typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + detail::boundary_view<Geometry1 const> view1(geometry1); + detail::boundary_view<Geometry2 const> view2(geometry2); + + return detail::overlay::linear_linear_linestring + < + detail::boundary_view<Geometry1 const>, + detail::boundary_view<Geometry2 const>, + LinestringOut, + overlay_intersection + >::apply(view1, view2, robust_policy, oit, strategy); + } +}; // dispatch for non-areal geometries template @@ -700,6 +743,79 @@ struct intersection_insert {}; +// dispatch for difference/intersection of pointlike-linear geometries +template +< + typename Point, typename Linear, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag +> +struct intersection_insert + < + Point, Linear, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + point_tag, Tag, point_tag, + false, false, false + > : detail_dispatch::overlay::pointlike_linear_point + < + Point, Linear, PointOut, OverlayType, + point_tag, typename tag_cast<Tag, segment_tag, linear_tag>::type + > +{}; + + +template +< + typename MultiPoint, typename Linear, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag +> +struct intersection_insert + < + MultiPoint, Linear, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + multi_point_tag, Tag, point_tag, + false, false, false + > : detail_dispatch::overlay::pointlike_linear_point + < + MultiPoint, Linear, PointOut, OverlayType, + multi_point_tag, + typename tag_cast<Tag, segment_tag, linear_tag>::type + > +{}; + + +template +< + typename Linestring, typename MultiPoint, typename PointOut, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Linestring, MultiPoint, PointOut, overlay_intersection, + Reverse1, Reverse2, ReverseOut, + linestring_tag, multi_point_tag, point_tag, + false, false, false + > +{ + template <typename RobustPolicy, typename OutputIterator, typename Strategy> + static inline OutputIterator apply(Linestring const& linestring, + MultiPoint const& multipoint, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + return detail_dispatch::overlay::pointlike_linear_point + < + MultiPoint, Linestring, PointOut, overlay_intersection, + multi_point_tag, linear_tag + >::apply(multipoint, linestring, robust_policy, out, strategy); + } +}; + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index d4ebcf296b..34517f6590 100644 --- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -157,13 +157,18 @@ protected: < typename Turns, typename LinearGeometry1, - typename LinearGeometry2 + typename LinearGeometry2, + typename RobustPolicy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, - LinearGeometry2 const& linear2) + LinearGeometry2 const& linear2, + RobustPolicy const& robust_policy) { turns.clear(); + + detail::get_turns::no_interrupt_policy interrupt_policy; + geometry::detail::relate::turns::get_turns < LinearGeometry1, @@ -173,8 +178,9 @@ protected: LinearGeometry1, LinearGeometry2, assign_policy - > - >::apply(turns, linear1, linear2); + >, + RobustPolicy + >::apply(turns, linear1, linear2, interrupt_policy, robust_policy); } @@ -229,19 +235,27 @@ public: > static inline OutputIterator apply(Linear1 const& linear1, Linear2 const& linear2, - RobustPolicy const&, + RobustPolicy const& robust_policy, OutputIterator oit, Strategy const& ) { typedef typename detail::relate::turns::get_turns < - Linear1, Linear2 + Linear1, + Linear2, + detail::get_turns::get_turn_info_type + < + Linear1, + Linear2, + assign_policy + >, + RobustPolicy >::turn_info turn_info; typedef std::vector<turn_info> turns_container; turns_container turns; - compute_turns(turns, linear1, linear2); + compute_turns(turns, linear1, linear2, robust_policy); if ( turns.empty() ) { diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp index a2f52848d1..baf9d4777d 100644 --- a/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -1,7 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -28,7 +33,7 @@ #include <boost/geometry/algorithms/detail/recalculate.hpp> -#include <boost/geometry/algorithms/num_points.hpp> +#include <boost/geometry/algorithms/is_empty.hpp> #include <boost/geometry/algorithms/reverse.hpp> #include <boost/geometry/algorithms/detail/overlay/add_rings.hpp> @@ -125,8 +130,7 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, // Intersection: return nothing // Difference: return first of them if (Direction == overlay_intersection - || (Direction == overlay_difference - && geometry::num_points(geometry1) == 0)) + || (Direction == overlay_difference && geometry::is_empty(geometry1))) { return out; } @@ -162,14 +166,15 @@ struct overlay OutputIterator out, Strategy const& ) { - if ( geometry::num_points(geometry1) == 0 - && geometry::num_points(geometry2) == 0 ) + bool const is_empty1 = geometry::is_empty(geometry1); + bool const is_empty2 = geometry::is_empty(geometry2); + + if (is_empty1 && is_empty2) { return out; } - if ( geometry::num_points(geometry1) == 0 - || geometry::num_points(geometry2) == 0 ) + if (is_empty1 || is_empty2) { return return_if_one_input_is_empty < diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp new file mode 100644 index 0000000000..156cb54867 --- /dev/null +++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp @@ -0,0 +1,343 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP + +#include <iterator> +#include <vector> + +#include <boost/range.hpp> + +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/geometries/box.hpp> + +#include <boost/geometry/iterators/segment_iterator.hpp> + +#include <boost/geometry/algorithms/disjoint.hpp> +#include <boost/geometry/algorithms/envelope.hpp> +#include <boost/geometry/algorithms/expand.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> + +#include <boost/geometry/algorithms/detail/not.hpp> +#include <boost/geometry/algorithms/detail/partition.hpp> +#include <boost/geometry/algorithms/detail/relate/less.hpp> +#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp> +#include <boost/geometry/algorithms/detail/equals/point_point.hpp> +#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp> +#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp> + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +// action struct for pointlike-linear difference/intersection +// it works the same as its pointlike-pointlike counterpart, hence the +// derivation +template <typename PointOut, overlay_type OverlayType> +struct action_selector_pl_l + : action_selector_pl_pl<PointOut, OverlayType> +{}; + +// difference/intersection of point-linear +template +< + typename Point, + typename Linear, + typename PointOut, + overlay_type OverlayType, + typename Policy +> +struct point_linear_point +{ + template <typename RobustPolicy, typename OutputIterator, typename Strategy> + static inline OutputIterator apply(Point const& point, + Linear const& linear, + RobustPolicy const&, + OutputIterator oit, + Strategy const&) + { + action_selector_pl_l + < + PointOut, OverlayType + >::apply(point, Policy::apply(point, linear), oit); + return oit; + } +}; + +// difference/intersection of multipoint-segment +template +< + typename MultiPoint, + typename Segment, + typename PointOut, + overlay_type OverlayType, + typename Policy +> +struct multipoint_segment_point +{ + template <typename RobustPolicy, typename OutputIterator, typename Strategy> + static inline OutputIterator apply(MultiPoint const& multipoint, + Segment const& segment, + RobustPolicy const&, + OutputIterator oit, + Strategy const&) + { + for (typename boost::range_iterator<MultiPoint const>::type + it = boost::begin(multipoint); + it != boost::end(multipoint); + ++it) + { + action_selector_pl_l + < + PointOut, OverlayType + >::apply(*it, Policy::apply(*it, segment), oit); + } + + return oit; + } +}; + + +// difference/intersection of multipoint-linear +template +< + typename MultiPoint, + typename Linear, + typename PointOut, + overlay_type OverlayType, + typename Policy +> +class multipoint_linear_point +{ +private: + // structs for partition -- start + struct expand_box + { + template <typename Box, typename Geometry> + static inline void apply(Box& total, Geometry const& geometry) + { + geometry::expand(total, geometry::return_envelope<Box>(geometry)); + } + + }; + + struct overlaps_box + { + template <typename Box, typename Geometry> + static inline bool apply(Box const& box, Geometry const& geometry) + { + return ! geometry::disjoint(geometry, box); + } + }; + + template <typename OutputIterator> + class item_visitor_type + { + public: + item_visitor_type(OutputIterator& oit) : m_oit(oit) {} + + template <typename Item1, typename Item2> + inline void apply(Item1 const& item1, Item2 const& item2) + { + action_selector_pl_l + < + PointOut, overlay_intersection + >::apply(item1, Policy::apply(item1, item2), m_oit); + } + + private: + OutputIterator& m_oit; + }; + // structs for partition -- end + + class segment_range + { + public: + typedef geometry::segment_iterator<Linear const> const_iterator; + typedef const_iterator iterator; + + segment_range(Linear const& linear) + : m_linear(linear) + {} + + const_iterator begin() const + { + return geometry::segments_begin(m_linear); + } + + const_iterator end() const + { + return geometry::segments_end(m_linear); + } + + private: + Linear const& m_linear; + }; + + template <typename OutputIterator> + static inline OutputIterator get_common_points(MultiPoint const& multipoint, + Linear const& linear, + OutputIterator oit) + { + item_visitor_type<OutputIterator> item_visitor(oit); + + segment_range rng(linear); + + geometry::partition + < + geometry::model::box + < + typename boost::range_value<MultiPoint>::type + >, + expand_box, + overlaps_box + >::apply(multipoint, rng, item_visitor); + + return oit; + } + +public: + template <typename RobustPolicy, typename OutputIterator, typename Strategy> + static inline OutputIterator apply(MultiPoint const& multipoint, + Linear const& linear, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + typedef std::vector + < + typename boost::range_value<MultiPoint>::type + > point_vector_type; + + point_vector_type common_points; + + // compute the common points + get_common_points(multipoint, linear, + std::back_inserter(common_points)); + + return multipoint_multipoint_point + < + MultiPoint, point_vector_type, PointOut, OverlayType + >::apply(multipoint, common_points, robust_policy, oit, strategy); + } +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch { namespace overlay +{ + +// dispatch struct for pointlike-linear difference/intersection computation +template +< + typename PointLike, + typename Linear, + typename PointOut, + overlay_type OverlayType, + typename Tag1, + typename Tag2 +> +struct pointlike_linear_point + : not_implemented<PointLike, Linear, PointOut> +{}; + + +template +< + typename Point, + typename Linear, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + Point, Linear, PointOut, OverlayType, point_tag, linear_tag + > : detail::overlay::point_linear_point + < + Point, Linear, PointOut, OverlayType, + detail::not_<detail::disjoint::reverse_covered_by> + > +{}; + + +template +< + typename Point, + typename Segment, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + Point, Segment, PointOut, OverlayType, point_tag, segment_tag + > : detail::overlay::point_linear_point + < + Point, Segment, PointOut, OverlayType, + detail::not_<detail::disjoint::reverse_covered_by> + > +{}; + + +template +< + typename MultiPoint, + typename Linear, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag + > : detail::overlay::multipoint_linear_point + < + MultiPoint, Linear, PointOut, OverlayType, + detail::not_<detail::disjoint::reverse_covered_by> + > +{}; + + +template +< + typename MultiPoint, + typename Segment, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag + > : detail::overlay::multipoint_segment_point + < + MultiPoint, Segment, PointOut, OverlayType, + detail::not_<detail::disjoint::reverse_covered_by> + > +{}; + + +}} // namespace detail_dispatch::overlay +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp index 0af062d271..438a377876 100644 --- a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp +++ b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -14,9 +14,9 @@ #include <algorithm> #include <vector> -#include <boost/assert.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> @@ -182,7 +182,7 @@ struct multipoint_point_point OutputIterator oit, Strategy const&) { - BOOST_ASSERT( OverlayType == overlay_difference ); + BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference ); for (typename boost::range_iterator<MultiPoint const>::type it = boost::begin(multipoint); @@ -264,7 +264,7 @@ struct multipoint_multipoint_point >::apply(multipoint2, multipoint1, robust_policy, oit, strategy); } - std::vector<typename point_type<MultiPoint2>::type> + std::vector<typename boost::range_value<MultiPoint2>::type> points2(boost::begin(multipoint2), boost::end(multipoint2)); std::sort(points2.begin(), points2.end(), detail::relate::less()); diff --git a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp index b469052c84..0f2da67b62 100644 --- a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp +++ b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp @@ -29,6 +29,8 @@ struct ring_properties typedef Point point_type; typedef typename default_area_result<Point>::type area_type; + bool valid; + // Filled by "select_rings" Point point; area_type area; @@ -43,7 +45,8 @@ struct ring_properties std::vector<ring_identifier> children; inline ring_properties() - : area(area_type()) + : valid(false) + , area(area_type()) , reversed(false) , discarded(false) , parent_area(-1) @@ -59,7 +62,7 @@ struct ring_properties // We should take a point somewhere in the middle of the ring, // to avoid taking a point on a (self)tangency, // in cases where multiple points come together - geometry::point_on_border(this->point, ring_or_box, true); + valid = geometry::point_on_border(this->point, ring_or_box, true); } inline area_type get_area() const diff --git a/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp index 516ec349e8..e77a163dd5 100644 --- a/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp +++ b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp @@ -19,7 +19,7 @@ #endif -#include <boost/geometry/algorithms/detail/signed_index_type.hpp> +#include <boost/geometry/algorithms/detail/signed_size_type.hpp> namespace boost { namespace geometry @@ -40,10 +40,10 @@ struct segment_identifier , segment_index(-1) {} - inline segment_identifier(signed_index_type src, - signed_index_type mul, - signed_index_type rin, - signed_index_type seg) + inline segment_identifier(signed_size_type src, + signed_size_type mul, + signed_size_type rin, + signed_size_type seg) : source_index(src) , multi_index(mul) , ring_index(rin) @@ -81,10 +81,10 @@ struct segment_identifier } #endif - signed_index_type source_index; - signed_index_type multi_index; - signed_index_type ring_index; - signed_index_type segment_index; + signed_size_type source_index; + signed_size_type multi_index; + signed_size_type ring_index; + signed_size_type segment_index; }; diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index b1f984ffe1..a74cb83f77 100644 --- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -12,6 +12,7 @@ #include <cstddef> +#include <boost/mpl/vector_c.hpp> #include <boost/range.hpp> #include <boost/geometry/core/access.hpp> diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp index 59d2ba703e..803a164711 100644 --- a/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -18,6 +18,7 @@ #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> #include <boost/geometry/algorithms/num_points.hpp> #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/geometries/concepts/check.hpp> @@ -116,8 +117,8 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2, return false; } - BOOST_ASSERT(info.enriched.travels_to_vertex_index >= 0); - BOOST_ASSERT(info.enriched.travels_to_ip_index >= 0); + BOOST_GEOMETRY_ASSERT(info.enriched.travels_to_vertex_index >= 0); + BOOST_GEOMETRY_ASSERT(info.enriched.travels_to_ip_index >= 0); if (info.seg_id.source_index == 0) { @@ -150,8 +151,8 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2, inline bool select_source(operation_type operation, - signed_index_type source1, - signed_index_type source2) + signed_size_type source1, + signed_size_type source2) { return (operation == operation_intersection && source1 != source2) || (operation == operation_union && source1 == source2) diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp index 25a34ba2ec..8b19add479 100644 --- a/boost/geometry/algorithms/detail/partition.hpp +++ b/boost/geometry/algorithms/detail/partition.hpp @@ -1,6 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2011-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -9,10 +14,13 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP +#include <cstddef> #include <vector> -#include <boost/range/algorithm/copy.hpp> -#include <boost/geometry/algorithms/assign.hpp> +#include <boost/range.hpp> +#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/algorithms/assign.hpp> + namespace boost { namespace geometry { @@ -20,8 +28,6 @@ namespace boost { namespace geometry namespace detail { namespace partition { -typedef std::vector<std::size_t> index_vector_type; - template <int Dimension, typename Box> inline void divide_box(Box const& box, Box& lower_box, Box& upper_box) { @@ -38,31 +44,26 @@ inline void divide_box(Box const& box, Box& lower_box, Box& upper_box) geometry::set<min_corner, Dimension>(upper_box, mid); } -// Divide collection into three subsets: lower, upper and oversized +// Divide forward_range into three subsets: lower, upper and oversized // (not-fitting) // (lower == left or bottom, upper == right or top) -template <typename OverlapsPolicy, typename InputCollection, typename Box> +template <typename OverlapsPolicy, typename Box, typename IteratorVector> inline void divide_into_subsets(Box const& lower_box, Box const& upper_box, - InputCollection const& collection, - index_vector_type const& input, - index_vector_type& lower, - index_vector_type& upper, - index_vector_type& exceeding) + IteratorVector const& input, + IteratorVector& lower, + IteratorVector& upper, + IteratorVector& exceeding) { - typedef boost::range_iterator + typedef typename boost::range_iterator < - index_vector_type const - >::type index_iterator_type; + IteratorVector const + >::type it_type; - for(index_iterator_type it = boost::begin(input); - it != boost::end(input); - ++it) + for(it_type it = boost::begin(input); it != boost::end(input); ++it) { - bool const lower_overlapping = OverlapsPolicy::apply(lower_box, - collection[*it]); - bool const upper_overlapping = OverlapsPolicy::apply(upper_box, - collection[*it]); + bool const lower_overlapping = OverlapsPolicy::apply(lower_box, **it); + bool const upper_overlapping = OverlapsPolicy::apply(upper_box, **it); if (lower_overlapping && upper_overlapping) { @@ -84,99 +85,109 @@ inline void divide_into_subsets(Box const& lower_box, } } -template <typename ExpandPolicy, typename Box, typename InputCollection> -inline void expand_with_elements(Box& total, - InputCollection const& collection, - index_vector_type const& input) +template +< + typename ExpandPolicy, + typename Box, + typename IteratorVector +> +inline void expand_with_elements(Box& total, IteratorVector const& input) { - typedef boost::range_iterator<index_vector_type const>::type it_type; + typedef typename boost::range_iterator<IteratorVector const>::type it_type; for(it_type it = boost::begin(input); it != boost::end(input); ++it) { - ExpandPolicy::apply(total, collection[*it]); + ExpandPolicy::apply(total, **it); } } -// Match collection with itself -template <typename InputCollection, typename Policy> -inline void handle_one(InputCollection const& collection, - index_vector_type const& input, - Policy& policy) +// Match forward_range with itself +template <typename Policy, typename IteratorVector> +inline void handle_one(IteratorVector const& input, Policy& policy) { if (boost::size(input) == 0) { return; } - typedef boost::range_iterator<index_vector_type const>::type - index_iterator_type; + typedef typename boost::range_iterator<IteratorVector const>::type it_type; // Quadratic behaviour at lowest level (lowest quad, or all exceeding) - for(index_iterator_type it1 = boost::begin(input); - it1 != boost::end(input); - ++it1) + for (it_type it1 = boost::begin(input); it1 != boost::end(input); ++it1) { - index_iterator_type it2 = it1; - for(++it2; it2 != boost::end(input); ++it2) + it_type it2 = it1; + for (++it2; it2 != boost::end(input); ++it2) { - policy.apply(collection[*it1], collection[*it2]); + policy.apply(**it1, **it2); } } } -// Match collection 1 with collection 2 +// Match forward range 1 with forward range 2 template < - typename InputCollection1, - typename InputCollection2, - typename Policy + typename Policy, + typename IteratorVector1, + typename IteratorVector2 > -inline void handle_two( - InputCollection1 const& collection1, index_vector_type const& input1, - InputCollection2 const& collection2, index_vector_type const& input2, +inline void handle_two(IteratorVector1 const& input1, + IteratorVector2 const& input2, Policy& policy) { + typedef typename boost::range_iterator + < + IteratorVector1 const + >::type iterator_type1; + + typedef typename boost::range_iterator + < + IteratorVector2 const + >::type iterator_type2; + if (boost::size(input1) == 0 || boost::size(input2) == 0) { return; } - typedef boost::range_iterator - < - index_vector_type const - >::type index_iterator_type; - - for(index_iterator_type it1 = boost::begin(input1); + for(iterator_type1 it1 = boost::begin(input1); it1 != boost::end(input1); ++it1) { - for(index_iterator_type it2 = boost::begin(input2); + for(iterator_type2 it2 = boost::begin(input2); it2 != boost::end(input2); ++it2) { - policy.apply(collection1[*it1], collection2[*it2]); + policy.apply(**it1, **it2); } } } -inline bool recurse_ok(index_vector_type const& input, +template <typename IteratorVector> +inline bool recurse_ok(IteratorVector const& input, std::size_t min_elements, std::size_t level) { return boost::size(input) >= min_elements && level < 100; } -inline bool recurse_ok(index_vector_type const& input1, - index_vector_type const& input2, +template <typename IteratorVector1, typename IteratorVector2> +inline bool recurse_ok(IteratorVector1 const& input1, + IteratorVector2 const& input2, std::size_t min_elements, std::size_t level) { return boost::size(input1) >= min_elements && recurse_ok(input2, min_elements, level); } -inline bool recurse_ok(index_vector_type const& input1, - index_vector_type const& input2, - index_vector_type const& input3, +template +< + typename IteratorVector1, + typename IteratorVector2, + typename IteratorVector3 +> +inline bool recurse_ok(IteratorVector1 const& input1, + IteratorVector2 const& input2, + IteratorVector3 const& input3, std::size_t min_elements, std::size_t level) { return boost::size(input1) >= min_elements @@ -193,7 +204,7 @@ template typename ExpandPolicy2, typename VisitBoxPolicy > -class partition_two_collections; +class partition_two_ranges; template @@ -204,79 +215,71 @@ template typename ExpandPolicy, typename VisitBoxPolicy > -class partition_one_collection +class partition_one_range { - typedef std::vector<std::size_t> index_vector_type; - - template <typename InputCollection> - static inline Box get_new_box(InputCollection const& collection, - index_vector_type const& input) + template <typename IteratorVector> + static inline Box get_new_box(IteratorVector const& input) { Box box; geometry::assign_inverse(box); - expand_with_elements<ExpandPolicy>(box, collection, input); + expand_with_elements<ExpandPolicy>(box, input); return box; } - template <typename InputCollection, typename Policy> + template <typename Policy, typename IteratorVector> static inline void next_level(Box const& box, - InputCollection const& collection, - index_vector_type const& input, + IteratorVector const& input, std::size_t level, std::size_t min_elements, Policy& policy, VisitBoxPolicy& box_policy) { if (recurse_ok(input, min_elements, level)) { - partition_one_collection + partition_one_range < 1 - Dimension, Box, OverlapsPolicy, ExpandPolicy, VisitBoxPolicy - >::apply(box, collection, input, - level + 1, min_elements, policy, box_policy); + >::apply(box, input, level + 1, min_elements, policy, box_policy); } else { - handle_one(collection, input, policy); + handle_one(input, policy); } } - // Function to switch to two collections if there are geometries exceeding - // the separation line - template <typename InputCollection, typename Policy> + // Function to switch to two forward ranges if there are + // geometries exceeding the separation line + template <typename Policy, typename IteratorVector> static inline void next_level2(Box const& box, - InputCollection const& collection, - index_vector_type const& input1, - index_vector_type const& input2, + IteratorVector const& input1, + IteratorVector const& input2, std::size_t level, std::size_t min_elements, Policy& policy, VisitBoxPolicy& box_policy) { - if (recurse_ok(input1, input2, min_elements, level)) { - partition_two_collections + partition_two_ranges < 1 - Dimension, Box, OverlapsPolicy, OverlapsPolicy, ExpandPolicy, ExpandPolicy, VisitBoxPolicy - >::apply(box, collection, input1, collection, input2, - level + 1, min_elements, policy, box_policy); + >::apply(box, input1, input2, level + 1, min_elements, + policy, box_policy); } else { - handle_two(collection, input1, collection, input2, policy); + handle_two(input1, input2, policy); } } public : - template <typename InputCollection, typename Policy> + template <typename Policy, typename IteratorVector> static inline void apply(Box const& box, - InputCollection const& collection, - index_vector_type const& input, + IteratorVector const& input, std::size_t level, std::size_t min_elements, Policy& policy, VisitBoxPolicy& box_policy) @@ -286,33 +289,31 @@ public : Box lower_box, upper_box; divide_box<Dimension>(box, lower_box, upper_box); - index_vector_type lower, upper, exceeding; - divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection, + IteratorVector lower, upper, exceeding; + divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, input, lower, upper, exceeding); if (boost::size(exceeding) > 0) { // Get the box of exceeding-only - Box exceeding_box = get_new_box(collection, exceeding); + Box exceeding_box = get_new_box(exceeding); // Recursively do exceeding elements only, in next dimension they // will probably be less exceeding within the new box - next_level(exceeding_box, collection, exceeding, level, - min_elements, policy, box_policy); - - // Switch to two collections, combine exceeding with lower resp upper - // but not lower/lower, upper/upper - next_level2(exceeding_box, collection, exceeding, lower, level, - min_elements, policy, box_policy); - next_level2(exceeding_box, collection, exceeding, upper, level, - min_elements, policy, box_policy); + next_level(exceeding_box, exceeding, level, min_elements, + policy, box_policy); + + // Switch to two forward ranges, combine exceeding with + // lower resp upper, but not lower/lower, upper/upper + next_level2(exceeding_box, exceeding, lower, level, min_elements, + policy, box_policy); + next_level2(exceeding_box, exceeding, upper, level, min_elements, + policy, box_policy); } // Recursively call operation both parts - next_level(lower_box, collection, lower, level, min_elements, - policy, box_policy); - next_level(upper_box, collection, upper, level, min_elements, - policy, box_policy); + next_level(lower_box, lower, level, min_elements, policy, box_policy); + next_level(upper_box, upper, level, min_elements, policy, box_policy); } }; @@ -326,25 +327,21 @@ template typename ExpandPolicy2, typename VisitBoxPolicy > -class partition_two_collections +class partition_two_ranges { - typedef std::vector<std::size_t> index_vector_type; - template < - typename InputCollection1, - typename InputCollection2, - typename Policy + typename Policy, + typename IteratorVector1, + typename IteratorVector2 > static inline void next_level(Box const& box, - InputCollection1 const& collection1, - index_vector_type const& input1, - InputCollection2 const& collection2, - index_vector_type const& input2, + IteratorVector1 const& input1, + IteratorVector2 const& input2, std::size_t level, std::size_t min_elements, Policy& policy, VisitBoxPolicy& box_policy) { - partition_two_collections + partition_two_ranges < 1 - Dimension, Box, @@ -353,50 +350,38 @@ class partition_two_collections ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy - >::apply(box, collection1, input1, collection2, input2, - level + 1, min_elements, - policy, box_policy); + >::apply(box, input1, input2, level + 1, min_elements, + policy, box_policy); } - template - < - typename ExpandPolicy, - typename InputCollection - > - static inline Box get_new_box(InputCollection const& collection, - index_vector_type const& input) + template <typename ExpandPolicy, typename IteratorVector> + static inline Box get_new_box(IteratorVector const& input) { Box box; geometry::assign_inverse(box); - expand_with_elements<ExpandPolicy>(box, collection, input); + expand_with_elements<ExpandPolicy>(box, input); return box; } - template - < - typename InputCollection1, - typename InputCollection2 - > - static inline Box get_new_box(InputCollection1 const& collection1, - index_vector_type const& input1, - InputCollection2 const& collection2, - index_vector_type const& input2) + template <typename IteratorVector1, typename IteratorVector2> + static inline Box get_new_box(IteratorVector1 const& input1, + IteratorVector2 const& input2) { - Box box = get_new_box<ExpandPolicy1>(collection1, input1); - expand_with_elements<ExpandPolicy2>(box, collection2, input2); + Box box = get_new_box<ExpandPolicy1>(input1); + expand_with_elements<ExpandPolicy2>(box, input2); return box; } public : template < - typename InputCollection1, - typename InputCollection2, - typename Policy + typename Policy, + typename IteratorVector1, + typename IteratorVector2 > static inline void apply(Box const& box, - InputCollection1 const& collection1, index_vector_type const& input1, - InputCollection2 const& collection2, index_vector_type const& input2, + IteratorVector1 const& input1, + IteratorVector2 const& input2, std::size_t level, std::size_t min_elements, Policy& policy, VisitBoxPolicy& box_policy) @@ -406,11 +391,11 @@ public : Box lower_box, upper_box; divide_box<Dimension>(box, lower_box, upper_box); - index_vector_type lower1, upper1, exceeding1; - index_vector_type lower2, upper2, exceeding2; - divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box, collection1, + IteratorVector1 lower1, upper1, exceeding1; + IteratorVector2 lower2, upper2, exceeding2; + divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box, input1, lower1, upper1, exceeding1); - divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box, collection2, + divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box, input2, lower2, upper2, exceeding2); if (boost::size(exceeding1) > 0) @@ -419,35 +404,31 @@ public : if (recurse_ok(exceeding1, exceeding2, min_elements, level)) { - Box exceeding_box = get_new_box(collection1, exceeding1, - collection2, exceeding2); - next_level(exceeding_box, collection1, exceeding1, - collection2, exceeding2, level, - min_elements, policy, box_policy); + Box exceeding_box = get_new_box(exceeding1, exceeding2); + next_level(exceeding_box, exceeding1, exceeding2, level, + min_elements, policy, box_policy); } else { - handle_two(collection1, exceeding1, collection2, exceeding2, - policy); + handle_two(exceeding1, exceeding2, policy); } // All exceeding from 1 with lower and upper of 2: - // (Check sizes of all three collections to avoid recurse into + // (Check sizes of all three forward ranges to avoid recurse into // the same combinations again and again) if (recurse_ok(lower2, upper2, exceeding1, min_elements, level)) { - Box exceeding_box - = get_new_box<ExpandPolicy1>(collection1, exceeding1); - next_level(exceeding_box, collection1, exceeding1, - collection2, lower2, level, min_elements, policy, box_policy); - next_level(exceeding_box, collection1, exceeding1, - collection2, upper2, level, min_elements, policy, box_policy); + Box exceeding_box = get_new_box<ExpandPolicy1>(exceeding1); + next_level(exceeding_box, exceeding1, lower2, level, + min_elements, policy, box_policy); + next_level(exceeding_box, exceeding1, upper2, level, + min_elements, policy, box_policy); } else { - handle_two(collection1, exceeding1, collection2, lower2, policy); - handle_two(collection1, exceeding1, collection2, upper2, policy); + handle_two(exceeding1, lower2, policy); + handle_two(exceeding1, upper2, policy); } } @@ -456,37 +437,36 @@ public : // All exceeding from 2 with lower and upper of 1: if (recurse_ok(lower1, upper1, exceeding2, min_elements, level)) { - Box exceeding_box - = get_new_box<ExpandPolicy2>(collection2, exceeding2); - next_level(exceeding_box, collection1, lower1, - collection2, exceeding2, level, min_elements, policy, box_policy); - next_level(exceeding_box, collection1, upper1, - collection2, exceeding2, level, min_elements, policy, box_policy); + Box exceeding_box = get_new_box<ExpandPolicy2>(exceeding2); + next_level(exceeding_box, lower1, exceeding2, level, + min_elements, policy, box_policy); + next_level(exceeding_box, upper1, exceeding2, level, + min_elements, policy, box_policy); } else { - handle_two(collection1, lower1, collection2, exceeding2, policy); - handle_two(collection1, upper1, collection2, exceeding2, policy); + handle_two(lower1, exceeding2, policy); + handle_two(upper1, exceeding2, policy); } } if (recurse_ok(lower1, lower2, min_elements, level)) { - next_level(lower_box, collection1, lower1, collection2, lower2, level, - min_elements, policy, box_policy); + next_level(lower_box, lower1, lower2, level, + min_elements, policy, box_policy); } else { - handle_two(collection1, lower1, collection2, lower2, policy); + handle_two(lower1, lower2, policy); } if (recurse_ok(upper1, upper2, min_elements, level)) { - next_level(upper_box, collection1, upper1, collection2, upper2, level, - min_elements, policy, box_policy); + next_level(upper_box, upper1, upper2, level, + min_elements, policy, box_policy); } else { - handle_two(collection1, upper1, collection2, upper2, policy); + handle_two(upper1, upper2, policy); } } }; @@ -523,63 +503,67 @@ template > class partition { - typedef std::vector<std::size_t> index_vector_type; - - template <typename ExpandPolicy, typename IncludePolicy, typename InputCollection> - static inline void expand_to_collection(InputCollection const& collection, - Box& total, index_vector_type& index_vector) + template + < + typename ExpandPolicy, + typename IncludePolicy, + typename ForwardRange, + typename IteratorVector + > + static inline void expand_to_range(ForwardRange const& forward_range, + Box& total, IteratorVector& iterator_vector) { - std::size_t index = 0; - for(typename boost::range_iterator<InputCollection const>::type it - = boost::begin(collection); - it != boost::end(collection); - ++it, ++index) + for(typename boost::range_iterator<ForwardRange const>::type it + = boost::begin(forward_range); + it != boost::end(forward_range); + ++it) { if (IncludePolicy::apply(*it)) { ExpandPolicy::apply(total, *it); - index_vector.push_back(index); + iterator_vector.push_back(it); } } } public : - template <typename InputCollection, typename VisitPolicy> - static inline void apply(InputCollection const& collection, + template <typename ForwardRange, typename VisitPolicy> + static inline void apply(ForwardRange const& forward_range, VisitPolicy& visitor, std::size_t min_elements = 16, VisitBoxPolicy box_visitor = detail::partition::visit_no_policy() ) { - if (std::size_t(boost::size(collection)) > min_elements) + typedef typename boost::range_iterator + < + ForwardRange const + >::type iterator_type; + + if (std::size_t(boost::size(forward_range)) > min_elements) { - index_vector_type index_vector; + std::vector<iterator_type> iterator_vector; Box total; assign_inverse(total); - expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection, - total, index_vector); + expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range, + total, iterator_vector); - detail::partition::partition_one_collection + detail::partition::partition_one_range < 0, Box, OverlapsPolicy1, ExpandPolicy1, VisitBoxPolicy - >::apply(total, collection, index_vector, 0, min_elements, - visitor, box_visitor); + >::apply(total, iterator_vector, 0, min_elements, + visitor, box_visitor); } else { - typedef typename boost::range_iterator - < - InputCollection const - >::type iterator_type; - for(iterator_type it1 = boost::begin(collection); - it1 != boost::end(collection); + for(iterator_type it1 = boost::begin(forward_range); + it1 != boost::end(forward_range); ++it1) { iterator_type it2 = it1; - for(++it2; it2 != boost::end(collection); ++it2) + for(++it2; it2 != boost::end(forward_range); ++it2) { visitor.apply(*it1, *it2); } @@ -589,53 +573,55 @@ public : template < - typename InputCollection1, - typename InputCollection2, + typename ForwardRange1, + typename ForwardRange2, typename VisitPolicy > - static inline void apply(InputCollection1 const& collection1, - InputCollection2 const& collection2, + static inline void apply(ForwardRange1 const& forward_range1, + ForwardRange2 const& forward_range2, VisitPolicy& visitor, std::size_t min_elements = 16, - VisitBoxPolicy box_visitor = detail::partition::visit_no_policy() + VisitBoxPolicy box_visitor + = detail::partition::visit_no_policy() ) { - if (std::size_t(boost::size(collection1)) > min_elements - && std::size_t(boost::size(collection2)) > min_elements) + typedef typename boost::range_iterator + < + ForwardRange1 const + >::type iterator_type1; + + typedef typename boost::range_iterator + < + ForwardRange2 const + >::type iterator_type2; + + if (std::size_t(boost::size(forward_range1)) > min_elements + && std::size_t(boost::size(forward_range2)) > min_elements) { - index_vector_type index_vector1, index_vector2; + std::vector<iterator_type1> iterator_vector1; + std::vector<iterator_type2> iterator_vector2; Box total; assign_inverse(total); - expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection1, - total, index_vector1); - expand_to_collection<ExpandPolicy2, IncludePolicy2>(collection2, - total, index_vector2); + expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range1, + total, iterator_vector1); + expand_to_range<ExpandPolicy2, IncludePolicy2>(forward_range2, + total, iterator_vector2); - detail::partition::partition_two_collections + detail::partition::partition_two_ranges < 0, Box, OverlapsPolicy1, OverlapsPolicy2, ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy - >::apply(total, - collection1, index_vector1, - collection2, index_vector2, - 0, min_elements, visitor, box_visitor); + >::apply(total, iterator_vector1, iterator_vector2, + 0, min_elements, visitor, box_visitor); } else { - typedef typename boost::range_iterator - < - InputCollection1 const - >::type iterator_type1; - typedef typename boost::range_iterator - < - InputCollection2 const - >::type iterator_type2; - for(iterator_type1 it1 = boost::begin(collection1); - it1 != boost::end(collection1); + for(iterator_type1 it1 = boost::begin(forward_range1); + it1 != boost::end(forward_range1); ++it1) { - for(iterator_type2 it2 = boost::begin(collection2); - it2 != boost::end(collection2); + for(iterator_type2 it2 = boost::begin(forward_range2); + it2 != boost::end(forward_range2); ++it2) { visitor.apply(*it1, *it2); diff --git a/boost/geometry/algorithms/detail/recalculate.hpp b/boost/geometry/algorithms/detail/recalculate.hpp index 2c3ea7413b..056f7c6e1d 100644 --- a/boost/geometry/algorithms/detail/recalculate.hpp +++ b/boost/geometry/algorithms/detail/recalculate.hpp @@ -21,6 +21,7 @@ #include <boost/mpl/if.hpp> #include <boost/numeric/conversion/bounds.hpp> #include <boost/numeric/conversion/cast.hpp> +#include <boost/range.hpp> #include <boost/type_traits.hpp> #include <boost/geometry/arithmetic/arithmetic.hpp> diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp index 2859841de4..cc9c1b67ca 100644 --- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp @@ -88,7 +88,7 @@ public: // TODO: This is O(N) // Run in a loop O(NM) - optimize! int const pig = detail::within::point_in_geometry(pt, m_other_areal); - //BOOST_ASSERT( pig != 0 ); + //BOOST_GEOMETRY_ASSERT( pig != 0 ); // inside if ( pig > 0 ) @@ -104,9 +104,9 @@ public: // Check if any interior ring is outside ring_identifier ring_id(0, -1, 0); - int const irings_count = boost::numeric_cast<int>( - geometry::num_interior_rings(areal) ); - for ( ; ring_id.ring_index < irings_count ; ++ring_id.ring_index ) + std::size_t const irings_count = geometry::num_interior_rings(areal); + for ( ; static_cast<std::size_t>(ring_id.ring_index) < irings_count ; + ++ring_id.ring_index ) { typename detail::sub_range_return_type<Areal const>::type range_ref = detail::sub_range(areal, ring_id); @@ -140,9 +140,9 @@ public: // Check if any interior ring is inside ring_identifier ring_id(0, -1, 0); - int const irings_count = boost::numeric_cast<int>( - geometry::num_interior_rings(areal) ); - for ( ; ring_id.ring_index < irings_count ; ++ring_id.ring_index ) + std::size_t const irings_count = geometry::num_interior_rings(areal); + for ( ; static_cast<std::size_t>(ring_id.ring_index) < irings_count ; + ++ring_id.ring_index ) { typename detail::sub_range_return_type<Areal const>::type range_ref = detail::sub_range(areal, ring_id); @@ -405,7 +405,7 @@ struct areal_areal typename TurnIt> void apply(Result & result, TurnIt it) { - //BOOST_ASSERT( it != last ); + //BOOST_GEOMETRY_ASSERT( it != last ); overlay::operation_type const op = it->operations[op_id].operation; @@ -498,7 +498,7 @@ struct areal_areal template <typename Result> void apply(Result & result) { - //BOOST_ASSERT( first != last ); + //BOOST_GEOMETRY_ASSERT( first != last ); if ( m_exit_detected /*m_previous_operation == overlay::operation_union*/ ) { @@ -618,7 +618,7 @@ struct areal_areal // O(N) - running it in a loop gives O(NM) int const pig = detail::within::point_in_geometry(range::front(range_ref), other_geometry); - //BOOST_ASSERT(pig != 0); + //BOOST_GEOMETRY_ASSERT(pig != 0); if ( pig > 0 ) { update<interior, interior, '2', transpose_result>(m_result); @@ -793,8 +793,8 @@ struct areal_areal { segment_identifier const& seg_id = turn.operations[OpId].seg_id; - signed_index_type - count = boost::numeric_cast<signed_index_type>( + signed_size_type + count = boost::numeric_cast<signed_size_type>( geometry::num_interior_rings( detail::single_geometry(analyser.geometry, seg_id))); @@ -804,8 +804,8 @@ struct areal_areal template <typename Analyser, typename Turn> static inline void for_no_turns_rings(Analyser & analyser, Turn const& turn, - signed_index_type first, - signed_index_type last) + signed_size_type first, + signed_size_type last) { segment_identifier seg_id = turn.operations[OpId].seg_id; diff --git a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index f98c3e9b82..9de1bacb7d 100644 --- a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -47,7 +47,7 @@ public: boost::ignore_unused_variable_warning(pt); #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER // may give false positives for INT - BOOST_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) + BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) && detail::equals::equals_point_point(pt, range::front(geometry)) || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any) && detail::equals::equals_point_point(pt, range::back(geometry)) ); diff --git a/boost/geometry/algorithms/detail/relate/de9im.hpp b/boost/geometry/algorithms/detail/relate/de9im.hpp new file mode 100644 index 0000000000..713a3fc8f0 --- /dev/null +++ b/boost/geometry/algorithms/detail/relate/de9im.hpp @@ -0,0 +1,439 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP + +#include <boost/mpl/is_sequence.hpp> +#include <boost/mpl/push_back.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/vector_c.hpp> +#include <boost/static_assert.hpp> +#include <boost/tuple/tuple.hpp> + +#include <boost/geometry/algorithms/detail/relate/result.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/core/topological_dimension.hpp> +#include <boost/geometry/core/tag.hpp> + +// TEMP - move this header to geometry/detail +#include <boost/geometry/index/detail/tuples.hpp> + +namespace boost { namespace geometry +{ + +namespace de9im +{ + +/*! +\brief DE-9IM model intersection matrix. +\ingroup de9im +\details This matrix can be used to express spatial relations as defined in + Dimensionally Extended 9-Intersection Model. + +\qbk{[heading See also]} +\qbk{* [link geometry.reference.algorithms.relation relation]} + */ +class matrix + : public detail::relate::matrix<3, 3> +{ +#ifdef DOXYGEN_INVOKED +public: + /*! + \brief Initializes all of the matrix elements to F + */ + matrix(); + /*! + \brief Subscript operator + \param index The index of the element + \return The element + */ + char operator[](std::size_t index) const; + /*! + \brief Returns the iterator to the first element + \return const RandomAccessIterator + */ + const_iterator begin() const; + /*! + \brief Returns the iterator past the last element + \return const RandomAccessIterator + */ + const_iterator end() const; + /*! + \brief Returns the number of elements + \return 9 + */ + static std::size_t size(); + /*! + \brief Returns raw pointer to elements + \return const pointer to array of elements + */ + inline const char * data() const; + /*! + \brief Returns std::string containing elements + \return string containing elements + */ + inline std::string str() const; +#endif +}; + +/*! +\brief DE-9IM model intersection mask. +\ingroup de9im +\details This mask can be used to check spatial relations as defined in + Dimensionally Extended 9-Intersection Model. + +\qbk{[heading See also]} +\qbk{* [link geometry.reference.algorithms.relate relate]} + */ +class mask + : public detail::relate::mask<3, 3> +{ + typedef detail::relate::mask<3, 3> base_type; + +public: + /*! + \brief The constructor. + \param code The mask pattern. + */ + inline explicit mask(const char* code) + : base_type(code) + {} + + /*! + \brief The constructor. + \param code The mask pattern. + */ + inline explicit mask(std::string const& code) + : base_type(code.c_str(), code.size()) + {} +}; + +// static_mask + +/*! +\brief DE-9IM model intersection mask (static version). +\ingroup de9im +\details This mask can be used to check spatial relations as defined in + Dimensionally Extended 9-Intersection Model. +\tparam II Interior/Interior intersection mask element +\tparam IB Interior/Boundary intersection mask element +\tparam IE Interior/Exterior intersection mask element +\tparam BI Boundary/Interior intersection mask element +\tparam BB Boundary/Boundary intersection mask element +\tparam BE Boundary/Exterior intersection mask element +\tparam EI Exterior/Interior intersection mask element +\tparam EB Exterior/Boundary intersection mask element +\tparam EE Exterior/Exterior intersection mask element + +\qbk{[heading See also]} +\qbk{* [link geometry.reference.algorithms.relate relate]} + */ +template +< + char II = '*', char IB = '*', char IE = '*', + char BI = '*', char BB = '*', char BE = '*', + char EI = '*', char EB = '*', char EE = '*' +> +class static_mask + : public detail::relate::static_mask + < + boost::mpl::vector_c + < + char, II, IB, IE, BI, BB, BE, EI, EB, EE + >, + 3, 3 + > +{}; + +} // namespace de9im + +namespace detail { namespace de9im +{ + +// a small helper util for ORing static masks + +template +< + typename Seq, + typename T, + bool IsSeq = boost::mpl::is_sequence<Seq>::value +> +struct push_back +{ + typedef typename boost::mpl::push_back + < + Seq, + T + >::type type; +}; + +template <typename Seq, typename T> +struct push_back<Seq, T, false> +{}; + +}} // namespace detail::de9im + +namespace de9im +{ + +inline +boost::tuples::cons + < + mask, + boost::tuples::cons<mask, boost::tuples::null_type> + > +operator||(mask const& m1, mask const& m2) +{ + namespace bt = boost::tuples; + + return bt::cons<mask, bt::cons<mask, bt::null_type> > + ( m1, bt::cons<mask, bt::null_type>(m2, bt::null_type()) ); +} + +template <typename Tail> +inline +typename index::detail::tuples::push_back + < + boost::tuples::cons<mask, Tail>, + mask + >::type +operator||(boost::tuples::cons<mask, Tail> const& t, mask const& m) +{ + namespace bt = boost::tuples; + + return index::detail::tuples::push_back + < + bt::cons<mask, Tail>, + mask + >::apply(t, m); +} + +template +< + char II1, char IB1, char IE1, + char BI1, char BB1, char BE1, + char EI1, char EB1, char EE1, + char II2, char IB2, char IE2, + char BI2, char BB2, char BE2, + char EI2, char EB2, char EE2 +> +inline +boost::mpl::vector< + static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>, + static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2> +> +operator||(static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1> const& , + static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2> const& ) +{ + return boost::mpl::vector + < + static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>, + static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2> + >(); +} + +template +< + typename Seq, + char II, char IB, char IE, + char BI, char BB, char BE, + char EI, char EB, char EE +> +inline +typename detail::de9im::push_back + < + Seq, + static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> + >::type +operator||(Seq const& , + static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> const& ) +{ + return typename detail::de9im::push_back + < + Seq, + static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> + >::type(); +} + +} // namespace de9im + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace de9im +{ + +// PREDEFINED MASKS + +// TODO: +// 1. specialize for simplified masks if available +// e.g. for TOUCHES use 1 mask for A/A +// 2. Think about dimensions > 2 e.g. should TOUCHES be true +// if the interior of the Areal overlaps the boundary of the Volumetric +// like it's true for Linear/Areal + +// EQUALS +template <typename Geometry1, typename Geometry2> +struct static_mask_equals_type +{ + typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia + //typedef geometry::de9im::static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC +}; + +// DISJOINT +template <typename Geometry1, typename Geometry2> +struct static_mask_disjoint_type +{ + typedef geometry::de9im::static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> type; +}; + +// TOUCHES - NOT P/P +template +< + typename Geometry1, + typename Geometry2, + std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value, + std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value +> +struct static_mask_touches_impl +{ + typedef boost::mpl::vector + < + geometry::de9im::static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>, + geometry::de9im::static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>, + geometry::de9im::static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'> + > type; +}; +// According to OGC, doesn't apply to P/P +// Using the above mask the result would be always false +template <typename Geometry1, typename Geometry2> +struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0> + : not_implemented<typename geometry::tag<Geometry1>::type, + typename geometry::tag<Geometry2>::type> +{}; + +template <typename Geometry1, typename Geometry2> +struct static_mask_touches_type + : static_mask_touches_impl<Geometry1, Geometry2> +{}; + +// WITHIN +template <typename Geometry1, typename Geometry2> +struct static_mask_within_type +{ + typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> type; +}; + +// COVERED_BY (non OGC) +template <typename Geometry1, typename Geometry2> +struct static_mask_covered_by_type +{ + typedef boost::mpl::vector + < + geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>, + geometry::de9im::static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>, + geometry::de9im::static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>, + geometry::de9im::static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'> + > type; +}; + +// CROSSES +// dim(G1) < dim(G2) - P/L P/A L/A +template +< + typename Geometry1, + typename Geometry2, + std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value, + std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value, + bool D1LessD2 = (Dim1 < Dim2) +> +struct static_mask_crosses_impl +{ + typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type; +}; +// TODO: I'm not sure if this one below should be available! +// dim(G1) > dim(G2) - L/P A/P A/L +template +< + typename Geometry1, typename Geometry2, std::size_t Dim1, std::size_t Dim2 +> +struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false> +{ + typedef geometry::de9im::static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type; +}; +// dim(G1) == dim(G2) - P/P A/A +template +< + typename Geometry1, typename Geometry2, std::size_t Dim +> +struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false> + : not_implemented + < + typename geometry::tag<Geometry1>::type, + typename geometry::tag<Geometry2>::type + > +{}; +// dim(G1) == 1 && dim(G2) == 1 - L/L +template <typename Geometry1, typename Geometry2> +struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false> +{ + typedef geometry::de9im::static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type; +}; + +template <typename Geometry1, typename Geometry2> +struct static_mask_crosses_type + : static_mask_crosses_impl<Geometry1, Geometry2> +{}; + +// OVERLAPS + +// dim(G1) != dim(G2) - NOT P/P, L/L, A/A +template +< + typename Geometry1, + typename Geometry2, + std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value, + std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value +> +struct static_mask_overlaps_impl + : not_implemented + < + typename geometry::tag<Geometry1>::type, + typename geometry::tag<Geometry2>::type + > +{}; +// dim(G1) == D && dim(G2) == D - P/P A/A +template <typename Geometry1, typename Geometry2, std::size_t Dim> +struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim> +{ + typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; +}; +// dim(G1) == 1 && dim(G2) == 1 - L/L +template <typename Geometry1, typename Geometry2> +struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1> +{ + typedef geometry::de9im::static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; +}; + +template <typename Geometry1, typename Geometry2> +struct static_mask_overlaps_type + : static_mask_overlaps_impl<Geometry1, Geometry2> +{}; + +}} // namespace detail::de9im +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP diff --git a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp index 2c44b009e7..20122471e5 100644 --- a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp +++ b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp @@ -14,6 +14,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP +#include <boost/geometry/core/assert.hpp> + #include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/range.hpp> //#include <boost/geometry/algorithms/detail/sub_range.hpp> @@ -89,7 +91,7 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true> Geometry const& geometry, Pred & pred) { - BOOST_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(first != last); const std::size_t count = boost::size(geometry); boost::ignore_unused_variable_warning(count); @@ -99,10 +101,10 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true> std::vector<bool> detected_intersections(count, false); for ( TurnIt it = first ; it != last ; ++it ) { - signed_index_type multi_index = it->operations[OpId].seg_id.multi_index; - BOOST_ASSERT(multi_index >= 0); + signed_size_type multi_index = it->operations[OpId].seg_id.multi_index; + BOOST_GEOMETRY_ASSERT(multi_index >= 0); std::size_t const index = static_cast<std::size_t>(multi_index); - BOOST_ASSERT(index < count); + BOOST_GEOMETRY_ASSERT(index < count); detected_intersections[index] = true; } @@ -141,12 +143,12 @@ public: {} segment_identifier const& seg_id() const { - BOOST_ASSERT(sid_ptr); + BOOST_GEOMETRY_ASSERT(sid_ptr); return *sid_ptr; } Point const& point() const { - BOOST_ASSERT(pt_ptr); + BOOST_GEOMETRY_ASSERT(pt_ptr); return *pt_ptr; } @@ -300,15 +302,15 @@ public: point_type const& get_exit_point() const { - BOOST_ASSERT(m_exit_operation != overlay::operation_none); - BOOST_ASSERT(m_exit_turn_ptr); + BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none); + BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr); return m_exit_turn_ptr->point; } TurnInfo const& get_exit_turn() const { - BOOST_ASSERT(m_exit_operation != overlay::operation_none); - BOOST_ASSERT(m_exit_turn_ptr); + BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none); + BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr); return *m_exit_turn_ptr; } diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp new file mode 100644 index 0000000000..a6f1545ed1 --- /dev/null +++ b/boost/geometry/algorithms/detail/relate/implementation.hpp @@ -0,0 +1,110 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP + + +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/relate/interface.hpp> + +#include <boost/geometry/algorithms/detail/relate/point_point.hpp> +#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp> +#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp> +#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp> +#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp> + + +namespace boost { namespace geometry { + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch { + +template <typename Point1, typename Point2> +struct relate<Point1, Point2, point_tag, point_tag, 0, 0, false> + : detail::relate::point_point<Point1, Point2> +{}; + +template <typename Point, typename MultiPoint> +struct relate<Point, MultiPoint, point_tag, multi_point_tag, 0, 0, false> + : detail::relate::point_multipoint<Point, MultiPoint> +{}; + +template <typename MultiPoint, typename Point> +struct relate<MultiPoint, Point, multi_point_tag, point_tag, 0, 0, false> + : detail::relate::multipoint_point<MultiPoint, Point> +{}; + +template <typename MultiPoint1, typename MultiPoint2> +struct relate<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, 0, 0, false> + : detail::relate::multipoint_multipoint<MultiPoint1, MultiPoint2> +{}; + +// TODO - for now commented out because before implementing it we must consider: +// 1. how the Box degenerated to a Point should be treated +// 2. what should be the definition of a Box degenerated to a Point +// 3. what fields should the matrix/mask contain for dimension > 2 and dimension > 9 +// +//template <typename Point, typename Box, int TopDim2> +//struct relate<Point, Box, point_tag, box_tag, 0, TopDim2, false> +// : detail::relate::point_box<Point, Box> +//{}; +// +//template <typename Box, typename Point, int TopDim1> +//struct relate<Box, Point, box_tag, point_tag, TopDim1, 0, false> +// : detail::relate::box_point<Box, Point> +//{}; + + +template <typename Point, typename Geometry, typename Tag2, int TopDim2> +struct relate<Point, Geometry, point_tag, Tag2, 0, TopDim2, true> + : detail::relate::point_geometry<Point, Geometry> +{}; + +template <typename Geometry, typename Point, typename Tag1, int TopDim1> +struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true> + : detail::relate::geometry_point<Geometry, Point> +{}; + + +template <typename Linear1, typename Linear2, typename Tag1, typename Tag2> +struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true> + : detail::relate::linear_linear<Linear1, Linear2> +{}; + + +template <typename Linear, typename Areal, typename Tag1, typename Tag2> +struct relate<Linear, Areal, Tag1, Tag2, 1, 2, true> + : detail::relate::linear_areal<Linear, Areal> +{}; + +template <typename Areal, typename Linear, typename Tag1, typename Tag2> +struct relate<Areal, Linear, Tag1, Tag2, 2, 1, true> + : detail::relate::areal_linear<Areal, Linear> +{}; + + +template <typename Areal1, typename Areal2, typename Tag1, typename Tag2> +struct relate<Areal1, Areal2, Tag1, Tag2, 2, 2, true> + : detail::relate::areal_areal<Areal1, Areal2> +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP diff --git a/boost/geometry/algorithms/detail/relate/interface.hpp b/boost/geometry/algorithms/detail/relate/interface.hpp new file mode 100644 index 0000000000..e2c067b68d --- /dev/null +++ b/boost/geometry/algorithms/detail/relate/interface.hpp @@ -0,0 +1,348 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP + + +#include <boost/type_traits/is_same.hpp> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> + +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> +#include <boost/geometry/core/topological_dimension.hpp> + +#include <boost/geometry/algorithms/detail/relate/de9im.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/geometries/concepts/check.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> + + +namespace boost { namespace geometry { + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +// Those are used only to allow dispatch::relate to produce compile-time error + +template <typename Geometry, + typename Tag = typename geometry::tag<Geometry>::type> +struct is_supported_by_generic +{ + static const bool value + = boost::is_same<Tag, linestring_tag>::value + || boost::is_same<Tag, multi_linestring_tag>::value + || boost::is_same<Tag, ring_tag>::value + || boost::is_same<Tag, polygon_tag>::value + || boost::is_same<Tag, multi_polygon_tag>::value; +}; + +template <typename Geometry1, + typename Geometry2, + typename Tag1 = typename geometry::tag<Geometry1>::type, + typename Tag2 = typename geometry::tag<Geometry2>::type> +struct is_generic +{ + static const bool value = is_supported_by_generic<Geometry1>::value + && is_supported_by_generic<Geometry2>::value; +}; + + +template <typename Point, typename Geometry, typename Tag> +struct is_generic<Point, Geometry, point_tag, Tag> +{ + static const bool value = is_supported_by_generic<Geometry>::value; +}; + +template <typename Geometry, typename Point, typename Tag> +struct is_generic<Geometry, Point, Tag, point_tag> +{ + static const bool value = is_supported_by_generic<Geometry>::value; +}; + +template <typename Point1, typename Point2> +struct is_generic<Point1, Point2, point_tag, point_tag> +{ + static const bool value = false; +}; + + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch { + + +template <typename Geometry1, + typename Geometry2, + typename Tag1 = typename geometry::tag<Geometry1>::type, + typename Tag2 = typename geometry::tag<Geometry2>::type, + int TopDim1 = geometry::topological_dimension<Geometry1>::value, + int TopDim2 = geometry::topological_dimension<Geometry2>::value, + bool IsGeneric = detail::relate::is_generic<Geometry1, Geometry2>::value +> +struct relate : not_implemented<Tag1, Tag2> +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +template <typename Geometry1, typename Geometry2> +struct interruption_enabled +{ + static const bool value = + dispatch::relate<Geometry1, Geometry2>::interruption_enabled; +}; + +template <typename Geometry1, + typename Geometry2, + typename Result, + bool IsSequence = boost::mpl::is_sequence<Result>::value> +struct result_handler_type + : not_implemented<Result> +{}; + +template <typename Geometry1, typename Geometry2> +struct result_handler_type<Geometry1, Geometry2, geometry::de9im::mask, false> +{ + typedef mask_handler + < + geometry::de9im::mask, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +template <typename Geometry1, typename Geometry2, typename Head, typename Tail> +struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail>, false> +{ + typedef mask_handler + < + boost::tuples::cons<Head, Tail>, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +template <typename Geometry1, typename Geometry2, + char II, char IB, char IE, + char BI, char BB, char BE, + char EI, char EB, char EE> +struct result_handler_type + < + Geometry1, + Geometry2, + geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>, + false + > +{ + typedef static_mask_handler + < + geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +template <typename Geometry1, typename Geometry2, typename StaticSequence> +struct result_handler_type<Geometry1, Geometry2, StaticSequence, true> +{ + typedef static_mask_handler + < + StaticSequence, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +namespace resolve_variant { + +template <typename Geometry1, typename Geometry2> +struct relate +{ + template <typename Mask> + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Mask const& mask) + { + concept::check<Geometry1 const>(); + concept::check<Geometry2 const>(); + assert_dimension_equal<Geometry1, Geometry2>(); + + typename detail::relate::result_handler_type + < + Geometry1, + Geometry2, + Mask + >::type handler(mask); + + dispatch::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, handler); + + return handler.result(); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> +struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> +{ + template <typename Mask> + struct visitor : boost::static_visitor<bool> + { + Geometry2 const& m_geometry2; + Mask const& m_mask; + + visitor(Geometry2 const& geometry2, Mask const& mask) + : m_geometry2(geometry2), m_mask(mask) {} + + template <typename Geometry1> + bool operator()(Geometry1 const& geometry1) const + { + return relate<Geometry1, Geometry2> + ::apply(geometry1, m_geometry2, m_mask); + } + }; + + template <typename Mask> + static inline bool + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2, + Mask const& mask) + { + return boost::apply_visitor(visitor<Mask>(geometry2, mask), geometry1); + } +}; + +template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Mask> + struct visitor : boost::static_visitor<bool> + { + Geometry1 const& m_geometry1; + Mask const& m_mask; + + visitor(Geometry1 const& geometry1, Mask const& mask) + : m_geometry1(geometry1), m_mask(mask) {} + + template <typename Geometry2> + bool operator()(Geometry2 const& geometry2) const + { + return relate<Geometry1, Geometry2> + ::apply(m_geometry1, geometry2, m_mask); + } + }; + + template <typename Mask> + static inline bool + apply(Geometry1 const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2, + Mask const& mask) + { + return boost::apply_visitor(visitor<Mask>(geometry1, mask), geometry2); + } +}; + +template < + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2) +> +struct relate< + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> +> +{ + template <typename Mask> + struct visitor : boost::static_visitor<bool> + { + Mask const& m_mask; + + visitor(Mask const& mask) + : m_mask(mask) {} + + template <typename Geometry1, typename Geometry2> + bool operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return relate<Geometry1, Geometry2> + ::apply(geometry1, geometry2, m_mask); + } + }; + + template <typename Mask> + static inline bool + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2, + Mask const& mask) + { + return boost::apply_visitor(visitor<Mask>(mask), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + +/*! +\brief Checks relation between a pair of geometries defined by a mask. +\ingroup relate +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Mask An intersection model Mask type. +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param mask An intersection model mask object. +\return true if the relation is compatible with the mask, false otherwise. + +\qbk{[include reference/algorithms/relate.qbk]} + */ +template <typename Geometry1, typename Geometry2, typename Mask> +inline bool relate(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Mask const& mask) +{ + return resolve_variant::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, mask); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP diff --git a/boost/geometry/algorithms/detail/relate/less.hpp b/boost/geometry/algorithms/detail/relate/less.hpp index 3f11d4e87d..462fcc35f1 100644 --- a/boost/geometry/algorithms/detail/relate/less.hpp +++ b/boost/geometry/algorithms/detail/relate/less.hpp @@ -14,6 +14,10 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/util/math.hpp> + namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 7d85a1d9a1..e7cbf6f6c2 100644 --- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -15,7 +15,9 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP #include <boost/core/ignore_unused.hpp> +#include <boost/range/size.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/topological_dimension.hpp> #include <boost/geometry/util/condition.hpp> @@ -97,7 +99,7 @@ public: } int const pig = detail::within::point_in_geometry(range::front(linestring), m_geometry2); - //BOOST_ASSERT_MSG(pig != 0, "There should be no IPs"); + //BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs"); if ( pig > 0 ) { @@ -323,8 +325,8 @@ struct linear_areal // if there was some previous ring if ( prev_seg_id_ptr != NULL ) { - signed_index_type const next_ring_index = prev_seg_id_ptr->ring_index + 1; - BOOST_ASSERT(next_ring_index >= 0); + signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1; + BOOST_GEOMETRY_ASSERT(next_ring_index >= 0); // if one of the last rings of previous single geometry was ommited if ( static_cast<std::size_t>(next_ring_index) @@ -394,8 +396,8 @@ struct linear_areal // if there was some previous ring if ( prev_seg_id_ptr != NULL ) { - signed_index_type const next_ring_index = prev_seg_id_ptr->ring_index + 1; - BOOST_ASSERT(next_ring_index >= 0); + signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1; + BOOST_GEOMETRY_ASSERT(next_ring_index >= 0); // if one of the last rings of previous single geometry was ommited if ( static_cast<std::size_t>(next_ring_index) @@ -456,7 +458,7 @@ struct linear_areal template <typename TurnIt> void operator()(TurnIt first, TurnIt last) const { - BOOST_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(first != last); static OpToPriority op_to_priority; // find the operation with the least priority int least_priority = op_to_priority(first->operations[0]); @@ -736,6 +738,8 @@ struct linear_areal // handle the interior overlap if ( m_interior_detected ) { + BOOST_GEOMETRY_ASSERT_MSG(m_previous_turn_ptr, "non-NULL ptr expected"); + // real interior overlap if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) ) { @@ -745,21 +749,16 @@ struct linear_areal // new range detected - reset previous state and check the boundary if ( first_in_range ) { - // actually it should be != NULL if m_interior_detected - // so an assert could be checked here - if ( m_previous_turn_ptr ) - { - segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; + segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; - bool const prev_back_b = is_endpoint_on_boundary<boundary_back>( - range::back(sub_range(geometry, prev_seg_id)), - boundary_checker); + bool const prev_back_b = is_endpoint_on_boundary<boundary_back>( + range::back(sub_range(geometry, prev_seg_id)), + boundary_checker); - // if there is a boundary on the last point - if ( prev_back_b ) - { - update<boundary, interior, '0', TransposeResult>(res); - } + // if there is a boundary on the last point + if ( prev_back_b ) + { + update<boundary, interior, '0', TransposeResult>(res); } // The exit_watcher is reset below @@ -1002,7 +1001,7 @@ struct linear_areal /*&& ( op == overlay::operation_blocked || op == overlay::operation_union )*/ ) // if we're here it's u or x { - BOOST_ASSERT(m_first_from_unknown); + BOOST_GEOMETRY_ASSERT(m_first_from_unknown); m_first_from_unknown_boundary_detected = true; } else @@ -1043,7 +1042,7 @@ struct linear_areal BoundaryChecker const& boundary_checker) { boost::ignore_unused(first, last); - //BOOST_ASSERT( first != last ); + //BOOST_GEOMETRY_ASSERT( first != last ); // For MultiPolygon many x/u operations may be generated as a first IP // if for all turns x/u was generated and any of the Polygons doesn't contain the LineString @@ -1071,8 +1070,8 @@ struct linear_areal // for sure update<interior, exterior, '1', TransposeResult>(res); - BOOST_ASSERT(first != last); - BOOST_ASSERT(m_previous_turn_ptr); + BOOST_GEOMETRY_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr); segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; @@ -1094,8 +1093,8 @@ struct linear_areal update<interior, interior, '1', TransposeResult>(res); m_interior_detected = false; - BOOST_ASSERT(first != last); - BOOST_ASSERT(m_previous_turn_ptr); + BOOST_GEOMETRY_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr); segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; @@ -1112,7 +1111,7 @@ struct linear_areal // This condition may be false if the Linestring is lying on the Polygon's collinear spike // if Polygon's spikes are not handled in get_turns() or relate() (they currently aren't) - //BOOST_ASSERT_MSG(m_previous_operation != overlay::operation_continue, + //BOOST_GEOMETRY_ASSERT_MSG(m_previous_operation != overlay::operation_continue, // "Unexpected operation! Probably the error in get_turns(L,A) or relate(L,A)"); // Currently one c/c turn is generated for the exit // when a Linestring is going out on a collinear spike @@ -1160,16 +1159,16 @@ struct linear_areal typedef typename boost::range_iterator<range2_type>::type range2_iterator; range2_type range2(sub_range(geometry2, turn.operations[other_op_id].seg_id)); - BOOST_ASSERT(boost::size(range1)); + BOOST_GEOMETRY_ASSERT(boost::size(range1)); std::size_t const s2 = boost::size(range2); - BOOST_ASSERT(s2 > 2); + BOOST_GEOMETRY_ASSERT(s2 > 2); std::size_t const seg_count2 = s2 - 1; std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index); std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index); - BOOST_ASSERT(p_seg_ij + 1 < boost::size(range1)); - BOOST_ASSERT(q_seg_ij + 1 < s2); + BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1)); + BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2); point1_type const& pi = range::at(range1, p_seg_ij); point2_type const& qi = range::at(range2, q_seg_ij); @@ -1178,8 +1177,8 @@ struct linear_areal geometry::convert(qi, qi_conv); bool const is_ip_qj = equals::equals_point_point(turn.point, qj); // TODO: test this! -// BOOST_ASSERT(!equals::equals_point_point(turn.point, pi)); -// BOOST_ASSERT(!equals::equals_point_point(turn.point, qi)); +// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi)); +// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi)); point1_type new_pj; geometry::convert(turn.point, new_pj); @@ -1211,7 +1210,7 @@ struct linear_areal template <typename It> static inline It find_next_non_duplicated(It first, It current, It last) { - BOOST_ASSERT( current != last ); + BOOST_GEOMETRY_ASSERT( current != last ); It it = current; @@ -1332,8 +1331,8 @@ struct linear_areal if ( first == last ) return last; - signed_index_type const multi_index = first->operations[1].seg_id.multi_index; - signed_index_type const ring_index = first->operations[1].seg_id.ring_index; + signed_size_type const multi_index = first->operations[1].seg_id.multi_index; + signed_size_type const ring_index = first->operations[1].seg_id.ring_index; fun(*first); ++first; @@ -1379,7 +1378,7 @@ struct linear_areal if ( is_union_detected ) { - BOOST_ASSERT(m_previous_turn_ptr != NULL); + BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr != NULL); if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point) ) { // break diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 20a22c3018..7a3f373e03 100644 --- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -14,7 +14,12 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP +#include <algorithm> + #include <boost/core/ignore_unused.hpp> +#include <boost/range/size.hpp> + +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/range.hpp> @@ -23,6 +28,7 @@ #include <boost/geometry/algorithms/detail/single_geometry.hpp> #include <boost/geometry/algorithms/detail/relate/point_geometry.hpp> +#include <boost/geometry/algorithms/detail/relate/result.hpp> #include <boost/geometry/algorithms/detail/relate/turns.hpp> #include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp> #include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp> @@ -576,7 +582,7 @@ struct linear_linear OtherBoundaryChecker const& /*other_boundary_checker*/) { boost::ignore_unused(first, last); - //BOOST_ASSERT( first != last ); + //BOOST_GEOMETRY_ASSERT( first != last ); // here, the possible exit is the real one // we know that we entered and now we exit @@ -586,7 +592,7 @@ struct linear_linear { update<interior, exterior, '1', transpose_result>(res); - BOOST_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(first != last); const TurnInfo * turn_ptr = NULL; if ( m_degenerated_turn_ptr ) @@ -598,7 +604,7 @@ struct linear_linear { segment_identifier const& prev_seg_id = turn_ptr->operations[op_id].seg_id; - //BOOST_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id))); + //BOOST_GEOMETRY_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id))); bool const prev_back_b = is_endpoint_on_boundary<boundary_back>( range::back(sub_range(geometry, prev_seg_id)), boundary_checker); @@ -688,7 +694,7 @@ struct linear_linear if ( first_in_range ) { - //BOOST_ASSERT(!boost::empty(ls1_ref)); + //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref)); bool const front_b = is_endpoint_on_boundary<boundary_front>( range::front(ls1_ref), boundary_checker); if ( front_b ) @@ -717,7 +723,7 @@ struct linear_linear if ( first_in_range ) { - //BOOST_ASSERT(!boost::empty(ls1_ref)); + //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref)); bool const front_b = is_endpoint_on_boundary<boundary_front>( range::front(ls1_ref), boundary_checker); if ( front_b ) diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp index 62ab100919..be08016a16 100644 --- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp +++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp @@ -18,6 +18,7 @@ //#include <boost/geometry/algorithms/within.hpp> //#include <boost/geometry/algorithms/covered_by.hpp> +#include <boost/geometry/algorithms/detail/relate/result.hpp> #include <boost/geometry/algorithms/detail/relate/topology_check.hpp> #include <boost/geometry/util/condition.hpp> @@ -43,18 +44,18 @@ struct point_geometry if ( pig > 0 ) // within { - set<interior, interior, '0', Transpose>(result); + relate::set<interior, interior, '0', Transpose>(result); } else if ( pig == 0 ) { - set<interior, boundary, '0', Transpose>(result); + relate::set<interior, boundary, '0', Transpose>(result); } else // pig < 0 - not within { - set<interior, exterior, '0', Transpose>(result); + relate::set<interior, exterior, '0', Transpose>(result); } - set<exterior, exterior, result_dimension<Point>::value, Transpose>(result); + relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -69,9 +70,9 @@ struct point_geometry typedef detail::relate::topology_check<Geometry> tc_t; //tc_t tc(geometry, point); //if ( tc.has_interior ) - set<exterior, interior, tc_t::interior, Transpose>(result); + relate::set<exterior, interior, tc_t::interior, Transpose>(result); //if ( tc.has_boundary ) - set<exterior, boundary, tc_t::boundary, Transpose>(result); + relate::set<exterior, boundary, tc_t::boundary, Transpose>(result); } else { @@ -79,9 +80,9 @@ struct point_geometry typedef detail::relate::topology_check<Geometry> tc_t; tc_t tc(geometry); if ( tc.has_interior ) - set<exterior, interior, tc_t::interior, Transpose>(result); + relate::set<exterior, interior, tc_t::interior, Transpose>(result); if ( tc.has_boundary ) - set<exterior, boundary, tc_t::boundary, Transpose>(result); + relate::set<exterior, boundary, tc_t::boundary, Transpose>(result); } } }; diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp index e623868b92..e55be08225 100644 --- a/boost/geometry/algorithms/detail/relate/point_point.hpp +++ b/boost/geometry/algorithms/detail/relate/point_point.hpp @@ -17,9 +17,12 @@ #include <algorithm> #include <vector> +#include <boost/range/empty.hpp> + #include <boost/geometry/algorithms/detail/equals/point_point.hpp> #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp> #include <boost/geometry/algorithms/detail/relate/less.hpp> +#include <boost/geometry/algorithms/detail/relate/result.hpp> namespace boost { namespace geometry { @@ -38,15 +41,15 @@ struct point_point bool equal = detail::equals::equals_point_point(point1, point2); if ( equal ) { - set<interior, interior, '0'>(result); + relate::set<interior, interior, '0'>(result); } else { - set<interior, exterior, '0'>(result); - set<exterior, interior, '0'>(result); + relate::set<interior, exterior, '0'>(result); + relate::set<exterior, interior, '0'>(result); } - set<exterior, exterior, result_dimension<Point1>::value>(result); + relate::set<exterior, exterior, result_dimension<Point1>::value>(result); } }; @@ -89,7 +92,7 @@ struct point_multipoint if ( boost::empty(multi_point) ) { // TODO: throw on empty input? - set<interior, exterior, '0', Transpose>(result); + relate::set<interior, exterior, '0', Transpose>(result); return; } @@ -97,20 +100,20 @@ struct point_multipoint if ( rel.first ) // some point of MP is equal to P { - set<interior, interior, '0', Transpose>(result); + relate::set<interior, interior, '0', Transpose>(result); if ( rel.second ) // a point of MP was found outside P { - set<exterior, interior, '0', Transpose>(result); + relate::set<exterior, interior, '0', Transpose>(result); } } else { - set<interior, exterior, '0', Transpose>(result); - set<exterior, interior, '0', Transpose>(result); + relate::set<interior, exterior, '0', Transpose>(result); + relate::set<exterior, interior, '0', Transpose>(result); } - set<exterior, exterior, result_dimension<Point>::value, Transpose>(result); + relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result); } }; @@ -144,12 +147,12 @@ struct multipoint_multipoint } else if ( empty1 ) { - set<exterior, interior, '0'>(result); + relate::set<exterior, interior, '0'>(result); return; } else if ( empty2 ) { - set<interior, exterior, '0'>(result); + relate::set<interior, exterior, '0'>(result); return; } } @@ -165,7 +168,7 @@ struct multipoint_multipoint // NlogN + MlogN bool all_handled = search<false>(multi_point1, multi_point2, result); - if ( all_handled || result.interrupt ) + if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) ) return; // MlogM + NlogM @@ -212,23 +215,23 @@ struct multipoint_multipoint // TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed // so if e.g. only I/I must be analysed we musn't check the other MPt - set<interior, interior, '0', Transpose>(result); + relate::set<interior, interior, '0', Transpose>(result); if ( found_outside ) // some point of MP2 was found outside of MP1 { - set<exterior, interior, '0', Transpose>(result); + relate::set<exterior, interior, '0', Transpose>(result); } } else { - set<interior, exterior, '0', Transpose>(result); - set<exterior, interior, '0', Transpose>(result); + relate::set<interior, exterior, '0', Transpose>(result); + relate::set<exterior, interior, '0', Transpose>(result); // if no point is intersecting the other MPt then we musn't analyse the reversed case all_handled = true; } - set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result); + relate::set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result); return all_handled; } diff --git a/boost/geometry/algorithms/detail/relate/relate.hpp b/boost/geometry/algorithms/detail/relate/relate.hpp deleted file mode 100644 index 946653452a..0000000000 --- a/boost/geometry/algorithms/detail/relate/relate.hpp +++ /dev/null @@ -1,339 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. - -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_HPP - -#include <cstddef> - -#include <boost/concept_check.hpp> -#include <boost/range.hpp> - -#include <boost/mpl/if.hpp> -#include <boost/mpl/or.hpp> -#include <boost/type_traits/is_base_of.hpp> - -#include <boost/geometry/algorithms/make.hpp> -#include <boost/geometry/algorithms/not_implemented.hpp> - -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/closure.hpp> -#include <boost/geometry/core/cs.hpp> -#include <boost/geometry/core/exterior_ring.hpp> -#include <boost/geometry/core/interior_rings.hpp> -#include <boost/geometry/core/point_order.hpp> -#include <boost/geometry/core/ring_type.hpp> -#include <boost/geometry/core/interior_rings.hpp> -#include <boost/geometry/core/tags.hpp> - -#include <boost/geometry/geometries/concepts/check.hpp> -#include <boost/geometry/strategies/concepts/within_concept.hpp> -#include <boost/geometry/strategies/default_strategy.hpp> -#include <boost/geometry/strategies/within.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/geometry/util/order_as_direction.hpp> -#include <boost/geometry/views/closeable_view.hpp> -#include <boost/geometry/views/reversible_view.hpp> - -#include <boost/geometry/algorithms/detail/relate/result.hpp> - -#include <boost/geometry/algorithms/detail/relate/point_point.hpp> -#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp> -#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp> -#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp> -#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp> - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace relate { - -// Those are used only to allow dispatch::relate to produce compile-time error - -template <typename Geometry, - typename Tag = typename geometry::tag<Geometry>::type> -struct is_supported_by_generic -{ - static const bool value - = boost::is_same<Tag, linestring_tag>::value - || boost::is_same<Tag, multi_linestring_tag>::value - || boost::is_same<Tag, ring_tag>::value - || boost::is_same<Tag, polygon_tag>::value - || boost::is_same<Tag, multi_polygon_tag>::value; -}; - -template <typename Geometry1, - typename Geometry2, - typename Tag1 = typename geometry::tag<Geometry1>::type, - typename Tag2 = typename geometry::tag<Geometry2>::type> -struct is_generic -{ - static const bool value = is_supported_by_generic<Geometry1>::value - && is_supported_by_generic<Geometry2>::value; -}; - - -template <typename Point, typename Geometry, typename Tag> -struct is_generic<Point, Geometry, point_tag, Tag> -{ - static const bool value = is_supported_by_generic<Geometry>::value; -}; - -template <typename Geometry, typename Point, typename Tag> -struct is_generic<Geometry, Point, Tag, point_tag> -{ - static const bool value = is_supported_by_generic<Geometry>::value; -}; - -template <typename Point1, typename Point2> -struct is_generic<Point1, Point2, point_tag, point_tag> -{ - static const bool value = false; -}; - - -}} // namespace detail::relate - -#ifndef DOXYGEN_NO_DISPATCH -namespace detail_dispatch { namespace relate { - - -template <typename Geometry1, - typename Geometry2, - typename Tag1 = typename geometry::tag<Geometry1>::type, - typename Tag2 = typename geometry::tag<Geometry2>::type, - int TopDim1 = geometry::topological_dimension<Geometry1>::value, - int TopDim2 = geometry::topological_dimension<Geometry2>::value, - bool IsGeneric = detail::relate::is_generic<Geometry1, Geometry2>::value -> -struct relate : not_implemented<Tag1, Tag2> -{}; - - -template <typename Point1, typename Point2> -struct relate<Point1, Point2, point_tag, point_tag, 0, 0, false> - : detail::relate::point_point<Point1, Point2> -{}; - -template <typename Point, typename MultiPoint> -struct relate<Point, MultiPoint, point_tag, multi_point_tag, 0, 0, false> - : detail::relate::point_multipoint<Point, MultiPoint> -{}; - -template <typename MultiPoint, typename Point> -struct relate<MultiPoint, Point, multi_point_tag, point_tag, 0, 0, false> - : detail::relate::multipoint_point<MultiPoint, Point> -{}; - -template <typename MultiPoint1, typename MultiPoint2> -struct relate<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, 0, 0, false> - : detail::relate::multipoint_multipoint<MultiPoint1, MultiPoint2> -{}; - -//template <typename Point, typename Box, int TopDim2> -//struct relate<Point, Box, point_tag, box_tag, 0, TopDim2, false> -// : detail::relate::point_box<Point, Box> -//{}; -// -//template <typename Box, typename Point, int TopDim1> -//struct relate<Box, Point, box_tag, point_tag, TopDim1, 0, false> -// : detail::relate::box_point<Box, Point> -//{}; - - -template <typename Point, typename Geometry, typename Tag2, int TopDim2> -struct relate<Point, Geometry, point_tag, Tag2, 0, TopDim2, true> - : detail::relate::point_geometry<Point, Geometry> -{}; - -template <typename Geometry, typename Point, typename Tag1, int TopDim1> -struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true> - : detail::relate::geometry_point<Geometry, Point> -{}; - - -template <typename Linear1, typename Linear2, typename Tag1, typename Tag2> -struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true> - : detail::relate::linear_linear<Linear1, Linear2> -{}; - - -template <typename Linear, typename Areal, typename Tag1, typename Tag2> -struct relate<Linear, Areal, Tag1, Tag2, 1, 2, true> - : detail::relate::linear_areal<Linear, Areal> -{}; - -template <typename Areal, typename Linear, typename Tag1, typename Tag2> -struct relate<Areal, Linear, Tag1, Tag2, 2, 1, true> - : detail::relate::areal_linear<Areal, Linear> -{}; - - -template <typename Areal1, typename Areal2, typename Tag1, typename Tag2> -struct relate<Areal1, Areal2, Tag1, Tag2, 2, 2, true> - : detail::relate::areal_areal<Areal1, Areal2> -{}; - - -}} // namespace detail_dispatch::relate -#endif // DOXYGEN_NO_DISPATCH - -namespace detail { namespace relate { - -template <typename Geometry1, typename Geometry2> -struct interruption_enabled -{ - static const bool value = - detail_dispatch::relate::relate<Geometry1, Geometry2>::interruption_enabled; -}; - -template <typename Geometry1, - typename Geometry2, - typename Result, - bool IsSequence = boost::mpl::is_sequence<Result>::value> -struct result_handler_type - : not_implemented<Result> -{}; - -template <typename Geometry1, typename Geometry2> -struct result_handler_type<Geometry1, Geometry2, matrix9, false> -{ - typedef matrix_handler<matrix9> type; -}; - -template <typename Geometry1, typename Geometry2> -struct result_handler_type<Geometry1, Geometry2, mask9, false> -{ - typedef mask_handler - < - mask9, - interruption_enabled - < - Geometry1, - Geometry2 - >::value - > type; -}; - -template <typename Geometry1, typename Geometry2, typename Head, typename Tail> -struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail>, false> -{ - typedef mask_handler - < - boost::tuples::cons<Head, Tail>, - interruption_enabled - < - Geometry1, - Geometry2 - >::value - > type; -}; - -template <typename Geometry1, typename Geometry2, - char II, char IB, char IE, - char BI, char BB, char BE, - char EI, char EB, char EE> -struct result_handler_type<Geometry1, Geometry2, static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>, false> -{ - typedef static_mask_handler - < - static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>, - interruption_enabled - < - Geometry1, - Geometry2 - >::value - > type; -}; - -template <typename Geometry1, typename Geometry2, typename StaticSequence> -struct result_handler_type<Geometry1, Geometry2, StaticSequence, true> -{ - typedef static_mask_handler - < - StaticSequence, - interruption_enabled - < - Geometry1, - Geometry2 - >::value - > type; -}; - -template <typename MatrixOrMask, typename Geometry1, typename Geometry2> -inline -typename result_handler_type - < - Geometry1, - Geometry2, - MatrixOrMask - >::type::result_type -relate(Geometry1 const& geometry1, - Geometry2 const& geometry2, - MatrixOrMask const& matrix_or_mask = MatrixOrMask()) -{ - typedef typename result_handler_type - < - Geometry1, - Geometry2, - MatrixOrMask - >::type handler_type; - - handler_type handler(matrix_or_mask); - detail_dispatch::relate::relate<Geometry1, Geometry2>::apply(geometry1, geometry2, handler); - return handler.result(); -} - -struct implemented_tag {}; - -template <template <typename, typename> class StaticMaskTrait, - typename Geometry1, - typename Geometry2> -struct relate_base - : boost::mpl::if_ - < - boost::mpl::or_ - < - boost::is_base_of - < - nyi::not_implemented_tag, - StaticMaskTrait<Geometry1, Geometry2> - >, - boost::is_base_of - < - nyi::not_implemented_tag, - detail_dispatch::relate::relate<Geometry1, Geometry2> - > - >, - not_implemented - < - typename geometry::tag<Geometry1>::type, - typename geometry::tag<Geometry2>::type - >, - implemented_tag - >::type -{ - static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) - { - typedef typename StaticMaskTrait<Geometry1, Geometry2>::type static_mask; - return detail::relate::relate<static_mask>(g1, g2); - } -}; - -}} // namespace detail::relate -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_HPP diff --git a/boost/geometry/algorithms/detail/relate/relate_impl.hpp b/boost/geometry/algorithms/detail/relate/relate_impl.hpp new file mode 100644 index 0000000000..e8e422993d --- /dev/null +++ b/boost/geometry/algorithms/detail/relate/relate_impl.hpp @@ -0,0 +1,80 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP + +#include <boost/mpl/if.hpp> +#include <boost/mpl/or.hpp> +#include <boost/type_traits/is_base_of.hpp> + +#include <boost/geometry/algorithms/detail/relate/interface.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/core/tag.hpp> + +namespace boost { namespace geometry { + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +struct implemented_tag {}; + +template <template <typename, typename> class StaticMaskTrait, + typename Geometry1, + typename Geometry2> +struct relate_impl + : boost::mpl::if_ + < + boost::mpl::or_ + < + boost::is_base_of + < + nyi::not_implemented_tag, + StaticMaskTrait<Geometry1, Geometry2> + >, + boost::is_base_of + < + nyi::not_implemented_tag, + dispatch::relate<Geometry1, Geometry2> + > + >, + not_implemented + < + typename geometry::tag<Geometry1>::type, + typename geometry::tag<Geometry2>::type + >, + implemented_tag + >::type +{ + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + { + typename detail::relate::result_handler_type + < + Geometry1, + Geometry2, + typename StaticMaskTrait<Geometry1, Geometry2>::type + >::type handler; + + dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler); + + return handler.result(); + } +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp index e26bda67f2..b7b9264449 100644 --- a/boost/geometry/algorithms/detail/relate/result.hpp +++ b/boost/geometry/algorithms/detail/relate/result.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // This file was modified by Oracle on 2013, 2014, 2015. // Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. @@ -14,21 +14,24 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP -#include <boost/tuple/tuple.hpp> +#include <cstddef> -#include <boost/mpl/is_sequence.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/at.hpp> #include <boost/mpl/begin.hpp> +#include <boost/mpl/deref.hpp> #include <boost/mpl/end.hpp> +#include <boost/mpl/is_sequence.hpp> #include <boost/mpl/next.hpp> -#include <boost/mpl/at.hpp> -#include <boost/mpl/vector_c.hpp> +#include <boost/static_assert.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/type_traits/integral_constant.hpp> -#include <boost/geometry/core/topological_dimension.hpp> +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/exception.hpp> #include <boost/geometry/util/condition.hpp> -// TEMP - move this header to geometry/detail -#include <boost/geometry/index/detail/tuples.hpp> - namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL @@ -42,125 +45,110 @@ enum field { interior = 0, boundary = 1, exterior = 2 }; // but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that // so some additional function could be added, e.g. set_dim() -// matrix +// --------------- MATRIX ---------------- -// TODO add height? +// matrix -template <std::size_t Width> +template <std::size_t Height, std::size_t Width = Height> class matrix { - BOOST_STATIC_ASSERT(Width == 2 || Width == 3); - public: - - static const std::size_t size = Width * Width; + typedef char value_type; + typedef std::size_t size_type; + typedef const char * const_iterator; + typedef const_iterator iterator; + + static const std::size_t static_width = Width; + static const std::size_t static_height = Height; + static const std::size_t static_size = Width * Height; inline matrix() { - ::memset(m_array, 'F', size); + ::memset(m_array, 'F', static_size); } template <field F1, field F2> inline char get() const { - static const bool in_bounds = F1 * Width + F2 < size; - return get_dispatch<F1, F2>(integral_constant<bool, in_bounds>()); + BOOST_STATIC_ASSERT(F1 < Height && F2 < Width); + static const std::size_t index = F1 * Width + F2; + BOOST_STATIC_ASSERT(index < static_size); + return m_array[index]; } template <field F1, field F2, char V> inline void set() { - static const bool in_bounds = F1 * Width + F2 < size; - set_dispatch<F1, F2, V>(integral_constant<bool, in_bounds>()); + BOOST_STATIC_ASSERT(F1 < Height && F2 < Width); + static const std::size_t index = F1 * Width + F2; + BOOST_STATIC_ASSERT(index < static_size); + m_array[index] = V; } - template <field F1, field F2, char D> - inline void update() + inline char operator[](std::size_t index) const { - static const bool in_bounds = F1 * Width + F2 < size; - update_dispatch<F1, F2, D>(integral_constant<bool, in_bounds>()); + BOOST_GEOMETRY_ASSERT(index < static_size); + return m_array[index]; } - - inline const char * data() const + + inline const_iterator begin() const { return m_array; } -private: - template <field F1, field F2> - inline char get_dispatch(integral_constant<bool, true>) const + inline const_iterator end() const { - return m_array[F1 * Width + F2]; + return m_array + static_size; } - template <field F1, field F2> - inline char get_dispatch(integral_constant<bool, false>) const + + inline static std::size_t size() { - return 'F'; + return static_size; } - - template <field F1, field F2, char V> - inline void set_dispatch(integral_constant<bool, true>) + + inline const char * data() const { - BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F'); - m_array[F1 * Width + F2] = V; + return m_array; } - template <field F1, field F2, char V> - inline void set_dispatch(integral_constant<bool, false>) - {} - template <field F1, field F2, char D> - inline void update_dispatch(integral_constant<bool, true>) + inline std::string str() const { - BOOST_STATIC_ASSERT('0' <= D && D <= '9'); - char c = m_array[F1 * Width + F2]; - if ( D > c || c > '9') - m_array[F1 * Width + F2] = D; + return std::string(m_array, static_size); } - template <field F1, field F2, char D> - inline void update_dispatch(integral_constant<bool, false>) - {} - char m_array[size]; -}; - -// TODO add EnableDimensions parameter? - -struct matrix9 {}; -//struct matrix4 {}; - -// matrix_width - -template <typename MatrixOrMask> -struct matrix_width - : not_implemented<MatrixOrMask> -{}; - -template <> -struct matrix_width<matrix9> -{ - static const std::size_t value = 3; +private: + char m_array[static_size]; }; // matrix_handler template <typename Matrix> class matrix_handler - : private matrix<matrix_width<Matrix>::value> { - typedef matrix<matrix_width<Matrix>::value> base_t; - public: - typedef std::string result_type; + typedef Matrix result_type; static const bool interrupt = false; + matrix_handler() + {} + matrix_handler(Matrix const&) {} - result_type result() const + result_type const& result() const { - return std::string(this->data(), - this->data() + base_t::size); + return m_matrix; + } + + result_type const& matrix() const + { + return m_matrix; + } + + result_type & matrix() + { + return m_matrix; } template <field F1, field F2, char D> @@ -168,53 +156,124 @@ public: { BOOST_STATIC_ASSERT('0' <= D && D <= '9'); - char const c = static_cast<base_t const&>(*this).template get<F1, F2>(); + char const c = m_matrix.template get<F1, F2>(); return D > c || c > '9'; } - //template <field F1, field F2> - //inline char get() const - //{ - // return static_cast<base_t const&>(*this).template get<F1, F2>(); - //} - template <field F1, field F2, char V> inline void set() { - static_cast<base_t&>(*this).template set<F1, F2, V>(); + static const bool in_bounds = F1 < Matrix::static_height + && F2 < Matrix::static_width; + typedef boost::integral_constant<bool, in_bounds> in_bounds_t; + set_dispatch<F1, F2, V>(in_bounds_t()); } template <field F1, field F2, char D> inline void update() { - static_cast<base_t&>(*this).template update<F1, F2, D>(); + static const bool in_bounds = F1 < Matrix::static_height + && F2 < Matrix::static_width; + typedef boost::integral_constant<bool, in_bounds> in_bounds_t; + update_dispatch<F1, F2, D>(in_bounds_t()); } + +private: + template <field F1, field F2, char V> + inline void set_dispatch(integral_constant<bool, true>) + { + static const std::size_t index = F1 * Matrix::static_width + F2; + BOOST_STATIC_ASSERT(index < Matrix::static_size); + BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F'); + m_matrix.template set<F1, F2, V>(); + } + template <field F1, field F2, char V> + inline void set_dispatch(integral_constant<bool, false>) + {} + + template <field F1, field F2, char D> + inline void update_dispatch(integral_constant<bool, true>) + { + static const std::size_t index = F1 * Matrix::static_width + F2; + BOOST_STATIC_ASSERT(index < Matrix::static_size); + BOOST_STATIC_ASSERT('0' <= D && D <= '9'); + char const c = m_matrix.template get<F1, F2>(); + if ( D > c || c > '9') + m_matrix.template set<F1, F2, D>(); + } + template <field F1, field F2, char D> + inline void update_dispatch(integral_constant<bool, false>) + {} + + Matrix m_matrix; }; -// RUN-TIME MASKS +// --------------- RUN-TIME MASK ---------------- -// mask9 +// run-time mask -class mask9 +template <std::size_t Height, std::size_t Width = Height> +class mask { public: - static const std::size_t width = 3; // TEMP + static const std::size_t static_width = Width; + static const std::size_t static_height = Height; + static const std::size_t static_size = Width * Height; + + inline mask(const char * s) + { + char * it = m_array; + char * const last = m_array + static_size; + for ( ; it != last && *s != '\0' ; ++it, ++s ) + { + char c = *s; + check_char(c); + *it = c; + } + if ( it != last ) + { + ::memset(it, '*', last - it); + } + } - inline mask9(std::string const& de9im_mask) + inline mask(const char * s, std::size_t count) { - // TODO: throw an exception here? - BOOST_ASSERT(de9im_mask.size() == 9); - ::memcpy(m_mask, de9im_mask.c_str(), 9); + if ( count > static_size ) + { + count = static_size; + } + if ( count > 0 ) + { + std::for_each(s, s + count, check_char); + ::memcpy(m_array, s, count); + } + if ( count < static_size ) + { + ::memset(m_array + count, '*', static_size - count); + } } template <field F1, field F2> inline char get() const { - return m_mask[F1 * 3 + F2]; + BOOST_STATIC_ASSERT(F1 < Height && F2 < Width); + static const std::size_t index = F1 * Width + F2; + BOOST_STATIC_ASSERT(index < static_size); + return m_array[index]; } private: - char m_mask[9]; + static inline void check_char(char c) + { + bool const is_valid = c == '*' || c == 'T' || c == 'F' + || ( c >= '0' && c <= '9' ); + if ( !is_valid ) + { + throw geometry::invalid_input_exception(); + } + } + + char m_array[static_size]; }; // interrupt() @@ -277,18 +336,18 @@ struct interrupt_dispatch_tuple<Masks, N, N> } }; -template <typename T0, typename T1, typename T2, typename T3, typename T4, - typename T5, typename T6, typename T7, typename T8, typename T9> -struct interrupt_dispatch<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, true> -{ - typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type; +//template <typename T0, typename T1, typename T2, typename T3, typename T4, +// typename T5, typename T6, typename T7, typename T8, typename T9> +//struct interrupt_dispatch<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, true> +//{ +// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type; - template <field F1, field F2, char V> - static inline bool apply(mask_type const& mask) - { - return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask); - } -}; +// template <field F1, field F2, char V> +// static inline bool apply(mask_type const& mask) +// { +// return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask); +// } +//}; template <typename Head, typename Tail> struct interrupt_dispatch<boost::tuples::cons<Head, Tail>, true> @@ -363,18 +422,18 @@ struct may_update_dispatch_tuple<Masks, N, N> } }; -template <typename T0, typename T1, typename T2, typename T3, typename T4, - typename T5, typename T6, typename T7, typename T8, typename T9> -struct may_update_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > -{ - typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type; +//template <typename T0, typename T1, typename T2, typename T3, typename T4, +// typename T5, typename T6, typename T7, typename T8, typename T9> +//struct may_update_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > +//{ +// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type; - template <field F1, field F2, char D, typename Matrix> - static inline bool apply(mask_type const& mask, Matrix const& matrix) - { - return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix); - } -}; +// template <field F1, field F2, char D, typename Matrix> +// static inline bool apply(mask_type const& mask, Matrix const& matrix) +// { +// return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix); +// } +//}; template <typename Head, typename Tail> struct may_update_dispatch< boost::tuples::cons<Head, Tail> > @@ -460,18 +519,18 @@ struct check_dispatch_tuple<Masks, N, N> } }; -template <typename T0, typename T1, typename T2, typename T3, typename T4, - typename T5, typename T6, typename T7, typename T8, typename T9> -struct check_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > -{ - typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type; +//template <typename T0, typename T1, typename T2, typename T3, typename T4, +// typename T5, typename T6, typename T7, typename T8, typename T9> +//struct check_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > +//{ +// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type; - template <typename Matrix> - static inline bool apply(mask_type const& mask, Matrix const& matrix) - { - return check_dispatch_tuple<mask_type>::apply(mask, matrix); - } -}; +// template <typename Matrix> +// static inline bool apply(mask_type const& mask, Matrix const& matrix) +// { +// return check_dispatch_tuple<mask_type>::apply(mask, matrix); +// } +//}; template <typename Head, typename Tail> struct check_dispatch< boost::tuples::cons<Head, Tail> > @@ -493,10 +552,10 @@ inline bool check_matrix(Mask const& mask, Matrix const& matrix) // matrix_width -template <> -struct matrix_width<mask9> +template <typename MatrixOrMask> +struct matrix_width { - static const std::size_t value = 3; + static const std::size_t value = MatrixOrMask::static_width; }; template <typename Tuple, @@ -526,20 +585,30 @@ struct matrix_width< boost::tuples::cons<Head, Tail> > value = matrix_width_tuple< boost::tuples::cons<Head, Tail> >::value; }; -// matrix_handler +// mask_handler template <typename Mask, bool Interrupt> class mask_handler - : private matrix<matrix_width<Mask>::value> + : private matrix_handler + < + relate::matrix<matrix_width<Mask>::value> + > { - typedef matrix<matrix_width<Mask>::value> base_t; + typedef matrix_handler + < + relate::matrix<matrix_width<Mask>::value> + > base_t; public: typedef bool result_type; bool interrupt; - inline mask_handler(Mask const& m) + inline mask_handler() + : interrupt(false) + {} + + inline explicit mask_handler(Mask const& m) : interrupt(false) , m_mask(m) {} @@ -547,23 +616,17 @@ public: result_type result() const { return !interrupt - && check_matrix(m_mask, static_cast<base_t const&>(*this)); + && check_matrix(m_mask, base_t::matrix()); } template <field F1, field F2, char D> inline bool may_update() const { return detail::relate::may_update<F1, F2, D>( - m_mask, static_cast<base_t const&>(*this) + m_mask, base_t::matrix() ); } - //template <field F1, field F2> - //inline char get() const - //{ - // return static_cast<base_t const&>(*this).template get<F1, F2>(); - //} - template <field F1, field F2, char V> inline void set() { @@ -594,29 +657,65 @@ private: Mask const& m_mask; }; -// STATIC MASKS +// --------------- COMPILE-TIME MASK ---------------- + +// static_check_characters +template +< + typename Seq, + typename First = typename boost::mpl::begin<Seq>::type, + typename Last = typename boost::mpl::end<Seq>::type +> +struct static_check_characters + : static_check_characters + < + Seq, + typename boost::mpl::next<First>::type + > +{ + typedef typename boost::mpl::deref<First>::type type; + static const char value = type::value; + static const bool is_valid = (value >= '0' && value <= '9') + || value == 'T' || value == 'F' || value == '*'; + BOOST_MPL_ASSERT_MSG((is_valid), + INVALID_STATIC_MASK_CHARACTER, + (type)); +}; + +template <typename Seq, typename Last> +struct static_check_characters<Seq, Last, Last> +{}; // static_mask -template <char II, char IB, char IE, - char BI, char BB, char BE, - char EI, char EB, char EE> -class static_mask +template +< + typename Seq, + std::size_t Height, + std::size_t Width = Height +> +struct static_mask { - typedef boost::mpl::vector_c - < - char, II, IB, IE, BI, BB, BE, EI, EB, EE - > vector_type; + static const std::size_t static_width = Width; + static const std::size_t static_height = Height; + static const std::size_t static_size = Width * Height; -public: - template <field F1, field F2> - struct get + BOOST_STATIC_ASSERT( + std::size_t(boost::mpl::size<Seq>::type::value) == static_size); + + template <detail::relate::field F1, detail::relate::field F2> + struct static_get { - BOOST_STATIC_ASSERT(F1 * 3 + F2 < boost::mpl::size<vector_type>::value); + BOOST_STATIC_ASSERT(std::size_t(F1) < static_height); + BOOST_STATIC_ASSERT(std::size_t(F2) < static_width); static const char value - = boost::mpl::at_c<vector_type, F1 * 3 + F2>::type::value; + = boost::mpl::at_c<Seq, F1 * static_width + F2>::type::value; }; + +private: + // check static_mask characters + enum { mask_check = sizeof(static_check_characters<Seq>) }; }; // static_should_handle_element @@ -624,7 +723,7 @@ public: template <typename StaticMask, field F1, field F2, bool IsSequence> struct static_should_handle_element_dispatch { - static const char mask_el = StaticMask::template get<F1, F2>::value; + static const char mask_el = StaticMask::template static_get<F1, F2>::value; static const bool value = mask_el == 'F' || mask_el == 'T' || ( mask_el >= '0' && mask_el <= '9' ); @@ -691,7 +790,7 @@ struct static_interrupt_dispatch template <typename StaticMask, char V, field F1, field F2, bool IsSequence> struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence> { - static const char mask_el = StaticMask::template get<F1, F2>::value; + static const char mask_el = StaticMask::template static_get<F1, F2>::value; static const bool value = ( V >= '0' && V <= '9' ) ? @@ -756,7 +855,7 @@ struct static_interrupt template <typename StaticMask, char D, field F1, field F2, bool IsSequence> struct static_may_update_dispatch { - static const char mask_el = StaticMask::template get<F1, F2>::value; + static const char mask_el = StaticMask::template static_get<F1, F2>::value; static const int version = mask_el == 'F' ? 0 : mask_el == 'T' ? 1 @@ -860,7 +959,7 @@ struct static_may_update } }; -// static_check +// static_check_matrix template <typename StaticMask, bool IsSequence> struct static_check_dispatch @@ -882,7 +981,7 @@ struct static_check_dispatch template <field F1, field F2> struct per_one { - static const char mask_el = StaticMask::template get<F1, F2>::value; + static const char mask_el = StaticMask::template static_get<F1, F2>::value; static const int version = mask_el == 'F' ? 0 : mask_el == 'T' ? 1 @@ -982,31 +1081,34 @@ struct static_check_matrix template <typename StaticMask, bool Interrupt> class static_mask_handler - : private matrix<3> + : private matrix_handler< matrix<3> > { - typedef matrix<3> base_t; + typedef matrix_handler< relate::matrix<3> > base_type; public: typedef bool result_type; bool interrupt; - inline static_mask_handler(StaticMask const& /*dummy*/) + inline static_mask_handler() + : interrupt(false) + {} + + inline explicit static_mask_handler(StaticMask const& /*dummy*/) : interrupt(false) {} result_type result() const { return (!Interrupt || !interrupt) - && static_check_matrix<StaticMask>:: - apply(static_cast<base_t const&>(*this)); + && static_check_matrix<StaticMask>::apply(base_type::matrix()); } template <field F1, field F2, char D> inline bool may_update() const { return static_may_update<StaticMask, D, F1, F2>:: - apply(static_cast<base_t const&>(*this)); + apply(base_type::matrix()); } template <field F1, field F2> @@ -1015,12 +1117,6 @@ public: return static_should_handle_element<StaticMask, F1, F2>::value; } - //template <field F1, field F2> - //inline char get() const - //{ - // return base_t::template get<F1, F2>(); - //} - template <field F1, field F2, char V> inline void set() { @@ -1056,7 +1152,7 @@ private: template <field F1, field F2, char V> inline void set_dispatch(integral_constant<int, 1>) { - base_t::template set<F1, F2, V>(); + base_type::template set<F1, F2, V>(); } // else template <field F1, field F2, char V> @@ -1073,7 +1169,7 @@ private: template <field F1, field F2, char V> inline void update_dispatch(integral_constant<int, 1>) { - base_t::template update<F1, F2, V>(); + base_type::template update<F1, F2, V>(); } // else template <field F1, field F2, char V> @@ -1081,165 +1177,9 @@ private: {} }; -// OPERATORS - -template <typename Mask1, typename Mask2> inline -boost::tuples::cons< - Mask1, - boost::tuples::cons<Mask2, boost::tuples::null_type> -> -operator||(Mask1 const& m1, Mask2 const& m2) -{ - namespace bt = boost::tuples; - - return - bt::cons< Mask1, bt::cons<Mask2, bt::null_type> > - ( m1, bt::cons<Mask2, bt::null_type>(m2, bt::null_type()) ); -} - -template <typename Head, typename Tail, typename Mask> inline -typename index::detail::tuples::push_back< - boost::tuples::cons<Head, Tail>, Mask ->::type -operator||(boost::tuples::cons<Head, Tail> const& t, Mask const& m) -{ - namespace bt = boost::tuples; - - return - index::detail::tuples::push_back< - bt::cons<Head, Tail>, Mask - >::apply(t, m); -} - -// PREDEFINED MASKS - -// TODO: -// 1. specialize for simplified masks if available -// e.g. for TOUCHES use 1 mask for A/A -// 2. Think about dimensions > 2 e.g. should TOUCHES be true -// if the interior of the Areal overlaps the boundary of the Volumetric -// like it's true for Linear/Areal - -// EQUALS -template <typename Geometry1, typename Geometry2> -struct static_mask_equals_type -{ - typedef static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia - //typedef static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC -}; - -// DISJOINT -typedef static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> static_mask_disjoint; +// --------------- UTIL FUNCTIONS ---------------- -// TOUCHES - NOT P/P -template <typename Geometry1, - typename Geometry2, - std::size_t Dim1 = topological_dimension<Geometry1>::value, - std::size_t Dim2 = topological_dimension<Geometry2>::value> -struct static_mask_touches_impl -{ - typedef boost::mpl::vector< - static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>, - static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>, - static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'> - > type; -}; -// According to OGC, doesn't apply to P/P -// Using the above mask the result would be always false -template <typename Geometry1, typename Geometry2> -struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0> - : not_implemented<typename geometry::tag<Geometry1>::type, - typename geometry::tag<Geometry2>::type> -{}; - -template <typename Geometry1, typename Geometry2> -struct static_mask_touches_type - : static_mask_touches_impl<Geometry1, Geometry2> -{}; - -// WITHIN -typedef static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> static_mask_within; - -// COVERED_BY (non OGC) -typedef boost::mpl::vector< - static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>, - static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>, - static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>, - static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'> - > static_mask_covered_by; - -// CROSSES -// dim(G1) < dim(G2) - P/L P/A L/A -template <typename Geometry1, - typename Geometry2, - std::size_t Dim1 = topological_dimension<Geometry1>::value, - std::size_t Dim2 = topological_dimension<Geometry2>::value, - bool D1LessD2 = (Dim1 < Dim2) -> -struct static_mask_crosses_impl -{ - typedef static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type; -}; -// TODO: I'm not sure if this one below should be available! -// dim(G1) > dim(G2) - L/P A/P A/L -template <typename Geometry1, typename Geometry2, - std::size_t Dim1, std::size_t Dim2 -> -struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false> -{ - typedef static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type; -}; -// dim(G1) == dim(G2) - P/P A/A -template <typename Geometry1, typename Geometry2, - std::size_t Dim -> -struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false> - : not_implemented<typename geometry::tag<Geometry1>::type, - typename geometry::tag<Geometry2>::type> -{}; -// dim(G1) == 1 && dim(G2) == 1 - L/L -template <typename Geometry1, typename Geometry2> -struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false> -{ - typedef static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type; -}; - -template <typename Geometry1, typename Geometry2> -struct static_mask_crosses_type - : static_mask_crosses_impl<Geometry1, Geometry2> -{}; - -// OVERLAPS - -// dim(G1) != dim(G2) - NOT P/P, L/L, A/A -template <typename Geometry1, - typename Geometry2, - std::size_t Dim1 = topological_dimension<Geometry1>::value, - std::size_t Dim2 = topological_dimension<Geometry2>::value -> -struct static_mask_overlaps_impl - : not_implemented<typename geometry::tag<Geometry1>::type, - typename geometry::tag<Geometry2>::type> -{}; -// dim(G1) == D && dim(G2) == D - P/P A/A -template <typename Geometry1, typename Geometry2, std::size_t Dim> -struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim> -{ - typedef static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; -}; -// dim(G1) == 1 && dim(G2) == 1 - L/L -template <typename Geometry1, typename Geometry2> -struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1> -{ - typedef static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; -}; - -template <typename Geometry1, typename Geometry2> -struct static_mask_overlaps_type - : static_mask_overlaps_impl<Geometry1, Geometry2> -{}; - -// RESULTS/HANDLERS UTILS +// set template <field F1, field F2, char V, typename Result> inline void set(Result & res) @@ -1273,33 +1213,7 @@ inline void set(Result & res) set_dispatch<F1, F2, V, Transpose>::apply(res); } -template <char V, typename Result> -inline void set(Result & res) -{ - res.template set<interior, interior, V>(); - res.template set<interior, boundary, V>(); - res.template set<interior, exterior, V>(); - res.template set<boundary, interior, V>(); - res.template set<boundary, boundary, V>(); - res.template set<boundary, exterior, V>(); - res.template set<exterior, interior, V>(); - res.template set<exterior, boundary, V>(); - res.template set<exterior, exterior, V>(); -} - -template <char II, char IB, char IE, char BI, char BB, char BE, char EI, char EB, char EE, typename Result> -inline void set(Result & res) -{ - res.template set<interior, interior, II>(); - res.template set<interior, boundary, IB>(); - res.template set<interior, exterior, IE>(); - res.template set<boundary, interior, BI>(); - res.template set<boundary, boundary, BB>(); - res.template set<boundary, exterior, BE>(); - res.template set<exterior, interior, EI>(); - res.template set<exterior, boundary, EB>(); - res.template set<exterior, exterior, EE>(); -} +// update template <field F1, field F2, char D, typename Result> inline void update(Result & res) @@ -1333,6 +1247,8 @@ inline void update(Result & res) update_result_dispatch<F1, F2, D, Transpose>::apply(res); } +// may_update + template <field F1, field F2, char D, typename Result> inline bool may_update(Result const& res) { @@ -1365,13 +1281,7 @@ inline bool may_update(Result const& res) return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res); } -template <typename Result, char II, char IB, char IE, char BI, char BB, char BE, char EI, char EB, char EE> -inline Result return_result() -{ - Result res; - set<II, IB, IE, BI, BB, BE, EI, EB, EE>(res); - return res; -} +// result_dimension template <typename Geometry> struct result_dimension diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp index 636c9756d8..d54948e1f5 100644 --- a/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/boost/geometry/algorithms/detail/relate/turns.hpp @@ -84,14 +84,30 @@ struct get_turns Geometry2 const& geometry2, InterruptPolicy & interrupt_policy) { - static const bool reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value; - static const bool reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value; - RobustPolicy robust_policy = geometry::get_rescale_policy < RobustPolicy >(geometry1, geometry2); + apply(turns, geometry1, geometry2, interrupt_policy, robust_policy); + } + + template <typename Turns, typename InterruptPolicy> + static inline void apply(Turns & turns, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + InterruptPolicy & interrupt_policy, + RobustPolicy const& robust_policy) + { + static const bool reverse1 = detail::overlay::do_reverse + < + geometry::point_order<Geometry1>::value + >::value; + + static const bool reverse2 = detail::overlay::do_reverse + < + geometry::point_order<Geometry2>::value + >::value; dispatch::get_turns < @@ -255,9 +271,14 @@ struct less { static LessOp less_op; - return left.operations[OpId].fraction < right.operations[OpId].fraction - || ( left.operations[OpId].fraction == right.operations[OpId].fraction - && less_op(left, right) ); + return + geometry::math::equals(left.operations[OpId].fraction, + right.operations[OpId].fraction) + ? + less_op(left, right) + : + (left.operations[OpId].fraction < right.operations[OpId].fraction) + ; } template <typename Turn> diff --git a/boost/geometry/algorithms/detail/relation/implementation.hpp b/boost/geometry/algorithms/detail/relation/implementation.hpp new file mode 100644 index 0000000000..b9a238d6c8 --- /dev/null +++ b/boost/geometry/algorithms/detail/relation/implementation.hpp @@ -0,0 +1,18 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP + + +#include <boost/geometry/algorithms/detail/relate/implementation.hpp> + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP diff --git a/boost/geometry/algorithms/detail/relation/interface.hpp b/boost/geometry/algorithms/detail/relation/interface.hpp new file mode 100644 index 0000000000..73737cf2c2 --- /dev/null +++ b/boost/geometry/algorithms/detail/relation/interface.hpp @@ -0,0 +1,186 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_INTERFACE_HPP + + +#include <boost/geometry/algorithms/detail/relate/interface.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate +{ + +template <typename Geometry1, typename Geometry2> +struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix, false> +{ + typedef matrix_handler<geometry::de9im::matrix> type; +}; + + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + + +namespace resolve_variant +{ + +template <typename Geometry1, typename Geometry2> +struct relation +{ + template <typename Matrix> + static inline Matrix apply(Geometry1 const& geometry1, + Geometry2 const& geometry2) + { + concept::check<Geometry1 const>(); + concept::check<Geometry2 const>(); + assert_dimension_equal<Geometry1, Geometry2>(); + + typename detail::relate::result_handler_type + < + Geometry1, + Geometry2, + Matrix + >::type handler; + + dispatch::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, handler); + + return handler.result(); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2> +struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2> +{ + template <typename Matrix> + struct visitor : boost::static_visitor<Matrix> + { + Geometry2 const& m_geometry2; + + visitor(Geometry2 const& geometry2) + : m_geometry2(geometry2) {} + + template <typename Geometry1> + Matrix operator()(Geometry1 const& geometry1) const + { + return relation<Geometry1, Geometry2> + ::template apply<Matrix>(geometry1, m_geometry2); + } + }; + + template <typename Matrix> + static inline Matrix + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1, + Geometry2 const& geometry2) + { + return boost::apply_visitor(visitor<Matrix>(geometry2), geometry1); + } +}; + +template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Matrix> + struct visitor : boost::static_visitor<Matrix> + { + Geometry1 const& m_geometry1; + + visitor(Geometry1 const& geometry1) + : m_geometry1(geometry1) {} + + template <typename Geometry2> + Matrix operator()(Geometry2 const& geometry2) const + { + return relation<Geometry1, Geometry2> + ::template apply<Matrix>(m_geometry1, geometry2); + } + }; + + template <typename Matrix> + static inline Matrix + apply(Geometry1 const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2) + { + return boost::apply_visitor(visitor<Matrix>(geometry1), geometry2); + } +}; + +template +< + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2) +> +struct relation + < + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> + > +{ + template <typename Matrix> + struct visitor : boost::static_visitor<Matrix> + { + template <typename Geometry1, typename Geometry2> + Matrix operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return relation<Geometry1, Geometry2> + ::template apply<Matrix>(geometry1, geometry2); + } + }; + + template <typename Matrix> + static inline Matrix + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1, + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2) + { + return boost::apply_visitor(visitor<Matrix>(), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief Calculates the relation between a pair of geometries as defined in DE-9IM. +\ingroup relation +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\return The DE-9IM matrix expressing the relation between geometries. + +\qbk{[include reference/algorithms/relation.qbk]} + */ +template <typename Geometry1, typename Geometry2> +inline de9im::matrix relation(Geometry1 const& geometry1, + Geometry2 const& geometry2) +{ + return resolve_variant::relation + < + Geometry1, + Geometry2 + >::template apply<de9im::matrix>(geometry1, geometry2); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP diff --git a/boost/geometry/algorithms/detail/result_inverse.hpp b/boost/geometry/algorithms/detail/result_inverse.hpp new file mode 100644 index 0000000000..01a1997e49 --- /dev/null +++ b/boost/geometry/algorithms/detail/result_inverse.hpp @@ -0,0 +1,44 @@ +// Boost.Geometry + +// Copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP + + +#include <boost/math/constants/constants.hpp> + +#include <boost/geometry/core/radius.hpp> +#include <boost/geometry/core/srs.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/geometry/algorithms/detail/flattening.hpp> + + +namespace boost { namespace geometry { namespace detail +{ + +template <typename T> +struct result_inverse +{ + void set(T const& d, T const& a) + { + distance = d; + azimuth = a; + } + + T distance; + T azimuth; +}; + +}}} // namespace boost::geometry::detail + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP diff --git a/boost/geometry/algorithms/detail/ring_identifier.hpp b/boost/geometry/algorithms/detail/ring_identifier.hpp index bc3fe1fef3..9ba39e4a8b 100644 --- a/boost/geometry/algorithms/detail/ring_identifier.hpp +++ b/boost/geometry/algorithms/detail/ring_identifier.hpp @@ -15,7 +15,7 @@ #endif -#include <boost/geometry/algorithms/detail/signed_index_type.hpp> +#include <boost/geometry/algorithms/detail/signed_size_type.hpp> namespace boost { namespace geometry @@ -32,9 +32,9 @@ struct ring_identifier , ring_index(-1) {} - inline ring_identifier(signed_index_type src, - signed_index_type mul, - signed_index_type rin) + inline ring_identifier(signed_size_type src, + signed_size_type mul, + signed_size_type rin) : source_index(src) , multi_index(mul) , ring_index(rin) @@ -68,9 +68,9 @@ struct ring_identifier #endif - signed_index_type source_index; - signed_index_type multi_index; - signed_index_type ring_index; + signed_size_type source_index; + signed_size_type multi_index; + signed_size_type ring_index; }; diff --git a/boost/geometry/algorithms/detail/sections/range_by_section.hpp b/boost/geometry/algorithms/detail/sections/range_by_section.hpp index d139a3fdd2..02cec6cb48 100644 --- a/boost/geometry/algorithms/detail/sections/range_by_section.hpp +++ b/boost/geometry/algorithms/detail/sections/range_by_section.hpp @@ -19,11 +19,11 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP -#include <boost/assert.hpp> #include <boost/mpl/assert.hpp> #include <boost/range.hpp> #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> @@ -77,7 +77,7 @@ struct full_section_multi { typedef typename boost::range_size<MultiGeometry>::type size_type; - BOOST_ASSERT + BOOST_GEOMETRY_ASSERT ( section.ring_id.multi_index >= 0 && size_type(section.ring_id.multi_index) < boost::size(multi) diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp index a744ea0a34..1ced394353 100644 --- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -1,12 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014. -// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -36,6 +36,7 @@ #include <boost/geometry/algorithms/detail/interior_iterator.hpp> #include <boost/geometry/algorithms/detail/recalculate.hpp> #include <boost/geometry/algorithms/detail/ring_identifier.hpp> +#include <boost/geometry/algorithms/detail/signed_size_type.hpp> #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/closure.hpp> @@ -80,12 +81,14 @@ struct section ring_identifier ring_id; Box bounding_box; - int begin_index; - int end_index; + // NOTE: size_type could be passed as template parameter + // NOTE: these probably also could be of type std::size_t + signed_size_type begin_index; + signed_size_type end_index; std::size_t count; std::size_t range_count; bool duplicate; - int non_duplicate_index; + signed_size_type non_duplicate_index; bool is_non_duplicate_first; bool is_non_duplicate_last; @@ -248,7 +251,7 @@ struct check_duplicate_loop<DimensionCount, DimensionCount> template <typename T, std::size_t Index, std::size_t Count> struct assign_loop { - static inline void apply(T dims[Count], int const value) + static inline void apply(T dims[Count], T const value) { dims[Index] = value; assign_loop<T, Index + 1, Count>::apply(dims, value); @@ -258,7 +261,7 @@ struct assign_loop template <typename T, std::size_t Count> struct assign_loop<T, Count, Count> { - static inline void apply(T [Count], int const) + static inline void apply(T [Count], T const) { } }; @@ -291,8 +294,8 @@ struct sectionalize_part typedef typename boost::range_value<Sections>::type section_type; BOOST_STATIC_ASSERT ( - (static_cast<int>(section_type::dimension_count) - == static_cast<int>(boost::mpl::size<DimensionVector>::value)) + (static_cast<std::size_t>(section_type::dimension_count) + == static_cast<std::size_t>(boost::mpl::size<DimensionVector>::value)) ); typedef typename geometry::robust_point_type @@ -307,8 +310,8 @@ struct sectionalize_part return; } - int index = 0; - int ndi = 0; // non duplicate index + signed_size_type index = 0; + signed_size_type ndi = 0; // non duplicate index section_type section; bool mark_first_non_duplicated = true; diff --git a/boost/geometry/algorithms/detail/signed_index_type.hpp b/boost/geometry/algorithms/detail/signed_size_type.hpp index 36dcf4de4c..db7344ec80 100644 --- a/boost/geometry/algorithms/detail/signed_index_type.hpp +++ b/boost/geometry/algorithms/detail/signed_size_type.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -8,8 +8,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_INDEX_TYPE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_INDEX_TYPE_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP #include <cstddef> @@ -20,10 +20,9 @@ namespace boost { namespace geometry { -typedef boost::make_signed<std::size_t>::type signed_index_type; -//typedef std::ptrdiff_t signed_index_type; +typedef boost::make_signed<std::size_t>::type signed_size_type; }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_INDEX_TYPE_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP diff --git a/boost/geometry/algorithms/detail/single_geometry.hpp b/boost/geometry/algorithms/detail/single_geometry.hpp index f38295ada6..31e4401099 100644 --- a/boost/geometry/algorithms/detail/single_geometry.hpp +++ b/boost/geometry/algorithms/detail/single_geometry.hpp @@ -14,7 +14,10 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SINGLE_GEOMETRY_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SINGLE_GEOMETRY_HPP +#include <boost/mpl/if.hpp> #include <boost/type_traits/is_base_of.hpp> + +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/util/range.hpp> @@ -44,17 +47,12 @@ struct single_geometry template <typename Geometry> struct single_geometry<Geometry, true> { - typedef typename boost::mpl::if_c - < - boost::is_const<Geometry>::value, - typename boost::range_value<Geometry>::type const&, - typename boost::range_value<Geometry>::type - >::type return_type; + typedef typename boost::range_reference<Geometry>::type return_type; template <typename Id> static inline return_type apply(Geometry & g, Id const& id) { - BOOST_ASSERT(id.multi_index >= 0); + BOOST_GEOMETRY_ASSERT(id.multi_index >= 0); typedef typename boost::range_size<Geometry>::type size_type; return range::at(g, static_cast<size_type>(id.multi_index)); } diff --git a/boost/geometry/algorithms/detail/sub_range.hpp b/boost/geometry/algorithms/detail/sub_range.hpp index eda3ce58ba..29edc94e6c 100644 --- a/boost/geometry/algorithms/detail/sub_range.hpp +++ b/boost/geometry/algorithms/detail/sub_range.hpp @@ -14,6 +14,9 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP +#include <boost/mpl/if.hpp> + +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/util/range.hpp> namespace boost { namespace geometry { @@ -84,7 +87,7 @@ struct sub_range<Geometry, Tag, true> template <typename Id> static inline return_type apply(Geometry & geometry, Id const& id) { - BOOST_ASSERT(0 <= id.multi_index); + BOOST_GEOMETRY_ASSERT(0 <= id.multi_index); typedef typename boost::range_size<Geometry>::type size_type; size_type const mi = static_cast<size_type>(id.multi_index); return sub_sub_range::apply(range::at(geometry, mi), id); @@ -111,6 +114,13 @@ sub_range(Geometry & geometry, Id const& id) return detail_dispatch::sub_range<Geometry>::apply(geometry, id); } +template <typename Geometry, typename Id> inline +typename sub_range_return_type<Geometry const>::type +sub_range(Geometry const& geometry, Id const& id) +{ + return detail_dispatch::sub_range<Geometry const>::apply(geometry, id); +} + } // namespace detail #endif // DOXYGEN_NO_DETAIL diff --git a/boost/geometry/algorithms/detail/sweep.hpp b/boost/geometry/algorithms/detail/sweep.hpp new file mode 100644 index 0000000000..3dc78261f2 --- /dev/null +++ b/boost/geometry/algorithms/detail/sweep.hpp @@ -0,0 +1,87 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP + +#include <boost/core/ignore_unused.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace sweep +{ + +struct no_interrupt_policy +{ + static bool const enabled = false; + + template <typename Event> + static inline bool apply(Event const&) + { + return false; + } +}; + +}} // namespace detail::sweep +#endif // DOXYGEN_NO_DETAIL + + +template +< + typename Range, + typename PriorityQueue, + typename InitializationVisitor, + typename EventVisitor, + typename InterruptPolicy +> +inline void sweep(Range const& range, PriorityQueue& queue, + InitializationVisitor& initialization_visitor, + EventVisitor& event_visitor, + InterruptPolicy const& interrupt_policy) +{ + typedef typename PriorityQueue::value_type event_type; + + initialization_visitor.apply(range, queue, event_visitor); + while (! queue.empty()) + { + event_type event = queue.top(); + queue.pop(); + event_visitor.apply(event, queue); + if (interrupt_policy.enabled && interrupt_policy.apply(event)) + { + break; + } + } + + boost::ignore_unused(interrupt_policy); +} + + +template +< + typename Range, + typename PriorityQueue, + typename InitializationVisitor, + typename EventVisitor +> +inline void sweep(Range const& range, PriorityQueue& queue, + InitializationVisitor& initialization_visitor, + EventVisitor& event_visitor) +{ + sweep(range, queue, initialization_visitor, event_visitor, + detail::sweep::no_interrupt_policy()); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP diff --git a/boost/geometry/algorithms/detail/thomas_inverse.hpp b/boost/geometry/algorithms/detail/thomas_inverse.hpp new file mode 100644 index 0000000000..96b237e054 --- /dev/null +++ b/boost/geometry/algorithms/detail/thomas_inverse.hpp @@ -0,0 +1,191 @@ +// Boost.Geometry + +// Copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP + + +#include <boost/math/constants/constants.hpp> + +#include <boost/geometry/core/radius.hpp> +#include <boost/geometry/core/srs.hpp> + +#include <boost/geometry/util/condition.hpp> +#include <boost/geometry/util/math.hpp> + +#include <boost/geometry/algorithms/detail/flattening.hpp> +#include <boost/geometry/algorithms/detail/result_inverse.hpp> + +namespace boost { namespace geometry { namespace detail +{ + +/*! +\brief The solution of the inverse problem of geodesics on latlong coordinates, + Forsyth-Andoyer-Lambert type approximation with second order terms. +\author See + - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965 + http://www.dtic.mil/docs/citations/AD0627893 + - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970 + http://www.dtic.mil/docs/citations/AD703541 +*/ +template <typename CT, bool EnableDistance, bool EnableAzimuth> +struct thomas_inverse +{ + typedef result_inverse<CT> result_type; + + template <typename T1, typename T2, typename Spheroid> + static inline result_type apply(T1 const& lon1, + T1 const& lat1, + T2 const& lon2, + T2 const& lat2, + Spheroid const& spheroid) + { + result_type result; + + // coordinates in radians + + if ( math::equals(lon1, lon2) + && math::equals(lat1, lat2) ) + { + result.set(CT(0), CT(0)); + return result; + } + + CT const f = detail::flattening<CT>(spheroid); + CT const one_minus_f = CT(1) - f; + +// CT const tan_theta1 = one_minus_f * tan(lat1); +// CT const tan_theta2 = one_minus_f * tan(lat2); +// CT const theta1 = atan(tan_theta1); +// CT const theta2 = atan(tan_theta2); + + CT const pi_half = math::pi<CT>() / CT(2); + CT const theta1 = math::equals(lat1, pi_half) ? lat1 : + math::equals(lat1, -pi_half) ? lat1 : + atan(one_minus_f * tan(lat1)); + CT const theta2 = math::equals(lat2, pi_half) ? lat2 : + math::equals(lat2, -pi_half) ? lat2 : + atan(one_minus_f * tan(lat2)); + + CT const theta_m = (theta1 + theta2) / CT(2); + CT const d_theta_m = (theta2 - theta1) / CT(2); + CT const d_lambda = lon2 - lon1; + CT const d_lambda_m = d_lambda / CT(2); + + CT const sin_theta_m = sin(theta_m); + CT const cos_theta_m = cos(theta_m); + CT const sin_d_theta_m = sin(d_theta_m); + CT const cos_d_theta_m = cos(d_theta_m); + CT const sin2_theta_m = math::sqr(sin_theta_m); + CT const cos2_theta_m = math::sqr(cos_theta_m); + CT const sin2_d_theta_m = math::sqr(sin_d_theta_m); + CT const cos2_d_theta_m = math::sqr(cos_d_theta_m); + CT const sin_d_lambda_m = sin(d_lambda_m); + CT const sin2_d_lambda_m = math::sqr(sin_d_lambda_m); + + CT const H = cos2_theta_m - sin2_d_theta_m; + CT const L = sin2_d_theta_m + H * sin2_d_lambda_m; + CT const cos_d = CT(1) - CT(2) * L; + CT const d = acos(cos_d); + CT const sin_d = sin(d); + + CT const one_minus_L = CT(1) - L; + + if ( math::equals(sin_d, CT(0)) + || math::equals(L, CT(0)) + || math::equals(one_minus_L, CT(0)) ) + { + result.set(CT(0), CT(0)); + return result; + } + + CT const U = CT(2) * sin2_theta_m * cos2_d_theta_m / one_minus_L; + CT const V = CT(2) * sin2_d_theta_m * cos2_theta_m / L; + CT const X = U + V; + CT const Y = U - V; + CT const T = d / sin_d; + //CT const D = CT(4) * math::sqr(T); + //CT const E = CT(2) * cos_d; + //CT const A = D * E; + //CT const B = CT(2) * D; + //CT const C = T - (A - E) / CT(2); + + if ( BOOST_GEOMETRY_CONDITION(EnableDistance) ) + { + //CT const n1 = X * (A + C*X); + //CT const n2 = Y * (B + E*Y); + //CT const n3 = D*X*Y; + + //CT const f_sqr = math::sqr(f); + //CT const f_sqr_per_64 = f_sqr / CT(64); + + CT const delta1d = f * (T*X-Y) / CT(4); + //CT const delta2d = f_sqr_per_64 * (n1 - n2 + n3); + + CT const a = get_radius<0>(spheroid); + + result.distance = a * sin_d * (T - delta1d); + //double S2 = a * sin_d * (T - delta1d + delta2d); + } + else + { + result.distance = CT(0); + } + + if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) ) + { + // NOTE: if both cos_latX == 0 then below we'd have 0 * INF + // it's a situation when the endpoints are on the poles +-90 deg + // in this case the azimuth could either be 0 or +-pi + // but above always 0 is returned + + // may also be used to calculate distance21 + //CT const D = CT(4) * math::sqr(T); + CT const E = CT(2) * cos_d; + //CT const A = D * E; + //CT const B = CT(2) * D; + // may also be used to calculate distance21 + CT const f_sqr = math::sqr(f); + CT const f_sqr_per_64 = f_sqr / CT(64); + + CT const F = CT(2)*Y-E*(CT(4)-X); + //CT const M = CT(32)*T-(CT(20)*T-A)*X-(B+CT(4))*Y; + CT const G = f*T/CT(2) + f_sqr_per_64; + CT const tan_d_lambda = tan(d_lambda); + CT const Q = -(F*G*tan_d_lambda) / CT(4); + + CT const d_lambda_p = (d_lambda + Q) / CT(2); + CT const tan_d_lambda_p = tan(d_lambda_p); + + CT const v = atan2(cos_d_theta_m, sin_theta_m * tan_d_lambda_p); + CT const u = atan2(-sin_d_theta_m, cos_theta_m * tan_d_lambda_p); + + CT const pi = math::pi<CT>(); + CT alpha1 = v + u; + if ( alpha1 > pi ) + { + alpha1 -= CT(2) * pi; + } + + result.azimuth = alpha1; + } + else + { + result.azimuth = CT(0); + } + + return result; + } +}; + +}}} // namespace boost::geometry::detail + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP diff --git a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp index 21f5fe40b7..2f82e1a8bd 100644 --- a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp +++ b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp @@ -1,8 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -12,7 +17,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP #include <boost/geometry/core/exception.hpp> -#include <boost/geometry/algorithms/num_points.hpp> +#include <boost/geometry/algorithms/is_empty.hpp> // BSG 2012-02-06: we use this currently only for distance. // For other scalar results area,length,perimeter it is commented on purpose. @@ -39,7 +44,7 @@ template <typename Geometry> inline void throw_on_empty_input(Geometry const& geometry) { #if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW) - if (geometry::num_points(geometry) == 0) + if (geometry::is_empty(geometry)) { throw empty_input_exception(); } diff --git a/boost/geometry/algorithms/detail/turns/compare_turns.hpp b/boost/geometry/algorithms/detail/turns/compare_turns.hpp index c29d5863b7..ec383bf103 100644 --- a/boost/geometry/algorithms/detail/turns/compare_turns.hpp +++ b/boost/geometry/algorithms/detail/turns/compare_turns.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2015, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -30,7 +30,7 @@ namespace detail { namespace turns // seg_id -> fraction -> other_id -> operation template < - typename IdLess = std::less<signed_index_type>, + typename IdLess = std::less<signed_size_type>, int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0, std::size_t OpId = 0 > @@ -85,10 +85,14 @@ struct less_seg_fraction_other_op template <typename Turn> static inline bool use_fraction(Turn const& left, Turn const& right) { - return left.operations[OpId].fraction < right.operations[OpId].fraction - || ( geometry::math::equals(left.operations[OpId].fraction, right.operations[OpId].fraction) - && use_other_id(left, right) - ); + return + geometry::math::equals(left.operations[OpId].fraction, + right.operations[OpId].fraction) + ? + use_other_id(left, right) + : + (left.operations[OpId].fraction < right.operations[OpId].fraction) + ; } template <typename Turn> diff --git a/boost/geometry/algorithms/detail/turns/print_turns.hpp b/boost/geometry/algorithms/detail/turns/print_turns.hpp index 9d4e45c41f..1e9b9df409 100644 --- a/boost/geometry/algorithms/detail/turns/print_turns.hpp +++ b/boost/geometry/algorithms/detail/turns/print_turns.hpp @@ -56,7 +56,7 @@ struct turn_printer <<": seg: " << turn.operations[0].seg_id.source_index << ", m: " << turn.operations[0].seg_id.multi_index << ", r: " << turn.operations[0].seg_id.ring_index - << ", s: " << turn.operations[0].seg_id.segment_index << ", "; + << ", s: " << turn.operations[0].seg_id.segment_index; out << ", fr: " << fraction[0]; out << ", col?: " << turn.operations[0].is_collinear; out << ' ' << geometry::dsv(turn.point) << ' '; @@ -70,7 +70,7 @@ struct turn_printer << ": seg: " << turn.operations[1].seg_id.source_index << ", m: " << turn.operations[1].seg_id.multi_index << ", r: " << turn.operations[1].seg_id.ring_index - << ", s: " << turn.operations[1].seg_id.segment_index << ", "; + << ", s: " << turn.operations[1].seg_id.segment_index; out << ", fr: " << fraction[1]; out << ", col?: " << turn.operations[1].is_collinear; out << ' ' << geometry::dsv(turn.point) << ' '; diff --git a/boost/geometry/algorithms/detail/vincenty_direct.hpp b/boost/geometry/algorithms/detail/vincenty_direct.hpp index 775687cfdb..1c47a0f68d 100644 --- a/boost/geometry/algorithms/detail/vincenty_direct.hpp +++ b/boost/geometry/algorithms/detail/vincenty_direct.hpp @@ -33,6 +33,18 @@ namespace boost { namespace geometry { namespace detail { +template <typename T> +struct result_direct +{ + void set(T const& lo2, T const& la2) + { + lon2 = lo2; + lat2 = la2; + } + T lon2; + T lat2; +}; + /*! \brief The solution of the direct problem of geodesics on latlong coordinates, after Vincenty, 1975 \author See @@ -45,45 +57,49 @@ namespace boost { namespace geometry { namespace detail */ template <typename CT> -class vincenty_direct +struct vincenty_direct { + typedef result_direct<CT> result_type; + public: template <typename T, typename Dist, typename Azi, typename Spheroid> - vincenty_direct(T const& lo1, - T const& la1, - Dist const& distance, - Azi const& azimuth12, - Spheroid const& spheroid) - : lon1(lo1) - , lat1(la1) - , is_distance_zero(false) + static inline result_type apply(T const& lo1, + T const& la1, + Dist const& distance, + Azi const& azimuth12, + Spheroid const& spheroid) { + result_type result; + + CT const lon1 = lo1; + CT const lat1 = la1; + if ( math::equals(distance, Dist(0)) || distance < Dist(0) ) { - is_distance_zero = true; - return; + result.set(lon1, lat1); + return result; } CT const radius_a = CT(get_radius<0>(spheroid)); CT const radius_b = CT(get_radius<2>(spheroid)); - flattening = geometry::detail::flattening<CT>(spheroid); + CT const flattening = geometry::detail::flattening<CT>(spheroid); - sin_azimuth12 = sin(azimuth12); - cos_azimuth12 = cos(azimuth12); + CT const sin_azimuth12 = sin(azimuth12); + CT const cos_azimuth12 = cos(azimuth12); // U: reduced latitude, defined by tan U = (1-f) tan phi - one_min_f = CT(1) - flattening; + CT const one_min_f = CT(1) - flattening; CT const tan_U1 = one_min_f * tan(lat1); CT const sigma1 = atan2(tan_U1, cos_azimuth12); // (1) // may be calculated from tan using 1 sqrt() CT const U1 = atan(tan_U1); - sin_U1 = sin(U1); - cos_U1 = cos(U1); + CT const sin_U1 = sin(U1); + CT const cos_U1 = cos(U1); - sin_alpha = cos_U1 * sin_azimuth12; // (2) - sin_alpha_sqr = math::sqr(sin_alpha); - cos_alpha_sqr = CT(1) - sin_alpha_sqr; + CT const sin_alpha = cos_U1 * sin_azimuth12; // (2) + CT const sin_alpha_sqr = math::sqr(sin_alpha); + CT const cos_alpha_sqr = CT(1) - sin_alpha_sqr; CT const b_sqr = radius_b * radius_b; CT const u_sqr = cos_alpha_sqr * (radius_a * radius_a - b_sqr) / b_sqr; @@ -91,9 +107,13 @@ public: CT const B = (u_sqr/CT(1024))*(CT(256) + u_sqr*(CT(-128) + u_sqr*(CT(74) - u_sqr*CT(47)))); // (4) CT s_div_bA = distance / (radius_b * A); - sigma = s_div_bA; // (7) + CT sigma = s_div_bA; // (7) CT previous_sigma; + CT sin_sigma; + CT cos_sigma; + CT cos_2sigma_m; + CT cos_2sigma_m_sqr; int counter = 0; // robustness @@ -120,35 +140,27 @@ public: } while ( geometry::math::abs(previous_sigma - sigma) > CT(1e-12) //&& geometry::math::abs(sigma) < pi && counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness - } - inline CT lat2() const - { - if ( is_distance_zero ) { - return lat1; + result.lat2 + = atan2( sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_azimuth12, + one_min_f * math::sqrt(sin_alpha_sqr + math::sqr(sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12))); // (8) } - return atan2( sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_azimuth12, - one_min_f * math::sqrt(sin_alpha_sqr + math::sqr(sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12))); // (8) - } - - inline CT lon2() const - { - if ( is_distance_zero ) { - return lon1; - } + CT const lambda = atan2( sin_sigma * sin_azimuth12, + cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_azimuth12); // (9) + CT const C = (flattening/CT(16)) * cos_alpha_sqr * ( CT(4) + flattening * ( CT(4) - CT(3) * cos_alpha_sqr ) ); // (10) + CT const L = lambda - (CT(1) - C) * flattening * sin_alpha + * ( sigma + C * sin_sigma * ( cos_2sigma_m + C * cos_sigma * ( CT(-1) + CT(2) * cos_2sigma_m_sqr ) ) ); // (11) - CT const lambda = atan2( sin_sigma * sin_azimuth12, - cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_azimuth12); // (9) - CT const C = (flattening/CT(16)) * cos_alpha_sqr * ( CT(4) + flattening * ( CT(4) - CT(3) * cos_alpha_sqr ) ); // (10) - CT const L = lambda - (CT(1) - C) * flattening * sin_alpha - * ( sigma + C * sin_sigma * ( cos_2sigma_m + C * cos_sigma * ( CT(-1) + CT(2) * cos_2sigma_m_sqr ) ) ); // (11) + result.lon2 = lon1 + L; + } - return lon1 + L; + return result; } + /* inline CT azimuth21() const { // NOTE: signs of X and Y are different than in the original paper @@ -156,32 +168,7 @@ public: CT(0) : atan2(-sin_alpha, sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12); // (12) } - -private: - CT sigma; - CT sin_sigma; - CT cos_sigma; - - CT cos_2sigma_m; - CT cos_2sigma_m_sqr; - - CT sin_alpha; - CT sin_alpha_sqr; - CT cos_alpha_sqr; - - CT sin_azimuth12; - CT cos_azimuth12; - - CT sin_U1; - CT cos_U1; - - CT flattening; - CT one_min_f; - - CT const lon1; - CT const lat1; - - bool is_distance_zero; + */ }; }}} // namespace boost::geometry::detail diff --git a/boost/geometry/algorithms/detail/vincenty_inverse.hpp b/boost/geometry/algorithms/detail/vincenty_inverse.hpp index 861452af00..fe05e95932 100644 --- a/boost/geometry/algorithms/detail/vincenty_inverse.hpp +++ b/boost/geometry/algorithms/detail/vincenty_inverse.hpp @@ -20,9 +20,11 @@ #include <boost/geometry/core/radius.hpp> #include <boost/geometry/core/srs.hpp> +#include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/math.hpp> #include <boost/geometry/algorithms/detail/flattening.hpp> +#include <boost/geometry/algorithms/detail/result_inverse.hpp> #ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS @@ -44,22 +46,25 @@ namespace boost { namespace geometry { namespace detail - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink */ -template <typename CT> -class vincenty_inverse +template <typename CT, bool EnableDistance, bool EnableAzimuth> +struct vincenty_inverse { + typedef result_inverse<CT> result_type; + public: template <typename T1, typename T2, typename Spheroid> - vincenty_inverse(T1 const& lon1, - T1 const& lat1, - T2 const& lon2, - T2 const& lat2, - Spheroid const& spheroid) - : is_result_zero(false) + static inline result_type apply(T1 const& lon1, + T1 const& lat1, + T2 const& lon2, + T2 const& lat2, + Spheroid const& spheroid) { + result_type result; + if (math::equals(lat1, lat2) && math::equals(lon1, lon2)) { - is_result_zero = true; - return; + result.set(CT(0), CT(0)); + return result; } CT const c1 = 1; @@ -79,8 +84,8 @@ public: if (L < -pi) L += two_pi; if (L > pi) L -= two_pi; - radius_a = CT(get_radius<0>(spheroid)); - radius_b = CT(get_radius<2>(spheroid)); + CT const radius_a = CT(get_radius<0>(spheroid)); + CT const radius_b = CT(get_radius<2>(spheroid)); CT const flattening = geometry::detail::flattening<CT>(spheroid); // U: reduced latitude, defined by tan U = (1-f) tan phi @@ -92,11 +97,11 @@ public: CT const temp_den_U1 = math::sqrt(c1 + math::sqr(tan_U1)); CT const temp_den_U2 = math::sqrt(c1 + math::sqr(tan_U2)); // cos = 1 / sqrt(1 + tan^2) - cos_U1 = c1 / temp_den_U1; - cos_U2 = c1 / temp_den_U2; + CT const cos_U1 = c1 / temp_den_U1; + CT const cos_U2 = c1 / temp_den_U2; // sin = tan / sqrt(1 + tan^2) - sin_U1 = tan_U1 / temp_den_U1; - sin_U2 = tan_U2 / temp_den_U2; + CT const sin_U1 = tan_U1 / temp_den_U1; + CT const sin_U2 = tan_U2 / temp_den_U2; // calculate sin U and cos U directly //CT const U1 = atan(tan_U1); @@ -107,6 +112,13 @@ public: //sin_U2 = tan_U2 * cos_U2; // sin(U2); CT previous_lambda; + CT sin_lambda; + CT cos_lambda; + CT sin_sigma; + CT sin_alpha; + CT cos2_alpha; + CT cos2_sigma_m; + CT sigma; int counter = 0; // robustness @@ -131,85 +143,59 @@ public: } while ( geometry::math::abs(previous_lambda - lambda) > c_e_12 && geometry::math::abs(lambda) < pi && counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness - } - - inline CT distance() const - { - if ( is_result_zero ) + + if ( BOOST_GEOMETRY_CONDITION(EnableDistance) ) { - return CT(0); + // Oops getting hard here + // (again, problem is that ttmath cannot divide by doubles, which is OK) + CT const c1 = 1; + CT const c2 = 2; + CT const c3 = 3; + CT const c4 = 4; + CT const c6 = 6; + CT const c47 = 47; + CT const c74 = 74; + CT const c128 = 128; + CT const c256 = 256; + CT const c175 = 175; + CT const c320 = 320; + CT const c768 = 768; + CT const c1024 = 1024; + CT const c4096 = 4096; + CT const c16384 = 16384; + + //CT sqr_u = cos2_alpha * (math::sqr(radius_a) - math::sqr(radius_b)) / math::sqr(radius_b); // above (1) + CT sqr_u = cos2_alpha * ( math::sqr(radius_a / radius_b) - c1 ); // above (1) + + CT A = c1 + sqr_u/c16384 * (c4096 + sqr_u * (-c768 + sqr_u * (c320 - c175 * sqr_u))); // (3) + CT B = sqr_u/c1024 * (c256 + sqr_u * ( -c128 + sqr_u * (c74 - c47 * sqr_u))); // (4) + CT delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/c4) * (cos(sigma)* (-c1 + c2 * cos2_sigma_m) + - (B/c6) * cos2_sigma_m * (-c3 + c4 * math::sqr(sin_sigma)) * (-c3 + c4 * cos2_sigma_m))); // (6) + + result.distance = radius_b * A * (sigma - delta_sigma); // (19) + } + else + { + result.distance = CT(0); + } + + if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) ) + { + result.azimuth = atan2(cos_U2 * sin_lambda, cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); // (20) + } + else + { + result.azimuth = CT(0); } - // Oops getting hard here - // (again, problem is that ttmath cannot divide by doubles, which is OK) - CT const c1 = 1; - CT const c2 = 2; - CT const c3 = 3; - CT const c4 = 4; - CT const c6 = 6; - CT const c47 = 47; - CT const c74 = 74; - CT const c128 = 128; - CT const c256 = 256; - CT const c175 = 175; - CT const c320 = 320; - CT const c768 = 768; - CT const c1024 = 1024; - CT const c4096 = 4096; - CT const c16384 = 16384; - - //CT sqr_u = cos2_alpha * (math::sqr(radius_a) - math::sqr(radius_b)) / math::sqr(radius_b); // above (1) - CT sqr_u = cos2_alpha * ( math::sqr(radius_a / radius_b) - c1 ); // above (1) - - CT A = c1 + sqr_u/c16384 * (c4096 + sqr_u * (-c768 + sqr_u * (c320 - c175 * sqr_u))); // (3) - CT B = sqr_u/c1024 * (c256 + sqr_u * ( -c128 + sqr_u * (c74 - c47 * sqr_u))); // (4) - CT delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/c4) * (cos(sigma)* (-c1 + c2 * cos2_sigma_m) - - (B/c6) * cos2_sigma_m * (-c3 + c4 * math::sqr(sin_sigma)) * (-c3 + c4 * cos2_sigma_m))); // (6) - - return radius_b * A * (sigma - delta_sigma); // (19) - } - - inline CT azimuth12() const - { - return is_result_zero ? - CT(0) : - atan2(cos_U2 * sin_lambda, cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); // (20) - } - - inline CT azimuth21() const - { - // NOTE: signs of X and Y are different than in the original paper - return is_result_zero ? - CT(0) : - atan2(-cos_U1 * sin_lambda, sin_U1 * cos_U2 - cos_U1 * sin_U2 * cos_lambda); // (21) + return result; } -private: - // alpha: azimuth of the geodesic at the equator - CT cos2_alpha; - CT sin_alpha; - - // sigma: angular distance p1,p2 on the sphere - // sigma1: angular distance on the sphere from the equator to p1 - // sigma_m: angular distance on the sphere from the equator to the midpoint of the line - CT sigma; - CT sin_sigma; - CT cos2_sigma_m; - - CT sin_lambda; - CT cos_lambda; - - // set only once - CT cos_U1; - CT cos_U2; - CT sin_U1; - CT sin_U2; - - // set only once - CT radius_a; - CT radius_b; - - bool is_result_zero; +// inline CT azimuth21() const +// { +// // NOTE: signs of X and Y are different than in the original paper +// atan2(-cos_U1 * sin_lambda, sin_U1 * cos_U2 - cos_U1 * sin_U2 * cos_lambda); // (21) +// } }; }}} // namespace boost::geometry::detail diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp index e7486f0e45..68e74a8c5c 100644 --- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp +++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp @@ -20,13 +20,15 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP -#include <boost/assert.hpp> + #include <boost/core/ignore_unused.hpp> #include <boost/mpl/assert.hpp> #include <boost/range.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/remove_reference.hpp> +#include <boost/geometry/core/assert.hpp> + #include <boost/geometry/algorithms/detail/equals/point_point.hpp> #include <boost/geometry/algorithms/detail/interior_iterator.hpp> @@ -53,7 +55,7 @@ inline int check_result_type(int result) template <typename T> inline T check_result_type(T result) { - BOOST_ASSERT(false); + BOOST_GEOMETRY_ASSERT(false); return result; } @@ -291,7 +293,7 @@ struct point_in_geometry<Geometry, multi_point_tag> { int pip = point_in_geometry<point_type>::apply(point, *it, strategy); - //BOOST_ASSERT(pip != 0); + //BOOST_GEOMETRY_ASSERT(pip != 0); if ( pip > 0 ) // inside return 1; } |