1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
5 
6 // This file was modified by Oracle on 2017, 2018.
7 // Modifications copyright (c) 2017-2018, Oracle and/or its affiliates.
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9 
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13 
14 
15 #if defined(_MSC_VER)
16 #pragma warning( disable : 4305 ) // truncation double -> float
17 #endif // defined(_MSC_VER)
18 
19 #define BOOST_GEOMETRY_SRS_ENABLE_STATIC_PROJECTION_HYBRID_INTERFACE
20 
21 #include <geometry_test_common.hpp>
22 
23 #include <boost/geometry/srs/projection.hpp>
24 
25 #include <boost/geometry/core/coordinate_type.hpp>
26 #include <boost/geometry/algorithms/make.hpp>
27 
28 #include <boost/geometry.hpp>
29 #include <boost/geometry/geometries/geometries.hpp>
30 #include <boost/geometry/geometries/point_xy.hpp>
31 
32 #include "proj4.hpp"
33 
34 namespace srs = bg::srs;
35 
36 template <typename P>
check_expected(P const & p1,P const & p2)37 bool check_expected(P const& p1, P const& p2)
38 {
39     return bg::math::abs(bg::get<0>(p1) - bg::get<0>(p2)) <= 1.0
40         && bg::math::abs(bg::get<1>(p1) - bg::get<1>(p2)) <= 1.0;
41 }
42 
43 template <typename StaticParams, typename GeoPoint, typename CartPoint>
test_forward(std::string const & id,GeoPoint const & geo_point,CartPoint const & cart_point,StaticParams const & params,std::string const & proj4="")44 void test_forward(std::string const& id, GeoPoint const& geo_point, CartPoint const& cart_point,
45                   StaticParams const& params, std::string const& proj4 = "")
46 {
47     try
48     {
49         srs::projection<StaticParams> prj = params;
50 
51         CartPoint xy;
52         prj.forward(geo_point, xy);
53 
54         bool ok = check_expected(xy, cart_point);
55 
56         BOOST_CHECK_MESSAGE(ok,
57                 " id: " << id
58                 << " point: " << bg::wkt(xy)
59                 << " different than expected: " << bg::wkt(cart_point));
60 
61         if (! proj4.empty())
62         {
63             srs::projection<> prj2 = srs::proj4(proj4);
64 
65             CartPoint xy2;
66             prj2.forward(geo_point, xy2);
67 
68             bool eq2 = bg::equals(xy, xy2);
69 
70             BOOST_CHECK_MESSAGE(eq2,
71                 " id: " << id << " result of static: "
72                 << bg::wkt(xy) << " different than dynamic: " << bg::wkt(xy2));
73 
74 #ifdef TEST_WITH_PROJ4
75             pj_projection prj3(proj4);
76 
77             CartPoint xy3;
78             prj3.forward(geo_point, xy3);
79 
80             bool eq3 = bg::equals(xy, xy3);
81 
82             BOOST_CHECK_MESSAGE(eq3,
83                 " id: " << id << " result: "
84                 << bg::wkt(xy) << " different than proj4: " << bg::wkt(xy3));
85 #endif // TEST_WITH_PROJ4
86         }
87     }
88     catch(bg::projection_exception const& e)
89     {
90         std::cout << "Exception in " << id << " : " << e.code() << std::endl;
91     }
92     catch(...)
93     {
94         std::cout << "Exception (unknown) in " << id << std::endl;
95     }
96 }
97 
98 template <typename StaticParams, typename GeoPoint, typename CartPoint>
test_forward(std::string const & id,GeoPoint const & geo_point,CartPoint const & cart_point,std::string const & proj4="")99 void test_forward(std::string const& id, GeoPoint const& geo_point, CartPoint const& cart_point,
100                   std::string const& proj4 = "")
101 {
102     test_forward(id, geo_point, cart_point, StaticParams(), proj4);
103 }
104 
105 template <typename T>
test_all()106 void test_all()
107 {
108     typedef bg::model::point<T, 2, bg::cs::geographic<bg::degree> > geo_point_type;
109     typedef bg::model::point<T, 2, bg::cs::cartesian> cart;
110 
111     geo_point_type amsterdam = bg::make<geo_point_type>(4.8925, 52.3731);
112     geo_point_type utrecht   = bg::make<geo_point_type>(5.1213, 52.0907);
113 
114     geo_point_type anchorage = bg::make<geo_point_type>(-149.90, 61.22);
115     geo_point_type juneau    = bg::make<geo_point_type>(-134.42, 58.30);
116 
117     geo_point_type auckland   = bg::make<geo_point_type>(174.74, -36.84);
118     geo_point_type wellington = bg::make<geo_point_type>(177.78, -41.29);
119 
120     geo_point_type aspen  = bg::make<geo_point_type>(-106.84, 39.19);
121     geo_point_type denver = bg::make<geo_point_type>(-104.88, 39.76);
122 
123     using namespace srs::spar;
124 
125     // IGH (internally using moll/sinu)
126     {
127         typedef parameters<proj_igh, ellps_sphere, units_m> params_t;
128         std::string sparams = "+proj=igh +ellps=sphere +units=m";
129         test_forward<params_t>("igh-am", amsterdam, cart(1489299.1509520211, 5776413.4260336142), sparams);
130         test_forward<params_t>("igh-ut", utrecht, cart(1498750.6627020084, 5747394.3313896423), sparams);
131         test_forward<params_t>("igh-as", aspen, cart(-11708973.126426676, 4357727.1232166551), sparams);
132         test_forward<params_t>("igh-de", denver, cart(-11536624.264589204, 4421108.2015589233), sparams);
133         test_forward<params_t>("igh-au", auckland, cart(18658819.353676274, -4096419.1686476548), sparams);
134         test_forward<params_t>("igh-we", wellington, cart(18733710.557981707, -4591140.1631184481), sparams);
135         test_forward<params_t>("igh-an", anchorage, cart(-14275110.630537530, 6648284.9393376000), sparams);
136         test_forward<params_t>("igh-ju", juneau, cart(-13421076.123140398, 6368936.3597440729), sparams);
137     }
138 
139     // Using moll
140     {
141         typedef parameters<proj_ob_tran, ellps_wgs84, o_proj<proj_moll>, units_m, o_lat_p<>, o_lon_p<> > params_t;
142         params_t params = params_t(proj_ob_tran(), ellps_wgs84(), o_proj<proj_moll>(), units_m(), o_lat_p<>(10), o_lon_p<>(90));
143         std::string sparams = "+proj=ob_tran +ellps=WGS84 +o_proj=moll +units=m +o_lat_p=10 +o_lon_p=90 +o_lon_o=11.50";
144         test_forward<params_t>("obt-m-am", amsterdam, cart(8688778.3518596273, -3348126.4518623645), params, sparams);
145         test_forward<params_t>("obt-m-ut", utrecht, cart(8693109.5205437448, -3379708.1134765535), params, sparams);
146         test_forward<params_t>("obt-m-as", aspen, cart(3691751.3259231807, 2371456.9674431868), params, sparams);
147         test_forward<params_t>("obt-m-de", denver, cart(3764685.2104777521, 2185616.0182080171), params, sparams);
148     }
149 
150     // Using sinu
151     {
152         // In Proj4 >= 5.0.0 ob_tran projection doesn't overwrite the ellipsoid's parameters to make sphere in underlying projection
153         // So in order to use spherical sinu projection WGS84-compatible sphere has to be set manually.
154         typedef parameters<proj_ob_tran, a<>, es<>, o_proj<proj_sinu>, units_m, o_lat_p<>, o_lon_p<> > params_t;
155         params_t params = params_t(proj_ob_tran(), a<>(6378137), es<>(0), o_proj<proj_sinu>(), units_m(), o_lat_p<>(10), o_lon_p<>(90));
156         std::string sparams = "+proj=ob_tran +a=6378137 +es=0 +o_proj=sinu +units=m +o_lat_p=10 +o_lon_p=90 +o_lon_o=11.50";
157         test_forward<params_t>("obt-s-am", amsterdam, cart(9220221.4221933037, -3059652.3579233172), params, sparams);
158         test_forward<params_t>("obt-s-ut", utrecht, cart(9216281.0977674071, -3089427.4415689218), params, sparams);
159         test_forward<params_t>("obt-s-as", aspen, cart(4010672.3356677019, 2150730.9484995930), params, sparams);
160         test_forward<params_t>("obt-s-de", denver, cart(4103945.8062708224, 1979964.9315176210), params, sparams);
161     }
162 }
163 
test_main(int,char * [])164 int test_main(int, char* [])
165 {
166     test_all<double>();
167 
168     return 0;
169 }
170