]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
92f5a8d4 | 3 | // Copyright (c) 2017-2018, Oracle and/or its affiliates. |
11fdf7f2 TL |
4 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle |
5 | ||
6 | // Use, modification and distribution is subject to the Boost Software License, | |
7 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
8 | // http://www.boost.org/LICENSE_1_0.txt) | |
9 | ||
10 | #ifndef BOOST_GEOMETRY_SRS_TRANSFORMATION_HPP | |
11 | #define BOOST_GEOMETRY_SRS_TRANSFORMATION_HPP | |
12 | ||
13 | ||
14 | #include <string> | |
15 | ||
16 | #include <boost/geometry/algorithms/convert.hpp> | |
17 | ||
18 | #include <boost/geometry/core/coordinate_dimension.hpp> | |
19 | ||
20 | #include <boost/geometry/geometries/point.hpp> | |
21 | #include <boost/geometry/geometries/multi_point.hpp> | |
22 | #include <boost/geometry/geometries/linestring.hpp> | |
23 | #include <boost/geometry/geometries/ring.hpp> | |
24 | #include <boost/geometry/geometries/segment.hpp> | |
25 | ||
26 | #include <boost/geometry/srs/projection.hpp> | |
92f5a8d4 | 27 | #include <boost/geometry/srs/projections/grids.hpp> |
11fdf7f2 TL |
28 | #include <boost/geometry/srs/projections/impl/pj_transform.hpp> |
29 | ||
30 | #include <boost/geometry/views/detail/indexed_point_view.hpp> | |
31 | ||
32 | #include <boost/mpl/assert.hpp> | |
33 | #include <boost/mpl/if.hpp> | |
34 | #include <boost/smart_ptr/shared_ptr.hpp> | |
35 | #include <boost/throw_exception.hpp> | |
36 | #include <boost/type_traits/is_integral.hpp> | |
37 | #include <boost/type_traits/is_same.hpp> | |
38 | ||
39 | ||
40 | namespace boost { namespace geometry | |
41 | { | |
42 | ||
43 | namespace projections { namespace detail | |
44 | { | |
45 | ||
46 | template <typename T1, typename T2> | |
47 | inline bool same_object(T1 const& , T2 const& ) | |
48 | { | |
49 | return false; | |
50 | } | |
51 | ||
52 | template <typename T> | |
53 | inline bool same_object(T const& o1, T const& o2) | |
54 | { | |
55 | return boost::addressof(o1) == boost::addressof(o2); | |
56 | } | |
57 | ||
58 | template | |
59 | < | |
60 | typename PtIn, | |
61 | typename PtOut, | |
92f5a8d4 | 62 | bool SameUnits = boost::is_same |
11fdf7f2 | 63 | < |
92f5a8d4 TL |
64 | typename geometry::detail::cs_angular_units<PtIn>::type, |
65 | typename geometry::detail::cs_angular_units<PtOut>::type | |
66 | >::value | |
11fdf7f2 TL |
67 | > |
68 | struct transform_geometry_point_coordinates | |
69 | { | |
70 | static inline void apply(PtIn const& in, PtOut & out, bool /*enable_angles*/) | |
71 | { | |
72 | geometry::set<0>(out, geometry::get<0>(in)); | |
73 | geometry::set<1>(out, geometry::get<1>(in)); | |
74 | } | |
75 | }; | |
76 | ||
77 | template <typename PtIn, typename PtOut> | |
78 | struct transform_geometry_point_coordinates<PtIn, PtOut, false> | |
79 | { | |
80 | static inline void apply(PtIn const& in, PtOut & out, bool enable_angles) | |
81 | { | |
82 | if (enable_angles) | |
83 | { | |
84 | geometry::set_from_radian<0>(out, geometry::get_as_radian<0>(in)); | |
85 | geometry::set_from_radian<1>(out, geometry::get_as_radian<1>(in)); | |
86 | } | |
87 | else | |
88 | { | |
89 | geometry::set<0>(out, geometry::get<0>(in)); | |
90 | geometry::set<1>(out, geometry::get<1>(in)); | |
91 | } | |
92 | } | |
93 | }; | |
94 | ||
95 | template <typename Geometry, typename CT> | |
96 | struct transform_geometry_point | |
97 | { | |
98 | typedef typename geometry::point_type<Geometry>::type point_type; | |
99 | ||
100 | typedef geometry::model::point | |
101 | < | |
102 | typename select_most_precise | |
103 | < | |
104 | typename geometry::coordinate_type<point_type>::type, | |
105 | CT | |
106 | >::type, | |
107 | geometry::dimension<point_type>::type::value, | |
108 | typename geometry::coordinate_system<point_type>::type | |
109 | > type; | |
110 | ||
111 | template <typename PtIn, typename PtOut> | |
112 | static inline void apply(PtIn const& in, PtOut & out, bool enable_angles) | |
113 | { | |
114 | transform_geometry_point_coordinates<PtIn, PtOut>::apply(in, out, enable_angles); | |
115 | projections::detail::copy_higher_dimensions<2>(in, out); | |
116 | } | |
117 | }; | |
118 | ||
119 | template <typename Geometry, typename CT> | |
120 | struct transform_geometry_range_base | |
121 | { | |
122 | struct convert_strategy | |
123 | { | |
124 | convert_strategy(bool enable_angles) | |
125 | : m_enable_angles(enable_angles) | |
126 | {} | |
127 | ||
128 | template <typename PtIn, typename PtOut> | |
129 | void apply(PtIn const& in, PtOut & out) | |
130 | { | |
131 | transform_geometry_point<Geometry, CT>::apply(in, out, m_enable_angles); | |
132 | } | |
133 | ||
134 | bool m_enable_angles; | |
135 | }; | |
136 | ||
137 | template <typename In, typename Out> | |
138 | static inline void apply(In const& in, Out & out, bool enable_angles) | |
139 | { | |
140 | // Change the order and/or closure if needed | |
141 | // In - arbitrary geometry | |
142 | // Out - either Geometry or std::vector | |
143 | // So the order and closure of In and Geometry shoudl be compared | |
144 | // std::vector's order is assumed to be the same as of Geometry | |
145 | geometry::detail::conversion::range_to_range | |
146 | < | |
147 | In, | |
148 | Out, | |
149 | geometry::point_order<In>::value != geometry::point_order<Out>::value | |
150 | >::apply(in, out, convert_strategy(enable_angles)); | |
151 | } | |
152 | }; | |
153 | ||
154 | template | |
155 | < | |
156 | typename Geometry, | |
157 | typename CT, | |
158 | typename Tag = typename geometry::tag<Geometry>::type | |
159 | > | |
160 | struct transform_geometry | |
161 | {}; | |
162 | ||
163 | template <typename Point, typename CT> | |
164 | struct transform_geometry<Point, CT, point_tag> | |
165 | : transform_geometry_point<Point, CT> | |
166 | {}; | |
167 | ||
168 | template <typename Segment, typename CT> | |
169 | struct transform_geometry<Segment, CT, segment_tag> | |
170 | { | |
171 | typedef geometry::model::segment | |
172 | < | |
173 | typename transform_geometry_point<Segment, CT>::type | |
174 | > type; | |
175 | ||
176 | template <typename In, typename Out> | |
177 | static inline void apply(In const& in, Out & out, bool enable_angles) | |
178 | { | |
179 | apply<0>(in, out, enable_angles); | |
180 | apply<1>(in, out, enable_angles); | |
181 | } | |
182 | ||
183 | private: | |
184 | template <std::size_t Index, typename In, typename Out> | |
185 | static inline void apply(In const& in, Out & out, bool enable_angles) | |
186 | { | |
187 | geometry::detail::indexed_point_view<In const, Index> in_pt(in); | |
188 | geometry::detail::indexed_point_view<Out, Index> out_pt(out); | |
189 | transform_geometry_point<Segment, CT>::apply(in_pt, out_pt, enable_angles); | |
190 | } | |
191 | }; | |
192 | ||
193 | template <typename MultiPoint, typename CT> | |
194 | struct transform_geometry<MultiPoint, CT, multi_point_tag> | |
195 | : transform_geometry_range_base<MultiPoint, CT> | |
196 | { | |
197 | typedef model::multi_point | |
198 | < | |
199 | typename transform_geometry_point<MultiPoint, CT>::type | |
200 | > type; | |
201 | }; | |
202 | ||
203 | template <typename LineString, typename CT> | |
204 | struct transform_geometry<LineString, CT, linestring_tag> | |
205 | : transform_geometry_range_base<LineString, CT> | |
206 | { | |
207 | typedef model::linestring | |
208 | < | |
209 | typename transform_geometry_point<LineString, CT>::type | |
210 | > type; | |
211 | }; | |
212 | ||
213 | template <typename Ring, typename CT> | |
214 | struct transform_geometry<Ring, CT, ring_tag> | |
215 | : transform_geometry_range_base<Ring, CT> | |
216 | { | |
217 | typedef model::ring | |
218 | < | |
219 | typename transform_geometry_point<Ring, CT>::type, | |
220 | geometry::point_order<Ring>::value == clockwise, | |
221 | geometry::closure<Ring>::value == closed | |
222 | > type; | |
223 | }; | |
224 | ||
225 | ||
226 | template | |
227 | < | |
228 | typename OutGeometry, | |
229 | typename CT, | |
230 | bool EnableTemporary = ! boost::is_same | |
231 | < | |
232 | typename select_most_precise | |
233 | < | |
234 | typename geometry::coordinate_type<OutGeometry>::type, | |
235 | CT | |
236 | >::type, | |
237 | typename geometry::coordinate_type<OutGeometry>::type | |
238 | >::type::value | |
239 | > | |
240 | struct transform_geometry_wrapper | |
241 | { | |
242 | typedef transform_geometry<OutGeometry, CT> transform; | |
243 | typedef typename transform::type type; | |
244 | ||
245 | template <typename InGeometry> | |
246 | transform_geometry_wrapper(InGeometry const& in, OutGeometry & out, bool input_angles) | |
247 | : m_out(out) | |
248 | { | |
249 | transform::apply(in, m_temp, input_angles); | |
250 | } | |
251 | ||
252 | type & get() { return m_temp; } | |
253 | void finish() { geometry::convert(m_temp, m_out); } // this is always copy 1:1 without changing the order or closure | |
254 | ||
255 | private: | |
256 | type m_temp; | |
257 | OutGeometry & m_out; | |
258 | }; | |
259 | ||
260 | template | |
261 | < | |
262 | typename OutGeometry, | |
263 | typename CT | |
264 | > | |
265 | struct transform_geometry_wrapper<OutGeometry, CT, false> | |
266 | { | |
267 | typedef transform_geometry<OutGeometry, CT> transform; | |
268 | typedef OutGeometry type; | |
269 | ||
270 | transform_geometry_wrapper(OutGeometry const& in, OutGeometry & out, bool input_angles) | |
271 | : m_out(out) | |
272 | { | |
273 | if (! same_object(in, out)) | |
274 | transform::apply(in, out, input_angles); | |
275 | } | |
276 | ||
277 | template <typename InGeometry> | |
278 | transform_geometry_wrapper(InGeometry const& in, OutGeometry & out, bool input_angles) | |
279 | : m_out(out) | |
280 | { | |
281 | transform::apply(in, out, input_angles); | |
282 | } | |
283 | ||
284 | OutGeometry & get() { return m_out; } | |
285 | void finish() {} | |
286 | ||
287 | private: | |
288 | OutGeometry & m_out; | |
289 | }; | |
290 | ||
291 | template <typename CT> | |
292 | struct transform_range | |
293 | { | |
294 | template | |
295 | < | |
296 | typename Proj1, typename Par1, | |
297 | typename Proj2, typename Par2, | |
92f5a8d4 TL |
298 | typename RangeIn, typename RangeOut, |
299 | typename Grids | |
11fdf7f2 TL |
300 | > |
301 | static inline bool apply(Proj1 const& proj1, Par1 const& par1, | |
302 | Proj2 const& proj2, Par2 const& par2, | |
92f5a8d4 TL |
303 | RangeIn const& in, RangeOut & out, |
304 | Grids const& grids1, Grids const& grids2) | |
11fdf7f2 TL |
305 | { |
306 | // NOTE: this has to be consistent with pj_transform() | |
307 | bool const input_angles = !par1.is_geocent && par1.is_latlong; | |
308 | ||
309 | transform_geometry_wrapper<RangeOut, CT> wrapper(in, out, input_angles); | |
310 | ||
311 | bool res = true; | |
312 | try | |
313 | { | |
92f5a8d4 | 314 | res = pj_transform(proj1, par1, proj2, par2, wrapper.get(), grids1, grids2); |
11fdf7f2 | 315 | } |
92f5a8d4 | 316 | catch (projection_exception const&) |
11fdf7f2 TL |
317 | { |
318 | res = false; | |
319 | } | |
320 | catch(...) | |
321 | { | |
322 | BOOST_RETHROW | |
323 | } | |
324 | ||
325 | wrapper.finish(); | |
326 | ||
327 | return res; | |
328 | } | |
329 | }; | |
330 | ||
331 | template <typename Policy> | |
332 | struct transform_multi | |
333 | { | |
334 | template | |
335 | < | |
336 | typename Proj1, typename Par1, | |
337 | typename Proj2, typename Par2, | |
92f5a8d4 TL |
338 | typename MultiIn, typename MultiOut, |
339 | typename Grids | |
11fdf7f2 TL |
340 | > |
341 | static inline bool apply(Proj1 const& proj1, Par1 const& par1, | |
342 | Proj2 const& proj2, Par2 const& par2, | |
92f5a8d4 TL |
343 | MultiIn const& in, MultiOut & out, |
344 | Grids const& grids1, Grids const& grids2) | |
11fdf7f2 TL |
345 | { |
346 | if (! same_object(in, out)) | |
347 | range::resize(out, boost::size(in)); | |
348 | ||
349 | return apply(proj1, par1, proj2, par2, | |
350 | boost::begin(in), boost::end(in), | |
92f5a8d4 TL |
351 | boost::begin(out), |
352 | grids1, grids2); | |
11fdf7f2 TL |
353 | } |
354 | ||
355 | private: | |
356 | template | |
357 | < | |
358 | typename Proj1, typename Par1, | |
359 | typename Proj2, typename Par2, | |
92f5a8d4 TL |
360 | typename InIt, typename OutIt, |
361 | typename Grids | |
11fdf7f2 TL |
362 | > |
363 | static inline bool apply(Proj1 const& proj1, Par1 const& par1, | |
364 | Proj2 const& proj2, Par2 const& par2, | |
92f5a8d4 TL |
365 | InIt in_first, InIt in_last, OutIt out_first, |
366 | Grids const& grids1, Grids const& grids2) | |
11fdf7f2 TL |
367 | { |
368 | bool res = true; | |
369 | for ( ; in_first != in_last ; ++in_first, ++out_first ) | |
370 | { | |
92f5a8d4 | 371 | if ( ! Policy::apply(proj1, par1, proj2, par2, *in_first, *out_first, grids1, grids2) ) |
11fdf7f2 TL |
372 | { |
373 | res = false; | |
374 | } | |
375 | } | |
376 | return res; | |
377 | } | |
378 | }; | |
379 | ||
380 | template | |
381 | < | |
382 | typename Geometry, | |
383 | typename CT, | |
384 | typename Tag = typename geometry::tag<Geometry>::type | |
385 | > | |
386 | struct transform | |
387 | : not_implemented<Tag> | |
388 | {}; | |
389 | ||
390 | template <typename Point, typename CT> | |
391 | struct transform<Point, CT, point_tag> | |
392 | { | |
393 | template | |
394 | < | |
395 | typename Proj1, typename Par1, | |
396 | typename Proj2, typename Par2, | |
92f5a8d4 TL |
397 | typename PointIn, typename PointOut, |
398 | typename Grids | |
11fdf7f2 TL |
399 | > |
400 | static inline bool apply(Proj1 const& proj1, Par1 const& par1, | |
401 | Proj2 const& proj2, Par2 const& par2, | |
92f5a8d4 TL |
402 | PointIn const& in, PointOut & out, |
403 | Grids const& grids1, Grids const& grids2) | |
11fdf7f2 TL |
404 | { |
405 | // NOTE: this has to be consistent with pj_transform() | |
406 | bool const input_angles = !par1.is_geocent && par1.is_latlong; | |
407 | ||
408 | transform_geometry_wrapper<PointOut, CT> wrapper(in, out, input_angles); | |
409 | ||
410 | typedef typename transform_geometry_wrapper<PointOut, CT>::type point_type; | |
411 | point_type * ptr = boost::addressof(wrapper.get()); | |
412 | ||
413 | std::pair<point_type *, point_type *> range = std::make_pair(ptr, ptr + 1); | |
414 | ||
415 | bool res = true; | |
416 | try | |
417 | { | |
92f5a8d4 | 418 | res = pj_transform(proj1, par1, proj2, par2, range, grids1, grids2); |
11fdf7f2 | 419 | } |
92f5a8d4 | 420 | catch (projection_exception const&) |
11fdf7f2 TL |
421 | { |
422 | res = false; | |
423 | } | |
424 | catch(...) | |
425 | { | |
426 | BOOST_RETHROW | |
427 | } | |
428 | ||
429 | wrapper.finish(); | |
430 | ||
431 | return res; | |
432 | } | |
433 | }; | |
434 | ||
435 | template <typename MultiPoint, typename CT> | |
436 | struct transform<MultiPoint, CT, multi_point_tag> | |
437 | : transform_range<CT> | |
438 | {}; | |
439 | ||
440 | template <typename Segment, typename CT> | |
441 | struct transform<Segment, CT, segment_tag> | |
442 | { | |
443 | template | |
444 | < | |
445 | typename Proj1, typename Par1, | |
446 | typename Proj2, typename Par2, | |
92f5a8d4 TL |
447 | typename SegmentIn, typename SegmentOut, |
448 | typename Grids | |
11fdf7f2 TL |
449 | > |
450 | static inline bool apply(Proj1 const& proj1, Par1 const& par1, | |
451 | Proj2 const& proj2, Par2 const& par2, | |
92f5a8d4 TL |
452 | SegmentIn const& in, SegmentOut & out, |
453 | Grids const& grids1, Grids const& grids2) | |
11fdf7f2 TL |
454 | { |
455 | // NOTE: this has to be consistent with pj_transform() | |
456 | bool const input_angles = !par1.is_geocent && par1.is_latlong; | |
457 | ||
458 | transform_geometry_wrapper<SegmentOut, CT> wrapper(in, out, input_angles); | |
459 | ||
460 | typedef typename geometry::point_type | |
461 | < | |
462 | typename transform_geometry_wrapper<SegmentOut, CT>::type | |
463 | >::type point_type; | |
464 | ||
465 | point_type points[2]; | |
466 | ||
467 | geometry::detail::assign_point_from_index<0>(wrapper.get(), points[0]); | |
468 | geometry::detail::assign_point_from_index<1>(wrapper.get(), points[1]); | |
469 | ||
470 | std::pair<point_type*, point_type*> range = std::make_pair(points, points + 2); | |
471 | ||
472 | bool res = true; | |
473 | try | |
474 | { | |
92f5a8d4 | 475 | res = pj_transform(proj1, par1, proj2, par2, range, grids1, grids2); |
11fdf7f2 | 476 | } |
92f5a8d4 | 477 | catch (projection_exception const&) |
11fdf7f2 TL |
478 | { |
479 | res = false; | |
480 | } | |
481 | catch(...) | |
482 | { | |
483 | BOOST_RETHROW | |
484 | } | |
485 | ||
486 | geometry::detail::assign_point_to_index<0>(points[0], wrapper.get()); | |
487 | geometry::detail::assign_point_to_index<1>(points[1], wrapper.get()); | |
488 | ||
489 | wrapper.finish(); | |
490 | ||
491 | return res; | |
492 | } | |
493 | }; | |
494 | ||
495 | template <typename Linestring, typename CT> | |
496 | struct transform<Linestring, CT, linestring_tag> | |
497 | : transform_range<CT> | |
498 | {}; | |
499 | ||
500 | template <typename MultiLinestring, typename CT> | |
501 | struct transform<MultiLinestring, CT, multi_linestring_tag> | |
502 | : transform_multi<transform_range<CT> > | |
503 | {}; | |
504 | ||
505 | template <typename Ring, typename CT> | |
506 | struct transform<Ring, CT, ring_tag> | |
507 | : transform_range<CT> | |
508 | {}; | |
509 | ||
510 | template <typename Polygon, typename CT> | |
511 | struct transform<Polygon, CT, polygon_tag> | |
512 | { | |
513 | template | |
514 | < | |
515 | typename Proj1, typename Par1, | |
516 | typename Proj2, typename Par2, | |
92f5a8d4 TL |
517 | typename PolygonIn, typename PolygonOut, |
518 | typename Grids | |
11fdf7f2 TL |
519 | > |
520 | static inline bool apply(Proj1 const& proj1, Par1 const& par1, | |
521 | Proj2 const& proj2, Par2 const& par2, | |
92f5a8d4 TL |
522 | PolygonIn const& in, PolygonOut & out, |
523 | Grids const& grids1, Grids const& grids2) | |
11fdf7f2 TL |
524 | { |
525 | bool r1 = transform_range | |
526 | < | |
527 | CT | |
528 | >::apply(proj1, par1, proj2, par2, | |
529 | geometry::exterior_ring(in), | |
92f5a8d4 TL |
530 | geometry::exterior_ring(out), |
531 | grids1, grids2); | |
11fdf7f2 TL |
532 | bool r2 = transform_multi |
533 | < | |
534 | transform_range<CT> | |
535 | >::apply(proj1, par1, proj2, par2, | |
536 | geometry::interior_rings(in), | |
92f5a8d4 TL |
537 | geometry::interior_rings(out), |
538 | grids1, grids2); | |
11fdf7f2 TL |
539 | return r1 && r2; |
540 | } | |
541 | }; | |
542 | ||
543 | template <typename MultiPolygon, typename CT> | |
544 | struct transform<MultiPolygon, CT, multi_polygon_tag> | |
545 | : transform_multi | |
546 | < | |
547 | transform | |
548 | < | |
549 | typename boost::range_value<MultiPolygon>::type, | |
550 | CT, | |
551 | polygon_tag | |
552 | > | |
553 | > | |
554 | {}; | |
555 | ||
556 | ||
557 | }} // namespace projections::detail | |
558 | ||
559 | namespace srs | |
560 | { | |
561 | ||
562 | ||
563 | /*! | |
564 | \brief Representation of projection | |
565 | \details Either dynamic or static projection representation | |
566 | \ingroup projection | |
567 | \tparam Proj1 default_dynamic or static projection parameters | |
568 | \tparam Proj2 default_dynamic or static projection parameters | |
569 | \tparam CT calculation type used internally | |
570 | */ | |
571 | template | |
572 | < | |
573 | typename Proj1 = srs::dynamic, | |
574 | typename Proj2 = srs::dynamic, | |
575 | typename CT = double | |
576 | > | |
577 | class transformation | |
578 | { | |
579 | typedef typename projections::detail::promote_to_double<CT>::type calc_t; | |
580 | ||
581 | public: | |
92f5a8d4 | 582 | // Both static and default constructed |
11fdf7f2 TL |
583 | transformation() |
584 | {} | |
585 | ||
92f5a8d4 | 586 | // First dynamic, second static and default constructed |
11fdf7f2 | 587 | template <typename Parameters1> |
92f5a8d4 TL |
588 | explicit transformation(Parameters1 const& parameters1, |
589 | typename boost::enable_if_c | |
590 | < | |
591 | boost::is_same<Proj1, srs::dynamic>::value | |
592 | && projections::dynamic_parameters<Parameters1>::is_specialized | |
593 | >::type * = 0) | |
594 | : m_proj1(parameters1) | |
595 | {} | |
596 | ||
597 | // First static, second static and default constructed | |
598 | explicit transformation(Proj1 const& parameters1) | |
11fdf7f2 TL |
599 | : m_proj1(parameters1) |
600 | {} | |
601 | ||
92f5a8d4 | 602 | // Both dynamic |
11fdf7f2 | 603 | template <typename Parameters1, typename Parameters2> |
92f5a8d4 TL |
604 | transformation(Parameters1 const& parameters1, |
605 | Parameters2 const& parameters2, | |
606 | typename boost::enable_if_c | |
607 | < | |
608 | boost::is_same<Proj1, srs::dynamic>::value | |
609 | && boost::is_same<Proj2, srs::dynamic>::value | |
610 | && projections::dynamic_parameters<Parameters1>::is_specialized | |
611 | && projections::dynamic_parameters<Parameters2>::is_specialized | |
612 | > * = 0) | |
613 | : m_proj1(parameters1) | |
614 | , m_proj2(parameters2) | |
615 | {} | |
616 | ||
617 | // First dynamic, second static | |
618 | template <typename Parameters1> | |
619 | transformation(Parameters1 const& parameters1, | |
620 | Proj2 const& parameters2, | |
621 | typename boost::enable_if_c | |
622 | < | |
623 | boost::is_same<Proj1, srs::dynamic>::value | |
624 | && projections::dynamic_parameters<Parameters1>::is_specialized | |
625 | > * = 0) | |
626 | : m_proj1(parameters1) | |
627 | , m_proj2(parameters2) | |
628 | {} | |
629 | ||
630 | // First static, second dynamic | |
631 | template <typename Parameters2> | |
632 | transformation(Proj1 const& parameters1, | |
633 | Parameters2 const& parameters2, | |
634 | typename boost::enable_if_c | |
635 | < | |
636 | boost::is_same<Proj2, srs::dynamic>::value | |
637 | && projections::dynamic_parameters<Parameters2>::is_specialized | |
638 | > * = 0) | |
639 | : m_proj1(parameters1) | |
640 | , m_proj2(parameters2) | |
641 | {} | |
642 | ||
643 | // Both static | |
644 | transformation(Proj1 const& parameters1, | |
645 | Proj2 const& parameters2) | |
11fdf7f2 TL |
646 | : m_proj1(parameters1) |
647 | , m_proj2(parameters2) | |
648 | {} | |
649 | ||
650 | template <typename GeometryIn, typename GeometryOut> | |
651 | bool forward(GeometryIn const& in, GeometryOut & out) const | |
92f5a8d4 TL |
652 | { |
653 | return forward(in, out, transformation_grids<detail::empty_grids_storage>()); | |
654 | } | |
655 | ||
656 | template <typename GeometryIn, typename GeometryOut> | |
657 | bool inverse(GeometryIn const& in, GeometryOut & out) const | |
658 | { | |
659 | return inverse(in, out, transformation_grids<detail::empty_grids_storage>()); | |
660 | } | |
661 | ||
662 | template <typename GeometryIn, typename GeometryOut, typename GridsStorage> | |
663 | bool forward(GeometryIn const& in, GeometryOut & out, | |
664 | transformation_grids<GridsStorage> const& grids) const | |
11fdf7f2 TL |
665 | { |
666 | BOOST_MPL_ASSERT_MSG((projections::detail::same_tags<GeometryIn, GeometryOut>::value), | |
667 | NOT_SUPPORTED_COMBINATION_OF_GEOMETRIES, | |
668 | (GeometryIn, GeometryOut)); | |
669 | ||
670 | return projections::detail::transform | |
671 | < | |
672 | GeometryOut, | |
673 | calc_t | |
674 | >::apply(m_proj1.proj(), m_proj1.proj().params(), | |
675 | m_proj2.proj(), m_proj2.proj().params(), | |
92f5a8d4 TL |
676 | in, out, |
677 | grids.src_grids, | |
678 | grids.dst_grids); | |
11fdf7f2 TL |
679 | } |
680 | ||
92f5a8d4 TL |
681 | template <typename GeometryIn, typename GeometryOut, typename GridsStorage> |
682 | bool inverse(GeometryIn const& in, GeometryOut & out, | |
683 | transformation_grids<GridsStorage> const& grids) const | |
11fdf7f2 TL |
684 | { |
685 | BOOST_MPL_ASSERT_MSG((projections::detail::same_tags<GeometryIn, GeometryOut>::value), | |
686 | NOT_SUPPORTED_COMBINATION_OF_GEOMETRIES, | |
687 | (GeometryIn, GeometryOut)); | |
688 | ||
689 | return projections::detail::transform | |
690 | < | |
691 | GeometryOut, | |
692 | calc_t | |
693 | >::apply(m_proj2.proj(), m_proj2.proj().params(), | |
694 | m_proj1.proj(), m_proj1.proj().params(), | |
92f5a8d4 TL |
695 | in, out, |
696 | grids.dst_grids, | |
697 | grids.src_grids); | |
698 | } | |
699 | ||
700 | template <typename GridsStorage> | |
701 | inline transformation_grids<GridsStorage> initialize_grids(GridsStorage & grids_storage) const | |
702 | { | |
703 | transformation_grids<GridsStorage> result(grids_storage); | |
704 | ||
705 | using namespace projections::detail; | |
706 | pj_gridlist_from_nadgrids(m_proj1.proj().params(), | |
707 | result.src_grids); | |
708 | pj_gridlist_from_nadgrids(m_proj2.proj().params(), | |
709 | result.dst_grids); | |
710 | ||
711 | return result; | |
11fdf7f2 TL |
712 | } |
713 | ||
714 | private: | |
715 | projections::proj_wrapper<Proj1, CT> m_proj1; | |
716 | projections::proj_wrapper<Proj2, CT> m_proj2; | |
717 | }; | |
718 | ||
92f5a8d4 | 719 | |
11fdf7f2 TL |
720 | } // namespace srs |
721 | ||
722 | ||
723 | }} // namespace boost::geometry | |
724 | ||
725 | ||
726 | #endif // BOOST_GEOMETRY_SRS_TRANSFORMATION_HPP |