diff options
Diffstat (limited to 'libs/geometry/test/strategies')
-rw-r--r-- | libs/geometry/test/strategies/Jamfile.v2 | 14 | ||||
-rw-r--r-- | libs/geometry/test/strategies/andoyer.cpp | 108 | ||||
-rw-r--r-- | libs/geometry/test/strategies/distance_default_result.cpp | 36 | ||||
-rw-r--r-- | libs/geometry/test/strategies/douglas_peucker.cpp | 422 | ||||
-rw-r--r-- | libs/geometry/test/strategies/pythagoras.cpp | 24 | ||||
-rw-r--r-- | libs/geometry/test/strategies/pythagoras_point_box.cpp | 28 | ||||
-rw-r--r-- | libs/geometry/test/strategies/side_of_intersection.cpp | 61 | ||||
-rw-r--r-- | libs/geometry/test/strategies/spherical_side.cpp | 37 | ||||
-rw-r--r-- | libs/geometry/test/strategies/vincenty.cpp | 271 |
9 files changed, 951 insertions, 50 deletions
diff --git a/libs/geometry/test/strategies/Jamfile.v2 b/libs/geometry/test/strategies/Jamfile.v2 index d32c10737..beb772b2a 100644 --- a/libs/geometry/test/strategies/Jamfile.v2 +++ b/libs/geometry/test/strategies/Jamfile.v2 @@ -1,11 +1,11 @@ # Boost.Geometry (aka GGL, Generic Geometry Library) # -# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. -# Copyright (c) 2008-2014 Bruno Lalande, Paris, France. -# Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +# Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +# Copyright (c) 2009-2015 Mateusz Loskot, London, UK. # -# This file was modified by Oracle on 2014. -# Modifications copyright (c) 2014, Oracle and/or its affiliates. +# This file was modified by Oracle on 2014, 2015. +# Modifications copyright (c) 2014-2015, Oracle and/or its affiliates. # # Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle # Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -16,9 +16,11 @@ test-suite boost-geometry-strategies : + [ run andoyer.cpp ] [ run cross_track.cpp ] [ run crossings_multiply.cpp ] [ run distance_default_result.cpp ] + [ run douglas_peucker.cpp ] [ run franklin.cpp ] [ run haversine.cpp ] [ run point_in_box.cpp ] @@ -28,7 +30,9 @@ test-suite boost-geometry-strategies [ run pythagoras_point_box.cpp ] [ run spherical_side.cpp ] [ run segment_intersection_collinear.cpp ] + [ run side_of_intersection.cpp ] [ run transform_cs.cpp ] [ run transformer.cpp ] + [ run vincenty.cpp ] [ run winding.cpp ] ; diff --git a/libs/geometry/test/strategies/andoyer.cpp b/libs/geometry/test/strategies/andoyer.cpp new file mode 100644 index 000000000..c1fe0293b --- /dev/null +++ b/libs/geometry/test/strategies/andoyer.cpp @@ -0,0 +1,108 @@ +// 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. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include <geometry_test_common.hpp> + +#include <boost/concept_check.hpp> + +#include <boost/geometry/strategies/geographic/distance_andoyer.hpp> + +#include <boost/geometry/core/srs.hpp> +#include <boost/geometry/strategies/strategies.hpp> +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/geometries/point.hpp> +#include <test_common/test_point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + + + +template <typename P1, typename P2> +void test_andoyer(double lon1, double lat1, double lon2, double lat2, double expected_km) +{ + // 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<P1>::type + >::type rtype; + + typedef bg::srs::spheroid<rtype> stype; + + typedef bg::strategy::distance::andoyer<stype> andoyer_type; + + BOOST_CONCEPT_ASSERT + ( + (bg::concept::PointDistanceStrategy<andoyer_type, P1, P2>) + ); + + andoyer_type andoyer; + typedef typename bg::strategy::distance + ::services::return_type<andoyer_type, P1, P2>::type return_type; + + + P1 p1, p2; + + 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); +} + +template <typename P1, typename P2> +void test_all() +{ + test_andoyer<P1, P2>(0, 90, 1, 80, 1116.814237); // polar + test_andoyer<P1, P2>(4, 52, 4, 52, 0.0); // no point difference + test_andoyer<P1, P2>(4, 52, 3, 40, 1336.039890); // normal case + + /* SQL Server gives: + 1116.82586908528, 0, 1336.02721932545 + + with: +SELECT 0.001 * geography::STGeomFromText('POINT(0 90)', 4326).STDistance(geography::STGeomFromText('POINT(1 80)', 4326)) +union SELECT 0.001 * geography::STGeomFromText('POINT(4 52)', 4326).STDistance(geography::STGeomFromText('POINT(4 52)', 4326)) +union SELECT 0.001 * geography::STGeomFromText('POINT(4 52)', 4326).STDistance(geography::STGeomFromText('POINT(3 40)', 4326)) + */ +} + +template <typename P> +void test_all() +{ + test_all<P, P>(); +} + +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<double, 2, bg::cs::geographic<bg::degree> > >(); + +#if defined(HAVE_TTMATH) + test_all<bg::model::point<ttmath::Big<1,4>, 2, bg::cs::geographic<bg::degree> > >(); + test_all<bg::model::point<ttmath_big, 2, bg::cs::geographic<bg::degree> > >(); +#endif + + return 0; +} diff --git a/libs/geometry/test/strategies/distance_default_result.cpp b/libs/geometry/test/strategies/distance_default_result.cpp index 40315d207..e862d3313 100644 --- a/libs/geometry/test/strategies/distance_default_result.cpp +++ b/libs/geometry/test/strategies/distance_default_result.cpp @@ -180,7 +180,7 @@ struct test_distance_result_box //========================================================================= -template <std::size_t D, typename CS> +template <std::size_t D, typename CoordinateSystem> inline void test_segment_all() { #if defined(HAVE_TTMATH) @@ -189,32 +189,32 @@ inline void test_segment_all() #endif typedef typename boost::mpl::if_ < - typename boost::is_same<CS, bg::cs::cartesian>::type, + typename boost::is_same<CoordinateSystem, bg::cs::cartesian>::type, double, float >::type float_return_type; - test_distance_result_segment<short, short, D, CS, double>(); - test_distance_result_segment<int, int, D, CS, double>(); - test_distance_result_segment<int, long, D, CS, double>(); - test_distance_result_segment<long, long, D, CS, double>(); + test_distance_result_segment<short, short, D, CoordinateSystem, double>(); + test_distance_result_segment<int, int, D, CoordinateSystem, double>(); + test_distance_result_segment<int, long, D, CoordinateSystem, double>(); + test_distance_result_segment<long, long, D, CoordinateSystem, double>(); - test_distance_result_segment<int, float, D, CS, float_return_type>(); - test_distance_result_segment<float, float, D, CS, float_return_type>(); + test_distance_result_segment<int, float, D, CoordinateSystem, float_return_type>(); + test_distance_result_segment<float, float, D, CoordinateSystem, float_return_type>(); - test_distance_result_segment<int, double, D, CS, double>(); - test_distance_result_segment<double, int, D, CS, double>(); - test_distance_result_segment<float, double, D, CS, double>(); - test_distance_result_segment<double, float, D, CS, double>(); - test_distance_result_segment<double, double, D, CS, double>(); + test_distance_result_segment<int, double, D, CoordinateSystem, double>(); + test_distance_result_segment<double, int, D, CoordinateSystem, double>(); + test_distance_result_segment<float, double, D, CoordinateSystem, double>(); + test_distance_result_segment<double, float, D, CoordinateSystem, double>(); + test_distance_result_segment<double, double, D, CoordinateSystem, double>(); #if defined(HAVE_TTMATH) - test_distance_result_segment<tt, int, D, CS, tt>(); - test_distance_result_segment<tt, default_integral, D, CS, tt>(); + test_distance_result_segment<tt, int, D, CoordinateSystem, tt>(); + test_distance_result_segment<tt, default_integral, D, CoordinateSystem, tt>(); - test_distance_result_segment<tt, float, D, CS, tt>(); - test_distance_result_segment<tt, double, D, CS, tt>(); - test_distance_result_segment<tt, tt, D, CS, tt>(); + test_distance_result_segment<tt, float, D, CoordinateSystem, tt>(); + test_distance_result_segment<tt, double, D, CoordinateSystem, tt>(); + test_distance_result_segment<tt, tt, D, CoordinateSystem, tt>(); #endif } diff --git a/libs/geometry/test/strategies/douglas_peucker.cpp b/libs/geometry/test/strategies/douglas_peucker.cpp new file mode 100644 index 000000000..b8b09f348 --- /dev/null +++ b/libs/geometry/test/strategies/douglas_peucker.cpp @@ -0,0 +1,422 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_douglas_peucker +#endif + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#ifndef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER +#define BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER +#endif +#endif + +#include <iostream> +#include <iterator> +#include <sstream> +#include <string> + +#include <boost/test/included/unit_test.hpp> + +#include <boost/assign/list_of.hpp> +#include <boost/core/ignore_unused.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/tuple/tuple.hpp> + +#include <boost/geometry/core/point_type.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/strategies/distance.hpp> +#include <boost/geometry/strategies/strategies.hpp> + +#include <boost/geometry/geometries/geometries.hpp> +#include <boost/geometry/geometries/adapted/boost_tuple.hpp> +#include <boost/geometry/geometries/register/multi_point.hpp> + +#include <boost/geometry/algorithms/comparable_distance.hpp> +#include <boost/geometry/algorithms/equals.hpp> + +#include <boost/geometry/io/wkt/wkt.hpp> +#include <boost/geometry/io/dsv/write.hpp> + + +namespace bg = ::boost::geometry; +namespace ba = ::boost::assign; +namespace services = bg::strategy::distance::services; + +typedef boost::tuple<double, double> tuple_point_type; +typedef std::vector<tuple_point_type> tuple_multi_point_type; + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type) +BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED(std::vector) + +typedef bg::strategy::distance::projected_point<> distance_strategy_type; +typedef bg::strategy::distance::projected_point + < + void, bg::strategy::distance::comparable::pythagoras<> + > comparable_distance_strategy_type; + + +template <typename CoordinateType> +struct default_simplify_strategy +{ + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + typedef typename bg::strategy::distance::services::default_strategy + < + bg::point_tag, bg::segment_tag, point_type + >::type default_distance_strategy_type; + + typedef bg::strategy::simplify::douglas_peucker + < + point_type, default_distance_strategy_type + > type; +}; + + +template <typename CoordinateType> +struct simplify_regular_distance_strategy +{ + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + typedef bg::strategy::simplify::douglas_peucker + < + point_type, distance_strategy_type + > type; +}; + +template <typename CoordinateType> +struct simplify_comparable_distance_strategy +{ + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + typedef bg::strategy::simplify::douglas_peucker + < + point_type, comparable_distance_strategy_type + > type; +}; + + + +template <typename Geometry> +inline Geometry from_wkt(std::string const& wkt) +{ + Geometry geometry; + boost::geometry::read_wkt(wkt, geometry); + return geometry; +} + +template <typename Iterator> +inline std::ostream& print_point_range(std::ostream& os, + Iterator first, + Iterator beyond, + std::string const& header) +{ + os << header << "("; + for (Iterator it = first; it != beyond; ++it) + { + os << " " << bg::dsv(*it); + } + os << " )"; + return os; +} + + +struct equals +{ + template <typename Iterator1, typename Iterator2> + static inline bool apply(Iterator1 begin1, Iterator1 end1, + Iterator2 begin2, Iterator2 end2) + { + std::size_t num_points1 = std::distance(begin1, end1); + std::size_t num_points2 = std::distance(begin2, end2); + + if ( num_points1 != num_points2 ) + { + return false; + } + + Iterator1 it1 = begin1; + Iterator2 it2 = begin2; + for (; it1 != end1; ++it1, ++it2) + { + if ( !bg::equals(*it1, *it2) ) + { + return false; + } + } + return true; + } + + template <typename Range1, typename Range2> + static inline bool apply(Range1 const& range1, Range2 const& range2) + { + return apply(boost::begin(range1), boost::end(range1), + boost::begin(range2), boost::end(range2)); + } +}; + + + + +template <typename Geometry> +struct test_one_case +{ + template <typename Strategy, typename Range> + static inline void apply(std::string const& case_id, + std::string const& wkt, + double max_distance, + Strategy const& strategy, + Range const& expected_result) + { + typedef typename bg::point_type<Geometry>::type point_type; + std::vector<point_type> result; + + Geometry geometry = from_wkt<Geometry>(wkt); + + std::string typeid_name + = typeid(typename bg::coordinate_type<point_type>::type).name(); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << case_id << " - " << typeid_name + << std::endl; + std::cout << wkt << std::endl; +#endif + + strategy.apply(geometry, std::back_inserter(result), max_distance); + + boost::ignore_unused(strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + print_point_range(std::cout, boost::begin(result), boost::end(result), + "output: "); + std::cout << std::endl << std::endl; +#endif + std::stringstream stream_expected; + print_point_range(stream_expected, boost::begin(expected_result), + boost::end(expected_result), + ""); + std::stringstream stream_detected; + print_point_range(stream_detected, boost::begin(result), + boost::end(result), + ""); + + BOOST_CHECK_MESSAGE(equals::apply(result, expected_result), + "case id: " << case_id << " - " << typeid_name + << ", geometry: " << wkt + << ", Expected: " << stream_expected.str() + << " - Detected: " << stream_detected.str()); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "---------------" << std::endl; + std::cout << "---------------" << std::endl; + std::cout << std::endl << std::endl; +#endif + } +}; + + +template <typename CoordinateType, typename Strategy> +inline void test_with_strategy(std::string label) +{ + std::cout.precision(20); + Strategy strategy; + + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + typedef bg::model::linestring<point_type> linestring_type; + typedef bg::model::segment<point_type> segment_type; + typedef test_one_case<linestring_type> tester; + + label = " (" + label + ")"; + + { + point_type const p1(-6,-13), p2(0,-15); + segment_type const s(point_type(12,-3), point_type(-12,5)); + + if (bg::comparable_distance(p1, s) >= bg::comparable_distance(p2, s)) + { + tester::apply("l01c1" + label, + "LINESTRING(12 -3, 4 8,-6 -13,-9 4,0 -15,-12 5)", + 10, + strategy, + ba::tuple_list_of(12,-3)(4,8)(-6,-13)(-12,5) + ); + } + else + { + tester::apply("l01c2" + label, + "LINESTRING(12 -3, 4 8,-6 -13,-9 4,0 -15,-12 5)", + 10, + strategy, + ba::tuple_list_of(12,-3)(4,8)(-6,-13)(-9,4)(0,-15)(-12,5) + ); + } + } + + tester::apply("l02" + label, + "LINESTRING(-6 -13,-9 4,0 -15,-12 5)", + 10, + strategy, + ba::tuple_list_of(-6,-13)(-12,5) + ); + + tester::apply("l03" + label, + "LINESTRING(12 -3, 4 8,-6 -13,-9 4,0 -14,-12 5)", + 10, + strategy, + ba::tuple_list_of(12,-3)(4,8)(-6,-13)(-12,5) + ); + + tester::apply("l04" + label, + "LINESTRING(12 -3, 4 8,-6 -13,-9 4,0 -14,-12 5)", + 14, + strategy, + ba::tuple_list_of(12,-3)(-6,-13)(-12,5) + ); + + { + segment_type const s(point_type(0,-1), point_type(5,-4)); + point_type const p1(5,-1), p2(0,-4); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + bool d_larger_first = (bg::distance(p1, s) > bg::distance(p2, s)); + bool d_larger_second = (bg::distance(p1, s) < bg::distance(p2, s)); + bool cd_larger_first + = (bg::comparable_distance(p1, s) > bg::comparable_distance(p2, s)); + bool cd_larger_second + = (bg::comparable_distance(p1, s) < bg::comparable_distance(p2, s)); + + std::cout << "segment: " << bg::dsv(s) << std::endl; + std::cout << "distance from " << bg::dsv(p1) << ": " + << bg::distance(p1, s) << std::endl; + std::cout << "comp. distance from " << bg::dsv(p1) << ": " + << bg::comparable_distance(p1, s) << std::endl; + std::cout << "distance from " << bg::dsv(p2) << ": " + << bg::distance(p2, s) << std::endl; + std::cout << "comp. distance from " << bg::dsv(p2) << ": " + << bg::comparable_distance(p2, s) << std::endl; + std::cout << "larger distance from " + << (d_larger_first ? "first" : (d_larger_second ? "second" : "equal")) + << std::endl; + std::cout << "larger comp. distance from " + << (cd_larger_first ? "first" : (cd_larger_second ? "second" : "equal")) + << std::endl; + std::cout << "difference of distances: " + << (bg::distance(p1, s) - bg::distance(p2, s)) + << std::endl; + std::cout << "difference of comp. distances: " + << (bg::comparable_distance(p1, s) - bg::comparable_distance(p2, s)) + << std::endl; +#endif + + std::string wkt = + "LINESTRING(0 0,5 0,0 -1,5 -1,0 -2,5 -2,0 -3,5 -3,0 -4,5 -4,0 0)"; + + if (bg::comparable_distance(p1, s) >= bg::comparable_distance(p2, s)) + { + tester::apply("l05c1" + label, + wkt, + 1, + strategy, + ba::tuple_list_of(0,0)(5,0)(0,-1)(5,-1)(0,-2)(5,-2)(0,-3)(5,-4)(0,0) + ); + tester::apply("l05c1a" + label, + wkt, + 2, + strategy, + ba::tuple_list_of(0,0)(5,0)(0,-1)(5,-1)(0,-2)(5,-4)(0,0) + ); + } + else + { + tester::apply("l05c2" + label, + wkt, + 1, + strategy, + ba::tuple_list_of(0,0)(5,0)(0,-1)(5,-1)(0,-2)(5,-2)(0,-4)(5,-4)(0,0) + ); + tester::apply("l05c2a" + label, + wkt, + 2, + strategy, + ba::tuple_list_of(0,0)(5,0)(0,-1)(5,-1)(0,-4)(5,-4)(0,0) + ); + } + } + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << std::endl; + std::cout << "*************************************************"; + std::cout << std::endl; + std::cout << std::endl; +#endif +} + + +BOOST_AUTO_TEST_CASE( test_default_strategy ) +{ + test_with_strategy<int, default_simplify_strategy<int>::type>("i"); + test_with_strategy<float, default_simplify_strategy<float>::type>("f"); + test_with_strategy<double, default_simplify_strategy<double>::type>("d"); + test_with_strategy + < + long double, + default_simplify_strategy<long double>::type + >("ld"); +} + +BOOST_AUTO_TEST_CASE( test_with_regular_distance_strategy ) +{ + test_with_strategy + < + int, + simplify_regular_distance_strategy<int>::type + >("i"); + + test_with_strategy + < + float, + simplify_regular_distance_strategy<float>::type + >("f"); + + test_with_strategy + < + double, + simplify_regular_distance_strategy<double>::type + >("d"); + test_with_strategy + < + long double, + simplify_regular_distance_strategy<long double>::type + >("ld"); +} + +BOOST_AUTO_TEST_CASE( test_with_comparable_distance_strategy ) +{ + test_with_strategy + < + int, + simplify_comparable_distance_strategy<int>::type + >("i"); + test_with_strategy + < + float, + simplify_comparable_distance_strategy<float>::type + >("f"); + test_with_strategy + < + double, + simplify_comparable_distance_strategy<double>::type + >("d"); + test_with_strategy + < + long double, + simplify_comparable_distance_strategy<long double>::type + >("ld"); +} diff --git a/libs/geometry/test/strategies/pythagoras.cpp b/libs/geometry/test/strategies/pythagoras.cpp index b8bcfed3c..3b81bf144 100644 --- a/libs/geometry/test/strategies/pythagoras.cpp +++ b/libs/geometry/test/strategies/pythagoras.cpp @@ -20,7 +20,6 @@ #endif #include <boost/timer.hpp> -#include <boost/typeof/typeof.hpp> #include <boost/concept/requires.hpp> #include <boost/concept_check.hpp> @@ -239,21 +238,28 @@ void test_integer(bool check_types) bg::assign_values(p2, 98765432, 87654321); typedef bg::strategy::distance::pythagoras<> pythagoras_type; - pythagoras_type pythagoras; - BOOST_AUTO(distance, pythagoras.apply(p1, p2)); - BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001); - typedef typename bg::strategy::distance::services::comparable_type < pythagoras_type >::type comparable_type; + + typedef typename bg::strategy::distance::services::return_type + < + pythagoras_type, point_type, point_type + >::type distance_type; + typedef typename bg::strategy::distance::services::return_type + < + comparable_type, point_type, point_type + >::type cdistance_type; + + pythagoras_type pythagoras; + distance_type distance = pythagoras.apply(p1, p2); + BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001); + comparable_type comparable; - BOOST_AUTO(cdistance, comparable.apply(p1, p2)); + cdistance_type cdistance = comparable.apply(p1, p2); BOOST_CHECK_EQUAL(cdistance, 11589696996311540); - typedef BOOST_TYPEOF(cdistance) cdistance_type; - typedef BOOST_TYPEOF(distance) distance_type; - distance_type distance2 = sqrt(distance_type(cdistance)); BOOST_CHECK_CLOSE(distance, distance2, 0.001); diff --git a/libs/geometry/test/strategies/pythagoras_point_box.cpp b/libs/geometry/test/strategies/pythagoras_point_box.cpp index d11e96e1c..9b1e817f3 100644 --- a/libs/geometry/test/strategies/pythagoras_point_box.cpp +++ b/libs/geometry/test/strategies/pythagoras_point_box.cpp @@ -29,7 +29,6 @@ #include <boost/core/ignore_unused.hpp> #include <boost/timer.hpp> -#include <boost/typeof/typeof.hpp> #include <boost/concept/requires.hpp> #include <boost/concept_check.hpp> @@ -336,22 +335,29 @@ inline void test_integer(bool check_types) bg::assign_values(b, 0, 0, 12345678, 23456789); bg::assign_values(p, 98765432, 87654321); - typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_pb_type; - pythagoras_pb_type pythagoras_pb; - BOOST_AUTO(distance, pythagoras_pb.apply(p, b)); - BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001); - + typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_type; typedef typename bg::strategy::distance::services::comparable_type < - pythagoras_pb_type + pythagoras_type >::type comparable_type; + + typedef typename bg::strategy::distance::services::return_type + < + pythagoras_type, point_type, box_type + >::type distance_type; + typedef typename bg::strategy::distance::services::return_type + < + comparable_type, point_type, box_type + >::type cdistance_type; + + pythagoras_type pythagoras; + distance_type distance = pythagoras.apply(p, b); + BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001); + comparable_type comparable; - BOOST_AUTO(cdistance, comparable.apply(p, b)); + cdistance_type cdistance = comparable.apply(p, b); BOOST_CHECK_EQUAL(cdistance, 11589696996311540); - typedef BOOST_TYPEOF(cdistance) cdistance_type; - typedef BOOST_TYPEOF(distance) distance_type; - distance_type distance2 = sqrt(distance_type(cdistance)); BOOST_CHECK_CLOSE(distance, distance2, 0.001); diff --git a/libs/geometry/test/strategies/side_of_intersection.cpp b/libs/geometry/test/strategies/side_of_intersection.cpp new file mode 100644 index 000000000..c5de7e0ea --- /dev/null +++ b/libs/geometry/test/strategies/side_of_intersection.cpp @@ -0,0 +1,61 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include <geometry_test_common.hpp> + +#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp> +#include <boost/geometry/geometries/point_xy.hpp> +#include <boost/geometry/geometries/segment.hpp> + + +namespace bg = boost::geometry; + +int test_main(int, char* []) +{ + typedef bg::model::d2::point_xy<int> point; + typedef bg::model::segment<point> segment; + + segment a(point(20, 10), point(10, 20)); + + segment b1(point(11, 16), point(20, 14)); // IP with a: (14.857, 15.143) + segment b2(point(10, 16), point(20, 14)); // IP with a: (15, 15) + + segment c1(point(15, 16), point(13, 8)); + segment c2(point(15, 16), point(14, 8)); + segment c3(point(15, 16), point(15, 8)); + + typedef bg::strategy::side::side_of_intersection side; + + BOOST_CHECK_EQUAL( 1, side::apply(a, b1, c1)); + BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c2)); + BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c3)); + + BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c1)); + BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c2)); + BOOST_CHECK_EQUAL( 0, side::apply(a, b2, c3)); + + // Check internal calculation-method: + BOOST_CHECK_EQUAL(-1400, side::side_value<int>(a, b1, c2)); + BOOST_CHECK_EQUAL( 2800, side::side_value<int>(a, b1, c1)); + + BOOST_CHECK_EQUAL (2800, side::side_value<int>(a, b1, c1)); + BOOST_CHECK_EQUAL(-1400, side::side_value<int>(a, b1, c2)); + BOOST_CHECK_EQUAL(-5600, side::side_value<int>(a, b1, c3)); + + BOOST_CHECK_EQUAL(12800, side::side_value<int>(a, b2, c1)); + BOOST_CHECK_EQUAL( 6400, side::side_value<int>(a, b2, c2)); + BOOST_CHECK_EQUAL( 0, side::side_value<int>(a, b2, c3)); + + // TODO: we might add a check calculating the IP, determining the side + // with the normal side strategy, and verify the results are equal + + return 0; +} + diff --git a/libs/geometry/test/strategies/spherical_side.cpp b/libs/geometry/test/strategies/spherical_side.cpp index a183a141b..6965692ea 100644 --- a/libs/geometry/test/strategies/spherical_side.cpp +++ b/libs/geometry/test/strategies/spherical_side.cpp @@ -3,6 +3,11 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +24,9 @@ #include <boost/geometry/strategies/spherical/ssf.hpp> #include <boost/geometry/strategies/cartesian/side_by_triangle.hpp> +#include <boost/geometry/strategies/agnostic/side_by_azimuth.hpp> +#include <boost/geometry/strategies/geographic/mapping_ssf.hpp> + #include <boost/geometry/core/cs.hpp> #include <boost/geometry/geometries/point.hpp> @@ -47,22 +55,37 @@ inline char side_char(int side) } template <typename Point> -void test_side1(std::string const& case_id, Point const& p1, Point const& p2, Point const& p3, +void test_side1(std::string const& /*case_id*/, Point const& p1, Point const& p2, Point const& p3, int expected, int expected_cartesian) { - // std::cout << case_id << ": "; - //int s = bg::strategy::side::side_via_plane<>::apply(p1, p2, p3); - int side_ssf = bg::strategy::side::spherical_side_formula<>::apply(p1, p2, p3); - //int side2 = bg::strategy::side::side_via_plane<>::apply(p1, p2, p3); - int side_ct = bg::strategy::side::side_by_cross_track<>::apply(p1, p2, p3); + namespace bgss = bg::strategy::side; + // std::cout << case_id << ": "; + //int s = bgss::side_via_plane<>::apply(p1, p2, p3); + int side_ssf = bgss::spherical_side_formula<>::apply(p1, p2, p3); + //int side2 = bgss::side_via_plane<>::apply(p1, p2, p3); + int side_ct = bgss::side_by_cross_track<>::apply(p1, p2, p3); + + // non-official + typedef bg::srs::spheroid<double> spheroid; + spheroid const sph(1.0, 1.0); + int side_azi = bgss::side_by_azimuth<spheroid>(sph).apply(p1, p2, p3); + int side_mssf1 = bgss::mapping_spherical_side_formula<spheroid>(sph).apply(p1, p2, p3); + int side_mssf2 = bgss::mapping_spherical_side_formula<spheroid, bgss::mapping_reduced>(sph).apply(p1, p2, p3); + int side_mssf3 = bgss::mapping_spherical_side_formula<spheroid, bgss::mapping_geocentric>(sph).apply(p1, p2, p3); + + // cartesian typedef bg::strategy::side::services::default_strategy<bg::cartesian_tag>::type cartesian_strategy; int side_cart = cartesian_strategy::apply(p1, p2, p3); - BOOST_CHECK_EQUAL(side_ssf, expected); BOOST_CHECK_EQUAL(side_ct, expected); + BOOST_CHECK_EQUAL(side_azi, expected); + BOOST_CHECK_EQUAL(side_mssf1, expected); + BOOST_CHECK_EQUAL(side_mssf2, expected); + BOOST_CHECK_EQUAL(side_mssf3, expected); BOOST_CHECK_EQUAL(side_cart, expected_cartesian); + /* std::cout << "exp: " << side_char(expected) diff --git a/libs/geometry/test/strategies/vincenty.cpp b/libs/geometry/test/strategies/vincenty.cpp new file mode 100644 index 000000000..b80da4bb5 --- /dev/null +++ b/libs/geometry/test/strategies/vincenty.cpp @@ -0,0 +1,271 @@ +// 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. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include <geometry_test_common.hpp> + +#include <boost/concept_check.hpp> + +#include <boost/geometry/strategies/geographic/distance_vincenty.hpp> +#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp> +#include <boost/geometry/algorithms/detail/vincenty_direct.hpp> + +#include <boost/geometry/core/srs.hpp> +#include <boost/geometry/strategies/strategies.hpp> +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/geometries/point.hpp> +#include <test_common/test_point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + +template <typename T> +void normalize_deg(T & deg) +{ + while ( deg > T(180) ) + deg -= T(360); + while ( deg <= T(-180) ) + deg += T(360); +} + +template <typename T> +T difference_deg(T const& a1, T const& a2) +{ + T d = a1 - a2; + normalize_deg(d); + return d; +} + +template <typename T> +void check_deg(std::string const& name, T const& a1, T const& a2, T const& percent, T const& error) +{ + T diff = bg::math::abs(difference_deg(a1, a2)); + + if ( bg::math::equals(a1, T(0)) || bg::math::equals(a2, T(0)) ) + { + if ( diff > error ) + { + BOOST_ERROR(name << " - the difference {" << diff << "} between {" << a1 << "} and {" << a2 << "} exceeds {" << error << "}"); + } + } + else + { + T greater = (std::max)(bg::math::abs(a1), bg::math::abs(a2)); + + if ( diff > greater * percent / T(100) ) + { + BOOST_ERROR(name << " the difference {" << diff << "} between {" << a1 << "} and {" << a2 << "} exceeds {" << percent << "}%"); + } + } +} + +double azimuth(double deg, double min, double sec) +{ + min = fabs(min); + sec = fabs(sec); + + if ( deg < 0 ) + { + min = -min; + sec = -sec; + } + + return deg + min/60.0 + sec/3600.0; +} + +double azimuth(double deg, double min) +{ + return azimuth(deg, min, 0.0); +} + +template <typename P> +bool non_precise_ct() +{ + typedef typename bg::coordinate_type<P>::type ct; + return boost::is_integral<ct>::value || boost::is_float<ct>::value; +} + +template <typename P1, typename P2, typename Spheroid> +void test_vincenty(double lon1, double lat1, double lon2, double lat2, + double expected_distance, + double expected_azimuth_12, + double expected_azimuth_21, + Spheroid const& spheroid) +{ + typedef typename bg::promote_floating_point + < + typename bg::select_calculation_type<P1, P2, void>::type + >::type calc_t; + + calc_t tolerance = non_precise_ct<P1>() || non_precise_ct<P2>() ? + 5.0 : 0.001; + calc_t error = non_precise_ct<P1>() || non_precise_ct<P2>() ? + 1e-5 : 1e-12; + + // formula + { + bg::detail::vincenty_inverse<calc_t> vi(lon1 * bg::math::d2r, + lat1 * bg::math::d2r, + lon2 * bg::math::d2r, + lat2 * bg::math::d2r, + spheroid); + calc_t dist = vi.distance(); + calc_t az12 = vi.azimuth12(); + calc_t az21 = vi.azimuth21(); + + calc_t az12_deg = az12 * bg::math::r2d; + calc_t az21_deg = az21 * bg::math::r2d; + + BOOST_CHECK_CLOSE(dist, calc_t(expected_distance), tolerance); + check_deg("az12_deg", az12_deg, calc_t(expected_azimuth_12), tolerance, error); + check_deg("az21_deg", az21_deg, calc_t(expected_azimuth_21), tolerance, error); + + bg::detail::vincenty_direct<calc_t> vd(lon1 * bg::math::d2r, + lat1 * bg::math::d2r, + dist, + az12, + spheroid); + calc_t direct_lon2 = vd.lon2(); + calc_t direct_lat2 = vd.lat2(); + calc_t direct_az21 = vd.azimuth21(); + + calc_t direct_lon2_deg = direct_lon2 * bg::math::r2d; + calc_t direct_lat2_deg = direct_lat2 * bg::math::r2d; + calc_t direct_az21_deg = direct_az21 * bg::math::r2d; + + check_deg("direct_lon2_deg", direct_lon2_deg, calc_t(lon2), tolerance, error); + check_deg("direct_lat2_deg", direct_lat2_deg, calc_t(lat2), tolerance, error); + check_deg("direct_az21_deg", direct_az21_deg, az21_deg, tolerance, error); + } + + // strategy + { + typedef bg::strategy::distance::vincenty<Spheroid> vincenty_type; + + BOOST_CONCEPT_ASSERT( + ( + bg::concept::PointDistanceStrategy<vincenty_type, P1, P2>) + ); + + vincenty_type vincenty(spheroid); + typedef typename bg::strategy::distance::services::return_type<vincenty_type, P1, P2>::type return_type; + + P1 p1; + P2 p2; + + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + + BOOST_CHECK_CLOSE(vincenty.apply(p1, p2), return_type(expected_distance), tolerance); + BOOST_CHECK_CLOSE(bg::distance(p1, p2, vincenty), return_type(expected_distance), tolerance); + } +} + +template <typename P1, typename P2> +void test_vincenty(double lon1, double lat1, double lon2, double lat2, + double expected_distance, + double expected_azimuth_12, + double expected_azimuth_21) +{ + test_vincenty<P1, P2>(lon1, lat1, lon2, lat2, + expected_distance, expected_azimuth_12, expected_azimuth_21, + bg::srs::spheroid<double>()); +} + +template <typename P1, typename P2> +void test_all() +{ + // See: + // - http://www.ga.gov.au/geodesy/datums/vincenty_inverse.jsp + // - http://www.ga.gov.au/geodesy/datums/vincenty_direct.jsp + // Values in the comments below was calculated using the above pages + // in some cases distances may be different, previously used values was left + + // use km + double gda_a = 6378.1370; + double gda_f = 1.0 / 298.25722210; + double gda_b = gda_a * ( 1.0 - gda_f ); + bg::srs::spheroid<double> gda_spheroid(gda_a, gda_b); + + // Test fractional coordinates only for non-integral types + if ( BOOST_GEOMETRY_CONDITION( + ! boost::is_integral<typename bg::coordinate_type<P1>::type>::value + && ! boost::is_integral<typename bg::coordinate_type<P2>::type>::value ) ) + { + // Flinders Peak -> Buninyong + test_vincenty<P1, P2>(azimuth(144,25,29.52440), azimuth(-37,57,3.72030), + azimuth(143,55,35.38390), azimuth(-37,39,10.15610), + 54.972271, azimuth(306,52,5.37), azimuth(127,10,25.07), + gda_spheroid); + } + + // Lodz -> Trondheim + test_vincenty<P1, P2>(azimuth(19,28), azimuth(51,47), + azimuth(10,21), azimuth(63,23), + 1399.032724, azimuth(340,54,25.14), azimuth(153,10,0.19), + gda_spheroid); + // London -> New York + test_vincenty<P1, P2>(azimuth(0,7,39), azimuth(51,30,26), + azimuth(-74,0,21), azimuth(40,42,46), + 5602.044851, azimuth(288,31,36.82), azimuth(51,10,33.43), + gda_spheroid); + + // Shanghai -> San Francisco + test_vincenty<P1, P2>(azimuth(121,30), azimuth(31,12), + azimuth(-122,25), azimuth(37,47), + 9899.698550, azimuth(45,12,44.76), azimuth(309,50,20.88), + gda_spheroid); + + test_vincenty<P1, P2>(0, 0, 0, 50, 5540.847042, 0, 180, gda_spheroid); // N + test_vincenty<P1, P2>(0, 0, 0, -50, 5540.847042, 180, 0, gda_spheroid); // S + test_vincenty<P1, P2>(0, 0, 50, 0, 5565.974540, 90, -90, gda_spheroid); // E + test_vincenty<P1, P2>(0, 0, -50, 0, 5565.974540, -90, 90, gda_spheroid); // W + + test_vincenty<P1, P2>(0, 0, 50, 50, 7284.879297, azimuth(32,51,55.87), azimuth(237,24,50.12), gda_spheroid); // NE + + // The original distance values, azimuths calculated using the web form mentioned above + // Using default spheroid units (meters) + test_vincenty<P1, P2>(0, 89, 1, 80, 1005153.5769, azimuth(178,53,23.85), azimuth(359,53,18.35)); // sub-polar + test_vincenty<P1, P2>(4, 52, 4, 52, 0.0, 0, 0); // no point difference + test_vincenty<P1, P2>(4, 52, 3, 40, 1336039.890, azimuth(183,41,29.08), azimuth(2,58,5.13)); // normal case +} + +template <typename P> +void test_all() +{ + test_all<P, P>(); +} + +int test_main(int, char* []) +{ + //test_all<float[2]>(); + //test_all<double[2]>(); + test_all<bg::model::point<double, 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> > >(); + +#if defined(HAVE_TTMATH) + test_all<bg::model::point<ttmath::Big<1,4>, 2, bg::cs::geographic<bg::degree> > >(); + test_all<bg::model::point<ttmath_big, 2, bg::cs::geographic<bg::degree> > >(); +#endif + + + return 0; +} |