]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | // Unit Test | |
3 | ||
4 | // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
5 | // Use, modification and distribution is subject to the Boost Software License, | |
6 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | #ifndef BOOST_GEOMETRY_TEST_DISTANCE_HPP | |
10 | #define BOOST_GEOMETRY_TEST_DISTANCE_HPP | |
11 | ||
12 | #include <geometry_test_common.hpp> | |
13 | ||
14 | #include <boost/geometry/algorithms/distance.hpp> | |
15 | #include <boost/geometry/io/wkt/read.hpp> | |
16 | #include <boost/geometry/strategies/strategies.hpp> | |
17 | ||
7c673cae FG |
18 | // Define a custom distance strategy |
19 | // For this one, the "taxicab" distance, | |
20 | // see http://en.wikipedia.org/wiki/Taxicab_geometry | |
21 | ||
22 | // For a point-point-distance operation, one typename Point is enough. | |
23 | // For a point-segment-distance operation, there is some magic inside | |
24 | // using another point type and casting if necessary. Therefore, | |
25 | // two point-types are necessary. | |
26 | struct taxicab_distance | |
27 | { | |
28 | template <typename P1, typename P2> | |
29 | static inline typename bg::coordinate_type<P1>::type apply( | |
30 | P1 const& p1, P2 const& p2) | |
31 | { | |
32 | using bg::get; | |
33 | using bg::math::abs; | |
34 | return abs(get<0>(p1) - get<1>(p2)) | |
35 | + abs(get<1>(p1) - get<1>(p2)); | |
36 | } | |
37 | }; | |
38 | ||
39 | ||
40 | ||
41 | namespace boost { namespace geometry { namespace strategy { namespace distance { namespace services | |
42 | { | |
43 | ||
44 | template <> | |
45 | struct tag<taxicab_distance> | |
46 | { | |
47 | typedef strategy_tag_distance_point_point type; | |
48 | }; | |
49 | ||
50 | ||
51 | template <typename P1, typename P2> | |
52 | struct return_type<taxicab_distance, P1, P2> | |
53 | { | |
54 | typedef typename coordinate_type<P1>::type type; | |
55 | }; | |
56 | ||
57 | ||
58 | template <> | |
59 | struct comparable_type<taxicab_distance> | |
60 | { | |
61 | typedef taxicab_distance type; | |
62 | }; | |
63 | ||
64 | template <> | |
65 | struct get_comparable<taxicab_distance> | |
66 | { | |
67 | static inline taxicab_distance apply(taxicab_distance const& input) | |
68 | { | |
69 | return input; | |
70 | } | |
71 | }; | |
72 | ||
73 | template <typename P1, typename P2> | |
74 | struct result_from_distance<taxicab_distance, P1, P2> | |
75 | { | |
76 | template <typename T> | |
77 | static inline typename coordinate_type<P1>::type apply(taxicab_distance const& , T const& value) | |
78 | { | |
79 | return value; | |
80 | } | |
81 | }; | |
82 | ||
83 | ||
84 | }}}}} // namespace bg::strategy::distance::services | |
85 | ||
86 | ||
87 | ||
88 | ||
89 | ||
90 | template <typename Geometry1, typename Geometry2> | |
91 | void test_distance(Geometry1 const& geometry1, | |
92 | Geometry2 const& geometry2, | |
93 | long double expected_distance) | |
94 | { | |
95 | typename bg::default_distance_result<Geometry1>::type distance = bg::distance(geometry1, geometry2); | |
96 | ||
97 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
98 | std::ostringstream out; | |
99 | out << typeid(typename bg::coordinate_type<Geometry1>::type).name() | |
100 | << std::endl | |
101 | << typeid(typename bg::default_distance_result<Geometry1>::type).name() | |
102 | << std::endl | |
103 | << "distance : " << bg::distance(geometry1, geometry2) | |
104 | << std::endl; | |
105 | std::cout << out.str(); | |
106 | #endif | |
107 | ||
108 | BOOST_CHECK_CLOSE(distance, expected_distance, 0.0001); | |
109 | } | |
110 | ||
111 | ||
112 | template <typename Geometry1, typename Geometry2> | |
113 | void test_geometry(std::string const& wkt1, std::string const& wkt2, double expected_distance) | |
114 | { | |
115 | Geometry1 geometry1; | |
116 | bg::read_wkt(wkt1, geometry1); | |
117 | Geometry2 geometry2; | |
118 | bg::read_wkt(wkt2, geometry2); | |
119 | ||
120 | test_distance(geometry1, geometry2, expected_distance); | |
121 | } | |
122 | ||
123 | template <typename Geometry1, typename Geometry2> | |
124 | void test_empty_input(Geometry1 const& geometry1, Geometry2 const& geometry2) | |
125 | { | |
126 | try | |
127 | { | |
128 | bg::distance(geometry1, geometry2); | |
129 | } | |
130 | catch(bg::empty_input_exception const& ) | |
131 | { | |
132 | return; | |
133 | } | |
134 | BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" ); | |
135 | } | |
136 | ||
137 | ||
138 | #endif |