From 8aadb31dc88f5088795ab940a9ced218203846c0 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 3 Jun 2014 13:41:39 +0300 Subject: [PATCH 1/2] [test][strategies] add unit test for pythagoras point box strategy --- test/strategies/pythagoras_point_box.cpp | 491 +++++++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 test/strategies/pythagoras_point_box.cpp diff --git a/test/strategies/pythagoras_point_box.cpp b/test/strategies/pythagoras_point_box.cpp new file mode 100644 index 000000000..dfc8f453b --- /dev/null +++ b/test/strategies/pythagoras_point_box.cpp @@ -0,0 +1,491 @@ +// 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 + +#if defined(_MSC_VER) +# pragma warning( disable : 4101 ) +#endif + +#include + +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include + +#ifdef HAVE_TTMATH +# include +#endif + + +namespace bg = boost::geometry; + + +BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + + +template +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::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 +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 +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 +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 +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; + } + + 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 strategy_type; + + BOOST_CONCEPT_ASSERT + ( (bg::concept::PointDistanceStrategy) ); + + 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 point_type; + typedef bg::model::box 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 +inline void test_big_2d() +{ + test_big_2d_with + (123456.78900001, 234567.89100001, + 987654.32100001, 876543.21900001, + 0.0); +} + +template +inline void test_big_2d_string() +{ + test_big_2d_with + ("123456.78900001", "234567.89100001", + "987654.32100001", "876543.21900001", + "0.0000000000000"); +} + +template +inline void test_integer(bool check_types) +{ + typedef bg::model::point point_type; + typedef bg::model::box 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_pb_type; + pythagoras_pb_type pythagoras_pb; + BOOST_AUTO(distance, pythagoras_pb.apply(p, b)); + BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001); + + typedef typename bg::strategy::distance::services::comparable_type + < + pythagoras_pb_type + >::type comparable_type; + comparable_type comparable; + BOOST_AUTO(cdistance, comparable.apply(p, b)); + BOOST_CHECK_EQUAL(cdistance, 11589696996311540); + + typedef BOOST_TYPEOF(cdistance) cdistance_type; + typedef BOOST_TYPEOF(distance) distance_type; + + distance_type distance2 = sqrt(distance_type(cdistance)); + BOOST_CHECK_CLOSE(distance, distance2, 0.001); + + if (check_types) + { + BOOST_CHECK((boost::is_same::type::value)); + BOOST_CHECK((boost::is_same::type::value)); + } +} + +template +void test_all_3d() +{ + test_null_distance_3d >(); + test_axis_3d >(); + test_arbitrary_3d >(); + + test_null_distance_3d >(); + test_axis_3d >(); + test_arbitrary_3d >(); +} + +template +void test_all_3d() +{ + test_all_3d(); + test_all_3d(); + test_all_3d(); + test_all_3d(); + test_all_3d >(); + test_all_3d >(); + test_all_3d >(); +} + +template +void time_compare_s(int const n) +{ + typedef bg::model::box

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 +inline void time_compare(int const n) +{ + time_compare_s >(n); + time_compare_s + < + P, bg::strategy::distance::comparable::pythagoras_point_box<> + >(n); +} + + + + +BOOST_AUTO_TEST_CASE( test_integer_all ) +{ + test_integer(true); + test_integer(true); + test_integer(false); +} + + +BOOST_AUTO_TEST_CASE( test_3d_all ) +{ + test_all_3d(); + test_all_3d(); + test_all_3d(); + + test_all_3d(); + + test_all_3d >(); + test_all_3d >(); + test_all_3d >(); +} + + +BOOST_AUTO_TEST_CASE( test_big_2d_all ) +{ + test_big_2d(); + test_big_2d(); + test_big_2d(); + test_big_2d(); +} + + +BOOST_AUTO_TEST_CASE( test_services_all ) +{ + test_services + < + bg::model::point, + bg::model::box, + long double + >(); + test_services, float>(); + + // reverse the point and box types + test_services + < + double[3], + bg::model::box >, + long double + >(); + test_services, float>(); +} + + +BOOST_AUTO_TEST_CASE( test_time_compare ) +{ + // TODO move this to another non-unit test + // time_compare >(10000); +} + + +#if defined(HAVE_TTMATH) +BOOST_AUTO_TEST_CASE( test_ttmath_all ) +{ + typedef ttmath::Big<1,4> tt; + typedef bg::model::point tt_point; + + //test_all_3d(); + test_all_3d(); + test_all_3d(); + test_big_2d(); + test_big_2d_string(); +} +#endif From 795fdf82a7aa601691ad4b9e950afa041d98e67e Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 3 Jun 2014 18:58:33 +0300 Subject: [PATCH 2/2] [test][strategies] add entry for unit test for pythagoras point-box --- test/strategies/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/strategies/Jamfile.v2 b/test/strategies/Jamfile.v2 index e994e46f0..567aca453 100644 --- a/test/strategies/Jamfile.v2 +++ b/test/strategies/Jamfile.v2 @@ -20,6 +20,7 @@ test-suite boost-geometry-strategies [ run haversine.cpp ] [ run projected_point.cpp ] [ run pythagoras.cpp ] + [ run pythagoras_point_box.cpp ] [ run spherical_side.cpp ] [ run segment_intersection_collinear.cpp ] [ run transform_cs.cpp ]