Line data Source code
1 : ///////////////////////////////////////////////////////////////////////////////
2 : //
3 : // Project: Internal C++ Test Suite for GDAL/OGR
4 : // Purpose: Test viewshed algorithm
5 : // Author: Andrew Bell
6 : //
7 : ///////////////////////////////////////////////////////////////////////////////
8 : /*
9 : * SPDX-License-Identifier: MIT
10 : ****************************************************************************/
11 :
12 : #include <cmath>
13 : #include <utility>
14 : #include <iostream>
15 :
16 : #include "gtest_include.h"
17 :
18 : #include "viewshed/viewshed.h"
19 : #include "viewshed/viewshed_types.h"
20 : #include "viewshed/util.h"
21 :
22 : namespace gdal
23 : {
24 : namespace viewshed
25 : {
26 :
27 4 : TEST(ViewshedInternal, angle)
28 : {
29 1 : EXPECT_DOUBLE_EQ(M_PI / 2, normalizeAngle(0));
30 1 : EXPECT_DOUBLE_EQ(M_PI / 4, normalizeAngle(45));
31 1 : EXPECT_DOUBLE_EQ(0.0, normalizeAngle(90));
32 1 : EXPECT_DOUBLE_EQ(7 * M_PI / 4, normalizeAngle(135));
33 1 : EXPECT_DOUBLE_EQ(3 * M_PI / 2, normalizeAngle(180));
34 1 : EXPECT_DOUBLE_EQ(M_PI, normalizeAngle(270));
35 1 : }
36 :
37 4 : TEST(ViewshedInternal, between)
38 : {
39 1 : EXPECT_TRUE(rayBetween(M_PI, 0, M_PI / 2));
40 1 : EXPECT_FALSE(rayBetween(M_PI, 0, 3 * M_PI / 2));
41 1 : EXPECT_TRUE(rayBetween(0, 3 * M_PI / 2, 7 * M_PI / 4));
42 1 : EXPECT_TRUE(rayBetween(M_PI / 4, 7 * M_PI / 4, 0));
43 1 : EXPECT_FALSE(rayBetween(M_PI / 4, 7 * M_PI / 4, M_PI));
44 1 : }
45 :
46 4 : TEST(ViewshedInternal, intersect)
47 : {
48 : // Top side
49 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(0, 0, 0, -2)));
50 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(M_PI, 0, 0, -2)));
51 1 : EXPECT_DOUBLE_EQ(horizontalIntersect(M_PI / 2, 0, 0, -2), 0);
52 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(3 * M_PI / 2, 0, 0, -2)));
53 1 : EXPECT_DOUBLE_EQ(horizontalIntersect(M_PI / 4, 0, 0, -2), 2);
54 1 : EXPECT_DOUBLE_EQ(horizontalIntersect(3 * M_PI / 4, 0, 0, -2), -2);
55 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(5 * M_PI / 4, 0, 0, -2)));
56 1 : EXPECT_DOUBLE_EQ(horizontalIntersect(M_PI / 6, 0, 0, -2), 2 * std::sqrt(3));
57 :
58 : // Bottom side
59 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(0, 0, 0, 2)));
60 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(M_PI, 0, 0, 2)));
61 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(M_PI / 2, 0, 0, 2)));
62 1 : EXPECT_DOUBLE_EQ(horizontalIntersect(3 * M_PI / 2, 0, 0, 2), 0);
63 :
64 1 : EXPECT_DOUBLE_EQ(horizontalIntersect(5 * M_PI / 4, 0, 0, 2), -2);
65 1 : EXPECT_DOUBLE_EQ(horizontalIntersect(7 * M_PI / 4, 0, 0, 2), 2);
66 1 : EXPECT_TRUE(std::isnan(horizontalIntersect(3 * M_PI / 4, 0, 0, 2)));
67 1 : EXPECT_NEAR(horizontalIntersect(7 * M_PI / 6, 0, 0, 2), -2 * std::sqrt(3),
68 : 1e-10);
69 :
70 : // Right side
71 1 : EXPECT_DOUBLE_EQ(verticalIntersect(0, 0, 0, 2), 0);
72 1 : EXPECT_TRUE(std::isnan(verticalIntersect(M_PI, 0, 0, 2)));
73 1 : EXPECT_TRUE(std::isnan(verticalIntersect(M_PI / 2, 0, 0, 2)));
74 1 : EXPECT_TRUE(std::isnan(verticalIntersect(3 * M_PI / 2, 0, 0, 2)));
75 1 : EXPECT_TRUE(std::isnan(verticalIntersect(5 * M_PI / 4, 0, 0, 2)));
76 1 : EXPECT_DOUBLE_EQ(verticalIntersect(M_PI / 4, 0, 0, 2), -2);
77 1 : EXPECT_DOUBLE_EQ(verticalIntersect(7 * M_PI / 4, 0, 0, 2), 2);
78 1 : EXPECT_DOUBLE_EQ(verticalIntersect(M_PI / 6, 0, 0, 2), -2 / std::sqrt(3));
79 :
80 : // Left side
81 1 : EXPECT_DOUBLE_EQ(verticalIntersect(M_PI, 0, 0, -2), 0);
82 1 : EXPECT_TRUE(std::isnan(verticalIntersect(0, 0, 0, -2)));
83 1 : EXPECT_TRUE(std::isnan(verticalIntersect(M_PI / 2, 0, 0, -2)));
84 1 : EXPECT_TRUE(std::isnan(verticalIntersect(3 * M_PI / 2, 0, 0, -2)));
85 1 : EXPECT_TRUE(std::isnan(verticalIntersect(3 * M_PI / 4, 0, 0, 2)));
86 1 : EXPECT_DOUBLE_EQ(verticalIntersect(3 * M_PI / 4, 0, 0, -2), -2);
87 1 : EXPECT_DOUBLE_EQ(verticalIntersect(5 * M_PI / 4, 0, 0, -2), 2);
88 1 : EXPECT_DOUBLE_EQ(verticalIntersect(5 * M_PI / 6, 0, 0, -2),
89 : -2 / std::sqrt(3));
90 1 : }
91 :
92 : void testShrinkWindowForAngles(Window &w, int, int, double, double);
93 :
94 4 : TEST(ViewshedInternal, shrinkbox)
95 : {
96 13 : auto testExtent = [](double start, double stop, Window expected)
97 : {
98 13 : Window extent{-3, 3, -2, 2};
99 13 : testShrinkWindowForAngles(extent, 0, 0, start, stop);
100 13 : EXPECT_EQ(extent, expected);
101 13 : };
102 :
103 : // Angles are standard (0 right going counter-clockwise
104 : // We go clockwise from start to stop.
105 1 : testExtent(3 * M_PI / 4, M_PI / 4, {-2, 3, -2, 1});
106 1 : testExtent(M_PI / 4, 3 * M_PI / 4, {-3, 3, -2, 2});
107 1 : testExtent(0.321750554, 2 * M_PI - 0.321750554,
108 : {0, 3, -1, 2}); // <2, 1>, <2, -1>
109 1 : testExtent(2 * M_PI - 0.321750554, 0.321750554,
110 : {-3, 3, -2, 2}); // <2, -1>, <2, 1>
111 1 : testExtent(7 * M_PI / 4, 5 * M_PI / 4, {-2, 3, 0, 2});
112 1 : testExtent(5 * M_PI / 4, 7 * M_PI / 4, {-3, 3, -2, 2});
113 1 : testExtent(M_PI + 0.321750554, M_PI - 0.321750554,
114 : {-3, 1, -1, 2}); // <-2, -1>, <-2, 1>
115 1 : testExtent(M_PI - 0.321750554, M_PI + 0.321750554,
116 : {-3, 3, -2, 2}); // <-2, 1>, <-2, -1>
117 1 : testExtent(M_PI / 4, 0.321750554, {0, 3, -2, 1}); // <2, 2>, <2, 1>
118 1 : testExtent(0.321750554, M_PI / 4, {-3, 3, -2, 2}); // <2, 1>, <2, 2>
119 1 : testExtent(M_PI / 4, 7 * M_PI / 4, {0, 3, -2, 2});
120 1 : testExtent(M_PI / 4, M_PI + 0.321750554,
121 : {-3, 3, -2, 2}); // <2, 2>, <-2, -1>
122 1 : testExtent(M_PI + 0.321750554, M_PI / 4,
123 : {-3, 3, -2, 2}); // <-2, -1>, <2, 2>
124 1 : }
125 :
126 : } // namespace viewshed
127 : } // namespace gdal
|