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