1 // Boost.Geometry (aka GGL, Generic Geometry Library)
4 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
6 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
16 #include <geometry_test_common.hpp>
19 # pragma warning( disable : 4101 )
22 #include <boost/timer.hpp>
24 #include <boost/concept/requires.hpp>
25 #include <boost/concept_check.hpp>
26 #include <boost/core/ignore_unused.hpp>
28 #include <boost/geometry/algorithms/assign.hpp>
29 #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
30 #include <boost/geometry/strategies/concepts/distance_concept.hpp>
33 #include <boost/geometry/geometries/point.hpp>
34 #include <boost/geometry/geometries/adapted/c_array.hpp>
35 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
37 #include <test_common/test_point.hpp>
40 # include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
43 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian
)
44 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian
)
47 template <typename P1
, typename P2
>
48 void test_null_distance_3d()
51 bg::assign_values(p1
, 1, 2, 3);
53 bg::assign_values(p2
, 1, 2, 3);
55 typedef bg::strategy::distance::pythagoras
<> pythagoras_type
;
56 typedef typename
bg::strategy::distance::services::return_type
<pythagoras_type
, P1
, P2
>::type return_type
;
58 pythagoras_type pythagoras
;
59 return_type result
= pythagoras
.apply(p1
, p2
);
61 BOOST_CHECK_EQUAL(result
, return_type(0));
64 template <typename P1
, typename P2
>
68 bg::assign_values(p1
, 0, 0, 0);
70 bg::assign_values(p2
, 1, 0, 0);
72 typedef bg::strategy::distance::pythagoras
<> pythagoras_type
;
73 typedef typename
bg::strategy::distance::services::return_type
<pythagoras_type
, P1
, P2
>::type return_type
;
75 pythagoras_type pythagoras
;
77 return_type result
= pythagoras
.apply(p1
, p2
);
78 BOOST_CHECK_EQUAL(result
, return_type(1));
80 bg::assign_values(p2
, 0, 1, 0);
81 result
= pythagoras
.apply(p1
, p2
);
82 BOOST_CHECK_EQUAL(result
, return_type(1));
84 bg::assign_values(p2
, 0, 0, 1);
85 result
= pythagoras
.apply(p1
, p2
);
86 BOOST_CHECK_CLOSE(result
, return_type(1), 0.001);
89 template <typename P1
, typename P2
>
90 void test_arbitrary_3d()
93 bg::assign_values(p1
, 1, 2, 3);
95 bg::assign_values(p2
, 9, 8, 7);
98 typedef bg::strategy::distance::pythagoras
<> strategy_type
;
99 typedef typename
bg::strategy::distance::services::return_type
<strategy_type
, P1
, P2
>::type return_type
;
101 strategy_type strategy
;
102 return_type result
= strategy
.apply(p1
, p2
);
103 BOOST_CHECK_CLOSE(result
, return_type(10.77032961427), 0.001);
107 // Check comparable distance
108 typedef bg::strategy::distance::comparable::pythagoras
<> strategy_type
;
109 typedef typename
bg::strategy::distance::services::return_type
<strategy_type
, P1
, P2
>::type return_type
;
111 strategy_type strategy
;
112 return_type result
= strategy
.apply(p1
, p2
);
113 BOOST_CHECK_EQUAL(result
, return_type(116));
117 template <typename P1
, typename P2
, typename CalculationType
>
120 namespace bgsd
= bg::strategy::distance
;
121 namespace services
= bg::strategy::distance::services
;
125 // Compile-check if there is a strategy for this type
126 typedef typename
services::default_strategy
128 bg::point_tag
, bg::point_tag
, P1
, P2
129 >::type pythagoras_strategy_type
;
131 boost::ignore_unused
<pythagoras_strategy_type
>();
136 bg::assign_values(p1
, 1, 2, 3);
139 bg::assign_values(p2
, 4, 5, 6);
141 double const sqr_expected
= 3*3 + 3*3 + 3*3; // 27
142 double const expected
= sqrt(sqr_expected
); // sqrt(27)=5.1961524227
144 // 1: normal, calculate distance:
146 typedef bgsd::pythagoras
<CalculationType
> strategy_type
;
148 BOOST_CONCEPT_ASSERT( (bg::concepts::PointDistanceStrategy
<strategy_type
, P1
, P2
>) );
150 typedef typename
bgsd::services::return_type
<strategy_type
, P1
, P2
>::type return_type
;
152 strategy_type strategy
;
153 return_type result
= strategy
.apply(p1
, p2
);
154 BOOST_CHECK_CLOSE(result
, return_type(expected
), 0.001);
156 // 2: the strategy should return the same result if we reverse parameters
157 result
= strategy
.apply(p2
, p1
);
158 BOOST_CHECK_CLOSE(result
, return_type(expected
), 0.001);
161 // 3: "comparable" to construct a "comparable strategy" for P1/P2
162 // a "comparable strategy" is a strategy which does not calculate the exact distance, but
163 // which returns results which can be mutually compared (e.g. avoid sqrt)
165 // 3a: "comparable_type"
166 typedef typename
services::comparable_type
<strategy_type
>::type comparable_type
;
168 // 3b: "get_comparable"
169 comparable_type comparable
= bgsd::services::get_comparable
<strategy_type
>::apply(strategy
);
171 return_type c_result
= comparable
.apply(p1
, p2
);
172 BOOST_CHECK_CLOSE(c_result
, return_type(sqr_expected
), 0.001);
174 // 4: the comparable_type should have a distance_strategy_constructor as well,
175 // knowing how to compare something with a fixed distance
176 return_type c_dist5
= services::result_from_distance
<comparable_type
, P1
, P2
>::apply(comparable
, 5.0);
177 return_type c_dist6
= services::result_from_distance
<comparable_type
, P1
, P2
>::apply(comparable
, 6.0);
179 // If this is the case:
180 BOOST_CHECK(c_dist5
< c_result
&& c_result
< c_dist6
);
182 // This should also be the case
183 return_type dist5
= services::result_from_distance
<strategy_type
, P1
, P2
>::apply(strategy
, 5.0);
184 return_type dist6
= services::result_from_distance
<strategy_type
, P1
, P2
>::apply(strategy
, 6.0);
185 BOOST_CHECK(dist5
< result
&& result
< dist6
);
189 template <typename CoordinateType
, typename CalculationType
, typename AssignType
>
190 void test_big_2d_with(AssignType
const& x1
, AssignType
const& y1
,
191 AssignType
const& x2
, AssignType
const& y2
)
193 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
194 typedef bg::strategy::distance::pythagoras
<CalculationType
> pythagoras_type
;
196 pythagoras_type pythagoras
;
197 typedef typename
bg::strategy::distance::services::return_type
<pythagoras_type
, point_type
, point_type
>::type return_type
;
201 bg::assign_values(p1
, x1
, y1
);
202 bg::assign_values(p2
, x2
, y2
);
203 return_type d
= pythagoras
.apply(p1
, p2
);
206 std::cout << typeid(CalculationType).name()
207 << " " << std::fixed << std::setprecision(20) << d
208 << std::endl << std::endl;
212 BOOST_CHECK_CLOSE(d
, return_type(1076554.5485833955678294387789057), 0.001);
215 template <typename CoordinateType
, typename CalculationType
>
218 test_big_2d_with
<CoordinateType
, CalculationType
>
219 (123456.78900001, 234567.89100001,
220 987654.32100001, 876543.21900001);
223 template <typename CoordinateType
, typename CalculationType
>
224 void test_big_2d_string()
226 test_big_2d_with
<CoordinateType
, CalculationType
>
227 ("123456.78900001", "234567.89100001",
228 "987654.32100001", "876543.21900001");
231 template <typename CoordinateType
>
232 void test_integer(bool check_types
)
234 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
237 bg::assign_values(p1
, 12345678, 23456789);
238 bg::assign_values(p2
, 98765432, 87654321);
240 typedef bg::strategy::distance::pythagoras
<> pythagoras_type
;
241 typedef typename
bg::strategy::distance::services::comparable_type
244 >::type comparable_type
;
246 typedef typename
bg::strategy::distance::services::return_type
248 pythagoras_type
, point_type
, point_type
249 >::type distance_type
;
250 typedef typename
bg::strategy::distance::services::return_type
252 comparable_type
, point_type
, point_type
253 >::type cdistance_type
;
255 pythagoras_type pythagoras
;
256 distance_type distance
= pythagoras
.apply(p1
, p2
);
257 BOOST_CHECK_CLOSE(distance
, 107655455.02347542, 0.001);
259 comparable_type comparable
;
260 cdistance_type cdistance
= comparable
.apply(p1
, p2
);
261 BOOST_CHECK_EQUAL(cdistance
, 11589696996311540.0);
263 distance_type distance2
= sqrt(distance_type(cdistance
));
264 BOOST_CHECK_CLOSE(distance
, distance2
, 0.001);
268 BOOST_CHECK((boost::is_same
<distance_type
, double>::type::value
));
269 // comparable_distance results in now double too, obviously because
270 // comp.distance point-segment can be fraction, even for integer input
271 BOOST_CHECK((boost::is_same
<cdistance_type
, double>::type::value
));
276 template <typename P1
, typename P2
>
279 test_null_distance_3d
<P1
, P2
>();
280 test_axis_3d
<P1
, P2
>();
281 test_arbitrary_3d
<P1
, P2
>();
284 template <typename P
>
287 test_all_3d
<P
, int[3]>();
288 test_all_3d
<P
, float[3]>();
289 test_all_3d
<P
, double[3]>();
290 test_all_3d
<P
, test::test_point
>();
291 test_all_3d
<P
, bg::model::point
<int, 3, bg::cs::cartesian
> >();
292 test_all_3d
<P
, bg::model::point
<float, 3, bg::cs::cartesian
> >();
293 test_all_3d
<P
, bg::model::point
<double, 3, bg::cs::cartesian
> >();
296 template <typename P
, typename Strategy
>
297 void time_compare_s(int const n
)
301 bg::assign_values(p1
, 1, 1);
302 bg::assign_values(p2
, 2, 2);
304 typename
bg::strategy::distance::services::return_type
<Strategy
, P
, P
>::type s
= 0;
305 for (int i
= 0; i
< n
; i
++)
307 for (int j
= 0; j
< n
; j
++)
309 bg::set
<0>(p2
, bg::get
<0>(p2
) + 0.001);
310 s
+= strategy
.apply(p1
, p2
);
313 std::cout
<< "s: " << s
<< " t: " << t
.elapsed() << std::endl
;
316 template <typename P
>
317 void time_compare(int const n
)
319 time_compare_s
<P
, bg::strategy::distance::pythagoras
<> >(n
);
320 time_compare_s
<P
, bg::strategy::distance::comparable::pythagoras
<> >(n
);
323 int test_main(int, char* [])
325 test_integer
<int>(true);
326 test_integer
<boost::long_long_type
>(true);
327 test_integer
<double>(false);
329 test_all_3d
<int[3]>();
330 test_all_3d
<float[3]>();
331 test_all_3d
<double[3]>();
333 test_all_3d
<test::test_point
>();
335 test_all_3d
<bg::model::point
<int, 3, bg::cs::cartesian
> >();
336 test_all_3d
<bg::model::point
<float, 3, bg::cs::cartesian
> >();
337 test_all_3d
<bg::model::point
<double, 3, bg::cs::cartesian
> >();
339 test_big_2d
<float, float>();
340 test_big_2d
<double, double>();
341 test_big_2d
<long double, long double>();
342 test_big_2d
<float, long double>();
344 test_services
<bg::model::point
<float, 3, bg::cs::cartesian
>, double[3], long double>();
345 test_services
<double[3], test::test_point
, float>();
348 // TODO move this to another non-unit test
349 // time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000);
351 #if defined(HAVE_TTMATH)
353 typedef ttmath::Big
<1,4> tt
;
354 typedef bg::model::point
<tt
, 3, bg::cs::cartesian
> tt_point
;
356 //test_all_3d<tt[3]>();
357 test_all_3d
<tt_point
>();
358 test_all_3d
<tt_point
, tt_point
>();
359 test_big_2d
<tt
, tt
>();
360 test_big_2d_string
<tt
, tt
>();