diff --git a/include/boost/geometry/algorithms/detail/assign_values.hpp b/include/boost/geometry/algorithms/detail/assign_values.hpp index ef5691e97c..b9fdcc7414 100644 --- a/include/boost/geometry/algorithms/detail/assign_values.hpp +++ b/include/boost/geometry/algorithms/detail/assign_values.hpp @@ -92,6 +92,7 @@ struct assign_inverse_box_or_segment geometry, boost::numeric::bounds::lowest() ); } + }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp index fe849e1091..baa4cf83dd 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -64,10 +65,38 @@ struct disjoint_segment_box_sphere_or_spheroid public: + struct disjoint_info + { + enum type + { + intersect, + disjoint_no_vertex, + disjoint_vertex + }; + disjoint_info(type t) : m_(t){} + operator type () const {return m_;} + type m_; + private : + //prevent automatic conversion for any other built-in types + template + operator T () const; + }; + template static inline bool apply(Segment const& segment, Box const& box, Strategy const& azimuth_strategy) + { + typedef typename point_type::type segment_point; + segment_point vertex; + return (apply(segment, box, azimuth_strategy, vertex) != disjoint_info::intersect); + } + + template + static inline disjoint_info apply(Segment const& segment, + Box const& box, + Strategy const& azimuth_strategy, + P& vertex) { assert_dimension_equal(); @@ -78,12 +107,15 @@ struct disjoint_segment_box_sphere_or_spheroid geometry::detail::assign_point_from_index<0>(segment, p0); geometry::detail::assign_point_from_index<1>(segment, p1); + //vertex not computed here + disjoint_info disjoint_return_value = disjoint_info::disjoint_no_vertex; + // Simplest cases first // Case 1: if box contains one of segment's endpoints then they are not disjoint if (! disjoint_point_box(p0, box) || ! disjoint_point_box(p1, box)) { - return false; + return disjoint_info::intersect; } // Case 2: disjoint if bounding boxes are disjoint @@ -119,9 +151,10 @@ struct disjoint_segment_box_sphere_or_spheroid box_seg, azimuth_strategy, alp1); + if (disjoint_box_box(box, box_seg)) { - return true; + return disjoint_return_value; } // Case 3: test intersection by comparing angles @@ -138,16 +171,14 @@ struct disjoint_segment_box_sphere_or_spheroid azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2); azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3); - bool b0 = alp1 > a_b0; - bool b1 = alp1 > a_b1; - bool b2 = alp1 > a_b2; - bool b3 = alp1 > a_b3; + bool b0 = formula::azimuth_side_value(alp1, a_b0) > 0; + bool b1 = formula::azimuth_side_value(alp1, a_b1) > 0; + bool b2 = formula::azimuth_side_value(alp1, a_b2) > 0; + bool b3 = formula::azimuth_side_value(alp1, a_b3) > 0; - // if not all box points on the same side of the segment then - // there is an intersection if (!(b0 && b1 && b2 && b3) && (b0 || b1 || b2 || b3)) { - return false; + return disjoint_info::intersect; } // Case 4: The only intersection case not covered above is when all four @@ -157,8 +188,8 @@ struct disjoint_segment_box_sphere_or_spheroid CT vertex_lat; CT lat_sum = lat1 + lat2; - if ((b0 && b1 && b2 && b3 && lat_sum > CT(0)) - || (!(b0 && b1 && b2 && b3) && lat_sum < CT(0))) + if ((lat1 < b_lat_min && lat_sum > CT(0)) + || (lat1 > b_lat_max && lat_sum < CT(0))) { CT b_lat_below; //latitude of box closest to equator @@ -180,6 +211,10 @@ struct disjoint_segment_box_sphere_or_spheroid alp1, azimuth_strategy); + geometry::set_from_radian<0>(vertex, vertex_lon); + geometry::set_from_radian<1>(vertex, vertex_lat); + disjoint_return_value = disjoint_info::disjoint_vertex; //vertex_computed + // Check if the vertex point is within the band defined by the // minimum and maximum longitude of the box; if yes, then return // false if the point is above the min latitude of the box; return @@ -187,11 +222,11 @@ struct disjoint_segment_box_sphere_or_spheroid if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max && std::abs(vertex_lat) > std::abs(b_lat_below)) { - return false; + return disjoint_info::intersect; } } - return true; + return disjoint_return_value; } }; diff --git a/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp b/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp index a01ace2b58..a4c607698d 100644 --- a/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp +++ b/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp @@ -110,6 +110,26 @@ struct default_strategy > {}; +template +struct default_strategy + : strategy::distance::services::default_strategy + < + segment_tag, box_tag, + typename point_type::type, + typename point_type::type + > +{}; + +template +struct default_strategy + : strategy::distance::services::default_strategy + < + segment_tag, box_tag, + typename point_type::type, + typename point_type::type + > +{}; + // Helper metafunction for default point-segment strategy retrieval diff --git a/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp b/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp index b63104da7d..5904ac1c9e 100644 --- a/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp +++ b/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp @@ -110,6 +110,19 @@ struct distance > {}; +template +struct distance + < + Linear, Box, Strategy, + linear_tag, box_tag, + strategy_tag_distance_segment_box, false + > + : detail::distance::linear_to_areal + < + Linear, Box, Strategy + > +{}; + template struct distance diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index fa95152476..85e06ec7bc 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -1,7 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014-2018 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Licensed under the Boost Software License version 1.0. @@ -9,7 +10,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP - #include #include @@ -48,7 +48,6 @@ #include - namespace boost { namespace geometry { @@ -73,7 +72,7 @@ class segment_to_box_2D_generic typedef typename strategy::distance::services::comparable_type < - Strategy + typename Strategy::distance_ps_strategy::type >::type comparable_strategy; typedef detail::closest_feature::point_to_point_range @@ -108,8 +107,8 @@ class segment_to_box_2D_generic comparable_strategy cstrategy = strategy::distance::services::get_comparable < - Strategy - >::apply(strategy); + typename Strategy::distance_ps_strategy::type + >::apply(strategy.get_distance_ps_strategy()); // get segment points segment_point p[2]; @@ -159,12 +158,12 @@ class segment_to_box_2D_generic if (imin < 4) { - return strategy.apply(box_points[imin], p[0], p[1]); + return strategy.get_distance_ps_strategy().apply(box_points[imin], p[0], p[1]); } else { unsigned int bimin = imin - 4; - return strategy.apply(p[bimin], + return strategy.get_distance_ps_strategy().apply(p[bimin], *bit_min[bimin].first, *bit_min[bimin].second); } @@ -280,8 +279,7 @@ template typename ReturnType, typename SegmentPoint, typename BoxPoint, - typename PPStrategy, - typename PSStrategy + typename SBStrategy > class segment_to_box_2D { @@ -340,10 +338,9 @@ class segment_to_box_2D SegmentPoint const& p1, BoxPoint const& bottom_right, BoxPoint const& top_right, - PPStrategy const& pp_strategy, - PSStrategy const& ps_strategy) + SBStrategy const& sb_strategy) { - boost::ignore_unused(pp_strategy, ps_strategy); + boost::ignore_unused(sb_strategy); // the implementation below is written for non-negative slope // segments @@ -355,22 +352,29 @@ class segment_to_box_2D LessEqual less_equal; - if (less_equal(geometry::get<1>(top_right), geometry::get<1>(p0))) - { - // closest box point is the top-right corner - return cast::apply(pp_strategy.apply(p0, top_right)); - } - else if (less_equal(geometry::get<1>(bottom_right), - geometry::get<1>(p0))) + typename SBStrategy::distance_ps_strategy::type ps_strategy = + sb_strategy.get_distance_ps_strategy(); + + if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0))) { - // distance is realized between p0 and right-most - // segment of box - ReturnType diff = cast::apply(geometry::get<0>(p0)) - - cast::apply(geometry::get<0>(bottom_right)); - return strategy::distance::services::result_from_distance - < - PSStrategy, BoxPoint, SegmentPoint - >::apply(ps_strategy, math::abs(diff)); + //if p0 is in box's band + if (less_equal(geometry::get<1>(p0), geometry::get<1>(top_right))) + { + // segment & crosses band (TODO:merge with box-box dist) + if (math::equals(geometry::get<0>(p0), geometry::get<0>(p1))) + { + SegmentPoint high = geometry::get<1>(p1) > geometry::get<1>(p0) ? p1 : p0; + if (less_equal(geometry::get<1>(high), geometry::get<1>(top_right))) + { + return cast::apply(ps_strategy.apply(high, bottom_right, top_right)); + } + return cast::apply(ps_strategy.apply(top_right, p0, p1)); + } + return cast::apply(ps_strategy.apply(p0, bottom_right, top_right)); + } + // distance is realized between the top-right + // corner of the box and the segment + return cast::apply(ps_strategy.apply(top_right, p0, p1)); } else { @@ -381,45 +385,55 @@ class segment_to_box_2D } }; - // it is assumed here that p0 lies above the box (so the // entire segment lies above the box) + template struct above_of_box { + static inline ReturnType apply(SegmentPoint const& p0, SegmentPoint const& p1, BoxPoint const& top_left, - PSStrategy const& ps_strategy) + SBStrategy const& sb_strategy) { - boost::ignore_unused(ps_strategy); - - // the segment lies above the box + boost::ignore_unused(sb_strategy); + return apply(p0, p1, p0, top_left, sb_strategy); + } + static inline ReturnType apply(SegmentPoint const& p0, + SegmentPoint const& p1, + SegmentPoint const& p_max, + BoxPoint const& top_left, + SBStrategy const& sb_strategy) + { + boost::ignore_unused(sb_strategy); typedef cast_to_result cast; - LessEqual less_equal; - // p0 is above the upper segment of the box - // (and inside its band) - if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p0))) + // p0 is above the upper segment of the box (and inside its band) + // then compute the vertical (i.e. meridian for spherical) distance + if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max))) { - ReturnType diff = cast::apply(geometry::get<1>(p0)) - - cast::apply(geometry::get<1>(top_left)); + ReturnType diff = + sb_strategy.get_distance_ps_strategy().vertical_or_meridian( + geometry::get_as_radian<1>(p_max), + geometry::get_as_radian<1>(top_left)); + return strategy::distance::services::result_from_distance < - PSStrategy, SegmentPoint, BoxPoint - >::apply(ps_strategy, math::abs(diff)); + SBStrategy, SegmentPoint, BoxPoint + >::apply(sb_strategy, math::abs(diff)); } // p0 is to the left of the box, but p1 is above the box // in this case the distance is realized between the // top-left corner of the box and the segment - return cast::apply(ps_strategy.apply(top_left, p0, p1)); + return cast::apply(sb_strategy.get_distance_ps_strategy(). + apply(top_left, p0, p1)); } }; - template struct check_right_left_of_box { @@ -429,8 +443,7 @@ class segment_to_box_2D BoxPoint const& top_right, BoxPoint const& bottom_left, BoxPoint const& bottom_right, - PPStrategy const& pp_strategy, - PSStrategy const& ps_strategy, + SBStrategy const& sb_strategy, ReturnType& result) { // p0 lies to the right of the box @@ -440,7 +453,7 @@ class segment_to_box_2D < LessEqual >::apply(p0, p1, bottom_right, top_right, - pp_strategy, ps_strategy); + sb_strategy); return true; } @@ -451,7 +464,7 @@ class segment_to_box_2D < typename other_compare::type >::apply(p1, p0, top_left, bottom_left, - pp_strategy, ps_strategy); + sb_strategy); return true; } @@ -459,7 +472,6 @@ class segment_to_box_2D } }; - template struct check_above_below_of_box { @@ -469,26 +481,37 @@ class segment_to_box_2D BoxPoint const& top_right, BoxPoint const& bottom_left, BoxPoint const& bottom_right, - PSStrategy const& ps_strategy, + SBStrategy const& sb_strategy, ReturnType& result) { + typedef compare_less_equal GreaterEqual; + // the segment lies below the box if (geometry::get<1>(p1) < geometry::get<1>(bottom_left)) { - result = above_of_box - < - typename other_compare::type - >::apply(p1, p0, bottom_right, ps_strategy); + result = sb_strategy.template segment_below_of_box + < + LessEqual, + ReturnType + >(p0, p1, + top_left, top_right, + bottom_left, bottom_right); return true; } // the segment lies above the box if (geometry::get<1>(p0) > geometry::get<1>(top_right)) { - result = above_of_box - < - LessEqual - >::apply(p0, p1, top_left, ps_strategy); + result = + std::min( + above_of_box + < + LessEqual + >::apply(p0, p1, top_left, sb_strategy), + above_of_box + < + GreaterEqual + >::apply(p1, p0, top_right, sb_strategy)); return true; } return false; @@ -499,47 +522,30 @@ class segment_to_box_2D { static inline bool apply(SegmentPoint const& p0, SegmentPoint const& p1, - BoxPoint const& bottom_left0, - BoxPoint const& top_right0, - BoxPoint const& bottom_left1, - BoxPoint const& top_right1, BoxPoint const& corner1, BoxPoint const& corner2, - PSStrategy const& ps_strategy, + SBStrategy const& sb_strategy, ReturnType& result) { - typedef cast_to_result cast; - - ReturnType diff0 = cast::apply(geometry::get<0>(p1)) - - cast::apply(geometry::get<0>(p0)); - ReturnType t_min0 = cast::apply(geometry::get<0>(bottom_left0)) - - cast::apply(geometry::get<0>(p0)); - ReturnType t_max0 = cast::apply(geometry::get<0>(top_right0)) - - cast::apply(geometry::get<0>(p0)); + typedef typename geometry::strategy::side::services::default_strategy + < + typename geometry::cs_tag::type + >::type side; + typedef cast_to_result cast; ReturnType diff1 = cast::apply(geometry::get<1>(p1)) - - cast::apply(geometry::get<1>(p0)); - ReturnType t_min1 = cast::apply(geometry::get<1>(bottom_left1)) - - cast::apply(geometry::get<1>(p0)); - ReturnType t_max1 = cast::apply(geometry::get<1>(top_right1)) - - cast::apply(geometry::get<1>(p0)); + - cast::apply(geometry::get<1>(p0)); - if (diff1 < 0) - { - diff1 = -diff1; - t_min1 = -t_min1; - t_max1 = -t_max1; - } + typename SBStrategy::distance_ps_strategy::type ps_strategy = + sb_strategy.get_distance_ps_strategy(); - // t_min0 > t_max1 - if (t_min0 * diff1 > t_max1 * diff0) + int sign = diff1 < 0 ? -1 : 1; + if (side::apply(p0, p1, corner1) * sign < 0) { result = cast::apply(ps_strategy.apply(corner1, p0, p1)); return true; } - - // t_max0 < t_min1 - if (t_max0 * diff1 < t_min1 * diff0) + if (side::apply(p0, p1, corner2) * sign > 0) { result = cast::apply(ps_strategy.apply(corner2, p0, p1)); return true; @@ -555,8 +561,7 @@ class segment_to_box_2D BoxPoint const& top_right, BoxPoint const& bottom_left, BoxPoint const& bottom_right, - PPStrategy const& pp_strategy, - PSStrategy const& ps_strategy) + SBStrategy const& sb_strategy) { typedef compare_less_equal less_equal; @@ -576,7 +581,7 @@ class segment_to_box_2D less_equal >::apply(p0, p1, top_left, top_right, bottom_left, bottom_right, - pp_strategy, ps_strategy, result)) + sb_strategy, result)) { return result; } @@ -586,16 +591,14 @@ class segment_to_box_2D less_equal >::apply(p0, p1, top_left, top_right, bottom_left, bottom_right, - ps_strategy, result)) + sb_strategy, result)) { return result; } if (check_generic_position::apply(p0, p1, - bottom_left, top_right, - bottom_left, top_right, top_left, bottom_right, - ps_strategy, result)) + sb_strategy, result)) { return result; } @@ -612,8 +615,7 @@ class segment_to_box_2D BoxPoint const& top_right, BoxPoint const& bottom_left, BoxPoint const& bottom_right, - PPStrategy const& pp_strategy, - PSStrategy const& ps_strategy) + SBStrategy const& sb_strategy) { typedef compare_less_equal greater_equal; @@ -630,7 +632,7 @@ class segment_to_box_2D greater_equal >::apply(p0, p1, bottom_left, bottom_right, top_left, top_right, - pp_strategy, ps_strategy, result)) + sb_strategy, result)) { return result; } @@ -640,16 +642,14 @@ class segment_to_box_2D greater_equal >::apply(p1, p0, top_right, top_left, bottom_right, bottom_left, - ps_strategy, result)) + sb_strategy, result)) { return result; } if (check_generic_position::apply(p0, p1, bottom_left, top_right, - top_right, bottom_left, - bottom_left, top_right, - ps_strategy, result)) + sb_strategy, result)) { return result; } @@ -665,8 +665,7 @@ class segment_to_box_2D BoxPoint const& top_right, BoxPoint const& bottom_left, BoxPoint const& bottom_right, - PPStrategy const& pp_strategy, - PSStrategy const& ps_strategy) + SBStrategy const& sb_strategy) { BOOST_GEOMETRY_ASSERT( geometry::less()(p0, p1) || geometry::has_nan_coordinate(p0) @@ -678,27 +677,43 @@ class segment_to_box_2D return negative_slope_segment(p0, p1, top_left, top_right, bottom_left, bottom_right, - pp_strategy, ps_strategy); + sb_strategy); } return non_negative_slope_segment(p0, p1, top_left, top_right, bottom_left, bottom_right, - pp_strategy, ps_strategy); + sb_strategy); } -}; + template + static inline ReturnType call_above_of_box(SegmentPoint const& p0, + SegmentPoint const& p1, + SegmentPoint const& p_max, + BoxPoint const& top_left, + SBStrategy const& sb_strategy) + { + return above_of_box::apply(p0, p1, p_max, top_left, sb_strategy); + } -//========================================================================= + template + static inline ReturnType call_above_of_box(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + SBStrategy const& sb_strategy) + { + return above_of_box::apply(p0, p1, top_left, sb_strategy); + } +}; +//========================================================================= template < typename Segment, typename Box, typename std::size_t Dimension, - typename PPStrategy, - typename PSStrategy + typename SBStrategy > class segment_to_box : not_implemented @@ -709,10 +724,9 @@ template < typename Segment, typename Box, - typename PPStrategy, - typename PSStrategy + typename SBStrategy > -class segment_to_box +class segment_to_box { private: typedef typename point_type::type segment_point; @@ -720,12 +734,7 @@ class segment_to_box typedef typename strategy::distance::services::comparable_type < - PPStrategy - >::type pp_comparable_strategy; - - typedef typename strategy::distance::services::comparable_type - < - PSStrategy + SBStrategy >::type ps_comparable_strategy; typedef typename strategy::distance::services::return_type @@ -735,13 +744,12 @@ class segment_to_box public: typedef typename strategy::distance::services::return_type < - PSStrategy, segment_point, box_point + SBStrategy, segment_point, box_point >::type return_type; static inline return_type apply(Segment const& segment, Box const& box, - PPStrategy const& pp_strategy, - PSStrategy const& ps_strategy) + SBStrategy const& sb_strategy) { segment_point p[2]; detail::assign_point_from_index<0>(segment, p[0]); @@ -754,7 +762,7 @@ class segment_to_box boost::is_same < ps_comparable_strategy, - PSStrategy + SBStrategy >, typename strategy::distance::services::comparable_type < @@ -781,6 +789,10 @@ class segment_to_box detail::assign_box_corners(box, bottom_left, bottom_right, top_left, top_right); + SBStrategy::mirror(p[0], p[1], + bottom_left, bottom_right, + top_left, top_right); + if (geometry::less()(p[0], p[1])) { return segment_to_box_2D @@ -788,12 +800,10 @@ class segment_to_box return_type, segment_point, box_point, - PPStrategy, - PSStrategy + SBStrategy >::apply(p[0], p[1], top_left, top_right, bottom_left, bottom_right, - pp_strategy, - ps_strategy); + sb_strategy); } else { @@ -802,12 +812,10 @@ class segment_to_box return_type, segment_point, box_point, - PPStrategy, - PSStrategy + SBStrategy >::apply(p[1], p[0], top_left, top_right, bottom_left, bottom_right, - pp_strategy, - ps_strategy); + sb_strategy); } } }; @@ -826,7 +834,7 @@ template struct distance < Segment, Box, Strategy, segment_tag, box_tag, - strategy_tag_distance_point_segment, false + strategy_tag_distance_segment_box, false > { typedef typename strategy::distance::services::return_type @@ -843,40 +851,13 @@ struct distance { assert_dimension_equal(); - typedef typename boost::mpl::if_ - < - boost::is_same - < - typename strategy::distance::services::comparable_type - < - Strategy - >::type, - Strategy - >, - typename strategy::distance::services::comparable_type - < - typename detail::distance::default_strategy - < - typename point_type::type, - typename point_type::type - >::type - >::type, - typename detail::distance::default_strategy - < - typename point_type::type, - typename point_type::type - >::type - >::type pp_strategy_type; - - return detail::distance::segment_to_box < Segment, Box, dimension::value, - pp_strategy_type, Strategy - >::apply(segment, box, pp_strategy_type(), strategy); + >::apply(segment, box, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/envelope/segment.hpp b/include/boost/geometry/algorithms/detail/envelope/segment.hpp index 06c64bafc8..751313155c 100644 --- a/include/boost/geometry/algorithms/detail/envelope/segment.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -35,13 +35,12 @@ #include +#include #include #include - #include #include - #include #include @@ -168,6 +167,12 @@ class envelope_segment_impl CalculationType lat1_rad = math::as_radian(lat1); CalculationType lat2_rad = math::as_radian(lat2); + if (math::equals(a1, a2)) + { + // the segment must lie on the equator or is very short or is meridian + return; + } + if (lat1 > lat2) { std::swap(lat1, lat2); @@ -175,12 +180,6 @@ class envelope_segment_impl std::swap(a1, a2); } - if (math::equals(a1, a2)) - { - // the segment must lie on the equator or is very short - return; - } - if (contains_pi_half(a1, a2)) { CalculationType p_max = envelope_segment_call_vertex_latitude @@ -354,8 +353,7 @@ class envelope_segment_impl CalculationType lon2_rad = math::as_radian(lon2); CalculationType lat2_rad = math::as_radian(lat2); CalculationType alp2; - strategy.apply(lon2_rad, lat2_rad, lon1_rad, lat1_rad, alp2); - alp2 += math::pi(); + strategy.apply_reverse(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp2); compute_box_corners(lon1, lat1, lon2, lat2, alp1, alp2, strategy); } diff --git a/include/boost/geometry/formulas/meridian_inverse.hpp b/include/boost/geometry/formulas/meridian_inverse.hpp index ae45281ced..43bec19970 100644 --- a/include/boost/geometry/formulas/meridian_inverse.hpp +++ b/include/boost/geometry/formulas/meridian_inverse.hpp @@ -20,6 +20,7 @@ #include #include +#include namespace boost { namespace geometry { namespace formula { diff --git a/include/boost/geometry/formulas/meridian_segment.hpp b/include/boost/geometry/formulas/meridian_segment.hpp new file mode 100644 index 0000000000..535e31e3db --- /dev/null +++ b/include/boost/geometry/formulas/meridian_segment.hpp @@ -0,0 +1,72 @@ +// Boost.Geometry + +// Copyright (c) 2017 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_FORMULAS_MERIDIAN_SEGMENT_HPP +#define BOOST_GEOMETRY_FORMULAS_MERIDIAN_SEGMENT_HPP + +#include + +#include +#include + +#include +#include +#include + +namespace boost { namespace geometry { namespace formula +{ + +/*! +\brief Test if a segment is meridian or not. +*/ + +class meridian_segment +{ + +public : + + enum SegmentType {NonMeridian, MeridianCrossingPole, MeridianNotCrossingPole}; + + template + static inline SegmentType is_meridian(T lon1, T lat1, T lon2, T lat2) + { + SegmentType res = NonMeridian; + T diff = geometry::math::longitude_distance_signed(lon1, lon2); + + if ( meridian_not_crossing_pole(lat1, lat2, diff) ) + { + res = MeridianNotCrossingPole; + } + else if ( meridian_crossing_pole(diff) ) + { + res = MeridianCrossingPole; + } + return res; + } + + template + static bool meridian_not_crossing_pole(T lat1, T lat2, T diff) + { + T half_pi = math::half_pi(); + return math::equals(diff, T(0)) || + (math::equals(lat2, half_pi) && math::equals(lat1, -half_pi)); + } + + template + static bool meridian_crossing_pole(T diff) + { + return math::equals(math::abs(diff), math::pi()); + } + +}; + +}}} // namespace boost::geometry::formula + +#endif //BOOST_GEOMETRY_FORMULAS_MERIDIAN_SEGMENT_HPP diff --git a/include/boost/geometry/formulas/vertex_longitude.hpp b/include/boost/geometry/formulas/vertex_longitude.hpp index cf63c10a0a..94cb614fe5 100644 --- a/include/boost/geometry/formulas/vertex_longitude.hpp +++ b/include/boost/geometry/formulas/vertex_longitude.hpp @@ -332,6 +332,23 @@ public : } }; +template +class vertex_longitude +{ +public : + template + static inline CT apply(CT& lon1, + CT& lat1, + CT& lon2, + CT& lat2, + CT const& vertex_lat, + CT& alp1, + Strategy const& azimuth_strategy) + { + return lon2; + } +}; + }}} // namespace boost::geometry::formula #endif // BOOST_GEOMETRY_FORMULAS_MAXIMUM_LONGITUDE_HPP diff --git a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp index b7127c834d..5aaa9db434 100644 --- a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp @@ -94,8 +94,6 @@ public : > {}; -public : - template inline typename calculation_type::type apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const @@ -159,6 +157,13 @@ public : return strategy.apply(p, projected); } + + template + inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const + { + return lat1 - lat2; + } + }; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS diff --git a/include/boost/geometry/strategies/cartesian/distance_segment_box.hpp b/include/boost/geometry/strategies/cartesian/distance_segment_box.hpp new file mode 100644 index 0000000000..80f5094a59 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/distance_segment_box.hpp @@ -0,0 +1,192 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2018 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP + +#include + +namespace boost { namespace geometry +{ + + +namespace strategy { namespace distance +{ + +template +< + typename CalculationType = void, + typename Strategy = pythagoras +> +struct cartesian_segment_box +{ + template + struct calculation_type + : promote_floating_point + < + typename strategy::distance::services::return_type + < + Strategy, + PointOfSegment, + PointOfBox + >::type + > + {}; + + // point-point strategy getters + struct distance_pp_strategy + { + typedef Strategy type; + }; + + inline typename distance_pp_strategy::type get_distance_pp_strategy() const + { + return typename distance_pp_strategy::type(); + } + // point-segment strategy getters + struct distance_ps_strategy + { + typedef projected_point type; + }; + + inline typename distance_ps_strategy::type get_distance_ps_strategy() const + { + return typename distance_ps_strategy::type(); + } + + template + inline ReturnType segment_below_of_box(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const&, + BoxPoint const&, + BoxPoint const&, + BoxPoint const& bottom_right) const + { + + + return geometry::detail::distance::segment_to_box_2D + < + ReturnType, + SegmentPoint, + BoxPoint, + cartesian_segment_box + >::template call_above_of_box + < + typename LessEqual::other + >(p1, p0, bottom_right, *this); + } + + template + static void mirror(SPoint&, + SPoint&, + BPoint&, + BPoint&, + BPoint&, + BPoint&) + {} +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +struct tag > +{ + typedef strategy_tag_distance_segment_box type; +}; + +template +struct return_type, PS, PB> + : cartesian_segment_box::template calculation_type +{}; + +template +struct comparable_type > +{ + // Define a cartesian_segment_box strategy with its underlying point-point + // strategy being comparable + typedef cartesian_segment_box + < + CalculationType, + typename comparable_type::type + > type; +}; + + +template +struct get_comparable > +{ + typedef typename comparable_type + < + cartesian_segment_box + >::type comparable_type; +public : + static inline comparable_type apply(cartesian_segment_box const& ) + { + return comparable_type(); + } +}; + +template +struct result_from_distance, PS, PB> +{ +private : + typedef typename return_type< + cartesian_segment_box + < + CalculationType, + Strategy + >, + PS, + PB + >::type return_type; +public : + template + static inline return_type apply(cartesian_segment_box const& , + T const& value) + { + Strategy s; + return result_from_distance::apply(s, value); + } +}; + +template +struct default_strategy + < + segment_tag, box_tag, Segment, Box, + cartesian_tag, cartesian_tag + > +{ + typedef cartesian_segment_box<> type; +}; + +template +struct default_strategy + < + box_tag, segment_tag, Box, Segment, + cartesian_tag, cartesian_tag + > +{ + typedef typename default_strategy + < + segment_tag, box_tag, Segment, Box, + cartesian_tag, cartesian_tag + >::type type; +}; + +} +#endif + +}} // namespace strategy::distance + +}} // namespace boost::geometry +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP diff --git a/include/boost/geometry/strategies/geographic/azimuth.hpp b/include/boost/geometry/strategies/geographic/azimuth.hpp index b918caccea..1179050208 100644 --- a/include/boost/geometry/strategies/geographic/azimuth.hpp +++ b/include/boost/geometry/strategies/geographic/azimuth.hpp @@ -57,39 +57,68 @@ public : T const& lon2_rad, T const& lat2_rad, T& a1, T& a2) const { - typedef typename boost::mpl::if_ - < - boost::is_void, T, CalculationType - >::type calc_t; - - typedef typename FormulaPolicy::template inverse inverse_type; - typedef typename inverse_type::result_type inverse_result; - inverse_result i_res = inverse_type::apply(calc_t(lon1_rad), calc_t(lat1_rad), - calc_t(lon2_rad), calc_t(lat2_rad), - m_spheroid); - a1 = i_res.azimuth; - a2 = i_res.reverse_azimuth; + compute(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a1, a2); } - template inline void apply(T const& lon1_rad, T const& lat1_rad, T const& lon2_rad, T const& lat2_rad, T& a1) const + { + compute(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a1, a1); + } + template + inline void apply_reverse(T const& lon1_rad, T const& lat1_rad, + T const& lon2_rad, T const& lat2_rad, + T& a2) const + { + compute(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a2, a2); + } + +private : + + template < + bool EnableAzimuth, + bool EnableReverseAzimuth, + typename T + > + inline void compute(T const& lon1_rad, T const& lat1_rad, + T const& lon2_rad, T const& lat2_rad, + T& a1, T& a2) const { typedef typename boost::mpl::if_ - < - boost::is_void, T, CalculationType - >::type calc_t; + < + boost::is_void, T, CalculationType + >::type calc_t; - typedef typename FormulaPolicy::template inverse inverse_type; + typedef typename FormulaPolicy::template inverse + < + calc_t, + false, + EnableAzimuth, + EnableReverseAzimuth, + false, + false + > inverse_type; typedef typename inverse_type::result_type inverse_result; inverse_result i_res = inverse_type::apply(calc_t(lon1_rad), calc_t(lat1_rad), calc_t(lon2_rad), calc_t(lat2_rad), m_spheroid); - a1 = i_res.azimuth; + if (EnableAzimuth) + { + a1 = i_res.azimuth; + } + if (EnableReverseAzimuth) + { + a2 = i_res.reverse_azimuth; + } } -private : Spheroid m_spheroid; }; diff --git a/include/boost/geometry/strategies/geographic/distance.hpp b/include/boost/geometry/strategies/geographic/distance.hpp index 7e2746ffd3..41e3cd7aaa 100644 --- a/include/boost/geometry/strategies/geographic/distance.hpp +++ b/include/boost/geometry/strategies/geographic/distance.hpp @@ -125,19 +125,6 @@ public : return apply(lon1, lat1, lon2, lat2, m_spheroid); } - // points on a meridian not crossing poles - template - inline CT meridian(CT lat1, CT lat2) const - { - typedef typename formula::meridian_inverse - < - CT, strategy::default_order::value - > meridian_inverse; - - return meridian_inverse::meridian_not_crossing_pole_dist - (lat1, lat2, m_spheroid); - } - inline Spheroid const& model() const { return m_spheroid; diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 918bec7763..f84bb4134f 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -13,6 +13,8 @@ #include +#include +#include #include #include #include @@ -27,6 +29,7 @@ #include #include #include +#include #include #include @@ -94,17 +97,6 @@ public : > {}; - struct distance_strategy - { - typedef geographic type; - }; - - inline typename distance_strategy::type get_distance_strategy() const - { - typedef typename distance_strategy::type distance_type; - return distance_type(m_spheroid); - } - explicit geographic_cross_track(Spheroid const& spheroid = Spheroid()) : m_spheroid(spheroid) {} @@ -121,6 +113,20 @@ public : m_spheroid)).distance; } + // points on a meridian not crossing poles + template + inline CT vertical_or_meridian(CT lat1, CT lat2) const + { + typedef typename formula::meridian_inverse + < + CT, + strategy::default_order::value + > meridian_inverse; + + return meridian_inverse::meridian_not_crossing_pole_dist(lat1, lat2, + m_spheroid); + } + private : template @@ -171,21 +177,22 @@ private : if (g4 < -1.25*pi)//close to -270 { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "g4=" << g4 << ", close to -270" << std::endl; + std::cout << "g4=" << g4 * math::r2d() << ", close to -270" << std::endl; #endif return g4 + 1.5 * pi; } else if (g4 > 1.25*pi)//close to 270 { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "g4=" << g4 << ", close to 270" << std::endl; + std::cout << "g4=" << g4 * math::r2d() << ", close to 270" << std::endl; #endif + der = -der; return - g4 + 1.5 * pi; } else if (g4 < 0 && g4 > -0.75*pi)//close to -90 { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "g4=" << g4 << ", close to -90" << std::endl; + std::cout << "g4=" << g4 * math::r2d() << ", close to -90" << std::endl; #endif der = -der; return -g4 - pi/2; @@ -233,6 +240,16 @@ private : std::swap(lat1, lat2); } +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << ">>\nSegment=(" << lon1 * math::r2d(); + std::cout << "," << lat1 * math::r2d(); + std::cout << "),(" << lon2 * math::r2d(); + std::cout << "," << lat2 * math::r2d(); + std::cout << ")\np=(" << lon3 * math::r2d(); + std::cout << "," << lat3 * math::r2d(); + std::cout << ")" << std::endl; +#endif + //segment on equator //Note: antipodal points on equator does not define segment on equator //but pass by the pole @@ -248,9 +265,6 @@ private : bool meridian_crossing_pole = meridian_inverse::meridian_crossing_pole(diff); - //bool meridian_crossing_pole = math::equals(math::abs(diff), pi); - //bool meridian_not_crossing_pole = math::equals(math::abs(diff), c0); - if (math::equals(lat1, c0) && math::equals(lat2, c0) && !meridian_crossing_pole) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK @@ -273,18 +287,28 @@ private : return non_iterative_case(lon3, lat1, lon3, lat3, spheroid); } - if ( (meridian_not_crossing_pole || meridian_crossing_pole ) && lat1 > lat2) + if ( (meridian_not_crossing_pole || meridian_crossing_pole ) && std::abs(lat1) > std::abs(lat2)) { +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << "Meridian segment not crossing pole" << std::endl; +#endif std::swap(lat1,lat2); } if (meridian_crossing_pole) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "Meridian segment" << std::endl; + std::cout << "Meridian segment crossing pole" << std::endl; #endif - result_distance_point_segment d1 = apply(lon1, lat1, lon1, half_pi, lon3, lat3, spheroid); - result_distance_point_segment d2 = apply(lon2, lat2, lon2, half_pi, lon3, lat3, spheroid); + CT sign_non_zero = lat3 >= c0 ? 1 : -1; + result_distance_point_segment d1 = + apply(lon1, lat1, + lon1, half_pi * sign_non_zero, + lon3, lat3, spheroid); + result_distance_point_segment d2 = + apply(lon2, lat2, + lon2, half_pi * sign_non_zero, + lon3, lat3, spheroid); if (d1.distance < d2.distance) { return d1; @@ -321,29 +345,31 @@ private : CT a312 = a13 - a12; - if (geometry::math::equals(a312, c0)) + // TODO: meridian case optimization + if (geometry::math::equals(a312, c0) && meridian_not_crossing_pole) { + boost::tuple minmax_elem = boost::minmax(lat1, lat2); + if (lat3 >= minmax_elem.template get<0>() && + lat3 <= minmax_elem.template get<1>()) + { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "point on segment" << std::endl; + std::cout << "Point on meridian segment" << std::endl; #endif - return non_iterative_case(lon3, lat3, c0); + return non_iterative_case(lon3, lat3, c0); + } } CT projection1 = cos( a312 ) * d1 / d3; #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "segment=(" << lon1 * math::r2d(); - std::cout << "," << lat1 * math::r2d(); - std::cout << "),(" << lon2 * math::r2d(); - std::cout << "," << lat2 * math::r2d(); - std::cout << ")\np=(" << lon3 * math::r2d(); - std::cout << "," << lat3 * math::r2d(); - std::cout << ")\na1=" << a12 * math::r2d() << std::endl; + std::cout << "a1=" << a12 * math::r2d() << std::endl; std::cout << "a13=" << a13 * math::r2d() << std::endl; std::cout << "a312=" << a312 * math::r2d() << std::endl; std::cout << "cos(a312)=" << cos(a312) << std::endl; + std::cout << "projection 1=" << projection1 << std::endl; #endif - if (projection1 < 0.0) + + if (projection1 < c0) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "projection closer to p1" << std::endl; @@ -358,15 +384,17 @@ private : CT a321 = a23 - a21; + CT projection2 = cos( a321 ) * d2 / d3; + #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "a21=" << a21 * math::r2d() << std::endl; std::cout << "a23=" << a23 * math::r2d() << std::endl; std::cout << "a321=" << a321 * math::r2d() << std::endl; std::cout << "cos(a321)=" << cos(a321) << std::endl; + std::cout << "projection 2=" << projection2 << std::endl; #endif - CT projection2 = cos( a321 ) * d2 / d3; - if (projection2 < 0.0) + if (projection2 < c0) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "projection closer to p2" << std::endl; @@ -402,13 +430,15 @@ private : #endif // Update s14 (using Newton method) - CT prev_distance = 0; + CT prev_distance; geometry::formula::result_direct res14; geometry::formula::result_inverse res34; + res34.distance = -1; int counter = 0; // robustness CT g4; CT delta_g4; + bool dist_improve = true; do{ prev_distance = res34.distance; @@ -425,23 +455,27 @@ private : lon3, lat3, spheroid); g4 = res34.azimuth - a4; - - CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit CT m34 = res34.reduced_length; CT der = (M43 / m34) * sin(g4); - // normalize (g4 - pi/2) + //normalize delta_g4 = normalize(g4, der); - s14 = s14 - delta_g4 / der; + result.distance = res34.distance; + + dist_improve = prev_distance > res34.distance || prev_distance == -1; + if (!dist_improve) + { + result.distance = prev_distance; + } #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "p4=" << res14.lon2 * math::r2d() << "," << res14.lat2 * math::r2d() << std::endl; std::cout << "a34=" << res34.azimuth * math::r2d() << std::endl; std::cout << "a4=" << a4 * math::r2d() << std::endl; - std::cout << "g4=" << g4 * math::r2d() << std::endl; + std::cout << "g4(normalized)=" << g4 * math::r2d() << std::endl; std::cout << "delta_g4=" << delta_g4 * math::r2d() << std::endl; std::cout << "der=" << der << std::endl; std::cout << "M43=" << M43 << std::endl; @@ -450,15 +484,11 @@ private : std::cout << "new_s14=" << s14 << std::endl; std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl; std::cout << "---------end of step " << counter << std::endl<< std::endl; -#endif - result.distance = prev_distance; - -#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK if (g4 == half_pi) { std::cout << "Stop msg: g4 == half_pi" << std::endl; } - if (res34.distance >= prev_distance && prev_distance != 0) + if (!dist_improve) { std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl; } @@ -466,16 +496,16 @@ private : { std::cout << "Stop msg: delta_g4 == 0" << std::endl; } - if (counter == 19) + if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS) { std::cout << "Stop msg: counter" << std::endl; } #endif } while (g4 != half_pi - && (prev_distance > res34.distance || prev_distance == 0) + && dist_improve && delta_g4 != 0 - && ++counter < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS ) ; + && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS); #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "distance=" << res34.distance << std::endl; diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp index 4f6b3b45b7..8e48fbf19a 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp @@ -61,14 +61,37 @@ template class geographic_cross_track_box_box { public: - typedef geographic_cross_track Strategy; + + // point-point strategy getters + struct distance_pp_strategy + { + typedef geographic type; + }; + + // point-segment strategy getters + struct distance_ps_strategy + { + typedef geographic_cross_track + < + FormulaPolicy, + Spheroid, + CalculationType + > type; + }; template - struct return_type - : services::return_type::type, typename point_type::type> + struct return_type : services::return_type + < + typename distance_ps_strategy::type, + typename point_type::type, + typename point_type::type + > {}; - inline geographic_cross_track_box_box() + //constructor + + explicit geographic_cross_track_box_box(Spheroid const& spheroid = Spheroid()) + : m_spheroid(spheroid) {} template @@ -90,8 +113,12 @@ class geographic_cross_track_box_box */ typedef typename return_type::type return_type; return details::cross_track_box_box_generic - ::apply(box1, box2, Strategy()); + ::apply(box1, box2, + typename distance_pp_strategy::type(m_spheroid), + typename distance_ps_strategy::type(m_spheroid)); } +private : + Spheroid m_spheroid; }; diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp index 016427428c..4508d5acb5 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp @@ -62,14 +62,22 @@ template class geographic_cross_track_point_box { public: - typedef geographic_cross_track Strategy; + // point-point strategy getters + struct distance_ps_strategy + { + typedef geographic_cross_track type; + }; template struct return_type - : services::return_type::type> + : services::return_type::type> {}; - inline geographic_cross_track_point_box() + //constructor + + explicit geographic_cross_track_point_box(Spheroid const& spheroid = Spheroid()) + : m_spheroid(spheroid) {} template @@ -91,8 +99,12 @@ class geographic_cross_track_point_box typedef typename return_type::type return_type; return details::cross_track_point_box_generic - ::apply(point, box, Strategy()); + ::apply(point, box, + typename distance_ps_strategy::type(m_spheroid)); } + +private : + Spheroid m_spheroid; }; diff --git a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp new file mode 100644 index 0000000000..6bde78ca27 --- /dev/null +++ b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp @@ -0,0 +1,311 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2018 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP + +#include + +namespace boost { namespace geometry +{ + + +namespace strategy { namespace distance +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +struct geographic_segment_box +{ + template + struct return_type + : promote_floating_point + < + typename select_calculation_type + < + PointOfSegment, + PointOfBox, + CalculationType + >::type + > + {}; + + // point-point strategy getters + struct distance_pp_strategy + { + typedef geographic type; + }; + + inline typename distance_pp_strategy::type get_distance_pp_strategy() const + { + typedef typename distance_pp_strategy::type distance_type; + return distance_type(m_spheroid); + } + // point-segment strategy getters + struct distance_ps_strategy + { + typedef geographic_cross_track + < + FormulaPolicy, + Spheroid, + CalculationType + > type; + }; + + inline typename distance_ps_strategy::type get_distance_ps_strategy() const + { + typedef typename distance_ps_strategy::type distance_type; + return distance_type(m_spheroid); + } + + //constructor + + explicit geographic_segment_box(Spheroid const& spheroid = Spheroid()) + : m_spheroid(spheroid) + {} + + // methods + + template + inline ReturnType segment_below_of_box(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right) const + { + typedef typename azimuth::geographic + < + FormulaPolicy, + Spheroid, + CalculationType + > azimuth_strategy_type; + azimuth_strategy_type az_strategy(m_spheroid); + + typedef typename envelope::geographic_segment + < + FormulaPolicy, + Spheroid, + CalculationType + > envelope_segment_strategy_type; + envelope_segment_strategy_type es_strategy(m_spheroid); + + return generic_segment_box::segment_below_of_box + < + LessEqual, + ReturnType + >(p0,p1,top_left,top_right,bottom_left,bottom_right, + geographic_segment_box(), + az_strategy, es_strategy); + } + + template + static void mirror(SPoint& p0, + SPoint& p1, + BPoint& bottom_left, + BPoint& bottom_right, + BPoint& top_left, + BPoint& top_right) + { + + generic_segment_box::mirror(p0, p1, + bottom_left, bottom_right, + top_left, top_right); + } + +private : + Spheroid m_spheroid; +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +//tags + +template +struct tag > +{ + typedef strategy_tag_distance_segment_box type; +}; + +template +< + typename FormulaPolicy, + typename Spheroid +> +struct tag > +{ + typedef strategy_tag_distance_segment_box type; +}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct tag > +{ + typedef strategy_tag_distance_segment_box type; +}; + +// return types + +template +struct return_type, PS, PB> + : geographic_segment_box::template return_type +{}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename PS, + typename PB +> +struct return_type, PS, PB> + : geographic_segment_box::template return_type +{}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType, + typename PS, + typename PB +> +struct return_type, PS, PB> + : geographic_segment_box::template return_type +{}; + +//comparable types + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct comparable_type > +{ + typedef geographic_segment_box + < + FormulaPolicy, Spheroid, CalculationType + > type; +}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct get_comparable > +{ + typedef typename comparable_type + < + geographic_segment_box + >::type comparable_type; +public : + static inline comparable_type + apply(geographic_segment_box const& ) + { + return comparable_type(); + } +}; + +// result from distance + +template +< + typename FormulaPolicy, + typename PS, + typename PB +> +struct result_from_distance, PS, PB> +{ +private : + typedef typename geographic_segment_box + < + FormulaPolicy + >::template return_type::type return_type; +public : + template + static inline return_type + apply(geographic_segment_box const& , T const& distance) + { + return distance; + } +}; + +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType, + typename PS, + typename PB +> +struct result_from_distance, PS, PB> +{ +private : + typedef typename geographic_segment_box + < + FormulaPolicy, Spheroid, CalculationType + >::template return_type::type return_type; +public : + template + static inline return_type + apply(geographic_segment_box const& , T const& distance) + { + return distance; + } +}; + + +// default strategies + +template +struct default_strategy + < + segment_tag, box_tag, Segment, Box, + geographic_tag, geographic_tag + > +{ + typedef geographic_segment_box<> type; +}; + +template +struct default_strategy + < + box_tag, segment_tag, Box, Segment, + geographic_tag, geographic_tag + > +{ + typedef typename default_strategy + < + segment_tag, box_tag, Segment, Box, + geographic_tag, geographic_tag + >::type type; +}; + +} +#endif + +}} // namespace strategy::distance + +}} // namespace boost::geometry +#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP diff --git a/include/boost/geometry/strategies/spherical/azimuth.hpp b/include/boost/geometry/strategies/spherical/azimuth.hpp index 7a711c9814..bdfc401575 100644 --- a/include/boost/geometry/strategies/spherical/azimuth.hpp +++ b/include/boost/geometry/strategies/spherical/azimuth.hpp @@ -37,42 +37,67 @@ public : {} template - static inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) + inline void apply(T const& lon1_rad, T const& lat1_rad, + T const& lon2_rad, T const& lat2_rad, + T& a1, T& a2) const { - typedef typename boost::mpl::if_ - < - boost::is_void, T, CalculationType - >::type calc_t; - - geometry::formula::result_spherical - result = geometry::formula::spherical_azimuth( - calc_t(lon1_rad), calc_t(lat1_rad), - calc_t(lon2_rad), calc_t(lat2_rad)); - - a1 = result.azimuth; - a2 = result.reverse_azimuth; + compute(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a1, a2); } - template inline void apply(T const& lon1_rad, T const& lat1_rad, T const& lon2_rad, T const& lat2_rad, T& a1) const { - typedef typename boost::mpl::if_ + compute(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a1, a1); + } + template + inline void apply_reverse(T const& lon1_rad, T const& lat1_rad, + T const& lon2_rad, T const& lat2_rad, + T& a2) const + { + compute(lon1_rad, lat1_rad, + lon2_rad, lat2_rad, + a2, a2); + } + +private : + + template + < + bool EnableAzimuth, + bool EnableReverseAzimuth, + typename T + > + inline void compute(T const& lon1_rad, T const& lat1_rad, + T const& lon2_rad, T const& lat2_rad, + T& a1, T& a2) const + { + typedef typename boost::mpl::if_ < boost::is_void, T, CalculationType >::type calc_t; geometry::formula::result_spherical - result = geometry::formula::spherical_azimuth( - calc_t(lon1_rad), calc_t(lat1_rad), - calc_t(lon2_rad), calc_t(lat2_rad)); - - a1 = result.azimuth; + result = geometry::formula::spherical_azimuth + < + calc_t, + EnableReverseAzimuth + >(calc_t(lon1_rad), calc_t(lat1_rad), + calc_t(lon2_rad), calc_t(lat2_rad)); + + if (EnableAzimuth) + { + a1 = result.azimuth; + } + if (EnableReverseAzimuth) + { + a2 = result.reverse_azimuth; + } } - }; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp index db029dff90..97a36b8b27 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -352,12 +352,6 @@ public : : m_strategy(s) {} - //TODO: apply a more general strategy getter - inline Strategy get_distance_strategy() const - { - return m_strategy; - } - // It might be useful in the future // to overload constructor with strategy info. // crosstrack(...) {} @@ -473,6 +467,12 @@ public : } } + template + inline radius_type vertical_or_meridian(T1 lat1, T2 lat2) const + { + return m_strategy.radius() * (lat1 - lat2); + } + inline typename Strategy::radius_type radius() const { return m_strategy.radius(); } @@ -531,12 +531,6 @@ public : : m_strategy(s) {} - //TODO: apply a more general strategy getter - inline Strategy get_distance_strategy() const - { - return m_strategy; - } - // It might be useful in the future // to overload constructor with strategy info. // crosstrack(...) {} @@ -569,6 +563,12 @@ public : return c * radius(); } + template + inline radius_type vertical_or_meridian(T1 lat1, T2 lat2) const + { + return m_strategy.radius() * (lat1 - lat2); + } + inline typename Strategy::radius_type radius() const { return m_strategy.radius(); } diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track_box_box.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track_box_box.hpp index efa7a728a6..55500af0ed 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track_box_box.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track_box_box.hpp @@ -44,18 +44,19 @@ class cross_track_box_box_generic { public : - template + template ReturnType static inline diagonal_case(Point topA, Point topB, Point bottomA, Point bottomB, bool north_shortest, bool non_overlap, - Strategy ps_strategy) + PPStrategy pp_strategy, + PSStrategy ps_strategy) { if (north_shortest && non_overlap) { - return ps_strategy.get_distance_strategy().apply(topA, bottomB); + return pp_strategy.apply(topA, bottomB); } if (north_shortest && !non_overlap) { @@ -63,7 +64,7 @@ public : } if (!north_shortest && non_overlap) { - return ps_strategy.get_distance_strategy().apply(bottomA, topB); + return pp_strategy.apply(bottomA, topB); } return ps_strategy.apply(bottomA, topB, bottomB); } @@ -73,11 +74,13 @@ public : < typename Box1, typename Box2, - typename Strategy + typename PPStrategy, + typename PSStrategy > ReturnType static inline apply (Box1 const& box1, Box2 const& box2, - Strategy ps_strategy) + PPStrategy pp_strategy, + PSStrategy ps_strategy) { // this method assumes that the coordinates of the point and @@ -129,7 +132,7 @@ public : #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK_BOX_BOX std::cout << "(box1 crosses antimeridian)"; #endif - return apply(box2, box1, ps_strategy); + return apply(box2, box1, pp_strategy, ps_strategy); } else { @@ -160,17 +163,17 @@ public : { return geometry::strategy::distance::services::result_from_distance < - Strategy, box_point_type1, box_point_type2 - >::apply(ps_strategy, ps_strategy.get_distance_strategy() - .meridian(lat_min1, lat_max2)); + PSStrategy, box_point_type1, box_point_type2 + >::apply(ps_strategy, ps_strategy + .vertical_or_meridian(lat_min1, lat_max2)); } else if (lat_max1 < lat_min2) { return geometry::strategy::distance::services::result_from_distance < - Strategy, box_point_type1, box_point_type2 - >::apply(ps_strategy, ps_strategy.get_distance_strategy(). - meridian(lat_min2, lat_max1)); + PSStrategy, box_point_type1, box_point_type2 + >::apply(ps_strategy, ps_strategy + .vertical_or_meridian(lat_min2, lat_max1)); } else { @@ -211,7 +214,7 @@ public : return diagonal_case(top_right2, top_left1, bottom_right2, bottom_left1, north_shortest, non_overlap, - ps_strategy); + pp_strategy, ps_strategy); } if (bottom_max && right_wrap) { @@ -221,7 +224,7 @@ public : return diagonal_case(top_left2, top_right1, bottom_left2, bottom_right1, north_shortest, non_overlap, - ps_strategy); + pp_strategy, ps_strategy); } if (!bottom_max && !right_wrap) { @@ -231,7 +234,7 @@ public : return diagonal_case(top_left1, top_right2, bottom_left1, bottom_right2, north_shortest, non_overlap, - ps_strategy); + pp_strategy, ps_strategy); } if (!bottom_max && right_wrap) { @@ -241,7 +244,7 @@ public : return diagonal_case(top_right1, top_left2, bottom_right1, bottom_left2, north_shortest, non_overlap, - ps_strategy); + pp_strategy, ps_strategy); } return ReturnType(0); } @@ -265,7 +268,7 @@ to cross track template < typename CalculationType = void, - typename Strategy = cross_track + typename Strategy = haversine > class cross_track_box_box { @@ -279,15 +282,44 @@ class cross_track_box_box typedef typename Strategy::radius_type radius_type; + // strategy getters + + // point-segment strategy getters + struct distance_ps_strategy + { + typedef cross_track type; + }; + + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type pp_comparable_strategy; + + typedef typename boost::mpl::if_ + < + boost::is_same + < + pp_comparable_strategy, + Strategy + >, + typename strategy::distance::services::comparable_type + < + typename distance_ps_strategy::type + >::type, + typename distance_ps_strategy::type + >::type ps_strategy_type; + + // constructors + inline cross_track_box_box() {} explicit inline cross_track_box_box(typename Strategy::radius_type const& r) - : m_ps_strategy(r) + : m_strategy(r) {} inline cross_track_box_box(Strategy const& s) - : m_ps_strategy(s) + : m_strategy(s) {} @@ -302,7 +334,7 @@ class cross_track_box_box #if !defined(BOOST_MSVC) BOOST_CONCEPT_ASSERT ( - (concepts::PointSegmentDistanceStrategy + (concepts::PointDistanceStrategy < Strategy, typename point_type::type, @@ -312,16 +344,18 @@ class cross_track_box_box #endif typedef typename return_type::type return_type; return details::cross_track_box_box_generic - ::apply(box1, box2, m_ps_strategy); + ::apply(box1, box2, + m_strategy, + ps_strategy_type(m_strategy)); } inline typename Strategy::radius_type radius() const { - return m_ps_strategy.radius(); + return m_strategy.radius(); } private: - Strategy m_ps_strategy; + Strategy m_strategy; }; @@ -419,7 +453,7 @@ struct default_strategy boost::is_void, typename default_strategy < - point_tag, segment_tag, + point_tag, point_tag, typename point_type::type, typename point_type::type, spherical_equatorial_tag, spherical_equatorial_tag >::type, diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp index 9c8e7f1a3e..917eabb8d6 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp @@ -100,14 +100,16 @@ public : return geometry::strategy::distance::services::result_from_distance < Strategy, Point, box_point_type - >::apply(ps_strategy, ps_strategy.get_distance_strategy().meridian(plat, lat_max)); + >::apply(ps_strategy, ps_strategy + .vertical_or_meridian(plat, lat_max)); } else if (plat < lat_min) { return geometry::strategy::distance::services::result_from_distance < Strategy, Point, box_point_type - >::apply(ps_strategy, ps_strategy.get_distance_strategy().meridian(lat_min, plat)); + >::apply(ps_strategy, ps_strategy + .vertical_or_meridian(lat_min, plat)); } else { @@ -186,8 +188,7 @@ public : \details Class which calculates the distance of a point to a box, for points and boxes on a sphere or globe \tparam CalculationType \tparam_calculation -\tparam Strategy underlying point-segment distance strategy, defaults -to cross track +\tparam Strategy underlying point-point distance strategy \qbk{ [heading See also] [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)] @@ -196,7 +197,7 @@ to cross track template < typename CalculationType = void, - typename Strategy = cross_track + typename Strategy = haversine > class cross_track_point_box { @@ -208,18 +209,49 @@ class cross_track_point_box typedef typename Strategy::radius_type radius_type; + // strategy getters + + // point-segment strategy getters + struct distance_ps_strategy + { + typedef cross_track type; + }; + + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type pp_comparable_strategy; + + typedef typename boost::mpl::if_ + < + boost::is_same + < + pp_comparable_strategy, + Strategy + >, + typename strategy::distance::services::comparable_type + < + typename distance_ps_strategy::type + >::type, + typename distance_ps_strategy::type + >::type ps_strategy_type; + + // constructors + inline cross_track_point_box() {} explicit inline cross_track_point_box(typename Strategy::radius_type const& r) - : m_ps_strategy(r) + : m_strategy(r) {} inline cross_track_point_box(Strategy const& s) - : m_ps_strategy(s) + : m_strategy(s) {} + // methods + // It might be useful in the future // to overload constructor with strategy info. // crosstrack(...) {} @@ -231,7 +263,7 @@ class cross_track_point_box #if !defined(BOOST_MSVC) BOOST_CONCEPT_ASSERT ( - (concepts::PointSegmentDistanceStrategy + (concepts::PointDistanceStrategy < Strategy, Point, typename point_type::type >) @@ -239,16 +271,17 @@ class cross_track_point_box #endif typedef typename return_type::type return_type; return details::cross_track_point_box_generic - ::apply(point, box, m_ps_strategy); + ::apply(point, box, + ps_strategy_type(m_strategy)); } inline typename Strategy::radius_type radius() const { - return m_ps_strategy.radius(); + return m_strategy.radius(); } private: - Strategy m_ps_strategy; + Strategy m_strategy; }; @@ -344,7 +377,7 @@ struct default_strategy boost::is_void, typename default_strategy < - point_tag, segment_tag, + point_tag, point_tag, Point, typename point_type::type, spherical_equatorial_tag, spherical_equatorial_tag >::type, diff --git a/include/boost/geometry/strategies/spherical/distance_haversine.hpp b/include/boost/geometry/strategies/spherical/distance_haversine.hpp index 1a4cbdf36b..bd46a93c6a 100644 --- a/include/boost/geometry/strategies/spherical/distance_haversine.hpp +++ b/include/boost/geometry/strategies/spherical/distance_haversine.hpp @@ -94,12 +94,6 @@ public : ); } - template - inline radius_type meridian(T1 lat1, T2 lat2) const - { - return m_radius * (lat1 - lat2); - } - inline radius_type radius() const { return m_radius; @@ -197,19 +191,6 @@ public : return calculation_type(m_radius) * c; } - /*! - \brief meridian distance calculation - \return the calculated distance (including multiplying with radius) - \param p1 first point - \param p2 second point - */ - - template - inline radius_type meridian(T1 lat1, T2 lat2) const - { - return m_radius * (lat1 - lat2); - } - /*! \brief access to radius value \return the radius diff --git a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp new file mode 100644 index 0000000000..d5647182a8 --- /dev/null +++ b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp @@ -0,0 +1,340 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2018 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP + +#include + +namespace boost { namespace geometry +{ + + +namespace strategy { namespace distance +{ + +struct generic_segment_box +{ + template + < + typename LessEqual, + typename ReturnType, + typename SegmentPoint, + typename BoxPoint, + typename SegmentBoxStrategy, + typename AzimuthStrategy, + typename EnvelopeSegmentStrategy + > + static inline ReturnType segment_below_of_box( + SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const&, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right, + SegmentBoxStrategy const& sb_strategy, + AzimuthStrategy & az_strategy, + EnvelopeSegmentStrategy & es_strategy) + { + ReturnType result; + typename LessEqual::other less_equal; + typedef geometry::model::segment Segment; + typedef typename cs_tag::type segment_cs_type; + typedef geometry::detail::disjoint:: + disjoint_segment_box_sphere_or_spheroid + disjoint_sb; + typedef typename disjoint_sb::disjoint_info disjoint_info_type; + + Segment seg(p0, p1); + + geometry::model::box input_box; + geometry::set_from_radian + (input_box, geometry::get_as_radian<0>(bottom_left)); + geometry::set_from_radian + (input_box, geometry::get_as_radian<1>(bottom_left)); + geometry::set_from_radian + (input_box, geometry::get_as_radian<0>(top_right)); + geometry::set_from_radian + (input_box, geometry::get_as_radian<1>(top_right)); + + SegmentPoint p_max; + + disjoint_info_type disjoint_result = disjoint_sb:: + apply(seg, input_box, az_strategy, p_max); + + if (disjoint_result == disjoint_info_type::intersect) //intersect + { + return 0; + } + // disjoint but vertex not computed + if (disjoint_result == disjoint_info_type::disjoint_no_vertex) + { + typedef typename coordinate_type::type CT; + + geometry::model::box mbr; + geometry::envelope(seg, mbr, es_strategy); + + CT lon1 = geometry::get_as_radian<0>(p0); + CT lat1 = geometry::get_as_radian<1>(p0); + CT lon2 = geometry::get_as_radian<0>(p1); + CT lat2 = geometry::get_as_radian<1>(p1); + + CT vertex_lat; + CT lat_sum = lat1 + lat2; + if (lat_sum > CT(0)) + { + vertex_lat = geometry::get_as_radian(mbr); + } else { + vertex_lat = geometry::get_as_radian(mbr); + } + + CT alp1; + az_strategy.apply(lon1, lat1, lon2, lat2, alp1); + CT vertex_lon = geometry::formula::vertex_longitude + < + CT, + segment_cs_type + >::apply(lon1, lat1, lon2, lat2, + vertex_lat, alp1, az_strategy); + + geometry::set_from_radian<0>(p_max, vertex_lon); + geometry::set_from_radian<1>(p_max, vertex_lat); + } + //otherwise disjoint and vertex computed inside disjoint + + if (less_equal(geometry::get_as_radian<0>(bottom_left), + geometry::get_as_radian<0>(p_max))) + { + result = boost::numeric_cast(typename + SegmentBoxStrategy::distance_ps_strategy::type().apply(bottom_left, p0, p1)); + } + else + { + result = geometry::detail::distance::segment_to_box_2D + < + ReturnType, + SegmentPoint, + BoxPoint, + SegmentBoxStrategy + >::template call_above_of_box + < + typename LessEqual::other + >(p1, p0, p_max, bottom_right, sb_strategy); + } + return result; + } + + template + static void mirror(SPoint& p0, + SPoint& p1, + BPoint& bottom_left, + BPoint& bottom_right, + BPoint& top_left, + BPoint& top_right) + { + //if segment's vertex is the southest point then mirror geometries + if (geometry::get<1>(p0) + geometry::get<1>(p1) < 0) + { + BPoint bl = bottom_left; + BPoint br = bottom_right; + geometry::set<1>(p0, geometry::get<1>(p0) * -1); + geometry::set<1>(p1, geometry::get<1>(p1) * -1); + geometry::set<1>(bottom_left, geometry::get<1>(top_left) * -1); + geometry::set<1>(top_left, geometry::get<1>(bl) * -1); + geometry::set<1>(bottom_right, geometry::get<1>(top_right) * -1); + geometry::set<1>(top_right, geometry::get<1>(br) * -1); + } + } +}; + +//=========================================================================== + +template +< + typename CalculationType = void, + typename Strategy = haversine +> +struct spherical_segment_box +{ + template + struct calculation_type + : promote_floating_point + < + typename strategy::distance::services::return_type + < + Strategy, + PointOfSegment, + PointOfBox + >::type + > + {}; + + // strategy getters + + // point-point strategy getters + struct distance_pp_strategy + { + typedef Strategy type; + }; + + inline typename distance_pp_strategy::type get_distance_pp_strategy() const + { + return typename distance_pp_strategy::type(); + } + // point-segment strategy getters + struct distance_ps_strategy + { + typedef cross_track type; + }; + + inline typename distance_ps_strategy::type get_distance_ps_strategy() const + { + return typename distance_ps_strategy::type(); + } + + // methods + + template + inline ReturnType segment_below_of_box(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right) const + { + typedef typename azimuth::spherical azimuth_strategy_type; + azimuth_strategy_type az_strategy; + + typedef typename envelope::spherical_segment + envelope_segment_strategy_type; + envelope_segment_strategy_type es_strategy; + + return generic_segment_box::segment_below_of_box + < + LessEqual, + ReturnType + >(p0,p1,top_left,top_right,bottom_left,bottom_right, + spherical_segment_box(), + az_strategy, es_strategy); + } + + template + static void mirror(SPoint& p0, + SPoint& p1, + BPoint& bottom_left, + BPoint& bottom_right, + BPoint& top_left, + BPoint& top_right) + { + + generic_segment_box::mirror(p0, p1, + bottom_left, bottom_right, + top_left, top_right); + } + +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +struct tag > +{ + typedef strategy_tag_distance_segment_box type; +}; + +template +struct return_type, PS, PB> + : spherical_segment_box::template calculation_type +{}; + +template +struct comparable_type > +{ + // Define a cartesian_segment_box strategy with its underlying point-segment + // strategy being comparable + typedef spherical_segment_box + < + CalculationType, + typename comparable_type::type + > type; +}; + + +template +struct get_comparable > +{ + typedef typename comparable_type + < + spherical_segment_box + >::type comparable_type; +public : + static inline comparable_type apply(spherical_segment_box const& ) + { + return comparable_type(); + } +}; + +template +struct result_from_distance, PS, PB> +{ +private : + typedef typename return_type< + spherical_segment_box + < + CalculationType, + Strategy + >, + PS, + PB + >::type return_type; +public : + template + static inline return_type apply(spherical_segment_box const& , + T const& value) + { + Strategy s; + return result_from_distance::apply(s, value); + } +}; + +template +struct default_strategy + < + segment_tag, box_tag, Segment, Box, + spherical_equatorial_tag, spherical_equatorial_tag + > +{ + typedef spherical_segment_box<> type; +}; + +template +struct default_strategy + < + box_tag, segment_tag, Box, Segment, + spherical_equatorial_tag, spherical_equatorial_tag + > +{ + typedef typename default_strategy + < + segment_tag, box_tag, Segment, Box, + spherical_equatorial_tag, spherical_equatorial_tag + >::type type; +}; + +} +#endif + +}} // namespace strategy::distance + +}} // namespace boost::geometry +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index 7d6cb618c6..b6430692f4 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +96,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/geometry/strategies/tags.hpp b/include/boost/geometry/strategies/tags.hpp index 7589c21071..748541f59b 100644 --- a/include/boost/geometry/strategies/tags.hpp +++ b/include/boost/geometry/strategies/tags.hpp @@ -7,6 +7,11 @@ // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2018. +// Modifications copyright (c) 2018 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -36,6 +41,7 @@ struct strategy_tag_distance_point_point {}; struct strategy_tag_distance_point_segment {}; struct strategy_tag_distance_point_box {}; struct strategy_tag_distance_box_box {}; +struct strategy_tag_distance_segment_box {}; }} // namespace boost::geometry diff --git a/test/algorithms/distance/Jamfile.v2 b/test/algorithms/distance/Jamfile.v2 index 5c5e6a4f76..c76f210312 100644 --- a/test/algorithms/distance/Jamfile.v2 +++ b/test/algorithms/distance/Jamfile.v2 @@ -20,6 +20,7 @@ test-suite boost-geometry-algorithms-distance [ run distance.cpp : : : : algorithms_distance ] [ run distance_areal_areal.cpp : : : : algorithms_distance_areal_areal ] [ run distance_geo_box_box.cpp : : : : algorithms_distance_geo_box_box ] + [ run distance_geo_linear_box.cpp : : : : algorithms_distance_geo_linear_box ] [ run distance_geo_pl_l.cpp : : : : algorithms_distance_geo_pl_l ] [ run distance_geo_pl_pl.cpp : : : : algorithms_distance_geo_pl_pl ] [ run distance_geo_point_box.cpp : : : : algorithms_distance_geo_point_box ] diff --git a/test/algorithms/distance/distance.cpp b/test/algorithms/distance/distance.cpp index e1aef1896b..f869692099 100644 --- a/test/algorithms/distance/distance.cpp +++ b/test/algorithms/distance/distance.cpp @@ -12,6 +12,7 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +//#include #include #include diff --git a/test/algorithms/distance/distance_brute_force.hpp b/test/algorithms/distance/distance_brute_force.hpp index 72194e6155..82d8f4d771 100644 --- a/test/algorithms/distance/distance_brute_force.hpp +++ b/test/algorithms/distance/distance_brute_force.hpp @@ -146,7 +146,6 @@ struct distance_brute_force : not_implemented {}; - template < typename Geometry1, @@ -169,6 +168,7 @@ struct distance_brute_force } }; +//=================================================================== template < @@ -197,6 +197,115 @@ struct distance_brute_force > : detail::distance_brute_force::distance_from_bg {}; +template +< + typename Point, + typename Linear, + typename Strategy +> +struct distance_brute_force +< + Point, Linear, Strategy, + point_tag, linear_tag, false +> +{ + typedef typename distance_result + < + Point, Linear, Strategy + >::type distance_type; + + static inline distance_type apply(Point const& point, + Linear const& linear, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + detail::distance_brute_force::distance_from_bg + >::apply(point, + geometry::segments_begin(linear), + geometry::segments_end(linear), + strategy); + } +}; + +template +< + typename Point, + typename Ring, + typename Strategy +> +struct distance_brute_force +< + Point, Ring, Strategy, + point_tag, ring_tag, false +> +{ + typedef typename distance_result + < + Point, Ring, Strategy + >::type distance_type; + + static inline distance_type apply(Point const& point, + Ring const& ring, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Point, + typename std::iterator_traits + < + segment_iterator + >::value_type, + Strategy + > + >::apply(point, + geometry::segments_begin(ring), + geometry::segments_end(ring), + strategy); + } +}; + +//TODO iterate over exterior rings +template +< + typename Point, + typename Polygon, + typename Strategy +> +struct distance_brute_force +< + Point, Polygon, Strategy, + point_tag, polygon_tag, false +> +{ + typedef typename distance_result + < + Point, Polygon, Strategy + >::type distance_type; + + static inline distance_type apply(Point const& point, + Polygon const& polygon, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Point, + typename std::iterator_traits + < + segment_iterator + >::value_type, + Strategy + > + >::apply(point, + geometry::segments_begin(polygon), + geometry::segments_end(polygon), + strategy); + } +}; template < @@ -213,190 +322,429 @@ struct distance_brute_force template < - typename Box1, - typename Box2, + typename Point, + typename MultiPoint, typename Strategy > struct distance_brute_force < - Box1, Box2, Strategy, - box_tag, box_tag, false -> : detail::distance_brute_force::distance_from_bg -{}; + Point, MultiPoint, Strategy, + point_tag, multi_point_tag, false +> +{ + typedef typename distance_result + < + Point, MultiPoint, Strategy + >::type distance_type; + + static inline distance_type apply(Point const& p, + MultiPoint const& mp, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + detail::distance_brute_force::distance_from_bg + >::apply(p, boost::begin(mp), boost::end(mp), strategy); + } +}; +//======================================================================= template < - typename Segment1, - typename Segment2, + typename Linear, + typename Segment, typename Strategy > struct distance_brute_force < - Segment1, Segment2, Strategy, - segment_tag, segment_tag, false -> : detail::distance_brute_force::distance_from_bg -{}; + Linear, Segment, Strategy, + linear_tag, segment_tag, false +> +{ + typedef typename distance_result + < + Linear, Segment, Strategy + >::type distance_type; + + static inline distance_type apply(Linear const& linear, + Segment const& segment, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + detail::distance_brute_force::distance_from_bg + >::apply(segment, + geometry::segments_begin(linear), + geometry::segments_end(linear), + strategy); + } +}; template < - typename Point, + typename Linear1, + typename Linear2, + typename Strategy +> +struct distance_brute_force +< + Linear1, Linear2, Strategy, + linear_tag, linear_tag, false +> +{ + typedef typename distance_result + < + Linear1, Linear2, Strategy + >::type distance_type; + + static inline distance_type apply(Linear1 const& linear1, + Linear2 const& linear2, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Linear1, + typename std::iterator_traits + < + segment_iterator + >::value_type, + Strategy + > + >::apply(linear1, + geometry::segments_begin(linear2), + geometry::segments_end(linear2), + strategy); + } +}; + +template +< typename Linear, + typename Ring, typename Strategy > struct distance_brute_force < - Point, Linear, Strategy, - point_tag, linear_tag, false + Linear, Ring, Strategy, + linear_tag, ring_tag, false > { typedef typename distance_result < - Point, Linear, Strategy + Linear, Ring, Strategy >::type distance_type; - static inline distance_type apply(Point const& point, - Linear const& linear, + static inline distance_type apply(Linear const& linear, + Ring const& ring, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Linear, + typename std::iterator_traits + < + segment_iterator + >::value_type, + Strategy + > + >::apply(linear, + geometry::segments_begin(ring), + geometry::segments_end(ring), + strategy); + } +}; + +template +< + typename Linear, + typename Polygon, + typename Strategy +> +struct distance_brute_force +< + Linear, Polygon, Strategy, + linear_tag, polygon_tag, false +> +{ + typedef typename distance_result + < + Linear, Polygon, Strategy + >::type distance_type; + + static inline distance_type apply(Linear const& linear, + Polygon const& polygon, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Linear, + typename std::iterator_traits + < + segment_iterator + >::value_type, + Strategy + > + >::apply(linear, + geometry::segments_begin(polygon), + geometry::segments_end(polygon), + strategy); + } +}; + + +template +< + typename Linear, + typename Box, + typename Strategy +> +struct distance_brute_force +< + Linear, Box, Strategy, + linear_tag, box_tag, false +> +{ + typedef typename distance_result + < + Linear, Box, Strategy + >::type distance_type; + + static inline distance_type apply(Linear const& linear, + Box const& box, Strategy const& strategy) { return detail::distance_brute_force::one_to_many < detail::distance_brute_force::distance_from_bg - >::apply(point, + >::apply(box, geometry::segments_begin(linear), geometry::segments_end(linear), strategy); } }; - template < - typename Point, + typename Linear, typename MultiPoint, typename Strategy > struct distance_brute_force < - Point, MultiPoint, Strategy, - point_tag, multi_point_tag, false + Linear, MultiPoint, Strategy, + linear_tag, multi_point_tag, false > { typedef typename distance_result < - Point, MultiPoint, Strategy + Linear, MultiPoint, Strategy >::type distance_type; - static inline distance_type apply(Point const& p, + static inline distance_type apply(Linear const& linear, MultiPoint const& mp, Strategy const& strategy) { return detail::distance_brute_force::one_to_many < - detail::distance_brute_force::distance_from_bg - >::apply(p, boost::begin(mp), boost::end(mp), strategy); + distance_brute_force + < + Linear, + typename boost::range_value::type, + Strategy + > + >::apply(linear, boost::begin(mp), boost::end(mp), strategy); } }; template < - typename MultiPoint1, - typename MultiPoint2, + typename Linear, + typename MultiPolygon, typename Strategy > struct distance_brute_force < - MultiPoint1, MultiPoint2, Strategy, - multi_point_tag, multi_point_tag, false + Linear, MultiPolygon, Strategy, + linear_tag, multi_polygon_tag, false > { typedef typename distance_result < - MultiPoint1, MultiPoint2, Strategy + Linear, MultiPolygon, Strategy >::type distance_type; - static inline distance_type apply(MultiPoint1 const& mp1, - MultiPoint2 const& mp2, + static inline distance_type apply(Linear const& linear, + MultiPolygon const& mp, Strategy const& strategy) { return detail::distance_brute_force::one_to_many < distance_brute_force < - MultiPoint1, - typename boost::range_value::type, + Linear, + typename boost::range_value::type, Strategy > - >::apply(mp1, boost::begin(mp2), boost::end(mp2), strategy); + >::apply(linear, boost::begin(mp), boost::end(mp), strategy); } }; +//================================================================= template < - typename MultiPoint, + typename Polygon, + typename Segment, + typename Strategy +> +struct distance_brute_force +< + Polygon, Segment, Strategy, + polygon_tag, segment_tag, false +> +{ + typedef typename distance_result + < + Polygon, Segment, Strategy + >::type distance_type; + + static inline distance_type apply(Polygon const& polygon, + Segment const& segment, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Segment, + typename std::iterator_traits + < + segment_iterator + >::value_type, + Strategy + > + >::apply(segment, + geometry::segments_begin(polygon), + geometry::segments_end(polygon), + strategy); + } +}; + +template +< + typename Polygon, typename Linear, typename Strategy > struct distance_brute_force < - MultiPoint, Linear, Strategy, - multi_point_tag, linear_tag, false + Polygon, Linear, Strategy, + polygon_tag, linear_tag, false > { typedef typename distance_result < - MultiPoint, Linear, Strategy + Polygon, Linear, Strategy >::type distance_type; - static inline distance_type apply(MultiPoint const& mp, + static inline distance_type apply(Polygon const& polygon, Linear const& linear, Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Linear, + typename std::iterator_traits + < + segment_iterator + >::value_type, + Strategy + > + >::apply(linear, + geometry::segments_begin(polygon), + geometry::segments_end(polygon), + strategy); + } +}; + +//======================================================================== + +template +< + typename MultiPoint1, + typename MultiPoint2, + typename Strategy +> +struct distance_brute_force +< + MultiPoint1, MultiPoint2, Strategy, + multi_point_tag, multi_point_tag, false +> +{ + typedef typename distance_result + < + MultiPoint1, MultiPoint2, Strategy + >::type distance_type; + + static inline distance_type apply(MultiPoint1 const& mp1, + MultiPoint2 const& mp2, + Strategy const& strategy) { return detail::distance_brute_force::one_to_many < distance_brute_force < - Linear, - typename boost::range_value::type, + MultiPoint1, + typename boost::range_value::type, Strategy > - >::apply(linear, boost::begin(mp), boost::end(mp), strategy); + >::apply(mp1, boost::begin(mp2), boost::end(mp2), strategy); } }; - template < - typename Linear, typename MultiPoint, + typename Linear, typename Strategy > struct distance_brute_force < - Linear, MultiPoint, Strategy, - linear_tag, multi_point_tag, false + MultiPoint, Linear, Strategy, + multi_point_tag, linear_tag, false > { typedef typename distance_result < - Linear, MultiPoint, Strategy + MultiPoint, Linear, Strategy >::type distance_type; - static inline distance_type apply(Linear const& linear, - MultiPoint const& multipoint, + static inline distance_type apply(MultiPoint const& mp, + Linear const& l, Strategy const& strategy) { - return distance_brute_force + return detail::distance_brute_force::one_to_many < - MultiPoint, Linear, Strategy, - multi_point_tag, linear_tag, false - >::apply(multipoint, linear, strategy); + distance_brute_force + < + MultiPoint, + typename boost::range_value::type, + Strategy + > + >::apply(mp, boost::begin(l), boost::end(l), strategy); } }; - template < typename MultiPoint, @@ -458,78 +806,123 @@ struct distance_brute_force } }; +//===================================================================== template < - typename Linear, + typename MultiPolygon, typename Segment, typename Strategy > struct distance_brute_force < - Linear, Segment, Strategy, - linear_tag, segment_tag, false + MultiPolygon, Segment, Strategy, + multi_polygon_tag, segment_tag, false > { typedef typename distance_result < - Linear, Segment, Strategy + MultiPolygon, Segment, Strategy >::type distance_type; - static inline distance_type apply(Linear const& linear, + static inline distance_type apply(MultiPolygon const& mp, Segment const& segment, Strategy const& strategy) { return detail::distance_brute_force::one_to_many < - detail::distance_brute_force::distance_from_bg - >::apply(segment, - geometry::segments_begin(linear), - geometry::segments_end(linear), - strategy); + distance_brute_force + < + Segment, + typename boost::range_value::type, + Strategy + > + >::apply(segment, boost::begin(mp), boost::end(mp), strategy); } }; +//======================================================================== template < - typename Linear1, - typename Linear2, + typename Segment1, + typename Segment2, typename Strategy > struct distance_brute_force < - Linear1, Linear2, Strategy, - linear_tag, linear_tag, false + Segment1, Segment2, Strategy, + segment_tag, segment_tag, false +> : detail::distance_brute_force::distance_from_bg +{}; + +template +< + typename Segment, + typename Ring, + typename Strategy +> +struct distance_brute_force +< + Segment, Ring, Strategy, + segment_tag, ring_tag, false > { typedef typename distance_result < - Linear1, Linear2, Strategy + Segment, Ring, Strategy >::type distance_type; - static inline distance_type apply(Linear1 const& linear1, - Linear2 const& linear2, + static inline distance_type apply(Segment const& segment, + Ring const& ring, Strategy const& strategy) { return detail::distance_brute_force::one_to_many < distance_brute_force < - Linear1, + Segment, typename std::iterator_traits < - segment_iterator + segment_iterator >::value_type, Strategy > - >::apply(linear1, - geometry::segments_begin(linear2), - geometry::segments_end(linear2), + >::apply(segment, + geometry::segments_begin(ring), + geometry::segments_end(ring), strategy); } }; +template +< + typename Segment, + typename Box, + typename Strategy +> +struct distance_brute_force +< + Segment, Box, Strategy, + segment_tag, box_tag, false +> : detail::distance_brute_force::distance_from_bg +{}; + +//==================================================================== + +template +< + typename Box1, + typename Box2, + typename Strategy +> +struct distance_brute_force +< + Box1, Box2, Strategy, + box_tag, box_tag, false +> : detail::distance_brute_force::distance_from_bg +{}; + } // namespace dispatch diff --git a/test/algorithms/distance/distance_geo_box_box.cpp b/test/algorithms/distance/distance_geo_box_box.cpp index 9af947d9d7..9c80cd7e98 100644 --- a/test/algorithms/distance/distance_geo_box_box.cpp +++ b/test/algorithms/distance/distance_geo_box_box.cpp @@ -8,6 +8,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html +#define BOOST_GEOMETRY_TEST_DEBUG + #ifndef BOOST_TEST_MODULE #define BOOST_TEST_MODULE test_distance_geographic_box_box #endif @@ -53,21 +55,21 @@ typedef bg::strategy::distance::geographic_cross_track, + stype, double > andoyer_bb; typedef bg::strategy::distance::geographic_cross_track_box_box < bg::strategy::thomas, - bg::srs::spheroid, + stype, double > thomas_bb; typedef bg::strategy::distance::geographic_cross_track_box_box < bg::strategy::vincenty, - bg::srs::spheroid, + stype, double > vincenty_bb; diff --git a/test/algorithms/distance/distance_geo_linear_box.cpp b/test/algorithms/distance/distance_geo_linear_box.cpp new file mode 100644 index 0000000000..4b6aacf30e --- /dev/null +++ b/test/algorithms/distance/distance_geo_linear_box.cpp @@ -0,0 +1,567 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2017, 2018 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#include + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_geographic_linear_areal +#endif + +#include +#include + +#include +#include +#include + +#include "test_distance_geo_common.hpp" +//#include "test_empty_geometry.hpp" + + +template +void test_distance_segment_polygon(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/polygon distance tests" << std::endl; +#endif + typedef bg::model::segment segment_type; + typedef bg::model::polygon polygon_type; + typedef test_distance_of_geometries tester; + + std::string const polygon = "POLYGON((10 10,0 20, 15 30, 20 15, 15 10, 10 10))"; + + tester::apply("s-r-1", "SEGMENT(0 0, 0 10)", polygon, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +template +void test_distance_linestring_polygon(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/polygon distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::polygon polygon_type; + typedef test_distance_of_geometries tester; + + std::string const polygon = "POLYGON((10 10,0 20, 15 30, 20 15, 15 10, 10 10))"; + + tester::apply("l-r-1", "LINESTRING(0 0, 0 10)", polygon, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +template +void test_distance_multi_linestring_polygon(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/polygon distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::multi_linestring multi_linestring_type; + typedef bg::model::polygon polygon_type; + typedef test_distance_of_geometries tester; + + std::string const polygon = "POLYGON((10 10,0 20, 15 30, 20 15, 15 10, 10 10))"; + + tester::apply("ml-r-1", "MULTILINESTRING((0 0, 0 10)(0 0, 10 0))", polygon, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +//===================================================================== + +template +void test_distance_segment_multi_polygon(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/multi_polygon distance tests" << std::endl; +#endif + typedef bg::model::segment segment_type; + typedef bg::model::polygon polygon_type; + typedef bg::model::multi_polygon multi_polygon_type; + typedef test_distance_of_geometries tester; + + std::string const mp = "MULTIPOLYGON(((20 20, 20 30, 30 40, 20 20)),\ + ((10 10,0 20, 15 30, 20 15, 15 10, 10 10)))"; + + tester::apply("s-r-1", "SEGMENT(0 0, 0 10)", mp, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +template +void test_distance_linestring_multi_polygon(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/multi_polygon distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::polygon polygon_type; + typedef bg::model::multi_polygon multi_polygon_type; + typedef test_distance_of_geometries tester; + + std::string const mp = "MULTIPOLYGON(((20 20, 20 30, 30 40, 20 20)),\ + ((10 10,0 20, 15 30, 20 15, 15 10, 10 10)))"; + + tester::apply("l-r-1", "LINESTRING(0 0, 0 10)", mp, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +template +void test_distance_multi_linestring_multi_polygon(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/multi_polygon distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::multi_linestring multi_linestring_type; + typedef bg::model::polygon polygon_type; + typedef bg::model::multi_polygon multi_polygon_type; + typedef test_distance_of_geometries tester; + + std::string const polygon = "MULTIPOLYGON(((20 20, 20 30, 30 40, 20 20)),\ + ((10 10,0 20, 15 30, 20 15, 15 10, 10 10)))"; + + tester::apply("ml-r-1", "MULTILINESTRING((0 0, 0 10)(0 0, 10 0))", polygon, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +//===================================================================== + +template +void test_distance_segment_ring(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/ring distance tests" << std::endl; +#endif + typedef bg::model::segment segment_type; + typedef bg::model::ring ring_type; + typedef test_distance_of_geometries tester; + + std::string const ring = "POLYGON((10 10,0 20, 15 30, 20 15, 15 10, 10 10))"; + + tester::apply("s-r-1", "SEGMENT(0 0, 0 10)", ring, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +template +void test_distance_linestring_ring(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/ring distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::ring ring_type; + typedef test_distance_of_geometries tester; + + std::string const ring = "POLYGON((10 10,0 20, 15 30, 20 15, 15 10, 10 10))"; + + tester::apply("l-r-1", "LINESTRING(0 0, 0 10)", ring, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +template +void test_distance_multi_linestring_ring(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/ring distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::multi_linestring multi_linestring_type; + typedef bg::model::ring ring_type; + typedef test_distance_of_geometries tester; + + std::string const ring = "POLYGON((10 10,0 20, 15 30, 20 15, 15 10, 10 10))"; + + tester::apply("ml-r-1", "MULTILINESTRING((0 0, 0 10)(0 0, 10 0))", ring, + ps_distance("POINT(0 10)", "SEGMENT(0 20, 10 10)", strategy_ps), + strategy_ps, true, false, false); +} + +//====================================================================== + +template +void test_distance_segment_box(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps, + Strategy_sb const& strategy_sb) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/box distance tests" << std::endl; +#endif + typedef bg::model::segment segment_type; + typedef bg::model::box box_type; + typedef test_distance_of_geometries tester; + + std::string const box_north = "BOX(10 10,20 20)"; + + tester::apply("sb1-1a", "SEGMENT(0 0, 0 20)", box_north, + pp_distance("POINT(0 20)", "POINT(10 20)", strategy_pp), + strategy_sb); + //segment with slope + tester::apply("sb1-1b", "SEGMENT(10 5, 20 6)", box_north, + pp_distance("POINT(20 6)", "POINT(20 10)", strategy_pp), + strategy_sb); + tester::apply("sb1-2", "SEGMENT(0 0, 0 10)", box_north, + ps_distance("POINT(0 10)", "SEGMENT(10 10,10 20)", strategy_ps), + strategy_sb); + tester::apply("sb1-3", "SEGMENT(0 0, 0 15)", box_north, + ps_distance("POINT(0 15)", "SEGMENT(10 10,10 20)", strategy_ps), + strategy_sb); + tester::apply("sb1-4", "SEGMENT(0 0, 0 25)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(0 0,0 25)", strategy_ps), + strategy_sb); + tester::apply("sb1-5", "SEGMENT(0 10, 0 25)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(0 0,0 25)", strategy_ps), + strategy_sb); + + tester::apply("sb2-2", "SEGMENT(0 5, 15 5)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(0 5,15 5)", strategy_ps), + strategy_sb); + tester::apply("sb2-3a", "SEGMENT(0 5, 20 5)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(0 5,20 5)", strategy_ps), + strategy_sb); + + // Test segments below box + tester::apply("test_b1", "SEGMENT(0 5, 9 5)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(0 5, 9 5)", strategy_ps), + strategy_sb); + tester::apply("test_b2", "SEGMENT(0 5, 10 5)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(0 5, 10 5)", strategy_ps), + strategy_sb); + tester::apply("test_b3", "SEGMENT(0 5, 11 5)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(0 5, 11 5)", strategy_ps), + strategy_sb); + tester::apply("test_b4", "SEGMENT(0 5, 20 5)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(0 5,20 5)", strategy_ps), + strategy_sb); + tester::apply("test_b5", "SEGMENT(0 5, 22 5)", box_north, + ps_distance("POINT(11 10)", "SEGMENT(0 5,22 5)", strategy_ps), + strategy_sb); + tester::apply("test_b6", "SEGMENT(10 5, 20 5)", box_north, + ps_distance("POINT(15 10)", "SEGMENT(10 5,20 5)", strategy_ps), + strategy_sb); + tester::apply("test_b7", "SEGMENT(10 5, 22 5)", box_north, + ps_distance("POINT(16 10)", "SEGMENT(10 5,22 5)", strategy_ps), + strategy_sb); + tester::apply("test_b8", "SEGMENT(12 5, 22 5)", box_north, + ps_distance("POINT(17 10)", "SEGMENT(12 5,22 5)", strategy_ps), + strategy_sb); + tester::apply("test_b9", "SEGMENT(18 5, 22 5)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(18 5,22 5)", strategy_ps), + strategy_sb); + tester::apply("test_b10", "SEGMENT(18 5, 24 5)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(18 5,24 5)", strategy_ps), + strategy_sb); + tester::apply("test_b11", "SEGMENT(20 5, 24 5)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(20 5,24 5)", strategy_ps), + strategy_sb); + tester::apply("test_b12", "SEGMENT(22 5, 24 5)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(22 5,24 5)", strategy_ps), + strategy_sb); + tester::apply("test_b13", "SEGMENT(0 5, 125 5)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(0 5, 125 5)", strategy_ps), + strategy_sb); + + // Test segments above box + tester::apply("test_a1", "SEGMENT(0 25, 9 25)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(0 25, 9 25)", strategy_ps), + strategy_sb); + tester::apply("test_a2", "SEGMENT(0 25, 10 25)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(0 25, 10 25)", strategy_ps), + strategy_sb); + tester::apply("test_a3", "SEGMENT(0 25, 11 25)", box_north, + ps_distance("POINT(11 20)", "SEGMENT(0 25, 11 25)", strategy_ps), + strategy_sb); + tester::apply("test_a4", "SEGMENT(0 25, 20 25)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(0 25, 20 25)", strategy_ps), + strategy_sb); + tester::apply("test_a5", "SEGMENT(0 25, 22 25)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(0 25, 22 25)", strategy_ps), + strategy_sb); + tester::apply("test_a6", "SEGMENT(10 25, 20 25)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(10 25, 20 25)", strategy_ps), + strategy_sb); + tester::apply("test_a7", "SEGMENT(10 25, 22 25)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(10 25, 22 25)", strategy_ps), + strategy_sb); + tester::apply("test_a8", "SEGMENT(12 25, 22 25)", box_north, + ps_distance("POINT(12 20)", "SEGMENT(12 25, 22 25)", strategy_ps), + strategy_sb); + tester::apply("test_a9", "SEGMENT(18 25, 22 25)", box_north, + ps_distance("POINT(18 20)", "SEGMENT(18 25, 22 25)", strategy_ps), + strategy_sb); + tester::apply("test_a10", "SEGMENT(18 25, 24 25)", box_north, + ps_distance("POINT(18 20)", "SEGMENT(18 25, 24 25)", strategy_ps), + strategy_sb); + tester::apply("test_a11", "SEGMENT(20 25, 24 25)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(20 25, 24 25)", strategy_ps), + strategy_sb); + tester::apply("test_a12", "SEGMENT(22 25, 24 25)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(22 25, 24 25)", strategy_ps), + strategy_sb); + + // Segments left-right of box + tester::apply("test_l1", "SEGMENT(0 5, 9 5)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(0 5, 9 5)", strategy_ps), + strategy_sb); + tester::apply("test_l2", "SEGMENT(0 10, 9 10)", box_north, + ps_distance("POINT(9 10)", "SEGMENT(10 10, 10 20)", strategy_ps), + strategy_sb); + tester::apply("test_l3", "SEGMENT(0 10, 9 15)", box_north, + ps_distance("POINT(9 15)", "SEGMENT(10 10, 10 20)", strategy_ps), + strategy_sb); + tester::apply("test_l4", "SEGMENT(0 10, 0 15)", box_north, + ps_distance("POINT(0 15)", "SEGMENT(10 10, 10 20)", strategy_ps), + strategy_sb); + tester::apply("test_l5", "SEGMENT(1 10, 0 15)", box_north, + ps_distance("POINT(1 10)", "SEGMENT(10 10, 10 20)", strategy_ps), + strategy_sb); + tester::apply("test_l6", "SEGMENT(0 20, 9 21)", box_north, + ps_distance("POINT(9 21)", "SEGMENT(10 10, 10 20)", strategy_ps), + strategy_sb); + tester::apply("test_r1", "SEGMENT(21 5, 29 5)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(21 5, 29 5)", strategy_ps), + strategy_sb); + tester::apply("test_r2", "SEGMENT(21 10, 29 10)", box_north, + ps_distance("POINT(21 10)", "SEGMENT(20 10, 20 20)", strategy_ps), + strategy_sb); + tester::apply("test_r3", "SEGMENT(21 10, 29 15)", box_north, + ps_distance("POINT(21 10)", "SEGMENT(20 10, 20 20)", strategy_ps), + strategy_sb); + tester::apply("test_r4", "SEGMENT(21 10, 21 15)", box_north, + ps_distance("POINT(21 15)", "SEGMENT(20 10, 20 20)", strategy_ps), + strategy_sb); + tester::apply("test_r5", "SEGMENT(21 10, 22 15)", box_north, + ps_distance("POINT(21 10)", "SEGMENT(20 10, 20 20)", strategy_ps), + strategy_sb); + tester::apply("test_r6", "SEGMENT(29 20, 21 21)", box_north, + ps_distance("POINT(21 21)", "SEGMENT(20 10, 20 20)", strategy_ps), + strategy_sb); + + //Segments on corners of box + //left-top corner + //generic + tester::apply("test_c1", "SEGMENT(9 19.5, 11 21)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(9 19.5, 11 21)", strategy_ps), + strategy_sb); + //degenerate + tester::apply("test_c2", "SEGMENT(9 19, 11 21)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(9 19, 11 21)", strategy_ps), + strategy_sb); + //left-bottom corner + //generic + tester::apply("test_c3", "SEGMENT(8.5 11, 11 9)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(8.5 11, 11 9)", strategy_ps), + strategy_sb); + //degenerate + tester::apply("test_c4", "SEGMENT(9 11, 11 9)", box_north, + 0, + strategy_sb); + //right-top corner + //generic + tester::apply("test_c5", "SEGMENT(19 21, 21 19.5)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(19 21, 21 19.5)", strategy_ps), + strategy_sb); + //degenerate + tester::apply("test_c6", "SEGMENT(19 21, 21 19)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(19 21, 21 19)", strategy_ps), + strategy_sb); + //right-bottom corner + //generic + tester::apply("test_c7", "SEGMENT(19 9, 21 10.5)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(19 9, 21 10.5)", strategy_ps), + strategy_sb); + tester::apply("test_c7", "SEGMENT(19 9, 21 11)", box_north, + 0, + strategy_sb); + + //Segment and box on different hemispheres + std::string const box_south = "BOX(10 -20,20 -10)"; + + tester::apply("test_ns1", "SEGMENT(10 20, 15 30)", box_south, + ps_distance("POINT(10 -10)", "SEGMENT(10 20, 15 30)", strategy_ps), + strategy_sb); + tester::apply("test_ns2", "SEGMENT(0 10, 12 10)", box_south, + pp_distance("POINT(12 10)", "POINT(12 -10)", strategy_pp), + strategy_sb); + tester::apply("test_ns3", "SEGMENT(10 10, 20 10)", box_south, + pp_distance("POINT(10 10)", "POINT(10 -10)", strategy_pp), + strategy_sb); + tester::apply("test_ns4", "SEGMENT(0 -10, 12 -10)", box_north, + pp_distance("POINT(12 10)", "POINT(12 -10)", strategy_pp), + strategy_sb); + tester::apply("test_ns5", "SEGMENT(10 -10, 20 -10)", box_north, + pp_distance("POINT(10 -10)", "POINT(10 10)", strategy_pp), + strategy_sb); + + //Box crossing equator + std::string const box_crossing_eq = "BOX(10 -10,20 10)"; + + tester::apply("test_cr1", "SEGMENT(10 20, 15 30)", box_crossing_eq, + pp_distance("POINT(10 10)", "POINT(10 20)", strategy_pp), + strategy_sb); + tester::apply("test_cr2", "SEGMENT(10 -20, 15 -30)", box_crossing_eq, + pp_distance("POINT(10 10)", "POINT(10 20)", strategy_pp), + strategy_sb); + + //Box crossing prime meridian + + std::string const box_crossing_mer = "BOX(-10 10,15 20)"; + + tester::apply("test_cr3", "SEGMENT(-5 25, 10 30)", box_crossing_mer, + pp_distance("POINT(-5 25)", "POINT(-5 20)", strategy_pp), + strategy_sb); + tester::apply("test_cr4", "SEGMENT(-5 5, 10 7)", box_crossing_mer, + pp_distance("POINT(10 7)", "POINT(10 10)", strategy_pp), + strategy_sb); + tester::apply("test_cr5", "SEGMENT(-5 5, 10 5)", box_crossing_mer, + ps_distance("POINT(2.5 10)", "SEGMENT(-5 5, 10 5)", strategy_ps), + strategy_sb); + + + //Geometries in south hemisphere + tester::apply("test_south1", "SEGMENT(10 -30, 15 -30)", box_south, + ps_distance("POINT(10 -20)", "SEGMENT(10 -30, 15 -30)", strategy_ps), + strategy_sb); + + //Segments in boxes corner + tester::apply("corner1", "SEGMENT(17 21, 25 20)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(17 21, 25 20)", strategy_ps), + strategy_sb); + tester::apply("corner2", "SEGMENT(17 21, 0 20)", box_north, + ps_distance("POINT(10 20)", "SEGMENT(17 21, 0 20)", strategy_ps), + strategy_sb); + tester::apply("corner3", "SEGMENT(17 5, 0 10)", box_north, + ps_distance("POINT(10 10)", "SEGMENT(17 5, 0 10)", strategy_ps), + strategy_sb); + tester::apply("corner4", "SEGMENT(17 5, 25 9)", box_north, + ps_distance("POINT(20 10)", "SEGMENT(17 5, 25 9)", strategy_ps), + strategy_sb); +} + +template +void test_distance_linestring_box(Strategy_ps const& strategy_ps, Strategy_sb const& strategy_sb) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/box distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::box box_type; + typedef test_distance_of_geometries tester; + + std::string const box_north = "BOX(10 10,20 20)"; + + tester::apply("sl1", "LINESTRING(0 20, 15 21, 25 19.9, 21 5, 15 5, 0 10)", box_north, + ps_distance("POINT(20 20)", "SEGMENT(15 21, 25 19.9)", strategy_ps), + strategy_ps, true, false, false); + + tester::apply("sl2", "LINESTRING(0 20, 15 21, 25 19.9, 21 5, 15 5, 15 15)", box_north, + 0, strategy_ps, true, false, false); + + tester::apply("sl3", "LINESTRING(0 20, 15 21, 25 19.9, 21 5, 15 5, 2 20)", box_north, + 0, strategy_ps, true, false, false); +} + +template +void test_distance_multi_linestring_box(Strategy_ps const& strategy_ps, Strategy_sb const& strategy_sb) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multi_linestring/box distance tests" << std::endl; +#endif + typedef bg::model::linestring linestring_type; + typedef bg::model::multi_linestring multi_linestring_type; + typedef bg::model::box box_type; + typedef test_distance_of_geometries tester; + + std::string const box_north = "BOX(10 10,20 20)"; + + tester::apply("sl1", "MULTILINESTRING((0 20, 15 21, 25 19.9, 21 5, 15 5, 0 10)(25 20, 22 4, 0 0))", box_north, + ps_distance("POINT(20 20)", "SEGMENT(15 21, 25 19.9)", strategy_ps), + strategy_sb, true, false, false); +} + +//=========================================================================== +//=========================================================================== +//=========================================================================== + + +template +void test_all_l_ar(Strategy_pp pp_strategy, Strategy_ps ps_strategy, Strategy_sb sb_strategy) +{ + test_distance_segment_polygon(pp_strategy, ps_strategy); + test_distance_linestring_polygon(pp_strategy, ps_strategy); + test_distance_multi_linestring_polygon(pp_strategy, ps_strategy); + + test_distance_segment_multi_polygon(pp_strategy, ps_strategy); + test_distance_linestring_multi_polygon(pp_strategy, ps_strategy); + test_distance_multi_linestring_multi_polygon(pp_strategy, ps_strategy); + + test_distance_segment_ring(pp_strategy, ps_strategy); + test_distance_linestring_ring(pp_strategy, ps_strategy); + test_distance_multi_linestring_ring(pp_strategy, ps_strategy); + + test_distance_segment_box(pp_strategy, ps_strategy, sb_strategy); + //test_distance_linestring_box(ps_strategy, sb_strategy); + //test_distance_multi_linestring_box(ps_strategy, sb_strategy); + + //test_more_empty_input_linear_areal(ps_strategy); +} + +BOOST_AUTO_TEST_CASE( test_all_linear_areal ) +{ + typedef bg::model::point > + sph_point; + test_all_l_ar(spherical_pp(), spherical_ps(), spherical_sb()); + + typedef bg::model::point > geo_point; + + test_all_l_ar(vincenty_pp(), vincenty_ps(), vincenty_sb()); + test_all_l_ar(thomas_pp(), thomas_ps(), thomas_sb()); + test_all_l_ar(andoyer_pp(), andoyer_ps(), andoyer_sb()); +} diff --git a/test/algorithms/distance/distance_geo_pl_l.cpp b/test/algorithms/distance/distance_geo_pl_l.cpp index 72f080b24f..1799e850df 100644 --- a/test/algorithms/distance/distance_geo_pl_l.cpp +++ b/test/algorithms/distance/distance_geo_pl_l.cpp @@ -240,13 +240,23 @@ void test_distance_point_segment(Strategy_pp const& strategy_pp, tester::apply("p-s-mer1", "POINT(2.5 2)", "SEGMENT(2 2,2 4)", - pp_distance("POINT(2.5 2)", "POINT(2 2)", strategy_pp), + pp_distance("POINT(2.5 2)", "POINT(2 2.000076608014728)", strategy_pp), strategy_ps, true, true); tester::apply("p-s-mer3", "POINT(2.5 5)", "SEGMENT(2 2,2 4)", pp_distance("POINT(2.5 5)", "POINT(2 4)", strategy_pp), strategy_ps, true, true); + tester::apply("p-s-mer4", + "POINT(0 20)", + "SEGMENT(0 40,180 80)", + pp_distance("POINT(0 20)", "POINT(0 40)", strategy_pp), + strategy_ps, true, true); + tester::apply("p-s-mer5", + "POINT(0 20)", + "SEGMENT(0 40,0 80)", + pp_distance("POINT(0 20)", "POINT(0 40)", strategy_pp), + strategy_ps, true, true); //degenerate segment tester::apply("p-s-deg", @@ -329,6 +339,34 @@ void test_distance_point_segment(Strategy_pp const& strategy_pp, 0, strategy_ps, true, true); + tester::apply("p-s-20", + "POINT(80 89)", + "SEGMENT(0 0,180 0)", + pp_distance("POINT(80 89)", "POINT(0 89.82633489283377)", strategy_pp), + strategy_ps, true, true); + + tester::apply("p-s-21", + "POINT(80 89)", + "SEGMENT(0 -1,180 1)", + pp_distance("POINT(80 89)", "POINT(0 89.82633489283377)", strategy_pp), + strategy_ps, true, true); + + // meridian special case + tester::apply("p-s-mer1", + "POINT(2.5 3)", + "SEGMENT(2 2,2 4)", + pp_distance("POINT(2.5 3)", "POINT(2 3.000114792872075)", strategy_pp), + strategy_ps, true, true); + tester::apply("p-s-mer2", + "POINT(1 80)", + "SEGMENT(0 0,0 90)", + pp_distance("POINT(1 80)", "POINT(0 80.00149225834545)", strategy_pp), + strategy_ps, true, true); + tester::apply("p-s-mer3", + "POINT(2 0)", + "SEGMENT(1 -1,1 0)", + pp_distance("POINT(2 0)", "POINT(1 0)", strategy_pp), + strategy_ps, true, true); } template @@ -343,38 +381,13 @@ void test_distance_point_segment_no_thomas(Strategy_pp const& strategy_pp, typedef test_distance_of_geometries tester; // thomas strategy is failing for those test cases + // this is because of inaccurate results for points close to poles - // meridian special case - tester::apply("p-s-mer2", - "POINT(2.5 3)", - "SEGMENT(2 2,2 4)", - pp_distance("POINT(2.5 3)", "POINT(2 3.000114792872075)", strategy_pp), - strategy_ps, true, true); - - tester::apply("p-s-mer4", - "POINT(1 80)", - "SEGMENT(0 0,0 90)", - pp_distance("POINT(1 80)", "POINT(0 80.00149225834545)", strategy_pp), - strategy_ps, true, true); - - // Half meridian segment passing through pole tester::apply("p-s-19", "POINT(90 89)", "SEGMENT(0 0,180 0)", pp_distance("POINT(90 89)", "POINT(90 90)", strategy_pp), strategy_ps, true, true); - - tester::apply("p-s-20", - "POINT(80 89)", - "SEGMENT(0 0,180 0)", - pp_distance("POINT(80 89)", "POINT(0 89.82633489283377)", strategy_pp), - strategy_ps, true, true); - - tester::apply("p-s-20", - "POINT(80 89)", - "SEGMENT(0 -1,180 1)", - pp_distance("POINT(80 89)", "POINT(0 89.82633489283377)", strategy_pp), - strategy_ps, true, true); } //=========================================================================== @@ -393,42 +406,42 @@ void test_distance_point_linestring(Strategy_pp const& strategy_pp, "POINT(0 0)", "LINESTRING(2 0,2 0)", pp_distance("POINT(0 0)", "POINT(2 0)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-l-02", "POINT(0 0)", "LINESTRING(2 0,3 0)", pp_distance("POINT(0 0)", "POINT(2 0)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-l-03", "POINT(2.5 3)", "LINESTRING(2 0,3 0)", pp_distance("POINT(2.5 3)", "POINT(2.5 0)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-l-04", "POINT(2 0)", "LINESTRING(2 0,3 0)", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-l-05", "POINT(3 0)", "LINESTRING(2 0,3 0)", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-l-06", "POINT(2.5 0)", "LINESTRING(2 0,3 0)", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-l-07", "POINT(7.5 10)", "LINESTRING(1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 0)", ps_distance("POINT(7.5 10)", "SEGMENT(7 0,8 0)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-l-08", "POINT(7.5 10)", "LINESTRING(1 1,2 1,3 1,4 1,5 1,6 1,7 1,20 2,21 2)", ps_distance("POINT(7.5 10)", "SEGMENT(7 1,20 2)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); } void test_distance_point_linestring_strategies() @@ -439,19 +452,22 @@ void test_distance_point_linestring_strategies() "POINT(2.5 3)", "LINESTRING(2 1,3 1)", 221147.24332788656, - vincenty_strategy()); + vincenty_strategy(), + true, false, false); tester::apply("p-l-03", "POINT(2.5 3)", "LINESTRING(2 1,3 1)", 221147.36682199029, - thomas_strategy()); + thomas_strategy(), + true, false, false); tester::apply("p-l-03", "POINT(2.5 3)", "LINESTRING(2 1,3 1)", 221144.76527049288, - andoyer_strategy()); + andoyer_strategy(), + true, false, false); } //=========================================================================== @@ -473,37 +489,37 @@ void test_distance_point_multilinestring(Strategy_pp const& strategy_pp, "POINT(0 0)", "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", pp_distance("POINT(0 0)", "POINT(2 0)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-ml-02", "POINT(2.5 3)", "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", pp_distance("POINT(2.5 3)", "POINT(2.5 0)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-ml-03", "POINT(2 0)", "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-ml-04", "POINT(3 0)", "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-ml-05", "POINT(2.5 0)", "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-ml-06", "POINT(7.5 10)", "MULTILINESTRING((-5 0,-3 0),(2 0,3 0,4 0,5 0,6 0,20 1,21 1))", ps_distance("POINT(7.5 10)", "SEGMENT(6 0,20 1)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); tester::apply("p-ml-07", "POINT(-8 10)", "MULTILINESTRING((-20 10,-19 11,-18 10,-6 0,-5 0,-3 0),(2 0,6 0,20 1,21 1))", ps_distance("POINT(-8 10)", "SEGMENT(-6 0,-18 10)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); } //=========================================================================== @@ -525,28 +541,27 @@ void test_distance_linestring_multipoint(Strategy_pp const& strategy_pp, "LINESTRING(2 0,0 2,100 80)", "MULTIPOINT(0 0,1 0,0 1,1 1)", ps_distance("POINT(1 1)", "SEGMENT(2 0,0 2)", strategy_ps), - strategy_ps); - + strategy_ps, true, false, false); tester::apply("l-mp-02", "LINESTRING(4 0,0 4,100 80)", "MULTIPOINT(0 0,1 0,0 1,1 1)", ps_distance("POINT(1 1)", "SEGMENT(0 4,4 0)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); tester::apply("l-mp-03", "LINESTRING(1 1,2 2,100 80)", "MULTIPOINT(0 0,1 0,0 1,1 1)", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("l-mp-04", "LINESTRING(3 3,4 4,100 80)", "MULTIPOINT(0 0,1 0,0 1,1 1)", pp_distance("POINT(1 1)", "POINT(3 3)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("l-mp-05", "LINESTRING(0 0,10 0,10 10,0 10,0 0)", "MULTIPOINT(1 -1,80 80,5 0,150 90)", 0, - strategy_ps); + strategy_ps, true, false, false); } //=========================================================================== @@ -567,22 +582,22 @@ void test_distance_multipoint_multilinestring(Strategy_pp const& strategy_pp, "MULTIPOINT(0 0,1 0,0 1,1 1)", "MULTILINESTRING((2 0,0 2),(2 2,3 3))", ps_distance("POINT(1 1)", "SEGMENT(2 0,0 2)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); tester::apply("mp-ml-02", "MULTIPOINT(0 0,1 0,0 1,1 1)", "MULTILINESTRING((3 0,0 3),(4 4,5 5))", ps_distance("POINT(1 1)", "SEGMENT(3 0,0 3)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); tester::apply("mp-ml-03", "MULTIPOINT(0 0,1 0,0 1,1 1)", "MULTILINESTRING((4 4,5 5),(1 1,2 2))", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("mp-ml-04", "MULTIPOINT(0 0,1 0,0 1,1 1)", "MULTILINESTRING((4 4,3 3),(4 4,5 5))", pp_distance("POINT(1 1)", "POINT(3 3)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); } //=========================================================================== @@ -601,27 +616,27 @@ void test_distance_multipoint_segment(Strategy_pp const& strategy_pp, "MULTIPOINT(0 0,1 0,0 1,1 1)", "SEGMENT(2 0,0 2)", ps_distance("POINT(1 1)", "SEGMENT(2 0,0 2)", strategy_ps), - strategy_ps); + strategy_ps, true, false, false); tester::apply("mp-s-02", "MULTIPOINT(0 0,1 0,0 1,1 1)", "SEGMENT(0 -3,1 -10)", pp_distance("POINT(0 0)", "POINT(0 -3)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("mp-s-03", "MULTIPOINT(0 0,1 0,0 1,1 1)", "SEGMENT(1 1,2 2)", 0, - strategy_ps); + strategy_ps, true, false, false); tester::apply("mp-s-04", "MULTIPOINT(0 0,1 0,0 1,1 1)", "SEGMENT(3 3,4 4)", pp_distance("POINT(1 1)", "POINT(3 3)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); tester::apply("mp-s-05", "MULTIPOINT(0 0,1 0,0 1,1 1)", "SEGMENT(0.5 -3,1 -10)", pp_distance("POINT(1 0)", "POINT(0.5 -3)", strategy_pp), - strategy_ps); + strategy_ps, true, false, false); } //=========================================================================== @@ -668,7 +683,7 @@ BOOST_AUTO_TEST_CASE( test_all_point_segment ) test_distance_point_segment(andoyer_pp(), andoyer_strategy()); test_distance_point_segment_no_thomas(vincenty_pp(), vincenty_strategy()); - ///test_distance_point_segment_no_thomas(thomas_pp(), thomas_strategy()); + //test_distance_point_segment_no_thomas(thomas_pp(), thomas_strategy()); test_distance_point_segment_no_thomas(andoyer_pp(), andoyer_strategy()); test_distance_point_linestring(vincenty_pp(), vincenty_strategy()); @@ -695,4 +710,5 @@ BOOST_AUTO_TEST_CASE( test_all_point_segment ) test_empty_input_pointlike_linear(vincenty_strategy()); test_empty_input_pointlike_linear(thomas_strategy()); test_empty_input_pointlike_linear(andoyer_strategy()); + } diff --git a/test/algorithms/distance/distance_geo_pl_pl.cpp b/test/algorithms/distance/distance_geo_pl_pl.cpp index a5a2acbaee..60c03de147 100644 --- a/test/algorithms/distance/distance_geo_pl_pl.cpp +++ b/test/algorithms/distance/distance_geo_pl_pl.cpp @@ -62,13 +62,13 @@ void test_distance_multipoint_point(Strategy const& strategy) "MULTIPOINT(1 1,1 2,2 3)", "POINT(0 0)", pp_distance("POINT(0 0)","POINT(1 1)",strategy), - strategy); + strategy, true, false, false); tester::apply("mp-p-01", "MULTIPOINT(0 0,0 2,2 0,2 2)", "POINT(1.1 1.1)", pp_distance("POINT(1.1 1.1)","POINT(2 2)",strategy), - strategy); + strategy, true, false, false); } //=========================================================================== diff --git a/test/algorithms/distance/distance_geo_point_box.cpp b/test/algorithms/distance/distance_geo_point_box.cpp index 5968f60417..744acfed68 100644 --- a/test/algorithms/distance/distance_geo_point_box.cpp +++ b/test/algorithms/distance/distance_geo_point_box.cpp @@ -56,21 +56,21 @@ typedef bg::strategy::distance::geographic_cross_track, + stype, double > andoyer_pb; typedef bg::strategy::distance::geographic_cross_track_point_box < bg::strategy::thomas, - bg::srs::spheroid, + stype, double > thomas_pb; typedef bg::strategy::distance::geographic_cross_track_point_box < bg::strategy::vincenty, - bg::srs::spheroid, + stype, double > vincenty_pb; @@ -436,11 +436,11 @@ void test_distance_multipoint_box(Strategy_pp const& strategy_pp, tester::apply("mpb1-1a", "MULTIPOINT(5 25,25 26)", box1, pp_distance("POINT(5 25)", "POINT(10 20)", strategy_pp), - strategy_pb); + strategy_pb, true, false, false); tester::apply("mpb1-2e", "MULTIPOINT(110 10,110 9,110 0)", box1, ps_distance("POINT(110 10)", "SEGMENT(20 10,20 20)", strategy_ps), - strategy_pb); + strategy_pb, true, false, false); } //=========================================================================== diff --git a/test/algorithms/distance/distance_linear_areal.cpp b/test/algorithms/distance/distance_linear_areal.cpp index ae396ba47b..cfc0e64a12 100644 --- a/test/algorithms/distance/distance_linear_areal.cpp +++ b/test/algorithms/distance/distance_linear_areal.cpp @@ -7,7 +7,7 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html - +#define BOOST_GEOMETRY_TEST_DEBUG #include #ifndef BOOST_TEST_MODULE @@ -38,6 +38,7 @@ typedef bg::default_distance_result::type return_type; typedef bg::strategy::distance::pythagoras<> point_point_strategy; typedef bg::strategy::distance::projected_point<> point_segment_strategy; +typedef bg::strategy::distance::cartesian_segment_box<> segment_box_strategy; //=========================================================================== @@ -952,7 +953,7 @@ BOOST_AUTO_TEST_CASE( test_all_multilinestring_ring ) BOOST_AUTO_TEST_CASE( test_all_segment_box ) { - test_distance_segment_box(point_segment_strategy()); + test_distance_segment_box(segment_box_strategy()); } BOOST_AUTO_TEST_CASE( test_all_linestring_box ) diff --git a/test/algorithms/distance/distance_se_box_box.cpp b/test/algorithms/distance/distance_se_box_box.cpp index 096091e20c..2ea7dbe663 100644 --- a/test/algorithms/distance/distance_se_box_box.cpp +++ b/test/algorithms/distance/distance_se_box_box.cpp @@ -36,7 +36,7 @@ typedef bg::default_distance_result::type return_type; typedef distance::cross_track_box_box<> box_box_strategy; typedef distance::cross_track_box_box < -void, distance::comparable::cross_track<> + void, distance::comparable::haversine<> > comparable_box_box_strategy; //=========================================================================== diff --git a/test/algorithms/distance/distance_se_point_box.cpp b/test/algorithms/distance/distance_se_point_box.cpp index e5b630b72a..e5c39bcb74 100644 --- a/test/algorithms/distance/distance_se_point_box.cpp +++ b/test/algorithms/distance/distance_se_point_box.cpp @@ -7,7 +7,7 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html - +#define BOOST_GEOMETRY_TEST_DEBUG #include #ifndef BOOST_TEST_MODULE @@ -37,7 +37,7 @@ typedef bg::default_distance_result::type return_type; typedef distance::cross_track_point_box<> point_box_strategy; typedef distance::cross_track_point_box < - void, distance::comparable::cross_track<> + void, distance::comparable::haversine<> > comparable_point_box_strategy; //=========================================================================== diff --git a/test/algorithms/distance/test_distance.hpp b/test/algorithms/distance/test_distance.hpp index 82154fe237..cfda00e29d 100644 --- a/test/algorithms/distance/test_distance.hpp +++ b/test/algorithms/distance/test_distance.hpp @@ -15,7 +15,6 @@ #include #include - // Define a custom distance strategy // For this one, the "taxicab" distance, // see http://en.wikipedia.org/wiki/Taxicab_geometry diff --git a/test/algorithms/distance/test_distance_geo_common.hpp b/test/algorithms/distance/test_distance_geo_common.hpp index a81af7ad1b..17013b77fe 100644 --- a/test/algorithms/distance/test_distance_geo_common.hpp +++ b/test/algorithms/distance/test_distance_geo_common.hpp @@ -44,16 +44,96 @@ namespace bg = ::boost::geometry; +typedef bg::srs::spheroid stype; + +// Spherical strategy for point-point distance + +typedef bg::strategy::distance::haversine spherical_pp; + +// Geo strategies for point-point distance + +typedef bg::strategy::distance::andoyer andoyer_pp; +typedef bg::strategy::distance::thomas thomas_pp; +typedef bg::strategy::distance::vincenty vincenty_pp; + +// Spherical strategy for point-segment distance + +typedef bg::strategy::distance::cross_track<> spherical_ps; + +// Geo strategies for point-segment distance + +typedef bg::strategy::distance::geographic_cross_track + andoyer_ps; + +typedef bg::strategy::distance::geographic_cross_track + thomas_ps; + +typedef bg::strategy::distance::geographic_cross_track + vincenty_ps; + +// Spherical strategy for segment-box distance + +typedef bg::strategy::distance::spherical_segment_box<> spherical_sb; + +// Geo strategies for segment-box distance + +typedef bg::strategy::distance::geographic_segment_box + andoyer_sb; + +typedef bg::strategy::distance::geographic_segment_box + thomas_sb; + +typedef bg::strategy::distance::geographic_segment_box + vincenty_sb; + + +//=========================================================================== + +template +inline typename bg::default_distance_result::type +pp_distance(std::string const& wkt1, + std::string const& wkt2, + Strategy const& strategy) +{ + Point p1, p2; + bg::read_wkt(wkt1, p1); + bg::read_wkt(wkt2, p2); + return bg::distance(p1, p2, strategy); +} + +//=========================================================================== + +template +inline typename bg::default_distance_result::type +ps_distance(std::string const& wkt1, + std::string const& wkt2, + Strategy const& strategy) +{ + Point p; + typedef bg::model::segment segment_type; + segment_type s; + bg::read_wkt(wkt1, p); + bg::read_wkt(wkt2, s); + return bg::distance(p, s, strategy); +} + //=================================================================== -//tag dispatching for swaping arguments in segments template struct dispatch { + //tag dispatching for swaping arguments in segments template static inline T swap(T const& t) { return t; } + + // mirror geometry w.r.t. equator + template + static inline T mirror(T const& t) + { + return t; + } }; // Specialization for segments @@ -71,6 +151,64 @@ template <> struct dispatch return s_swaped; } + + template + static inline Segment mirror(Segment const& s) + { + Segment s_mirror; + + bg::set<0, 0>(s_mirror, bg::get<0, 0>(s)); + bg::set<0, 1>(s_mirror, bg::get<0, 1>(s) * -1); + bg::set<1, 0>(s_mirror, bg::get<1, 0>(s)); + bg::set<1, 1>(s_mirror, bg::get<1, 1>(s) * -1); + + return s_mirror; + } +}; + +// Specialization for boxes +template <> struct dispatch +{ + template + static inline T swap(T const& t) + { + return t; + } + + template + static inline Box mirror(Box const& b) + { + Box b_mirror; + + bg::set<0, 0>(b_mirror, bg::get(b)); + bg::set<0, 1>(b_mirror, bg::get(b) * -1); + bg::set<1, 0>(b_mirror, bg::get(b)); + bg::set<1, 1>(b_mirror, bg::get(b) * -1); + + return b_mirror; + } +}; + + +// Specialization for points +template <> struct dispatch +{ + template + static inline T swap(T const& t) + { + return t; + } + + template + static inline Point mirror(Point const& p) + { + Point p_mirror; + + bg::set<0>(p_mirror, bg::get<0>(p)); + bg::set<1>(p_mirror, bg::get<1>(p) * -1); + + return p_mirror; + } }; //======================================================================== @@ -133,14 +271,16 @@ struct test_distance_of_geometries DistanceType const& expected_distance, Strategy const& strategy, bool test_reversed = true, - bool swap_geometry_args = false) + bool swap_geometry_args = false, + bool mirror_geometry = true) { Geometry1 geometry1 = from_wkt(wkt1); Geometry2 geometry2 = from_wkt(wkt2); apply(case_id, geometry1, geometry2, expected_distance, - strategy, test_reversed, swap_geometry_args); + strategy, test_reversed, swap_geometry_args, + mirror_geometry); } @@ -156,7 +296,8 @@ struct test_distance_of_geometries DistanceType const& expected_distance, Strategy const& strategy, bool test_reversed = true, - bool swap_geometry_args = false) + bool swap_geometry_args = false, + bool mirror_geometry = true) { #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << "case ID: " << case_id << "; " @@ -272,7 +413,35 @@ struct test_distance_of_geometries << std::endl; std::cout << std::endl; #endif - } + } + if (mirror_geometry) + { + Geometry1 g1 = dispatch + < + typename boost::geometry::tag::type + >::mirror(geometry1); + + Geometry2 g2 = dispatch + < + typename boost::geometry::tag::type + >::mirror(geometry2); + + // check distance with given strategy + dist = bg::distance(g1, g2, strategy); + + check_equal + < + default_distance_result + >::apply(case_id, "mirror", g1, g2, + dist, expected_distance); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "distance[mirror geometries] = " + << dist + << std::endl; + std::cout << std::endl; +#endif + } #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << std::endl; #endif diff --git a/test/strategies/distance.cpp b/test/strategies/distance.cpp index dfe47b9ec4..876e287301 100644 --- a/test/strategies/distance.cpp +++ b/test/strategies/distance.cpp @@ -12,7 +12,7 @@ #include -#include +#include #include #include #include