PageRenderTime 62ms CodeModel.GetById 14ms app.highlight 43ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/libs/geometry/test/algorithms/distance.cpp

http://hadesmem.googlecode.com/
C++ | 250 lines | 153 code | 60 blank | 37 comment | 0 complexity | 1aa79a3798abd710a7371af95feea589 MD5 | raw file
  1// Boost.Geometry (aka GGL, Generic Geometry Library)
  2// Unit Test
  3
  4// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
  5// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
  6// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
  7
  8// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  9// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
 10
 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)
 14
 15#define TEST_ARRAY
 16
 17#include <sstream>
 18
 19#include <algorithms/test_distance.hpp>
 20
 21#include <boost/mpl/if.hpp>
 22#include <boost/array.hpp>
 23
 24#include <boost/geometry/geometries/geometries.hpp>
 25#include <boost/geometry/geometries/point_xy.hpp>
 26#include <boost/geometry/geometries/adapted/c_array.hpp>
 27#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
 28
 29#include <test_common/test_point.hpp>
 30#include <test_geometries/custom_segment.hpp>
 31#include <test_geometries/wrapped_boost_array.hpp>
 32
 33BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
 34BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
 35
 36// Register boost array as a linestring
 37namespace boost { namespace geometry { namespace traits
 38{
 39template <typename Point, std::size_t PointCount>
 40struct tag< boost::array<Point, PointCount> >
 41{
 42    typedef linestring_tag type;
 43};
 44
 45}}}
 46
 47template <typename P>
 48void test_distance_point()
 49{
 50    namespace services = bg::strategy::distance::services;
 51    typedef typename bg::default_distance_result<P>::type return_type;
 52
 53    // Basic, trivial test
 54
 55    P p1;
 56    bg::set<0>(p1, 1);
 57    bg::set<1>(p1, 1);
 58
 59    P p2;
 60    bg::set<0>(p2, 2);
 61    bg::set<1>(p2, 2);
 62
 63    return_type d = bg::distance(p1, p2);
 64    BOOST_CHECK_CLOSE(d, return_type(1.4142135), 0.001);
 65
 66    // Test specifying strategy manually
 67    typename services::default_strategy<bg::point_tag, P>::type strategy;
 68
 69    d = bg::distance(p1, p2, strategy);
 70    BOOST_CHECK_CLOSE(d, return_type(1.4142135), 0.001);
 71
 72    {
 73        // Test custom strategy
 74        BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<taxicab_distance<P> >) );
 75
 76        typedef typename services::return_type<taxicab_distance<P> >::type cab_return_type;
 77        BOOST_MPL_ASSERT((boost::is_same<cab_return_type, typename bg::coordinate_type<P>::type>));
 78
 79        taxicab_distance<P> tcd;
 80        cab_return_type d = bg::distance(p1, p2, tcd);
 81
 82        BOOST_CHECK( bg::math::abs(d - cab_return_type(2)) <= cab_return_type(0.01) );
 83    }
 84
 85    {
 86        // test comparability
 87
 88        typedef typename services::default_strategy<bg::point_tag, P>::type strategy_type;
 89        typedef typename services::comparable_type<strategy_type>::type comparable_strategy_type;
 90
 91        strategy_type strategy;
 92        comparable_strategy_type comparable_strategy = services::get_comparable<strategy_type>::apply(strategy);
 93        return_type comparable = services::result_from_distance<comparable_strategy_type>::apply(comparable_strategy, 3);
 94
 95        BOOST_CHECK_CLOSE(comparable, return_type(9), 0.001);
 96    }
 97}
 98
 99template <typename P>
