diff options
Diffstat (limited to 'libs/geometry/test/algorithms/distance')
15 files changed, 5958 insertions, 0 deletions
diff --git a/libs/geometry/test/algorithms/distance/Jamfile.v2 b/libs/geometry/test/algorithms/distance/Jamfile.v2 new file mode 100644 index 000000000..bb76a8622 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/Jamfile.v2 @@ -0,0 +1,28 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +# Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +# Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +# +# 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 +# +# 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-algorithms-distance + : + [ run distance.cpp ] + [ run distance_areal_areal.cpp ] + [ run distance_linear_areal.cpp ] + [ run distance_linear_linear.cpp ] + [ run distance_pointlike_areal.cpp ] + [ run distance_pointlike_linear.cpp ] + [ run distance_pointlike_pointlike.cpp ] + [ run distance_se_pl_l.cpp ] + [ run distance_se_pl_pl.cpp ] + ; diff --git a/libs/geometry/test/algorithms/distance/distance.cpp b/libs/geometry/test/algorithms/distance/distance.cpp new file mode 100644 index 000000000..84e066808 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance.cpp @@ -0,0 +1,540 @@ +// 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. + +// 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 <string> +#include <sstream> + +#include "test_distance.hpp" + +#include <boost/mpl/if.hpp> +#include <boost/array.hpp> + +#include <boost/geometry/geometries/geometries.hpp> +#include <boost/geometry/geometries/point_xy.hpp> +#include <boost/geometry/geometries/adapted/c_array.hpp> +#include <boost/geometry/geometries/adapted/boost_tuple.hpp> + +#include <test_common/test_point.hpp> +#include <test_geometries/custom_segment.hpp> +#include <test_geometries/wrapped_boost_array.hpp> + +// includes for multi-geometries +#include <boost/geometry/multi/geometries/multi_point.hpp> +#include <boost/geometry/multi/geometries/multi_linestring.hpp> +#include <boost/geometry/multi/geometries/multi_polygon.hpp> +#include <boost/geometry/multi/io/wkt/read.hpp> + +#include <boost/variant/variant.hpp> + +BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) +BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian) + +// Register boost array as a linestring +namespace boost { namespace geometry { namespace traits +{ +template <typename Point, std::size_t PointCount> +struct tag< boost::array<Point, PointCount> > +{ + typedef linestring_tag type; +}; + +}}} + +template <typename P> +void test_distance_point() +{ + namespace services = bg::strategy::distance::services; + typedef typename bg::default_distance_result<P>::type return_type; + + // Basic, trivial test + + P p1; + bg::set<0>(p1, 1); + bg::set<1>(p1, 1); + + P p2; + bg::set<0>(p2, 2); + bg::set<1>(p2, 2); + + return_type d = bg::distance(p1, p2); + BOOST_CHECK_CLOSE(d, return_type(1.4142135), 0.001); + + // Test specifying strategy manually + typename services::default_strategy + < + bg::point_tag, bg::point_tag, P + >::type strategy; + + d = bg::distance(p1, p2, strategy); + BOOST_CHECK_CLOSE(d, return_type(1.4142135), 0.001); + + { + // Test custom strategy + BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<taxicab_distance, P, P>) ); + + typedef typename services::return_type<taxicab_distance, P, P>::type cab_return_type; + BOOST_MPL_ASSERT((boost::is_same<cab_return_type, typename bg::coordinate_type<P>::type>)); + + taxicab_distance tcd; + cab_return_type d = bg::distance(p1, p2, tcd); + + BOOST_CHECK( bg::math::abs(d - cab_return_type(2)) <= cab_return_type(0.01) ); + } + + { + // test comparability + + typedef typename services::default_strategy + < + bg::point_tag, bg::point_tag, P + >::type strategy_type; + typedef typename services::comparable_type<strategy_type>::type comparable_strategy_type; + + strategy_type strategy; + comparable_strategy_type comparable_strategy = services::get_comparable<strategy_type>::apply(strategy); + return_type comparable = services::result_from_distance<comparable_strategy_type, P, P>::apply(comparable_strategy, 3); + + BOOST_CHECK_CLOSE(comparable, return_type(9), 0.001); + } +} + +template <typename P> +void test_distance_segment() +{ + typedef typename bg::default_distance_result<P>::type return_type; + + P s1; bg::set<0>(s1, 1); bg::set<1>(s1, 1); + P s2; bg::set<0>(s2, 4); bg::set<1>(s2, 4); + + // Check points left, right, projected-left, projected-right, on segment + P p1; bg::set<0>(p1, 0); bg::set<1>(p1, 1); + P p2; bg::set<0>(p2, 1); bg::set<1>(p2, 0); + P p3; bg::set<0>(p3, 3); bg::set<1>(p3, 1); + P p4; bg::set<0>(p4, 1); bg::set<1>(p4, 3); + P p5; bg::set<0>(p5, 3); bg::set<1>(p5, 3); + + bg::model::referring_segment<P const> const seg(s1, s2); + + return_type d1 = bg::distance(p1, seg); + return_type d2 = bg::distance(p2, seg); + return_type d3 = bg::distance(p3, seg); + return_type d4 = bg::distance(p4, seg); + return_type d5 = bg::distance(p5, seg); + + BOOST_CHECK_CLOSE(d1, return_type(1), 0.001); + BOOST_CHECK_CLOSE(d2, return_type(1), 0.001); + BOOST_CHECK_CLOSE(d3, return_type(1.4142135), 0.001); + BOOST_CHECK_CLOSE(d4, return_type(1.4142135), 0.001); + BOOST_CHECK_CLOSE(d5, return_type(0), 0.001); + + // Reverse case: segment/point instead of point/segment + return_type dr1 = bg::distance(seg, p1); + return_type dr2 = bg::distance(seg, p2); + + BOOST_CHECK_CLOSE(dr1, d1, 0.001); + BOOST_CHECK_CLOSE(dr2, d2, 0.001); + + // Test specifying strategy manually: + // 1) point-point-distance + typename bg::strategy::distance::services::default_strategy + < + bg::point_tag, bg::point_tag, P + >::type pp_strategy; + d1 = bg::distance(p1, seg, pp_strategy); + BOOST_CHECK_CLOSE(d1, return_type(1), 0.001); + + // 2) point-segment-distance + typename bg::strategy::distance::services::default_strategy + < + bg::point_tag, bg::segment_tag, P + >::type ps_strategy; + d1 = bg::distance(p1, seg, ps_strategy); + BOOST_CHECK_CLOSE(d1, return_type(1), 0.001); + + // 3) custom point strategy + taxicab_distance tcd; + d1 = bg::distance(p1, seg, tcd); + BOOST_CHECK_CLOSE(d1, return_type(1), 0.001); +} + +template <typename Point, typename Geometry, typename T> +void test_distance_linear(std::string const& wkt_point, std::string const& wkt_geometry, T const& expected) +{ + Point p; + bg::read_wkt(wkt_point, p); + + Geometry g; + bg::read_wkt(wkt_geometry, g); + + typedef typename bg::default_distance_result<Point>::type return_type; + return_type d = bg::distance(p, g); + + // For point-to-linestring (or point-to-polygon), both a point-strategy and a point-segment-strategy can be specified. + // Test this. + return_type ds1 = bg::distance(p, g, bg::strategy::distance::pythagoras<>()); + return_type ds2 = bg::distance(p, g, bg::strategy::distance::projected_point<>()); + + BOOST_CHECK_CLOSE(d, return_type(expected), 0.001); + BOOST_CHECK_CLOSE(ds1, return_type(expected), 0.001); + BOOST_CHECK_CLOSE(ds2, return_type(expected), 0.001); +} + +template <typename P> +void test_distance_array_as_linestring() +{ + typedef typename bg::default_distance_result<P>::type return_type; + + // Normal array does not have + boost::array<P, 2> points; + bg::set<0>(points[0], 1); + bg::set<1>(points[0], 1); + bg::set<0>(points[1], 3); + bg::set<1>(points[1], 3); + + P p; + bg::set<0>(p, 2); + bg::set<1>(p, 1); + + return_type d = bg::distance(p, points); + BOOST_CHECK_CLOSE(d, return_type(0.70710678), 0.001); + + bg::set<0>(p, 5); bg::set<1>(p, 5); + d = bg::distance(p, points); + BOOST_CHECK_CLOSE(d, return_type(2.828427), 0.001); +} + + +// code moved from the distance unit test in multi/algorithms -- start +template <typename Geometry1, typename Geometry2> +void test_distance(std::string const& wkt1, std::string const& wkt2, double expected) +{ + Geometry1 g1; + Geometry2 g2; + bg::read_wkt(wkt1, g1); + bg::read_wkt(wkt2, g2); + typename bg::default_distance_result<Geometry1, Geometry2>::type d = bg::distance(g1, g2); + + BOOST_CHECK_CLOSE(d, expected, 0.0001); +} + +template <typename Geometry1, typename Geometry2, typename Strategy> +void test_distance(Strategy const& strategy, std::string const& wkt1, + std::string const& wkt2, double expected) +{ + Geometry1 g1; + Geometry2 g2; + bg::read_wkt(wkt1, g1); + bg::read_wkt(wkt2, g2); + typename bg::default_distance_result<Geometry1, Geometry2>::type d = bg::distance(g1, g2, strategy); + + BOOST_CHECK_CLOSE(d, expected, 0.0001); +} + + +template <typename P> +void test_2d() +{ + typedef bg::model::multi_point<P> mp; + typedef bg::model::multi_linestring<bg::model::linestring<P> > ml; + test_distance<P, P>("POINT(0 0)", "POINT(1 1)", sqrt(2.0)); + test_distance<P, mp>("POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<mp, P>("MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + test_distance<mp, mp>("MULTIPOINT((1 1),(1 0),(0 2))", "MULTIPOINT((2 2),(2 3))", sqrt(2.0)); + test_distance<P, ml>("POINT(0 0)", "MULTILINESTRING((1 1,2 2),(1 0,2 0),(0 2,0 3))", 1.0); + test_distance<ml, P>("MULTILINESTRING((1 1,2 2),(1 0,2 0),(0 2,0 3))", "POINT(0 0)", 1.0); + test_distance<ml, mp>("MULTILINESTRING((1 1,2 2),(1 0,2 0),(0 2,0 3))", "MULTIPOINT((0 0),(1 1))", 0.0); + + // Test with a strategy + bg::strategy::distance::pythagoras<> pyth; + test_distance<P, P>(pyth, "POINT(0 0)", "POINT(1 1)", sqrt(2.0)); + test_distance<P, mp>(pyth, "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<mp, P>(pyth, "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); +} + + +template <typename P> +void test_3d() +{ + typedef bg::model::multi_point<P> mp; + test_distance<P, P>("POINT(0 0 0)", "POINT(1 1 1)", sqrt(3.0)); + test_distance<P, mp>("POINT(0 0 0)", "MULTIPOINT((1 1 1),(1 0 0),(0 1 2))", 1.0); + test_distance<mp, mp>("MULTIPOINT((1 1 1),(1 0 0),(0 0 2))", "MULTIPOINT((2 2 2),(2 3 4))", sqrt(3.0)); +} + + +template <typename P1, typename P2> +void test_mixed() +{ + typedef bg::model::multi_point<P1> mp1; + typedef bg::model::multi_point<P2> mp2; + + test_distance<P1, P2>("POINT(0 0)", "POINT(1 1)", sqrt(2.0)); + + test_distance<P1, mp1>("POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<P1, mp2>("POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<P2, mp1>("POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<P2, mp2>("POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + + // Test automatic reversal + test_distance<mp1, P1>("MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + test_distance<mp1, P2>("MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + test_distance<mp2, P1>("MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + test_distance<mp2, P2>("MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + + // Test multi-multi using different point types for each + test_distance<mp1, mp2>("MULTIPOINT((1 1),(1 0),(0 2))", "MULTIPOINT((2 2),(2 3))", sqrt(2.0)); + + // Test with a strategy + using namespace bg::strategy::distance; + + test_distance<P1, P2>(pythagoras<>(), "POINT(0 0)", "POINT(1 1)", sqrt(2.0)); + + test_distance<P1, mp1>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<P1, mp2>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<P2, mp1>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + test_distance<P2, mp2>(pythagoras<>(), "POINT(0 0)", "MULTIPOINT((1 1),(1 0),(0 2))", 1.0); + + // Most interesting: reversal AND a strategy (note that the stategy must be reversed automatically + test_distance<mp1, P1>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + test_distance<mp1, P2>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + test_distance<mp2, P1>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); + test_distance<mp2, P2>(pythagoras<>(), "MULTIPOINT((1 1),(1 0),(0 2))", "POINT(0 0)", 1.0); +} +// code moved from the distance unit test in multi/algorithms -- end + + + + +template <typename P> +void test_all() +{ + test_distance_point<P>(); + test_distance_segment<P>(); + test_distance_array_as_linestring<P>(); + + test_geometry<P, bg::model::segment<P> >("POINT(1 3)", "LINESTRING(1 1,4 4)", sqrt(2.0)); + test_geometry<P, bg::model::segment<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0)); + + test_geometry<P, P>("POINT(1 1)", "POINT(2 2)", sqrt(2.0)); + test_geometry<P, P>("POINT(0 0)", "POINT(0 3)", 3.0); + test_geometry<P, P>("POINT(0 0)", "POINT(4 0)", 4.0); + test_geometry<P, P>("POINT(0 3)", "POINT(4 0)", 5.0); + test_geometry<P, bg::model::linestring<P> >("POINT(1 3)", "LINESTRING(1 1,4 4)", sqrt(2.0)); + test_geometry<P, bg::model::linestring<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0)); + test_geometry<P, bg::model::linestring<P> >("POINT(50 50)", "LINESTRING(50 40, 40 50)", sqrt(50.0)); + test_geometry<P, bg::model::linestring<P> >("POINT(50 50)", "LINESTRING(50 40, 40 50, 0 90)", sqrt(50.0)); + test_geometry<bg::model::linestring<P>, P>("LINESTRING(1 1,4 4)", "POINT(1 3)", sqrt(2.0)); + test_geometry<bg::model::linestring<P>, P>("LINESTRING(50 40, 40 50)", "POINT(50 50)", sqrt(50.0)); + test_geometry<bg::model::linestring<P>, P>("LINESTRING(50 40, 40 50, 0 90)", "POINT(50 50)", sqrt(50.0)); + + // Rings + test_geometry<P, bg::model::ring<P> >("POINT(1 3)", "POLYGON((1 1,4 4,5 0,1 1))", sqrt(2.0)); + test_geometry<P, bg::model::ring<P> >("POINT(3 1)", "POLYGON((1 1,4 4,5 0,1 1))", 0.0); + // other way round + test_geometry<bg::model::ring<P>, P>("POLYGON((1 1,4 4,5 0,1 1))", "POINT(3 1)", 0.0); + // open ring + test_geometry<P, bg::model::ring<P, true, false> >("POINT(1 3)", "POLYGON((4 4,5 0,1 1))", sqrt(2.0)); + + // Polygons + test_geometry<P, bg::model::polygon<P> >("POINT(1 3)", "POLYGON((1 1,4 4,5 0,1 1))", sqrt(2.0)); + test_geometry<P, bg::model::polygon<P> >("POINT(3 1)", "POLYGON((1 1,4 4,5 0,1 1))", 0.0); + // other way round + test_geometry<bg::model::polygon<P>, P>("POLYGON((1 1,4 4,5 0,1 1))", "POINT(3 1)", 0.0); + // open polygon + test_geometry<P, bg::model::polygon<P, true, false> >("POINT(1 3)", "POLYGON((4 4,5 0,1 1))", sqrt(2.0)); + + // Polygons with holes + std::string donut = "POLYGON ((0 0,1 9,8 1,0 0),(1 1,4 1,1 4,1 1))"; + test_geometry<P, bg::model::polygon<P> >("POINT(2 2)", donut, 0.5 * sqrt(2.0)); + test_geometry<P, bg::model::polygon<P> >("POINT(3 3)", donut, 0.0); + // other way round + test_geometry<bg::model::polygon<P>, P>(donut, "POINT(2 2)", 0.5 * sqrt(2.0)); + // open + test_geometry<P, bg::model::polygon<P, true, false> >("POINT(2 2)", "POLYGON ((0 0,1 9,8 1),(1 1,4 1,1 4))", 0.5 * sqrt(2.0)); + + // Should (currently) give compiler assertion + // test_geometry<bg::model::polygon<P>, bg::model::polygon<P> >(donut, donut, 0.5 * sqrt(2.0)); + + // DOES NOT COMPILE - cannot do read_wkt (because boost::array is not variably sized) + // test_geometry<P, boost::array<P, 2> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0)); + + test_geometry<P, test::wrapped_boost_array<P, 2> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0)); + + test_distance_linear<P, bg::model::linestring<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0)); +} + +template <typename P> +void test_empty_input() +{ + P p; + bg::model::linestring<P> line_empty; + bg::model::polygon<P> poly_empty; + bg::model::ring<P> ring_empty; + bg::model::multi_point<P> mp_empty; + bg::model::multi_linestring<bg::model::linestring<P> > ml_empty; + + test_empty_input(p, line_empty); + test_empty_input(p, poly_empty); + test_empty_input(p, ring_empty); + + test_empty_input(p, mp_empty); + test_empty_input(p, ml_empty); + test_empty_input(mp_empty, mp_empty); + + // Test behaviour if one of the inputs is empty + bg::model::multi_point<P> mp; + mp.push_back(p); + test_empty_input(mp_empty, mp); + test_empty_input(mp, mp_empty); +} + +void test_large_integers() +{ + typedef bg::model::point<int, 2, bg::cs::cartesian> int_point_type; + typedef bg::model::point<double, 2, bg::cs::cartesian> double_point_type; + + // point-point + { + std::string const a = "POINT(2544000 528000)"; + std::string const b = "POINT(2768040 528000)"; + int_point_type ia, ib; + double_point_type da, db; + bg::read_wkt(a, ia); + bg::read_wkt(b, ib); + bg::read_wkt(a, da); + bg::read_wkt(b, db); + + BOOST_AUTO(idist, bg::distance(ia, ib)); + BOOST_AUTO(ddist, bg::distance(da, db)); + + BOOST_CHECK_MESSAGE(std::abs(idist - ddist) < 0.1, + "within<a double> different from within<an int>"); + } + // Point-segment + { + std::string const a = "POINT(2600000 529000)"; + std::string const b = "LINESTRING(2544000 528000, 2768040 528000)"; + int_point_type ia; + double_point_type da; + bg::model::segment<int_point_type> ib; + bg::model::segment<double_point_type> db; + bg::read_wkt(a, ia); + bg::read_wkt(b, ib); + bg::read_wkt(a, da); + bg::read_wkt(b, db); + + BOOST_AUTO(idist, bg::distance(ia, ib)); + BOOST_AUTO(ddist, bg::distance(da, db)); + + BOOST_CHECK_MESSAGE(std::abs(idist - ddist) < 0.1, + "within<a double> different from within<an int>"); + } +} + +template <typename T> +void test_variant() +{ + typedef bg::model::point<T, 2, bg::cs::cartesian> point_type; + typedef bg::model::segment<point_type> segment_type; + typedef bg::model::box<point_type> box_type; + typedef boost::variant<point_type, segment_type, box_type> variant_type; + + point_type point; + std::string const point_li = "POINT(1 3)"; + bg::read_wkt(point_li, point); + + segment_type seg; + std::string const seg_li = "LINESTRING(1 1,4 4)"; + bg::read_wkt(seg_li, seg); + + variant_type v1, v2; + + BOOST_MPL_ASSERT(( + boost::is_same + < + typename bg::distance_result + < + variant_type, variant_type, bg::default_strategy + >::type, + double + > + )); + + // Default strategy + v1 = point; + v2 = point; + BOOST_CHECK_CLOSE(bg::distance(v1, v2), bg::distance(point, point), 0.0001); + BOOST_CHECK_CLOSE(bg::distance(v1, point), bg::distance(point, point), 0.0001); + BOOST_CHECK_CLOSE(bg::distance(point, v2), bg::distance(point, point), 0.0001); + v1 = point; + v2 = seg; + BOOST_CHECK_CLOSE(bg::distance(v1, v2), bg::distance(point, seg), 0.0001); + BOOST_CHECK_CLOSE(bg::distance(v1, seg), bg::distance(point, seg), 0.0001); + BOOST_CHECK_CLOSE(bg::distance(point, v2), bg::distance(point, seg), 0.0001); + + // User defined strategy + v1 = point; + v2 = point; + bg::strategy::distance::haversine<double> s; + //BOOST_CHECK_CLOSE(bg::distance(v1, v2, s), bg::distance(point, point, s), 0.0001); + //BOOST_CHECK_CLOSE(bg::distance(v1, point, s), bg::distance(point, point, s), 0.0001); + //BOOST_CHECK_CLOSE(bg::distance(point, v2, s), bg::distance(point, point, s), 0.0001); +} + +int test_main(int, char* []) +{ +#ifdef TEST_ARRAY + //test_all<int[2]>(); + //test_all<float[2]>(); + //test_all<double[2]>(); + //test_all<test::test_point>(); // located here because of 3D +#endif + + test_large_integers(); + + test_all<bg::model::d2::point_xy<int> >(); + test_all<boost::tuple<float, float> >(); + test_all<bg::model::d2::point_xy<float> >(); + test_all<bg::model::d2::point_xy<double> >(); + +#ifdef HAVE_TTMATH + test_all<bg::model::d2::point_xy<ttmath_big> >(); +#endif + + test_empty_input<bg::model::d2::point_xy<int> >(); + + // below are the test cases moved here from the distance unit test + // in test/multi/algorithms + test_2d<boost::tuple<float, float> >(); + test_2d<bg::model::d2::point_xy<float> >(); + test_2d<bg::model::d2::point_xy<double> >(); + + test_3d<boost::tuple<float, float, float> >(); + test_3d<bg::model::point<double, 3, bg::cs::cartesian> >(); + + test_mixed<bg::model::d2::point_xy<float>, bg::model::d2::point_xy<double> >(); + +#ifdef HAVE_TTMATH + test_2d<bg::model::d2::point_xy<ttmath_big> >(); + test_mixed<bg::model::d2::point_xy<ttmath_big>, bg::model::d2::point_xy<double> >(); +#endif + + test_empty_input<bg::model::d2::point_xy<int> >(); + + test_variant<double>(); + test_variant<int>(); + + return 0; +} diff --git a/libs/geometry/test/algorithms/distance/distance_all.cpp b/libs/geometry/test/algorithms/distance/distance_all.cpp new file mode 100644 index 000000000..74a46fffb --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_all.cpp @@ -0,0 +1,20 @@ +// 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_all +#endif + +#include "distance_pointlike_pointlike.cpp" +#include "distance_pointlike_linear.cpp" +#include "distance_pointlike_areal.cpp" +#include "distance_linear_linear.cpp" +#include "distance_linear_areal.cpp" +#include "distance_areal_areal.cpp" diff --git a/libs/geometry/test/algorithms/distance/distance_areal_areal.cpp b/libs/geometry/test/algorithms/distance/distance_areal_areal.cpp new file mode 100644 index 000000000..37c324e81 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_areal_areal.cpp @@ -0,0 +1,436 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014-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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_areal_areal +#endif + +#include <boost/test/included/unit_test.hpp> + +#include "test_distance_common.hpp" + + +typedef bg::model::point<int,2,bg::cs::cartesian> int_point_type; +typedef bg::model::point<double,2,bg::cs::cartesian> point_type; +typedef bg::model::polygon<point_type, false> polygon_type; +typedef bg::model::multi_polygon<polygon_type> multi_polygon_type; +typedef bg::model::ring<point_type, false> ring_type; +typedef bg::model::box<int_point_type> int_box_type; +typedef bg::model::box<point_type> box_type; + +namespace services = bg::strategy::distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef bg::strategy::distance::projected_point<> point_segment_strategy; +typedef bg::strategy::distance::pythagoras_box_box<> box_box_strategy; + +//=========================================================================== + +template <typename Strategy> +void test_distance_polygon_polygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "polygon/polygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<polygon_type, polygon_type> tester; + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,5 20,5 25,-5 25,-5 20))", + 10, 100, strategy); + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,-5 5,5 5,5 20,-5 20))", + 0, 0, strategy); + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,-5 -20,5 -20,5 20,-5 20))", + 0, 0, strategy); + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10),\ + (-5 -5,-5 5,5 5,5 -5,-5 -5))", + "polygon((-1 -1,0 0,-1 0,-1 -1))", + 4, 16, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_polygon_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "polygon/multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + polygon_type, multi_polygon_type + > tester; + + tester::apply("polygon((12 0,14 0,19 0,19.9 -1,12 0))", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0.1, 0.01, strategy); + + tester::apply("polygon((19 0,19.9 -1,12 0,20.5 0.5,19 0))", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_polygon_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "polygon/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<polygon_type, ring_type> tester; + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,5 20,5 25,-5 25,-5 20))", + 10, 100, strategy); + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,-5 5,5 5,5 20,-5 20))", + 0, 0, strategy); + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,-5 -20,5 -20,5 20,-5 20))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipolygon_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipolygon/multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_polygon_type, multi_polygon_type + > tester; + + tester::apply("multipolygon(((12 0,14 0,14 1,12 0)),\ + ((18 0,19 0,19.9 -1,18 0)))", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0.1, 0.01, strategy); + + tester::apply("multipolygon(((18 0,19 0,19.9 -1,18 0)),\ + ((12 0,14 0,20.5 0.5,12 0)))", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipolygon_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipolygon/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_polygon_type, ring_type + > tester; + + tester::apply("multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + "polygon((12 0,14 0,19 0,19.9 -1,12 0))", + 0.1, 0.01, strategy); + + tester::apply("multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + "polygon((19 0,19.9 -1,12 0,20.5 0.5,19 0))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_ring_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "ring/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<ring_type, ring_type> tester; + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,5 20,5 25,-5 25,-5 20))", + 10, 100, strategy); + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,-5 5,5 5,5 20,-5 20))", + 0, 0, strategy); + + tester::apply("polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + "polygon((-5 20,-5 -20,5 -20,5 20,-5 20))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_box_box(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "box/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<int_box_type, int_box_type> int_tester; + typedef test_distance_of_geometries<box_type, box_type> tester; + + int_tester::apply("box(5 5,10 10)", + "box(0 0,1 1)", + sqrt(32.0), 32, strategy); + + tester::apply("box(5 5,10 10)", + "box(0 0,1 1)", + sqrt(32.0), 32, strategy); + + tester::apply("box(3 8,13 18)", + "box(0 0,5 5)", + 3, 9, strategy); + + tester::apply("box(5 5,10 10)", + "box(0 0,5 5)", + 0, 0, strategy); + + tester::apply("box(5 5,10 10)", + "box(0 0,6 6)", + 0, 0, strategy); + + tester::apply("box(3 5,13 15)", + "box(0 0,5 5)", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_polygon_box(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "polygon/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<polygon_type, box_type> tester; + + tester::apply("polygon((10 10,10 5,5 5,5 10,10 10))", + "box(0 0,1 1)", + sqrt(32.0), 32, strategy); + + tester::apply("polygon((10 10,10 5,5 5,5 10,10 10))", + "box(0 0,5 5)", + 0, 0, strategy); + + tester::apply("polygon((10 10,10 5,5 5,5 10,10 10))", + "box(0 0,6 6)", + 0, 0, strategy); + + tester::apply("polygon((10 10,15 5,10 0,5 5,10 10))", + "box(5 0,7.5 2.5)", + 0, 0, strategy); + + tester::apply("polygon((10 10,15 5,10 0,5 5,10 10))", + "box(5 0,6 1)", + sqrt(4.5), 4.5, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipolygon_box(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipolygon/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<multi_polygon_type, box_type> tester; + + tester::apply("multipolygon(((-10 -10,-10 -9,-9 -9,-9 -10,-10 -10)),\ + ((2 2,2 3,3 3,3 2,2 2)))", + "box(0 0,1 1)", + sqrt(2.0), 2, strategy); + + tester::apply("multipolygon(((-10 -10,-10 -9,-9 -9,-9 -10,-10 -10)),\ + ((2 2,2 3,3 3,3 2,2 2)))", + "box(0 0,2 2)", + 0, 0, strategy); + + tester::apply("multipolygon(((-10 -10,-10 -9,-9 -9,-9 -10,-10 -10)),\ + ((2 2,2 3,3 3,3 2,2 2)))", + "box(0 0,2.5 2)", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_ring_box(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "ring/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<ring_type, box_type> tester; + + tester::apply("polygon((10 10,10 5,5 5,5 10,10 10))", + "box(0 0,1 1)", + sqrt(32.0), 32, strategy); + + tester::apply("polygon((10 10,10 5,5 5,5 10,10 10))", + "box(0 0,5 5)", + 0, 0, strategy); + + tester::apply("polygon((10 10,10 5,5 5,5 10,10 10))", + "box(0 0,6 6)", + 0, 0, strategy); + + tester::apply("polygon((10 10,15 5,10 0,5 5,10 10))", + "box(5 0,7.5 2.5)", + 0, 0, strategy); + + tester::apply("polygon((10 10,15 5,10 0,5 5,10 10))", + "box(5 0,6 1)", + sqrt(4.5), 4.5, strategy); +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_areal_areal(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::polygon<Point> polygon_empty; + bg::model::multi_polygon<bg::model::polygon<Point> > multipolygon_empty; + bg::model::ring<Point> ring_empty; + + bg::model::polygon<Point> polygon = + from_wkt<bg::model::polygon<Point> >("polygon((0 0,1 0,0 1))"); + + bg::model::multi_polygon<bg::model::polygon<Point> > multipolygon = + from_wkt + < + bg::model::multi_polygon<bg::model::polygon<Point> > + >("multipolygon(((0 0,1 0,0 1)))"); + + bg::model::ring<Point> ring = + from_wkt<bg::model::ring<Point> >("polygon((0 0,1 0,0 1))"); + + // 1st geometry is empty + test_empty_input(polygon_empty, polygon, strategy); + test_empty_input(polygon_empty, multipolygon, strategy); + test_empty_input(polygon_empty, ring, strategy); + test_empty_input(multipolygon_empty, polygon, strategy); + test_empty_input(multipolygon_empty, multipolygon, strategy); + test_empty_input(multipolygon_empty, ring, strategy); + test_empty_input(ring_empty, polygon, strategy); + test_empty_input(ring_empty, multipolygon, strategy); + test_empty_input(ring_empty, ring, strategy); + + // 2nd geometry is empty + test_empty_input(polygon, polygon_empty, strategy); + test_empty_input(polygon, multipolygon_empty, strategy); + test_empty_input(polygon, ring_empty, strategy); + test_empty_input(multipolygon, polygon_empty, strategy); + test_empty_input(multipolygon, multipolygon_empty, strategy); + test_empty_input(multipolygon, ring_empty, strategy); + test_empty_input(ring, polygon_empty, strategy); + test_empty_input(ring, multipolygon_empty, strategy); + test_empty_input(ring, ring_empty, strategy); + + // both geometries are empty + test_empty_input(polygon_empty, polygon_empty, strategy); + test_empty_input(polygon_empty, multipolygon_empty, strategy); + test_empty_input(polygon_empty, ring_empty, strategy); + test_empty_input(multipolygon_empty, polygon_empty, strategy); + test_empty_input(multipolygon_empty, multipolygon_empty, strategy); + test_empty_input(multipolygon_empty, ring_empty, strategy); + test_empty_input(ring_empty, polygon_empty, strategy); + test_empty_input(ring_empty, multipolygon_empty, strategy); + test_empty_input(ring_empty, ring_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_polygon_polygon ) +{ + test_distance_polygon_polygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_polygon_multipolygon ) +{ + test_distance_polygon_multipolygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_polygon_ring ) +{ + test_distance_polygon_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipolygon_multipolygon ) +{ + test_distance_multipolygon_multipolygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipolygon_ring ) +{ + test_distance_multipolygon_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_ring_ring ) +{ + test_distance_ring_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_box_box ) +{ + test_distance_box_box(box_box_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_polygon_box ) +{ + test_distance_polygon_box(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipolygon_box ) +{ + test_distance_multipolygon_box(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_ring_box ) +{ + test_distance_ring_box(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_areal_areal ) +{ + test_more_empty_input_areal_areal<point_type>(point_segment_strategy()); +} diff --git a/libs/geometry/test/algorithms/distance/distance_brute_force.hpp b/libs/geometry/test/algorithms/distance/distance_brute_force.hpp new file mode 100644 index 000000000..e645ec524 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_brute_force.hpp @@ -0,0 +1,493 @@ +// 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_GEOMETRY_TEST_DISTANCE_BRUTE_FORCE_HPP +#define BOOST_GEOMETRY_TEST_DISTANCE_BRUTE_FORCE_HPP + +#include <iterator> + +#include <boost/mpl/assert.hpp> +#include <boost/mpl/or.hpp> +#include <boost/range.hpp> + +#include <boost/geometry/core/reverse_dispatch.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tag_cast.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/iterators/segment_iterator.hpp> + +#include <boost/geometry/algorithms/distance.hpp> +#include <boost/geometry/algorithms/intersects.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> + + +namespace boost { namespace geometry +{ + +namespace unit_test +{ + +namespace detail { namespace distance_brute_force +{ + +struct distance_from_bg +{ + template <typename Geometry1, typename Geometry2, typename Strategy> + static inline + typename distance_result<Geometry1, Geometry2, Strategy>::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + BOOST_MPL_ASSERT + ((typename boost::mpl::or_ + < + boost::is_same<typename tag<Geometry1>::type, point_tag>, + boost::is_same<typename tag<Geometry1>::type, segment_tag> + >::type)); + + BOOST_MPL_ASSERT + ((typename boost::mpl::or_ + < + boost::is_same<typename tag<Geometry2>::type, point_tag>, + boost::is_same<typename tag<Geometry2>::type, segment_tag> + >::type)); + + return geometry::distance(geometry1, geometry2, strategy); + } +}; + + +template <typename Geometry1, typename Geometry2, typename Strategy> +inline +typename distance_result<Geometry1, Geometry2, Strategy>::type +bg_distance(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + return distance_from_bg::apply(geometry1, geometry2, strategy); +} + + +template <typename Policy> +struct one_to_many +{ + template <typename Geometry, typename Iterator, typename Strategy> + static inline typename distance_result + < + Geometry, + typename std::iterator_traits<Iterator>::value_type, + Strategy + >::type + apply(Geometry const& geometry, Iterator begin, Iterator end, + Strategy const& strategy) + { + typedef typename distance_result + < + Geometry, + typename std::iterator_traits<Iterator>::value_type, + Strategy + >::type distance_type; + + bool first = true; + distance_type d_min(0); + for (Iterator it = begin; it != end; ++it, first = false) + { + distance_type d = Policy::apply(geometry, *it, strategy); + + if ( first || d < d_min ) + { + d_min = d; + } + } + return d_min; + } +}; + + + +}} // namespace detail::distance_brute_force + + +namespace dispatch +{ + +template +< + typename Geometry1, + typename Geometry2, + typename Strategy, + typename Tag1 = typename tag_cast + < + typename tag<Geometry1>::type, + segment_tag, + linear_tag + >::type, + typename Tag2 = typename tag_cast + < + typename tag<Geometry2>::type, + segment_tag, + linear_tag + >::type, + bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value +> +struct distance_brute_force + : not_implemented<Geometry1, Geometry2> +{}; + + +template +< + typename Geometry1, + typename Geometry2, + typename Strategy, + typename Tag1, + typename Tag2 +> +struct distance_brute_force<Geometry1, Geometry2, Strategy, Tag1, Tag2, true> +{ + static inline typename distance_result<Geometry1, Geometry2, Strategy>::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return distance_brute_force + < + Geometry2, Geometry1, Strategy + >::apply(geometry2, geometry1, strategy); + } +}; + + +template +< + typename Point1, + typename Point2, + typename Strategy +> +struct distance_brute_force +< + Point1, Point2, Strategy, + point_tag, point_tag, false +> : detail::distance_brute_force::distance_from_bg +{}; + + +template +< + typename Point, + typename Segment, + typename Strategy +> +struct distance_brute_force +< + Point, Segment, Strategy, + point_tag, segment_tag, false +> : detail::distance_brute_force::distance_from_bg +{}; + + +template +< + typename Segment1, + typename Segment2, + typename Strategy +> +struct distance_brute_force +< + Segment1, Segment2, Strategy, + segment_tag, segment_tag, false +> : detail::distance_brute_force::distance_from_bg +{}; + + +template +< + typename Point, + typename Linear, + typename Strategy +> +struct distance_brute_force +< + Point, Linear, Strategy, + point_tag, linear_tag, false +> +{ + typedef typename distance_result + < + Point, Linear, Strategy + >::type distance_type; + + static inline distance_type apply(Point const& point, + Linear const& linear, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + detail::distance_brute_force::distance_from_bg + >::apply(point, + geometry::segments_begin(linear), + geometry::segments_end(linear), + strategy); + } +}; + + +template +< + typename Point, + typename MultiPoint, + typename Strategy +> +struct distance_brute_force +< + Point, MultiPoint, Strategy, + point_tag, multi_point_tag, false +> +{ + typedef typename distance_result + < + Point, MultiPoint, Strategy + >::type distance_type; + + static inline distance_type apply(Point const& p, + MultiPoint const& mp, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + detail::distance_brute_force::distance_from_bg + >::apply(p, boost::begin(mp), boost::end(mp), strategy); + } +}; + +template +< + typename MultiPoint1, + typename MultiPoint2, + typename Strategy +> +struct distance_brute_force +< + MultiPoint1, MultiPoint2, Strategy, + multi_point_tag, multi_point_tag, false +> +{ + typedef typename distance_result + < + MultiPoint1, MultiPoint2, Strategy + >::type distance_type; + + static inline distance_type apply(MultiPoint1 const& mp1, + MultiPoint2 const& mp2, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + MultiPoint1, + typename boost::range_value<MultiPoint2>::type, + Strategy + > + >::apply(mp1, boost::begin(mp2), boost::end(mp2), strategy); + } +}; + + +template +< + typename MultiPoint, + typename Linear, + typename Strategy +> +struct distance_brute_force +< + MultiPoint, Linear, Strategy, + multi_point_tag, linear_tag, false +> +{ + typedef typename distance_result + < + MultiPoint, Linear, Strategy + >::type distance_type; + + static inline distance_type apply(MultiPoint const& mp, + Linear const& linear, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Linear, + typename boost::range_value<MultiPoint>::type, + Strategy + > + >::apply(linear, boost::begin(mp), boost::end(mp), strategy); + } +}; + + +template +< + typename Linear, + typename MultiPoint, + typename Strategy +> +struct distance_brute_force +< + Linear, MultiPoint, Strategy, + linear_tag, multi_point_tag, false +> +{ + typedef typename distance_result + < + Linear, MultiPoint, Strategy + >::type distance_type; + + static inline distance_type apply(Linear const& linear, + MultiPoint const& multipoint, + Strategy const& strategy) + { + return distance_brute_force + < + MultiPoint, Linear, Strategy, + multi_point_tag, linear_tag, false + >::apply(multipoint, linear, strategy); + } +}; + + +template +< + typename MultiPoint, + typename Segment, + typename Strategy +> +struct distance_brute_force +< + MultiPoint, Segment, Strategy, + multi_point_tag, segment_tag, false +> +{ + typedef typename distance_result + < + MultiPoint, Segment, Strategy + >::type distance_type; + + static inline distance_type apply(MultiPoint const& mp, + Segment const& segment, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + detail::distance_brute_force::distance_from_bg + >::apply(segment, boost::begin(mp), boost::end(mp), strategy); + } +}; + + +template +< + typename Linear, + typename Segment, + typename Strategy +> +struct distance_brute_force +< + Linear, Segment, Strategy, + linear_tag, segment_tag, false +> +{ + typedef typename distance_result + < + Linear, Segment, Strategy + >::type distance_type; + + static inline distance_type apply(Linear const& linear, + Segment const& segment, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + detail::distance_brute_force::distance_from_bg + >::apply(segment, + geometry::segments_begin(linear), + geometry::segments_end(linear), + strategy); + } +}; + + +template +< + typename Linear1, + typename Linear2, + typename Strategy +> +struct distance_brute_force +< + Linear1, Linear2, Strategy, + linear_tag, linear_tag, false +> +{ + typedef typename distance_result + < + Linear1, Linear2, Strategy + >::type distance_type; + + static inline distance_type apply(Linear1 const& linear1, + Linear2 const& linear2, + Strategy const& strategy) + { + return detail::distance_brute_force::one_to_many + < + distance_brute_force + < + Linear1, + typename std::iterator_traits + < + segment_iterator<Linear2 const> + >::value_type, + Strategy + > + >::apply(linear1, + geometry::segments_begin(linear2), + geometry::segments_end(linear2), + strategy); + } +}; + +} // namespace dispatch + + + + + +template <typename Geometry1, typename Geometry2, typename Strategy> +inline typename distance_result<Geometry1, Geometry2, Strategy>::type +distance_brute_force(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + return dispatch::distance_brute_force + < + Geometry1, Geometry2, Strategy + >::apply(geometry1, geometry2, strategy); +} + +} // namespace unit_test + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_TEST_DISTANCE_BRUTE_FORCE_HPP diff --git a/libs/geometry/test/algorithms/distance/distance_linear_areal.cpp b/libs/geometry/test/algorithms/distance/distance_linear_areal.cpp new file mode 100644 index 000000000..ae396ba47 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_linear_areal.cpp @@ -0,0 +1,971 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014-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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_linear_areal +#endif + +#include <boost/test/included/unit_test.hpp> + +#include "test_distance_common.hpp" + + +typedef bg::model::point<double,2,bg::cs::cartesian> point_type; +typedef bg::model::point<int,2,bg::cs::cartesian> int_point_type; +typedef bg::model::segment<point_type> segment_type; +typedef bg::model::segment<int_point_type> int_segment_type; +typedef bg::model::linestring<point_type> linestring_type; +typedef bg::model::multi_linestring<linestring_type> multi_linestring_type; +typedef bg::model::polygon<point_type, false> polygon_type; +typedef bg::model::polygon<point_type, false, false> open_polygon_type; +typedef bg::model::multi_polygon<polygon_type> multi_polygon_type; +typedef bg::model::multi_polygon<open_polygon_type> open_multipolygon_type; +typedef bg::model::ring<point_type, false> ring_type; +typedef bg::model::box<point_type> box_type; +typedef bg::model::box<int_point_type> int_box_type; + +namespace services = bg::strategy::distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef bg::strategy::distance::pythagoras<> point_point_strategy; +typedef bg::strategy::distance::projected_point<> point_segment_strategy; + +//=========================================================================== + +template <typename Strategy> +void test_distance_segment_polygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/polygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<segment_type, polygon_type> tester; + + tester::apply("segment(-1 20,1 20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("segment(1 20,2 40)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("segment(-1 20,-1 5)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("segment(-1 20,-1 -20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("segment(0 0,1 1)", + "polygon((2 2))", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_polygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/polygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<linestring_type, polygon_type> tester; + + tester::apply("linestring(-1 20,1 20,1 30)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("linestring(-5 1,-2 1)", + "polygon((0 0,10 0,10 10,0 10,0 0))", + 2, 4, strategy); + + tester::apply("linestring(-1 20,1 20,1 5)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("linestring(-1 20,1 20,1 -20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("linestring(-2 1)", + "polygon((0 0,10 0,10 10,0 10,0 0))", + 2, 4, strategy); + + tester::apply("linestring(-5 1,-2 1)", + "polygon((0 0))", + sqrt(5.0), 5, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_open_polygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/open polygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + linestring_type, open_polygon_type + > tester; + + tester::apply("linestring(-5 1,-2 1)", + "polygon((0 0,10 0,10 10,0 10))", + 2, 4, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multilinestring_polygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/polygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_linestring_type, polygon_type + > tester; + + tester::apply("multilinestring((-100 -100,-90 -90),(-1 20,1 20,1 30))", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("multilinestring((-1 20,1 20,1 30),(-1 20,1 20,1 5))", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("multilinestring((-1 20,1 20,1 30),(-1 20,1 20,1 -20))", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("multilinestring((-100 -100,-90 -90),(1 20))", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("multilinestring((-100 -100,-90 -90),(-1 20,1 20,1 30))", + "polygon((-110 -110))", + sqrt(200.0), 200, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_segment_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + segment_type, multi_polygon_type + > tester; + + tester::apply("segment(-1 20,1 20)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((0 22,-1 30, 2 40,0 22)))", + 2, 4, strategy); + + tester::apply("segment(12 0,14 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 2, 4, strategy); + + tester::apply("segment(12 0,20.5 0.5)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); + + tester::apply("segment(12 0,50 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + linestring_type, multi_polygon_type + > tester; + + tester::apply("linestring(-1 20,1 20)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((0 22,-1 30, 2 40,0 22)))", + 2, 4, strategy); + + tester::apply("linestring(12 0,14 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 2, 4, strategy); + + tester::apply("linestring(12 0,20.5 0.5)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); + + tester::apply("linestring(12 0,50 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_open_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/open multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + linestring_type, open_multipolygon_type + > tester; + + tester::apply("linestring(-5 1,-2 1)", + "multipolygon(((0 0,10 0,10 10,0 10)))", + 2, 4, strategy); + + tester::apply("linestring(-5 1,-3 1)", + "multipolygon(((20 20,21 20,21 21,20 21)),((0 0,10 0,10 10,0 10)))", + 3, 9, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multilinestring_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_linestring_type, multi_polygon_type + > tester; + + tester::apply("multilinestring((12 0,14 0),(19 0,19.9 -1))", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10)))", + 0.1, 0.01, strategy); + + tester::apply("multilinestring((19 0,19.9 -1),(12 0,20.5 0.5))", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_segment_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<segment_type, ring_type> tester; + + tester::apply("segment(-1 20,1 20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("segment(1 20,2 40)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("segment(-1 20,-1 5)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("segment(-1 20,-1 -20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<linestring_type, ring_type> tester; + + tester::apply("linestring(-1 20,1 20,1 30)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("linestring(-1 20,1 20,1 5)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("linestring(-1 20,1 20,1 -20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multilinestring_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_linestring_type, ring_type + > tester; + + tester::apply("multilinestring((-100 -100,-90 -90),(-1 20,1 20,1 30))", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("multilinestring((-1 20,1 20,1 30),(-1 20,1 20,1 5))", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("multilinestring((-1 20,1 20,1 30),(-1 20,1 20,1 -20))", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_segment_box(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "2D segment/box distance tests" << std::endl; +#endif + typedef int_box_type B; + typedef segment_type S; + typedef int_segment_type IS; + + typedef test_distance_of_geometries<B, S> tester; + typedef test_distance_of_geometries<B, IS> itester; + + // 1st example by Adam Wulkiewicz + tester::apply("BOX(5 51,42 96)", + "SEGMENT(6.6799994 95.260002,35.119999 56.340004)", + 0, 0, strategy); + + // 2nd example by Adam Wulkiewicz + tester::apply("BOX(51 55,94 100)", + "SEGMENT(92.439995 50.130001,59.959999 80.870003)", + 0, 0, strategy); + + // segments that intersect the box + tester::apply("box(0 0,1 1)", + "segment(-1 0.5,0.5 0.75)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 0.5,1.5 0.75)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 -1,0.5 2)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 1,1.5 0.75)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(2 0,0 2)", + 0, 0, strategy); + + // segment that has closest point on box boundary + tester::apply("box(0 0,1 1)", + "segment(4 0.5,5 0.75)", + 3, 9, strategy); + + // segment that has closest point on box corner + tester::apply("box(0 0,1 1)", + "segment(4 0,0 4)", + sqrt(2.0), 2, strategy); + itester::apply("box(0 0,1 1)", + "segment(-4 0,0 -4)", + sqrt(8.0), 8, strategy); + itester::apply("box(0 0,1 1)", + "segment(-8 4,4 -8)", + sqrt(8.0), 8, strategy); + tester::apply("box(0 0,1 1)", + "segment(-4 0,0 4)", + 1.5 * sqrt(2.0), 4.5, strategy); + tester::apply("box(0 0,1 1)", + "segment(-4 0,1 5)", + 1.5 * sqrt(2.0), 4.5, strategy); + itester::apply("box(0 0,1 1)", + "segment(0 -2,3 1)", + 0.5 * sqrt(2.0), 0.5, strategy); + itester::apply("box(0 0,1 1)", + "segment(0 -2,2 2)", + 0, 0, strategy); + + // horizontal segments + itester::apply("box(0 0,1 1)", + "segment(-2 -1,-1 -1)", + sqrt(2.0), 2, strategy); + itester::apply("box(0 0,1 1)", + "segment(-1 -1,0 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-0.5 -1,0.5 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 -1,0.75 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 -1,1.25 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 -1,2 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(2 -1,3 -1)", + sqrt(2.0), 2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -1,2 -1)", + 1, 1, strategy); + + tester::apply("box(0 0,1 1)", + "segment(-2 0,-1 0)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 0,0 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-0.5 0,0.5 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 0,0.75 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 0,1.25 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 0,2 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(2 0,3 0)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 0,2 0)", + 0, 0, strategy); + + tester::apply("box(0 0,1 1)", + "segment(-2 0.5,-1 0.5)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 0.5,0 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-0.5 0.5,0.5 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 0.5,0.75 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 0.5,1.25 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 0.5,2 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(2 0.5,3 0.5)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 0.5,2 0.5)", + 0, 0, strategy); + + tester::apply("box(0 0,1 1)", + "segment(-2 1,-1 1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 1,0 1)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-0.5 1,0.5 1)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 1,0.75 1)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 1,1.25 1)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 1,2 1)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(2 1,3 1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 1,2 1)", + 0, 0, strategy); + + tester::apply("box(0 0,1 1)", + "segment(-2 3,-1 3)", + sqrt(5.0), 5, strategy); + itester::apply("box(0 0,1 1)", + "segment(-1 3,0 3)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(-0.5 3,0.5 3)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 3,0.75 3)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 3,1.25 3)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 3,2 3)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(2 3,3 3)", + sqrt(5.0), 5, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 3,2 3)", + 2, 4, strategy); + + // vertical segments + tester::apply("box(0 0,1 1)", + "segment(-1 -2,-1 -1)", + sqrt(2.0), 2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 -1,-1 0)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 -0.5,-1 0.5)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 0.5,-1 0.75)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 0.5,-1 1.25)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 1,-1 2)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 2,-1 3)", + sqrt(2.0), 2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 -2,-1 2)", + 1, 1, strategy); + + tester::apply("box(0 0,1 1)", + "segment(0 -2,0 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 -1,0 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 -0.5,0 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 0.5,0 0.75)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 0.5,0 1.25)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 1,0 2)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 2,0 3)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 -2,0 2)", + 0, 0, strategy); + + tester::apply("box(0 0,1 1)", + "segment(0.5 -2,0.5 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 -1,0.5 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 -0.5,0.5 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 0.5,0.5 0.75)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 0.5,0.5 1.25)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 1,0.5 2)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 2,0.5 3)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 -2,0.5 2)", + 0, 0, strategy); + + tester::apply("box(0 0,1 1)", + "segment(1 -2,1 -1)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 -1,1 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 -0.5,1 0.5)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 0.5,1 0.75)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 0.5,1 1.25)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 1,1 2)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 2,1 3)", + 1, 1, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 -2,1 2)", + 0, 0, strategy); + + tester::apply("box(0 0,1 1)", + "segment(3 -2,3 -1)", + sqrt(5.0), 5, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 -1,3 0)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 -0.5,3 0.5)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 0.5,3 0.75)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 0.5,3 1.25)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 1,3 2)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 2,3 3)", + sqrt(5.0), 5, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 -2,3 2)", + 2, 4, strategy); + + // positive slope + itester::apply("box(0 0,1 1)", + "segment(-2 -2,-1 -1)", + sqrt(2.0), 2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,0 -0.5)", + 0.5, 0.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,0.5 -0.5)", + 0.5, 0.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,1 -0.5)", + 0.5, 0.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,2 0)", + sqrt(0.2), 0.2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,4 1)", + sqrt(0.2), 0.2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,-1.5 0)", + 1.5, 2.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,-1.5 0.5)", + 1.5, 2.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,-1.5 1)", + 1.5, 2.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,0 2)", + sqrt(0.2), 0.2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,1 4)", + sqrt(0.2), 0.2, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,4 2)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,2 4)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,4 3)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,3 4)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 -2,3 3)", + 0, 0, strategy); + + // negative slope + tester::apply("box(0 0,1 1)", + "segment(-2 -2,-1 -3)", + sqrt(8.0), 8, strategy); + tester::apply("box(0 0,1 1)", + "segment(-3 -1,0 -4)", + sqrt(8.0), 8, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 0.75,-1.5 0.5)", + 1.5, 2.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 1.5,-1.5 0.5)", + 1.5, 2.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 2,0.75 1.5)", + 0.5, 0.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 2,0.75 1.5)", + 0.5, 0.25, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 2,2 0)", + 0, 0, strategy); + tester::apply("box(0 0,1 1)", + "segment(0 3,3 0)", + sqrt(0.5), 0.5, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 4,4 -1)", + sqrt(0.5), 0.5, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 4,0 3)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(-2 5,-1 4)", + sqrt(10.0), 10, strategy); + tester::apply("box(0 0,1 1)", + "segment(3 -1,4 -4)", + sqrt(5.0), 5, strategy); + tester::apply("box(0 0,1 1)", + "segment(1 2,2 1)", + sqrt(0.5), 0.5, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 -2,2 -3)", + 2, 4, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 -2,0 -3)", + sqrt(5.0), 5, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 -2,0.5 -3.5)", + sqrt(5.0), 5, strategy); + tester::apply("box(0 0,1 1)", + "segment(-1 -2,0.5 -3.5)", + sqrt(5.0), 5, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 3,2.5 2)", + sqrt(2.45), 2.45, strategy); + tester::apply("box(0 0,1 1)", + "segment(0.5 1.5,1.5 -1.5)", + 0, 0, strategy); + + // test degenerate segment + tester::apply("box(0 0,2 2)", + "segment(4 1,4 1)", + 2, 4, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_box(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<linestring_type, box_type> tester; + + // linestrings that intersect the box + tester::apply("linestring(-1 0.5,0.5 0.75)", + "box(0 0,1 1)", + 0, 0, strategy); + tester::apply("linestring(-1 0.5,1.5 0.75)", + "box(0 0,1 1)", + 0, 0, strategy); + + // linestring that has closest point on box boundary + tester::apply("linestring(4 0.5,5 0.75)", + "box(0 0,1 1)", + 3, 9, strategy); + + // linestring that has closest point on box corner + tester::apply("linestring(4 0,0 4)", + "box(0 0,1 1)", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multilinestring_box(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<multi_linestring_type, box_type> tester; + + // multilinestring that intersects the box + tester::apply("multilinestring((-1 0.5,0.5 0.75),(4 0.5,5 0.75))", + "box(0 0,1 1)", + 0, 0, strategy); + + // multilinestring that has closest point on box boundary + tester::apply("multilinestring((4 0.5,5 0.75))", + "box(0 0,1 1)", + 3, 9, strategy); + + // multilinestring that has closest point on box corner + tester::apply("multilinestring((5 0,0 5),(4 0,0 4))", + "box(0 0,1 1)", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_linear_areal(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::linestring<Point> line_empty; + bg::model::polygon<Point> polygon_empty; + bg::model::multi_linestring<bg::model::linestring<Point> > multiline_empty; + bg::model::multi_polygon<bg::model::polygon<Point> > multipolygon_empty; + bg::model::ring<Point> ring_empty; + + bg::model::linestring<Point> line = + from_wkt<bg::model::linestring<Point> >("linestring(0 0,1 1)"); + + bg::model::polygon<Point> polygon = + from_wkt<bg::model::polygon<Point> >("polygon((0 0,1 0,0 1))"); + + bg::model::ring<Point> ring = + from_wkt<bg::model::ring<Point> >("polygon((0 0,1 0,0 1))"); + + // 1st geometry is empty + test_empty_input(line_empty, polygon, strategy); + test_empty_input(line_empty, ring, strategy); + test_empty_input(multiline_empty, polygon, strategy); + test_empty_input(multiline_empty, ring, strategy); + + // 2nd geometry is empty + test_empty_input(line, polygon_empty, strategy); + test_empty_input(line, multipolygon_empty, strategy); + test_empty_input(line, ring_empty, strategy); + + // both geometries are empty + test_empty_input(line_empty, polygon_empty, strategy); + test_empty_input(line_empty, multipolygon_empty, strategy); + test_empty_input(line_empty, ring_empty, strategy); + test_empty_input(multiline_empty, polygon_empty, strategy); + test_empty_input(multiline_empty, multipolygon_empty, strategy); + test_empty_input(multiline_empty, ring_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_segment_polygon ) +{ + test_distance_segment_polygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_polygon ) +{ + test_distance_linestring_polygon(point_segment_strategy()); + test_distance_linestring_open_polygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multilinestring_polygon ) +{ + test_distance_multilinestring_polygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_segment_multipolygon ) +{ + test_distance_segment_multipolygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_multipolygon ) +{ + test_distance_linestring_multipolygon(point_segment_strategy()); + test_distance_linestring_open_multipolygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multilinestring_multipolygon ) +{ + test_distance_multilinestring_multipolygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_segment_ring ) +{ + test_distance_segment_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_ring ) +{ + test_distance_linestring_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multilinestring_ring ) +{ + test_distance_multilinestring_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_segment_box ) +{ + test_distance_segment_box(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_box ) +{ + test_distance_linestring_box(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multilinestring_box ) +{ + test_distance_multilinestring_box(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_linear_areal ) +{ + test_more_empty_input_linear_areal<point_type>(point_segment_strategy()); +} diff --git a/libs/geometry/test/algorithms/distance/distance_linear_linear.cpp b/libs/geometry/test/algorithms/distance/distance_linear_linear.cpp new file mode 100644 index 000000000..efd1ceab9 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_linear_linear.cpp @@ -0,0 +1,320 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014-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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_linear_linear +#endif + +#include <boost/test/included/unit_test.hpp> + +#include "test_distance_common.hpp" + + +typedef bg::model::point<double,2,bg::cs::cartesian> point_type; +typedef bg::model::segment<point_type> segment_type; +typedef bg::model::linestring<point_type> linestring_type; +typedef bg::model::multi_linestring<linestring_type> multi_linestring_type; + +namespace services = bg::strategy::distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef bg::strategy::distance::projected_point<> point_segment_strategy; + +//=========================================================================== + +template <typename Strategy> +void test_distance_segment_segment(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/segment distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<segment_type, segment_type> tester; + + tester::apply("segment(0 0,10 0)", + "segment(4 2,4 0.5)", + return_type(0.5), return_type(0.25), strategy); + + tester::apply("segment(0 0,10 0)", + "segment(4 2,4 -0.5)", + return_type(0), return_type(0), strategy); + + tester::apply("segment(0 0,10 0)", + "segment(4 2,0 0)", + return_type(0), return_type(0), strategy); + + tester::apply("segment(0 0,10 0)", + "segment(-2 3,1 2)", + return_type(2), return_type(4), strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_segment_linestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/linestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<segment_type, linestring_type> tester; + + tester::apply("segment(-1 -1,-2 -2)", + "linestring(2 1,1 2,4 0)", + sqrt(12.5), 12.5, strategy); + + tester::apply("segment(1 1,2 2)", + "linestring(2 1,1 2,4 0)", + 0, 0, strategy); + + tester::apply("segment(1 1,2 2)", + "linestring(3 3,3 3)", + sqrt(2.0), 2, strategy); + + tester::apply("segment(1 1,2 2)", + "linestring(3 3)", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_linestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/linestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + linestring_type, linestring_type + > tester; + + // It is not obvious that linestrings with only one point are valid + tester::apply("linestring(1 1)", "linestring(2 1)", + 1, 1, strategy); + + tester::apply("linestring(1 1,3 1)", "linestring(2 1)", + 0, 0, strategy); + + tester::apply("linestring(1 1)", "linestring(0 0,-2 0,2 -2,2 0)", + sqrt(2.0), 2, strategy); + + tester::apply("linestring(1 1,1 1)", "linestring(2 1,2 1)", + 1, 1, strategy); + + tester::apply("linestring(1 1,1 1,1 1)", "linestring(2 1,2 1,2 1,2 1)", + 1, 1, strategy); + + tester::apply("linestring(1 1,3 1)", "linestring(2 1,2 1)", + 0, 0, strategy); + + tester::apply("linestring(1 1,1 1)", "linestring(0 0,-2 0,2 -2,2 0)", + sqrt(2.0), 2, strategy); + + tester::apply("linestring(1 1,3 1)", "linestring(2 1, 4 1)", + 0, 0, strategy); + + tester::apply("linestring(1 1,2 2,3 3)", "linestring(2 1,1 2,4 0)", + 0, 0, strategy); + + tester::apply("linestring(1 1,2 2,3 3)", "linestring(1 0,2 -1,4 0)", + 1, 1, strategy); + + tester::apply("linestring(1 1,2 2,3 3)", + "linestring(1 -10,2 0,2.1 -10,4 0)", + sqrt(2.0), 2, strategy); + + tester::apply("linestring(1 1,2 2,3 3)", + "linestring(1 -10,2 1.9,2.1 -10,4 0)", + sqrt(0.005), 0.005, strategy); + + tester::apply("linestring(1 1,1 2)", "linestring(0 0,-2 0,2 -2,2 0)", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_segment_multilinestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "segment/multilinestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + segment_type, multi_linestring_type + > tester; + + tester::apply("segment(-1 -1,-2 -2)", + "multilinestring((2 1,1 2),(4 0,4 10))", + sqrt(12.5), 12.5, strategy); + + tester::apply("segment(1 1,2 2)", + "multilinestring((2 1,1 2),(4 0,4 10))", + 0, 0, strategy); + + tester::apply("segment(1 1,2 2)", + "multilinestring((2.5 0,4 0,5 0),(3 3,3 3))", + sqrt(2.0), 2, strategy); + + tester::apply("segment(1 1,2 2)", + "multilinestring((2.5 0),(3 3,3 3))", + sqrt(2.0), 2, strategy); + + tester::apply("segment(1 1,2 2)", + "multilinestring((2.5 0,4 0,5 0),(3 3))", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_multilinestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/multilinestring distance tests" << std::endl; +#endif + + typedef test_distance_of_geometries + < + linestring_type, multi_linestring_type + > tester; + + tester::apply("linestring(1 1,2 2,3 3)", + "multilinestring((2 1,1 2,4 0),(1 -10,2 1.9,2.1 -10,4 0))", + 0, 0, strategy); + + tester::apply("linestring(1 1,2 2,3 3)", + "multilinestring((1 -10,2 0,2.1 -10,4 0),(1 -10,2 1.9,2.1 -10,4 0))", + sqrt(0.005), 0.005, strategy); + + tester::apply("linestring(1 1,2 2)", + "multilinestring((2.5 0,4 0,5 0),(3 3,3 3))", + sqrt(2.0), 2, strategy); + + tester::apply("linestring(2 2)", + "multilinestring((2.5 0,4 0,5 0),(3 3,3 3))", + sqrt(2.0), 2, strategy); + + tester::apply("linestring(1 1,2 2)", + "multilinestring((2.5 0,4 0,5 0),(3 3))", + sqrt(2.0), 2, strategy); + + tester::apply("linestring(1 1,2 2,3 3,4 4,5 5,6 6,7 7,8 8,9 9)", + "multilinestring((2.5 0,4 0,5 0),(10 10,10 10))", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multilinestring_multilinestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multilinestring/multilinestring distance tests" << std::endl; +#endif + + typedef test_distance_of_geometries + < + multi_linestring_type, multi_linestring_type + > tester; + + tester::apply("multilinestring((0 0,0 1,1 1),(10 0,11 1,12 2))", + "multilinestring((0.5 0.5,0.75 0.75),(11 0,11 7))", + 0, 0, strategy); + + tester::apply("multilinestring((0 0,0 1,1 1),(10 0,11 1,12 2))", + "multilinestring((0.5 0.5,0.75 0.75),(11 0,11 0.9))", + sqrt(0.005), 0.005, strategy); + + tester::apply("multilinestring((0 0,0 1,1 1),(10 0,11 1,12 2))", + "multilinestring((0.5 0.5,0.75 0.75),(11.1 0,11.1 0.9))", + sqrt(0.02), 0.02, strategy); + + tester::apply("multilinestring((0 0),(1 1))", + "multilinestring((2 2),(3 3))", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_linear_linear(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::linestring<Point> line_empty; + bg::model::multi_linestring<bg::model::linestring<Point> > multiline_empty; + + bg::model::linestring<Point> line = + from_wkt<bg::model::linestring<Point> >("linestring(0 0,1 1)"); + + // 1st geometry is empty + test_empty_input(line_empty, line, strategy); + test_empty_input(multiline_empty, line, strategy); + + // 2nd geometry is empty + test_empty_input(line, line_empty, strategy); + test_empty_input(line, multiline_empty, strategy); + + // both geometries are empty + test_empty_input(line_empty, line_empty, strategy); + test_empty_input(line_empty, multiline_empty, strategy); + test_empty_input(multiline_empty, multiline_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_segment_segment ) +{ + test_distance_segment_segment(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_segment_linestring ) +{ + test_distance_segment_linestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_linestring ) +{ + test_distance_linestring_linestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_segment_multilinestring ) +{ + test_distance_segment_multilinestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_multilinestring ) +{ + test_distance_linestring_multilinestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multilinestring_multilinestring ) +{ + test_distance_multilinestring_multilinestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_linear_linear ) +{ + test_more_empty_input_linear_linear<point_type>(point_segment_strategy()); +} diff --git a/libs/geometry/test/algorithms/distance/distance_pointlike_areal.cpp b/libs/geometry/test/algorithms/distance/distance_pointlike_areal.cpp new file mode 100644 index 000000000..fd5c6c852 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_pointlike_areal.cpp @@ -0,0 +1,670 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014-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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_pointlike_areal +#endif + +#include <boost/test/included/unit_test.hpp> + +#include "test_distance_common.hpp" + + +typedef bg::model::point<double,2,bg::cs::cartesian> point_type; +typedef bg::model::multi_point<point_type> multi_point_type; +typedef bg::model::point<double,3,bg::cs::cartesian> point_type_3d; +typedef bg::model::multi_point<point_type_3d> multi_point_type_3d; +typedef bg::model::polygon<point_type, false> polygon_type; +typedef bg::model::multi_polygon<polygon_type> multi_polygon_type; +typedef bg::model::ring<point_type, false> ring_type; +typedef bg::model::box<point_type> box_type; +typedef bg::model::box<point_type_3d> box_type_3d; + +namespace services = bg::strategy::distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef bg::strategy::distance::pythagoras<> point_point_strategy; +typedef bg::strategy::distance::projected_point<> point_segment_strategy; +typedef bg::strategy::distance::pythagoras_point_box<> point_box_strategy; + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_polygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/polygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, polygon_type> tester; + + tester::apply("point(0 -20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("point(12 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 2, 4, strategy); + + tester::apply("point(0 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("point(0 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10),\ + (-5 -5,-5 5,5 5,5 -5,-5 -5))", + 5, 25, strategy); + + // polygons with single-point rings + tester::apply("point(0 0)", + "polygon((-5 5))", + sqrt(50.0), 50, strategy); + + tester::apply("point(0 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10),(-5 5))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, ring_type> tester; + + tester::apply("point(0 -20)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 10, 100, strategy); + + tester::apply("point(12 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 2, 4, strategy); + + tester::apply("point(0 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + // single-point rings + tester::apply("point(0 0)", + "polygon((-10 -10))", + sqrt(200.0), 200, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, multi_polygon_type> tester; + + tester::apply("point(0 -20)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((0 22,-1 30,2 40,0 22)))", + 10, 100, strategy); + + tester::apply("point(12 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 2, 4, strategy); + + tester::apply("point(0 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); + + tester::apply("point(0 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10),\ + (-5 -5,-5 5,5 5,5 -5,-5 -5)),\ + ((100 0,101 0,101 1,100 1,100 0)))", + 5, 25, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_polygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/polygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<multi_point_type, polygon_type> tester; + + tester::apply("multipoint(0 -20,0 -15)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 5, 25, strategy); + + tester::apply("multipoint(16 0,12 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 2, 4, strategy); + + tester::apply("multipoint(0 0,5 5,4 4)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + tester::apply("multipoint(0 0,2 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10),\ + (-5 -5,-5 5,5 5,5 -5,-5 -5))", + 3, 9, strategy); + + tester::apply("multipoint(4 4,11 11)", + "polygon((0 0,0 10,10 10,10 0,0 0))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_ring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/ring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<multi_point_type, ring_type> tester; + + tester::apply("multipoint(0 -20,0 -15)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 5, 25, strategy); + + tester::apply("multipoint(16 0,12 0)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 2, 4, strategy); + + tester::apply("multipoint(0 0,5 5,4 4)", + "polygon((-10 -10,10 -10,10 10,-10 10,-10 -10))", + 0, 0, strategy); + + // single-point ring + tester::apply("multipoint(0 0,5 5,4 4)", + "polygon((10 10))", + sqrt(50.0), 50, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_multipolygon(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/multipolygon distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_point_type, multi_polygon_type + > tester; + + tester::apply("multipoint(0 -20,0 -15)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((0 22,-1 30,2 40,0 22)))", + 5, 25, strategy); + + tester::apply("multipoint(16 0,12 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 2, 4, strategy); + + tester::apply("multipoint(0 0,4 4,5 5)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10)),\ + ((20 -1,21 2,30 -10,20 -1)))", + 0, 0, strategy); + + tester::apply("multipoint(0 0,2 0)", + "multipolygon(((-10 -10,10 -10,10 10,-10 10,-10 -10),\ + (-5 -5,-5 5,5 5,5 -5,-5 -5)),\ + ((100 0,101 0,101 1,100 1,100 0)))", + 3, 9, strategy); + + tester::apply("MULTIPOINT(19 19,100 100)", + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0),\ + (4 4,4 6,6 6,6 4,4 4)), ((10 10,10 20,20 20,20 10,10 10),\ + (14 14,14 16,16 16,16 14,14 14)))", + 0, 0, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_box_2d(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "2D point/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<box_type, point_type> tester; + + // point inside box + tester::apply("box(-1 -1,1 1)", + "point(0 0)", 0, 0, strategy); + + // points on box corners + tester::apply("box(-1 -1,1 1)", + "point(-1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1,1 1)", + "point(-1 1)", 0, 0, strategy); + tester::apply("box(-1 -1,1 1)", + "point(1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1,1 1)", + "point(1 1)", 0, 0, strategy); + + // points on box boundary edges + tester::apply("box(-1 -1,1 1)", + "point(0 -1)", 0, 0, strategy); + tester::apply("box(-1 -1,1 1)", + "point(-1 0)", 0, 0, strategy); + tester::apply("box(-1 -1,1 1)", + "point(1 0)", 0, 0, strategy); + tester::apply("box(-1 -1,1 1)", + "point(0 1)", 0, 0, strategy); + + // points outside box + tester::apply("box(-1 -1,1 1)", + "point(0 4)", 3, 9, strategy); + tester::apply("box(-1 -1,1 1)", + "point(0.5 4)", 3, 9, strategy); + tester::apply("box(-1 -1,1 1)", + "point(-0.5 5)", 4, 16, strategy); + tester::apply("box(-1 -1,1 1)", + "point(3 0.25)", 2, 4, strategy); + tester::apply("box(-1 -1,1 1)", + "point(-3 -0.25)", 2, 4, strategy); + tester::apply("box(-1 -1,1 1)", + "point(3 5)", sqrt(20.0), 20, strategy); + tester::apply("box(-1 -1,1 1)", + "point(-5 -4)", 5, 25, strategy); + tester::apply("box(-1 -1,1 1)", + "point(2 -2)", sqrt(2.0), 2, strategy); + tester::apply("box(-1 -1,1 1)", + "point(-3 4)", sqrt(13.0), 13, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_box_different_point_types(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "2D point/box distance tests with different points" + << std::endl; +#endif + typedef point_type double_point; + typedef box_type double_box; + typedef bg::model::point<int,2,bg::cs::cartesian> int_point; + typedef bg::model::box<int_point> int_box; + + test_distance_of_geometries + < + int_point, int_box + >::apply("point(0 0)", + "box(1 1, 2 2)", + sqrt(2.0), 2, strategy); + + test_distance_of_geometries + < + double_point, int_box + >::apply("point(0.5 0)", + "box(1 -1,2 1)", + 0.5, 0.25, strategy); + + test_distance_of_geometries + < + double_point, double_box + >::apply("point(1.5 0)", + "box(1 -1,2 1)", + 0, 0, strategy); + + test_distance_of_geometries + < + double_point, int_box + >::apply("point(1.5 0)", + "box(1 -1,2 1)", + 0, 0, strategy); + + test_distance_of_geometries + < + int_point, double_box + >::apply("point(1 0)", + "box(0.5 -1,1.5 1)", + 0, 0, strategy); + + test_distance_of_geometries + < + int_point, double_box + >::apply("point(0 0)", + "box(0.5, -1,1.5, 1)", + 0.5, 0.25, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_box_3d(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "3D point/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<box_type_3d, point_type_3d> tester; + + // point inside box + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 0 0)", 0, 0, strategy); + + // points on box corners + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 -1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 -1 1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 1 1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 -1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 -1 1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 1 1)", 0, 0, strategy); + + // points on box boundary edges + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 -1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 -1 1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 1 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 1 1)", 0, 0, strategy); + + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 0 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 0 1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 0 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 0 1)", 0, 0, strategy); + + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 -1 0)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 1 0)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 -1 0)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 1 0)", 0, 0, strategy); + + // point on box faces + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 0 -1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 0 1)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 -1 0)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 1 0)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-1 0 0)", 0, 0, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(1 0 0)", 0, 0, strategy); + + // points outside box -- closer to box corners + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-2 -3 -4)", sqrt(14.0), 14, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-2 -3 3)", 3, 9, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-2 5 -2)", sqrt(18.0), 18, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-2 5 3)", sqrt(21.0), 21, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(4 -6 -3)", sqrt(38.0), 38, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(4 -6 4)", sqrt(43.0), 43, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(4 7 -2)", sqrt(46.0), 46, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(4 7 8)", sqrt(94.0), 94, strategy); + + + // points closer to box facets + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 0 10)", 9, 81, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 0 -5)", 4, 16, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 7 0)", 6, 36, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 -6 0)", 5, 25, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(4 0 0)", 3, 9, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-3 0 0)", 2, 4, strategy); + + // points closer to box edges + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 -4 -5)", 5, 25, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 -3 6)", sqrt(29.0), 29, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 2 -7)", sqrt(37.0), 37, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(0 8 7)", sqrt(85.0), 85, strategy); + + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-4 0 -4)", sqrt(18.0), 18, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-3 0 5)", sqrt(20.0), 20, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(2 0 -6)", sqrt(26.0), 26, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(8 0 6)", sqrt(74.0), 74, strategy); + + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-5 -5 0)", sqrt(32.0), 32, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(-4 6 0)", sqrt(34.0), 34, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(3 -7 0)", sqrt(40.0), 40, strategy); + tester::apply("box(-1 -1 -1,1 1 1)", + "point(9 7 0)", 10, 100, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_box_2d(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "2D multipoint/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<box_type, multi_point_type> tester; + + // at least one point inside the box + tester::apply("box(0 0,10 10)", + "multipoint(0 0,-1 -1,20 20)", + 0, 0, strategy); + + tester::apply("box(0 0,10 10)", + "multipoint(1 1,-1 -1,20 20)", + 0, 0, strategy); + + tester::apply("box(0 0,10 10)", + "multipoint(1 1,2 2,3 3)", + 0, 0, strategy); + + // all points outside the box + tester::apply("box(0 0,10 10)", + "multipoint(-1 -1,20 20)", + sqrt(2.0), 2, strategy); + + tester::apply("box(0 0,10 10)", + "multipoint(5 13, 50 50)", + 3, 9, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_box_3d(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "3D multipoint/box distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + box_type_3d, multi_point_type_3d + > tester; + + // at least one point inside the box + tester::apply("box(0 0 0,10 10 10)", + "multipoint(0 0 0,-1 -1 -1,20 20 20)", + 0, 0, strategy); + + tester::apply("box(0 0 0,10 10 10)", + "multipoint(1 1 1,-1 -1 -1,20 20 20)", + 0, 0, strategy); + + tester::apply("box(0 0 0,10 10 10)", + "multipoint(1 1 1,2 2 2,3 3 3)", + 0, 0, strategy); + + // all points outside the box + tester::apply("box(0 0 0,10 10 10)", + "multipoint(-1 -1 -1,20 20 20)", + sqrt(3.0), 3, strategy); + + tester::apply("box(0 0 0,10 10 10)", + "multipoint(5 5 13,50 50 50)", + 3, 9, strategy); +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_pointlike_areal(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::multi_point<Point> multipoint_empty; + bg::model::polygon<Point> polygon_empty; + bg::model::multi_polygon<bg::model::polygon<Point> > multipolygon_empty; + bg::model::ring<Point> ring_empty; + + Point point = from_wkt<Point>("point(0 0)"); + bg::model::polygon<Point> polygon = + from_wkt<bg::model::polygon<Point> >("polygon((0 0,1 0,0 1))"); + bg::model::ring<Point> ring = + from_wkt<bg::model::ring<Point> >("polygon((0 0,1 0,0 1))"); + + // 1st geometry is empty + test_empty_input(multipoint_empty, polygon, strategy); + test_empty_input(multipoint_empty, ring, strategy); + + // 2nd geometry is empty + test_empty_input(point, polygon_empty, strategy); + test_empty_input(point, multipolygon_empty, strategy); + test_empty_input(point, ring_empty, strategy); + + // both geometries are empty + test_empty_input(multipoint_empty, polygon_empty, strategy); + test_empty_input(multipoint_empty, multipolygon_empty, strategy); + test_empty_input(multipoint_empty, ring_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_point_polygon ) +{ + test_distance_point_polygon(point_point_strategy()); // back-compatibility + test_distance_point_polygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_point_multipolygon ) +{ + test_distance_point_multipolygon(point_point_strategy()); // back-compatibility + test_distance_point_multipolygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_point_ring ) +{ + test_distance_point_ring(point_point_strategy()); // back-compatibility + test_distance_point_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_polygon ) +{ + test_distance_multipoint_polygon(point_point_strategy()); // back-compatibility + test_distance_multipoint_polygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_multipolygon ) +{ + test_distance_multipoint_multipolygon(point_point_strategy()); // back-compatibility + test_distance_multipoint_multipolygon(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_ring ) +{ + test_distance_multipoint_ring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_point_box_2d ) +{ + point_box_strategy pb_strategy; + + test_distance_point_box_2d(pb_strategy); + test_distance_point_box_different_point_types(pb_strategy); +} + +BOOST_AUTO_TEST_CASE( test_all_point_box_3d ) +{ + test_distance_point_box_3d(point_box_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_box_2d ) +{ + test_distance_multipoint_box_2d(point_box_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_box_3d ) +{ + test_distance_multipoint_box_3d(point_box_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_pointlike_areal ) +{ + test_more_empty_input_pointlike_areal + < + point_type + >(point_segment_strategy()); +} diff --git a/libs/geometry/test/algorithms/distance/distance_pointlike_linear.cpp b/libs/geometry/test/algorithms/distance/distance_pointlike_linear.cpp new file mode 100644 index 000000000..ad22bf120 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_pointlike_linear.cpp @@ -0,0 +1,338 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014-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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_pointlike_linear +#endif + +#include <boost/test/included/unit_test.hpp> + +#include "test_distance_common.hpp" + + +typedef bg::model::point<double,2,bg::cs::cartesian> point_type; +typedef bg::model::multi_point<point_type> multi_point_type; +typedef bg::model::segment<point_type> segment_type; +typedef bg::model::linestring<point_type> linestring_type; +typedef bg::model::multi_linestring<linestring_type> multi_linestring_type; + +namespace services = bg::strategy::distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef bg::strategy::distance::pythagoras<> point_point_strategy; +typedef bg::strategy::distance::projected_point<> point_segment_strategy; + + +//=========================================================================== + + +template <typename Strategy> +void test_distance_point_segment(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/segment distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, segment_type> tester; + + tester::apply("point(0 0)", "segment(2 0,3 0)", 2, 4, strategy); + tester::apply("point(2.5 3)", "segment(2 0,3 0)", 3, 9, strategy); + tester::apply("point(2 0)", "segment(2 0,3 0)", 0, 0, strategy); + tester::apply("point(3 0)", "segment(2 0,3 0)", 0, 0, strategy); + tester::apply("point(2.5 0)", "segment(2 0,3 0)", 0, 0, strategy); + + // distance is a NaN + tester::apply("POINT(4.297374e+307 8.433875e+307)", + "SEGMENT(26 87,13 95)", + 0, 0, strategy, false); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_linestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/linestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, linestring_type> tester; + + tester::apply("point(0 0)", "linestring(2 0,3 0)", 2, 4, strategy); + tester::apply("point(2.5 3)", "linestring(2 0,3 0)", 3, 9, strategy); + tester::apply("point(2 0)", "linestring(2 0,3 0)", 0, 0, strategy); + tester::apply("point(3 0)", "linestring(2 0,3 0)", 0, 0, strategy); + tester::apply("point(2.5 0)", "linestring(2 0,3 0)", 0, 0, strategy); + + // linestring with a single point + tester::apply("point(0 0)", "linestring(2 0)", 2, 4, strategy); + + // distance is a NaN + tester::apply("POINT(4.297374e+307 8.433875e+307)", + "LINESTRING(26 87,13 95)", + 0, 0, strategy, false); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_multilinestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/multilinestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + point_type, multi_linestring_type + > tester; + + tester::apply("point(0 0)", + "multilinestring((-5 0,-3 0),(2 0,3 0))", + 2, 4, strategy); + tester::apply("point(2.5 3)", + "multilinestring((-5 0,-3 0),(2 0,3 0))", + 3, 9, strategy); + tester::apply("point(2 0)", + "multilinestring((-5 0,-3 0),(2 0,3 0))", + 0, 0, strategy); + tester::apply("point(3 0)", + "multilinestring((-5 0,-3 0),(2 0,3 0))", + 0, 0, strategy); + tester::apply("point(2.5 0)", + "multilinestring((-5 0,-3 0),(2 0,3 0))", + 0, 0, strategy); + tester::apply("POINT(0 0)", + "MULTILINESTRING((10 10,10 0),(0.0 -0.0,0.0 -0.0))", + 0, 0, strategy); + tester::apply("POINT(0 0)", + "MULTILINESTRING((10 10,10 0),(1 1,1 1))", + sqrt(2.0), 2, strategy); + tester::apply("POINT(0 0)", + "MULTILINESTRING((10 10,10 0),(1 1,2 2))", + sqrt(2.0), 2, strategy); + tester::apply("POINT(0 0)", + "MULTILINESTRING((10 10,10 0),(20 20,20 20))", + 10, 100, strategy); + + // multilinestrings containing an empty linestring + tester::apply("POINT(0 0)", + "MULTILINESTRING((),(10 0),(20 20,20 20))", + 10, 100, strategy); + tester::apply("POINT(0 0)", + "MULTILINESTRING((),(10 0),(),(20 20,20 20))", + 10, 100, strategy); + + // multilinestrings containing a linestring with a single point + tester::apply("POINT(0 0)", + "MULTILINESTRING((10 0),(20 20,20 20))", + 10, 100, strategy); + tester::apply("POINT(0 0)", + "MULTILINESTRING((20 20,20 20),(10 0))", + 10, 100, strategy); + + // multilinestring with a single-point linestring and empty linestrings + tester::apply("POINT(0 0)", + "MULTILINESTRING((),(20 20,20 20),(),(10 0))", + 10, 100, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_multipoint(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/multipoint distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + linestring_type, multi_point_type + > tester; + + tester::apply("linestring(2 0,0 2,100 100)", + "multipoint(0 0,1 0,0 1,1 1)", + 0, 0, strategy); + tester::apply("linestring(4 0,0 4,100 100)", + "multipoint(0 0,1 0,0 1,1 1)", + sqrt(2.0), 2, strategy); + tester::apply("linestring(1 1,2 2,100 100)", + "multipoint(0 0,1 0,0 1,1 1)", + 0, 0, strategy); + tester::apply("linestring(3 3,4 4,100 100)", + "multipoint(0 0,1 0,0 1,1 1)", + sqrt(8.0), 8, strategy); + + // linestring with a single point + tester::apply("linestring(1 8)", + "multipoint(0 0,3 0,4 -7,10 100)", + sqrt(65.0), 65, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_multilinestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/multilinestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_point_type, multi_linestring_type + > tester; + + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((2 0,0 2),(2 2,3 3))", + 0, 0, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((3 0,0 3),(4 4,5 5))", + 0.5 * sqrt(2.0), 0.5, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((4 4,5 5),(1 1,2 2))", + 0, 0, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((3 3,4 4),(4 4,5 5))", + sqrt(8.0), 8, strategy); + + // multilinestring with empty linestring + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((),(3 3,4 4),(4 4,5 5))", + sqrt(8.0), 8, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((3 3,4 4),(),(4 4,5 5))", + sqrt(8.0), 8, strategy); + + // multilinestrings with a single-point linestrings + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((3 3),(4 4,5 5))", + sqrt(8.0), 8, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((4 4,5 5),(3 3))", + sqrt(8.0), 8, strategy); + + // multilinestring with a single-point linestring and empty linestring + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multilinestring((4 4,5 5),(),(3 3))", + sqrt(8.0), 8, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_segment(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/segment distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<multi_point_type, segment_type> tester; + + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "segment(2 0,0 2)", + 0, 0, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "segment(4 0,0 4)", + sqrt(2.0), 2, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "segment(1 1,2 2)", + 0, 0, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "segment(3 3,4 4)", + sqrt(8.0), 8, strategy); + tester::apply("multipoint(4 4,5 5,2 2,3 3)", + "segment(0 0,1 1)", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_pointlike_linear(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::linestring<Point> line_empty; + bg::model::multi_point<Point> multipoint_empty; + bg::model::multi_linestring<bg::model::linestring<Point> > multiline_empty; + + Point point = from_wkt<Point>("point(0 0)"); + bg::model::linestring<Point> line = + from_wkt<bg::model::linestring<Point> >("linestring(0 0,1 1)"); + + // 1st geometry is empty + test_empty_input(multipoint_empty, line, strategy); + + // 2nd geometry is empty + test_empty_input(point, line_empty, strategy); + test_empty_input(point, multiline_empty, strategy); + + // both geometries are empty + test_empty_input(multipoint_empty, line_empty, strategy); + test_empty_input(multipoint_empty, multiline_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + + +//=========================================================================== +//=========================================================================== +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_point_segment ) +{ + test_distance_point_segment(point_point_strategy()); // back-compatibility + test_distance_point_segment(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_point_linestring ) +{ + test_distance_point_linestring(point_point_strategy()); // back-compatibility + test_distance_point_linestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_point_multilinestring ) +{ + test_distance_point_multilinestring(point_point_strategy()); // back-compatibility + test_distance_point_multilinestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_multipoint ) +{ + test_distance_linestring_multipoint(point_point_strategy()); // back-compatibility + test_distance_linestring_multipoint(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_multilinestring ) +{ + test_distance_multipoint_multilinestring(point_point_strategy()); // back-compatibility + test_distance_multipoint_multilinestring(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_segment ) +{ + test_distance_multipoint_segment(point_segment_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_pointlike_linear ) +{ + test_more_empty_input_pointlike_linear + < + point_type + >(point_segment_strategy()); +} diff --git a/libs/geometry/test/algorithms/distance/distance_pointlike_pointlike.cpp b/libs/geometry/test/algorithms/distance/distance_pointlike_pointlike.cpp new file mode 100644 index 000000000..265faeb9f --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_pointlike_pointlike.cpp @@ -0,0 +1,148 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014-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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_pointlike_pointlike +#endif + +#include <boost/test/included/unit_test.hpp> + +#include "test_distance_common.hpp" + + +typedef bg::model::point<double,2,bg::cs::cartesian> point_type; +typedef bg::model::multi_point<point_type> multi_point_type; + +namespace services = bg::strategy::distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef bg::strategy::distance::pythagoras<> point_point_strategy; + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_point(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/point distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, point_type> tester; + + tester::apply("point(1 1)", + "point(0 0)", + sqrt(2.0), 2, strategy); + tester::apply("point(1 1)", + "point(1 1)", + 0, 0, strategy); + + // distance overflows + tester::apply("point(0 0)", + "point(4.297374e+307 8.433875e+307)", + 0, 0, strategy, false); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_multipoint(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/multipoint distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, multi_point_type> tester; + + tester::apply("point(1 1)", + "multipoint(1 1,2 1,2 2,1 2)", + 0, 0, strategy); + tester::apply("point(1 1)", + "multipoint(2 2,2 3,3 2,3 3)", + sqrt(2.0), 2, strategy); + tester::apply("point(3 0)", + "multipoint(2 2,2 4,4 2,4 4)", + sqrt(5.0), 5, strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_multipoint(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/multipoint distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_point_type, multi_point_type + > tester; + + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multipoint(1 1,2 1,2 2,1 2)", + 0, 0, strategy); + tester::apply("multipoint(0 0,1 0,0 1,1 1)", + "multipoint(2 2,2 3,3 2,3 3)", + sqrt(2.0), 2, strategy); +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_pointlike_pointlike(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::multi_point<Point> multipoint_empty; + + Point point = from_wkt<Point>("point(0 0)"); + + // 1st geometry is empty + test_empty_input(multipoint_empty, point, strategy); + + // 2nd geometry is empty + test_empty_input(point, multipoint_empty, strategy); + + // both geometries are empty + test_empty_input(multipoint_empty, multipoint_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_point_point ) +{ + test_distance_point_point(point_point_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_point_multipoint ) +{ + test_distance_point_multipoint(point_point_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_multipoint ) +{ + test_distance_multipoint_multipoint(point_point_strategy()); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_pointlike_pointlike ) +{ + test_more_empty_input_pointlike_pointlike + < + point_type + >(point_point_strategy()); +} diff --git a/libs/geometry/test/algorithms/distance/distance_se_pl_l.cpp b/libs/geometry/test/algorithms/distance/distance_se_pl_l.cpp new file mode 100644 index 000000000..65c80f8d2 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_se_pl_l.cpp @@ -0,0 +1,566 @@ +// 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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_spherical_equatorial_pl_l +#endif + +#include <boost/test/included/unit_test.hpp> + +#include "test_distance_se_common.hpp" + + +typedef bg::cs::spherical_equatorial<bg::degree> cs_type; +typedef bg::model::point<double, 2, cs_type> point_type; +typedef bg::model::segment<point_type> segment_type; +typedef bg::model::multi_point<point_type> multi_point_type; +typedef bg::model::segment<point_type> segment_type; +typedef bg::model::linestring<point_type> linestring_type; +typedef bg::model::multi_linestring<linestring_type> multi_linestring_type; + +namespace services = bg::strategy::distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef bg::strategy::distance::haversine<double> point_point_strategy; +typedef bg::strategy::distance::cross_track<> point_segment_strategy; + + +//=========================================================================== + +template <typename Strategy> +inline bg::default_distance_result<point_type>::type +pp_distance(std::string const& wkt1, + std::string const& wkt2, + Strategy const& strategy) +{ + point_type p1, p2; + bg::read_wkt(wkt1, p1); + bg::read_wkt(wkt2, p2); + return bg::distance(p1, p2) * strategy.radius(); +} + +template <typename Strategy> +inline bg::default_comparable_distance_result<point_type>::type +pp_comparable_distance(std::string const& wkt1, + std::string const& wkt2, + Strategy const&) +{ + point_type p1, p2; + bg::read_wkt(wkt1, p1); + bg::read_wkt(wkt2, p2); + return bg::comparable_distance(p1, p2); +} + +template <typename Strategy> +inline bg::default_distance_result<point_type>::type +ps_distance(std::string const& wkt1, + std::string const& wkt2, + Strategy const& strategy) +{ + point_type p; + segment_type s; + bg::read_wkt(wkt1, p); + bg::read_wkt(wkt2, s); + return bg::distance(p, s, strategy); +} + +template <typename Strategy> +inline bg::default_comparable_distance_result<point_type>::type +ps_comparable_distance(std::string const& wkt1, + std::string const& wkt2, + Strategy const& strategy) +{ + point_type p; + segment_type s; + bg::read_wkt(wkt1, p); + bg::read_wkt(wkt2, s); + return bg::comparable_distance(p, s, strategy); +} + +template <typename Strategy, typename T> +T to_comparable(Strategy const& strategy, T const& distance) +{ + namespace services = bg::strategy::distance::services; + + typedef typename services::comparable_type + < + Strategy + >::type comparable_strategy; + + typedef typename services::result_from_distance + < + comparable_strategy, + point_type, + bg::point_type<segment_type>::type + > get_comparable_distance; + + comparable_strategy cstrategy = services::get_comparable + < + Strategy + >::apply(strategy); + + return get_comparable_distance::apply(cstrategy, distance); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_segment(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/segment distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, segment_type> tester; + + tester::apply("p-s-01", + "POINT(0 0)", + "SEGMENT(2 0,3 0)", + 2.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 2.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-s-02", + "POINT(2.5 3)", + "SEGMENT(2 0,3 0)", + 3.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 3.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-s-03", + "POINT(2 0)", + "SEGMENT(2 0,3 0)", + 0, + strategy); + tester::apply("p-s-04", + "POINT(3 0)", + "SEGMENT(2 0,3 0)", + 0, + strategy); + tester::apply("p-s-05", + "POINT(2.5 0)", + "SEGMENT(2 0,3 0)", + 0, + strategy); + tester::apply("p-s-06", + "POINT(3.5 3)", + "SEGMENT(2 0,3 0)", + pp_distance("POINT(3 0)", "POINT(3.5 3)", strategy), + pp_comparable_distance("POINT(3 0)", + "POINT(3.5 3)", + strategy), + strategy); + // very small distances to segment + tester::apply("p-s-07", + "POINT(90 1e-3)", + "SEGMENT(0.5 0,175.5 0)", + 1e-3 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 1e-3 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-s-08", + "POINT(90 1e-4)", + "SEGMENT(0.5 0,175.5 0)", + 1e-4 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 1e-4 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-s-09", + "POINT(90 1e-5)", + "SEGMENT(0.5 0,175.5 0)", + 1e-5 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 1e-5 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-s-10", + "POINT(90 1e-6)", + "SEGMENT(0.5 0,175.5 0)", + 1e-6 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 1e-6 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-s-11", + "POINT(90 1e-7)", + "SEGMENT(0.5 0,175.5 0)", + 1e-7 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 1e-7 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-s-12", + "POINT(90 1e-8)", + "SEGMENT(0.5 0,175.5 0)", + 1e-8 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 1e-8 * bg::math::d2r * strategy.radius()), + strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_linestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/linestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, linestring_type> tester; + + tester::apply("p-l-01", + "POINT(0 0)", + "LINESTRING(2 0,2 0)", + 2.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 2.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-l-02", + "POINT(0 0)", + "LINESTRING(2 0,3 0)", + 2.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 2.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-l-03", + "POINT(2.5 3)", + "LINESTRING(2 0,3 0)", + 3.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 3.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-l-04", + "POINT(2 0)", + "LINESTRING(2 0,3 0)", + 0, + strategy); + tester::apply("p-l-05", + "POINT(3 0)", + "LINESTRING(2 0,3 0)", + 0, + strategy); + tester::apply("p-l-06", + "POINT(2.5 0)", + "LINESTRING(2 0,3 0)", + 0, + strategy); + tester::apply("p-l-07", + "POINT(7.5 10)", + "LINESTRING(1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 0)", + 10.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 10.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-l-08", + "POINT(7.5 10)", + "LINESTRING(1 1,2 1,3 1,4 1,5 1,6 1,7 1,20 2,21 2)", + ps_distance("POINT(7.5 10)", "SEGMENT(7 1,20 2)", strategy), + ps_comparable_distance("POINT(7.5 10)", + "SEGMENT(7 1,20 2)", + strategy), + strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_multilinestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/multilinestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + point_type, multi_linestring_type + > tester; + + tester::apply("p-ml-01", + "POINT(0 0)", + "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", + 2.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 2.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-ml-02", + "POINT(2.5 3)", + "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", + 3.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 3.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("p-ml-03", + "POINT(2 0)", + "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", + 0, + strategy); + tester::apply("p-ml-04", + "POINT(3 0)", + "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", + 0, + strategy); + tester::apply("p-ml-05", + "POINT(2.5 0)", + "MULTILINESTRING((-5 0,-3 0),(2 0,3 0))", + 0, + strategy); + tester::apply("p-ml-06", + "POINT(7.5 10)", + "MULTILINESTRING((-5 0,-3 0),(2 0,3 0,4 0,5 0,6 0,20 1,21 1))", + ps_distance("POINT(7.5 10)", "SEGMENT(6 0,20 1)", strategy), + ps_comparable_distance("POINT(7.5 10)", + "SEGMENT(6 0,20 1)", + strategy), + strategy); + tester::apply("p-ml-07", + "POINT(-8 10)", + "MULTILINESTRING((-20 10,-19 11,-18 10,-6 0,-5 0,-3 0),(2 0,6 0,20 1,21 1))", + ps_distance("POINT(-8 10)", "SEGMENT(-6 0,-18 10)", strategy), + ps_comparable_distance("POINT(-8 10)", + "SEGMENT(-6 0,-18 10)", + strategy), + strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_linestring_multipoint(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "linestring/multipoint distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + linestring_type, multi_point_type + > tester; + + tester::apply("l-mp-01", + "LINESTRING(2 0,0 2,100 80)", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + ps_distance("POINT(1 1)", "SEGMENT(2 0,0 2)", strategy), + ps_comparable_distance("POINT(1 1)", + "SEGMENT(2 0,0 2)", + strategy), + strategy); + tester::apply("l-mp-02", + "LINESTRING(4 0,0 4,100 80)", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + ps_distance("POINT(1 1)", "SEGMENT(0 4,4 0)", strategy), + ps_comparable_distance("POINT(1 1)", + "SEGMENT(0 4,4 0)", + strategy), + strategy); + tester::apply("l-mp-03", + "LINESTRING(1 1,2 2,100 80)", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + 0, + strategy); + tester::apply("l-mp-04", + "LINESTRING(3 3,4 4,100 80)", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + pp_distance("POINT(1 1)", "POINT(3 3)", strategy), + pp_comparable_distance("POINT(1 1)", "POINT(3 3)", strategy), + strategy); + tester::apply("l-mp-05", + "LINESTRING(0 0,10 0,10 10,0 10,0 0)", + "MULTIPOINT(1 -1,80 80,5 0,150 90)", + 0, + strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_multilinestring(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/multilinestring distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_point_type, multi_linestring_type + > tester; + + tester::apply("mp-ml-01", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "MULTILINESTRING((2 0,0 2),(2 2,3 3))", + ps_distance("POINT(1 1)", "SEGMENT(2 0,0 2)", strategy), + ps_comparable_distance("POINT(1 1)", + "SEGMENT(2 0,0 2)", + strategy), + strategy); + tester::apply("mp-ml-02", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "MULTILINESTRING((3 0,0 3),(4 4,5 5))", + ps_distance("POINT(1 1)", "SEGMENT(3 0,0 3)", strategy), + ps_comparable_distance("POINT(1 1)", + "SEGMENT(3 0,0 3)", + strategy), + strategy); + tester::apply("mp-ml-03", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "MULTILINESTRING((4 4,5 5),(1 1,2 2))", + 0, + strategy); + tester::apply("mp-ml-04", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "MULTILINESTRING((4 4,3 3),(4 4,5 5))", + pp_distance("POINT(1 1)", "POINT(3 3)", strategy), + pp_comparable_distance("POINT(1 1)", "POINT(3 3)", strategy), + strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_segment(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/segment distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<multi_point_type, segment_type> tester; + + tester::apply("mp-s-01", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "SEGMENT(2 0,0 2)", + ps_distance("POINT(1 1)", "SEGMENT(2 0,0 2)", strategy), + ps_comparable_distance("POINT(1 1)", + "SEGMENT(2 0,0 2)", + strategy), + strategy); + tester::apply("mp-s-02", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "SEGMENT(0 -3,1 -10)", + 3.0 * bg::math::d2r * strategy.radius(), + to_comparable(strategy, + 3.0 * bg::math::d2r * strategy.radius()), + strategy); + tester::apply("mp-s-03", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "SEGMENT(1 1,2 2)", + 0, + strategy); + tester::apply("mp-s-04", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "SEGMENT(3 3,4 4)", + pp_distance("POINT(1 1)", "POINT(3 3)", strategy), + pp_comparable_distance("POINT(1 1)", "POINT(3 3)", strategy), + strategy); + tester::apply("mp-s-05", + "MULTIPOINT(0 0,1 0,0 1,1 1)", + "SEGMENT(0.5 -3,1 -10)", + pp_distance("POINT(1 0)", "POINT(0.5 -3)", strategy), + pp_comparable_distance("POINT(1 0)", + "POINT(0.5 -3)", + strategy), + strategy); +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_pointlike_linear(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::linestring<Point> line_empty; + bg::model::multi_point<Point> multipoint_empty; + bg::model::multi_linestring<bg::model::linestring<Point> > multiline_empty; + + Point point = from_wkt<Point>("POINT(0 0)"); + bg::model::linestring<Point> line = + from_wkt<bg::model::linestring<Point> >("LINESTRING(0 0,1 1)"); + + // 1st geometry is empty + test_empty_input(multipoint_empty, line, strategy); + + // 2nd geometry is empty + test_empty_input(point, line_empty, strategy); + test_empty_input(point, multiline_empty, strategy); + + // both geometries are empty + test_empty_input(multipoint_empty, line_empty, strategy); + test_empty_input(multipoint_empty, multiline_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + + +//=========================================================================== +//=========================================================================== +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_point_segment ) +{ + test_distance_point_segment(point_segment_strategy()); + test_distance_point_segment(point_segment_strategy(earth_radius_km)); + test_distance_point_segment(point_segment_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_point_linestring ) +{ + test_distance_point_linestring(point_segment_strategy()); + test_distance_point_linestring(point_segment_strategy(earth_radius_km)); + test_distance_point_linestring(point_segment_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_point_multilinestring ) +{ + test_distance_point_multilinestring(point_segment_strategy()); + test_distance_point_multilinestring(point_segment_strategy(earth_radius_km)); + test_distance_point_multilinestring(point_segment_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_linestring_multipoint ) +{ + test_distance_linestring_multipoint(point_segment_strategy()); + test_distance_linestring_multipoint(point_segment_strategy(earth_radius_km)); + test_distance_linestring_multipoint(point_segment_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_multilinestring ) +{ + test_distance_multipoint_multilinestring(point_segment_strategy()); + test_distance_multipoint_multilinestring(point_segment_strategy(earth_radius_km)); + test_distance_multipoint_multilinestring(point_segment_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_segment ) +{ + test_distance_multipoint_segment(point_segment_strategy()); + test_distance_multipoint_segment(point_segment_strategy(earth_radius_km)); + test_distance_multipoint_segment(point_segment_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_pointlike_linear ) +{ + test_more_empty_input_pointlike_linear + < + point_type + >(point_segment_strategy()); + + test_more_empty_input_pointlike_linear + < + point_type + >(point_segment_strategy(earth_radius_km)); + + test_more_empty_input_pointlike_linear + < + point_type + >(point_segment_strategy(earth_radius_miles)); +} diff --git a/libs/geometry/test/algorithms/distance/distance_se_pl_pl.cpp b/libs/geometry/test/algorithms/distance/distance_se_pl_pl.cpp new file mode 100644 index 000000000..2e14e8892 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/distance_se_pl_pl.cpp @@ -0,0 +1,303 @@ +// 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 + +#include <iostream> + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_distance_spherical_equatorial_pl_pl +#endif + +#include <boost/range.hpp> + +#include <boost/test/included/unit_test.hpp> +#include <boost/geometry/strategies/strategies.hpp> + +#include "test_distance_se_common.hpp" + + +typedef bg::cs::spherical_equatorial<bg::degree> cs_type; +typedef bg::model::point<double, 2, cs_type> point_type; +typedef bg::model::multi_point<point_type> multi_point_type; + +namespace distance = bg::strategy::distance; +namespace services = distance::services; +typedef bg::default_distance_result<point_type>::type return_type; + +typedef distance::haversine<double> point_point_strategy; +typedef distance::comparable::haversine<double> comparable_point_point_strategy; + +//=========================================================================== + +template <typename Strategy> +inline typename bg::distance_result<point_type, point_type, Strategy>::type +distance_from_wkt(std::string const& wkt1, + std::string const& wkt2, + Strategy const& strategy) +{ + point_type p1, p2; + bg::read_wkt(wkt1, p1); + bg::read_wkt(wkt2, p2); + return bg::distance(p1, p2, strategy); +} + +inline bg::default_comparable_distance_result<point_type>::type +comparable_distance_from_wkt(std::string const& wkt1, + std::string const& wkt2) +{ + point_type p1, p2; + bg::read_wkt(wkt1, p1); + bg::read_wkt(wkt2, p2); + return bg::comparable_distance(p1, p2); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_point(Strategy const& strategy, + bool is_comparable_strategy = false) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/point distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, point_type> tester; + + tester::apply("p-p-01", + "POINT(10 10)", + "POINT(0 0)", + (is_comparable_strategy + ? 0.0150768448035229 + : (0.24619691677893202 * strategy.radius())), + 0.0150768448035229, + strategy); + tester::apply("p-p-02", + "POINT(10 10)", + "POINT(10 10)", + 0, + strategy); + + // antipodal points + tester::apply("p-p-03", + "POINT(0 10)", + "POINT(180 -10)", + (is_comparable_strategy + ? 1.0 + : (180.0 * bg::math::d2r * strategy.radius())), + 1.0, + strategy); + tester::apply("p-p-04", + "POINT(0 0)", + "POINT(180 0)", + (is_comparable_strategy + ? 1.0 + : (180.0 * bg::math::d2r * strategy.radius())), + 1.0, + strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_point_multipoint(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/multipoint distance tests" << std::endl; +#endif + typedef test_distance_of_geometries<point_type, multi_point_type> tester; + + tester::apply("p-mp-01", + "POINT(10 10)", + "MULTIPOINT(10 10,20 10,20 20,10 20)", + 0, + strategy); + tester::apply("p-mp-02", + "POINT(10 10)", + "MULTIPOINT(20 20,20 30,30 20,30 30)", + distance_from_wkt("POINT(10 10)", "POINT(20 20)", strategy), + comparable_distance_from_wkt("POINT(10 10)", "POINT(20 20)"), + strategy); + tester::apply("p-mp-03", + "POINT(3 0)", + "MULTIPOINT(20 20,20 40,40 20,40 40)", + distance_from_wkt("POINT(3 0)", "POINT(20 20)", strategy), + comparable_distance_from_wkt("POINT(3 0)", "POINT(20 20)"), + strategy); + + // almost antipodal points + tester::apply("p-mp-04", + "POINT(179 2)", + "MULTIPOINT(3 3,4 3,4 4,3 4)", + distance_from_wkt("POINT(179 2)", "POINT(4 4)", strategy), + comparable_distance_from_wkt("POINT(179 2)", "POINT(4 4)"), + strategy); + + // minimum distance across the dateline + tester::apply("p-mp-05", + "POINT(355 5)", + "MULTIPOINT(10 10,20 10,20 20,10 20)", + distance_from_wkt("POINT(355 5)", "POINT(10 10)", strategy), + comparable_distance_from_wkt("POINT(355 5)", "POINT(10 10)"), + strategy); + tester::apply("p-mp-06", + "POINT(-5 5)", + "MULTIPOINT(10 10,20 10,20 20,10 20)", + distance_from_wkt("POINT(-5 5)", "POINT(10 10)", strategy), + comparable_distance_from_wkt("POINT(-5 5)", "POINT(10 10)"), + strategy); +} + +//=========================================================================== + +template <typename Strategy> +void test_distance_multipoint_multipoint(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "multipoint/multipoint distance tests" << std::endl; +#endif + typedef test_distance_of_geometries + < + multi_point_type, multi_point_type + > tester; + + tester::apply("mp-mp-01", + "MULTIPOINT(10 10,11 10,10 11,11 11)", + "MULTIPOINT(11 11,12 11,12 12,11 12)", + 0, + strategy); + tester::apply("mp-mp-02", + "MULTIPOINT(10 10,11 10,10 11,11 11)", + "MULTIPOINT(12 12,12 13,13 12,13 13)", + distance_from_wkt("POINT(11 11)", "POINT(12 12)", strategy), + comparable_distance_from_wkt("POINT(11 11)", "POINT(12 12)"), + strategy); + + // example with many points in each multi-point so that the r-tree + // does some splitting. + tester::apply("mp-mp-03", + "MULTIPOINT(1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 8,1 9,1 10,\ + 2 1,2 2,2 3,2 4,2 5,2 6,2 7,2 8,2 9,2 10,\ + 3 1,3 2,3 3,3 4,3 5,3 6,3 7,3 8,3 9,3 10,\ + 10 1,10 10)", + "MULTIPOINT(11 11,11 12,11 13,11 14,11 15,\ + 11 16,11 17,11 18,11 19,11 20,\ + 12 11,12 12,12 13,12 24,12 15,\ + 12 16,12 17,12 18,12 29,12 20,\ + 13 11,13 12,13 13,13 24,13 15,\ + 13 16,13 17,13 18,13 29,13 20,\ + 20 11,20 20)", + distance_from_wkt("POINT(10 10)", "POINT(11 11)", strategy), + comparable_distance_from_wkt("POINT(10 10)", "POINT(11 11)"), + strategy); + +} + +//=========================================================================== + +template <typename Point, typename Strategy> +void test_more_empty_input_pointlike_pointlike(Strategy const& strategy) +{ +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "testing on empty inputs... " << std::flush; +#endif + bg::model::multi_point<Point> multipoint_empty; + + Point point = from_wkt<Point>("POINT(0 0)"); + + // 1st geometry is empty + test_empty_input(multipoint_empty, point, strategy); + + // 2nd geometry is empty + test_empty_input(point, multipoint_empty, strategy); + + // both geometries are empty + test_empty_input(multipoint_empty, multipoint_empty, strategy); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "done!" << std::endl; +#endif +} + +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_all_point_point ) +{ + test_distance_point_point(point_point_strategy()); + test_distance_point_point(point_point_strategy(earth_radius_km)); + test_distance_point_point(point_point_strategy(earth_radius_miles)); + + test_distance_point_point(comparable_point_point_strategy(), true); + test_distance_point_point + (comparable_point_point_strategy(earth_radius_km), true); + test_distance_point_point + (comparable_point_point_strategy(earth_radius_miles), true); +} + +BOOST_AUTO_TEST_CASE( test_all_point_multipoint ) +{ + test_distance_point_multipoint(point_point_strategy()); + test_distance_point_multipoint(point_point_strategy(earth_radius_km)); + test_distance_point_multipoint(point_point_strategy(earth_radius_miles)); + + test_distance_point_multipoint(comparable_point_point_strategy()); + test_distance_point_multipoint + (comparable_point_point_strategy(earth_radius_km)); + test_distance_point_multipoint + (comparable_point_point_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_multipoint_multipoint ) +{ + test_distance_multipoint_multipoint(point_point_strategy()); + test_distance_multipoint_multipoint(point_point_strategy(earth_radius_km)); + test_distance_multipoint_multipoint + (point_point_strategy(earth_radius_miles)); + + test_distance_multipoint_multipoint(comparable_point_point_strategy()); + test_distance_multipoint_multipoint + (comparable_point_point_strategy(earth_radius_km)); + test_distance_multipoint_multipoint + (comparable_point_point_strategy(earth_radius_miles)); +} + +BOOST_AUTO_TEST_CASE( test_all_empty_input_pointlike_pointlike ) +{ + test_more_empty_input_pointlike_pointlike + < + point_type + >(point_point_strategy()); + + test_more_empty_input_pointlike_pointlike + < + point_type + >(point_point_strategy(earth_radius_km)); + + test_more_empty_input_pointlike_pointlike + < + point_type + >(point_point_strategy(earth_radius_miles)); + + test_more_empty_input_pointlike_pointlike + < + point_type + >(comparable_point_point_strategy()); + + test_more_empty_input_pointlike_pointlike + < + point_type + >(comparable_point_point_strategy(earth_radius_km)); + + test_more_empty_input_pointlike_pointlike + < + point_type + >(comparable_point_point_strategy(earth_radius_miles)); +} diff --git a/libs/geometry/test/algorithms/distance/test_distance.hpp b/libs/geometry/test/algorithms/distance/test_distance.hpp new file mode 100644 index 000000000..82154fe23 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/test_distance.hpp @@ -0,0 +1,139 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2010-2012 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) + +#ifndef BOOST_GEOMETRY_TEST_DISTANCE_HPP +#define BOOST_GEOMETRY_TEST_DISTANCE_HPP + +#include <geometry_test_common.hpp> + +#include <boost/geometry/algorithms/distance.hpp> +#include <boost/geometry/io/wkt/read.hpp> +#include <boost/geometry/strategies/strategies.hpp> + + +// Define a custom distance strategy +// For this one, the "taxicab" distance, +// see http://en.wikipedia.org/wiki/Taxicab_geometry + +// For a point-point-distance operation, one typename Point is enough. +// For a point-segment-distance operation, there is some magic inside +// using another point type and casting if necessary. Therefore, +// two point-types are necessary. +struct taxicab_distance +{ + template <typename P1, typename P2> + static inline typename bg::coordinate_type<P1>::type apply( + P1 const& p1, P2 const& p2) + { + using bg::get; + using bg::math::abs; + return abs(get<0>(p1) - get<1>(p2)) + + abs(get<1>(p1) - get<1>(p2)); + } +}; + + + +namespace boost { namespace geometry { namespace strategy { namespace distance { namespace services +{ + +template <> +struct tag<taxicab_distance> +{ + typedef strategy_tag_distance_point_point type; +}; + + +template <typename P1, typename P2> +struct return_type<taxicab_distance, P1, P2> +{ + typedef typename coordinate_type<P1>::type type; +}; + + +template <> +struct comparable_type<taxicab_distance> +{ + typedef taxicab_distance type; +}; + +template <> +struct get_comparable<taxicab_distance> +{ + static inline taxicab_distance apply(taxicab_distance const& input) + { + return input; + } +}; + +template <typename P1, typename P2> +struct result_from_distance<taxicab_distance, P1, P2> +{ + template <typename T> + static inline typename coordinate_type<P1>::type apply(taxicab_distance const& , T const& value) + { + return value; + } +}; + + +}}}}} // namespace bg::strategy::distance::services + + + + + +template <typename Geometry1, typename Geometry2> +void test_distance(Geometry1 const& geometry1, + Geometry2 const& geometry2, + long double expected_distance) +{ + typename bg::default_distance_result<Geometry1>::type distance = bg::distance(geometry1, geometry2); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::ostringstream out; + out << typeid(typename bg::coordinate_type<Geometry1>::type).name() + << std::endl + << typeid(typename bg::default_distance_result<Geometry1>::type).name() + << std::endl + << "distance : " << bg::distance(geometry1, geometry2) + << std::endl; + std::cout << out.str(); +#endif + + BOOST_CHECK_CLOSE(distance, expected_distance, 0.0001); +} + + +template <typename Geometry1, typename Geometry2> +void test_geometry(std::string const& wkt1, std::string const& wkt2, double expected_distance) +{ + Geometry1 geometry1; + bg::read_wkt(wkt1, geometry1); + Geometry2 geometry2; + bg::read_wkt(wkt2, geometry2); + + test_distance(geometry1, geometry2, expected_distance); +} + +template <typename Geometry1, typename Geometry2> +void test_empty_input(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + try + { + bg::distance(geometry1, geometry2); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" ); +} + + +#endif diff --git a/libs/geometry/test/algorithms/distance/test_distance_common.hpp b/libs/geometry/test/algorithms/distance/test_distance_common.hpp new file mode 100644 index 000000000..11ef52c40 --- /dev/null +++ b/libs/geometry/test/algorithms/distance/test_distance_common.hpp @@ -0,0 +1,605 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2014-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_GEOMETRY_TEST_DISTANCE_COMMON_HPP +#define BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP + +#include <iostream> +#include <string> + +#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/point_xy.hpp> +#include <boost/geometry/geometries/segment.hpp> +#include <boost/geometry/geometries/linestring.hpp> +#include <boost/geometry/geometries/polygon.hpp> +#include <boost/geometry/geometries/ring.hpp> +#include <boost/geometry/geometries/box.hpp> +#include <boost/geometry/geometries/multi_point.hpp> +#include <boost/geometry/geometries/multi_linestring.hpp> +#include <boost/geometry/geometries/multi_polygon.hpp> + +#include <boost/geometry/io/wkt/write.hpp> +#include <boost/geometry/io/dsv/write.hpp> + +#include <boost/geometry/algorithms/num_interior_rings.hpp> +#include <boost/geometry/algorithms/distance.hpp> +#include <boost/geometry/algorithms/comparable_distance.hpp> + +#include <from_wkt.hpp> +#include <string_from_type.hpp> + + +#ifndef BOOST_GEOMETRY_TEST_DISTANCE_HPP + +namespace bg = ::boost::geometry; + +// function copied from BG's test_distance.hpp + +template <typename Geometry1, typename Geometry2> +void test_empty_input(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + try + { + bg::distance(geometry1, geometry2); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" ); +} +#endif // BOOST_GEOMETRY_TEST_DISTANCE_HPP + + + +//======================================================================== + + + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +// pretty print geometry -- START +template <typename Geometry, typename GeometryTag> +struct pretty_print_geometry_dispatch +{ + template <typename Stream> + static inline Stream& apply(Geometry const& geometry, Stream& os) + { + os << bg::wkt(geometry); + return os; + } +}; + +template <typename Geometry> +struct pretty_print_geometry_dispatch<Geometry, bg::segment_tag> +{ + template <typename Stream> + static inline Stream& apply(Geometry const& geometry, Stream& os) + { + os << "SEGMENT" << bg::dsv(geometry); + return os; + } +}; + +template <typename Geometry> +struct pretty_print_geometry_dispatch<Geometry, bg::box_tag> +{ + template <typename Stream> + static inline Stream& apply(Geometry const& geometry, Stream& os) + { + os << "BOX" << bg::dsv(geometry); + return os; + } +}; + + +template <typename Geometry> +struct pretty_print_geometry +{ + template <typename Stream> + static inline Stream& apply(Geometry const& geometry, Stream& os) + { + return pretty_print_geometry_dispatch + < + Geometry, typename bg::tag<Geometry>::type + >::apply(geometry, os); + } +}; +// pretty print geometry -- END +#endif // BOOST_GEOMETRY_TEST_DEBUG + + +//======================================================================== + + +template <typename T> +struct check_equal +{ + static inline void apply(T const& detected, T const& expected, + bool is_finite) + { + if (is_finite) + { + BOOST_CHECK(detected == expected); + } + else + { + BOOST_CHECK(! boost::math::isfinite(detected)); + } + } +}; + +template <> +struct check_equal<double> +{ + static inline void apply(double detected, double expected, + bool is_finite) + { + if (is_finite) + { + BOOST_CHECK_CLOSE(detected, expected, 0.0001); + } + else + { + BOOST_CHECK(! boost::math::isfinite(detected)); + } + } +}; + + +//======================================================================== + +template +< + typename Geometry1, typename Geometry2, + int id1 = bg::geometry_id<Geometry1>::value, + int id2 = bg::geometry_id<Geometry2>::value +> +struct test_distance_of_geometries + : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0> +{}; + + +template <typename Geometry1, typename Geometry2> +class test_distance_of_geometries<Geometry1, Geometry2, 0, 0> +{ +private: + template + < + typename G1, + typename G2, + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void base_test(std::string const& header, + G1 const& g1, G2 const& g2, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite) + { + typedef typename bg::default_distance_result + < + G1, G2 + >::type default_distance_result; + + typedef typename bg::strategy::distance::services::return_type + < + Strategy, G1, G2 + >::type distance_result_from_strategy; + + static const bool same_regular = boost::is_same + < + default_distance_result, + distance_result_from_strategy + >::type::value; + + BOOST_CHECK( same_regular ); + + + typedef typename bg::default_comparable_distance_result + < + G1, G2 + >::type default_comparable_distance_result; + + typedef typename bg::strategy::distance::services::return_type + < + typename bg::strategy::distance::services::comparable_type + < + Strategy + >::type, + G1, + G2 + >::type comparable_distance_result_from_strategy; + + static const bool same_comparable = boost::is_same + < + default_comparable_distance_result, + comparable_distance_result_from_strategy + >::type::value; + + BOOST_CHECK( same_comparable ); + + + // check distance with default strategy + default_distance_result dist_def = bg::distance(g1, g2); + + check_equal + < + default_distance_result + >::apply(dist_def, expected_distance, is_finite); + + + // check distance with passed strategy + distance_result_from_strategy dist = bg::distance(g1, g2, strategy); + + check_equal + < + default_distance_result + >::apply(dist, expected_distance, is_finite); + + + // check comparable distance with default strategy + default_comparable_distance_result cdist_def = + bg::comparable_distance(g1, g2); + + check_equal + < + default_comparable_distance_result + >::apply(cdist_def, expected_comparable_distance, is_finite); + + + // check comparable distance with passed strategy + comparable_distance_result_from_strategy cdist = + bg::comparable_distance(g1, g2, strategy); + + check_equal + < + default_comparable_distance_result + >::apply(cdist, expected_comparable_distance, is_finite); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name() + << string_from_type<typename bg::coordinate_type<Geometry2>::type>::name() + << " -> " + << string_from_type<default_distance_result>::name() + << string_from_type<default_comparable_distance_result>::name() + << std::endl; + + std::cout << "distance" << header + << " (def. strategy) = " << dist_def << " ; " + << "distance" << header + <<" (passed strategy) = " << dist << " ; " + << "comp. distance" << header <<" (def. strategy) = " + << cdist_def << " ; " + << "comp. distance" << header <<" (passed strategy) = " + << cdist << std::endl; +#endif + } + +public: + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(std::string const& wkt1, + std::string const& wkt2, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite = true) + { + Geometry1 geometry1 = from_wkt<Geometry1>(wkt1); + Geometry2 geometry2 = from_wkt<Geometry2>(wkt2); + + apply(geometry1, geometry2, + expected_distance, expected_comparable_distance, + strategy, is_finite); + } + + + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite = true) + { +#ifdef BOOST_GEOMETRY_TEST_DEBUG + typedef pretty_print_geometry<Geometry1> PPG1; + typedef pretty_print_geometry<Geometry2> PPG2; + PPG1::apply(geometry1, std::cout); + std::cout << " - "; + PPG2::apply(geometry2, std::cout); + std::cout << std::endl; +#endif + + base_test("", geometry1, geometry2, + expected_distance, expected_comparable_distance, + strategy, is_finite); + + base_test("[reversed args]", geometry2, geometry1, + expected_distance, expected_comparable_distance, + strategy, is_finite); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; +#endif + } +}; + + +//======================================================================== + +template <typename Segment, typename Polygon> +struct test_distance_of_geometries +< + Segment, Polygon, + 92 /* segment */, 3 /* polygon */ +> + : public test_distance_of_geometries<Segment, Polygon, 0, 0> +{ + typedef test_distance_of_geometries<Segment, Polygon, 0, 0> base; + + typedef typename bg::ring_type<Polygon>::type ring_type; + + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(std::string const& wkt_segment, + std::string const& wkt_polygon, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite = true) + { + Segment segment = from_wkt<Segment>(wkt_segment); + Polygon polygon = from_wkt<Polygon>(wkt_polygon); + apply(segment, + polygon, + expected_distance, + expected_comparable_distance, + strategy, + is_finite); + } + + + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(Segment const& segment, + Polygon const& polygon, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite = true) + { + base::apply(segment, polygon, expected_distance, + expected_comparable_distance, strategy, is_finite); + + if ( bg::num_interior_rings(polygon) == 0 ) { +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "... testing also exterior ring ..." << std::endl; +#endif + test_distance_of_geometries + < + Segment, ring_type + >::apply(segment, + bg::exterior_ring(polygon), + expected_distance, + expected_comparable_distance, + strategy, + is_finite); + } + } +}; + +//======================================================================== + +template <typename Box, typename Segment> +struct test_distance_of_geometries +< + Box, Segment, + 94 /* box */, 92 /* segment */ +> +{ + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(std::string const& wkt_box, + std::string const& wkt_segment, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite = true) + { + test_distance_of_geometries + < + Segment, Box, 92, 94 + >::apply(wkt_segment, + wkt_box, + expected_distance, + expected_comparable_distance, + strategy, + is_finite); + } +}; + + +template <typename Segment, typename Box> +struct test_distance_of_geometries +< + Segment, Box, + 92 /* segment */, 94 /* box */ +> + : public test_distance_of_geometries<Segment, Box, 0, 0> +{ + typedef test_distance_of_geometries<Segment, Box, 0, 0> base; + + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(std::string const& wkt_segment, + std::string const& wkt_box, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite = true) + { + Segment segment = from_wkt<Segment>(wkt_segment); + Box box = from_wkt<Box>(wkt_box); + apply(segment, + box, + expected_distance, + expected_comparable_distance, + strategy, + is_finite); + } + + + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(Segment const& segment, + Box const& box, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool is_finite = true) + { + typedef typename bg::strategy::distance::services::return_type + < + Strategy, Segment, Box + >::type distance_result_type; + + typedef typename bg::strategy::distance::services::comparable_type + < + Strategy + >::type comparable_strategy; + + typedef typename bg::strategy::distance::services::return_type + < + comparable_strategy, Segment, Box + >::type comparable_distance_result_type; + + + base::apply(segment, box, expected_distance, + expected_comparable_distance, strategy, is_finite); + + comparable_strategy cstrategy = + bg::strategy::distance::services::get_comparable + < + Strategy + >::apply(strategy); + + distance_result_type distance_generic = + bg::detail::distance::segment_to_box_2D_generic + < + Segment, Box, Strategy + >::apply(segment, box, strategy); + + comparable_distance_result_type comparable_distance_generic = + bg::detail::distance::segment_to_box_2D_generic + < + Segment, Box, comparable_strategy + >::apply(segment, box, cstrategy); + + + check_equal + < + distance_result_type + >::apply(distance_generic, expected_distance, is_finite); + + check_equal + < + comparable_distance_result_type + >::apply(comparable_distance_generic, + expected_comparable_distance, + is_finite); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "... testing with naive seg-box distance algorithm..." + << std::endl; + std::cout << "distance (generic algorithm) = " + << distance_generic << " ; " + << "comp. distance (generic algorithm) = " + << comparable_distance_generic + << std::endl; + std::cout << std::endl << std::endl; +#endif + } +}; + +//======================================================================== + + +template <typename Geometry1, typename Geometry2, typename Strategy> +void test_empty_input(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + try + { + bg::distance(geometry1, geometry2, strategy); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" ); + + try + { + bg::distance(geometry2, geometry1, strategy); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" ); +} + +#endif // BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP diff --git a/libs/geometry/test/algorithms/distance/test_distance_se_common.hpp b/libs/geometry/test/algorithms/distance/test_distance_se_common.hpp new file mode 100644 index 000000000..5e846346d --- /dev/null +++ b/libs/geometry/test/algorithms/distance/test_distance_se_common.hpp @@ -0,0 +1,381 @@ +// 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_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP +#define BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP + +#include <iostream> +#include <string> + +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/geometries/point_xy.hpp> +#include <boost/geometry/geometries/segment.hpp> +#include <boost/geometry/geometries/linestring.hpp> +#include <boost/geometry/geometries/polygon.hpp> +#include <boost/geometry/geometries/ring.hpp> +#include <boost/geometry/geometries/box.hpp> +#include <boost/geometry/multi/geometries/multi_point.hpp> +#include <boost/geometry/multi/geometries/multi_linestring.hpp> +#include <boost/geometry/multi/geometries/multi_polygon.hpp> + +#include <boost/geometry/io/wkt/write.hpp> +#include <boost/geometry/multi/io/wkt/write.hpp> + +#include <boost/geometry/io/dsv/write.hpp> +#include <boost/geometry/multi/io/dsv/write.hpp> + +#include <boost/geometry/algorithms/num_interior_rings.hpp> +#include <boost/geometry/algorithms/distance.hpp> +#include <boost/geometry/algorithms/comparable_distance.hpp> + +#include <from_wkt.hpp> +#include <string_from_type.hpp> + +#include "distance_brute_force.hpp" + +namespace bg = ::boost::geometry; + +static const double earth_radius_km = 6371.0; +static const double earth_radius_miles = 3959.0; + + +//======================================================================== + + +template <typename T> +struct check_equal +{ + template <typename Value, typename = void> + struct equal_to + { + static inline void apply(Value const& x, Value const& y) + { + BOOST_CHECK(x == y); + } + }; + + template <typename Dummy> + struct equal_to<double, Dummy> + { + static inline void apply(double x, double y) + { + BOOST_CHECK_CLOSE(x, y, 0.001); + } + }; + + template <typename Geometry1, typename Geometry2> + static inline void apply(std::string const& /*case_id*/, + std::string const& /*subcase_id*/, + Geometry1 const& /*geometry1*/, + Geometry2 const& /*geometry2*/, + T const& detected, + T const& expected) + { + equal_to<T>::apply(expected, detected); + /* + TODO: + Ideally we would want the following, but it does not work well + approximate equality test. + + BOOST_CHECK_MESSAGE(equal_to<T>::apply(expected, detected), + "case ID: " << case_id << "-" << subcase_id << "; " + << "G1: " << bg::wkt(geometry1) + << " - " + << "G2: " << bg::wkt(geometry2) + << " -> Detected: " << detected + << "; Expected: " << expected); + */ + } +}; + +//======================================================================== + +template +< + typename Geometry1, typename Geometry2, + int id1 = bg::geometry_id<Geometry1>::value, + int id2 = bg::geometry_id<Geometry2>::value +> +struct test_distance_of_geometries + : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0> +{}; + + +template <typename Geometry1, typename Geometry2> +struct test_distance_of_geometries<Geometry1, Geometry2, 0, 0> +{ + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(std::string const& case_id, + std::string const& wkt1, + std::string const& wkt2, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool test_reversed = true) + { + Geometry1 geometry1 = from_wkt<Geometry1>(wkt1); + Geometry2 geometry2 = from_wkt<Geometry2>(wkt2); + + apply(case_id, geometry1, geometry2, + expected_distance, expected_comparable_distance, + strategy, test_reversed); + } + + template <typename DistanceType, typename Strategy> + static inline + void apply(std::string const& case_id, + std::string const& wkt1, + std::string const& wkt2, + DistanceType const& expected_distance, + Strategy const& strategy, + bool test_reversed = true) + { + Geometry1 geometry1 = from_wkt<Geometry1>(wkt1); + Geometry2 geometry2 = from_wkt<Geometry2>(wkt2); + + apply(case_id, geometry1, geometry2, + expected_distance, expected_distance, + strategy, test_reversed); + } + + + template + < + typename DistanceType, + typename ComparableDistanceType, + typename Strategy + > + static inline + void apply(std::string const& case_id, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + DistanceType const& expected_distance, + ComparableDistanceType const& expected_comparable_distance, + Strategy const& strategy, + bool test_reversed = true) + { +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "case ID: " << case_id << "; " + << "G1: " << bg::wkt(geometry1) + << " - " + << "G2: " << bg::wkt(geometry2) + << std::endl; +#endif + namespace services = bg::strategy::distance::services; + + using bg::unit_test::distance_brute_force; + + typedef typename bg::default_distance_result + < + Geometry1, Geometry2 + >::type default_distance_result; + + typedef typename services::return_type + < + Strategy, Geometry1, Geometry2 + >::type distance_result_from_strategy; + + static const bool same_regular = boost::is_same + < + default_distance_result, + distance_result_from_strategy + >::type::value; + + BOOST_CHECK(same_regular); + + typedef typename bg::default_comparable_distance_result + < + Geometry1, Geometry2 + >::type default_comparable_distance_result; + + typedef typename services::return_type + < + typename services::comparable_type<Strategy>::type, + Geometry1, + Geometry2 + >::type comparable_distance_result_from_strategy; + + static const bool same_comparable = boost::is_same + < + default_comparable_distance_result, + comparable_distance_result_from_strategy + >::type::value; + + BOOST_CHECK( same_comparable ); + + // check distance with passed strategy + distance_result_from_strategy dist = + bg::distance(geometry1, geometry2, strategy); + + check_equal + < + distance_result_from_strategy + >::apply(case_id, "a", geometry1, geometry2, + dist, expected_distance); + + // check against the comparable distance computed in a + // brute-force manner + default_distance_result dist_brute_force + = distance_brute_force(geometry1, geometry2, strategy); + + check_equal + < + default_distance_result + >::apply(case_id, "b", geometry1, geometry2, + dist_brute_force, expected_distance); + + // check comparable distance with passed strategy + comparable_distance_result_from_strategy cdist = + bg::comparable_distance(geometry1, geometry2, strategy); + + check_equal + < + default_comparable_distance_result + >::apply(case_id, "c", geometry1, geometry2, + cdist, expected_comparable_distance); + + // check against the comparable distance computed in a + // brute-force manner + default_comparable_distance_result cdist_brute_force + = distance_brute_force(geometry1, + geometry2, + services::get_comparable + < + Strategy + >::apply(strategy)); + + check_equal + < + default_comparable_distance_result + >::apply(case_id, "d", geometry1, geometry2, + cdist_brute_force, expected_comparable_distance); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name() + << string_from_type<typename bg::coordinate_type<Geometry2>::type>::name() + << " -> " + << string_from_type<default_distance_result>::name() + << string_from_type<default_comparable_distance_result>::name() + << std::endl; + std::cout << "strategy radius: " << strategy.radius() << std::endl; + std::cout << "expected distance = " + << expected_distance << " ; " + << "expected comp. distance = " + << expected_comparable_distance + << std::endl; + std::cout << "distance = " + << dist << " ; " + << "comp. distance = " + << cdist + << std::endl; + + if ( !test_reversed ) + { + std::cout << std::endl; + } +#endif + + if ( test_reversed ) + { + // check distance with given strategy + dist = bg::distance(geometry2, geometry1, strategy); + + check_equal + < + default_distance_result + >::apply(case_id, "ra", geometry2, geometry1, + dist, expected_distance); + + // check comparable distance with given strategy + cdist = bg::comparable_distance(geometry2, geometry1, strategy); + + check_equal + < + default_comparable_distance_result + >::apply(case_id, "rc", geometry2, geometry1, + cdist, expected_comparable_distance); + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "distance[reversed args] = " + << dist << " ; " + << "comp. distance[reversed args] = " + << cdist + << std::endl; + std::cout << std::endl; +#endif + } + } +}; + + +//======================================================================== + + +template <typename Geometry1, typename Geometry2, typename Strategy> +void test_empty_input(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + try + { + bg::distance(geometry1, geometry2); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, + "A empty_input_exception should have been thrown"); + + try + { + bg::distance(geometry2, geometry1); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, + "A empty_input_exception should have been thrown"); + + try + { + bg::distance(geometry1, geometry2, strategy); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, + "A empty_input_exception should have been thrown"); + + try + { + bg::distance(geometry2, geometry1, strategy); + } + catch(bg::empty_input_exception const& ) + { + return; + } + BOOST_CHECK_MESSAGE(false, + "A empty_input_exception should have been thrown"); +} + +#endif // BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP |