1 /******************************************************************************
2  *
3  * Project:  PROJ
4  * Purpose:  Test grids.hpp
5  * Author:   Even Rouault <even dot rouault at spatialys dot com>
6  *
7  ******************************************************************************
8  * Copyright (c) 2020, Even Rouault <even dot rouault at spatialys dot com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "gtest_include.h"
30 
31 #include "grids.hpp"
32 
33 #include "proj_internal.h" // M_PI
34 
35 namespace {
36 
37 // ---------------------------------------------------------------------------
38 
39 class GridTest : public ::testing::Test {
40 
DummyLogFunction(void *,int,const char *)41     static void DummyLogFunction(void *, int, const char *) {}
42 
43   protected:
SetUp()44     void SetUp() override {
45         m_ctxt = proj_context_create();
46         proj_log_func(m_ctxt, nullptr, DummyLogFunction);
47         m_ctxt2 = proj_context_create();
48         proj_log_func(m_ctxt2, nullptr, DummyLogFunction);
49     }
50 
TearDown()51     void TearDown() override {
52         proj_context_destroy(m_ctxt);
53         proj_context_destroy(m_ctxt2);
54     }
55 
56     PJ_CONTEXT *m_ctxt = nullptr;
57     PJ_CONTEXT *m_ctxt2 = nullptr;
58 };
59 
60 // ---------------------------------------------------------------------------
61 
TEST_F(GridTest,VerticalShiftGridSet_null)62 TEST_F(GridTest, VerticalShiftGridSet_null) {
63     auto gridSet = NS_PROJ::VerticalShiftGridSet::open(m_ctxt, "null");
64     ASSERT_NE(gridSet, nullptr);
65     auto grid = gridSet->gridAt(0.0, 0.0);
66     ASSERT_NE(grid, nullptr);
67     EXPECT_EQ(grid->width(), 3);
68     EXPECT_EQ(grid->height(), 3);
69     EXPECT_EQ(grid->extentAndRes().west, -M_PI);
70     EXPECT_TRUE(grid->isNullGrid());
71     EXPECT_FALSE(grid->hasChanged());
72     float out = -1.0f;
73     EXPECT_TRUE(grid->valueAt(0, 0, out));
74     EXPECT_EQ(out, 0.0f);
75     EXPECT_FALSE(grid->isNodata(0.0f, 0.0));
76     gridSet->reassign_context(m_ctxt2);
77     gridSet->reopen(m_ctxt2);
78 }
79 
80 // ---------------------------------------------------------------------------
81 
TEST_F(GridTest,VerticalShiftGridSet_gtx)82 TEST_F(GridTest, VerticalShiftGridSet_gtx) {
83     ASSERT_EQ(NS_PROJ::VerticalShiftGridSet::open(m_ctxt, "foobar"), nullptr);
84     auto gridSet =
85         NS_PROJ::VerticalShiftGridSet::open(m_ctxt, "tests/test_nodata.gtx");
86     ASSERT_NE(gridSet, nullptr);
87     ASSERT_EQ(gridSet->gridAt(-100, -100), nullptr);
88     auto grid = gridSet->gridAt(4.15 / 180 * M_PI, 52.15 / 180 * M_PI);
89     ASSERT_NE(grid, nullptr);
90     EXPECT_TRUE(grid->isNodata(-88.8888f, 1.0));
91     gridSet->reassign_context(m_ctxt2);
92     gridSet->reopen(m_ctxt2);
93     grid = gridSet->gridAt(4.15 / 180 * M_PI, 52.15 / 180 * M_PI);
94     EXPECT_NE(grid, nullptr);
95 }
96 
97 // ---------------------------------------------------------------------------
98 
TEST_F(GridTest,HorizontalShiftGridSet_null)99 TEST_F(GridTest, HorizontalShiftGridSet_null) {
100     auto gridSet = NS_PROJ::HorizontalShiftGridSet::open(m_ctxt, "null");
101     ASSERT_NE(gridSet, nullptr);
102     auto grid = gridSet->gridAt(0.0, 0.0);
103     ASSERT_NE(grid, nullptr);
104     EXPECT_EQ(grid->width(), 3);
105     EXPECT_EQ(grid->height(), 3);
106     EXPECT_EQ(grid->extentAndRes().west, -M_PI);
107     EXPECT_TRUE(grid->isNullGrid());
108     EXPECT_FALSE(grid->hasChanged());
109     float out1 = -1.0f;
110     float out2 = -1.0f;
111     EXPECT_TRUE(grid->valueAt(0, 0, false, out1, out2));
112     EXPECT_EQ(out1, 0.0f);
113     EXPECT_EQ(out2, 0.0f);
114     gridSet->reassign_context(m_ctxt2);
115     gridSet->reopen(m_ctxt2);
116 }
117 
118 // ---------------------------------------------------------------------------
119 
TEST_F(GridTest,HorizontalShiftGridSet_gtiff)120 TEST_F(GridTest, HorizontalShiftGridSet_gtiff) {
121     auto gridSet =
122         NS_PROJ::HorizontalShiftGridSet::open(m_ctxt, "tests/test_hgrid.tif");
123     ASSERT_NE(gridSet, nullptr);
124     EXPECT_EQ(gridSet->format(), "gtiff");
125     EXPECT_TRUE(gridSet->name().find("tests/test_hgrid.tif") !=
126                 std::string::npos)
127         << gridSet->name();
128     EXPECT_EQ(gridSet->grids().size(), 1U);
129     ASSERT_EQ(gridSet->gridAt(-100, -100), nullptr);
130     auto grid = gridSet->gridAt(5.5 / 180 * M_PI, 53.5 / 180 * M_PI);
131     ASSERT_NE(grid, nullptr);
132     EXPECT_EQ(grid->width(), 4);
133     EXPECT_EQ(grid->height(), 4);
134     EXPECT_EQ(grid->extentAndRes().west, 4.0 / 180 * M_PI);
135     EXPECT_FALSE(grid->isNullGrid());
136     EXPECT_FALSE(grid->hasChanged());
137     float out1 = -1.0f;
138     float out2 = -1.0f;
139     EXPECT_TRUE(grid->valueAt(0, 3, false, out1, out2));
140     EXPECT_EQ(out1, static_cast<float>(14400.0 / 3600. / 180 * M_PI));
141     EXPECT_EQ(out2, static_cast<float>(900.0 / 3600. / 180 * M_PI));
142     gridSet->reassign_context(m_ctxt2);
143     gridSet->reopen(m_ctxt2);
144     grid = gridSet->gridAt(5.5 / 180 * M_PI, 53.5 / 180 * M_PI);
145     EXPECT_NE(grid, nullptr);
146 }
147 
148 // ---------------------------------------------------------------------------
149 
TEST_F(GridTest,GenericShiftGridSet_null)150 TEST_F(GridTest, GenericShiftGridSet_null) {
151     auto gridSet = NS_PROJ::GenericShiftGridSet::open(m_ctxt, "null");
152     ASSERT_NE(gridSet, nullptr);
153     auto grid = gridSet->gridAt(0.0, 0.0);
154     ASSERT_NE(grid, nullptr);
155     EXPECT_EQ(grid->width(), 3);
156     EXPECT_EQ(grid->height(), 3);
157     EXPECT_EQ(grid->extentAndRes().west, -M_PI);
158     EXPECT_TRUE(grid->isNullGrid());
159     EXPECT_FALSE(grid->hasChanged());
160     float out = -1.0f;
161     EXPECT_TRUE(grid->valueAt(0, 0, 0, out));
162     EXPECT_EQ(out, 0.0f);
163     EXPECT_EQ(grid->unit(0), "");
164     EXPECT_EQ(grid->description(0), "");
165     EXPECT_EQ(grid->metadataItem("foo"), "");
166     EXPECT_EQ(grid->samplesPerPixel(), 0);
167     gridSet->reassign_context(m_ctxt2);
168     gridSet->reopen(m_ctxt2);
169 }
170 
171 // ---------------------------------------------------------------------------
172 
TEST_F(GridTest,GenericShiftGridSet_gtiff)173 TEST_F(GridTest, GenericShiftGridSet_gtiff) {
174     ASSERT_EQ(NS_PROJ::GenericShiftGridSet::open(m_ctxt, "foobar"), nullptr);
175     auto gridSet = NS_PROJ::GenericShiftGridSet::open(
176         m_ctxt, "tests/nkgrf03vel_realigned_extract.tif");
177     ASSERT_NE(gridSet, nullptr);
178     ASSERT_EQ(gridSet->gridAt(-100, -100), nullptr);
179     auto grid = gridSet->gridAt(21.3333333 / 180 * M_PI, 63.0 / 180 * M_PI);
180     ASSERT_NE(grid, nullptr);
181     EXPECT_EQ(grid->width(), 5);
182     EXPECT_EQ(grid->height(), 5);
183     EXPECT_EQ(grid->extentAndRes().isGeographic, true);
184     EXPECT_EQ(grid->extentAndRes().west, 21.0 / 180 * M_PI);
185     EXPECT_FALSE(grid->isNullGrid());
186     EXPECT_FALSE(grid->hasChanged());
187     float out = -1.0f;
188     EXPECT_FALSE(grid->valueAt(0, 0, grid->samplesPerPixel(), out));
189     EXPECT_EQ(grid->metadataItem("area_of_use"), "Nordic and Baltic countries");
190     EXPECT_EQ(grid->metadataItem("non_existing"), std::string());
191     EXPECT_EQ(grid->metadataItem("non_existing", 1), std::string());
192     EXPECT_EQ(grid->metadataItem("non_existing", 10), std::string());
193     gridSet->reassign_context(m_ctxt2);
194     gridSet->reopen(m_ctxt2);
195     grid = gridSet->gridAt(21.3333333 / 180 * M_PI, 63.0 / 180 * M_PI);
196     EXPECT_NE(grid, nullptr);
197 }
198 
199 // ---------------------------------------------------------------------------
200 
TEST_F(GridTest,GenericShiftGridSet_gtiff_with_subgrid)201 TEST_F(GridTest, GenericShiftGridSet_gtiff_with_subgrid) {
202     auto gridSet = NS_PROJ::GenericShiftGridSet::open(
203         m_ctxt, "tests/test_hgrid_with_subgrid.tif");
204     ASSERT_NE(gridSet, nullptr);
205     ASSERT_EQ(gridSet->gridAt(-100, -100), nullptr);
206     auto grid =
207         gridSet->gridAt(-115.5416667 / 180 * M_PI, 51.1666667 / 180 * M_PI);
208     ASSERT_NE(grid, nullptr);
209     EXPECT_EQ(grid->width(), 11);
210     EXPECT_EQ(grid->height(), 21);
211     EXPECT_EQ(grid->metadataItem("grid_name"), "ALbanff");
212 }
213 
214 // ---------------------------------------------------------------------------
215 
TEST_F(GridTest,GenericShiftGridSet_gtiff_with_two_level_of_subgrids_no_grid_name)216 TEST_F(GridTest,
217        GenericShiftGridSet_gtiff_with_two_level_of_subgrids_no_grid_name) {
218     auto gridSet = NS_PROJ::GenericShiftGridSet::open(
219         m_ctxt, "tests/test_hgrid_with_two_level_of_subgrids_no_grid_name.tif");
220     ASSERT_NE(gridSet, nullptr);
221     ASSERT_EQ(gridSet->gridAt(-100, -100), nullptr);
222     auto grid = gridSet->gridAt(-45.5 / 180 * M_PI, 22.5 / 180 * M_PI);
223     ASSERT_NE(grid, nullptr);
224     EXPECT_EQ(grid->width(), 8);
225     EXPECT_EQ(grid->height(), 8);
226 }
227 
228 // ---------------------------------------------------------------------------
229 
TEST_F(GridTest,GenericShiftGridSet_gtiff_projected)230 TEST_F(GridTest, GenericShiftGridSet_gtiff_projected) {
231     auto gridSet = NS_PROJ::GenericShiftGridSet::open(
232         m_ctxt, "tests/test_3d_grid_projected.tif");
233     ASSERT_NE(gridSet, nullptr);
234     ASSERT_EQ(gridSet->gridAt(-1000, -1000), nullptr);
235     auto grid = gridSet->gridAt(1500300.0, 5400300.0);
236     ASSERT_NE(grid, nullptr);
237     EXPECT_EQ(grid->width(), 2);
238     EXPECT_EQ(grid->height(), 2);
239     EXPECT_EQ(grid->extentAndRes().isGeographic, false);
240     EXPECT_EQ(grid->extentAndRes().west, 1500000.0);
241     EXPECT_EQ(grid->extentAndRes().east, 1501000.0);
242     EXPECT_EQ(grid->extentAndRes().south, 5400000.0);
243     EXPECT_EQ(grid->extentAndRes().north, 5401000.0);
244     EXPECT_EQ(grid->extentAndRes().resX, 1000);
245     EXPECT_EQ(grid->extentAndRes().resY, 1000);
246 }
247 
248 } // namespace
249