diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/geometry/test/strategies | |
parent | Initial commit. (diff) | |
download | ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/geometry/test/strategies')
33 files changed, 7309 insertions, 0 deletions
diff --git a/src/boost/libs/geometry/test/strategies/Jamfile.v2 b/src/boost/libs/geometry/test/strategies/Jamfile.v2 new file mode 100644 index 00000000..e58abee7 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/Jamfile.v2 @@ -0,0 +1,46 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +# Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +# +# This file was modified by Oracle on 2014-2019. +# Modifications copyright (c) 2014-2019, 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 +# 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) + +test-suite boost-geometry-strategies + : + [ run andoyer.cpp : : : : strategies_andoyer ] + [ run cross_track.cpp : : : : strategies_cross_track ] + [ run crossings_multiply.cpp : : : : strategies_crossings_multiply ] + [ run distance_default_result.cpp : : : : strategies_distance_default_result ] + [ run distance_cross_track.cpp : : : : strategies_distance_cross_track ] + [ run douglas_peucker.cpp : : : : strategies_douglas_peucker ] + [ run envelope_segment.cpp : : : : strategies_envelope_segment ] + [ run franklin.cpp : : : : strategies_franklin ] + [ run haversine.cpp : : : : strategies_haversine ] + [ run point_in_box.cpp : : : : strategies_point_in_box ] + [ run projected_point.cpp : : : : strategies_projected_point ] + [ run projected_point_ax.cpp : : : : strategies_projected_point_ax ] + [ run pythagoras.cpp : : : : strategies_pythagoras ] + [ run pythagoras_point_box.cpp : : : : strategies_pythagoras_point_box ] + [ run segment_intersection.cpp : : : : strategies_segment_intersection ] + [ run segment_intersection_collinear.cpp : : : : strategies_segment_intersection_collinear ] + [ run segment_intersection_geo.cpp : : : : strategies_segment_intersection_geo ] + [ run segment_intersection_sph.cpp : : : : strategies_segment_intersection_sph ] + [ run side_of_intersection.cpp : : : : strategies_side_of_intersection ] + [ run spherical_side.cpp : : : : strategies_spherical_side ] + [ run thomas.cpp : : : : strategies_thomas ] + [ run transform_cs.cpp : : : : strategies_transform_cs ] + [ run transformer.cpp : : : : strategies_transformer ] + [ run matrix_transformer.cpp : : : : strategies_matrix_transformer ] + [ run vincenty.cpp : : : : strategies_vincenty ] + [ run winding.cpp : : : : strategies_winding ] + ; diff --git a/src/boost/libs/geometry/test/strategies/andoyer.cpp b/src/boost/libs/geometry/test/strategies/andoyer.cpp new file mode 100644 index 00000000..515bbf2e --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/andoyer.cpp @@ -0,0 +1,346 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// 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-2017. +// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// 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/algorithms/assign.hpp> +#include <boost/geometry/algorithms/distance.hpp> +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/srs/spheroid.hpp> +#include <boost/geometry/strategies/concepts/distance_concept.hpp> +#include <boost/geometry/strategies/geographic/distance_andoyer.hpp> +#include <boost/geometry/strategies/geographic/side_andoyer.hpp> + +#include <test_common/test_point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + + + +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) +{ + 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) +{ + // 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; + typedef bg::strategy::distance::geographic<bg::strategy::andoyer, stype> geographic_type; + typedef bg::formula::andoyer_inverse<rtype, true, false> andoyer_inverse_type; + + BOOST_CONCEPT_ASSERT + ( + (bg::concepts::PointDistanceStrategy<andoyer_type, P1, P2>) + ); + + andoyer_type andoyer; + geographic_type geographic; + typedef typename bg::strategy::distance + ::services::return_type<andoyer_type, P1, P2>::type return_type; + + P1 p1; + P2 p2; + + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + + return_type d_strategy = andoyer.apply(p1, p2); + return_type d_strategy2 = geographic.apply(p1, p2); + return_type d_function = bg::distance(p1, p2, andoyer); + + double diff = bg::math::longitude_distance_signed<bg::degree>(lon1, lon2); + return_type d_formula; + + // if the points lay on a meridian, distance strategy calls the special formula + // for meridian distance that returns different result than andoyer formula + // for nearly antipodal points + if (bg::math::equals(diff, 0.0) + || bg::math::equals(bg::math::abs(diff), 180.0)) + { + d_formula = d_strategy; + } + else + { + 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_strategy2 / 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::formula::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, + bool is_antipodal = false) +{ + double d180 = is_antipodal ? 0 : 180; + 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, d180 - expected_azimuth_deg); + test_distazi<P1, P2>(-lon1, -lat1, -lon2, -lat2, expected_km, -d180 + 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, + double lon, double lat, + int expected_side) +{ + // 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::strategy::side::andoyer<stype> strategy_type; + typedef bg::strategy::side::geographic<bg::strategy::andoyer, stype> strategy2_type; + + strategy_type strategy; + strategy2_type strategy2; + + PS p1, p2; + P p; + + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + bg::assign_values(p, lon, lat); + + int side = strategy.apply(p1, p2, p); + int side2 = strategy2.apply(p1, p2, p); + + BOOST_CHECK_EQUAL(side, expected_side); + BOOST_CHECK_EQUAL(side2, expected_side); +} + +template <typename P1, typename P2> +void test_all() +{ + // 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, 20003.9, 0.0); + test_distazi<P1, P2>(0, 0, -180, 0, 20003.9, 0.0); + test_distazi<P1, P2>(-90, 0, 90, 0, 20003.9, 0.0); + test_distazi<P1, P2>(90, 0, -90, 0, 20003.9, 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, 20003.92, 0.0, true); + } + + /* 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)) + */ + + + 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); + test_side<P1, P2>(10, 0, 10, -1, 10, 2, 0); + + test_side<P1, P2>(10, 0, 10, 1, 0, 2, 1); // left + test_side<P1, P2>(10, 0, 10, -1, 0, 2, -1); // right + + test_side<P1, P2>(-10, -10, 10, 10, 10, 0, -1); // right + test_side<P1, P2>(-10, -10, 10, 10, -10, 0, 1); // left + test_side<P1, P2>(170, -10, -170, 10, -170, 0, -1); // right + test_side<P1, P2>(170, -10, -170, 10, 170, 0, 1); // left +} + +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/src/boost/libs/geometry/test/strategies/cross_track.cpp b/src/boost/libs/geometry/test/strategies/cross_track.cpp new file mode 100644 index 00000000..861251e4 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/cross_track.cpp @@ -0,0 +1,181 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// 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/core/ignore_unused.hpp> + +#include <boost/geometry/io/wkt/read.hpp> + +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/algorithms/distance.hpp> + +#include <boost/geometry/strategies/spherical/distance_haversine.hpp> +#include <boost/geometry/strategies/spherical/distance_cross_track.hpp> + +#include <boost/geometry/strategies/concepts/distance_concept.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/segment.hpp> + + +// This test is GIS oriented. + + +template <typename Point, typename LatitudePolicy> +void test_distance( + typename bg::coordinate_type<Point>::type const& lon1, + typename bg::coordinate_type<Point>::type const& lat1, + typename bg::coordinate_type<Point>::type const& lon2, + typename bg::coordinate_type<Point>::type const& lat2, + typename bg::coordinate_type<Point>::type const& lon3, + typename bg::coordinate_type<Point>::type const& lat3, + typename bg::coordinate_type<Point>::type const& radius, + typename bg::coordinate_type<Point>::type const& expected, + typename bg::coordinate_type<Point>::type const& tolerance) +{ + typedef bg::strategy::distance::cross_track + < + typename bg::coordinate_type<Point>::type + > strategy_type; + + typedef typename bg::strategy::distance::services::return_type + < + strategy_type, + Point, + Point + >::type return_type; + + + { + // compile-check if there is a strategy for this type + typedef typename bg::strategy::distance::services::default_strategy + < + bg::point_tag, bg::segment_tag, Point, Point + >::type cross_track_strategy_type; + + typedef typename bg::strategy::distance::services::default_strategy + < + bg::segment_tag, bg::point_tag, Point, Point + >::type reversed_tags_cross_track_strategy_type; + + boost::ignore_unused<cross_track_strategy_type, + reversed_tags_cross_track_strategy_type>(); + } + + + BOOST_CONCEPT_ASSERT + ( + (bg::concepts::PointSegmentDistanceStrategy<strategy_type, Point, Point>) + ); + + + Point p1, p2, p3; + bg::assign_values(p1, lon1, LatitudePolicy::apply(lat1)); + bg::assign_values(p2, lon2, LatitudePolicy::apply(lat2)); + bg::assign_values(p3, lon3, LatitudePolicy::apply(lat3)); + + + strategy_type strategy; + return_type d = strategy.apply(p1, p2, p3); + + BOOST_CHECK_CLOSE(radius * d, expected, tolerance); + + // The strategy should return the same result if we reverse the parameters + d = strategy.apply(p1, p3, p2); + BOOST_CHECK_CLOSE(radius * d, expected, tolerance); + + // Test specifying radius explicitly + strategy_type strategy_radius(radius); + d = strategy_radius.apply(p1, p2, p3); + BOOST_CHECK_CLOSE(d, expected, tolerance); + + + // Test the "default strategy" registration + bg::model::referring_segment<Point const> segment(p2, p3); + d = bg::distance(p1, segment); + BOOST_CHECK_CLOSE(radius * d, expected, tolerance); +} + + +template <typename Point> +void test_case_boost_geometry_list_20120625() +{ + // This function tests the bug submitted by Karsten Ahnert + // on Boost.Geometry list at 2012-06-25, and wherefore he + // submitted a patch a few days later. + + Point p1, p2; + bg::model::segment<Point> s1, s2; + + bg::read_wkt("POINT(1 1)", p1); + bg::read_wkt("POINT(5 1)", p2); + bg::read_wkt("LINESTRING(0 2,2 2)", s1); + bg::read_wkt("LINESTRING(2 2,4 2)", s2); + + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, s1), 0.0174586, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, s2), 0.0246783, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, s1), 0.0551745, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, s2), 0.0246783, 0.0001); + + // Check degenerated segments + bg::model::segment<Point> s3; + bg::read_wkt("LINESTRING(2 2,2 2)", s3); + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, s3), 0.0246783, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, s3), 0.0551745, 0.0001); + + // Point/Point distance should be identical: + Point p3; + bg::read_wkt("POINT(2 2)", p3); + BOOST_CHECK_CLOSE(boost::geometry::distance(p1, p3), 0.0246783, 0.0001); + BOOST_CHECK_CLOSE(boost::geometry::distance(p2, p3), 0.0551745, 0.0001); +} + + +template <typename Point, typename LatitudePolicy> +void test_all() +{ + typename bg::coordinate_type<Point>::type const average_earth_radius = 6372795.0; + + // distance (Paris <-> Amsterdam/Barcelona), + // with coordinates rounded as below ~87 km + // is equal to distance (Paris <-> Barcelona/Amsterdam) + typename bg::coordinate_type<Point>::type const p_to_ab = 86.798321 * 1000.0; + test_distance<Point, LatitudePolicy>(2, 48, 4, 52, 2, 41, average_earth_radius, p_to_ab, 0.1); + test_distance<Point, LatitudePolicy>(2, 48, 2, 41, 4, 52, average_earth_radius, p_to_ab, 0.1); + + test_case_boost_geometry_list_20120625<Point>(); +} + + +int test_main(int, char* []) +{ + test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> >, geographic_policy >(); + + // NYI: haversine for mathematical spherical coordinate systems + // test_all<bg::model::point<double, 2, bg::cs::spherical<bg::degree> >, mathematical_policya >(); + +#if defined(HAVE_TTMATH) + typedef ttmath::Big<1,4> tt; + //test_all<bg::model::point<tt, 2, bg::cs::geographic<bg::degree> >, geographic_policy>(); +#endif + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/crossings_multiply.cpp b/src/boost/libs/geometry/test/strategies/crossings_multiply.cpp new file mode 100644 index 00000000..f57d383f --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/crossings_multiply.cpp @@ -0,0 +1,87 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2010-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) + + +#include <strategies/test_within.hpp> + + +template <typename Point> +void test_all() +{ + typedef bg::model::polygon<Point> polygon; + + std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))"; + std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))"; + std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))"; + + bg::strategy::within::crossings_multiply<Point> s; + + + test_geometry<Point, polygon>("b1", "POINT(1 1)", box, s, true); + test_geometry<Point, polygon>("b2", "POINT(3 3)", box, s, false); + + // Test ALL corners (officialy false but some strategies might answer true) + test_geometry<Point, polygon>("b3a", "POINT(0 0)", box, s, false); + test_geometry<Point, polygon>("b3b", "POINT(0 2)", box, s, false); + test_geometry<Point, polygon>("b3c", "POINT(2 2)", box, s, false); + test_geometry<Point, polygon>("b3d", "POINT(2 0)", box, s, false); + + // Test ALL sides (officialy false but some strategies might answer true) + test_geometry<Point, polygon>("b4a", "POINT(0 1)", box, s, false); + test_geometry<Point, polygon>("b4b", "POINT(1 2)", box, s, true); // different + test_geometry<Point, polygon>("b4c", "POINT(2 1)", box, s, false); + test_geometry<Point, polygon>("b4d", "POINT(1 0)", box, s, false); + + + test_geometry<Point, polygon>("t1", "POINT(1 1)", triangle, s, true); + test_geometry<Point, polygon>("t2", "POINT(3 3)", triangle, s, false); + + test_geometry<Point, polygon>("t3a", "POINT(0 0)", triangle, s, false); + test_geometry<Point, polygon>("t3b", "POINT(0 4)", triangle, s, true); // diff + test_geometry<Point, polygon>("t3c", "POINT(5 0)", triangle, s, false); + + test_geometry<Point, polygon>("t4a", "POINT(0 2)", triangle, s, false); + test_geometry<Point, polygon>("t4b", "POINT(3 2)", triangle, s, false); + test_geometry<Point, polygon>("t4c", "POINT(2 0)", triangle, s, false); + + + test_geometry<Point, polygon>("h1", "POINT(0.5 0.5)", with_hole, s, true); + test_geometry<Point, polygon>("h2a", "POINT(1.5 1.5)", with_hole, s, false); + test_geometry<Point, polygon>("h2b", "POINT(5 5)", with_hole, s, false); + + test_geometry<Point, polygon>("h3a", "POINT(1 1)", with_hole, s, true); // diff + test_geometry<Point, polygon>("h3b", "POINT(2 2)", with_hole, s, false); + test_geometry<Point, polygon>("h3c", "POINT(0 0)", with_hole, s, false); + + test_geometry<Point, polygon>("h4a", "POINT(1 1.5)", with_hole, s, false); + test_geometry<Point, polygon>("h4b", "POINT(1.5 2)", with_hole, s, false); + + // Lying ON (one of the sides of) interior ring + test_geometry<Point, polygon>("#77-1", "POINT(6 3.5)", + "POLYGON((5 3,5 4,4 4,4 5,3 5,3 6,5 6,5 5,7 5,7 6,8 6,8 5,9 5,9 2,8 2,8 1,7 1,7 2,5 2,5 3),(6 3,8 3,8 4,6 4,6 3))", + s, false); +} + + +int test_main(int, char* []) +{ + test_all<bg::model::point<float, 2, bg::cs::cartesian> >(); + test_all<bg::model::point<double, 2, bg::cs::cartesian> >(); + +#if defined(HAVE_TTMATH) + test_all<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >(); +#endif + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/distance.cpp b/src/boost/libs/geometry/test/strategies/distance.cpp new file mode 100644 index 00000000..876e2873 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/distance.cpp @@ -0,0 +1,117 @@ +// 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) + +#include <geometry_test_common.hpp> + +#include <boost/concept_check.hpp> + +#include <boost/geometry/srs/srs.hpp> +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/strategies/strategies.hpp> + +#include <test_common/test_point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + +typedef bg::srs::spheroid<double> stype; + +typedef bg::strategy::andoyer andoyer_formula; +typedef bg::strategy::thomas thomas_formula; +typedef bg::strategy::vincenty vincenty_formula; + +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 FormulaPolicy> +void test_distance(double lon1, double lat1, double lon2, double lat2) +{ + 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; + + P1 p1; + P2 p2; + + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + + // Test strategy that implements meridian distance against formula + // that implements general distance + // That may change in the future but in any case these calls must return + // the same result + + calc_t dist_formula = FormulaPolicy::template inverse + < + double, true, false, false, false, false + >::apply(lon1 * bg::math::d2r<double>(), + lat1 * bg::math::d2r<double>(), + lon2 * bg::math::d2r<double>(), + lat2 * bg::math::d2r<double>(), + stype()).distance; + + bg::strategy::distance::geographic<FormulaPolicy, stype> strategy; + calc_t dist_strategy = strategy.apply(p1, p2); + BOOST_CHECK_CLOSE(dist_formula, dist_strategy, tolerance); +} + +template <typename P1, typename P2, typename FormulaPolicy> +void test_distance_reverse(double lon1, double lat1, + double lon2, double lat2) +{ + test_distance<P1, P2, FormulaPolicy>(lon1, lat1, lon2, lat2); + test_distance<P1, P2, FormulaPolicy>(lon2, lat2, lon1, lat1); +} + +template <typename P1, typename P2, typename FormulaPolicy> +void test_meridian() +{ + test_distance_reverse<P1, P2, FormulaPolicy>(0., 70., 0., 80.); + test_distance_reverse<P1, P2, FormulaPolicy>(0, 70, 0., -80.); + test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 0., 80.); + test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 0., -80.); + + test_distance_reverse<P1, P2, FormulaPolicy>(0., 70., 180., 80.); + test_distance_reverse<P1, P2, FormulaPolicy>(0., 70., 180., -80.); + test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 180., 80.); + test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 180., -80.); + + test_distance_reverse<P1, P2, FormulaPolicy>(350., 70., 170., 80.); + test_distance_reverse<P1, P2, FormulaPolicy>(350., 70., 170., -80.); + test_distance_reverse<P1, P2, FormulaPolicy>(350., -70., 170., 80.); + test_distance_reverse<P1, P2, FormulaPolicy>(350., -70., 170., -80.); +} + +template <typename P> +void test_all() +{ + test_meridian<P, P, andoyer_formula>(); + test_meridian<P, P, thomas_formula>(); + test_meridian<P, P, vincenty_formula>(); +} + +int test_main(int, char* []) +{ + 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> > >(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/distance_cross_track.cpp b/src/boost/libs/geometry/test/strategies/distance_cross_track.cpp new file mode 100644 index 00000000..3ec098c8 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/distance_cross_track.cpp @@ -0,0 +1,116 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2019 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, 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 +// http://www.boost.org/LICENSE_1_0.txt) + + +#include <sstream> + +#include "../formulas/test_formula.hpp" +#include "distance_cross_track_cases.hpp" + +#include <boost/geometry/strategies/strategies.hpp> +#include <boost/geometry/srs/spheroid.hpp> + +struct error{ + double long_distance; + double short_distance; + double very_short_distance; + double very_very_short_distance; +}; + +void check_result(double const& result, double const& expected, + double const& reference, error const& reference_error) +{ + BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 0.1, + std::setprecision(20) << "result {" << result + << "} different than expected {" << expected << "}."); + + double reference_error_value = result > 2000 ? reference_error.long_distance + : result > 100 ? reference_error.short_distance + : result > 20 ? reference_error.very_short_distance + : reference_error.very_very_short_distance; + + BOOST_GEOMETRY_CHECK_CLOSE(result, reference, reference_error_value, + std::setprecision(20) << "result {" << result + << "} different than reference {" + << reference << "}."); +} + +template <typename Point> +void test_all(expected_results const& results) +{ + double const d2r = bg::math::d2r<double>(); + + double lon1r = results.p1.lon * d2r; + double lat1r = results.p1.lat * d2r; + double lon2r = results.p2.lon * d2r; + double lat2r = results.p2.lat * d2r; + double lon3r = results.p3.lon * d2r; + double lat3r = results.p3.lat * d2r; + + typedef bg::srs::spheroid<double> Spheroid; + + // WGS84 + Spheroid spheroid(6378137.0, 6356752.3142451793); + + error errors [] = + { + {0.00000001, 0.00000001, 0.00000001, 0.000001}, //vincenty + {0.0002, 0.002, 0.01, 0.2}, //thomas + {0.002, 0.4, 15, 25}, //andoyer + {1, 6, 15, 200} //spherical + }; + + //vincenty + double distance = bg::strategy::distance::detail::geographic_cross_track<bg::strategy::vincenty, Spheroid, double, true>(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.vincenty_bisection, results.reference, errors[0]); + + distance = bg::strategy::distance::geographic_cross_track<bg::strategy::vincenty, Spheroid, double>(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.vincenty, results.reference, errors[0]); + + //thomas + distance = bg::strategy::distance::detail::geographic_cross_track<bg::strategy::thomas, Spheroid, double, true>(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.thomas_bisection, results.reference, errors[1]); + + distance = bg::strategy::distance::geographic_cross_track<bg::strategy::thomas, Spheroid, double>(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.thomas, results.reference, errors[1]); + + //andoyer + distance = bg::strategy::distance::detail::geographic_cross_track<bg::strategy::andoyer, Spheroid, double, true>(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.andoyer_bisection, results.reference, errors[2]); + + distance = bg::strategy::distance::geographic_cross_track<bg::strategy::andoyer, Spheroid, double>(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.andoyer, results.reference, errors[2]); + + //spherical + distance = bg::strategy::distance::cross_track<>(bg::formula::mean_radius<double>(spheroid)) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.spherical, results.reference, errors[3]); + +} + +int test_main(int, char*[]) +{ + typedef bg::model::point<double, 2, bg::cs::geographic<bg::radian> > point; + + for (size_t i = 0; i < expected_size; ++i) + { + test_all<point>(expected[i]); + } + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/distance_cross_track_cases.hpp b/src/boost/libs/geometry/test/strategies/distance_cross_track_cases.hpp new file mode 100644 index 00000000..01cf2a12 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/distance_cross_track_cases.hpp @@ -0,0 +1,518 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2019 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_TEST_DISTANCE_CROSS_TRACK_CASES_HPP +#define BOOST_GEOMETRY_TEST_DISTANCE_CROSS_TRACK_CASES_HPP + +struct coordinates +{ + double lon; + double lat; +}; + +struct expected_results +{ + coordinates p1; //1st point of segment + coordinates p2; //2nd point of segment + coordinates p3; //point to compute distance from segment + double reference; // karney or vincenty + double vincenty_bisection; + double vincenty; + double thomas_bisection; + double thomas; + double andoyer_bisection; + double andoyer; + double spherical; +}; + +expected_results expected[] = +{ + { + { 0, 0 },{ 1, 1 },{ 0, 1 }, + 78442.119873761606868, + 78442.119873761606868, + 78442.119873761592316, + 78442.118218914125464, + 78442.118218840550981, + 78440.792929481409374, + 78440.792934224984492, + 78618.810427426869865 + } , { + { 0, 0 },{ 1, 1 },{ 1, 0 }, + 78453.98942845336569, + 78453.98942845336569, + 78453.98942845336569, + 78453.990728736869642, + 78453.990728682110785, + 78453.54172924211889, + 78453.541733992169611, + 78630.786885094828904 + } , { + { 10, 15 },{ 30, 15 },{ 15, 80 }, + 7204174.4886689241976, + 7204174.4886689241976, + 7204174.4886689241976, + 7204174.4785777237266, + 7204174.4785777227953, + 7204194.9162934627384, + 7204194.9162937803194, + 7205729.8545973757282 + } , { + { 10, 15 },{ 30, 15 },{ 15, 10 }, + 571412.78107940487098, + 571412.78107940487098, + 571412.78107940475456, + 571412.77996722259559, + 571412.77996722620446, + 571408.51759251800831, + 571408.51759251928888, + 574226.66911869682372 + } , { + { 10, 15 },{ 30, 15 },{ 5, 10 }, + 775316.40275838342495, + 775316.40275838342495, + 775316.40275838342495, + 775316.40098149504047, + 775316.40098149504047, + 775309.55307898123283, + 775309.55307898123283, + 776861.2271022957284 + } , { + { 10, 15 },{ 30, 15 },{ 35, 10 }, + 775316.40275838342495, + 775316.40275838342495, + 775316.40275838342495, + 775316.40098149504047, + 775316.40098149504047, + 775309.55307898123283, + 775309.55307898123283, + 776861.22710229584482 + } , { + { 2, 2 },{ 3, 2 },{ 3.5, 3 }, + 123770.82713049851009, + 123770.82713049851009, + 123770.82713049851009, + 123770.82682863833907, + 123770.82682863833907, + 123769.27773668900772, + 123769.27773668900772, + 124295.90554402528505 + } , { + { 2, 2 },{ 3, 2 },{ 1.5, 3 }, + 123770.82713049851009, + 123770.82713049851009, + 123770.82713049851009, + 123770.82682863833907, + 123770.82682863833907, + 123769.27773668900772, + 123769.27773668900772, + 124295.90554402528505 + } , { + { 2, 2 },{ 3, 2 },{ 2, 3 }, + 110576.41139532231318, + 110576.41139532231318, + 110576.41139532238594, + 110576.41139116862905, + 110576.41139118297724, + 110575.1780244907568, + 110575.17802451056195, + 111195.07457694716868 + } , { + { 2, 2 },{ 3, 2 },{ 3, 3 }, + 110576.41139532234229, + 110576.41139532234229, + 110576.41139532234229, + 110576.41139242639474, + 110576.41139243228827, + 110575.17802478378871, + 110575.17802474705968, + 111195.07457694721234 + } , { + { 2, 2 },{ 3, 2 },{ 3.5, 1 }, + 123784.75399867084343, + 123784.75399867084343, + 123784.75399867084343, + 123784.75369734384003, + 123784.75369734384003, + 123783.19294134904339, + 123783.19294134904339, + 124311.043335600305 + } , { + { 2, 2 },{ 3, 2 },{ 1.5, 1 }, + 123784.75399867084343, + 123784.75399867084343, + 123784.75399867084343, + 123784.75369734384003, + 123784.75369734384003, + 123783.19294134904339, + 123783.19294134904339, + 124311.043335600305 + } , { + { 2, 2 },{ 3, 2 },{ 2, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , { + { 2, 2 },{ 3, 2 },{ 3, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , { + { 2, -2 },{ 3, -2 },{ 3, -1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , { + { 220, 2 },{ 3, 2 },{ 3, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , //antimeridian + { + { 220, 2 },{ 3, 2 },{ 220, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , //meridian + { + { 2, 2 },{ 2, 4 },{ 2.5, 2 }, + 55626.064900081859, + 55626.064900081859, + 55626.064900081867, + 55626.06490013907, + 55626.064900107223, + 55626.065279513903, + 55626.065279463517, + 55563.670489238102 + } , { + { 2, 2 },{ 2, 4 },{ 2.5, 5 }, + 123722.15822285149, + 123722.15822285149, + 123722.15822285149, + 123722.15791917888, + 123722.15791917888, + 123720.64936755209, + 123720.64936755209, + 124243.00560435352 + } , { + { 2, 2 },{ 2, 4 },{ 2.5, 3 }, + 55583.973320908837, + 55583.973320908837, + 55583.97332090883, + 55583.973320941128, + 55583.973320900877, + 55583.97416950998, + 55583.974169663285, + 55521.343440931159 + } , { + { 0, 40 },{ 180, 80 },{ 0, 20 }, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7361901053, + 2217162.7361901053, + 2217171.9891410829, + 2217171.9891410829, + 2223901.5946926316 + } , { + { 0, 40 },{ 0, 80 },{ 0, 20 }, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7361901053, + 2217162.7361901053, + 2217171.9891410829, + 2217171.9891410829, + 2223901.5946926316 + } , { + { 0, 0 },{ 0, 90 },{ 0, 80 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 0, 0 },{ 0, 90 },{ 1, 80 }, + 19392.530629092114, + 19392.530629092114, + 19392.530629092107, + 19392.53062953979, + 19392.530629094777, + 19392.328788289116, + 19392.328788113067, + 19307.872231041671 + } , { + { 1, -1 }, { 1, 0 },{ 2, 0 }, + 111319.4907932264, + 111319.4907932264, + 111319.4907932264, + 111319.49079334327, + 111319.49079326246, + 111319.49079326226, + 111319.49079326246, + 111195.07973463158 + } , //equator + { + { 2, 0 },{ 3, 0 },{ 0, 0 }, + 222638.98158645280637, + 222638.98158645280637, + 222638.98158645280637, + 222638.98158654122381, + 222638.98158654122381, + 222638.98158654125291, + 222638.98158654125291, + 222390.15946926316246 + } , { + { 2, 0 },{ 3, 0 },{ 2.5, 3 }, + 331725.86989626317518, + 331725.86989626317518, + 331725.86989626317518, + 331725.87608870770782, + 331725.87608870770782, + 331722.14136137196328, + 331722.14136137196328, + 333585.2392038948019 + } , { + { 2, 0 },{ 3, 0 },{ 2, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 2, 0 },{ 3, 0 },{ 3, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 2, 0 },{ 3, 0 },{ 2.5, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 2, 0 },{ 3, 0 },{ 3.5, 3 }, + 336358.80734967370518, + 336358.80734967370518, + 336358.80734967370518, + 336358.80718013871228, + 336358.80718013871228, + 336354.9292840428534, + 336354.9292840428534, + 338182.45508443051949 + } , //segment pass by pole +/* those cases have expected very large reference errors for spherical + * { + { 0, 0 },{ 180, 0 },{ 0, 90 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10007557.176116843 + } , { + { 0, 0 },{ 180, 0 },{ 80, 89 }, + 109996.81571864839, + 109996.81571864839, + 109996.81571864836, + 109996.81571864968, + 109996.81571858823, + 109995.58014976831, + 109995.58014972134, + 9896362.096382184, + }*/ // short distance to segment + { + { 0.5, 0 },{ 175.5, 0 },{ 90, 1e-3 }, + 110.57427582169922, + 110.57427582169922, + 110.57427582169922, + 110.57427792305019, + 110.57427792305019, + 110.57302444153535, + 110.57302444153535, + 111.19507973475258 + } , { + { 0.5, 0 },{ 175.5, 0 },{ 90, 1e-8 }, + 0.0011057427582158647, + 0.0011057427582158647, + 0.0011057427582158647, + 0.0011057427792293744, + 0.0011057427792293744, + 0.0011057302444142166, + 0.0011057302444142166, + 0.0011119503057618657 + } , { + // mysql Bug #29545865 + { -16.42203, -7.52882 },{ 4.89998, -6.15568 },{ 3.32696, -6.29345 }, + 481.73908764883043, + 481.73908764883043, + 481.73908764873721, + 481.74578258317035, + 481.74576160418479, + 480.34603374821353, + 480.34602624448405, + 508.0731159303939 + } , { // same segment but the point is from the other side + { -16.42203, -7.52882 },{ 4.89998, -6.15568 },{ 3.3262, -6.28451}, + 510.48273138899611, + 510.48273138899611, + 510.48273138908797, + 510.47605556026537, + 510.47605888246693, + 511.86547773473234, + 511.86548088955459, + 489.55321195417821 + } , { + { -16.42203, -7.52882 },{ 4.89998, -6.1556 },{ 3.32696, -6.2889 }, + 11.511229576046485, + 11.511229576046485, + 11.51122957617916, + 11.50474785537202, + 11.504394870933424, + 12.898977232559222, + 12.898968261046516, + 12.130727461169611 + } , { + { -16.42203, -7.52882 },{ 4.89998, -6.1556 },{ 3.32696, -6.28895 }, + 6.0009073659133909, + 6.0009073659133909, + 6.0009073659387502, + 5.9949823734311893, + 5.9941706378723278, + 7.3883629173067344, + 7.3889362323779535, + 17.671122161310702 + } , { + // mysql Bug #29545865 + //{ 8.65279, -2.71668 }, + { -7.13372, 8.35583 },{ -9.09998, -1.22625 },{ -7.35561, 7.2137 }, + 1671.2894143458557, + 1671.2894143458557, + 1671.2894143458786, + 1671.2962894596874, + 1671.296284713379, + 1677.2323385335374, + 1677.232338307874, + 1668.697566121507 + } +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + , { + { 0, 10 }, { 20, 10 }, { 18.00000000000003908, 10.054676080707787733 }, + 0.0011398027228318023, + 0.0011398027228318023, + 0.0060057460922939617, + 0, + 0, + 0, + 0.30055333992381872, + 39.88666722147299 + } , { + { 0, 10 }, { 20, 10 }, { 18, 10.054678231628329854 }, + 0.23669789852514209, + 0.23669789852514209, + 0.23669789883426567, + 0.25069019912476698, + 0.23204712322540744, + 0.26712030782599411, + 0.40206187237490559, + 40.125767043637062 + } , { + { 0, 10 }, { 20, 10 },{ 17.999999999999950262, 10.054676091041047314 }, + 2.7930744094407741e-06, + 2.7930744094407741e-06, + 0.0058967770186943418, + 0, + 0, + 0, + 0.30055160527904862, + 39.887815883329125 + } +#endif + , // large distance to segment + { + { 0.5, 0 }, { 175.5, 0 }, { 90, 90 }, + 10001965.729311479, + 10001965.729311479, + 10001965.729311479, + 10001965.729311479, + 10001965.729311479, + 10001958.678477952, + 10001958.678477952, + 10007557.108987356 + } , { + { 0.5, -89 }, { 175.5, -89 }, { 90, 90 }, + 19892237.59370932, + 19892237.59370932, + 19892237.59370932, + 19892237.570068691, + 19892237.570068691, + 19892224.746673118, + 19892224.746673118, + 19903919.272499084 + } , //acos issue solved + { + { 90, 0 }, { 0, 1.000005 }, {0, 90}, + 9891389.2448064201, + 9891389.2448064201, + 9891389.2448064163, + 9891370.4775929395, + 9891370.4775932431, + 9891383.4444574378, + 9891383.4444574378, + 9896361.5404068138 + } +}; + +size_t const expected_size = sizeof(expected) / sizeof(expected_results); + +#endif // BOOST_GEOMETRY_TEST_DISTANCE_CROSS_TRACK_CASES_HPP diff --git a/src/boost/libs/geometry/test/strategies/distance_default_result.cpp b/src/boost/libs/geometry/test/strategies/distance_default_result.cpp new file mode 100644 index 00000000..e862d331 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/distance_default_result.cpp @@ -0,0 +1,270 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_default_result +#endif + +#include <cstddef> +#include <iostream> + +#include <boost/test/included/unit_test.hpp> + +#include <boost/mpl/assert.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/util/calculation_type.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/segment.hpp> +#include <boost/geometry/geometries/box.hpp> + +#include <boost/geometry/strategies/strategies.hpp> +#include <boost/geometry/strategies/default_distance_result.hpp> +#include <boost/geometry/strategies/default_comparable_distance_result.hpp> + +#if defined(HAVE_TTMATH) +#include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + +namespace bg = ::boost::geometry; + + +template <typename DefaultResult, typename ExpectedResult> +struct assert_equal_types +{ + assert_equal_types() + { + static const bool are_same = + boost::is_same<DefaultResult, ExpectedResult>::type::value; + + BOOST_MPL_ASSERT_MSG((are_same), + WRONG_DEFAULT_DISTANCE_RESULT, + (types<DefaultResult, ExpectedResult>)); + } +}; + +//========================================================================= + +template +< + typename Geometry1, + typename Geometry2, + typename ExpectedResult, + typename ExpectedComparableResult +> +inline void test_distance_result() +{ + typedef typename bg::default_distance_result + < + Geometry1, Geometry2 + >::type result12; + + typedef typename bg::default_distance_result + < + Geometry2, Geometry1 + >::type result21; + + typedef typename bg::default_comparable_distance_result + < + Geometry1, Geometry2 + >::type comparable_result12; + + typedef typename bg::default_comparable_distance_result + < + Geometry2, Geometry1 + >::type comparable_result21; + + assert_equal_types<result12, ExpectedResult>(); + assert_equal_types<result21, ExpectedResult>(); + assert_equal_types<comparable_result12, ExpectedComparableResult>(); + assert_equal_types<comparable_result21, ExpectedComparableResult>(); +} + +//========================================================================= + +template +< + typename CoordinateType1, + typename CoordinateType2, + std::size_t Dimension, + typename CoordinateSystem, + typename ExpectedResult, + typename ExpectedComparableResult = ExpectedResult +> +struct test_distance_result_segment +{ + test_distance_result_segment() + { + typedef typename bg::model::point + < + CoordinateType1, Dimension, CoordinateSystem + > point1; + + typedef typename bg::model::point + < + CoordinateType2, Dimension, CoordinateSystem + > point2; + + typedef typename bg::model::segment<point1> segment1; + typedef typename bg::model::segment<point2> segment2; + + test_distance_result + < + point1, point2, ExpectedResult, ExpectedComparableResult + >(); + + test_distance_result + < + point1, segment2, ExpectedResult, ExpectedComparableResult + >(); + + test_distance_result + < + point2, segment1, ExpectedResult, ExpectedComparableResult + >(); + } +}; + +//========================================================================= + +template +< + typename CoordinateType1, + typename CoordinateType2, + std::size_t Dimension, + typename ExpectedResult, + typename ExpectedComparableResult = ExpectedResult +> +struct test_distance_result_box +{ + test_distance_result_box() + { + typedef typename bg::model::point + < + CoordinateType1, Dimension, bg::cs::cartesian + > point1; + + typedef typename bg::model::point + < + CoordinateType2, Dimension, bg::cs::cartesian + > point2; + + typedef typename bg::model::box<point1> box1; + typedef typename bg::model::box<point2> box2; + + test_distance_result + < + point1, box2, ExpectedResult, ExpectedComparableResult + >(); + + test_distance_result + < + point2, box1, ExpectedResult, ExpectedComparableResult + >(); + + test_distance_result + < + box1, box2, ExpectedResult, ExpectedComparableResult + >(); + } +}; + +//========================================================================= + +template <std::size_t D, typename CoordinateSystem> +inline void test_segment_all() +{ +#if defined(HAVE_TTMATH) + typedef ttmath_big tt; + typedef bg::util::detail::default_integral::type default_integral; +#endif + typedef typename boost::mpl::if_ + < + typename boost::is_same<CoordinateSystem, bg::cs::cartesian>::type, + double, + float + >::type float_return_type; + + 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, CoordinateSystem, float_return_type>(); + test_distance_result_segment<float, float, D, CoordinateSystem, float_return_type>(); + + 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, CoordinateSystem, tt>(); + test_distance_result_segment<tt, default_integral, D, CoordinateSystem, 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 +} + +//========================================================================= + +template <std::size_t D> +inline void test_box_all() +{ +#if defined(HAVE_TTMATH) + typedef ttmath_big tt; +#endif + typedef bg::util::detail::default_integral::type default_integral; + + test_distance_result_box<short, short, D, double, default_integral>(); + test_distance_result_box<int, int, D, double, default_integral>(); + test_distance_result_box<int, long, D, double, default_integral>(); + test_distance_result_box<long, long, D, double, default_integral>(); + + test_distance_result_box<int, float, D, double>(); + test_distance_result_box<float, float, D, double>(); + + test_distance_result_box<int, double, D, double>(); + test_distance_result_box<double, int, D, double>(); + test_distance_result_box<float, double, D, double>(); + test_distance_result_box<double, float, D, double>(); + test_distance_result_box<double, double, D, double>(); + +#if defined(HAVE_TTMATH) + test_distance_result_box<tt, int, D, tt>(); + test_distance_result_box<tt, default_integral, D, tt>(); + + test_distance_result_box<tt, float, D, tt>(); + test_distance_result_box<tt, double, D, tt>(); + test_distance_result_box<tt, tt, D, tt>(); +#endif +} + +//========================================================================= + +BOOST_AUTO_TEST_CASE( test_point_point_or_point_segment ) +{ + test_segment_all<2, bg::cs::cartesian>(); + test_segment_all<3, bg::cs::cartesian>(); + test_segment_all<4, bg::cs::cartesian>(); + test_segment_all<2, bg::cs::spherical_equatorial<bg::degree> >(); +} + +BOOST_AUTO_TEST_CASE( test_point_box_or_box ) +{ + test_box_all<2>(); + test_box_all<3>(); + test_box_all<4>(); +} diff --git a/src/boost/libs/geometry/test/strategies/douglas_peucker.cpp b/src/boost/libs/geometry/test/strategies/douglas_peucker.cpp new file mode 100644 index 00000000..7f9e77f2 --- /dev/null +++ b/src/boost/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/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> + +#include <boost/assign/list_of.hpp> +#include <boost/core/ignore_unused.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/tuple/tuple.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/src/boost/libs/geometry/test/strategies/envelope_segment.cpp b/src/boost/libs/geometry/test/strategies/envelope_segment.cpp new file mode 100644 index 00000000..09610e3c --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/envelope_segment.cpp @@ -0,0 +1,134 @@ +// Boost.Geometry + +// Copyright (c) 2016-2018 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, 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 +// http://www.boost.org/LICENSE_1_0.txt) + +#include <geometry_test_common.hpp> +#include <boost/geometry/io/wkt/wkt.hpp> +#include <boost/geometry/geometries/box.hpp> +#include <boost/geometry/strategies/geographic/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> + +template +< + typename FormulaPolicy, + typename P, + typename CT +> +void test_strategies_lat(P p1, P p2, CT expected_max, CT expected_min, + CT expected_max_sph, CT expected_min_sph, CT error = 0.0001) +{ + bg::model::box<P> box; + + bg::strategy::envelope::geographic_segment + < + FormulaPolicy, + bg::srs::spheroid<CT>, + CT + > strategy_geo; + + strategy_geo.apply(p1, p2, box); + + CT p_min_degree_geo = bg::get<0, 1>(box); + CT p_max_degree_geo = bg::get<1, 1>(box); + + BOOST_CHECK_CLOSE(p_max_degree_geo, expected_max, error); + BOOST_CHECK_CLOSE(p_min_degree_geo, expected_min, error); + + typedef bg::strategy::envelope::spherical_segment<CT> strategy_sph_t; + + strategy_sph_t::apply(p1, p2, box); + + CT p_min_degree_sph = bg::get<0, 1>(box); + CT p_max_degree_sph = bg::get<1, 1>(box); + + BOOST_CHECK_CLOSE(p_max_degree_sph, expected_max_sph, error); + BOOST_CHECK_CLOSE(p_min_degree_sph, expected_min_sph, error); +} + + +template <typename CT> +void test_all() +{ + typedef bg::model::point<CT, 2, bg::cs::geographic<bg::degree> > Pg; + + // Short segments + test_strategies_lat<bg::strategy::thomas> + (Pg(1, 1), Pg(10, 5), 5.0, 1.0, 5.0, 1.0); + + test_strategies_lat<bg::strategy::thomas> + (Pg(1, 1), Pg(10, 1), 1.0031124506594733, 1.0, 1.0030915676477881, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(-5, 1), Pg(4, 1), 1.0031124506594733, 1.0, 1.0030915676477881, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(175, 1), Pg(184, 1), 1.0031124506594733, 1.0, 1.0030915676477881, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(355, 1), Pg(4, 1), 1.0031124506594733, 1.0, 1.0030915676477881, 1.0); + + // Reverse direction + test_strategies_lat<bg::strategy::thomas> + (Pg(1, 2), Pg(70, 1), 2.0239716998355468, 1.0, 2.0228167431951536, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(70, 1), Pg(1, 2), 2.0239716998351849, 1.0, 2.022816743195063, 1.0); + + // Long segments + test_strategies_lat<bg::strategy::thomas> + (Pg(0, 1), Pg(170, 1), 11.975026023950877, 1.0, 11.325049479775814, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(0, 1), Pg(179, 1), 68.452669316418039, 1.0, 63.437566893227093, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(0, 1), Pg(179.5, 1), 78.84050225214871, 1.0, 75.96516822754981, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(0, 1), Pg(180.5, 1), 78.84050225214871, 1.0, 75.965168227550194, 1.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(0, 1), Pg(180, 1), 90.0, 1.0, 90.0, 1.0); + + // South hemisphere + test_strategies_lat<bg::strategy::thomas> + (Pg(1, -1), Pg(10, -5), -1.0, -5.0, -1.0, -5.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(1, -1), Pg(10, -1), -1.0, -1.0031124506594733, -1.0, -1.0030915676477881); + test_strategies_lat<bg::strategy::thomas> + (Pg(1, -1), Pg(170, -1), -1.0, -10.85834257048573, -1.0, -10.321374780571153); + + // Different strategies for inverse + test_strategies_lat<bg::strategy::thomas> + (Pg(1, 1), Pg(10, 1), 1.0031124506594733, 1.0, + 1.0030915676477881, 1.0, 0.00000001); + test_strategies_lat<bg::strategy::andoyer> + (Pg(1, 1), Pg(10, 1), 1.0031124504591062, 1.0, + 1.0030915676477881, 1.0, 0.00000001); + test_strategies_lat<bg::strategy::vincenty> + (Pg(1, 1), Pg(10, 1), 1.0031124508942098, 1.0, + 1.0030915676477881, 1.0, 0.00000001); + + // Meridian and equator + test_strategies_lat<bg::strategy::thomas> + (Pg(1, 10), Pg(1, -10), 10.0, -10.0, 10.0, -10.0); + test_strategies_lat<bg::strategy::thomas> + (Pg(1, 0), Pg(10, 0), 0.0, 0.0, 0.0, 0.0); + + // One endpoint in northern hemisphere and the other in southern hemisphere + test_strategies_lat<bg::strategy::thomas> + (Pg(1, 1), Pg(150, -5), 1.0, -8.1825389632359933, 1.0, -8.0761230625567588); + test_strategies_lat<bg::strategy::thomas> + (Pg(150, -5), Pg(1, 1), 1.0, -8.1825389632359933, 1.0, -8.0761230625568015); + test_strategies_lat<bg::strategy::thomas> + (Pg(150, 5), Pg(1, -1), 8.1825389632359933, -1.0, 8.0761230625568015, -1.0); +} + + + +int test_main( int , char* [] ) +{ + test_all<double>(); + + return 0; +} + diff --git a/src/boost/libs/geometry/test/strategies/franklin.cpp b/src/boost/libs/geometry/test/strategies/franklin.cpp new file mode 100644 index 00000000..6a6c5fe1 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/franklin.cpp @@ -0,0 +1,86 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2010-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) + + +#include <strategies/test_within.hpp> + + +template <typename Point> +void test_all() +{ + typedef bg::model::polygon<Point> polygon; + + std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))"; + std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))"; + std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))"; + + bg::strategy::within::franklin<Point> s; + + test_geometry<Point, polygon>("b1", "POINT(1 1)", box, s, true); + test_geometry<Point, polygon>("b2", "POINT(3 3)", box, s, false); + + // Test ALL corners (officialy false but some strategies might answer true) + test_geometry<Point, polygon>("b3a", "POINT(0 0)", box, s, true); // different + test_geometry<Point, polygon>("b3b", "POINT(0 2)", box, s, false); + test_geometry<Point, polygon>("b3c", "POINT(2 2)", box, s, false); + test_geometry<Point, polygon>("b3d", "POINT(2 0)", box, s, false); + + // Test ALL sides (officialy false but some strategies might answer true) + test_geometry<Point, polygon>("b4a", "POINT(0 1)", box, s, true); // different + test_geometry<Point, polygon>("b4b", "POINT(1 2)", box, s, false); + test_geometry<Point, polygon>("b4c", "POINT(2 1)", box, s, false); + test_geometry<Point, polygon>("b4d", "POINT(1 0)", box, s, true); // different + + + test_geometry<Point, polygon>("t1", "POINT(1 1)", triangle, s, true); + test_geometry<Point, polygon>("t2", "POINT(3 3)", triangle, s, false); + + test_geometry<Point, polygon>("t3a", "POINT(0 0)", triangle, s, true); // diff + test_geometry<Point, polygon>("t3b", "POINT(0 4)", triangle, s, false); + test_geometry<Point, polygon>("t3c", "POINT(5 0)", triangle, s, true); // diff + + test_geometry<Point, polygon>("t4a", "POINT(0 2)", triangle, s, true); // diff + test_geometry<Point, polygon>("t4b", "POINT(3 2)", triangle, s, false); + test_geometry<Point, polygon>("t4c", "POINT(2 0)", triangle, s, true); // diff + + + test_geometry<Point, polygon>("h1", "POINT(0.5 0.5)", with_hole, s, true); + test_geometry<Point, polygon>("h2a", "POINT(1.5 1.5)", with_hole, s, false); + test_geometry<Point, polygon>("h2b", "POINT(5 5)", with_hole, s, false); + + test_geometry<Point, polygon>("h3a", "POINT(1 1)", with_hole, s, false); + test_geometry<Point, polygon>("h3b", "POINT(2 2)", with_hole, s, true); // diff + test_geometry<Point, polygon>("h3c", "POINT(0 0)", with_hole, s, true); // diff + + test_geometry<Point, polygon>("h4a", "POINT(1 1.5)", with_hole, s, false); + test_geometry<Point, polygon>("h4b", "POINT(1.5 2)", with_hole, s, true); // diff + + // Lying ON (one of the sides of) interior ring + test_geometry<Point, polygon>("#77-1", "POINT(6 3.5)", + "POLYGON((5 3,5 4,4 4,4 5,3 5,3 6,5 6,5 5,7 5,7 6,8 6,8 5,9 5,9 2,8 2,8 1,7 1,7 2,5 2,5 3),(6 3,8 3,8 4,6 4,6 3))", + s, false); +} + + +int test_main(int, char* []) +{ + test_all<bg::model::point<float, 2, bg::cs::cartesian> >(); + test_all<bg::model::point<double, 2, bg::cs::cartesian> >(); + +#if defined(HAVE_TTMATH) + test_all<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >(); +#endif + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/haversine.cpp b/src/boost/libs/geometry/test/strategies/haversine.cpp new file mode 100644 index 00000000..b6853954 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/haversine.cpp @@ -0,0 +1,266 @@ +// 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. + +// 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/requires.hpp> +#include <boost/concept_check.hpp> +#include <boost/core/ignore_unused.hpp> + +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/strategies/spherical/distance_haversine.hpp> +#include <boost/geometry/strategies/concepts/distance_concept.hpp> + + +#include <boost/geometry/geometries/point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + + + +double const average_earth_radius = 6372795.0; + + +template <typename Point, typename LatitudePolicy> +struct test_distance +{ + typedef bg::strategy::distance::haversine<double> haversine_type; + typedef typename bg::strategy::distance::services::return_type<haversine_type, Point, Point>::type return_type; + + BOOST_CONCEPT_ASSERT + ( + (bg::concepts::PointDistanceStrategy<haversine_type, Point, Point>) + ); + + + static void test(double lon1, double lat1, double lon2, double lat2, + double radius, double expected, double tolerance) + { + haversine_type strategy(radius); + + Point p1, p2; + bg::assign_values(p1, lon1, LatitudePolicy::apply(lat1)); + bg::assign_values(p2, lon2, LatitudePolicy::apply(lat2)); + return_type d = strategy.apply(p1, p2); + + BOOST_CHECK_CLOSE(d, expected, tolerance); + } +}; + +template <typename Point, typename LatitudePolicy> +void test_all() +{ + // earth to unit-sphere -> divide by earth circumference, then it is from 0-1, + // then multiply with 2 PI, so effectively just divide by earth radius + double e2u = 1.0 / average_earth_radius; + + // ~ Amsterdam/Paris, 467 kilometers + double const a_p = 467.2704 * 1000.0; + test_distance<Point, LatitudePolicy>::test(4, 52, 2, 48, average_earth_radius, a_p, 1.0); + test_distance<Point, LatitudePolicy>::test(2, 48, 4, 52, average_earth_radius, a_p, 1.0); + test_distance<Point, LatitudePolicy>::test(4, 52, 2, 48, 1.0, a_p * e2u, 0.001); + + // ~ Amsterdam/Barcelona + double const a_b = 1232.9065 * 1000.0; + test_distance<Point, LatitudePolicy>::test(4, 52, 2, 41, average_earth_radius, a_b, 1.0); + test_distance<Point, LatitudePolicy>::test(2, 41, 4, 52, average_earth_radius, a_b, 1.0); + test_distance<Point, LatitudePolicy>::test(4, 52, 2, 41, 1.0, a_b * e2u, 0.001); +} + + +template <typename P1, typename P2, typename CalculationType, typename LatitudePolicy> +void test_services() +{ + namespace bgsd = bg::strategy::distance; + namespace services = bg::strategy::distance::services; + + { + + // Compile-check if there is a strategy for this type + typedef typename services::default_strategy + < + bg::point_tag, bg::point_tag, P1, P2 + >::type haversine_strategy_type; + + boost::ignore_unused<haversine_strategy_type>(); + } + + P1 p1; + bg::assign_values(p1, 4, 52); + + P2 p2; + bg::assign_values(p2, 2, 48); + + // ~ Amsterdam/Paris, 467 kilometers + double const km = 1000.0; + double const a_p = 467.2704 * km; + double const expected = a_p; + + double const expected_lower = 460.0 * km; + double const expected_higher = 470.0 * km; + + // 1: normal, calculate distance: + + typedef bgsd::haversine<double, CalculationType> strategy_type; + typedef typename bgsd::services::return_type<strategy_type, P1, P2>::type return_type; + + strategy_type strategy(average_earth_radius); + return_type result = strategy.apply(p1, p2); + BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + // 2: the strategy should return the same result if we reverse parameters + result = strategy.apply(p2, p1); + BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + + // 3: "comparable" to construct a "comparable strategy" for P1/P2 + // a "comparable strategy" is a strategy which does not calculate the exact distance, but + // which returns results which can be mutually compared (e.g. avoid sqrt) + + // 3a: "comparable_type" + typedef typename services::comparable_type<strategy_type>::type comparable_type; + + // 3b: "get_comparable" + comparable_type comparable = bgsd::services::get_comparable<strategy_type>::apply(strategy); + + // Check vice versa: + // First the result of the comparable strategy + return_type c_result = comparable.apply(p1, p2); + // Second the comparable result of the expected distance + return_type c_expected = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, expected); + // And that one should be equa. + BOOST_CHECK_CLOSE(c_result, return_type(c_expected), 0.001); + + // 4: the comparable_type should have a distance_strategy_constructor as well, + // knowing how to compare something with a fixed distance + return_type c_dist_lower = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, expected_lower); + return_type c_dist_higher = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, expected_higher); + + // If this is the case: + BOOST_CHECK(c_dist_lower < c_result && c_result < c_dist_higher); + + // Calculate the Haversine by hand here: + return_type c_check = return_type(2.0) * asin(sqrt(c_result)) * average_earth_radius; + BOOST_CHECK_CLOSE(c_check, expected, 0.001); + + // This should also be the case + return_type dist_lower = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, expected_lower); + return_type dist_higher = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, expected_higher); + BOOST_CHECK(dist_lower < result && result < dist_higher); +} + +/**** +template <typename P, typename Strategy> +void time_compare_s(int const n) +{ + boost::timer t; + P p1, p2; + bg::assign_values(p1, 1, 1); + bg::assign_values(p2, 2, 2); + Strategy strategy; + typename Strategy::return_type s = 0; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + s += strategy.apply(p1, p2); + } + } + std::cout << "s: " << s << " t: " << t.elapsed() << std::endl; +} + +template <typename P> +void time_compare(int const n) +{ + time_compare_s<P, bg::strategy::distance::haversine<double> >(n); + time_compare_s<P, bg::strategy::distance::comparable::haversine<double> >(n); +} + +#include <time.h> +double time_sqrt(int n) +{ + clock_t start = clock(); + + double v = 2.0; + double s = 0.0; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + s += sqrt(v); + v += 1.0e-10; + } + } + clock_t end = clock(); + double diff = double(end - start) / CLOCKS_PER_SEC; + + std::cout << "Check: " << s << " Time: " << diff << std::endl; + return diff; +} + +double time_normal(int n) +{ + clock_t start = clock(); + + double v = 2.0; + double s = 0.0; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + s += v; + v += 1.0e-10; + } + } + clock_t end = clock(); + double diff = double(end - start) / CLOCKS_PER_SEC; + + std::cout << "Check: " << s << " Time: " << diff << std::endl; + return diff; +} +***/ + +int test_main(int, char* []) +{ + test_all<bg::model::point<int, 2, bg::cs::spherical_equatorial<bg::degree> >, geographic_policy>(); + test_all<bg::model::point<float, 2, bg::cs::spherical_equatorial<bg::degree> >, geographic_policy>(); + test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> >, geographic_policy>(); + + // NYI: haversine for mathematical spherical coordinate systems + // test_all<bg::model::point<double, 2, bg::cs::spherical<bg::degree> >, mathematical_policy>(); + + //double t1 = time_sqrt(20000); + //double t2 = time_normal(20000); + //std::cout << "Factor: " << (t1 / t2) << std::endl; + //time_compare<bg::model::point<double, 2, bg::cs::spherical<bg::radian> > >(10000); + +#if defined(HAVE_TTMATH) + typedef ttmath::Big<1,4> tt; + test_all<bg::model::point<tt, 2, bg::cs::spherical_equatorial<bg::degree> >, geographic_policy>(); +#endif + + + test_services + < + bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> >, + bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> >, + double, + geographic_policy + >(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/matrix_transformer.cpp b/src/boost/libs/geometry/test/strategies/matrix_transformer.cpp new file mode 100644 index 00000000..b617b5c2 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/matrix_transformer.cpp @@ -0,0 +1,103 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2019 Tinko Bartels + +// 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/geometry/strategies/transform/matrix_transformers.hpp> +#include <boost/geometry/algorithms/transform.hpp> +#include <boost/geometry/geometries/point.hpp> + +template <typename coordinate_type> +void test_all() +{ + typedef bg::model::point<coordinate_type, 2, bg::cs::cartesian> point_2d; + typedef bg::model::point<coordinate_type, 3, bg::cs::cartesian> point_3d; + typedef bg::model::point<coordinate_type, 4, bg::cs::cartesian> point_4d; + + point_2d p2d; + point_3d p3d; + point_4d p4d; + + bg::assign_values(p2d, 3, 5); + + boost::qvm::mat<coordinate_type, 5, 3> mat24; + boost::qvm::A<0, 0>(mat24) = 1; boost::qvm::A<0, 1>(mat24) = 0; boost::qvm::A<0, 2>(mat24) = 0; + boost::qvm::A<1, 0>(mat24) = 0; boost::qvm::A<1, 1>(mat24) = 1; boost::qvm::A<1, 2>(mat24) = 0; + boost::qvm::A<2, 0>(mat24) = 1; boost::qvm::A<2, 1>(mat24) = -1; boost::qvm::A<2, 2>(mat24) = 0; + boost::qvm::A<3, 0>(mat24) = -1; boost::qvm::A<3, 1>(mat24) = 1; boost::qvm::A<3, 2>(mat24) = 0; + boost::qvm::A<4, 0>(mat24) = 0; boost::qvm::A<4, 1>(mat24) = 0; boost::qvm::A<4, 2>(mat24) = 1; + bg::strategy::transform::matrix_transformer<coordinate_type, 2, 4> trans24(mat24); + bg::transform(p2d, p4d, trans24); + + BOOST_CHECK_CLOSE(double(bg::get<0>(p4d)), 3.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(p4d)), 5.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<2>(p4d)), -2.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<3>(p4d)), 2.0, 0.001); + + bg::strategy::transform::scale_transformer<coordinate_type, 4, 4> scale44(2); + bg::transform(p4d, p4d, scale44); + + BOOST_CHECK_CLOSE(double(bg::get<0>(p4d)), 6.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(p4d)), 10.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<2>(p4d)), -4.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<3>(p4d)), 4.0, 0.001); + + boost::qvm::mat<coordinate_type, 4, 5> mat43; + boost::qvm::A<0, 0>(mat43) = 0 ; boost::qvm::A<0, 1>(mat43) = 0; boost::qvm::A<0, 2>(mat43) = 0.5; boost::qvm::A<0, 3>(mat43) = 0 ; boost::qvm::A<0, 4>(mat43) = 0; + boost::qvm::A<1, 0>(mat43) = 0.5; boost::qvm::A<1, 1>(mat43) = 0; boost::qvm::A<1, 2>(mat43) = 0 ; boost::qvm::A<1, 3>(mat43) = 0 ; boost::qvm::A<1, 4>(mat43) = 0; + boost::qvm::A<2, 0>(mat43) = 0 ; boost::qvm::A<2, 1>(mat43) = 0; boost::qvm::A<2, 2>(mat43) = 0 ; boost::qvm::A<2, 3>(mat43) = 0.5; boost::qvm::A<2, 4>(mat43) = 0; + boost::qvm::A<3, 0>(mat43) = 0 ; boost::qvm::A<3, 1>(mat43) = 0; boost::qvm::A<3, 2>(mat43) = 0 ; boost::qvm::A<3, 3>(mat43) = 0 ; boost::qvm::A<3, 4>(mat43) = 1; + bg::strategy::transform::matrix_transformer<coordinate_type, 4, 3> trans43(mat43); + bg::transform(p4d, p3d, trans43); + + BOOST_CHECK_CLOSE(double(bg::get<0>(p3d)), -2.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(p3d)), 3.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<2>(p3d)), 2.0, 0.001); + + bg::strategy::transform::matrix_transformer<coordinate_type, 3, 3> trans33(1, 0, 0, 0, + 0, 0, 1, 0, + 0, 1, 0, 0, + 0, 0, 0, 1); + bg::transform(p3d, p3d, trans33); + + BOOST_CHECK_CLOSE(double(bg::get<0>(p3d)), -2.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(p3d)), 2.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<2>(p3d)), 3.0, 0.001); + + boost::qvm::mat<coordinate_type, 3, 4> mat32; + boost::qvm::A<0, 0>(mat32) = 1; boost::qvm::A<0, 1>(mat32) = 1; boost::qvm::A<0, 2>(mat32) = 1; boost::qvm::A<0, 3>(mat32) = 0; + boost::qvm::A<1, 0>(mat32) = -1; boost::qvm::A<1, 1>(mat32) = 0; boost::qvm::A<1, 2>(mat32) = 1; boost::qvm::A<1, 3>(mat32) = 0; + boost::qvm::A<2, 0>(mat32) = 0; boost::qvm::A<2, 1>(mat32) = 0; boost::qvm::A<2, 2>(mat32) = 0; boost::qvm::A<2, 3>(mat32) = 1; + + bg::strategy::transform::matrix_transformer<coordinate_type, 3, 2> trans32(mat32); + bg::transform(p3d, p2d, trans32); + + BOOST_CHECK_CLOSE(double(bg::get<0>(p2d)), 3.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(p2d)), 5.0, 0.001); + + bg::strategy::transform::matrix_transformer<coordinate_type, 2, 2> + trans_composed( + trans32.matrix() * trans33.matrix() * trans43.matrix() * scale44.matrix() * trans24.matrix()); + bg::transform(p2d, p2d, trans_composed); + + BOOST_CHECK_CLOSE(double(bg::get<0>(p2d)), 3.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(p2d)), 5.0, 0.001); +} + +int test_main(int, char* []) +{ + test_all<float>(); + test_all<double>(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/point_in_box.cpp b/src/boost/libs/geometry/test/strategies/point_in_box.cpp new file mode 100644 index 00000000..50d5f65a --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/point_in_box.cpp @@ -0,0 +1,81 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2010-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) + + +#include <strategies/test_within.hpp> + + +template <typename Point> +void test_box_of(std::string const& wkt_point, std::string const& wkt_box, + bool expected_within, bool expected_covered_by) +{ + typedef bg::model::box<Point> box_type; + + Point point; + box_type box; + bg::read_wkt(wkt_point, point); + bg::read_wkt(wkt_box, box); + + bool detected_within = bg::within(point, box); + bool detected_covered_by = bg::covered_by(point, box); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + + // Also test with the non-default agnostic side version + namespace wi = bg::strategy::within; + wi::point_in_box_by_side<> within_strategy; + wi::point_in_box_by_side<wi::decide_covered_by> covered_by_strategy; + + detected_within = bg::within(point, box, within_strategy); + detected_covered_by = bg::covered_by(point, box, covered_by_strategy); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + + // We might exchange strategies between within/covered by. + // So the lines below might seem confusing, but are as intended + detected_within = bg::covered_by(point, box, within_strategy); + detected_covered_by = bg::within(point, box, covered_by_strategy); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + + // Finally we call the strategies directly + detected_within = within_strategy.apply(point, box); + detected_covered_by = covered_by_strategy.apply(point, box); + BOOST_CHECK_EQUAL(detected_within, expected_within); + BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); +} + +template <typename Point> +void test_box() +{ + test_box_of<Point>("POINT(1 1)", "BOX(0 0,2 2)", true, true); + test_box_of<Point>("POINT(0 0)", "BOX(0 0,2 2)", false, true); + test_box_of<Point>("POINT(2 2)", "BOX(0 0,2 2)", false, true); + test_box_of<Point>("POINT(0 1)", "BOX(0 0,2 2)", false, true); + test_box_of<Point>("POINT(1 0)", "BOX(0 0,2 2)", false, true); + test_box_of<Point>("POINT(3 3)", "BOX(0 0,2 2)", false, false); +} + + +int test_main(int, char* []) +{ + test_box<bg::model::point<float, 2, bg::cs::cartesian> >(); + test_box<bg::model::point<double, 2, bg::cs::cartesian> >(); + +#if defined(HAVE_TTMATH) + test_box<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >(); +#endif + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/projected_point.cpp b/src/boost/libs/geometry/test/strategies/projected_point.cpp new file mode 100644 index 00000000..c2307eb4 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/projected_point.cpp @@ -0,0 +1,75 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// 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 <strategies/test_projected_point.hpp> + + +template <typename P1, typename P2> +void test_all_2d() +{ + test_2d<P1, P2>("POINT(1 1)", "POINT(0 0)", "POINT(2 3)", 0.27735203958327); + test_2d<P1, P2>("POINT(2 2)", "POINT(1 4)", "POINT(4 1)", 0.5 * sqrt(2.0)); + test_2d<P1, P2>("POINT(6 1)", "POINT(1 4)", "POINT(4 1)", 2.0); + test_2d<P1, P2>("POINT(1 6)", "POINT(1 4)", "POINT(4 1)", 2.0); +} + +template <typename P> +void test_all_2d() +{ + //test_all_2d<P, int[2]>(); + //test_all_2d<P, float[2]>(); + //test_all_2d<P, double[2]>(); + //test_all_2d<P, test::test_point>(); + test_all_2d<P, bg::model::point<int, 2, bg::cs::cartesian> >(); + test_all_2d<P, bg::model::point<float, 2, bg::cs::cartesian> >(); + test_all_2d<P, bg::model::point<double, 2, bg::cs::cartesian> >(); + test_all_2d<P, bg::model::point<long double, 2, bg::cs::cartesian> >(); +} + +int test_main(int, char* []) +{ + test_all_2d<int[2]>(); + test_all_2d<float[2]>(); + test_all_2d<double[2]>(); + //test_all_2d<test::test_point>(); + + test_all_2d<bg::model::point<int, 2, bg::cs::cartesian> >(); + test_all_2d<bg::model::point<float, 2, bg::cs::cartesian> >(); + test_all_2d<bg::model::point<double, 2, bg::cs::cartesian> >(); + + test_services + < + bg::model::point<double, 2, bg::cs::cartesian>, + bg::model::point<float, 2, bg::cs::cartesian>, + long double + >(); + + +#if defined(HAVE_TTMATH) + test_all_2d + < + bg::model::point<ttmath_big, 2, bg::cs::cartesian>, + bg::model::point<ttmath_big, 2, bg::cs::cartesian> + >(); +#endif + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/projected_point_ax.cpp b/src/boost/libs/geometry/test/strategies/projected_point_ax.cpp new file mode 100644 index 00000000..e9bd9096 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/projected_point_ax.cpp @@ -0,0 +1,87 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// 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 <strategies/test_projected_point.hpp> + + +template <typename P1, typename P2> +void test_all_2d_ax() +{ + typedef bg::strategy::distance::detail::projected_point_ax<> strategy_type; + typedef bg::strategy::distance::detail::projected_point_ax + < + void, + bg::strategy::distance::comparable::pythagoras<> + > comparable_strategy_type; + + typedef typename strategy_type::result_type<P1, P2>::type result_type; + + strategy_type strategy; + comparable_strategy_type comparable_strategy; + boost::ignore_unused(strategy, comparable_strategy); + + test_2d<P1, P2>("POINT(1 1)", "POINT(0 0)", "POINT(2 3)", + result_type(0, 0.27735203958327), + result_type(0, 0.27735203958327 * 0.27735203958327), + strategy, comparable_strategy); + + test_2d<P1, P2>("POINT(2 2)", "POINT(1 4)", "POINT(4 1)", + result_type(0, 0.5 * sqrt(2.0)), + result_type(0, 0.5), + strategy, comparable_strategy); + + test_2d<P1, P2>("POINT(6 1)", "POINT(1 4)", "POINT(4 1)", + result_type(sqrt(2.0), sqrt(2.0)), + result_type(2.0, 2.0), + strategy, comparable_strategy); + + test_2d<P1, P2>("POINT(1 6)", "POINT(1 4)", "POINT(4 1)", + result_type(sqrt(2.0), sqrt(2.0)), + result_type(2.0, 2.0), + strategy, comparable_strategy); +} + +template <typename P> +void test_all_2d_ax() +{ + test_all_2d_ax<P, bg::model::point<int, 2, bg::cs::cartesian> >(); + test_all_2d_ax<P, bg::model::point<float, 2, bg::cs::cartesian> >(); + test_all_2d_ax<P, bg::model::point<double, 2, bg::cs::cartesian> >(); + test_all_2d_ax<P, bg::model::point<long double, 2, bg::cs::cartesian> >(); +} + +int test_main(int, char* []) +{ + test_all_2d_ax<bg::model::point<int, 2, bg::cs::cartesian> >(); + test_all_2d_ax<bg::model::point<float, 2, bg::cs::cartesian> >(); + test_all_2d_ax<bg::model::point<double, 2, bg::cs::cartesian> >(); + +#if defined(HAVE_TTMATH) + test_all_2d_ax + < + bg::model::point<ttmath_big, 2, bg::cs::cartesian>, + bg::model::point<ttmath_big, 2, bg::cs::cartesian> + >(); +#endif + + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/pythagoras.cpp b/src/boost/libs/geometry/test/strategies/pythagoras.cpp new file mode 100644 index 00000000..8bb02c03 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/pythagoras.cpp @@ -0,0 +1,363 @@ +// 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. + +// 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> + +#if defined(_MSC_VER) +# pragma warning( disable : 4101 ) +#endif + +#include <boost/timer.hpp> + +#include <boost/concept/requires.hpp> +#include <boost/concept_check.hpp> +#include <boost/core/ignore_unused.hpp> + +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp> +#include <boost/geometry/strategies/concepts/distance_concept.hpp> + + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/adapted/c_array.hpp> +#include <boost/geometry/geometries/adapted/boost_tuple.hpp> + +#include <test_common/test_point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + +BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + + +template <typename P1, typename P2> +void test_null_distance_3d() +{ + P1 p1; + bg::assign_values(p1, 1, 2, 3); + P2 p2; + bg::assign_values(p2, 1, 2, 3); + + typedef bg::strategy::distance::pythagoras<> pythagoras_type; + typedef typename bg::strategy::distance::services::return_type<pythagoras_type, P1, P2>::type return_type; + + pythagoras_type pythagoras; + return_type result = pythagoras.apply(p1, p2); + + BOOST_CHECK_EQUAL(result, return_type(0)); +} + +template <typename P1, typename P2> +void test_axis_3d() +{ + P1 p1; + bg::assign_values(p1, 0, 0, 0); + P2 p2; + bg::assign_values(p2, 1, 0, 0); + + typedef bg::strategy::distance::pythagoras<> pythagoras_type; + typedef typename bg::strategy::distance::services::return_type<pythagoras_type, P1, P2>::type return_type; + + pythagoras_type pythagoras; + + return_type result = pythagoras.apply(p1, p2); + BOOST_CHECK_EQUAL(result, return_type(1)); + + bg::assign_values(p2, 0, 1, 0); + result = pythagoras.apply(p1, p2); + BOOST_CHECK_EQUAL(result, return_type(1)); + + bg::assign_values(p2, 0, 0, 1); + result = pythagoras.apply(p1, p2); + BOOST_CHECK_CLOSE(result, return_type(1), 0.001); +} + +template <typename P1, typename P2> +void test_arbitrary_3d() +{ + P1 p1; + bg::assign_values(p1, 1, 2, 3); + P2 p2; + bg::assign_values(p2, 9, 8, 7); + + { + typedef bg::strategy::distance::pythagoras<> strategy_type; + typedef typename bg::strategy::distance::services::return_type<strategy_type, P1, P2>::type return_type; + + strategy_type strategy; + return_type result = strategy.apply(p1, p2); + BOOST_CHECK_CLOSE(result, return_type(10.77032961427), 0.001); + } + + { + // Check comparable distance + typedef bg::strategy::distance::comparable::pythagoras<> strategy_type; + typedef typename bg::strategy::distance::services::return_type<strategy_type, P1, P2>::type return_type; + + strategy_type strategy; + return_type result = strategy.apply(p1, p2); + BOOST_CHECK_EQUAL(result, return_type(116)); + } +} + +template <typename P1, typename P2, typename CalculationType> +void test_services() +{ + namespace bgsd = bg::strategy::distance; + namespace services = bg::strategy::distance::services; + + { + + // Compile-check if there is a strategy for this type + typedef typename services::default_strategy + < + bg::point_tag, bg::point_tag, P1, P2 + >::type pythagoras_strategy_type; + + boost::ignore_unused<pythagoras_strategy_type>(); + } + + + P1 p1; + bg::assign_values(p1, 1, 2, 3); + + P2 p2; + bg::assign_values(p2, 4, 5, 6); + + double const sqr_expected = 3*3 + 3*3 + 3*3; // 27 + double const expected = sqrt(sqr_expected); // sqrt(27)=5.1961524227 + + // 1: normal, calculate distance: + + typedef bgsd::pythagoras<CalculationType> strategy_type; + + BOOST_CONCEPT_ASSERT( (bg::concepts::PointDistanceStrategy<strategy_type, P1, P2>) ); + + typedef typename bgsd::services::return_type<strategy_type, P1, P2>::type return_type; + + strategy_type strategy; + return_type result = strategy.apply(p1, p2); + BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + // 2: the strategy should return the same result if we reverse parameters + result = strategy.apply(p2, p1); + BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + + // 3: "comparable" to construct a "comparable strategy" for P1/P2 + // a "comparable strategy" is a strategy which does not calculate the exact distance, but + // which returns results which can be mutually compared (e.g. avoid sqrt) + + // 3a: "comparable_type" + typedef typename services::comparable_type<strategy_type>::type comparable_type; + + // 3b: "get_comparable" + comparable_type comparable = bgsd::services::get_comparable<strategy_type>::apply(strategy); + + return_type c_result = comparable.apply(p1, p2); + BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001); + + // 4: the comparable_type should have a distance_strategy_constructor as well, + // knowing how to compare something with a fixed distance + return_type c_dist5 = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, 5.0); + return_type c_dist6 = services::result_from_distance<comparable_type, P1, P2>::apply(comparable, 6.0); + + // If this is the case: + BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6); + + // This should also be the case + return_type dist5 = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, 5.0); + return_type dist6 = services::result_from_distance<strategy_type, P1, P2>::apply(strategy, 6.0); + BOOST_CHECK(dist5 < result && result < dist6); +} + + +template <typename CoordinateType, typename CalculationType, typename AssignType> +void test_big_2d_with(AssignType const& x1, AssignType const& y1, + AssignType const& x2, AssignType const& y2) +{ + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + typedef bg::strategy::distance::pythagoras<CalculationType> pythagoras_type; + + pythagoras_type pythagoras; + typedef typename bg::strategy::distance::services::return_type<pythagoras_type, point_type, point_type>::type return_type; + + + point_type p1, p2; + bg::assign_values(p1, x1, y1); + bg::assign_values(p2, x2, y2); + return_type d = pythagoras.apply(p1, p2); + + /*** + std::cout << typeid(CalculationType).name() + << " " << std::fixed << std::setprecision(20) << d + << std::endl << std::endl; + ***/ + + + BOOST_CHECK_CLOSE(d, return_type(1076554.5485833955678294387789057), 0.001); +} + +template <typename CoordinateType, typename CalculationType> +void test_big_2d() +{ + test_big_2d_with<CoordinateType, CalculationType> + (123456.78900001, 234567.89100001, + 987654.32100001, 876543.21900001); +} + +template <typename CoordinateType, typename CalculationType> +void test_big_2d_string() +{ + test_big_2d_with<CoordinateType, CalculationType> + ("123456.78900001", "234567.89100001", + "987654.32100001", "876543.21900001"); +} + +template <typename CoordinateType> +void test_integer(bool check_types) +{ + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + + point_type p1, p2; + bg::assign_values(p1, 12345678, 23456789); + bg::assign_values(p2, 98765432, 87654321); + + typedef bg::strategy::distance::pythagoras<> pythagoras_type; + 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; + cdistance_type cdistance = comparable.apply(p1, p2); + BOOST_CHECK_EQUAL(cdistance, 11589696996311540.0); + + distance_type distance2 = sqrt(distance_type(cdistance)); + BOOST_CHECK_CLOSE(distance, distance2, 0.001); + + if (check_types) + { + BOOST_CHECK((boost::is_same<distance_type, double>::type::value)); + // comparable_distance results in now double too, obviously because + // comp.distance point-segment can be fraction, even for integer input + BOOST_CHECK((boost::is_same<cdistance_type, double>::type::value)); + } +} + + +template <typename P1, typename P2> +void test_all_3d() +{ + test_null_distance_3d<P1, P2>(); + test_axis_3d<P1, P2>(); + test_arbitrary_3d<P1, P2>(); +} + +template <typename P> +void test_all_3d() +{ + test_all_3d<P, int[3]>(); + test_all_3d<P, float[3]>(); + test_all_3d<P, double[3]>(); + test_all_3d<P, test::test_point>(); + test_all_3d<P, bg::model::point<int, 3, bg::cs::cartesian> >(); + test_all_3d<P, bg::model::point<float, 3, bg::cs::cartesian> >(); + test_all_3d<P, bg::model::point<double, 3, bg::cs::cartesian> >(); +} + +template <typename P, typename Strategy> +void time_compare_s(int const n) +{ + boost::timer t; + P p1, p2; + bg::assign_values(p1, 1, 1); + bg::assign_values(p2, 2, 2); + Strategy strategy; + typename bg::strategy::distance::services::return_type<Strategy, P, P>::type s = 0; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + bg::set<0>(p2, bg::get<0>(p2) + 0.001); + s += strategy.apply(p1, p2); + } + } + std::cout << "s: " << s << " t: " << t.elapsed() << std::endl; +} + +template <typename P> +void time_compare(int const n) +{ + time_compare_s<P, bg::strategy::distance::pythagoras<> >(n); + time_compare_s<P, bg::strategy::distance::comparable::pythagoras<> >(n); +} + +int test_main(int, char* []) +{ + test_integer<int>(true); + test_integer<boost::long_long_type>(true); + test_integer<double>(false); + + test_all_3d<int[3]>(); + test_all_3d<float[3]>(); + test_all_3d<double[3]>(); + + test_all_3d<test::test_point>(); + + test_all_3d<bg::model::point<int, 3, bg::cs::cartesian> >(); + test_all_3d<bg::model::point<float, 3, bg::cs::cartesian> >(); + test_all_3d<bg::model::point<double, 3, bg::cs::cartesian> >(); + + test_big_2d<float, float>(); + test_big_2d<double, double>(); + test_big_2d<long double, long double>(); + test_big_2d<float, long double>(); + + test_services<bg::model::point<float, 3, bg::cs::cartesian>, double[3], long double>(); + test_services<double[3], test::test_point, float>(); + + + // TODO move this to another non-unit test + // time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000); + +#if defined(HAVE_TTMATH) + + typedef ttmath::Big<1,4> tt; + typedef bg::model::point<tt, 3, bg::cs::cartesian> tt_point; + + //test_all_3d<tt[3]>(); + test_all_3d<tt_point>(); + test_all_3d<tt_point, tt_point>(); + test_big_2d<tt, tt>(); + test_big_2d_string<tt, tt>(); +#endif + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/pythagoras_point_box.cpp b/src/boost/libs/geometry/test/strategies/pythagoras_point_box.cpp new file mode 100644 index 00000000..4121ce02 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/pythagoras_point_box.cpp @@ -0,0 +1,505 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// 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_TEST_MODULE +#define BOOST_TEST_MODULE test_pythagoras_point_box +#endif + +#include <boost/test/included/unit_test.hpp> + +#if defined(_MSC_VER) +# pragma warning( disable : 4101 ) +#endif + +#include <boost/core/ignore_unused.hpp> +#include <boost/timer.hpp> + +#include <boost/concept/requires.hpp> +#include <boost/concept_check.hpp> + +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/algorithms/expand.hpp> +#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp> +#include <boost/geometry/strategies/concepts/distance_concept.hpp> + + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/box.hpp> +#include <boost/geometry/geometries/adapted/c_array.hpp> +#include <boost/geometry/geometries/adapted/boost_tuple.hpp> + +#include <test_common/test_point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + + +namespace bg = boost::geometry; + + +BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + + +template <typename Box, typename Coordinate> +inline void assign_values(Box& box, + Coordinate const& x1, + Coordinate const& y1, + Coordinate const& z1, + Coordinate const& x2, + Coordinate const& y2, + Coordinate const& z2) +{ + typename bg::point_type<Box>::type p1, p2; + bg::assign_values(p1, x1, y1, z1); + bg::assign_values(p2, x2, y2, z2); + bg::assign(box, p1); + bg::expand(box, p2); +} + +template <typename Point, typename Box> +inline void test_null_distance_3d() +{ + Point p; + bg::assign_values(p, 1, 2, 4); + Box b; + assign_values(b, 1, 2, 3, 4, 5, 6); + + typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_pb_type; + typedef typename bg::strategy::distance::services::return_type + < + pythagoras_pb_type, Point, Box + >::type return_type; + + pythagoras_pb_type pythagoras_pb; + return_type result = pythagoras_pb.apply(p, b); + + BOOST_CHECK_EQUAL(result, return_type(0)); + + bg::assign_values(p, 1, 3, 4); + result = pythagoras_pb.apply(p, b); + BOOST_CHECK_EQUAL(result, return_type(0)); + + bg::assign_values(p, 2, 3, 4); + result = pythagoras_pb.apply(p, b); + BOOST_CHECK_EQUAL(result, return_type(0)); +} + +template <typename Point, typename Box> +inline void test_axis_3d() +{ + Box b; + assign_values(b, 0, 0, 0, 1, 1, 1); + Point p; + bg::assign_values(p, 2, 0, 0); + + typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_pb_type; + typedef typename bg::strategy::distance::services::return_type + < + pythagoras_pb_type, Point, Box + >::type return_type; + + pythagoras_pb_type pythagoras_pb; + + return_type result = pythagoras_pb.apply(p, b); + BOOST_CHECK_EQUAL(result, return_type(1)); + + bg::assign_values(p, 0, 2, 0); + result = pythagoras_pb.apply(p, b); + BOOST_CHECK_EQUAL(result, return_type(1)); + + bg::assign_values(p, 0, 0, 2); + result = pythagoras_pb.apply(p, b); + BOOST_CHECK_CLOSE(result, return_type(1), 0.001); +} + +template <typename Point, typename Box> +inline void test_arbitrary_3d() +{ + Box b; + assign_values(b, 0, 0, 0, 1, 2, 3); + Point p; + bg::assign_values(p, 9, 8, 7); + + { + typedef bg::strategy::distance::pythagoras_point_box<> strategy_type; + typedef typename bg::strategy::distance::services::return_type + < + strategy_type, Point, Box + >::type return_type; + + strategy_type strategy; + return_type result = strategy.apply(p, b); + BOOST_CHECK_CLOSE(result, return_type(10.77032961427), 0.001); + } + + { + // Check comparable distance + typedef bg::strategy::distance::comparable::pythagoras_point_box<> + strategy_type; + + typedef typename bg::strategy::distance::services::return_type + < + strategy_type, Point, Box + >::type return_type; + + strategy_type strategy; + return_type result = strategy.apply(p, b); + BOOST_CHECK_EQUAL(result, return_type(116)); + } +} + +template <typename Point, typename Box, typename CalculationType> +inline void test_services() +{ + namespace bgsd = bg::strategy::distance; + namespace services = bg::strategy::distance::services; + + { + // Compile-check if there is a strategy for this type + typedef typename services::default_strategy + < + bg::point_tag, bg::box_tag, Point, Box + >::type pythagoras_pb_strategy_type; + + // reverse geometry tags + typedef typename services::default_strategy + < + bg::box_tag, bg::point_tag, Box, Point + >::type reversed_pythagoras_pb_strategy_type; + + boost::ignore_unused + < + pythagoras_pb_strategy_type, + reversed_pythagoras_pb_strategy_type + >(); + } + + Point p; + bg::assign_values(p, 1, 2, 3); + + Box b; + assign_values(b, 4, 5, 6, 14, 15, 16); + + double const sqr_expected = 3*3 + 3*3 + 3*3; // 27 + double const expected = sqrt(sqr_expected); // sqrt(27)=5.1961524227 + + // 1: normal, calculate distance: + + typedef bgsd::pythagoras_point_box<CalculationType> strategy_type; + + BOOST_CONCEPT_ASSERT + ( (bg::concepts::PointDistanceStrategy<strategy_type, Point, Box>) ); + + typedef typename bgsd::services::return_type + < + strategy_type, Point, Box + >::type return_type; + + strategy_type strategy; + return_type result = strategy.apply(p, b); + BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + // 2: the strategy should return the same result if we reverse parameters + // result = strategy.apply(p2, p1); + // BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + + // 3: "comparable" to construct a "comparable strategy" for Point/Box + // a "comparable strategy" is a strategy which does not calculate the exact distance, but + // which returns results which can be mutually compared (e.g. avoid sqrt) + + // 3a: "comparable_type" + typedef typename services::comparable_type + < + strategy_type + >::type comparable_type; + + // 3b: "get_comparable" + comparable_type comparable = bgsd::services::get_comparable + < + strategy_type + >::apply(strategy); + + typedef typename bgsd::services::return_type + < + comparable_type, Point, Box + >::type comparable_return_type; + + comparable_return_type c_result = comparable.apply(p, b); + BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001); + + // 4: the comparable_type should have a distance_strategy_constructor as well, + // knowing how to compare something with a fixed distance + comparable_return_type c_dist5 = services::result_from_distance + < + comparable_type, Point, Box + >::apply(comparable, 5.0); + + comparable_return_type c_dist6 = services::result_from_distance + < + comparable_type, Point, Box + >::apply(comparable, 6.0); + + // If this is the case: + BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6); + + // This should also be the case + return_type dist5 = services::result_from_distance + < + strategy_type, Point, Box + >::apply(strategy, 5.0); + return_type dist6 = services::result_from_distance + < + strategy_type, Point, Box + >::apply(strategy, 6.0); + BOOST_CHECK(dist5 < result && result < dist6); +} + +template +< + typename CoordinateType, + typename CalculationType, + typename AssignType +> +inline void test_big_2d_with(AssignType const& x1, AssignType const& y1, + AssignType const& x2, AssignType const& y2, + AssignType const& zero) +{ + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + typedef bg::model::box<point_type> box_type; + typedef bg::strategy::distance::pythagoras_point_box + < + CalculationType + > pythagoras_pb_type; + + pythagoras_pb_type pythagoras_pb; + typedef typename bg::strategy::distance::services::return_type + < + pythagoras_pb_type, point_type, box_type + >::type return_type; + + + point_type p; + box_type b; + bg::assign_values(b, zero, zero, x1, y1); + bg::assign_values(p, x2, y2); + return_type d = pythagoras_pb.apply(p, b); + + BOOST_CHECK_CLOSE(d, return_type(1076554.5485833955678294387789057), 0.001); +} + +template <typename CoordinateType, typename CalculationType> +inline void test_big_2d() +{ + test_big_2d_with<CoordinateType, CalculationType> + (123456.78900001, 234567.89100001, + 987654.32100001, 876543.21900001, + 0.0); +} + +template <typename CoordinateType, typename CalculationType> +inline void test_big_2d_string() +{ + test_big_2d_with<CoordinateType, CalculationType> + ("123456.78900001", "234567.89100001", + "987654.32100001", "876543.21900001", + "0.0000000000000"); +} + +template <typename CoordinateType> +inline void test_integer(bool check_types) +{ + typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type; + typedef bg::model::box<point_type> box_type; + + point_type p; + box_type b; + bg::assign_values(b, 0, 0, 12345678, 23456789); + bg::assign_values(p, 98765432, 87654321); + + typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_type; + 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, 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; + cdistance_type cdistance = comparable.apply(p, b); + BOOST_CHECK_EQUAL(cdistance, 11589696996311540.0); + + distance_type distance2 = sqrt(distance_type(cdistance)); + BOOST_CHECK_CLOSE(distance, distance2, 0.001); + + if (check_types) + { + BOOST_CHECK((boost::is_same<distance_type, double>::type::value)); + BOOST_CHECK((boost::is_same<cdistance_type, boost::long_long_type>::type::value)); + } +} + +template <typename P1, typename P2> +void test_all_3d() +{ + test_null_distance_3d<P1, bg::model::box<P2> >(); + test_axis_3d<P1, bg::model::box<P2> >(); + test_arbitrary_3d<P1, bg::model::box<P2> >(); + + test_null_distance_3d<P2, bg::model::box<P1> >(); + test_axis_3d<P2, bg::model::box<P1> >(); + test_arbitrary_3d<P2, bg::model::box<P1> >(); +} + +template <typename P> +void test_all_3d() +{ + test_all_3d<P, int[3]>(); + test_all_3d<P, float[3]>(); + test_all_3d<P, double[3]>(); + test_all_3d<P, test::test_point>(); + test_all_3d<P, bg::model::point<int, 3, bg::cs::cartesian> >(); + test_all_3d<P, bg::model::point<float, 3, bg::cs::cartesian> >(); + test_all_3d<P, bg::model::point<double, 3, bg::cs::cartesian> >(); +} + +template <typename P, typename Strategy> +void time_compare_s(int const n) +{ + typedef bg::model::box<P> box_type; + + boost::timer t; + P p; + box_type b; + bg::assign_values(b, 0, 0, 1, 1); + bg::assign_values(p, 2, 2); + Strategy strategy; + typename bg::strategy::distance::services::return_type + < + Strategy, P, box_type + >::type s = 0; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + bg::set<0>(p, bg::get<0>(p) + 0.001); + s += strategy.apply(p, b); + } + } + std::cout << "s: " << s << " t: " << t.elapsed() << std::endl; +} + +template <typename P> +inline void time_compare(int const n) +{ + time_compare_s<P, bg::strategy::distance::pythagoras_point_box<> >(n); + time_compare_s + < + P, bg::strategy::distance::comparable::pythagoras_point_box<> + >(n); +} + + + + +BOOST_AUTO_TEST_CASE( test_integer_all ) +{ + test_integer<int>(true); + test_integer<boost::long_long_type>(true); + test_integer<double>(false); +} + + +BOOST_AUTO_TEST_CASE( test_3d_all ) +{ + test_all_3d<int[3]>(); + test_all_3d<float[3]>(); + test_all_3d<double[3]>(); + + test_all_3d<test::test_point>(); + + test_all_3d<bg::model::point<int, 3, bg::cs::cartesian> >(); + test_all_3d<bg::model::point<float, 3, bg::cs::cartesian> >(); + test_all_3d<bg::model::point<double, 3, bg::cs::cartesian> >(); +} + + +BOOST_AUTO_TEST_CASE( test_big_2d_all ) +{ + test_big_2d<float, float>(); + test_big_2d<double, double>(); + test_big_2d<long double, long double>(); + test_big_2d<float, long double>(); +} + + +BOOST_AUTO_TEST_CASE( test_services_all ) +{ + test_services + < + bg::model::point<float, 3, bg::cs::cartesian>, + bg::model::box<double[3]>, + long double + >(); + test_services<double[3], bg::model::box<test::test_point>, float>(); + + // reverse the point and box types + test_services + < + double[3], + bg::model::box<bg::model::point<float, 3, bg::cs::cartesian> >, + long double + >(); + test_services<test::test_point, bg::model::box<double[3]>, float>(); +} + + +BOOST_AUTO_TEST_CASE( test_time_compare ) +{ + // TODO move this to another non-unit test + // time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000); +} + + +#if defined(HAVE_TTMATH) +BOOST_AUTO_TEST_CASE( test_ttmath_all ) +{ + typedef ttmath::Big<1,4> tt; + typedef bg::model::point<tt, 3, bg::cs::cartesian> tt_point; + + //test_all_3d<tt[3]>(); + test_all_3d<tt_point>(); + test_all_3d<tt_point, tt_point>(); + test_big_2d<tt, tt>(); + test_big_2d_string<tt, tt>(); +} +#endif diff --git a/src/boost/libs/geometry/test/strategies/segment_intersection.cpp b/src/boost/libs/geometry/test/strategies/segment_intersection.cpp new file mode 100644 index 00000000..5bccc1d4 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/segment_intersection.cpp @@ -0,0 +1,218 @@ +// 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. + +// 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) + + +#if defined(_MSC_VER) +// We deliberately mix float/double's here so turn off warning +#pragma warning( disable : 4244 ) +#endif // defined(_MSC_VER) + +#include <geometry_test_common.hpp> + +#include <boost/geometry/algorithms/assign.hpp> + +#include <boost/geometry/strategies/cartesian/intersection.hpp> +#include <boost/geometry/strategies/intersection_result.hpp> + +#include <boost/geometry/policies/relate/intersection_points.hpp> +#include <boost/geometry/policies/relate/direction.hpp> +#include <boost/geometry/policies/relate/tupled.hpp> + +#include <boost/geometry/algorithms/intersection.hpp> +#include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/segment.hpp> +#include <boost/geometry/geometries/adapted/boost_tuple.hpp> + +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian); + + +template <typename P> +static void test_segment_intersection(int caseid, + int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, + char expected_how, + int expected_x1 = -99, int expected_y1 = -99, + int expected_x2 = -99, int expected_y2 = -99) +{ + using namespace boost::geometry; + + typedef typename bg::coordinate_type<P>::type coordinate_type; + typedef bg::model::referring_segment<const P> segment_type; + + P p1, p2, p3, p4; + bg::assign_values(p1, x1, y1); + bg::assign_values(p2, x2, y2); + bg::assign_values(p3, x3, y3); + bg::assign_values(p4, x4, y4); + + segment_type s12(p1,p2); + segment_type s34(p3,p4); + + bg::detail::segment_as_subrange<segment_type> sr12(s12); + bg::detail::segment_as_subrange<segment_type> sr34(s34); + + std::size_t expected_count = 0; + + if (expected_x1 != -99 && expected_y1 != -99) + { + expected_count++; + } + if (expected_x2 != -99 && expected_y2 != -99) + { + expected_count++; + } + + // Using intersection_insert + + std::vector<P> out; + bg::detail::intersection::intersection_insert<P>(s12, s34, + std::back_inserter(out)); + + // Using strategy + typedef bg::segment_intersection_points<P> result_type; + + typedef bg::policies::relate::segments_intersection_points + < + result_type + > points_policy_type; + + result_type is + = bg::strategy::intersection::cartesian_segments<> + ::apply(sr12, sr34, points_policy_type()); + + bg::policies::relate::direction_type dir + = bg::strategy::intersection::cartesian_segments<> + ::apply(sr12, sr34, bg::policies::relate::segments_direction()); + + //BOOST_CHECK_EQUAL(boost::size(out), expected_count); + BOOST_CHECK_EQUAL(is.count, expected_count); + BOOST_CHECK_MESSAGE(dir.how == expected_how, + caseid + << " how: detected: " << dir.how + << " expected: " << expected_how); + + if (expected_count == 2 + && is.count == 2 + && boost::size(out) == 2) + { + // Two intersection points, reverse expectation if necessary + bool const first_matches + = std::fabs(bg::get<0>(out[0]) - expected_x1) < 1.0e-6 + && std::fabs(bg::get<1>(out[0]) - expected_y1) < 1.0e-6; + + if (! first_matches) + { + std::swap(expected_x1, expected_x2); + std::swap(expected_y1, expected_y2); + } + } + + if (expected_x1 != -99 && expected_y1 != -99 + && boost::size(out) >= 1) + { + + BOOST_CHECK_CLOSE(bg::get<0>(out[0]), coordinate_type(expected_x1), 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(out[0]), coordinate_type(expected_y1), 0.001); + + BOOST_CHECK_CLOSE(bg::get<0>(is.intersections[0]), expected_x1, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(is.intersections[0]), expected_y1, 0.001); + + } + if (expected_x2 != -99 && expected_y2 != -99 + && boost::size(out) >= 2) + { + BOOST_CHECK_CLOSE(bg::get<0>(out[1]), coordinate_type(expected_x2), 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(out[1]), coordinate_type(expected_y2), 0.001); + + BOOST_CHECK_CLOSE(bg::get<0>(is.intersections[1]), expected_x2, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(is.intersections[1]), expected_y2, 0.001); + } +} + + +template <typename P> +void test_all() +{ + test_segment_intersection<P>( 1, 0,2, 2,0, 0,0, 2,2, 'i', 1, 1); + test_segment_intersection<P>( 2, 2,2, 3,1, 0,0, 2,2, 'a', 2, 2); + test_segment_intersection<P>( 3, 3,1, 2,2, 0,0, 2,2, 't', 2, 2); + test_segment_intersection<P>( 4, 0,2, 1,1, 0,0, 2,2, 'm', 1, 1); + + test_segment_intersection<P>( 5, 1,1, 0,2, 0,0, 2,2, 's', 1, 1); + test_segment_intersection<P>( 6, 0,2, 2,0, 0,0, 1,1, 'm', 1, 1); + test_segment_intersection<P>( 7, 2,0, 0,2, 0,0, 1,1, 'm', 1, 1); + test_segment_intersection<P>( 8, 2,3, 3,2, 0,0, 2,2, 'd'); + + test_segment_intersection<P>( 9, 0,0, 2,2, 0,0, 2,2, 'e', 0, 0, 2, 2); + test_segment_intersection<P>(10, 2,2, 0,0, 0,0, 2,2, 'e', 2, 2, 0, 0); + test_segment_intersection<P>(11, 1,1, 3,3, 0,0, 2,2, 'c', 1, 1, 2, 2); + test_segment_intersection<P>(12, 3,3, 1,1, 0,0, 2,2, 'c', 1, 1, 2, 2); + + test_segment_intersection<P>(13, 0,2, 2,2, 2,1, 2,3, 'm', 2, 2); + test_segment_intersection<P>(14, 2,2, 2,4, 2,0, 2,2, 'a', 2, 2); + test_segment_intersection<P>(15, 2,2, 2,4, 2,0, 2,1, 'd'); + test_segment_intersection<P>(16, 2,4, 2,2, 2,0, 2,1, 'd'); + + test_segment_intersection<P>(17, 2,1, 2,3, 2,2, 2,4, 'c', 2, 2, 2, 3); + test_segment_intersection<P>(18, 2,3, 2,1, 2,2, 2,4, 'c', 2, 3, 2, 2); + test_segment_intersection<P>(19, 0,2, 2,2, 4,2, 2,2, 't', 2, 2); + test_segment_intersection<P>(20, 0,2, 2,2, 2,2, 4,2, 'a', 2, 2); + + test_segment_intersection<P>(21, 1,2, 3,2, 2,1, 2,3, 'i', 2, 2); + test_segment_intersection<P>(22, 2,4, 2,1, 2,1, 2,3, 'c', 2, 1, 2, 3); + test_segment_intersection<P>(23, 2,4, 2,1, 2,3, 2,1, 'c', 2, 3, 2, 1); + test_segment_intersection<P>(24, 1,1, 3,3, 0,0, 3,3, 'c', 1, 1, 3, 3); + + test_segment_intersection<P>(25, 2,0, 2,4, 2,1, 2,3, 'c', 2, 1, 2, 3); + test_segment_intersection<P>(26, 2,0, 2,4, 2,3, 2,1, 'c', 2, 3, 2, 1); + test_segment_intersection<P>(27, 0,0, 4,4, 1,1, 3,3, 'c', 1, 1, 3, 3); + test_segment_intersection<P>(28, 0,0, 4,4, 3,3, 1,1, 'c', 3, 3, 1, 1); + + test_segment_intersection<P>(29, 1,1, 3,3, 0,0, 4,4, 'c', 1, 1, 3, 3); + test_segment_intersection<P>(30, 0,0, 2,2, 2,2, 3,1, 'a', 2, 2); + test_segment_intersection<P>(31, 0,0, 2,2, 2,2, 1,3, 'a', 2, 2); + test_segment_intersection<P>(32, 0,0, 2,2, 1,1, 2,0, 's', 1, 1); + + test_segment_intersection<P>(33, 0,0, 2,2, 1,1, 0,2, 's', 1, 1); + test_segment_intersection<P>(34, 2,2, 1,3, 0,0, 2,2, 'a', 2, 2); + test_segment_intersection<P>(35, 2,2, 3,1, 0,0, 2,2, 'a', 2, 2); + test_segment_intersection<P>(36, 0,0, 2,2, 0,2, 1,1, 'm', 1, 1); + + test_segment_intersection<P>(37, 0,0, 2,2, 2,0, 1,1, 'm', 1, 1); + test_segment_intersection<P>(38, 1,1, 0,2, 0,0, 2,2, 's', 1, 1); + test_segment_intersection<P>(39, 1,1, 2,0, 0,0, 2,2, 's', 1, 1); + test_segment_intersection<P>(40, 2,0, 1,1, 0,0, 2,2, 'm', 1, 1); + + test_segment_intersection<P>(41, 1,2, 0,2, 2,2, 0,2, 'c', 1, 2, 0, 2); + test_segment_intersection<P>(42, 2,1, 1,1, 2,2, 0,2, 'd'); + test_segment_intersection<P>(43, 4,1, 3,1, 2,2, 0,2, 'd'); + test_segment_intersection<P>(44, 4,2, 3,2, 2,2, 0,2, 'd'); + + test_segment_intersection<P>(45, 2,0, 0,2, 0,0, 2,2, 'i', 1, 1); + + // In figure: times 2 + test_segment_intersection<P>(46, 8,2, 4,6, 0,0, 8, 8, 'i', 5, 5); +} + +int test_main(int, char* []) +{ +#if !defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) + test_all<boost::tuple<double, double> >(); + test_all<bg::model::point<float, 2, bg::cs::cartesian> >(); +#endif + test_all<bg::model::point<double, 2, bg::cs::cartesian> >(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/segment_intersection_collinear.cpp b/src/boost/libs/geometry/test/strategies/segment_intersection_collinear.cpp new file mode 100644 index 00000000..287888f9 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/segment_intersection_collinear.cpp @@ -0,0 +1,527 @@ +// 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) 2017, 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) + +#define BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO + +#include <geometry_test_common.hpp> + +#include <boost/geometry/algorithms/assign.hpp> + +#include <boost/geometry/strategies/cartesian/intersection.hpp> +#include <boost/geometry/strategies/intersection_result.hpp> + +#include <boost/geometry/policies/relate/intersection_points.hpp> +#include <boost/geometry/policies/relate/direction.hpp> +#include <boost/geometry/policies/relate/tupled.hpp> + +#include <boost/geometry/algorithms/intersection.hpp> +#include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/segment.hpp> + + +template <typename IntersectionPoints> +static int check(IntersectionPoints const& is, + std::size_t index, double expected_x, double expected_y) +{ + if (expected_x != -99 && expected_y != -99 && is.count > index) + { + double x = bg::get<0>(is.intersections[index]); + double y = bg::get<1>(is.intersections[index]); + + BOOST_CHECK_CLOSE(x, expected_x, 0.001); + BOOST_CHECK_CLOSE(y, expected_y, 0.001); + return 1; + } + return 0; +} + + +template <typename P> +static void test_segment_intersection(std::string const& case_id, + int x1, int y1, int x2, int y2, + int x3, int y3, int x4, int y4, + char expected_how, bool expected_opposite, + int expected_arrival1, int expected_arrival2, + int expected_x1, int expected_y1, + int expected_x2 = -99, int expected_y2 = -99) + +{ + boost::ignore_unused(case_id); + + typedef bg::model::referring_segment<const P> segment_type; + + P p1, p2, p3, p4; + bg::assign_values(p1, x1, y1); + bg::assign_values(p2, x2, y2); + bg::assign_values(p3, x3, y3); + bg::assign_values(p4, x4, y4); + + segment_type s12(p1, p2); + segment_type s34(p3, p4); + + bg::detail::segment_as_subrange<segment_type> sr12(s12); + bg::detail::segment_as_subrange<segment_type> sr34(s34); + + typedef bg::segment_intersection_points<P> result_type; + + typedef bg::policies::relate::segments_intersection_points + < + result_type + > points_policy_type; + + // Get the intersection point (or two points) + result_type is + = bg::strategy::intersection::cartesian_segments<> + ::apply(sr12, sr34, points_policy_type()); + + // Get just a character for Left/Right/intersects/etc, purpose is more for debugging + bg::policies::relate::direction_type dir + = bg::strategy::intersection::cartesian_segments<> + ::apply(sr12, sr34, bg::policies::relate::segments_direction()); + + std::size_t expected_count = + check(is, 0, expected_x1, expected_y1) + + check(is, 1, expected_x2, expected_y2); + + BOOST_CHECK_EQUAL(is.count, expected_count); + BOOST_CHECK_EQUAL(dir.how, expected_how); + BOOST_CHECK_EQUAL(dir.opposite, expected_opposite); + BOOST_CHECK_EQUAL(dir.arrival[0], expected_arrival1); + BOOST_CHECK_EQUAL(dir.arrival[1], expected_arrival2); +} + +template <typename P, typename Pair> +static void test_segment_ratio(std::string const& case_id, + int x1, int y1, int x2, int y2, + int x3, int y3, int x4, int y4, + Pair expected_pair_a1, Pair expected_pair_a2, + Pair expected_pair_b1, Pair expected_pair_b2, + int exp_ax1, int exp_ay1, int exp_ax2, int exp_ay2, + std::size_t expected_count = 2) + +{ + boost::ignore_unused(case_id); + + typedef bg::model::referring_segment<const P> segment_type; + + P p1, p2, p3, p4; + bg::assign_values(p1, x1, y1); + bg::assign_values(p2, x2, y2); + bg::assign_values(p3, x3, y3); + bg::assign_values(p4, x4, y4); + + segment_type s12(p1, p2); + segment_type s34(p3, p4); + + bg::detail::segment_as_subrange<segment_type> sr12(s12); + bg::detail::segment_as_subrange<segment_type> sr34(s34); + + typedef bg::segment_intersection_points<P> result_type; + + typedef bg::policies::relate::segments_intersection_points + < + result_type + > points_policy_type; + + // Get the intersection point (or two points) + result_type is + = bg::strategy::intersection::cartesian_segments<> + ::apply(sr12, sr34, points_policy_type()); + + typedef bg::segment_ratio<typename bg::coordinate_type<P>::type> ratio_type; + + ratio_type expected_a1(expected_pair_a1.first, expected_pair_a1.second); + ratio_type expected_a2(expected_pair_a2.first, expected_pair_a2.second); + ratio_type expected_b1(expected_pair_b1.first, expected_pair_b1.second); + ratio_type expected_b2(expected_pair_b2.first, expected_pair_b2.second); + + BOOST_CHECK_EQUAL(is.count, expected_count); + + BOOST_CHECK_EQUAL(is.fractions[0].robust_ra, expected_a1); + BOOST_CHECK_EQUAL(is.fractions[0].robust_rb, expected_b1); + BOOST_CHECK_EQUAL(bg::get<0>(is.intersections[0]), exp_ax1); + BOOST_CHECK_EQUAL(bg::get<1>(is.intersections[0]), exp_ay1); + + if (expected_count == 2) + { + BOOST_CHECK_EQUAL(bg::get<0>(is.intersections[1]), exp_ax2); + BOOST_CHECK_EQUAL(bg::get<1>(is.intersections[1]), exp_ay2); + BOOST_CHECK_EQUAL(is.fractions[1].robust_ra, expected_a2); + BOOST_CHECK_EQUAL(is.fractions[1].robust_rb, expected_b2); + } +} + + +template <typename P> +void test_all() +{ + // Collinear - non opposite + + // a1---------->a2 + // b1--->b2 + test_segment_intersection<P>("n1", + 2, 0, 6, 0, + 0, 0, 2, 0, + 'a', false, -1, 0, + 2, 0); + + // a1---------->a2 + // b1--->b2 + test_segment_intersection<P>("n2", + 2, 0, 6, 0, + 1, 0, 3, 0, + 'c', false, -1, 1, + 2, 0, 3, 0); + + // a1---------->a2 + // b1--->b2 + test_segment_intersection<P>("n3", + 2, 0, 6, 0, + 2, 0, 4, 0, + 'c', false, -1, 1, + 2, 0, 4, 0); + + // a1---------->a2 + // b1--->b2 + test_segment_intersection<P>("n4", + 2, 0, 6, 0, + 3, 0, 5, 0, + 'c', false, -1, 1, + 3, 0, 5, 0); + + // a1---------->a2 + // b1--->b2 + test_segment_intersection<P>("n5", + 2, 0, 6, 0, + 4, 0, 6, 0, + 'c', false, 0, 0, + 4, 0, 6, 0); + + // a1---------->a2 + // b1--->b2 + test_segment_intersection<P>("n6", + 2, 0, 6, 0, + 5, 0, 7, 0, + 'c', false, 1, -1, + 5, 0, 6, 0); + + // a1---------->a2 + // b1--->b2 + test_segment_intersection<P>("n7", + 2, 0, 6, 0, + 6, 0, 8, 0, + 'a', false, 0, -1, + 6, 0); + + // Collinear - opposite + // a1---------->a2 + // b2<---b1 + test_segment_intersection<P>("o1", + 2, 0, 6, 0, + 2, 0, 0, 0, + 'f', true, -1, -1, + 2, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_intersection<P>("o2", + 2, 0, 6, 0, + 3, 0, 1, 0, + 'c', true, -1, -1, + 2, 0, 3, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_intersection<P>("o3", + 2, 0, 6, 0, + 4, 0, 2, 0, + 'c', true, -1, 0, + 2, 0, 4, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_intersection<P>("o4", + 2, 0, 6, 0, + 5, 0, 3, 0, + 'c', true, -1, 1, + 3, 0, 5, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_intersection<P>("o5", + 2, 0, 6, 0, + 6, 0, 4, 0, + 'c', true, 0, 1, + 4, 0, 6, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_intersection<P>("o6", + 2, 0, 6, 0, + 7, 0, 5, 0, + 'c', true, 1, 1, + 5, 0, 6, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_intersection<P>("o7", + 2, 0, 6, 0, + 8, 0, 6, 0, + 't', true, 0, 0, + 6, 0); + + // a1---------->a2 + // b1---------->b2 + test_segment_intersection<P>("e1", + 2, 0, 6, 0, + 2, 0, 6, 0, + 'e', false, 0, 0, + 2, 0, 6, 0); + + // a1---------->a2 + // b2<----------b1 + test_segment_intersection<P>("e1", + 2, 0, 6, 0, + 6, 0, 2, 0, + 'e', true, 0, 0, + 2, 0, 6, 0); + + // Disjoint (in vertical direction, picture still horizontal) + // a2<---a1 + // b2<---b1 + test_segment_intersection<P>("case_recursive_boxes_1", + 10, 7, 10, 6, + 10, 10, 10, 9, + 'd', false, 0, 0, + -1, -1, -1, -1); + +} + + +template <typename P> +void test_ratios() +{ + // B inside A + // a1------------>a2 + // b1--->b2 + test_segment_ratio<P>("n4", + 2, 0, 7, 0, + 3, 0, 5, 0, + std::make_pair(1, 5), std::make_pair(3, 5), // IP located on 1/5, 3/5 w.r.t A + std::make_pair(0, 1), std::make_pair(1, 1), // IP located on 0, 1 w.r.t. B + // IP's are ordered as in A (currently) + 3, 0, 5, 0); + + // a1------------>a2 + // b2<---b1 + test_segment_ratio<P>("o4", + 2, 0, 7, 0, + 5, 0, 3, 0, + std::make_pair(1, 5), std::make_pair(3, 5), + std::make_pair(1, 1), std::make_pair(0, 1), + 3, 0, 5, 0); + + // a2<------------a1 + // b2<---b1 + test_segment_ratio<P>("o4b", + 7, 0, 2, 0, + 5, 0, 3, 0, + std::make_pair(2, 5), std::make_pair(4, 5), + std::make_pair(0, 1), std::make_pair(1, 1), + 5, 0, 3, 0); + + // a2<------------a1 + // b1--->b2 + test_segment_ratio<P>("o4c", + 7, 0, 2, 0, + 3, 0, 5, 0, + std::make_pair(2, 5), std::make_pair(4, 5), + std::make_pair(1, 1), std::make_pair(0, 1), + 5, 0, 3, 0); + + // Touch-interior + // a1---------->a2 + // b1--->b2 + test_segment_ratio<P>("n3", + 2, 0, 7, 0, + 2, 0, 4, 0, + std::make_pair(0, 1), std::make_pair(2, 5), + std::make_pair(0, 1), std::make_pair(1, 1), + 2, 0, 4, 0); + + // a2<-------------a1 + // b2<----b1 + test_segment_ratio<P>("n3b", + 7, 0, 2, 0, + 7, 0, 5, 0, + std::make_pair(0, 1), std::make_pair(2, 5), + std::make_pair(0, 1), std::make_pair(1, 1), + 7, 0, 5, 0); + + + // A inside B + // a1--->a2 + // b1------------>b2 + test_segment_ratio<P>("rn4", + 3, 0, 5, 0, + 2, 0, 7, 0, + std::make_pair(0, 1), std::make_pair(1, 1), + std::make_pair(1, 5), std::make_pair(3, 5), + 3, 0, 5, 0); + + // a2<---a1 + // b1------------>b2 + test_segment_ratio<P>("ro4", + 5, 0, 3, 0, + 2, 0, 7, 0, + std::make_pair(0, 1), std::make_pair(1, 1), + std::make_pair(3, 5), std::make_pair(1, 5), + 5, 0, 3, 0); + + // a2<---a1 + // b2<------------b1 + test_segment_ratio<P>("ro4b", + 5, 0, 3, 0, + 7, 0, 2, 0, + std::make_pair(0, 1), std::make_pair(1, 1), + std::make_pair(2, 5), std::make_pair(4, 5), + 5, 0, 3, 0); + + // a1--->a2 + // b2<------------b1 + test_segment_ratio<P>("ro4c", + 3, 0, 5, 0, + 7, 0, 2, 0, + std::make_pair(0, 1), std::make_pair(1, 1), + std::make_pair(4, 5), std::make_pair(2, 5), + 3, 0, 5, 0); + + // B inside A, boundaries intersect + // We change the coordinates a bit (w.r.t. n3 above) to have it asymmetrical + // a1---------->a2 + // b1--->b2 + test_segment_ratio<P>("n3", + 2, 0, 7, 0, + 2, 0, 4, 0, + std::make_pair(0, 1), std::make_pair(2, 5), + std::make_pair(0, 1), std::make_pair(1, 1), + 2, 0, 4, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_ratio<P>("o3", + 2, 0, 7, 0, + 4, 0, 2, 0, + std::make_pair(0, 1), std::make_pair(2, 5), + std::make_pair(1, 1), std::make_pair(0, 1), + 2, 0, 4, 0); + + // a1---------->a2 + // b1--->b2 + test_segment_ratio<P>("n5", + 2, 0, 7, 0, + 5, 0, 7, 0, + std::make_pair(3, 5), std::make_pair(1, 1), + std::make_pair(0, 1), std::make_pair(1, 1), + 5, 0, 7, 0); + + // a1---------->a2 + // b2<---b1 + test_segment_ratio<P>("o5", + 2, 0, 7, 0, + 7, 0, 5, 0, + std::make_pair(3, 5), std::make_pair(1, 1), + std::make_pair(1, 1), std::make_pair(0, 1), + 5, 0, 7, 0); + + // Generic (overlaps) + // a1---------->a2 + // b1----->b2 + test_segment_ratio<P>("n2", + 2, 0, 7, 0, + 1, 0, 4, 0, + std::make_pair(0, 1), std::make_pair(2, 5), + std::make_pair(1, 3), std::make_pair(1, 1), + 2, 0, 4, 0); + + // Same, b reversed + test_segment_ratio<P>("n2_b", + 2, 0, 7, 0, + 4, 0, 1, 0, + std::make_pair(0, 1), std::make_pair(2, 5), + std::make_pair(2, 3), std::make_pair(0, 1), + 2, 0, 4, 0); + + // Same, both reversed + test_segment_ratio<P>("n2_c", + 7, 0, 2, 0, + 4, 0, 1, 0, + std::make_pair(3, 5), std::make_pair(1, 1), + std::make_pair(0, 1), std::make_pair(2, 3), + 4, 0, 2, 0); + + // a1---------->a2 + // b1----->b2 + test_segment_ratio<P>("n6", + 2, 0, 6, 0, + 5, 0, 8, 0, + std::make_pair(3, 4), std::make_pair(1, 1), + std::make_pair(0, 1), std::make_pair(1, 3), + 5, 0, 6, 0); + + // Degenerated one + // a1---------->a2 + // b1/b2 + const int ignored = 99; + test_segment_ratio<P>("degenerated1", + 2, 0, 6, 0, + 5, 0, 5, 0, + std::make_pair(3, 4), // IP located on 3/4 w.r.t A + std::make_pair(ignored, 1), // not checked + std::make_pair(0, 1), // IP located at any place w.r.t B, so 0 + std::make_pair(ignored, 1), // not checked + 5, 0, + ignored, ignored, + 1); + + test_segment_ratio<P>("degenerated2", + 5, 0, 5, 0, + 2, 0, 6, 0, + std::make_pair(0, 1), std::make_pair(ignored, 1), + std::make_pair(3, 4), std::make_pair(ignored, 1), + 5, 0, + ignored, ignored, + 1); + + // Vertical one like in box_poly5 but in integer + test_segment_ratio<P>("box_poly5", + 45, 25, 45, 15, + 45, 22, 45, 19, + std::make_pair(3, 10), std::make_pair(6, 10), + std::make_pair(0, 1), std::make_pair(1, 1), + 45, 22, 45, 19); +} + +int test_main(int, char* []) +{ + // We don't rescale but use integer points as, by nature, robust points + test_all<bg::model::point<int, 2, bg::cs::cartesian> >(); + test_ratios<bg::model::point<int, 2, bg::cs::cartesian> >(); + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/segment_intersection_geo.cpp b/src/boost/libs/geometry/test/strategies/segment_intersection_geo.cpp new file mode 100644 index 00000000..16a41091 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/segment_intersection_geo.cpp @@ -0,0 +1,430 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2016-2018, 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) + + +#include "segment_intersection_geo.hpp" + + +template <typename T> +void test_geographic() +{ + typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > point_t; + typedef bg::model::segment<point_t> segment_t; + + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -2, -1 -1)", 'a', "POINT(-1 -1)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -2, 1 1)", "SEGMENT(-1 -2, -1 -1)", 'f', "POINT(-1 -2)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 1, -1 -1)", "SEGMENT(-1 -2, -1 -1)", 't', "POINT(-1 -1)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 1, -1 -2)", "SEGMENT(-1 -2, -1 -1)", 'a', "POINT(-1 -2)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -2, -1 -1)", "SEGMENT(-1 -1, 1 1)", 'a', "POINT(-1 -1)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -2, -1 -1)", "SEGMENT(-1 -2, 1 1)", 'f', "POINT(-1 -2)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -2, -1 -1)", "SEGMENT(1 1, -1 -1)", 't', "POINT(-1 -1)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -2, -1 -1)", "SEGMENT(1 1, -1 -2)", 'a', "POINT(-1 -2)"); + + test_strategies<segment_t, point_t>( + "SEGMENT(-1 -2, -1 2)", "SEGMENT(-2 -2, 2 2)", + great_elliptic('i', "POINT(-1 -1.000457053724121)"), + geodesic_vincenty('i', "POINT(-1 -1.000459099991114)"), + geodesic_andoyer('i', "POINT(-1 -1.000453510849886)")); + test_strategies<segment_t, point_t>( + "SEGMENT(-2 -2, 2 2)", "SEGMENT(-1 -2, -1 2)", + great_elliptic('i', "POINT(-1 -1.000457053724121)"), + geodesic_vincenty('i', "POINT(-1 -1.000459099991114)"), + geodesic_andoyer('i', "POINT(-1 -1.000453510849886)")); + + // crossing X + test_strategies<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(-45 45, 45 -45)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000001380087204053 -0.0000000000000063611)"), + geodesic_andoyer('i', "POINT(0 0.0003512140328446071)")); + test_strategies<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(45 -45, -45 45)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000001380087204053 -0.0000000000000063611)"), + geodesic_andoyer('i', "POINT(0 0.0003512140328446071)")); + test_strategies<segment_t, point_t>( + "SEGMENT(45 45, -45 -45)", "SEGMENT(-45 45, 45 -45)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000001380087204053 -0.0000000000000063611)"), + geodesic_andoyer('i', "POINT(0 0.0003512140328446071)")); + test_strategies<segment_t, point_t>( + "SEGMENT(45 45, -45 -45)", "SEGMENT(45 -45, -45 45)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000001380087204053 -0.0000000000000063611)"), + geodesic_andoyer('i', "POINT(0 0.0003512140328446071)")); + + // crossing X + test_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 1, 1 -1)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000000000000596354 -0.0000000000626626779)"), + geodesic_andoyer('i', "POINT(-0.000000000000000596354 0.0000055787431347552)")); + test_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(1 -1, -1 1)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000000000000596354 -0.0000000000626626779)"), + geodesic_andoyer('i', "POINT(-0.000000000000000596354 0.0000055787431347552)")); + test_strategies<segment_t, point_t>( + "SEGMENT(1 1, -1 -1)", "SEGMENT(-1 1, 1 -1)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000000000000596354 -0.0000000000626626779)"), + geodesic_andoyer('i', "POINT(-0.000000000000000596354 0.0000055787431347552)")); + test_strategies<segment_t, point_t>( + "SEGMENT(1 1, -1 -1)", "SEGMENT(1 -1, -1 1)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.000000000000000596354 -0.0000000000626626779)"), + geodesic_andoyer('i', "POINT(-0.000000000000000596354 0.0000055787431347552)")); + + // equal + // // + test_all_strategies<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(-45 -45, 45 45)", 'e', "POINT(-45 -45)", "POINT(45 45)", false); + // // + test_all_strategies<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(45 45, -45 -45)", 'e', "POINT(-45 -45)", "POINT(45 45)", true); + + // starting outside s1 + // / + // | + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, -1 -1)", 'a', "POINT(-1 -1)"); + // / + // /| + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, 0 0)", 'm', "POINT(0 0)"); + // /| + // / | + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, 1 1)", 't', "POINT(1 1)"); + // |/ + // /| + test_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, 2 2)", + great_elliptic('i', "POINT(0 0)"), + geodesic_vincenty('i', "POINT(0.00000013628420059 0.00000013624239008)"), + geodesic_thomas('i', "POINT(-0.00004079969079346 -0.00004078714535240)"), + geodesic_andoyer('i', "POINT(-0.01217344899138908 -0.01216980051876599)")); + // ------ + // ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, -1 0)", 'a', "POINT(-1 0)"); + // ------ + // ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, 0 0)", 'c', "POINT(-1 0)", "POINT(0 0)", false); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(0 0, -2 0)", 'c', "POINT(-1 0)", "POINT(0 0)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 0, -1 0)", "SEGMENT(-2 0, 0 0)", 'c', "POINT(0 0)", "POINT(-1 0)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 0, -1 0)", "SEGMENT(0 0, -2 0)", 'c', "POINT(0 0)", "POINT(-1 0)", false); + // ------ + // --------- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, 1 0)", 'c', "POINT(-1 0)", "POINT(1 0)", false); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(1 0, -2 0)", 'c', "POINT(-1 0)", "POINT(1 0)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 0, -1 0)", "SEGMENT(-2 0, 1 0)", 'c', "POINT(1 0)", "POINT(-1 0)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 0, -1 0)", "SEGMENT(1 0, -2 0)", 'c', "POINT(1 0)", "POINT(-1 0)", false); + // ------ + // ------------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, 2 0)", 'c', "POINT(-1 0)", "POINT(1 0)", false); + + // starting at s1 + // / + // // + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, 0 0)", 'c', "POINT(-1 -1)", "POINT(0 0)", false); + // // + // // + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, 1 1)", 'e', "POINT(-1 -1)", "POINT(1 1)", false); + // | / + // |/ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, 2 2)", 'f', "POINT(-1 -1)"); + // ------ + // --- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, 0 0)", 'c', "POINT(-1 0)", "POINT(0 0)", false); + // ------ + // ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, 1 0)", 'e', "POINT(-1 0)", "POINT(1 0)", false); + // ------ + // --------- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, 2 0)", 'c', "POINT(-1 0)", "POINT(1 0)", false); + + // starting inside + // // + // / + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(0 0, 1 1)", 'c', "POINT(0 0)", "POINT(1 1)", false); + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(1 1, 0 0)", 'c', "POINT(0 0)", "POINT(1 1)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 1, -1 -1)", "SEGMENT(0 0, 1 1)", 'c', "POINT(1 1)", "POINT(0 0)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 1, -1 -1)", "SEGMENT(1 1, 0 0)", 'c', "POINT(1 1)", "POINT(0 0)", false); + test_all_strategies<segment_t, point_t>( + "SEGMENT(0 0, 1 1)", "SEGMENT(-1 -1, 1 1)", 'c', "POINT(0 0)", "POINT(1 1)", false); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 1, 0 0)", "SEGMENT(-1 -1, 1 1)", 'c', "POINT(1 1)", "POINT(0 0)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(0 0, 1 1)", "SEGMENT(1 1, -1 -1)", 'c', "POINT(0 0)", "POINT(1 1)", true); + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 1, 0 0)", "SEGMENT(1 1, -1 -1)", 'c', "POINT(1 1)", "POINT(0 0)", false); + // |/ + // / + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(0 0, 2 2)", 's', "POINT(0 0)"); + // ------ + // --- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(0 0, 1 0)", 'c', "POINT(0 0)", "POINT(1 0)", false); + // ------ + // ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(0 0, 2 0)", 'c', "POINT(0 0)", "POINT(1 0)", false); + + // starting at p2 + // | + // / + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(1 1, 2 2)", 'a', "POINT(1 1)"); + // ------ + // --- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(1 0, 2 0)", 'a', "POINT(1 0)"); + + // disjoint, crossing + // / + // | + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-3 -3, -2 -2)", 'd'); + // | + // / + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(2 2, 3 3)", 'd'); + // disjoint, collinear + // ------ + // ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-3 0, -2 0)", 'd'); + // ------ + // ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(2 0, 3 0)", 'd'); + + // degenerated + // / + // * + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, -2 -2)", 'd'); + // / + // * + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, -1 -1)", '0', "POINT(-1 -1)"); + // / + // * + // / + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(0 0, 0 0)", '0', "POINT(0 0)"); + // * + // / + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(1 1, 1 1)", '0', "POINT(1 1)"); + // * + // / + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(2 2, 2 2)", 'd'); + // similar to above, collinear + // * ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, -2 0)", 'd'); + // *------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, -1 0)", '0', "POINT(-1 0)"); + // ---*--- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(0 0, 0 0)", '0', "POINT(0 0)"); + // ------* + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(1 0, 1 0)", '0', "POINT(1 0)"); + // ------ * + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(2 0, 2 0)", 'd'); + + // Northern hemisphere + // --- ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-3 50, -2 50)", 'd'); + // ------ + // --- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, -1 50)", 'a', "POINT(-1 50)"); + // \/ + // /\ (avoid multi-line comment) + test_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, 0 50)", + great_elliptic('i', "POINT(-0.5 50.0032229484023)"), + geodesic_vincenty('i', "POINT(-0.4999999996073994 50.00323192256208)"), + geodesic_thomas('i', "POINT(-0.4999999963998482 50.00323192258598)"), + geodesic_andoyer('i', "POINT(-0.4999990340391772 50.00323192463806)")); + // ________ + // / _____\ (avoid multi-line comment) + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, 1 50)", 't', "POINT(1 50)"); + // _________ + // / _____ \ (avoid multi-line comment) + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, 2 50)", 'd'); + // ______ + // /___ \ (avoid multi-line comment) + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-1 50, 0 50)", 'f', "POINT(-1 50)"); + // ------ + // ------ + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-1 50, 1 50)", 'e', "POINT(-1 50)", "POINT(1 50)", false); + // ________ + // /_____ \ (avoid multi-line comment) + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-1 50, 2 50)", 'f', "POINT(-1 50)"); + // ______ + // / ___\ (avoid multi-line comment) + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(0 50, 1 50)", 't', "POINT(1 50)"); + // \/ + // /\ (avoid multi-line comment) + test_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(0 50, 2 50)", + great_elliptic('i', "POINT(0.5 50.0032229484023)"), + geodesic_vincenty('i', "POINT(0.4999999996112415 50.00323192256208)"), + geodesic_thomas('i', "POINT(0.5000000051005989 50.00323192258598)"), + geodesic_andoyer('i', "POINT(0.5000009655139563 50.00323192463806)")); + // ------ + // --- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(1 50, 2 50)", 'a', "POINT(1 50)"); + // ------ --- + test_all_strategies<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(2 50, 3 50)", 'd'); + + // ___| + test_all_strategies<segment_t, point_t>( + "SEGMENT(0 0, 1 0)", "SEGMENT(1 0, 1 1)", 'a', "POINT(1 0)"); + // ___| + test_all_strategies<segment_t, point_t>( + "SEGMENT(1 0, 1 1)", "SEGMENT(0 0, 1 0)", 'a', "POINT(1 0)"); + + // |/ + // /| + test_strategies<segment_t, point_t>( + "SEGMENT(10 -1, 20 1)", "SEGMENT(12.5 -1, 12.5 1)", + great_elliptic('i', "POINT(12.5 -0.50051443471392)"), + geodesic_vincenty('i', "POINT(12.5 -0.5005177749487734)"), + geodesic_thomas('i', "POINT(12.5 -0.5005177654827411)"), + geodesic_andoyer('i', "POINT(12.5 -0.500525380045163)")); + // |/ + // /| + test_strategies<segment_t, point_t>( + "SEGMENT(10 -1, 20 1)", "SEGMENT(17.5 -1, 17.5 1)", + great_elliptic('i', "POINT(17.5 0.50051443471392)"), + geodesic_vincenty('i', "POINT(17.5 0.5005177748229335)"), + geodesic_thomas('i', "POINT(17.5 0.5005178030678186)"), + geodesic_andoyer('i', "POINT(17.5 0.5004949944844279)")); + + // vertical, crossing at the pole or disjoint + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 45, -90 60)", "SEGMENT(0 50, 180 70)", 'i', "POINT(0 90)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 -45, -90 -60)", "SEGMENT(0 -50, 180 -70)", 'i', "POINT(0 -90)"); + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 45, -90 60)", "SEGMENT(0 -50, 180 -70)", 'd'); + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 -45, -90 -60)", "SEGMENT(0 50, 180 70)", 'd'); + + // vertical touching at the pole + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 90, 90 45)", "SEGMENT(0 90, 0 45)", 'f', "POINT(90 90)"); // should probably be (0 90) + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 90, 90 45)", "SEGMENT(0 45, 0 90)", 'a', "POINT(90 90)"); // should probably be (0 90) + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 45, 90 90)", "SEGMENT(0 90, 0 45)", 'a', "POINT(90 90)"); // should probably be (0 90) + test_all_strategies<segment_t, point_t>( + "SEGMENT(90 45, 90 90)", "SEGMENT(0 45, 0 90)", 't', "POINT(90 90)"); // should probably be (0 90) + + // one vertical with endpoint at a pole + /*test_strategies<segment_t, point_t>( + "SEGMENT(0 90, 90 0)", "SEGMENT(89 45, 91 45)", + great_elliptic('i', "POINT(90 45.00436354465514)"), + geodesic_vincenty('i', "POINT(90.00000000000112 45.00437824795338)"), + geodesic_thomas('i', "POINT(90.00000000472062 45.00437824797395)"), + geodesic_andoyer('i', "POINT(89.99999993672924 45.00437824794587)")); + test_strategies<segment_t, point_t>( + "SEGMENT(90 0, 0 90)", "SEGMENT(89 45, 91 45)", + great_elliptic('i', "POINT(90 45.00436354465514)"), + geodesic_vincenty('i', "POINT(90.00000000000112 45.00437824795338)"), + geodesic_thomas('i', "POINT(90.00000000472062 45.00437824797395)"), + geodesic_andoyer('i', "POINT(89.99999993672924 45.00437824794587)")); + test_strategies<segment_t, point_t>( + "SEGMENT(0 -90, 90 0)", "SEGMENT(89 -45, 91 -45)", + great_elliptic('i', "POINT(90 -45.00436354465514)"), + geodesic_vincenty('i', "POINT(90.00000000000112 -45.00437824795338)"), + geodesic_thomas('i', "POINT(90.00000000472062 -45.00437824797395)"), + geodesic_andoyer('i', "POINT(89.99999993672924 -45.00437824794587)")); + test_strategies<segment_t, point_t>( + "SEGMENT(90 0, 0 -90)", "SEGMENT(89 -45, 91 -45)", + great_elliptic('i', "POINT(90 -45.00436354465514)"), + geodesic_vincenty('i', "POINT(90.00000000000112 -45.00437824795338)"), + geodesic_thomas('i', "POINT(90.00000000472062 -45.00437824797395)"), + geodesic_andoyer('i', "POINT(89.99999993672924 -45.00437824794587)"));*/ +} + +template <typename T> +void test_geographic_radian() +{ + typedef bg::model::point<T, 2, bg::cs::geographic<bg::radian> > point_t; + typedef bg::model::segment<point_t> segment_t; + + bg::strategy::intersection::geographic_segments<bg::strategy::vincenty> strategy; + + // https://github.com/boostorg/geometry/issues/470 + point_t p0(0.000000001, 0.000000001); + point_t p1(0.000000001, 0.000000005); + point_t p2(0.000000005, 0.000000005); + segment_t s1(p0, p1); + segment_t s2(p1, p2); + test_strategy_one(s1, s1, strategy, 'e', 2, p0, p1); + test_strategy_one(s2, s2, strategy, 'e', 2, p1, p2); +} + +int test_main(int, char* []) +{ + //test_geographic<float>(); + test_geographic<double>(); + + test_geographic_radian<double>(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/segment_intersection_geo.hpp b/src/boost/libs/geometry/test/strategies/segment_intersection_geo.hpp new file mode 100644 index 00000000..4cfb571e --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/segment_intersection_geo.hpp @@ -0,0 +1,270 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. + +// Copyright (c) 2016, Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_GEO_HPP +#define BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_GEO_HPP + + +#include "segment_intersection_sph.hpp" + +#include <boost/geometry/strategies/geographic/intersection.hpp> +#include <boost/geometry/strategies/geographic/intersection_elliptic.hpp> + + +template <typename S, typename P> +void test_default_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + typename bg::strategy::intersection::services::default_strategy + < + bg::geographic_tag + >::type strategy; + + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id); +} + +template <typename S, typename P> +void test_great_elliptic(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + bg::strategy::intersection::great_elliptic_segments<> strategy; + + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id); +} +/* +template <typename S, typename P> +void test_experimental_elliptic(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + bg::strategy::intersection::experimental_elliptic_segments<> strategy; + + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id); +} +*/ +template <typename S, typename P> +void test_geodesic_vincenty(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + bg::strategy::intersection::geographic_segments<bg::strategy::vincenty, 4> strategy; + + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id); +} + +template <typename S, typename P> +void test_geodesic_thomas(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + bg::strategy::intersection::geographic_segments<bg::strategy::thomas, 2> strategy; + + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id); +} + +template <typename S, typename P> +void test_geodesic_andoyer(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + bg::strategy::intersection::geographic_segments<bg::strategy::andoyer, 1> strategy; + + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id); +} + + +struct strategy_base +{ + strategy_base(char m_) + : m(m_), expected_count(0), opposite(-1) + {} + strategy_base(char m_, std::string const& wkt1_) + : m(m_), expected_count(1), wkt1(wkt1_), opposite(-1) + {} + strategy_base(char m_, std::string const& wkt1_, std::string const& wkt2_, bool opposite_) + : m(m_), expected_count(1), wkt1(wkt1_), wkt2(wkt2_), opposite(opposite_ ? 1 : 0) + {} + + char m; + std::size_t expected_count; + std::string wkt1, wkt2; + int opposite; +}; +struct strategy_default : strategy_base +{ + strategy_default(char m) + : strategy_base(m) + {} + strategy_default(char m, std::string const& wkt1) + : strategy_base(m, wkt1) + {} + strategy_default(char m, std::string const& wkt1, std::string const& wkt2, bool opposite) + : strategy_base(m, wkt1, wkt2, opposite) + {} +}; +struct geodesic_vincenty : strategy_base +{ + geodesic_vincenty(char m) + : strategy_base(m) + {} + geodesic_vincenty(char m, std::string const& wkt1) + : strategy_base(m, wkt1) + {} + geodesic_vincenty(char m, std::string const& wkt1, std::string const& wkt2, bool opposite) + : strategy_base(m, wkt1, wkt2, opposite) + {} +}; +struct geodesic_thomas : strategy_base +{ + geodesic_thomas(char m) + : strategy_base(m) + {} + geodesic_thomas(char m, std::string const& wkt1) + : strategy_base(m, wkt1) + {} + geodesic_thomas(char m, std::string const& wkt1, std::string const& wkt2, bool opposite) + : strategy_base(m, wkt1, wkt2, opposite) + {} +}; +struct geodesic_andoyer : strategy_base +{ + geodesic_andoyer(char m) + : strategy_base(m) + {} + geodesic_andoyer(char m, std::string const& wkt1) + : strategy_base(m, wkt1) + {} + geodesic_andoyer(char m, std::string const& wkt1, std::string const& wkt2, bool opposite) + : strategy_base(m, wkt1, wkt2, opposite) + {} +}; +struct great_elliptic : strategy_base +{ + great_elliptic(char m) + : strategy_base(m) + {} + great_elliptic(char m, std::string const& wkt1) + : strategy_base(m, wkt1) + {} + great_elliptic(char m, std::string const& wkt1, std::string const& wkt2, bool opposite) + : strategy_base(m, wkt1, wkt2, opposite) + {} +}; + + +template <typename S, typename P> +void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + strategy_default const& s) +{ + test_default_strategy<S, P>(s1_wkt, s2_wkt, s.m, s.expected_count, s.wkt1, s.wkt2); +} + +template <typename S, typename P> +void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + great_elliptic const& s) +{ + test_great_elliptic<S, P>(s1_wkt, s2_wkt, s.m, s.expected_count, s.wkt1, s.wkt2); +} + +template <typename S, typename P> +void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + geodesic_vincenty const& s) +{ + test_geodesic_vincenty<S, P>(s1_wkt, s2_wkt, s.m, s.expected_count, s.wkt1, s.wkt2); +} + +template <typename S, typename P> +void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + geodesic_thomas const& s) +{ + test_geodesic_thomas<S, P>(s1_wkt, s2_wkt, s.m, s.expected_count, s.wkt1, s.wkt2); +} + +template <typename S, typename P> +void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + geodesic_andoyer const& s) +{ + test_geodesic_andoyer<S, P>(s1_wkt, s2_wkt, s.m, s.expected_count, s.wkt1, s.wkt2); +} + + +template <typename S, typename P, typename SR1> +void test_strategies(std::string const& s1_wkt, std::string const& s2_wkt, + SR1 const& sr1) +{ + test_strategy<S, P>(s1_wkt, s2_wkt, sr1); +} +template <typename S, typename P, typename SR1, typename SR2> +void test_strategies(std::string const& s1_wkt, std::string const& s2_wkt, + SR1 const& sr1, SR2 const& sr2) +{ + test_strategy<S, P>(s1_wkt, s2_wkt, sr1); + test_strategy<S, P>(s1_wkt, s2_wkt, sr2); +} +template <typename S, typename P, typename SR1, typename SR2, typename SR3> +void test_strategies(std::string const& s1_wkt, std::string const& s2_wkt, + SR1 const& sr1, SR2 const& sr2, SR3 const& sr3) +{ + test_strategy<S, P>(s1_wkt, s2_wkt, sr1); + test_strategy<S, P>(s1_wkt, s2_wkt, sr2); + test_strategy<S, P>(s1_wkt, s2_wkt, sr3); +} +template <typename S, typename P, typename SR1, typename SR2, typename SR3, typename SR4> +void test_strategies(std::string const& s1_wkt, std::string const& s2_wkt, + SR1 const& sr1, SR2 const& sr2, SR3 const& sr3, SR4 const& sr4) +{ + test_strategy<S, P>(s1_wkt, s2_wkt, sr1); + test_strategy<S, P>(s1_wkt, s2_wkt, sr2); + test_strategy<S, P>(s1_wkt, s2_wkt, sr3); + test_strategy<S, P>(s1_wkt, s2_wkt, sr4); +} + + +template <typename S, typename P> +void test_all_strategies(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::string const& ip0_wkt = "") +{ + std::size_t expected_count = ip0_wkt.empty() ? 0 : 1; + + test_default_strategy<S, P>(s1_wkt, s2_wkt, m, expected_count, ip0_wkt); + test_great_elliptic<S, P>(s1_wkt, s2_wkt, m, expected_count, ip0_wkt); + //test_experimental_elliptic<S, P>(s1_wkt, s2_wkt, m, expected_count, ip0_wkt); + test_geodesic_vincenty<S, P>(s1_wkt, s2_wkt, m, expected_count, ip0_wkt); + test_geodesic_thomas<S, P>(s1_wkt, s2_wkt, m, expected_count, ip0_wkt); + test_geodesic_andoyer<S, P>(s1_wkt, s2_wkt, m, expected_count, ip0_wkt); +} + +template <typename S, typename P> +void test_all_strategies(std::string const& s1_wkt, std::string const& s2_wkt, + char m, + std::string const& ip0_wkt, std::string const& ip1_wkt, + bool opposite) +{ + int opposite_id = opposite ? 1 : 0; + + test_default_strategy<S, P>(s1_wkt, s2_wkt, m, 2, ip0_wkt, ip1_wkt, opposite_id); + test_great_elliptic<S, P>(s1_wkt, s2_wkt, m, 2, ip0_wkt, ip1_wkt, opposite_id); + //test_experimental_elliptic<S, P>(s1_wkt, s2_wkt, m, 2, ip0_wkt, ip1_wkt, opposite_id); + test_geodesic_vincenty<S, P>(s1_wkt, s2_wkt, m, 2, ip0_wkt, ip1_wkt, opposite_id); + test_geodesic_thomas<S, P>(s1_wkt, s2_wkt, m, 2, ip0_wkt, ip1_wkt, opposite_id); + test_geodesic_andoyer<S, P>(s1_wkt, s2_wkt, m, 2, ip0_wkt, ip1_wkt, opposite_id); +} + +#endif // BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_GEO_HPP diff --git a/src/boost/libs/geometry/test/strategies/segment_intersection_sph.cpp b/src/boost/libs/geometry/test/strategies/segment_intersection_sph.cpp new file mode 100644 index 00000000..37a2af24 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/segment_intersection_sph.cpp @@ -0,0 +1,299 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2016-2018, 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) + + +#define BOOST_GEOMETRY_TEST_GEO_INTERSECTION_TEST_SIMILAR +#include "segment_intersection_sph.hpp" + + +#include <boost/geometry/strategies/spherical/intersection.hpp> + + +template <typename S, typename P> +void test_spherical_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "") +{ + bg::strategy::intersection::spherical_segments<> strategy; + + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt); +} + +template <typename T> +void test_spherical() +{ + typedef bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > point_t; + typedef bg::model::segment<point_t> segment_t; + + // crossing X + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(-45 45, 45 -45)", 'i', 1, "POINT(0 0)"); + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(45 -45, -45 45)", 'i', 1, "POINT(0 0)"); + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(45 45, -45 -45)", "SEGMENT(-45 45, 45 -45)", 'i', 1, "POINT(0 0)"); + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(45 45, -45 -45)", "SEGMENT(45 -45, -45 45)", 'i', 1, "POINT(0 0)"); + // crossing X + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 1, 1 -1)", 'i', 1, "POINT(0 0)"); + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(1 -1, -1 1)", 'i', 1, "POINT(0 0)"); + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(1 1, -1 -1)", "SEGMENT(-1 1, 1 -1)", 'i', 1, "POINT(0 0)"); + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(1 1, -1 -1)", "SEGMENT(1 -1, -1 1)", 'i', 1, "POINT(0 0)"); + + // equal + // // + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(-45 -45, 45 45)", 'e', 2, "POINT(-45 -45)", "POINT(45 45)"); + // // + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-45 -45, 45 45)", "SEGMENT(45 45, -45 -45)", 'e', 2, "POINT(-45 -45)", "POINT(45 45)"); + + // starting outside s1 + // / + // | + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, -1 -1)", 'a', 1, "POINT(-1 -1)"); + // / + // /| + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, 0 0)", 'm', 1, "POINT(0 0)"); + // /| + // / | + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, 1 1)", 't', 1, "POINT(1 1)"); + // |/ + // /| + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, 2 2)", 'i', 1, "POINT(0 0)"); + // ------ + // ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, -1 0)", 'a', 1, "POINT(-1 0)"); + // ------ + // ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, 0 0)", 'c', 2, "POINT(-1 0)", "POINT(0 0)"); + // ------ + // --------- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, 1 0)", 'c', 2, "POINT(-1 0)", "POINT(1 0)"); + // ------ + // ------------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, 2 0)", 'c', 2, "POINT(-1 0)", "POINT(1 0)"); + + // starting at s1 + // / + // // + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, 0 0)", 'c', 2, "POINT(-1 -1)", "POINT(0 0)"); + // // + // // + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, 1 1)", 'e', 2, "POINT(-1 -1)", "POINT(1 1)"); + // | / + // |/ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, 2 2)", 'f', 1, "POINT(-1 -1)"); + // ------ + // --- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, 0 0)", 'c', 2, "POINT(-1 0)", "POINT(0 0)"); + // ------ + // ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, 1 0)", 'e', 2, "POINT(-1 0)", "POINT(1 0)"); + // ------ + // --------- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, 2 0)", 'c', 2, "POINT(-1 0)", "POINT(1 0)"); + + // starting inside + // // + // / + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(0 0, 1 1)", 'c', 2, "POINT(0 0)", "POINT(1 1)"); + // |/ + // / + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(0 0, 2 2)", 's', 1, "POINT(0 0)"); + // ------ + // --- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(0 0, 1 0)", 'c', 2, "POINT(0 0)", "POINT(1 0)"); + // ------ + // ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(0 0, 2 0)", 'c', 2, "POINT(0 0)", "POINT(1 0)"); + + // starting at p2 + // | + // / + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(1 1, 2 2)", 'a', 1, "POINT(1 1)"); + // ------ + // --- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(1 0, 2 0)", 'a', 1, "POINT(1 0)"); + + // disjoint, crossing + // / + // | + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-3 -3, -2 -2)", 'd', 0); + // | + // / + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(2 2, 3 3)", 'd', 0); + // disjoint, collinear + // ------ + // ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-3 0, -2 0)", 'd', 0); + // ------ + // ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(2 0, 3 0)", 'd', 0); + + // degenerated + // / + // * + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-2 -2, -2 -2)", 'd', 0); + // / + // * + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(-1 -1, -1 -1)", '0', 1, "POINT(-1 -1)"); + // / + // * + // / + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(0 0, 0 0)", '0', 1, "POINT(0 0)"); + // * + // / + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(1 1, 1 1)", '0', 1, "POINT(1 1)"); + // * + // / + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 -1, 1 1)", "SEGMENT(2 2, 2 2)", 'd', 0); + // similar to above, collinear + // * ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-2 0, -2 0)", 'd', 0); + // *------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(-1 0, -1 0)", '0', 1, "POINT(-1 0)"); + // ---*--- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(0 0, 0 0)", '0', 1, "POINT(0 0)"); + // ------* + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(1 0, 1 0)", '0', 1, "POINT(1 0)"); + // ------ * + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 0, 1 0)", "SEGMENT(2 0, 2 0)", 'd', 0); + + // Northern hemisphere + // --- ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-3 50, -2 50)", 'd', 0); + // ------ + // --- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, -1 50)", 'a', 1, "POINT(-1 50)"); + // \/ + // /\ (avoid multi-line comment) + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, 0 50)", 'i', 1, "POINT(-0.5 50.0032229484023)"); + // ________ + // / _____\ (avoid multi-line comment) + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, 1 50)", 't', 1, "POINT(1 50)"); + // _________ + // / _____ \ (avoid multi-line comment) + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-2 50, 2 50)", 'd', 0); + // ______ + // /___ \ (avoid multi-line comment) + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-1 50, 0 50)", 'f', 1, "POINT(-1 50)"); + // ------ + // ------ + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-1 50, 1 50)", 'e', 2, "POINT(-1 50)", "POINT(1 50)"); + // ________ + // /_____ \ (avoid multi-line comment) + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(-1 50, 2 50)", 'f', 1, "POINT(-1 50)"); + // ______ + // / ___\ (avoid multi-line comment) + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(0 50, 1 50)", 't', 1, "POINT(1 50)"); + // \/ + // /\ (avoid multi-line comment) + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(0 50, 2 50)", 'i', 1, "POINT(0.5 50.0032229484023)"); + // ------ + // --- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(1 50, 2 50)", 'a', 1, "POINT(1 50)"); + // ------ --- + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(-1 50, 1 50)", "SEGMENT(2 50, 3 50)", 'd', 0); + + // ___| + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(0 0, 1 0)", "SEGMENT(1 0, 1 1)", 'a', 1, "POINT(1 0)"); + // ___| + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(1 0, 1 1)", "SEGMENT(0 0, 1 0)", 'a', 1, "POINT(1 0)"); + + // |/ + // /| + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(10 -1, 20 1)", "SEGMENT(12.5 -1, 12.5 1)", 'i', 1, "POINT(12.5 -0.50051443471392)"); + // |/ + // /| + test_spherical_strategy<segment_t, point_t>( + "SEGMENT(10 -1, 20 1)", "SEGMENT(17.5 -1, 17.5 1)", 'i', 1, "POINT(17.5 0.50051443471392)"); +} + +template <typename T> +void test_spherical_radian() +{ + typedef bg::model::point<T, 2, bg::cs::spherical_equatorial<bg::radian> > point_t; + typedef bg::model::segment<point_t> segment_t; + + bg::strategy::intersection::spherical_segments<> strategy; + + // https://github.com/boostorg/geometry/issues/470 + point_t p0(0.00001, 0.00001); + point_t p1(0.00001, 0.00005); + point_t p2(0.00005, 0.00005); + segment_t s1(p0, p1); + segment_t s2(p1, p2); + test_strategy_one(s1, s1, strategy, 'e', 2, p0, p1); + test_strategy_one(s2, s2, strategy, 'e', 2, p1, p2); +} + +int test_main(int, char* []) +{ + //test_spherical<float>(); + test_spherical<double>(); + + test_spherical_radian<double>(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/segment_intersection_sph.hpp b/src/boost/libs/geometry/test/strategies/segment_intersection_sph.hpp new file mode 100644 index 00000000..687d3402 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/segment_intersection_sph.hpp @@ -0,0 +1,221 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2016-2018, Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_SPH_HPP +#define BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_SPH_HPP + + +#include <geometry_test_common.hpp> + +#include <boost/geometry/algorithms/equals.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/segment.hpp> + +#include <boost/geometry/io/wkt/read.hpp> +#include <boost/geometry/io/wkt/write.hpp> + +#include <boost/geometry/policies/relate/direction.hpp> +#include <boost/geometry/policies/relate/intersection_points.hpp> +#include <boost/geometry/policies/relate/tupled.hpp> + +#include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp> + +template <typename T> +bool equals_relaxed_val(T const& v1, T const& v2, T const& eps_scale) +{ + T const c1 = 1; + T relaxed_eps = std::numeric_limits<T>::epsilon() + * bg::math::detail::greatest(c1, bg::math::abs(v1), bg::math::abs(v2)) + * eps_scale; + return bg::math::abs(v1 - v2) <= relaxed_eps; +} + +template <typename P1, typename P2, typename T> +bool equals_relaxed(P1 const& p1, P2 const& p2, T const& eps_scale) +{ + typedef typename bg::select_coordinate_type<P1, P2>::type calc_t; + calc_t c1 = 1; + calc_t p10 = bg::get<0>(p1); + calc_t p11 = bg::get<1>(p1); + calc_t p20 = bg::get<0>(p2); + calc_t p21 = bg::get<1>(p2); + calc_t relaxed_eps = std::numeric_limits<calc_t>::epsilon() + * bg::math::detail::greatest(c1, bg::math::abs(p10), bg::math::abs(p11), bg::math::abs(p20), bg::math::abs(p21)) + * eps_scale; + calc_t diff0 = p10 - p20; + // needed e.g. for -179.999999 - 180.0 + if (diff0 < -180) + diff0 += 360; + return bg::math::abs(diff0) <= relaxed_eps + && bg::math::abs(p11 - p21) <= relaxed_eps; +} + +template <typename S1, typename S2, typename Strategy, typename P> +void test_strategy_one(S1 const& s1, S2 const& s2, + Strategy const& strategy, + char m, std::size_t expected_count, + P const& ip0 = P(), P const& ip1 = P(), + int opposite_id = -1) +{ + typedef typename bg::coordinate_type<P>::type coord_t; + typedef bg::policies::relate::segments_tupled + < + bg::policies::relate::segments_intersection_points + < + bg::segment_intersection_points<P, bg::segment_ratio<coord_t> > + >, + bg::policies::relate::segments_direction + > policy_t; + + typedef typename policy_t::return_type return_type; + + bg::detail::segment_as_subrange<S1> sr1(s1); + bg::detail::segment_as_subrange<S2> sr2(s2); + + return_type res = strategy.apply(sr1, sr2, policy_t()); + + size_t const res_count = boost::get<0>(res).count; + char const res_method = boost::get<1>(res).how; + + BOOST_CHECK_MESSAGE(res_method == m, + "IP method: " << res_method << " different than expected: " << m + << " for " << bg::wkt(s1) << " and " << bg::wkt(s2)); + + BOOST_CHECK_MESSAGE(res_count == expected_count, + "IP count: " << res_count << " different than expected: " << expected_count + << " for " << bg::wkt(s1) << " and " << bg::wkt(s2)); + + // The EPS is scaled because during the conversion various angles may be not converted + // to cartesian 3d the same way which results in a different intersection point + // For more information read the info in spherical intersection strategy file. + + // Plus in geographic CS the result strongly depends on the compiler, + // probably due to differences in FP trigonometric function implementations + + int eps_scale = 1; + bool is_geographic = boost::is_same<typename bg::cs_tag<S1>::type, bg::geographic_tag>::value; + if (is_geographic) + { + eps_scale = 100000; + } + else + { + eps_scale = res_method != 'i' ? 1 : 1000; + } + + if (res_count > 0 && expected_count > 0) + { + P const& res_i0 = boost::get<0>(res).intersections[0]; + coord_t denom_a0 = boost::get<0>(res).fractions[0].robust_ra.denominator(); + coord_t denom_b0 = boost::get<0>(res).fractions[0].robust_rb.denominator(); + BOOST_CHECK_MESSAGE(equals_relaxed(res_i0, ip0, eps_scale), + "IP0: " << std::setprecision(16) << bg::wkt(res_i0) << " different than expected: " << bg::wkt(ip0) + << " for " << bg::wkt(s1) << " and " << bg::wkt(s2)); + BOOST_CHECK_MESSAGE(denom_a0 > coord_t(0), + "IP0 fraction A denominator: " << std::setprecision(16) << denom_a0 << " is incorrect"); + BOOST_CHECK_MESSAGE(denom_b0 > coord_t(0), + "IP0 fraction B denominator: " << std::setprecision(16) << denom_b0 << " is incorrect"); + } + if (res_count > 1 && expected_count > 1) + { + P const& res_i1 = boost::get<0>(res).intersections[1]; + coord_t denom_a1 = boost::get<0>(res).fractions[1].robust_ra.denominator(); + coord_t denom_b1 = boost::get<0>(res).fractions[1].robust_rb.denominator(); + BOOST_CHECK_MESSAGE(equals_relaxed(res_i1, ip1, eps_scale), + "IP1: " << std::setprecision(16) << bg::wkt(res_i1) << " different than expected: " << bg::wkt(ip1) + << " for " << bg::wkt(s1) << " and " << bg::wkt(s2)); + BOOST_CHECK_MESSAGE(denom_a1 > coord_t(0), + "IP1 fraction A denominator: " << std::setprecision(16) << denom_a1 << " is incorrect"); + BOOST_CHECK_MESSAGE(denom_b1 > coord_t(0), + "IP1 fraction B denominator: " << std::setprecision(16) << denom_b1 << " is incorrect"); + } + + if (opposite_id >= 0) + { + bool opposite = opposite_id != 0; + BOOST_CHECK_MESSAGE(opposite == boost::get<1>(res).opposite, + bg::wkt(s1) << " and " << bg::wkt(s2) << (opposite_id == 0 ? " are not " : " are ") << "opposite" ); + } +} + +template <typename T> +T translated(T v, double t) +{ + v += T(t); + if (v > 180) + v -= 360; + return v; +} + +template <typename S1, typename S2, typename Strategy, typename P> +void test_strategy(S1 const& s1, S2 const& s2, + Strategy const& strategy, + char m, std::size_t expected_count, + P const& ip0 = P(), P const& ip1 = P(), + int opposite_id = -1) +{ + S1 s1t = s1; + S2 s2t = s2; + P ip0t = ip0; + P ip1t = ip1; + +#ifndef BOOST_GEOMETRY_TEST_GEO_INTERSECTION_TEST_SIMILAR + test_strategy_one(s1t, s2t, strategy, m, expected_count, ip0t, ip1t, opposite_id); +#else + double t = 0; + for (int i = 0; i < 4; ++i, t += 90) + { + bg::set<0, 0>(s1t, translated(bg::get<0, 0>(s1), t)); + bg::set<1, 0>(s1t, translated(bg::get<1, 0>(s1), t)); + bg::set<0, 0>(s2t, translated(bg::get<0, 0>(s2), t)); + bg::set<1, 0>(s2t, translated(bg::get<1, 0>(s2), t)); + if (expected_count > 0) + bg::set<0>(ip0t, translated(bg::get<0>(ip0), t)); + if (expected_count > 1) + bg::set<0>(ip1t, translated(bg::get<0>(ip1), t)); + + test_strategy_one(s1t, s2t, strategy, m, expected_count, ip0t, ip1t, opposite_id); + } +#endif +} + +template <typename S1, typename S2, typename P, typename Strategy> +void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + Strategy const& strategy, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + S1 s1; + S2 s2; + P ip0, ip1; + + bg::read_wkt(s1_wkt, s1); + bg::read_wkt(s2_wkt, s2); + if (! ip0_wkt.empty()) + bg::read_wkt(ip0_wkt, ip0); + if (!ip1_wkt.empty()) + bg::read_wkt(ip1_wkt, ip1); + + test_strategy(s1, s2, strategy, m, expected_count, ip0, ip1, opposite_id); +} + +template <typename S, typename P, typename Strategy> +void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt, + Strategy const& strategy, + char m, std::size_t expected_count, + std::string const& ip0_wkt = "", std::string const& ip1_wkt = "", + int opposite_id = -1) +{ + test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id); +} + +#endif // BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_SPH_HPP diff --git a/src/boost/libs/geometry/test/strategies/side_of_intersection.cpp b/src/boost/libs/geometry/test/strategies/side_of_intersection.cpp new file mode 100644 index 00000000..b42270e3 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/side_of_intersection.cpp @@ -0,0 +1,108 @@ +// 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<boost::long_long_type> point; + typedef bg::model::segment<point> segment; + + typedef bg::strategy::side::side_of_intersection side; + + point no_fb(-99, -99); + + 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)); + + + BOOST_CHECK_EQUAL( 1, side::apply(a, b1, c1, no_fb)); + BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c2, no_fb)); + BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c3, no_fb)); + + BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c1, no_fb)); + BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c2, no_fb)); + BOOST_CHECK_EQUAL( 0, side::apply(a, b2, c3, no_fb)); + + // Collinear cases + // 1: segments intersecting are collinear (with a fallback point): + { + point fb(5, 5); + segment col1(point(0, 5), point(5, 5)); + segment col2(point(5, 5), point(10, 5)); // One IP with col1 at (5,5) + segment col3(point(5, 0), point(5, 5)); + BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb)); + } + // 2: segment of side calculation collinear with one of the segments + { + point fb(5, 5); + segment col1(point(0, 5), point(10, 5)); + segment col2(point(5, 5), point(5, 12)); // IP with col1 at (5,5) + segment col3(point(5, 1), point(5, 5)); // collinear with col2 + BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb)); + } + { + point fb(5, 5); + segment col1(point(10, 5), point(0, 5)); + segment col2(point(5, 5), point(5, 12)); // IP with col1 at (5,5) + segment col3(point(5, 1), point(5, 5)); // collinear with col2 + BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb)); + } + { + point fb(5, 5); + segment col1(point(0, 5), point(10, 5)); + segment col2(point(5, 12), point(5, 5)); // IP with col1 at (5,5) + segment col3(point(5, 1), point(5, 5)); // collinear with col2 + BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb)); + } + + { + point fb(517248, -517236); + segment col1(point(-172408, -517236), point(862076, -517236)); + segment col2(point(517248, -862064), point(517248, -172408)); + segment col3(point(517248, -172408), point(517248, -517236)); + BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb)); + } + { + point fb(-221647, -830336); + segment col1(point(-153817, -837972), point(-222457, -830244)); + segment col2(point(-221139, -833615), point(-290654, -384388)); + segment col3(point(-255266, -814663), point(-264389, -811197)); + BOOST_CHECK_EQUAL(1, side::apply(col1, col2, col3, fb)); // Left of segment... + } + + + { + point fb(27671131, 30809240); + segment col1(point(27671116, 30809247), point(27675474, 30807351)); + segment col2(point(27666779, 30811130), point(27671139, 30809237)); + segment col3(point(27671122, 30809244), point(27675480, 30807348)); + BOOST_CHECK_EQUAL(1, side::apply(col1, col2, col3, fb)); // Left of segment... + } + + // 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/src/boost/libs/geometry/test/strategies/spherical_side.cpp b/src/boost/libs/geometry/test/strategies/spherical_side.cpp new file mode 100644 index 00000000..b834e016 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/spherical_side.cpp @@ -0,0 +1,173 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// 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/algorithms/assign.hpp> + +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/segment.hpp> + +#include <boost/geometry/strategies/spherical/side_by_cross_track.hpp> +//#include <boost/geometry/strategies/spherical/side_via_plane.hpp> +#include <boost/geometry/strategies/spherical/ssf.hpp> +#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp> + +#include <boost/geometry/strategies/geographic/mapping_ssf.hpp> +#include <boost/geometry/strategies/geographic/side_andoyer.hpp> +#include <boost/geometry/strategies/geographic/side_thomas.hpp> +#include <boost/geometry/strategies/geographic/side_vincenty.hpp> + +#include <boost/geometry/util/math.hpp> + + +namespace boost { namespace geometry { + +template <typename Vector, typename Point1, typename Point2> +static inline Vector create_vector(Point1 const& p1, Point2 const& p2) +{ + Vector v; + convert(p1, v); + subtract_point(v, p2); + return v; +} + +}} + +inline char side_char(int side) +{ + return side == 1 ? 'L' + : side == -1 ? 'R' + : '-' + ; +} + +template <typename Point> +void test_side1(std::string const& /*case_id*/, Point const& p1, Point const& p2, Point const& p3, + int expected, int expected_cartesian) +{ + 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_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); + int side_andoyer = bgss::andoyer<spheroid>(sph).apply(p1, p2, p3); + int side_thomas = bgss::thomas<spheroid>(sph).apply(p1, p2, p3); + int side_vincenty = bgss::vincenty<spheroid>(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_mssf1, expected); + BOOST_CHECK_EQUAL(side_mssf2, expected); + BOOST_CHECK_EQUAL(side_mssf3, expected); + BOOST_CHECK_EQUAL(side_andoyer, expected); + BOOST_CHECK_EQUAL(side_thomas, expected); + BOOST_CHECK_EQUAL(side_vincenty, expected); + BOOST_CHECK_EQUAL(side_cart, expected_cartesian); + + /* + std::cout + << "exp: " << side_char(expected) + << " ssf: " << side_char(side1) + << " pln: " << side_char(side2) + << " ct: " << side_char(side3) + //<< " def: " << side_char(side4) + << " cart: " << side_char(side5) + << std::endl; + */ +} + +template <typename Point> +void test_side(std::string const& case_id, Point const& p1, Point const& p2, Point const& p3, + int expected, int expected_cartesian = -999) +{ + if (expected_cartesian == -999) + { + expected_cartesian = expected; + } + test_side1(case_id, p1, p2, p3, expected, expected_cartesian); + test_side1(case_id, p2, p1, p3, -expected, -expected_cartesian); +} + + +template <typename Point> +void test_all() +{ + typedef typename bg::coordinate_type<Point>::type CT; + + Point amsterdam(bg::math::rounding_cast<CT>(5.9), bg::math::rounding_cast<CT>(52.4)); + Point barcelona(2.0, 41.0); + Point paris(2.0, 48.0); + Point milan(7.0, 45.0); + + //goto wrong; + + test_side<Point>("bp-m", barcelona, paris, milan, -1); + test_side<Point>("bm-p", barcelona, milan, paris, 1); + test_side<Point>("mp-b", milan, paris, barcelona, 1); + + test_side<Point>("am-p", amsterdam, milan, paris, -1); + test_side<Point>("pm-a", paris, milan, amsterdam, 1); + + // http://www.gcmap.com/mapui?P=30N+10E-50N+50E,39N+30E + Point gcmap_p1(10.0, 30.0); + Point gcmap_p2(50.0, 50.0); + test_side<Point>("blog1", gcmap_p1, gcmap_p2, Point(30.0, 41.0), -1, 1); + test_side<Point>("blog1", gcmap_p1, gcmap_p2, Point(30.0, 42.0), -1, 1); + test_side<Point>("blog1", gcmap_p1, gcmap_p2, Point(30.0, 43.0), -1, 1); + test_side<Point>("blog1", gcmap_p1, gcmap_p2, Point(30.0, 44.0), 1); + + // http://www.gcmap.com/mapui?P=50N+80E-60N+50W,65N+30E + Point gcmap_np1(80.0, 50.0); + Point gcmap_np2(-50.0, 60.0); + // http://www.gcmap.com/mapui?P=50N+140E-60N+10E,65N+30E + //Point gcmap_np1(140.0, 50.0); + //Point gcmap_np2(10.0, 60.0); + //test_side<Point>(gcmap_np1, gcmap_np2, gcmap_np, 1); + test_side<Point>("40", gcmap_np1, gcmap_np2, Point(30.0, 60.0), 1, -1); + test_side<Point>("45", gcmap_np1, gcmap_np2, Point(30.0, 65.0), 1, -1); + test_side<Point>("70", gcmap_np1, gcmap_np2, Point(30.0, 70.0), 1, -1); + test_side<Point>("75", gcmap_np1, gcmap_np2, Point(30.0, 75.0), -1); +} + +int test_main(int, char* []) +{ + test_all<bg::model::point<int, 2, bg::cs::spherical<bg::degree> > >(); + test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >(); + +#if defined(HAVE_TTMATH) + typedef ttmath::Big<1,4> tt; + test_all<bg::model::point<tt, 2, bg::cs::spherical_equatorial<bg::degree> > >(); +#endif + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/test_projected_point.hpp b/src/boost/libs/geometry/test/strategies/test_projected_point.hpp new file mode 100644 index 00000000..72a0d906 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/test_projected_point.hpp @@ -0,0 +1,185 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_STRATEGIES_TEST_PROJECTED_POINT_HPP +#define BOOST_GEOMETRY_TEST_STRATEGIES_TEST_PROJECTED_POINT_HPP + +#include <geometry_test_common.hpp> + +#include <boost/core/ignore_unused.hpp> + +#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp> +#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp> +#include <boost/geometry/strategies/concepts/distance_concept.hpp> + +#include <boost/geometry/io/wkt/read.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/adapted/c_array.hpp> +#include <boost/geometry/geometries/adapted/boost_tuple.hpp> +#include <test_common/test_point.hpp> + +#ifdef HAVE_TTMATH +# include <boost/geometry/extensions/contrib/ttmath_stub.hpp> +#endif + +BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + + +template <typename P, typename PS, typename CalculationType> +void test_services() +{ + PS p1, p2; + bg::assign_values(p1, 0, 0); + bg::assign_values(p2, 0, 4); + + P p; + bg::assign_values(p, 2, 0); + + CalculationType const sqr_expected = 4; + CalculationType const expected = 2; + + + namespace bgsd = bg::strategy::distance; + namespace services = bg::strategy::distance::services; + + { + // compile-check if there is a strategy for this type + typedef typename services::default_strategy + < + bg::point_tag, bg::segment_tag, P, PS + >::type projected_point_strategy_type; + + typedef typename services::default_strategy + < + bg::segment_tag, bg::point_tag, PS, P + >::type reversed_tags_projected_point_strategy_type; + + boost::ignore_unused<projected_point_strategy_type, + reversed_tags_projected_point_strategy_type>(); + } + + // 1: normal, calculate distance: + + typedef bgsd::projected_point<CalculationType> strategy_type; + + BOOST_CONCEPT_ASSERT( (bg::concepts::PointSegmentDistanceStrategy<strategy_type, P, PS>) ); + + typedef typename services::return_type<strategy_type, P, PS>::type return_type; + + strategy_type strategy; + return_type result = strategy.apply(p, p1, p2); + BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + // 2: the strategy should return the same result if we reverse parameters + result = strategy.apply(p, p2, p1); + BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); + + + // 3: "comparable" to construct a "comparable strategy" for P1/P2 + // a "comparable strategy" is a strategy which does not calculate the exact distance, but + // which returns results which can be mutually compared (e.g. avoid sqrt) + + // 3a: "comparable_type" + typedef typename services::comparable_type<strategy_type>::type comparable_type; + + // 3b: "get_comparable" + comparable_type comparable = bgsd::services::get_comparable<strategy_type>::apply(strategy); + + return_type c_result = comparable.apply(p, p1, p2); + BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001); +} + +template <typename T1, typename T2> +void test_check_close(T1 const& v1, T2 const& v2, double f) +{ + BOOST_CHECK_CLOSE(v1, v2, f); +} + +template <typename T1, typename T2> +void test_check_close(bg::strategy::distance::detail::projected_point_ax_result<T1> const& v1, + bg::strategy::distance::detail::projected_point_ax_result<T2> const& v2, + double f) +{ + BOOST_CHECK_CLOSE(v1.atd, v2.atd, f); + BOOST_CHECK_CLOSE(v1.xtd, v2.xtd, f); +} + +template <typename P1, typename P2, typename T, typename Strategy, typename ComparableStrategy> +void test_2d(std::string const& wkt_p, + std::string const& wkt_sp1, + std::string const& wkt_sp2, + T expected_distance, + T expected_comparable_distance, + Strategy strategy, + ComparableStrategy comparable_strategy) +{ + P1 p; + P2 sp1, sp2; + bg::read_wkt(wkt_p, p); + bg::read_wkt(wkt_sp1, sp1); + bg::read_wkt(wkt_sp2, sp2); + + BOOST_CONCEPT_ASSERT + ( + (bg::concepts::PointSegmentDistanceStrategy<Strategy, P1, P2>) + ); + BOOST_CONCEPT_ASSERT + ( + (bg::concepts::PointSegmentDistanceStrategy<ComparableStrategy, P1, P2>) + ); + + { + typedef typename bg::strategy::distance::services::return_type<Strategy, P1, P2>::type return_type; + return_type d = strategy.apply(p, sp1, sp2); + test_check_close(d, expected_distance, 0.001); + } + + // Test combination with the comparable strategy + { + typedef typename bg::strategy::distance::services::return_type<ComparableStrategy, P1, P2>::type return_type; + return_type d = comparable_strategy.apply(p, sp1, sp2); + test_check_close(d, expected_comparable_distance, 0.01); + } + +} + +template <typename P1, typename P2, typename T> +void test_2d(std::string const& wkt_p, + std::string const& wkt_sp1, + std::string const& wkt_sp2, + T expected_distance) +{ + typedef bg::strategy::distance::projected_point<> strategy_type; + typedef bg::strategy::distance::projected_point + < + void, + bg::strategy::distance::comparable::pythagoras<> + > comparable_strategy_type; + + strategy_type strategy; + comparable_strategy_type comparable_strategy; + + T expected_squared_distance = expected_distance * expected_distance; + test_2d<P1, P2>(wkt_p, wkt_sp1, wkt_sp2, expected_distance, expected_squared_distance, strategy, comparable_strategy); +} + +#endif // BOOST_GEOMETRY_TEST_STRATEGIES_TEST_PROJECTED_POINT_HPP diff --git a/src/boost/libs/geometry/test/strategies/test_within.hpp b/src/boost/libs/geometry/test/strategies/test_within.hpp new file mode 100644 index 00000000..ae9b06dd --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/test_within.hpp @@ -0,0 +1,106 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014, 2019. +// Modifications copyright (c) 2014, 2019 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_STRATEGIES_TEST_WITHIN_HPP +#define BOOST_GEOMETRY_TEST_STRATEGIES_TEST_WITHIN_HPP + + +#include <geometry_test_common.hpp> + +#include <boost/geometry/algorithms/covered_by.hpp> +#include <boost/geometry/algorithms/within.hpp> + +#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp> +#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp> +#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp> +#include <boost/geometry/strategies/cartesian/point_in_box.hpp> +#include <boost/geometry/strategies/cartesian/box_in_box.hpp> +#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp> + +#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp> +#include <boost/geometry/strategies/spherical/ssf.hpp> + + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/box.hpp> +#include <boost/geometry/geometries/polygon.hpp> + +#include <boost/geometry/io/wkt/wkt.hpp> + + +template <typename Strategy> +inline const char * strategy_name(Strategy const&) +{ + return typeid(Strategy).name(); +} + +template <typename P, typename PoS, typename CT> +inline const char * strategy_name(bg::strategy::within::crossings_multiply<P, PoS, CT> const&) +{ + return "crossings_multiply"; +} + +template <typename P, typename PoS, typename CT> +inline const char * strategy_name(bg::strategy::within::franklin<P, PoS, CT> const&) +{ + return "franklin"; +} + +template <typename P, typename PoS, typename CT> +inline const char * strategy_name(bg::strategy::within::winding<P, PoS, CT> const&) +{ + return "winding"; +} + + +template <typename Point, typename Polygon, typename Strategy> +void test_point_in_polygon(std::string const& case_id, + Point const& point, + Polygon const& polygon, + Strategy const& strategy, + bool expected, + bool use_within = true) +{ + BOOST_CONCEPT_ASSERT( (bg::concepts::WithinStrategyPolygonal<Point, Polygon, Strategy>) ); + bool detected = use_within ? + bg::within(point, polygon, strategy) : + bg::covered_by(point, polygon, strategy); + + BOOST_CHECK_MESSAGE(detected == expected, + (use_within ? "within: " : "covered_by: ") << case_id + << " strategy: " << strategy_name(strategy) + << " output expected: " << int(expected) + << " detected: " << int(detected) + ); +} + + +template <typename Point, typename Polygon, typename Strategy> +void test_geometry(std::string const& case_id, + std::string const& wkt_point, + std::string const& wkt_polygon, + Strategy const& strategy, + bool expected, + bool use_within = true) +{ + Point point; + Polygon polygon; + bg::read_wkt(wkt_point, point); + bg::read_wkt(wkt_polygon, polygon); + + test_point_in_polygon(case_id, point, polygon, strategy, expected, use_within); +} + + +#endif // BOOST_GEOMETRY_TEST_STRATEGIES_TEST_WITHIN_HPP diff --git a/src/boost/libs/geometry/test/strategies/thomas.cpp b/src/boost/libs/geometry/test/strategies/thomas.cpp new file mode 100644 index 00000000..596b3504 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/thomas.cpp @@ -0,0 +1,153 @@ +// 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 2015, 2017. +// Modifications copyright (c) 2015-2017 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/algorithms/assign.hpp> +#include <boost/geometry/algorithms/distance.hpp> +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/srs/spheroid.hpp> +#include <boost/geometry/strategies/concepts/distance_concept.hpp> +#include <boost/geometry/strategies/geographic/distance_thomas.hpp> +#include <boost/geometry/strategies/geographic/side_thomas.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_distance(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::thomas<stype> thomas_type; + typedef bg::strategy::distance::geographic<bg::strategy::thomas, stype> geographic_type; + + BOOST_CONCEPT_ASSERT + ( + (bg::concepts::PointDistanceStrategy<thomas_type, P1, P2>) + ); + + thomas_type thomas; + geographic_type geographic; + typedef typename bg::strategy::distance + ::services::return_type<thomas_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(thomas.apply(p1, p2), return_type(1000.0 * expected_km), 0.001); + BOOST_CHECK_CLOSE(geographic.apply(p1, p2), return_type(1000.0 * expected_km), 0.001); + BOOST_CHECK_CLOSE(bg::distance(p1, p2, thomas), return_type(1000.0 * expected_km), 0.001); +} + +template <typename PS, typename P> +void test_side(double lon1, double lat1, + double lon2, double lat2, + double lon, double lat, + int expected_side) +{ + // 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::strategy::side::thomas<stype> strategy_type; + typedef bg::strategy::side::geographic<bg::strategy::thomas, stype> strategy2_type; + + strategy_type strategy; + strategy2_type strategy2; + + PS p1, p2; + P p; + + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + bg::assign_values(p, lon, lat); + + int side = strategy.apply(p1, p2, p); + int side2 = strategy2.apply(p1, p2, p); + + BOOST_CHECK_EQUAL(side, expected_side); + BOOST_CHECK_EQUAL(side2, expected_side); +} + +template <typename P1, typename P2> +void test_all() +{ + test_distance<P1, P2>(0, 90, 1, 80, 1116.825795); // polar + test_distance<P1, P2>(0, -90, 1, -80, 1116.825795); // polar + test_distance<P1, P2>(4, 52, 4, 52, 0.0); // no point difference + test_distance<P1, P2>(4, 52, 3, 40, 1336.025365); // normal case + + 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); + test_side<P1, P2>(10, 0, 10, -1, 10, 2, 0); + + test_side<P1, P2>(10, 0, 10, 1, 0, 2, 1); // left + test_side<P1, P2>(10, 0, 10, -1, 0, 2, -1); // right + + test_side<P1, P2>(-10, -10, 10, 10, 10, 0, -1); // right + test_side<P1, P2>(-10, -10, 10, 10, -10, 0, 1); // left + test_side<P1, P2>(170, -10, -170, 10, -170, 0, -1); // right + test_side<P1, P2>(170, -10, -170, 10, 170, 0, 1); // left +} + +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/src/boost/libs/geometry/test/strategies/transform_cs.cpp b/src/boost/libs/geometry/test/strategies/transform_cs.cpp new file mode 100644 index 00000000..777104ee --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/transform_cs.cpp @@ -0,0 +1,149 @@ +// 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. + +// 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/geometry/strategies/strategy_transform.hpp> +#include <boost/geometry/algorithms/transform.hpp> +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/point_xy.hpp> + +template <typename T, typename P> +inline T check_distance(P const& p) +{ + T x = bg::get<0>(p); + T y = bg::get<1>(p); + T z = bg::get<2>(p); + return sqrt(x * x + y * y + z * z); +} + +template <typename T> +void test_transformations_spherical() +{ + T const input_long = 15.0; + T const input_lat = 5.0; + + T const expected_long = 0.26179938779914943653855361527329; + T const expected_lat = 0.08726646259971647884618453842443; + + // Can be checked using http://www.calc3d.com/ejavascriptcoordcalc.html + // (for phi use long, in radians, for theta use lat, in radians, they are listed there as "theta, phi") + T const expected_polar_x = 0.084186; + T const expected_polar_y = 0.0225576; + T const expected_polar_z = 0.996195; + + // Can be checked with same URL using 90-theta for lat. + // So for theta use 85 degrees, in radians: 0.08726646259971647884618453842443 + T const expected_equatorial_x = 0.962250; + T const expected_equatorial_y = 0.257834; + T const expected_equatorial_z = 0.0871557; + + // 1: Spherical-polar (lat=5, so it is near the pole - on a unit sphere) + bg::model::point<T, 2, bg::cs::spherical<bg::degree> > sp(input_long, input_lat); + + // 1a: to radian + bg::model::point<T, 2, bg::cs::spherical<bg::radian> > spr; + bg::transform(sp, spr); + BOOST_CHECK_CLOSE(bg::get<0>(spr), expected_long, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(spr), expected_lat, 0.001); + + // 1b: to cartesian-3d + bg::model::point<T, 3, bg::cs::cartesian> pc3; + bg::transform(sp, pc3); + BOOST_CHECK_CLOSE(bg::get<0>(pc3), expected_polar_x, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(pc3), expected_polar_y, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(pc3), expected_polar_z, 0.001); + BOOST_CHECK_CLOSE(check_distance<T>(pc3), 1.0, 0.001); + + // 1c: back + bg::transform(pc3, spr); + BOOST_CHECK_CLOSE(bg::get<0>(spr), expected_long, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(spr), expected_lat, 0.001); + + // 2: Spherical-equatorial (lat=5, so it is near the equator) + bg::model::point<T, 2, bg::cs::spherical_equatorial<bg::degree> > se(input_long, input_lat); + + // 2a: to radian + bg::model::point<T, 2, bg::cs::spherical_equatorial<bg::radian> > ser; + bg::transform(se, ser); + BOOST_CHECK_CLOSE(bg::get<0>(ser), expected_long, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(ser), expected_lat, 0.001); + + bg::transform(se, pc3); + BOOST_CHECK_CLOSE(bg::get<0>(pc3), expected_equatorial_x, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(pc3), expected_equatorial_y, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(pc3), expected_equatorial_z, 0.001); + BOOST_CHECK_CLOSE(check_distance<T>(pc3), 1.0, 0.001); + + // 2c: back + bg::transform(pc3, ser); + BOOST_CHECK_CLOSE(bg::get<0>(spr), expected_long, 0.001); // expected_long + BOOST_CHECK_CLOSE(bg::get<1>(spr), expected_lat, 0.001); // expected_lat + + + // 3: Spherical-polar including radius + bg::model::point<T, 3, bg::cs::spherical<bg::degree> > sp3(input_long, input_lat, 0.5); + + // 3a: to radian + bg::model::point<T, 3, bg::cs::spherical<bg::radian> > spr3; + bg::transform(sp3, spr3); + BOOST_CHECK_CLOSE(bg::get<0>(spr3), expected_long, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(spr3), expected_lat, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(spr3), 0.5, 0.001); + + // 3b: to cartesian-3d + bg::transform(sp3, pc3); + BOOST_CHECK_CLOSE(bg::get<0>(pc3), expected_polar_x / 2.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(pc3), expected_polar_y / 2.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(pc3), expected_polar_z / 2.0, 0.001); + BOOST_CHECK_CLOSE(check_distance<T>(pc3), 0.5, 0.001); + + // 3c: back + bg::transform(pc3, spr3); + BOOST_CHECK_CLOSE(bg::get<0>(spr3), expected_long, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(spr3), expected_lat, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(spr3), 0.5, 0.001); + + + // 4: Spherical-equatorial including radius + bg::model::point<T, 3, bg::cs::spherical_equatorial<bg::degree> > se3(input_long, input_lat, 0.5); + + // 4a: to radian + bg::model::point<T, 3, bg::cs::spherical_equatorial<bg::radian> > ser3; + bg::transform(se3, ser3); + BOOST_CHECK_CLOSE(bg::get<0>(ser3), expected_long, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(ser3), expected_lat, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(ser3), 0.5, 0.001); + + // 4b: to cartesian-3d + bg::transform(se3, pc3); + BOOST_CHECK_CLOSE(bg::get<0>(pc3), expected_equatorial_x / 2.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(pc3), expected_equatorial_y / 2.0, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(pc3), expected_equatorial_z / 2.0, 0.001); + BOOST_CHECK_CLOSE(check_distance<T>(pc3), 0.5, 0.001); + + // 4c: back + bg::transform(pc3, ser3); + BOOST_CHECK_CLOSE(bg::get<0>(ser3), expected_long, 0.001); + BOOST_CHECK_CLOSE(bg::get<1>(ser3), expected_lat, 0.001); + BOOST_CHECK_CLOSE(bg::get<2>(ser3), 0.5, 0.001); +} + +int test_main(int, char* []) +{ + test_transformations_spherical<double>(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/transformer.cpp b/src/boost/libs/geometry/test/strategies/transformer.cpp new file mode 100644 index 00000000..5cdc567e --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/transformer.cpp @@ -0,0 +1,119 @@ +// 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. + +// 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/geometry/strategies/transform/inverse_transformer.hpp> +#include <boost/geometry/strategies/transform/map_transformer.hpp> +#include <boost/geometry/strategies/transform/matrix_transformers.hpp> + + +#include <boost/geometry/algorithms/make.hpp> +#include <boost/geometry/algorithms/transform.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/adapted/c_array.hpp> +#include <boost/geometry/geometries/adapted/boost_tuple.hpp> + +BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + + +template <typename P, typename T> +void check_inverse(P const& p, T const& trans) +{ + typedef typename bg::coordinate_type<P>::type coordinate_type; + const std::size_t dim = bg::dimension<P>::value; + + bg::strategy::transform::inverse_transformer<coordinate_type, dim, dim> inverse(trans); + + P i; + bg::transform(p, i, inverse); + + BOOST_CHECK_CLOSE(double(bg::get<0>(i)), 1.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(i)), 1.0, 0.001); +} + +template <typename P> +void test_all() +{ + typedef typename bg::coordinate_type<P>::type coordinate_type; + const std::size_t dim = bg::dimension<P>::value; + + P p; + bg::assign_values(p, 1, 1); + + { + bg::strategy::transform::translate_transformer<coordinate_type, dim, dim> trans(1, 1); + P tp; + bg::transform(p, tp, trans); + + BOOST_CHECK_CLOSE(double(bg::get<0>(tp)), 2.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(tp)), 2.0, 0.001); + + check_inverse(tp, trans); + } + + { + bg::strategy::transform::scale_transformer<coordinate_type, dim, dim> trans(10, 10); + P tp; + bg::transform(p, tp, trans); + + BOOST_CHECK_CLOSE(double(bg::get<0>(tp)), 10.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(tp)), 10.0, 0.001); + + check_inverse(tp, trans); + } + + { + bg::strategy::transform::rotate_transformer<bg::degree, double, dim, dim> trans(90.0); + P tp; + bg::transform(p, tp, trans); + + BOOST_CHECK_CLOSE(double(bg::get<0>(tp)), 1.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(tp)), -1.0, 0.001); + check_inverse(tp, trans); + } + + { + // Map from 0,0,2,2 to 0,0,500,500 + bg::strategy::transform::map_transformer<coordinate_type, dim, dim, false> trans + ( + 0.0, 0.0, 2.0, 2.0, 500, 500 + ); + P tp; + bg::transform(p, tp, trans); + + BOOST_CHECK_CLOSE(double(bg::get<0>(tp)), 250.0, 0.001); + BOOST_CHECK_CLOSE(double(bg::get<1>(tp)), 250.0, 0.001); + + check_inverse(tp, trans); + } +} + +int test_main(int, char* []) +{ + //test_all<int[2]>(); + //test_all<float[2]>(); + //test_all<double[2]>(); + + test_all<boost::tuple<float, float> >(); + + //test_all<point<int, 2, cs::cartesian> >(); + test_all<bg::model::point<float, 2, bg::cs::cartesian> >(); + test_all<bg::model::point<double, 2, bg::cs::cartesian> >(); + + return 0; +} diff --git a/src/boost/libs/geometry/test/strategies/vincenty.cpp b/src/boost/libs/geometry/test/strategies/vincenty.cpp new file mode 100644 index 00000000..279db467 --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/vincenty.cpp @@ -0,0 +1,330 @@ +// 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, 2015, 2016, 2017. +// Modifications copyright (c) 2014-2017 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/algorithms/assign.hpp> +#include <boost/geometry/algorithms/distance.hpp> +#include <boost/geometry/formulas/vincenty_inverse.hpp> +#include <boost/geometry/formulas/vincenty_direct.hpp> +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/srs/spheroid.hpp> +#include <boost/geometry/strategies/concepts/distance_concept.hpp> +#include <boost/geometry/strategies/geographic/distance_vincenty.hpp> +#include <boost/geometry/strategies/geographic/side_vincenty.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 + { + double const d2r = bg::math::d2r<double>(); + double const r2d = bg::math::r2d<double>(); + + typedef bg::formula::vincenty_inverse<calc_t, true, true> inverse_formula; + typename inverse_formula::result_type + result_i = inverse_formula::apply(lon1 * d2r, + lat1 * d2r, + lon2 * d2r, + lat2 * d2r, + spheroid); + calc_t dist = result_i.distance; + calc_t az12 = result_i.azimuth; + //calc_t az21 = vi.azimuth21(); + + calc_t az12_deg = az12 * r2d; + //calc_t az21_deg = az21 * 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); + + typedef bg::formula::vincenty_direct<calc_t> direct_formula; + typename direct_formula::result_type + result_d = direct_formula::apply(lon1 * d2r, + lat1 * d2r, + dist, + az12, + spheroid); + calc_t direct_lon2 = result_d.lon2; + calc_t direct_lat2 = result_d.lat2; + //calc_t direct_az21 = vd.azimuth21(); + + calc_t direct_lon2_deg = direct_lon2 * r2d; + calc_t direct_lat2_deg = direct_lat2 * r2d; + //calc_t direct_az21_deg = direct_az21 * 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); + } + + // distance strategies + { + typedef bg::strategy::distance::vincenty<Spheroid> vincenty_type; + typedef bg::strategy::distance::geographic<bg::strategy::vincenty, Spheroid> geographic_type; + + BOOST_CONCEPT_ASSERT( + ( + bg::concepts::PointDistanceStrategy<vincenty_type, P1, P2>) + ); + + vincenty_type vincenty(spheroid); + geographic_type geographic(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(geographic.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 PS, typename P> +void test_side(double lon1, double lat1, + double lon2, double lat2, + double lon, double lat, + int expected_side) +{ + // 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::strategy::side::vincenty<stype> strategy_type; + typedef bg::strategy::side::geographic<bg::strategy::vincenty, stype> strategy2_type; + + strategy_type strategy; + strategy2_type strategy2; + + PS p1, p2; + P p; + + bg::assign_values(p1, lon1, lat1); + bg::assign_values(p2, lon2, lat2); + bg::assign_values(p, lon, lat); + + int side = strategy.apply(p1, p2, p); + int side2 = strategy2.apply(p1, p2, p); + + BOOST_CHECK_EQUAL(side, expected_side); + BOOST_CHECK_EQUAL(side2, expected_side); +} + +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 + + 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); + test_side<P1, P2>(10, 0, 10, -1, 10, 2, 0); + + test_side<P1, P2>(10, 0, 10, 1, 0, 2, 1); // left + test_side<P1, P2>(10, 0, 10, -1, 0, 2, -1); // right + + test_side<P1, P2>(-10, -10, 10, 10, 10, 0, -1); // right + test_side<P1, P2>(-10, -10, 10, 10, -10, 0, 1); // left + test_side<P1, P2>(170, -10, -170, 10, -170, 0, -1); // right + test_side<P1, P2>(170, -10, -170, 10, 170, 0, 1); // left +} + +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; +} diff --git a/src/boost/libs/geometry/test/strategies/winding.cpp b/src/boost/libs/geometry/test/strategies/winding.cpp new file mode 100644 index 00000000..d19244ae --- /dev/null +++ b/src/boost/libs/geometry/test/strategies/winding.cpp @@ -0,0 +1,218 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// 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 + +// 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 <strategies/test_within.hpp> + + +template <typename Point> +void test_cartesian() +{ + typedef bg::model::polygon<Point> polygon; + + std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))"; + std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))"; + std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))"; + + bg::strategy::within::winding<Point> s; + + + test_geometry<Point, polygon>("b1", "POINT(1 1)", box, s, true); + test_geometry<Point, polygon>("b2", "POINT(3 3)", box, s, false); + + // Test ALL corners (officialy false but some strategies might answer true) + test_geometry<Point, polygon>("b3a", "POINT(0 0)", box, s, false); + test_geometry<Point, polygon>("b3b", "POINT(0 2)", box, s, false); + test_geometry<Point, polygon>("b3c", "POINT(2 2)", box, s, false); + test_geometry<Point, polygon>("b3d", "POINT(2 0)", box, s, false); + + // Test ALL sides (officialy false but some strategies might answer true) + test_geometry<Point, polygon>("b4a", "POINT(0 1)", box, s, false); + test_geometry<Point, polygon>("b4b", "POINT(1 2)", box, s, false); + test_geometry<Point, polygon>("b4c", "POINT(2 1)", box, s, false); + test_geometry<Point, polygon>("b4d", "POINT(1 0)", box, s, false); + + + test_geometry<Point, polygon>("t1", "POINT(1 1)", triangle, s, true); + test_geometry<Point, polygon>("t2", "POINT(3 3)", triangle, s, false); + + test_geometry<Point, polygon>("t3a", "POINT(0 0)", triangle, s, false); + test_geometry<Point, polygon>("t3b", "POINT(0 4)", triangle, s, false); + test_geometry<Point, polygon>("t3c", "POINT(5 0)", triangle, s, false); + + test_geometry<Point, polygon>("t4a", "POINT(0 2)", triangle, s, false); + test_geometry<Point, polygon>("t4b", "POINT(3 2)", triangle, s, false); + test_geometry<Point, polygon>("t4c", "POINT(2 0)", triangle, s, false); + + + test_geometry<Point, polygon>("h1", "POINT(0.5 0.5)", with_hole, s, true); + test_geometry<Point, polygon>("h2a", "POINT(1.5 1.5)", with_hole, s, false); + test_geometry<Point, polygon>("h2b", "POINT(5 5)", with_hole, s, false); + + test_geometry<Point, polygon>("h3a", "POINT(1 1)", with_hole, s, false); + test_geometry<Point, polygon>("h3b", "POINT(2 2)", with_hole, s, false); + test_geometry<Point, polygon>("h3c", "POINT(0 0)", with_hole, s, false); + + test_geometry<Point, polygon>("h4a", "POINT(1 1.5)", with_hole, s, false); + test_geometry<Point, polygon>("h4b", "POINT(1.5 2)", with_hole, s, false); + + // Lying ON (one of the sides of) interior ring + test_geometry<Point, polygon>("#77-1", "POINT(6 3.5)", + "POLYGON((5 3,5 4,4 4,4 5,3 5,3 6,5 6,5 5,7 5,7 6,8 6,8 5,9 5,9 2,8 2,8 1,7 1,7 2,5 2,5 3),(6 3,8 3,8 4,6 4,6 3))", + s, false); +} + +template <typename T> +void test_spherical() +{ + typedef bg::model::point<T, 2, bg::cs::spherical_equatorial<bg::degree> > point; + typedef bg::model::polygon<point> polygon; + + bg::strategy::within::winding<point> s; + + + // Ticket #9354 + test_geometry<point, polygon>( + "#9354", + "POINT(-78.1239 25.9556)", + "POLYGON((-97.08466667 25.95683333, -97.13683333 25.954, -97.1 26, -97.08466667 25.95683333))", + s, + false); + + test_geometry<point, polygon>( + "sph1N", + "POINT(0 10.001)", + "POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))", + s, + bg::strategy::side::spherical_side_formula<>::apply( + point(-10, 10), + point(10, 10), + point(0, (T)10.001)) == -1 // right side + /*true*/); + test_geometry<point, polygon>( + "sph1S", + "POINT(0 -10.001)", + "POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))", + s, + bg::strategy::side::spherical_side_formula<>::apply( + point(10, -10), + point(-10, -10), + point(0, (T)-10.001)) == -1 // right side + /*true*/); + + test_geometry<point, polygon>( + "sph2S", + "POINT(0 10.001)", + "POLYGON((-10 20, 10 20, 10 10, -10 10, -10 20))", + s, + bg::strategy::side::spherical_side_formula<>::apply( + point(10, 10), + point(-10, 10), + point(0, (T)10.001)) == -1 // right side + /*false*/); + + test_geometry<point, polygon>( + "sph3N", + "POINT(0 10)", + "POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))", + s, + bg::strategy::side::spherical_side_formula<>::apply( + point(-10, 10), + point(10, 10), + point(0, (T)10.001)) == -1 // right side + /*true*/); + test_geometry<point, polygon>( + "sph3S", + "POINT(0 -10)", + "POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))", + s, + bg::strategy::side::spherical_side_formula<>::apply( + point(10, -10), + point(-10, -10), + point(0, (T)-10.001)) == -1 // right side + /*true*/); + + test_geometry<point, polygon>( + "sphEq1", + "POINT(179 10)", + "POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))", + s, + true, + false); + test_geometry<point, polygon>( + "sphEq2", + "POINT(179 10)", + "POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))", + s, + false, + false); + test_geometry<point, polygon>( + "sphEq3", + "POINT(-179 10)", + "POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))", + s, + true, + false); + test_geometry<point, polygon>( + "sphEq4", + "POINT(-179 10)", + "POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))", + s, + false, + false); + + test_geometry<point, polygon>( + "sphEq5", + "POINT(169 10)", + "POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))", + s, + false, + false); + test_geometry<point, polygon>( + "sphEq6", + "POINT(-169 10)", + "POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))", + s, + false, + false); + test_geometry<point, polygon>( + "sphEq7", + "POINT(169 10)", + "POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))", + s, + false, + false); + test_geometry<point, polygon>( + "sphEq8", + "POINT(-169 10)", + "POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))", + s, + false, + false); +} + +int test_main(int, char* []) +{ + test_cartesian<bg::model::point<float, 2, bg::cs::cartesian> >(); + test_cartesian<bg::model::point<double, 2, bg::cs::cartesian> >(); + + test_spherical<float>(); + test_spherical<double>(); + +#if defined(HAVE_TTMATH) + test_cartesian<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >(); + test_spherical<ttmath_big>(); +#endif + + return 0; +} |