]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/line_interpolate.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / line_interpolate.cpp
1 // Boost.Geometry
2 // Unit Test
3
4 // Copyright (c) 2018, Oracle and/or its affiliates.
5
6 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
7
8 // Licensed under the Boost Software License version 1.0.
9 // http://www.boost.org/users/license.html
10
11
12 #include <geometry_test_common.hpp>
13
14 #include <boost/geometry.hpp>
15 #include <boost/geometry/geometries/geometries.hpp>
16
17 #include <boost/geometry/algorithms/line_interpolate.hpp>
18 #include <boost/geometry/algorithms/length.hpp>
19
20 #include <boost/geometry/iterators/segment_iterator.hpp>
21
22 #include <boost/geometry/strategies/strategies.hpp>
23
24 #include <boost/geometry/io/wkt/wkt.hpp>
25
26 template <typename P, typename Tag = typename bg::tag<P>::type>
27 struct check_points: bg::not_implemented<Tag>
28 {};
29
30 template <typename P>
31 struct check_points<P, bg::point_tag>
32 {
33 static void apply(P const& p0, P const& p1)
34 {
35 double p00 = bg::get<0>(p0);
36 double p10 = bg::get<0>(p1);
37
38 BOOST_CHECK_CLOSE(p00, p10, 0.001);
39
40 double p01 = bg::get<1>(p0);
41 double p11 = bg::get<1>(p1);
42
43 BOOST_CHECK_CLOSE(p01, p11, 0.001);
44 }
45 };
46
47 template <typename P>
48 struct check_points<P, bg::multi_point_tag>
49 {
50 template <typename Range>
51 static void apply(Range const& r0, Range const& r1)
52 {
53
54 typedef typename boost::range_iterator<Range const>::type iterator_t;
55 typedef typename boost::range_value<Range const>::type point_t;
56
57 std::size_t count0 = boost::size(r0);
58 std::size_t count1 = boost::size(r1);
59
60 BOOST_CHECK_MESSAGE(count0 == count1, bg::wkt(r0) << " != " << bg::wkt(r1));
61
62 if (count0 == count1)
63 {
64 for (iterator_t it0 = boost::begin(r0), it1 = boost::begin(r1);
65 it0 < boost::end(r0); it0++, it1++)
66 {
67 check_points<point_t>::apply(*it0, *it1);
68 }
69 }
70 }
71 };
72
73 template <typename G, typename P, typename S>
74 inline void test(std::string const& wkt1,
75 double fraction,
76 std::string const& wkt2,
77 S str)
78 {
79 G g;
80 bg::read_wkt(wkt1, g);
81
82 P o;
83 bg::read_wkt(wkt2, o);
84
85 P p1;
86 bg::line_interpolate(g, fraction * bg::length(g), p1, str);
87 check_points<P>::apply(p1, o);
88
89 }
90
91 template <typename G, typename P>
92 inline void test(std::string const& wkt1,
93 double fraction,
94 std::string const& wkt2)
95 {
96 G g;
97 bg::read_wkt(wkt1, g);
98
99 P o;
100 bg::read_wkt(wkt2, o);
101
102 P p1;
103 bg::line_interpolate(g, fraction * bg::length(g), p1);
104 check_points<P>::apply(p1, o);
105 }
106
107 template <typename G, typename P>
108 inline void test_distance(std::string const& wkt1,
109 double distance,
110 std::string const& wkt2)
111 {
112 G g;
113 bg::read_wkt(wkt1, g);
114
115 P o;
116 bg::read_wkt(wkt2, o);
117
118 P p1;
119 bg::line_interpolate(g, distance, p1);
120 check_points<P>::apply(p1, o);
121 }
122
123 template <typename G, typename P, typename S>
124 inline void test_distance(std::string const& wkt1,
125 double distance,
126 std::string const& wkt2,
127 S str)
128 {
129 G g;
130 bg::read_wkt(wkt1, g);
131
132 P o;
133 bg::read_wkt(wkt2, o);
134
135 P p1;
136 bg::line_interpolate(g, distance, p1, str);
137 check_points<P>::apply(p1, o);
138 }
139
140 std::string const s = "SEGMENT(1 1, 2 2)";
141 std::string const l1 = "LINESTRING(1 1, 2 1, 2 2, 1 2, 1 3)";
142 std::string const l2 = "LINESTRING(0 2, 5 2, 5 1, 20 1)";
143 std::string const l00 = "LINESTRING()";
144 std::string const l01 = "LINESTRING(1 1)";
145 std::string const l02 = "LINESTRING(1 1, 1 1)";
146
147 void test_car_edge_cases()
148 {
149 typedef bg::model::point<double, 2, bg::cs::cartesian> P;
150 typedef bg::model::multi_point<P> MP;
151 typedef bg::model::linestring<P> LS;
152
153 //negative input distance
154 test_distance<LS,P>(l1, -1, "POINT(1 1)");
155 test_distance<LS,MP>(l1, -1, "MULTIPOINT((1 1))");
156
157 //input distance longer than total length
158 test_distance<LS,P>(l1, 5, "POINT(1 3)");
159 test_distance<LS,MP>(l1, 5, "MULTIPOINT((1 3))");
160
161 //linestring with only one point
162 test_distance<LS,P>(l01, 1, "POINT(1 1)");
163 test_distance<LS,MP>(l01, 1, "MULTIPOINT((1 1))");
164
165 //linestring with two same points
166 test_distance<LS,P>(l02, 1, "POINT(1 1)");
167 test_distance<LS,MP>(l02, 1, "MULTIPOINT((1 1))");
168
169 //empty linestring
170 try
171 {
172 test_distance<LS,P>(l00, 1, "POINT(1 1)");
173 }
174 catch(bg::empty_input_exception const& )
175 {
176 return;
177 }
178 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
179 }
180
181 void test_car()
182 {
183 typedef bg::model::point<double, 2, bg::cs::cartesian> P;
184 typedef bg::model::multi_point<P> MP;
185 typedef bg::model::segment<P> S;
186 typedef bg::model::linestring<P> LS;
187
188 test<S,P>(s, 0, "POINT(1 1)");
189 test<S,P>(s, 0.5, "POINT(1.5 1.5)");
190 test<S,P>(s, 1, "POINT(2 2)");
191
192 test<LS,P>(l1, 0, "POINT(1 1)");
193 test<LS,P>(l1, 0.1, "POINT(1.4 1)");
194 test<LS,P>(l1, 0.2, "POINT(1.8 1)");
195 test<LS,P>(l1, 0.3, "POINT(2 1.2)");
196 test<LS,P>(l1, 0.4, "POINT(2 1.6)");
197 test<LS,P>(l1, 0.5, "POINT(2 2)");
198 test<LS,P>(l1, 0.6, "POINT(1.6 2)");
199 test<LS,P>(l1, 0.7, "POINT(1.2 2)");
200 test<LS,P>(l1, 0.8, "POINT(1 2.2)");
201 test<LS,P>(l1, 0.9, "POINT(1 2.6)");
202 test<LS,P>(l1, 1, "POINT(1 3)");
203
204 test<LS,MP>(l1, 0, "MULTIPOINT((1 1))");
205 //(1 3) missing due to floating point round off errors
206 test<LS,MP>(l1, 0.1, "MULTIPOINT((1.4 1)(1.8 1)(2 1.2)(2 1.6)(2 2)(1.6 2)\
207 (1.2 2)(1 2.2)(1 2.6))");
208 //(1 3) is not missing if you directly pass the distance
209 test_distance<LS,MP>(l1, 0.4, "MULTIPOINT((1.4 1)(1.8 1)(2 1.2)(2 1.6)(2 2)(1.6 2)\
210 (1.2 2)(1 2.2)(1 2.6)(1 3))");
211 test<LS,MP>(l1, 0.2, "MULTIPOINT((1.8 1)(2 1.6)(1.6 2)(1 2.2))");//(1 3) missing
212 test<LS,MP>(l1, 0.4, "MULTIPOINT((2 1.6)(1 2.2))");
213 test<LS,MP>(l1, 0.5, "MULTIPOINT((2 2)(1 3))");
214 test<LS,MP>(l1, 0.6, "MULTIPOINT((1.6 2))");
215 test<LS,MP>(l1, 1, "MULTIPOINT((1 3))");
216 }
217
218 void test_sph()
219 {
220 typedef bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > P;
221 typedef bg::model::multi_point<P> MP;
222 typedef bg::model::segment<P> S;
223 typedef bg::model::linestring<P> LS;
224
225 test<S,P>(s, 0, "POINT(1 1)");
226 test<S,P>(s, 0.5, "POINT(1.4998857365615981 1.5000570914791198)");
227 test<S,P>(s, 1, "POINT(2 2)");
228
229 test<LS,P>(l1, 0, "POINT(1 1)");
230 test<LS,P>(l1, 0.1, "POINT(1.39998476912905323 1.0000365473536286)");
231 test<LS,P>(l1, 0.2, "POINT(1.79996953825810646 1.0000243679448551)");
232 test<LS,P>(l1, 0.3, "POINT(2 1.1999238595669637)");
233 test<LS,P>(l1, 0.4, "POINT(2 1.5998477098527744)");
234 test<LS,P>(l1, 0.5, "POINT(2 1.9997715601390484)");
235 test<LS,P>(l1, 0.6, "POINT(1.6000609543036084 2.0000730473928678)");
236 test<LS,P>(l1, 0.7, "POINT(1.1998933176222553 2.0000486811516014)");
237 test<LS,P>(l1, 0.8, "POINT(1 2.2001522994279883)");
238 test<LS,P>(l1, 0.9, "POINT(1 2.6000761497139444)");
239 test<LS,P>(l1, 1, "POINT(1 3)");
240
241 test<LS,MP>(l1, 0, "MULTIPOINT((1 1))");
242 test<LS,MP>(l1, 0.1, "MULTIPOINT((1.39998476912905323 1.0000365473536286)\
243 (1.79996953825810646 1.0000243679448551)\
244 (2 1.1999238595669637)\
245 (2 1.5998477098527744)\
246 (2 1.9997715601385837)\
247 (1.6000609543036084 2.0000730473928678)\
248 (1.1998933176222553 2.0000486811516014)\
249 (1 2.2001522994279883)\
250 (1 2.6000761497139444)\
251 )");//(1,3)
252 test<LS,MP>(l1, 0.2, "MULTIPOINT((1.79996953825810646 1.0000243679448551)\
253 (2 1.5998477098527744)\
254 (1.6000609543036084 2.0000730473928678)\
255 (1 2.2001522994279883)\
256 )");//(1,3)
257 test<LS,MP>(l1, 0.4, "MULTIPOINT((2 1.5998477098527744)(1 2.2001522994279883))");
258 test<LS,MP>(l1, 0.5, "MULTIPOINT((2 1.9997715601385837)(1 3))");
259 test<LS,MP>(l1, 0.6, "MULTIPOINT((1.6000609543036084 2.0000730473928678))");
260 test<LS,MP>(l1, 1, "MULTIPOINT((1 3))");
261
262 test<LS,MP>(l2, 0.3, "MULTIPOINT((5.3014893312120446 1.0006787676128222)\
263 (11.600850053156366 1.0085030143490989)\
264 (17.9002174825842 1.0041514208039872))");
265
266 }
267
268 template <typename Strategy>
269 void test_sph(Strategy str)
270 {
271 typedef bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > P;
272 typedef bg::model::segment<P> S;
273
274 test_distance<S,P>(s, 0, "POINT(1 1)", str);
275 test_distance<S,P>(s, 0.01, "POINT(1.4051065077123643 1.405268220524982)");
276 test_distance<S,P>(s, 0.01, "POINT(1.0040505023484179 1.0040529633262307)", str);
277 test_distance<S,P>(s, 1, "POINT(1.4051065077123015 1.405268220524919)", str);
278 test_distance<S,P>(s, 1, "POINT(2 2)");
279 test_distance<S,P>(s, 10, "POINT(2 2)");
280 }
281
282 template <typename Strategy>
283 void test_geo(Strategy str)
284 {
285 typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > P;
286 typedef bg::model::multi_point<P> MP;
287 typedef bg::model::segment<P> S;
288 typedef bg::model::linestring<P> LS;
289
290 test<S,P>(s, 0, "POINT(1 1)", str);
291 test<S,P>(s, 0.5, "POINT(1.4998780900539985 1.5000558288006378)", str);
292 test<S,P>(s, 1, "POINT(2 2)", str);
293
294 test<LS,P>(l1, 0, "POINT(1 1)", str);
295 test<LS,P>(l1, 0.1, "POINT(1.3986445638301882 1.0000367522730751)", str);
296 test<LS,P>(l1, 0.2, "POINT(1.79728912766037641 1.0000247772611039)", str);
297 test<LS,P>(l1, 0.3, "POINT(2 1.1972285554368427)", str);
298 test<LS,P>(l1, 0.4, "POINT(2 1.598498298996567)", str);
299 test<LS,P>(l1, 0.5, "POINT(2 1.9997664696834965)", str);
300 test<LS,P>(l1, 0.6, "POINT(1.6013936980010324 2.0000734568388099)", str);
301 test<LS,P>(l1, 0.7, "POINT(1.2025664628960846 2.0000494983098767)", str);
302 test<LS,P>(l1, 0.8, "POINT(1 2.1974612279909937)", str);
303 test<LS,P>(l1, 0.9, "POINT(1 2.5987263175375022)", str);
304 test<LS,P>(l1, 1, "POINT(1 3)", str);
305
306 test<LS,MP>(l1, 0, "MULTIPOINT((1 1))", str);
307
308 //adnoyer is missing the last point in the following cases
309 // of linestrings due to inaccuracy
310 if (!boost::is_same<Strategy, bg::strategy::line_interpolate::geographic
311 <bg::strategy::andoyer> >::value)
312 {
313 test<LS,MP>(l1, 0.1, "MULTIPOINT((1.3986445638301882 1.0000367522730751)\
314 (1.79728912766037641 1.0000247772582571)\
315 (2 1.1972285554368427)\
316 (2 1.598498298996567)\
317 (2 1.9997664696834965)\
318 (1.6013936980010324 2.0000734568388099)\
319 (1.2025664628960846 2.0000495003440779)\
320 (1 2.1974612279909937)\
321 (1 2.5987263175375022)\
322 (1 3))", str);
323
324 test<LS,MP>(l1, 0.2, "MULTIPOINT((1.79728912766037641 1.0000247772613331)\
325 (2 1.598498298996567)\
326 (1.6013936980010324 2.0000734568388099)\
327 (1 2.1974612279909937)\
328 (1 3))", str);
329 }
330 test<LS,MP>(l1, 0.4, "MULTIPOINT((2 1.598498298996567)(1 2.1974612279909937))", str);
331 test<LS,MP>(l1, 0.5, "MULTIPOINT((2 1.9997664696834965)(1 3))", str);
332 test<LS,MP>(l1, 0.6, "MULTIPOINT((1.6013936980010324 2.0000734568388099))", str);
333 test<LS,MP>(l1, 1, "MULTIPOINT((1 3))", str);
334
335 test<LS,MP>(l2, 0.3, "MULTIPOINT((5.306157814 1.0006937303)\
336 (11.60351281 1.0085614548123072)\
337 (17.90073492 1.004178475142552))", str);
338 }
339
340 template <typename Strategy>
341 void test_geo_non_standard_spheroid(Strategy str)
342 {
343 typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > P;
344 typedef bg::model::segment<P> S;
345
346 test<S,P>(s, 0, "POINT(1 1)", str);
347 test<S,P>(s, 0.5, "POINT(1.5127731436886724 1.5129021873759412)", str);
348 test<S,P>(s, 1, "POINT(2 2)", str);
349 }
350
351 int test_main(int, char* [])
352 {
353 test_car();
354 test_car_edge_cases();
355
356 test_sph();
357 test_sph(bg::strategy::line_interpolate::spherical<>(100));
358
359 typedef bg::srs::spheroid<double> stype;
360
361 test_geo(bg::strategy::line_interpolate::geographic<bg::strategy::andoyer>());
362 test_geo(bg::strategy::line_interpolate::geographic<bg::strategy::thomas>());
363 test_geo(bg::strategy::line_interpolate::geographic<bg::strategy::vincenty>());
364
365 test_geo_non_standard_spheroid(bg::strategy::line_interpolate::geographic
366 <bg::strategy::vincenty>(stype(5000000,6000000)));
367
368 return 0;
369 }
370