mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 21:44:04 +00:00
Merge branch 'develop' into feature/cluster
This commit is contained in:
commit
34db67d51d
28
circle.yml
28
circle.yml
@ -3,7 +3,7 @@
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Copyright Antony Polukhin 2014.
|
||||
# Copyright Adam Wulkiewicz 2015.
|
||||
# Copyright Adam Wulkiewicz 2015-2016.
|
||||
|
||||
general:
|
||||
branches:
|
||||
@ -38,16 +38,16 @@ dependencies:
|
||||
- sudo apt-get update
|
||||
|
||||
# gcc, g++, gcov
|
||||
- sudo apt-get install gcc-4.8 g++-4.8 build-essential
|
||||
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 10
|
||||
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 10
|
||||
- sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-4.8 10
|
||||
- sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 20
|
||||
- sudo update-alternatives --set cc /usr/bin/gcc
|
||||
- sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 20
|
||||
- sudo update-alternatives --set c++ /usr/bin/g++
|
||||
- sudo update-alternatives --config gcc
|
||||
- sudo update-alternatives --config g++
|
||||
- sudo apt-get install gcc-4.9 g++-4.9 build-essential
|
||||
#- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 10
|
||||
#- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 10
|
||||
- sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-4.9 10
|
||||
#- sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 20
|
||||
#- sudo update-alternatives --set cc /usr/bin/gcc
|
||||
#- sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 20
|
||||
#- sudo update-alternatives --set c++ /usr/bin/g++
|
||||
#- sudo update-alternatives --config gcc
|
||||
#- sudo update-alternatives --config g++
|
||||
- sudo update-alternatives --config gcov
|
||||
|
||||
# coveralls-lcov for lcov *.info to JSON conversion
|
||||
@ -86,9 +86,9 @@ dependencies:
|
||||
|
||||
# download and install the latest lcov
|
||||
# do not use the old one from sources
|
||||
- wget http://downloads.sourceforge.net/ltp/lcov-1.11.tar.gz
|
||||
- tar xvzf lcov-1.11.tar.gz
|
||||
- cd lcov-1.11 && sudo make install
|
||||
- wget http://downloads.sourceforge.net/ltp/lcov-1.12.tar.gz
|
||||
- tar xvzf lcov-1.12.tar.gz
|
||||
- cd lcov-1.12 && sudo make install
|
||||
|
||||
# create a direcotry for temporary coverage data
|
||||
- if [ ! -d $COVERAGE_ROOT ]; then mkdir $COVERAGE_ROOT; fi
|
||||
|
@ -185,4 +185,5 @@ execfile("make_qbk.py")
|
||||
os.chdir("..")
|
||||
|
||||
# Use either bjam or b2 or ../../../b2 (the last should be done on Release branch)
|
||||
run_command("b2")
|
||||
if "--release-build" not in sys.argv:
|
||||
run_command("b2")
|
||||
|
@ -1,15 +1,16 @@
|
||||
[/============================================================================
|
||||
Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
Copyright (c) 2009-2015 Barend Gehrels, Geodan, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2015 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2009-2015 Mateusz Loskot <mateusz@loskot.net>, London, UK
|
||||
Copyright (c) 2011-2015 Adam Wulkiewicz
|
||||
Copyright (c) 2009-2016 Barend Gehrels, Geodan, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2016 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2009-2016 Mateusz Loskot <mateusz@loskot.net>, London, UK.
|
||||
Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
This file was modified by Oracle on 2015.
|
||||
Modifications copyright (c) 2015, Oracle and/or its affiliates.
|
||||
This file was modified by Oracle on 2015, 2016.
|
||||
Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
Use, modification and distribution is subject to the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -18,6 +19,20 @@
|
||||
|
||||
[section:release_notes Release Notes]
|
||||
|
||||
[/=================]
|
||||
[heading Boost 1.61]
|
||||
[/=================]
|
||||
|
||||
[*Solved tickets]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11637 11637] Unused parameter warning.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11917 11917] Andoyer distance strategy returns 0 for antipodal points (default geographic distance).
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11928 11928] Improvement of the accuracy of surveyor area strategy.
|
||||
|
||||
[*Bugfixes]
|
||||
|
||||
* Fix wrong result of intersects/disjoints for Segment and Box when Segment is parallel to Box's face.
|
||||
|
||||
[/=================]
|
||||
[heading Boost 1.60]
|
||||
[/=================]
|
||||
|
@ -277,7 +277,7 @@ inline void buffer(GeometryIn const& geometry_in,
|
||||
rescale_policy_type rescale_policy
|
||||
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
|
||||
|
||||
detail::buffer::buffer_inserter<polygon_type>(geometry_in, std::back_inserter(geometry_out),
|
||||
detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
|
||||
distance_strategy,
|
||||
side_strategy,
|
||||
join_strategy,
|
||||
|
@ -83,7 +83,7 @@ struct hull_to_geometry
|
||||
geometry::point_order<OutputGeometry>::value,
|
||||
geometry::closure<OutputGeometry>::value
|
||||
>::apply(geometry,
|
||||
std::back_inserter(
|
||||
range::back_inserter(
|
||||
// Handle linestring, ring and polygon the same:
|
||||
detail::as_range
|
||||
<
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2015 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2016 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@ -49,23 +49,17 @@ struct andoyer_inverse
|
||||
T2 const& lat2,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
CT const c0 = CT(0);
|
||||
CT const c1 = CT(1);
|
||||
CT const pi = math::pi<CT>();
|
||||
|
||||
result_type result;
|
||||
|
||||
// coordinates in radians
|
||||
|
||||
if ( math::equals(lon1, lon2)
|
||||
&& math::equals(lat1, lat2) )
|
||||
if ( math::equals(lon1, lon2) && math::equals(lat1, lat2) )
|
||||
{
|
||||
result.set(CT(0), CT(0));
|
||||
return result;
|
||||
}
|
||||
|
||||
CT const pi_half = math::pi<CT>() / CT(2);
|
||||
|
||||
if ( math::equals(math::abs(lat1), pi_half)
|
||||
&& math::equals(math::abs(lat2), pi_half) )
|
||||
{
|
||||
result.set(CT(0), CT(0));
|
||||
result.set(c0, c0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -80,22 +74,16 @@ struct andoyer_inverse
|
||||
// H,G,T = infinity if cos_d = 1 or cos_d = -1
|
||||
// lat1 == +-90 && lat2 == +-90
|
||||
// lat1 == lat2 && lon1 == lon2
|
||||
CT const cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon;
|
||||
CT const d = acos(cos_d);
|
||||
CT const sin_d = sin(d);
|
||||
|
||||
// just in case since above lat1 and lat2 is checked
|
||||
// the check below is equal to cos_d == 1 || cos_d == -1 || d == 0
|
||||
if ( math::equals(sin_d, CT(0)) )
|
||||
{
|
||||
result.set(CT(0), CT(0));
|
||||
return result;
|
||||
}
|
||||
|
||||
// if the function returned before this place
|
||||
// and endpoints were on the poles +-90 deg
|
||||
// in this case the azimuth could either be 0 or +-pi
|
||||
CT cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon;
|
||||
// on some platforms cos_d may be outside valid range
|
||||
if (cos_d < -c1)
|
||||
cos_d = -c1;
|
||||
else if (cos_d > c1)
|
||||
cos_d = c1;
|
||||
|
||||
CT const d = acos(cos_d); // [0, pi]
|
||||
CT const sin_d = sin(d); // [-1, 1]
|
||||
|
||||
CT const f = detail::flattening<CT>(spheroid);
|
||||
|
||||
if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
|
||||
@ -103,11 +91,18 @@ struct andoyer_inverse
|
||||
CT const K = math::sqr(sin_lat1-sin_lat2);
|
||||
CT const L = math::sqr(sin_lat1+sin_lat2);
|
||||
CT const three_sin_d = CT(3) * sin_d;
|
||||
// H or G = infinity if cos_d = 1 or cos_d = -1
|
||||
CT const H = (d+three_sin_d)/(CT(1)-cos_d);
|
||||
CT const G = (d-three_sin_d)/(CT(1)+cos_d);
|
||||
|
||||
// for e.g. lat1=-90 && lat2=90 here we have G*L=INF*0
|
||||
CT const one_minus_cos_d = c1 - cos_d;
|
||||
CT const one_plus_cos_d = c1 + cos_d;
|
||||
// cos_d = 1 or cos_d = -1 means that the points are antipodal
|
||||
|
||||
CT const H = math::equals(one_minus_cos_d, c0) ?
|
||||
c0 :
|
||||
(d + three_sin_d) / one_minus_cos_d;
|
||||
CT const G = math::equals(one_plus_cos_d, c0) ?
|
||||
c0 :
|
||||
(d - three_sin_d) / one_plus_cos_d;
|
||||
|
||||
CT const dd = -(f/CT(4))*(H*K+G*L);
|
||||
|
||||
CT const a = get_radius<0>(spheroid);
|
||||
@ -116,41 +111,88 @@ struct andoyer_inverse
|
||||
}
|
||||
else
|
||||
{
|
||||
result.distance = CT(0);
|
||||
result.distance = c0;
|
||||
}
|
||||
|
||||
if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )
|
||||
{
|
||||
CT A = CT(0);
|
||||
CT U = CT(0);
|
||||
if ( ! math::equals(cos_lat2, CT(0)) )
|
||||
// sin_d = 0 <=> antipodal points
|
||||
if (math::equals(sin_d, c0))
|
||||
{
|
||||
CT const tan_lat2 = sin_lat2/cos_lat2;
|
||||
CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
|
||||
A = atan2(sin_dlon, M);
|
||||
CT const sin_2A = sin(CT(2)*A);
|
||||
U = (f/CT(2))*math::sqr(cos_lat1)*sin_2A;
|
||||
// T = inf
|
||||
// dA = inf
|
||||
// azimuth = -inf
|
||||
if (lat1 <= lat2)
|
||||
result.azimuth = c0;
|
||||
else
|
||||
result.azimuth = pi;
|
||||
}
|
||||
|
||||
CT V = CT(0);
|
||||
if ( ! math::equals(cos_lat1, CT(0)) )
|
||||
else
|
||||
{
|
||||
CT const tan_lat1 = sin_lat1/cos_lat1;
|
||||
CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
|
||||
CT const B = atan2(sin_dlon, N);
|
||||
CT const sin_2B = sin(CT(2)*B);
|
||||
V = (f/CT(2))*math::sqr(cos_lat2)*sin_2B;
|
||||
CT const c2 = CT(2);
|
||||
|
||||
CT A = c0;
|
||||
CT U = c0;
|
||||
if ( ! math::equals(cos_lat2, c0) )
|
||||
{
|
||||
CT const tan_lat2 = sin_lat2/cos_lat2;
|
||||
CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
|
||||
A = atan2(sin_dlon, M);
|
||||
CT const sin_2A = sin(c2*A);
|
||||
U = (f/ c2)*math::sqr(cos_lat1)*sin_2A;
|
||||
}
|
||||
|
||||
CT V = c0;
|
||||
if ( ! math::equals(cos_lat1, c0) )
|
||||
{
|
||||
CT const tan_lat1 = sin_lat1/cos_lat1;
|
||||
CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
|
||||
CT const B = atan2(sin_dlon, N);
|
||||
CT const sin_2B = sin(c2*B);
|
||||
V = (f/ c2)*math::sqr(cos_lat2)*sin_2B;
|
||||
}
|
||||
|
||||
CT const T = d / sin_d;
|
||||
CT const dA = V*T-U;
|
||||
|
||||
result.azimuth = A - dA;
|
||||
|
||||
// even with sin_d == 0 checked above if the second point
|
||||
// is somewhere in the antipodal area T may still be great
|
||||
// therefore dA may be great and the resulting azimuth
|
||||
// may be some more or less arbitrary angle
|
||||
if (A >= c0) // A indicates Eastern hemisphere
|
||||
{
|
||||
if (dA >= c0) // A altered towards 0
|
||||
{
|
||||
if ((result.azimuth) < c0)
|
||||
result.azimuth = c0;
|
||||
}
|
||||
else // dA < 0, A altered towards pi
|
||||
{
|
||||
if (result.azimuth > pi)
|
||||
result.azimuth = pi;
|
||||
}
|
||||
}
|
||||
else // A indicates Western hemisphere
|
||||
{
|
||||
if (dA <= c0) // A altered towards 0
|
||||
{
|
||||
if (result.azimuth > c0)
|
||||
result.azimuth = c0;
|
||||
}
|
||||
else // dA > 0, A altered towards -pi
|
||||
{
|
||||
CT const minus_pi = -pi;
|
||||
if ((result.azimuth) < minus_pi)
|
||||
result.azimuth = minus_pi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// infinity if sin_d = 0, so cos_d = 1 or cos_d = -1
|
||||
CT const T = d / sin_d;
|
||||
CT const dA = V*T-U;
|
||||
|
||||
result.azimuth = A - dA;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.azimuth = CT(0);
|
||||
result.azimuth = c0;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -128,7 +128,9 @@ struct disjoint_segment_box_impl
|
||||
&& t_min.first > ti_max)
|
||||
||
|
||||
(geometry::math::equals(t_max.second, 0)
|
||||
&& t_max.first < ti_min) )
|
||||
&& t_max.first < ti_min)
|
||||
||
|
||||
(math::sign(ti_min) * math::sign(ti_max) > 0) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -197,6 +199,11 @@ struct disjoint_segment_box_impl
|
||||
{
|
||||
if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
|
||||
if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
|
||||
|
||||
if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( t_min.first > diff || t_max.first < 0 )
|
||||
|
@ -54,7 +54,7 @@ struct intersection
|
||||
<
|
||||
Geometry1, Geometry2, OneOut,
|
||||
overlay_intersection
|
||||
>::apply(geometry1, geometry2, robust_policy, std::back_inserter(geometry_out), strategy);
|
||||
>::apply(geometry1, geometry2, robust_policy, range::back_inserter(geometry_out), strategy);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ inline void difference(Geometry1 const& geometry1,
|
||||
|
||||
detail::difference::difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
std::back_inserter(output_collection));
|
||||
range::back_inserter(output_collection));
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,7 +139,7 @@ struct range_remove_spikes
|
||||
|
||||
// Copy output
|
||||
geometry::clear(range);
|
||||
std::copy(cleaned.begin(), cleaned.end(), std::back_inserter(range));
|
||||
std::copy(cleaned.begin(), cleaned.end(), range::back_inserter(range));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -77,7 +77,7 @@ struct simplify_copy
|
||||
{
|
||||
std::copy
|
||||
(
|
||||
boost::begin(range), boost::end(range), std::back_inserter(out)
|
||||
boost::begin(range), boost::end(range), geometry::range::back_inserter(out)
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -113,7 +113,7 @@ struct simplify_range
|
||||
{
|
||||
simplify_range_insert::apply
|
||||
(
|
||||
range, std::back_inserter(out), max_distance, strategy
|
||||
range, geometry::range::back_inserter(out), max_distance, strategy
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ inline void sym_difference(Geometry1 const& geometry1,
|
||||
|
||||
detail::sym_difference::sym_difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
std::back_inserter(output_collection));
|
||||
range::back_inserter(output_collection));
|
||||
}
|
||||
|
||||
|
||||
|
@ -162,7 +162,7 @@ struct transform_polygon
|
||||
geometry::clear(poly2);
|
||||
|
||||
if (!transform_range_out<point2_type>(geometry::exterior_ring(poly1),
|
||||
std::back_inserter(geometry::exterior_ring(poly2)), strategy))
|
||||
range::back_inserter(geometry::exterior_ring(poly2)), strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -189,7 +189,7 @@ struct transform_polygon
|
||||
for ( ; it1 != boost::end(rings1); ++it1, ++it2)
|
||||
{
|
||||
if ( ! transform_range_out<point2_type>(*it1,
|
||||
std::back_inserter(*it2),
|
||||
range::back_inserter(*it2),
|
||||
strategy) )
|
||||
{
|
||||
return false;
|
||||
@ -228,7 +228,7 @@ struct transform_range
|
||||
// Should NOT be done here!
|
||||
// geometry::clear(range2);
|
||||
return transform_range_out<point_type>(range1,
|
||||
std::back_inserter(range2), strategy);
|
||||
range::back_inserter(range2), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -271,7 +271,7 @@ inline void union_(Geometry1 const& geometry1,
|
||||
concept::check<geometry_out>();
|
||||
|
||||
detail::union_::union_insert<geometry_out>(geometry1, geometry2,
|
||||
std::back_inserter(output_collection));
|
||||
range::back_inserter(output_collection));
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ template <>
|
||||
struct modify<false>
|
||||
{
|
||||
template <typename Ring, typename Point>
|
||||
static inline void push_back(Ring& ring, Point const& point)
|
||||
static inline void push_back(Ring& /*ring*/, Point const& /*point*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,11 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
@ -17,7 +22,7 @@
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
//#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
@ -98,8 +103,20 @@ public :
|
||||
PointOfSegment const& p2,
|
||||
summation& state)
|
||||
{
|
||||
// Below formulas are equivalent, however the two lower ones
|
||||
// suffer less from accuracy loss for great values of coordinates.
|
||||
// See: https://svn.boost.org/trac/boost/ticket/11928
|
||||
|
||||
// SUM += x2 * y1 - x1 * y2;
|
||||
state.sum += detail::determinant<return_type>(p2, p1);
|
||||
// state.sum += detail::determinant<return_type>(p2, p1);
|
||||
|
||||
// SUM += (x2 - x1) * (y2 + y1)
|
||||
//state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1)))
|
||||
// * (return_type(get<1>(p2)) + return_type(get<1>(p1)));
|
||||
|
||||
// SUM += (x1 + x2) * (y1 - y2)
|
||||
state.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2)))
|
||||
* (return_type(get<1>(p1)) - return_type(get<1>(p2)));
|
||||
}
|
||||
|
||||
static inline return_type result(summation const& state)
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2016.
|
||||
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/andoyer_inverse.hpp>
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
@ -50,6 +51,8 @@ are about the same as Vincenty. In my (Barend's) testcases the results didn't di
|
||||
\see http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115 (implementation)
|
||||
\see http://futureboy.homeip.net/frinksamp/navigation.frink (implementation)
|
||||
\see http://www.voidware.com/earthdist.htm (implementation)
|
||||
\see http://www.dtic.mil/docs/citations/AD0627893
|
||||
\see http://www.dtic.mil/docs/citations/AD703541
|
||||
*/
|
||||
template
|
||||
<
|
||||
@ -82,16 +85,17 @@ public :
|
||||
: m_spheroid(spheroid)
|
||||
{}
|
||||
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
inline typename calculation_type<Point1, Point2>::type
|
||||
apply(Point1 const& point1, Point2 const& point2) const
|
||||
{
|
||||
return calc<typename calculation_type<Point1, Point2>::type>
|
||||
(
|
||||
get_as_radian<0>(point1), get_as_radian<1>(point1),
|
||||
get_as_radian<0>(point2), get_as_radian<1>(point2)
|
||||
);
|
||||
return geometry::detail::andoyer_inverse
|
||||
<
|
||||
typename calculation_type<Point1, Point2>::type,
|
||||
true, false
|
||||
>::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
|
||||
get_as_radian<0>(point2), get_as_radian<1>(point2),
|
||||
m_spheroid).distance;
|
||||
}
|
||||
|
||||
inline Spheroid const& model() const
|
||||
@ -100,55 +104,6 @@ public :
|
||||
}
|
||||
|
||||
private :
|
||||
template <typename CT, typename T>
|
||||
inline CT calc(T const& lon1,
|
||||
T const& lat1,
|
||||
T const& lon2,
|
||||
T const& lat2) const
|
||||
{
|
||||
CT const G = (lat1 - lat2) / 2.0;
|
||||
CT const lambda = (lon1 - lon2) / 2.0;
|
||||
|
||||
if (geometry::math::equals(lambda, 0.0)
|
||||
&& geometry::math::equals(G, 0.0))
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
CT const F = (lat1 + lat2) / 2.0;
|
||||
|
||||
CT const sinG2 = math::sqr(sin(G));
|
||||
CT const cosG2 = math::sqr(cos(G));
|
||||
CT const sinF2 = math::sqr(sin(F));
|
||||
CT const cosF2 = math::sqr(cos(F));
|
||||
CT const sinL2 = math::sqr(sin(lambda));
|
||||
CT const cosL2 = math::sqr(cos(lambda));
|
||||
|
||||
CT const S = sinG2 * cosL2 + cosF2 * sinL2;
|
||||
CT const C = cosG2 * cosL2 + sinF2 * sinL2;
|
||||
|
||||
CT const c0 = 0;
|
||||
CT const c1 = 1;
|
||||
CT const c2 = 2;
|
||||
CT const c3 = 3;
|
||||
|
||||
if (geometry::math::equals(S, c0) || geometry::math::equals(C, c0))
|
||||
{
|
||||
return c0;
|
||||
}
|
||||
|
||||
CT const radius_a = CT(get_radius<0>(m_spheroid));
|
||||
CT const flattening = geometry::detail::flattening<CT>(m_spheroid);
|
||||
|
||||
CT const omega = atan(math::sqrt(S / C));
|
||||
CT const r3 = c3 * math::sqrt(S * C) / omega; // not sure if this is r or greek nu
|
||||
CT const D = c2 * omega * radius_a;
|
||||
CT const H1 = (r3 - c1) / (c2 * C);
|
||||
CT const H2 = (r3 + c1) / (c2 * S);
|
||||
|
||||
return D * (c1 + flattening * (H1 * sinF2 * cosG2 - H2 * cosF2 * sinG2) );
|
||||
}
|
||||
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2015.
|
||||
// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2016.
|
||||
// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#define BOOST_GEOMETRY_UTIL_RANGE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/config.hpp>
|
||||
@ -362,6 +363,50 @@ erase(Range & rng,
|
||||
return erase(rng, first, last);
|
||||
}
|
||||
|
||||
// back_inserter
|
||||
|
||||
template <class Container>
|
||||
class back_insert_iterator
|
||||
: public std::iterator<std::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
public:
|
||||
typedef Container container_type;
|
||||
|
||||
explicit back_insert_iterator(Container & c)
|
||||
: container(boost::addressof(c))
|
||||
{}
|
||||
|
||||
back_insert_iterator & operator=(typename Container::value_type const& value)
|
||||
{
|
||||
range::push_back(*container, value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator & operator* ()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator & operator++ ()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator operator++(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Container * container;
|
||||
};
|
||||
|
||||
template <typename Range>
|
||||
inline back_insert_iterator<Range> back_inserter(Range & rng)
|
||||
{
|
||||
return back_insert_iterator<Range>(rng);
|
||||
}
|
||||
|
||||
}}} // namespace boost::geometry::range
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP
|
||||
|
@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@ -61,7 +61,24 @@ void test_all()
|
||||
|
||||
// ccw
|
||||
test_geometry<bg::model::polygon<P, false> >
|
||||
("POLYGON((0 0,0 7,4 2,2 0,0 0), (1 1,2 1,2 2,1 2,1 1))", -15.0);
|
||||
("POLYGON((0 0,0 7,4 2,2 0,0 0), (1 1,2 1,2 2,1 2,1 1))", -15.0);
|
||||
|
||||
test_geometry<bg::model::polygon<P, false> >
|
||||
("POLYGON((1 0,0 1,-1 0,0 -1,1 0))", 2);
|
||||
|
||||
typedef typename bg::coordinate_type<P>::type coord_type;
|
||||
if (BOOST_GEOMETRY_CONDITION((boost::is_same<coord_type, double>::value)))
|
||||
{
|
||||
test_geometry<bg::model::polygon<P, false, false> >
|
||||
("POLYGON((100000001 100000000, 100000000 100000001, \
|
||||
99999999 100000000, 100000000 99999999))", 2);
|
||||
}
|
||||
else if (BOOST_GEOMETRY_CONDITION((boost::is_same<coord_type, float>::value)))
|
||||
{
|
||||
test_geometry<bg::model::polygon<P, false, false> >
|
||||
("POLYGON((100001 100000, 100000 100001, \
|
||||
99999 100000, 100000 99999))", 2);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
|
@ -83,9 +83,16 @@ void test_additional()
|
||||
|
||||
// http://stackoverflow.com/questions/32457920/boost-rtree-of-box-gives-wrong-intersection-with-segment
|
||||
// http://lists.boost.org/geometry/2015/09/3476.php
|
||||
// For now disabled by default even though it works properly on MSVC14
|
||||
// it's probable that the result depends on the compiler
|
||||
#ifdef BOOST_GEOMETRY_ENABLE_FAILING_TESTS
|
||||
typedef bg::model::point<typename bg::coordinate_type<P>::type, 3, bg::cs::cartesian> point3d_t;
|
||||
test_geometry<bg::model::segment<point3d_t>, bg::model::box<point3d_t> >(
|
||||
"SEGMENT(2 1 0,2 1 10)",
|
||||
"BOX(0 0 0,10 0 10)",
|
||||
false);
|
||||
test_geometry<bg::model::segment<point3d_t>, bg::model::box<point3d_t> >(
|
||||
"SEGMENT(2 1 0,2 1 10)",
|
||||
"BOX(0 -5 0,10 0 10)",
|
||||
false);
|
||||
// and derived from the cases above
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(12 0,20 10)",
|
||||
"BOX(0 0,10 10)",
|
||||
@ -98,12 +105,46 @@ void test_additional()
|
||||
"SEGMENT(2 0,18 8)",
|
||||
"BOX(0 0,10 10)",
|
||||
true);
|
||||
typedef bg::model::point<typename bg::coordinate_type<P>::type, 3, bg::cs::cartesian> point3d_t;
|
||||
test_geometry<bg::model::segment<point3d_t>, bg::model::box<point3d_t> >(
|
||||
"SEGMENT(2 1 0,2 1 10)",
|
||||
"BOX(0 0 0,10 0 10)",
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(1 0,1 10)",
|
||||
"BOX(0 0,0 10)",
|
||||
false);
|
||||
#endif
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(-1 0,-1 10)",
|
||||
"BOX(0 0,0 10)",
|
||||
false);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(2 1,2 1)",
|
||||
"BOX(0 0,10 0)",
|
||||
false);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(2 3,2 3)",
|
||||
"BOX(0 0,10 0)",
|
||||
false);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(0 0,10 0)",
|
||||
"BOX(0 0,10 0)",
|
||||
true);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(10 0,10 0)",
|
||||
"BOX(0 0,10 0)",
|
||||
true);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(1 0,1 0)",
|
||||
"BOX(0 0,10 0)",
|
||||
true);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(0 0,0 10)",
|
||||
"BOX(0 0,0 10)",
|
||||
true);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(0 10,0 10)",
|
||||
"BOX(0 0,0 10)",
|
||||
true);
|
||||
test_geometry<bg::model::segment<P>, bg::model::box<P> >(
|
||||
"SEGMENT(0 1,0 1)",
|
||||
"BOX(0 0,0 10)",
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library) Point concept unit tests
|
||||
//
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2016 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2016 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -9,8 +10,6 @@
|
||||
#ifndef GEOMETRY_TEST_POINT_CONCEPT_FUNCTION_REQUIRING_A_POINT_HPP
|
||||
#define GEOMETRY_TEST_POINT_CONCEPT_FUNCTION_REQUIRING_A_POINT_HPP
|
||||
|
||||
#include <boost/concept/requires.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/point_concept.hpp>
|
||||
|
||||
namespace bg = boost::geometry;
|
||||
@ -18,13 +17,11 @@ namespace bg = boost::geometry;
|
||||
namespace test
|
||||
{
|
||||
template <typename P, typename C>
|
||||
|
||||
inline BOOST_CONCEPT_REQUIRES(
|
||||
((bg::concept::Point<P>))
|
||||
((bg::concept::ConstPoint<C>)),
|
||||
(void))
|
||||
function_requiring_a_point(P& p1, const C& p2)
|
||||
inline void function_requiring_a_point(P& p1, const C& p2)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((bg::concept::Point<P>));
|
||||
BOOST_CONCEPT_ASSERT((bg::concept::ConstPoint<C>));
|
||||
|
||||
bg::set<0>(p1, bg::get<0>(p2));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Unit Test
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@ -27,6 +28,7 @@
|
||||
#include <boost/iterator/iterator_concepts.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
@ -96,6 +98,28 @@ inline Geometry from_wkt(std::string const& wkt)
|
||||
}
|
||||
|
||||
|
||||
// this function is implemented because std::max_element() requires ForwardIterator
|
||||
// but bg::point_iterator<> is InputIterator since it returns non-true reference
|
||||
template <typename InputIt, typename Pred>
|
||||
inline boost::optional<typename std::iterator_traits<InputIt>::value_type>
|
||||
max_value(InputIt first, InputIt last, Pred pred)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIt>::value_type value_type;
|
||||
if (first != last)
|
||||
{
|
||||
value_type found = *first++;
|
||||
for (; first != last; )
|
||||
{
|
||||
value_type current = *first++;
|
||||
if (pred(current, found))
|
||||
found = current;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
|
||||
template <typename Iterator>
|
||||
inline std::ostream& print_point_range(std::ostream& os,
|
||||
Iterator first,
|
||||
@ -460,13 +484,12 @@ struct test_point_iterator_of_geometry
|
||||
>::value_type point;
|
||||
if (const_begin != const_end)
|
||||
{
|
||||
const_point_iterator pit_max = std::max_element(const_begin,
|
||||
const_end,
|
||||
bg::less<point>());
|
||||
|
||||
BOOST_CHECK(pit_max != const_end); // to avoid warnings
|
||||
boost::optional<point>
|
||||
pt_max = max_value(const_begin, const_end, bg::less<point>());
|
||||
|
||||
BOOST_CHECK(bool(pt_max)); // to avoid warnings
|
||||
#ifdef BOOST_GEOMETRY_TEST_DEBUG
|
||||
std::cout << "max point: " << bg::dsv(*pit_max) << std::endl;
|
||||
std::cout << "max point: " << bg::dsv(*pt_max) << std::endl;
|
||||
#endif
|
||||
}
|
||||
#ifdef BOOST_GEOMETRY_TEST_DEBUG
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Unit Test
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2016 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2016 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015.
|
||||
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2015, 2016.
|
||||
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@ -37,6 +37,33 @@
|
||||
|
||||
|
||||
|
||||
double make_deg(double deg, double min, double sec)
|
||||
{
|
||||
return deg + min / 60.0 + sec / 3600.0;
|
||||
}
|
||||
|
||||
double to_rad(double deg)
|
||||
{
|
||||
return bg::math::pi<double>() * deg / 180.0;
|
||||
}
|
||||
|
||||
double to_deg(double rad)
|
||||
{
|
||||
return 180.0 * rad / bg::math::pi<double>();
|
||||
}
|
||||
|
||||
double normlized_deg(double deg)
|
||||
{
|
||||
double const pi = bg::math::pi<double>();
|
||||
if (deg > 180)
|
||||
return deg - 360;
|
||||
else if (deg < -180)
|
||||
return deg + 360;
|
||||
else
|
||||
return deg;
|
||||
}
|
||||
|
||||
|
||||
template <typename P1, typename P2>
|
||||
void test_distance(double lon1, double lat1, double lon2, double lat2, double expected_km)
|
||||
{
|
||||
@ -49,6 +76,7 @@ void test_distance(double lon1, double lat1, double lon2, double lat2, double ex
|
||||
typedef bg::srs::spheroid<rtype> stype;
|
||||
|
||||
typedef bg::strategy::distance::andoyer<stype> andoyer_type;
|
||||
typedef bg::detail::andoyer_inverse<rtype, true, false> andoyer_inverse_type;
|
||||
|
||||
BOOST_CONCEPT_ASSERT
|
||||
(
|
||||
@ -65,10 +93,73 @@ void test_distance(double lon1, double lat1, double lon2, double lat2, double ex
|
||||
bg::assign_values(p1, lon1, lat1);
|
||||
bg::assign_values(p2, lon2, lat2);
|
||||
|
||||
BOOST_CHECK_CLOSE(andoyer.apply(p1, p2), return_type(1000.0 * expected_km), 0.001);
|
||||
BOOST_CHECK_CLOSE(bg::distance(p1, p2, andoyer), return_type(1000.0 * expected_km), 0.001);
|
||||
return_type d_strategy = andoyer.apply(p1, p2);
|
||||
return_type d_function = bg::distance(p1, p2, andoyer);
|
||||
return_type d_formula = andoyer_inverse_type::apply(to_rad(lon1), to_rad(lat1), to_rad(lon2), to_rad(lat2), stype()).distance;
|
||||
|
||||
BOOST_CHECK_CLOSE(d_strategy / 1000.0, expected_km, 0.001);
|
||||
BOOST_CHECK_CLOSE(d_function / 1000.0, expected_km, 0.001);
|
||||
BOOST_CHECK_CLOSE(d_formula / 1000.0, expected_km, 0.001);
|
||||
}
|
||||
|
||||
template <typename PS, typename P>
|
||||
void test_azimuth(double lon1, double lat1,
|
||||
double lon2, double lat2,
|
||||
double expected_azimuth_deg)
|
||||
{
|
||||
// Set radius type, but for integer coordinates we want to have floating point radius type
|
||||
typedef typename bg::promote_floating_point
|
||||
<
|
||||
typename bg::coordinate_type<PS>::type
|
||||
>::type rtype;
|
||||
|
||||
typedef bg::srs::spheroid<rtype> stype;
|
||||
typedef bg::detail::andoyer_inverse<rtype, false, true> andoyer_inverse_type;
|
||||
|
||||
rtype a_formula = andoyer_inverse_type::apply(to_rad(lon1), to_rad(lat1), to_rad(lon2), to_rad(lat2), stype()).azimuth;
|
||||
|
||||
rtype azimuth_deg = to_deg(a_formula);
|
||||
|
||||
if (bg::math::equals(azimuth_deg, -180.0))
|
||||
azimuth_deg = 180.0;
|
||||
if (bg::math::equals(expected_azimuth_deg, -180.0))
|
||||
expected_azimuth_deg = 180.0;
|
||||
|
||||
if (bg::math::equals(expected_azimuth_deg, 0.0))
|
||||
{
|
||||
BOOST_CHECK(bg::math::equals(azimuth_deg, expected_azimuth_deg));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_CHECK_CLOSE(azimuth_deg, expected_azimuth_deg, 0.001);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
void test_distazi(double lon1, double lat1, double lon2, double lat2, double expected_km, double expected_azimuth_deg)
|
||||
{
|
||||
test_distance<P1, P2>(lon1, lat1, lon2, lat2, expected_km);
|
||||
test_azimuth<P1, P2>(lon1, lat1, lon2, lat2, expected_azimuth_deg);
|
||||
}
|
||||
|
||||
// requires SW->NE
|
||||
template <typename P1, typename P2>
|
||||
void test_distazi_symm(double lon1, double lat1, double lon2, double lat2, double expected_km, double expected_azimuth_deg)
|
||||
{
|
||||
test_distazi<P1, P2>(lon1, lat1, lon2, lat2, expected_km, expected_azimuth_deg);
|
||||
test_distazi<P1, P2>(-lon1, lat1, -lon2, lat2, expected_km, -expected_azimuth_deg);
|
||||
test_distazi<P1, P2>(lon1, -lat1, lon2, -lat2, expected_km, 180 - expected_azimuth_deg);
|
||||
test_distazi<P1, P2>(-lon1, -lat1, -lon2, -lat2, expected_km, -180 + expected_azimuth_deg);
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
void test_distazi_symmNS(double lon1, double lat1, double lon2, double lat2, double expected_km, double expected_azimuth_deg)
|
||||
{
|
||||
test_distazi<P1, P2>(lon1, lat1, lon2, lat2, expected_km, expected_azimuth_deg);
|
||||
test_distazi<P1, P2>(lon1, -lat1, lon2, -lat2, expected_km, 180 - expected_azimuth_deg);
|
||||
}
|
||||
|
||||
|
||||
template <typename PS, typename P>
|
||||
void test_side(double lon1, double lat1,
|
||||
double lon2, double lat2,
|
||||
@ -102,9 +193,80 @@ void test_side(double lon1, double lat1,
|
||||
template <typename P1, typename P2>
|
||||
void test_all()
|
||||
{
|
||||
test_distance<P1, P2>(0, 90, 1, 80, 1116.814237); // polar
|
||||
test_distance<P1, P2>(4, 52, 4, 52, 0.0); // no point difference
|
||||
test_distance<P1, P2>(4, 52, 3, 40, 1336.039890); // normal case
|
||||
// polar
|
||||
test_distazi<P1, P2>(0, 90, 1, 80,
|
||||
1116.814237, 179);
|
||||
|
||||
// no point difference
|
||||
test_distazi<P1, P2>(4, 52, 4, 52,
|
||||
0.0, 0.0);
|
||||
|
||||
// normal cases
|
||||
test_distazi<P1, P2>(4, 52, 3, 40,
|
||||
1336.039890, -176.3086);
|
||||
test_distazi<P1, P2>(3, 52, 4, 40,
|
||||
1336.039890, 176.3086);
|
||||
test_distazi<P1, P2>(make_deg(17, 19, 43.28),
|
||||
make_deg(40, 30, 31.151),
|
||||
18, 40,
|
||||
80.323245,
|
||||
make_deg(134, 27, 50.05));
|
||||
|
||||
// antipodal
|
||||
// ok? in those cases shorter path would pass through a pole
|
||||
// but 90 or -90 would be consistent with distance?
|
||||
test_distazi<P1, P2>(0, 0, 180, 0, 20037.5, 0.0);
|
||||
test_distazi<P1, P2>(0, 0, -180, 0, 20037.5, 0.0);
|
||||
test_distazi<P1, P2>(-90, 0, 90, 0, 20037.5, 0.0);
|
||||
test_distazi<P1, P2>(90, 0, -90, 0, 20037.5, 0.0);
|
||||
|
||||
// 0, 45, 90 ...
|
||||
for (int i = 0 ; i < 360 ; i += 45)
|
||||
{
|
||||
// 0 45 90 ...
|
||||
double l = normlized_deg(i);
|
||||
// -1 44 89 ...
|
||||
double l1 = normlized_deg(i - 1);
|
||||
// 1 46 91 ...
|
||||
double l2 = normlized_deg(i + 1);
|
||||
|
||||
// near equator
|
||||
test_distazi_symm<P1, P2>(l1, -1, l2, 1, 313.7956, 45.1964);
|
||||
|
||||
// near poles
|
||||
test_distazi_symmNS<P1, P2>(l, -89.5, l, 89.5, 19892.2, 0.0);
|
||||
test_distazi_symmNS<P1, P2>(l, -89.6, l, 89.6, 19914.6, 0.0);
|
||||
test_distazi_symmNS<P1, P2>(l, -89.7, l, 89.7, 19936.9, 0.0);
|
||||
test_distazi_symmNS<P1, P2>(l, -89.8, l, 89.8, 19959.2, 0.0);
|
||||
test_distazi_symmNS<P1, P2>(l, -89.9, l, 89.9, 19981.6, 0.0);
|
||||
test_distazi_symmNS<P1, P2>(l, -89.99, l, 89.99, 20001.7, 0.0);
|
||||
test_distazi_symmNS<P1, P2>(l, -89.999, l, 89.999, 20003.7, 0.0);
|
||||
// antipodal
|
||||
test_distazi_symmNS<P1, P2>(l, -90, l, 90, 20003.9, 0.0);
|
||||
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-10.0), -10.0, normlized_deg(l+135), 45, 14892.1, 34.1802);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-30.0), -30.0, normlized_deg(l+135), 45, 17890.7, 33.7002);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-40.0), -40.0, normlized_deg(l+135), 45, 19319.7, 33.4801);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-41.0), -41.0, normlized_deg(l+135), 45, 19459.1, 33.2408);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-42.0), -42.0, normlized_deg(l+135), 45, 19597.8, 32.7844);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-43.0), -43.0, normlized_deg(l+135), 45, 19735.8, 31.7784);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.0), -44.0, normlized_deg(l+135), 45, 19873.0, 28.5588);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.1), -44.1, normlized_deg(l+135), 45, 19886.7, 27.8304);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.2), -44.2, normlized_deg(l+135), 45, 19900.4, 26.9173);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.3), -44.3, normlized_deg(l+135), 45, 19914.1, 25.7401);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.4), -44.4, normlized_deg(l+135), 45, 19927.7, 24.1668);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.5), -44.5, normlized_deg(l+135), 45, 19941.4, 21.9599);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.6), -44.6, normlized_deg(l+135), 45, 19955.0, 18.6438);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.7), -44.7, normlized_deg(l+135), 45, 19968.6, 13.1096);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.8), -44.8, normlized_deg(l+135), 45, 19982.3, 2.0300);
|
||||
// nearly antipodal
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.9), -44.9, normlized_deg(l+135), 45, 19995.9, 0.0);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.95), -44.95, normlized_deg(l+135), 45, 20002.7, 0.0);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.99), -44.99, normlized_deg(l+135), 45, 20008.1, 0.0);
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-44.999), -44.999, normlized_deg(l+135), 45, 20009.4, 0.0);
|
||||
// antipodal
|
||||
test_distazi_symm<P1, P2>(normlized_deg(l-45), -45, normlized_deg(l+135), 45, 20020.7, 0.0);
|
||||
}
|
||||
|
||||
/* SQL Server gives:
|
||||
1116.82586908528, 0, 1336.02721932545
|
||||
@ -115,6 +277,7 @@ union SELECT 0.001 * geography::STGeomFromText('POINT(4 52)', 4326).STDistance(g
|
||||
union SELECT 0.001 * geography::STGeomFromText('POINT(4 52)', 4326).STDistance(geography::STGeomFromText('POINT(3 40)', 4326))
|
||||
*/
|
||||
|
||||
|
||||
test_side<P1, P2>(0, 0, 0, 1, 0, 2, 0);
|
||||
test_side<P1, P2>(0, 0, 0, 1, 0, -2, 0);
|
||||
test_side<P1, P2>(10, 0, 10, 1, 10, 2, 0);
|
||||
@ -139,8 +302,8 @@ int test_main(int, char* [])
|
||||
{
|
||||
//test_all<float[2]>();
|
||||
//test_all<double[2]>();
|
||||
test_all<bg::model::point<int, 2, bg::cs::geographic<bg::degree> > >();
|
||||
test_all<bg::model::point<float, 2, bg::cs::geographic<bg::degree> > >();
|
||||
//test_all<bg::model::point<int, 2, bg::cs::geographic<bg::degree> > >();
|
||||
//test_all<bg::model::point<float, 2, bg::cs::geographic<bg::degree> > >();
|
||||
test_all<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
|
||||
|
||||
#if defined(HAVE_TTMATH)
|
||||
|
@ -108,6 +108,12 @@ void test_all()
|
||||
BOOST_CHECK(bgr::at(v, i) == i);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<T> w;
|
||||
std::copy(v.begin(), v.end(), bgr::back_inserter(w));
|
||||
BOOST_CHECK(v.size() == w.size() && std::equal(v.begin(), v.end(), w.begin()));
|
||||
}
|
||||
|
||||
BOOST_CHECK(bgr::front(v) == 0);
|
||||
BOOST_CHECK(bgr::back(v) == 19);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user