Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: GDAL algorithms
5 : * Purpose: Test alg
6 : * Author: Even Rouault, even.rouault at spatialys.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include <array>
15 :
16 : #include "gdal_unit_test.h"
17 :
18 : #include "cpl_conv.h"
19 :
20 : #include "gdal_alg.h"
21 : #include "gdalwarper.h"
22 : #include "gdal_priv.h"
23 :
24 : #include "gtest_include.h"
25 :
26 : #include "test_data.h"
27 :
28 : namespace
29 : {
30 : // Common fixture with test data
31 : struct test_alg : public ::testing::Test
32 : {
33 : std::string data_;
34 :
35 12 : test_alg()
36 12 : {
37 : // Compose data path for test group
38 12 : data_ = tut::common::data_basedir;
39 12 : }
40 : };
41 :
42 : typedef struct
43 : {
44 : double dfLevel;
45 : int nPoints;
46 : double x;
47 : double y;
48 : } writeCbkData;
49 :
50 0 : static CPLErr writeCbk(double dfLevel, int nPoints, double *padfX,
51 : double *padfY, void *userData)
52 : {
53 0 : writeCbkData *data = (writeCbkData *)userData;
54 0 : data->dfLevel = dfLevel;
55 0 : data->nPoints = nPoints;
56 0 : if (nPoints == 1)
57 : {
58 0 : data->x = padfX[0];
59 0 : data->y = padfY[0];
60 : }
61 0 : return CE_None;
62 : }
63 :
64 : // Dummy test
65 4 : TEST_F(test_alg, GDAL_CG_FeedLine_dummy)
66 : {
67 : writeCbkData data;
68 1 : memset(&data, 0, sizeof(data));
69 : GDALContourGeneratorH hCG =
70 1 : GDAL_CG_Create(1, 1, FALSE, 0, 1, 0, writeCbk, &data);
71 1 : double scanline[] = {0};
72 1 : EXPECT_EQ(GDAL_CG_FeedLine(hCG, scanline), CE_None);
73 1 : EXPECT_EQ(data.dfLevel, 0);
74 1 : EXPECT_EQ(data.nPoints, 0);
75 1 : EXPECT_DOUBLE_EQ(data.x, 0.0);
76 1 : EXPECT_DOUBLE_EQ(data.y, 0.0);
77 1 : GDAL_CG_Destroy(hCG);
78 1 : }
79 :
80 : // GDALWarpResolveWorkingDataType: default type
81 4 : TEST_F(test_alg, GDALWarpResolveWorkingDataType_default_type)
82 : {
83 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
84 1 : GDALWarpResolveWorkingDataType(psOptions);
85 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
86 1 : GDALDestroyWarpOptions(psOptions);
87 1 : }
88 :
89 : // GDALWarpResolveWorkingDataType: do not change user specified type
90 4 : TEST_F(test_alg, GDALWarpResolveWorkingDataType_keep_user_type)
91 : {
92 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
93 1 : psOptions->eWorkingDataType = GDT_CFloat64;
94 1 : GDALWarpResolveWorkingDataType(psOptions);
95 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_CFloat64);
96 1 : GDALDestroyWarpOptions(psOptions);
97 1 : }
98 :
99 : // GDALWarpResolveWorkingDataType: effect of padfSrcNoDataReal
100 4 : TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfSrcNoDataReal)
101 : {
102 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
103 1 : psOptions->nBandCount = 1;
104 1 : psOptions->padfSrcNoDataReal =
105 1 : static_cast<double *>(CPLMalloc(sizeof(double)));
106 1 : psOptions->padfSrcNoDataReal[0] = 0.0;
107 1 : GDALWarpResolveWorkingDataType(psOptions);
108 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
109 :
110 1 : psOptions->eWorkingDataType = GDT_Unknown;
111 1 : psOptions->padfSrcNoDataReal[0] = -1.0;
112 1 : GDALWarpResolveWorkingDataType(psOptions);
113 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Int16);
114 :
115 1 : psOptions->eWorkingDataType = GDT_Unknown;
116 1 : psOptions->padfSrcNoDataReal[0] = 2.0;
117 1 : GDALWarpResolveWorkingDataType(psOptions);
118 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
119 :
120 1 : psOptions->eWorkingDataType = GDT_Unknown;
121 1 : psOptions->padfSrcNoDataReal[0] = 256.0;
122 1 : GDALWarpResolveWorkingDataType(psOptions);
123 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_UInt16);
124 :
125 1 : psOptions->eWorkingDataType = GDT_Unknown;
126 1 : psOptions->padfSrcNoDataReal[0] = 2.5;
127 1 : GDALWarpResolveWorkingDataType(psOptions);
128 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Float32);
129 :
130 1 : psOptions->eWorkingDataType = GDT_Unknown;
131 1 : psOptions->padfSrcNoDataReal[0] = 2.12345678;
132 1 : GDALWarpResolveWorkingDataType(psOptions);
133 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Float64);
134 :
135 1 : GDALDestroyWarpOptions(psOptions);
136 1 : }
137 :
138 : // GDALWarpResolveWorkingDataType: effect of padfSrcNoDataReal
139 4 : TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfSrcNoDataReal_with_band)
140 : {
141 : GDALDatasetUniquePtr poDS(GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
142 2 : ->Create("", 1, 1, 1, GDT_Byte, nullptr));
143 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
144 : // False-positive: hSrcDS is no longer used after GDALDestroyWarpOptions()
145 : // coverity[escape]
146 1 : psOptions->hSrcDS = GDALDataset::ToHandle(poDS.get());
147 1 : psOptions->nBandCount = 1;
148 1 : psOptions->panSrcBands =
149 1 : static_cast<int *>(CPLMalloc(psOptions->nBandCount * sizeof(int)));
150 1 : psOptions->panSrcBands[0] = 1;
151 1 : psOptions->padfSrcNoDataReal =
152 1 : static_cast<double *>(CPLMalloc(sizeof(double)));
153 1 : psOptions->padfSrcNoDataReal[0] = 0.0;
154 1 : GDALWarpResolveWorkingDataType(psOptions);
155 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
156 :
157 1 : psOptions->padfSrcNoDataReal[0] = -1.0;
158 1 : GDALWarpResolveWorkingDataType(psOptions);
159 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
160 :
161 1 : psOptions->eWorkingDataType = GDT_Unknown;
162 1 : psOptions->padfSrcNoDataReal[0] = 2.0;
163 1 : GDALWarpResolveWorkingDataType(psOptions);
164 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
165 :
166 1 : GDALDestroyWarpOptions(psOptions);
167 1 : }
168 :
169 : // GDALWarpResolveWorkingDataType: effect of padfSrcNoDataImag
170 4 : TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfSrcNoDataImag)
171 : {
172 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
173 1 : psOptions->nBandCount = 1;
174 1 : psOptions->padfSrcNoDataReal =
175 1 : static_cast<double *>(CPLMalloc(sizeof(double)));
176 1 : psOptions->padfSrcNoDataImag =
177 1 : static_cast<double *>(CPLMalloc(sizeof(double)));
178 1 : psOptions->padfSrcNoDataReal[0] = 0.0;
179 1 : psOptions->padfSrcNoDataImag[0] = 0.0;
180 1 : GDALWarpResolveWorkingDataType(psOptions);
181 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
182 :
183 1 : psOptions->eWorkingDataType = GDT_Unknown;
184 1 : psOptions->padfSrcNoDataReal[0] = 0.0;
185 1 : psOptions->padfSrcNoDataImag[0] = 1.0;
186 1 : GDALWarpResolveWorkingDataType(psOptions);
187 : // Could probably be CInt16
188 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_CInt32);
189 :
190 1 : psOptions->eWorkingDataType = GDT_Unknown;
191 1 : psOptions->padfSrcNoDataReal[0] = 0.0;
192 1 : psOptions->padfSrcNoDataImag[0] = 1.5;
193 1 : GDALWarpResolveWorkingDataType(psOptions);
194 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_CFloat32);
195 :
196 1 : psOptions->eWorkingDataType = GDT_Unknown;
197 1 : psOptions->padfSrcNoDataReal[0] = 0.0;
198 1 : psOptions->padfSrcNoDataImag[0] = 2.12345678;
199 1 : GDALWarpResolveWorkingDataType(psOptions);
200 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_CFloat64);
201 :
202 1 : GDALDestroyWarpOptions(psOptions);
203 1 : }
204 :
205 : // GDALWarpResolveWorkingDataType: effect of padfDstNoDataReal
206 4 : TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfDstNoDataReal)
207 : {
208 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
209 1 : psOptions->nBandCount = 1;
210 1 : psOptions->padfDstNoDataReal =
211 1 : static_cast<double *>(CPLMalloc(sizeof(double)));
212 1 : psOptions->padfDstNoDataReal[0] = 0.0;
213 1 : GDALWarpResolveWorkingDataType(psOptions);
214 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
215 :
216 1 : psOptions->eWorkingDataType = GDT_Unknown;
217 1 : psOptions->padfDstNoDataReal[0] = -1.0;
218 1 : GDALWarpResolveWorkingDataType(psOptions);
219 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Int16);
220 :
221 1 : psOptions->eWorkingDataType = GDT_Unknown;
222 1 : psOptions->padfDstNoDataReal[0] = 2.0;
223 1 : GDALWarpResolveWorkingDataType(psOptions);
224 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
225 :
226 1 : psOptions->eWorkingDataType = GDT_Unknown;
227 1 : psOptions->padfDstNoDataReal[0] = 256.0;
228 1 : GDALWarpResolveWorkingDataType(psOptions);
229 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_UInt16);
230 :
231 1 : psOptions->eWorkingDataType = GDT_Unknown;
232 1 : psOptions->padfDstNoDataReal[0] = 2.5;
233 1 : GDALWarpResolveWorkingDataType(psOptions);
234 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Float32);
235 :
236 1 : psOptions->eWorkingDataType = GDT_Unknown;
237 1 : psOptions->padfDstNoDataReal[0] = 2.12345678;
238 1 : GDALWarpResolveWorkingDataType(psOptions);
239 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Float64);
240 :
241 1 : GDALDestroyWarpOptions(psOptions);
242 1 : }
243 :
244 : // GDALWarpResolveWorkingDataType: effect of padfDstNoDataImag
245 4 : TEST_F(test_alg, GDALWarpResolveWorkingDataType_padfDstNoDataImag)
246 : {
247 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
248 1 : psOptions->nBandCount = 1;
249 1 : psOptions->padfDstNoDataReal =
250 1 : static_cast<double *>(CPLMalloc(sizeof(double)));
251 1 : psOptions->padfDstNoDataImag =
252 1 : static_cast<double *>(CPLMalloc(sizeof(double)));
253 1 : psOptions->padfDstNoDataReal[0] = 0.0;
254 1 : psOptions->padfDstNoDataImag[0] = 0.0;
255 1 : GDALWarpResolveWorkingDataType(psOptions);
256 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_Byte);
257 :
258 1 : psOptions->eWorkingDataType = GDT_Unknown;
259 1 : psOptions->padfDstNoDataReal[0] = 0.0;
260 1 : psOptions->padfDstNoDataImag[0] = 1.0;
261 1 : GDALWarpResolveWorkingDataType(psOptions);
262 : // Could probably be CInt16
263 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_CInt32);
264 :
265 1 : psOptions->eWorkingDataType = GDT_Unknown;
266 1 : psOptions->padfDstNoDataImag[0] = 0.0;
267 1 : psOptions->padfDstNoDataImag[0] = 1.5;
268 1 : GDALWarpResolveWorkingDataType(psOptions);
269 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_CFloat32);
270 :
271 1 : psOptions->eWorkingDataType = GDT_Unknown;
272 1 : psOptions->padfDstNoDataImag[0] = 0.0;
273 1 : psOptions->padfDstNoDataImag[0] = 2.12345678;
274 1 : GDALWarpResolveWorkingDataType(psOptions);
275 1 : EXPECT_EQ(psOptions->eWorkingDataType, GDT_CFloat64);
276 :
277 1 : GDALDestroyWarpOptions(psOptions);
278 1 : }
279 :
280 : // Test GDALAutoCreateWarpedVRT() with creation of an alpha band
281 4 : TEST_F(test_alg, GDALAutoCreateWarpedVRT_alpha_band)
282 : {
283 : GDALDatasetUniquePtr poDS(GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
284 1 : ->Create("", 1, 1, 1, GDT_Byte, nullptr));
285 1 : poDS->SetProjection(SRS_WKT_WGS84_LAT_LONG);
286 1 : double adfGeoTransform[6] = {10, 1, 0, 20, 0, -1};
287 1 : poDS->SetGeoTransform(adfGeoTransform);
288 1 : GDALWarpOptions *psOptions = GDALCreateWarpOptions();
289 1 : psOptions->nDstAlphaBand = 2;
290 : GDALDatasetH hWarpedVRT =
291 1 : GDALAutoCreateWarpedVRT(GDALDataset::ToHandle(poDS.get()), nullptr,
292 : nullptr, GRA_NearestNeighbour, 0.0, psOptions);
293 1 : ASSERT_TRUE(hWarpedVRT != nullptr);
294 1 : ASSERT_EQ(GDALGetRasterCount(hWarpedVRT), 2);
295 1 : EXPECT_EQ(
296 : GDALGetRasterColorInterpretation(GDALGetRasterBand(hWarpedVRT, 2)),
297 : GCI_AlphaBand);
298 1 : GDALDestroyWarpOptions(psOptions);
299 1 : GDALClose(hWarpedVRT);
300 : }
301 :
302 : // Test GDALIsLineOfSightVisible() with single point dataset
303 4 : TEST_F(test_alg, GDALIsLineOfSightVisible_single_point_dataset)
304 : {
305 1 : auto const sizeX = 1;
306 1 : auto const sizeY = 1;
307 1 : auto const numBands = 1;
308 : GDALDatasetUniquePtr poDS(
309 : GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
310 1 : ->Create("", sizeX, sizeY, numBands, GDT_Int8, nullptr));
311 1 : ASSERT_TRUE(poDS != nullptr);
312 :
313 1 : int8_t val = 42;
314 1 : auto pBand = poDS->GetRasterBand(1);
315 1 : ASSERT_TRUE(pBand != nullptr);
316 1 : ASSERT_TRUE(poDS->RasterIO(GF_Write, 0, 0, 1, 1, &val, 1, 1, GDT_Int8, 1,
317 : nullptr, 0, 0, 0, nullptr) == CE_None);
318 : // Both points below terrain
319 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 0, 0, 0.0, 0, 0, 0.0, nullptr,
320 : nullptr, nullptr));
321 : // One point below terrain
322 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 0, 0, 0.0, 0, 0, 43.0, nullptr,
323 : nullptr, nullptr));
324 : int xIntersection, yIntersection;
325 1 : int *pXIntersection = &xIntersection;
326 1 : int *pYIntersection = &yIntersection;
327 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(
328 : pBand, 0, 0, 0.0, 0, 0, 43.0, pXIntersection, pYIntersection, nullptr));
329 1 : EXPECT_EQ(*pXIntersection, 0);
330 1 : EXPECT_EQ(*pYIntersection, 0);
331 : // Both points above terrain
332 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 0, 0, 44.0, 0, 0, 43.0, nullptr,
333 : nullptr, nullptr));
334 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 0, 0, 44.0, 0, 0, 43.0,
335 : pXIntersection, pYIntersection,
336 : nullptr));
337 : }
338 :
339 : // Test GDALIsLineOfSightVisible() with 10x10 default dataset
340 4 : TEST_F(test_alg, GDALIsLineOfSightVisible_default_square_dataset)
341 : {
342 1 : auto const sizeX = 10;
343 1 : auto const sizeY = 10;
344 1 : auto const numBands = 1;
345 : GDALDatasetUniquePtr poDS(
346 : GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
347 1 : ->Create("", sizeX, sizeY, numBands, GDT_Int8, nullptr));
348 1 : ASSERT_TRUE(poDS != nullptr);
349 :
350 1 : auto pBand = poDS->GetRasterBand(1);
351 1 : ASSERT_TRUE(pBand != nullptr);
352 :
353 1 : const int x1 = 1;
354 1 : const int y1 = 1;
355 1 : const int x2 = 2;
356 1 : const int y2 = 2;
357 :
358 : // Both points are above terrain.
359 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, x1, y1, 1.0, x2, y2, 1.0,
360 : nullptr, nullptr, nullptr));
361 : // Both points are above terrain, supply intersection.
362 : int xIntersection, yIntersection;
363 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, x1, y1, 1.0, x2, y2, 1.0,
364 : &xIntersection, &yIntersection,
365 : nullptr));
366 : // Flip the order, same result.
367 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, x2, y2, 1.0, x1, y1, 1.0,
368 : nullptr, nullptr, nullptr));
369 :
370 : // One point is below terrain.
371 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, x1, y1, -1.0, x2, y2, 1.0,
372 : nullptr, nullptr, nullptr));
373 1 : int *pXIntersection = &xIntersection;
374 1 : int *pYIntersection = &yIntersection;
375 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, x1, y1, -1.0, x2, y2, 1.0,
376 : pXIntersection, pYIntersection,
377 : nullptr));
378 1 : EXPECT_EQ(*pXIntersection, 1);
379 1 : EXPECT_EQ(*pYIntersection, 1);
380 : // Flip the order, same result.
381 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, x2, y2, -1.0, x1, y1, 1.0,
382 : pXIntersection, pYIntersection,
383 : nullptr));
384 1 : EXPECT_EQ(*pXIntersection, 2);
385 1 : EXPECT_EQ(*pYIntersection, 2);
386 :
387 : // Both points are below terrain.
388 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, x1, y1, -1.0, x2, y2, -1.0,
389 : nullptr, nullptr, nullptr));
390 : // Flip the order, same result.
391 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, x2, y2, -1.0, x1, y1, -1.0,
392 : nullptr, nullptr, nullptr));
393 : }
394 :
395 : // Test GDALIsLineOfSightVisible() through a mountain (not a unit test)
396 4 : TEST_F(test_alg, GDALIsLineOfSightVisible_through_mountain)
397 : {
398 1 : GDALAllRegister();
399 :
400 1 : const std::string path = data_ + SEP + "n43.dt0";
401 : const auto poDS = GDALDatasetUniquePtr(
402 1 : GDALDataset::FromHandle(GDALOpen(path.c_str(), GA_ReadOnly)));
403 1 : if (!poDS)
404 : {
405 0 : GTEST_SKIP() << "Cannot open " << path;
406 : }
407 :
408 1 : auto pBand = poDS->GetRasterBand(1);
409 1 : ASSERT_TRUE(pBand != nullptr);
410 : std::array<double, 6> geoFwdTransform;
411 1 : ASSERT_TRUE(poDS->GetGeoTransform(geoFwdTransform.data()) == CE_None);
412 : std::array<double, 6> geoInvTransform;
413 1 : ASSERT_TRUE(
414 : GDALInvGeoTransform(geoFwdTransform.data(), geoInvTransform.data()));
415 :
416 : // Check both sides of a mesa (north and south ends).
417 : // Top mesa at (x=8,y=58,alt=221)
418 1 : const double mesaLatTop = 43.5159;
419 1 : const double mesaLngTop = -79.9327;
420 :
421 : // Bottom is at (x=12,y=64,alt=199)
422 1 : const double mesaLatBottom = 43.4645;
423 1 : const double mesaLngBottom = -79.8985;
424 :
425 : // In between the two locations, the mesa reaches a local max altiude of 321.
426 :
427 : double dMesaTopX, dMesaTopY, dMesaBottomX, dMesaBottomY;
428 1 : GDALApplyGeoTransform(geoInvTransform.data(), mesaLngTop, mesaLatTop,
429 : &dMesaTopX, &dMesaTopY);
430 1 : GDALApplyGeoTransform(geoInvTransform.data(), mesaLngBottom, mesaLatBottom,
431 : &dMesaBottomX, &dMesaBottomY);
432 1 : const int iMesaTopX = static_cast<int>(dMesaTopX);
433 1 : const int iMesaTopY = static_cast<int>(dMesaTopY);
434 1 : const int iMesaBottomX = static_cast<int>(dMesaBottomX);
435 1 : const int iMesaBottomY = static_cast<int>(dMesaBottomY);
436 :
437 : // Both points are just above terrain, with terrain between.
438 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, iMesaTopX, iMesaTopY, 222,
439 : iMesaBottomX, iMesaBottomY, 199,
440 : nullptr, nullptr, nullptr));
441 : // Flip the order, same result.
442 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, iMesaBottomX, iMesaBottomY,
443 : 199, iMesaTopX, iMesaTopY, 222,
444 : nullptr, nullptr, nullptr));
445 :
446 : // Both points above terrain.
447 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, iMesaTopX, iMesaTopY, 322,
448 : iMesaBottomX, iMesaBottomY, 322,
449 : nullptr, nullptr, nullptr));
450 :
451 : // Both points below terrain.
452 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, iMesaTopX, iMesaTopY, 0,
453 : iMesaBottomX, iMesaBottomY, 0,
454 : nullptr, nullptr, nullptr));
455 :
456 : // Test negative slope bresenham diagonals across the whole raster.
457 : // Both high above terrain.
458 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 0, 0, 460, 120, 120, 460,
459 : nullptr, nullptr, nullptr));
460 : // Both heights are 1m above in the corners, but middle terrain violates LOS.
461 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 0, 0, 295, 120, 120, 183,
462 : nullptr, nullptr, nullptr));
463 :
464 : int xIntersection, yIntersection;
465 1 : int *pXIntersection = &xIntersection;
466 1 : int *pYIntersection = &yIntersection;
467 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 0, 0, 295, 120, 120, 183,
468 : pXIntersection, pYIntersection,
469 : nullptr));
470 1 : EXPECT_EQ(*pXIntersection, 2);
471 1 : EXPECT_EQ(*pYIntersection, 2);
472 :
473 : // Test positive slope bresenham diagnoals across the whole raster.
474 : // Both high above terrain.
475 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 0, 120, 460, 120, 0, 460,
476 : nullptr, nullptr, nullptr));
477 : // Both heights are 1m above in the corners, but middle terrain violates LOS.
478 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 0, 120, 203, 120, 0, 247,
479 : nullptr, nullptr, nullptr));
480 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 0, 120, 203, 120, 0, 247,
481 : pXIntersection, pYIntersection,
482 : nullptr));
483 :
484 1 : EXPECT_EQ(*pXIntersection, 120);
485 1 : EXPECT_EQ(*pYIntersection, 0);
486 :
487 : // Vertical line tests with hill between two points, in both directions.
488 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 83, 111, 154, 83, 117, 198,
489 : nullptr, nullptr, nullptr));
490 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 83, 117, 198, 83, 111, 154,
491 : nullptr, nullptr, nullptr));
492 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 83, 111, 460, 83, 117, 460,
493 : nullptr, nullptr, nullptr));
494 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 83, 117, 460, 83, 111, 460,
495 : nullptr, nullptr, nullptr));
496 :
497 : // Horizontal line tests with hill between two points, in both directions.
498 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 75, 115, 192, 89, 115, 191,
499 : nullptr, nullptr, nullptr));
500 1 : EXPECT_FALSE(GDALIsLineOfSightVisible(pBand, 89, 115, 191, 75, 115, 192,
501 : nullptr, nullptr, nullptr));
502 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 75, 115, 460, 89, 115, 460,
503 : nullptr, nullptr, nullptr));
504 1 : EXPECT_TRUE(GDALIsLineOfSightVisible(pBand, 89, 115, 460, 75, 115, 460,
505 : nullptr, nullptr, nullptr));
506 : }
507 :
508 : } // namespace
|