100void test_distance_segment()
101{
102    typedef typename bg::default_distance_result<P>::type return_type;
103    typedef typename bg::coordinate_type<P>::type coordinate_type;
104
105    P s1; bg::set<0>(s1, 1); bg::set<1>(s1, 1);
106    P s2; bg::set<0>(s2, 4); bg::set<1>(s2, 4);
107
108    // Check points left, right, projected-left, projected-right, on segment
109    P p1; bg::set<0>(p1, 0); bg::set<1>(p1, 1);
110    P p2; bg::set<0>(p2, 1); bg::set<1>(p2, 0);
111    P p3; bg::set<0>(p3, 3); bg::set<1>(p3, 1);
112    P p4; bg::set<0>(p4, 1); bg::set<1>(p4, 3);
113    P p5; bg::set<0>(p5, 3); bg::set<1>(p5, 3);
114
115    bg::model::referring_segment<P const> const seg(s1, s2);
116
117    return_type d1 = bg::distance(p1, seg);
118    return_type d2 = bg::distance(p2, seg);
119    return_type d3 = bg::distance(p3, seg);
120    return_type d4 = bg::distance(p4, seg);
121    return_type d5 = bg::distance(p5, seg);
122
123    BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
124    BOOST_CHECK_CLOSE(d2, return_type(1), 0.001);
125    BOOST_CHECK_CLOSE(d3, return_type(1.4142135), 0.001);
126    BOOST_CHECK_CLOSE(d4, return_type(1.4142135), 0.001);
127    BOOST_CHECK_CLOSE(d5, return_type(0), 0.001);
128
129    // Reverse case: segment/point instead of point/segment
130    return_type dr1 = bg::distance(seg, p1);
131    return_type dr2 = bg::distance(seg, p2);
132
133    BOOST_CHECK_CLOSE(dr1, d1, 0.001);
134    BOOST_CHECK_CLOSE(dr2, d2, 0.001);
135
136    // Test specifying strategy manually:
137    // 1) point-point-distance
138    typename bg::strategy::distance::services::default_strategy<bg::point_tag, P>::type pp_strategy;
139    d1 = bg::distance(p1, seg, pp_strategy);
140    BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
141
142    // 2) point-segment-distance
143    typename bg::strategy::distance::services::default_strategy<bg::segment_tag, P>::type ps_strategy;
144    d1 = bg::distance(p1, seg, ps_strategy);
145    BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
146
147    // 3) custom point strategy
148    taxicab_distance<P> tcd;
149    d1 = bg::distance(p1, seg, tcd);
150    BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
151}
152
153
154template <typename P>
155void test_distance_array_as_linestring()
156{
157    typedef typename bg::default_distance_result<P>::type return_type;
158
159    // Normal array does not have
160    boost::array<P, 2> points;
161    bg::set<0>(points[0], 1);
162    bg::set<1>(points[0], 1);
163    bg::set<0>(points[1], 3);
164    bg::set<1>(points[1], 3);
165
166    P p;
167    bg::set<0>(p, 2);
168    bg::set<1>(p, 1);
169
170    return_type d = bg::distance(p, points);
171    BOOST_CHECK_CLOSE(d, return_type(0.70710678), 0.001);
172
173    bg::set<0>(p, 5); bg::set<1>(p, 5);
174    d = bg::distance(p, points);
175    BOOST_CHECK_CLOSE(d, return_type(2.828427), 0.001);
176}
177
178
179
180
181template <typename P>
182void test_all()
183{
184    test_distance_point<P>();
185    test_distance_segment<P>();
186    test_distance_array_as_linestring<P>();
187
188    test_geometry<P, bg::model::segment<P> >("POINT(1 3)", "LINESTRING(1 1,4 4)", sqrt(2.0));
189    test_geometry<P, bg::model::segment<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
190
191    test_geometry<P, P>("POINT(1 1)", "POINT(2 2)", sqrt(2.0));
192    test_geometry<P, P>("POINT(0 0)", "POINT(0 3)", 3.0);
193    test_geometry<P, P>("POINT(0 0)", "POINT(4 0)", 4.0);
194    test_geometry<P, P>("POINT(0 3)", "POINT(4 0)", 5.0);
195    test_geometry<P, bg::model::linestring<P> >("POINT(1 3)", "LINESTRING(1 1,4 4)", sqrt(2.0));
196    test_geometry<P, bg::model::linestring<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
197    test_geometry<bg::model::linestring<P>, P>("LINESTRING(1 1,4 4)", "POINT(1 3)", sqrt(2.0));
198
199    // Rings
200    test_geometry<P, bg::model::ring<P> >("POINT(1 3)", "POLYGON((1 1,4 4,5 0,1 1))", sqrt(2.0));
201    test_geometry<P, bg::model::ring<P> >("POINT(3 1)", "POLYGON((1 1,4 4,5 0,1 1))", 0.0);
202    // other way round
203    test_geometry<bg::model::ring<P>, P>("POLYGON((1 1,4 4,5 0,1 1))", "POINT(3 1)", 0.0);
204    // open ring
205    test_geometry<P, bg::model::ring<P, true, false> >("POINT(1 3)", "POLYGON((4 4,5 0,1 1))", sqrt(2.0));
206
207    // Polygons
208    test_geometry<P, bg::model::polygon<P> >("POINT(1 3)", "POLYGON((1 1,4 4,5 0,1 1))", sqrt(2.0));
209    test_geometry<P, bg::model::polygon<P> >("POINT(3 1)", "POLYGON((1 1,4 4,5 0,1 1))", 0.0);
210    // other way round
211    test_geometry<bg::model::polygon<P>, P>("POLYGON((1 1,4 4,5 0,1 1))", "POINT(3 1)", 0.0);
212    // open polygon
213    test_geometry<P, bg::model::polygon<P, true, false> >("POINT(1 3)", "POLYGON((4 4,5 0,1 1))", sqrt(2.0));
214
215    // Polygons with holes
216    std::string donut = "POLYGON ((0 0,1 9,8 1,0 0),(1 1,4 1,1 4,1 1))";
217    test_geometry<P, bg::model::polygon<P> >("POINT(2 2)", donut, 0.5 * sqrt(2.0));
218    test_geometry<P, bg::model::polygon<P> >("POINT(3 3)", donut, 0.0);
219    // other way round
220    test_geometry<bg::model::polygon<P>, P>(donut, "POINT(2 2)", 0.5 * sqrt(2.0));
221    // open
222    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));
223
224
225    // DOES NOT COMPILE - cannot do read_wkt (because boost::array is not variably sized)
226    // test_geometry<P, boost::array<P, 2> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
227
228    test_geometry<P, test::wrapped_boost_array<P, 2> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
229}
230
231int test_main(int, char* [])
232{
233#ifdef TEST_ARRAY
234    //test_all<int[2]>();
235    //test_all<float[2]>();
236    //test_all<double[2]>();
237    //test_all<test::test_point>(); // located here because of 3D
238#endif
239
240    test_all<bg::model::d2::point_xy<int> >();
241    test_all<boost::tuple<float, float> >();
242    test_all<bg::model::d2::point_xy<float> >();
243    test_all<bg::model::d2::point_xy<double> >();
244
245#ifdef HAVE_TTMATH
246    test_all<bg::model::d2::point_xy<ttmath_big> >();
247#endif
248
249    return 0;
250}