1 /*
2  * Stellarium
3  * Copyright (C) 2015 Alexander Wolf
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #include <QObject>
21 #include <QtDebug>
22 #include <QVariantList>
23 
24 #include "tests/testRefraction.hpp"
25 #include "StelUtils.hpp"
26 
QTEST_GUILESS_MAIN(TestRefraction)27 QTEST_GUILESS_MAIN(TestRefraction)
28 
29 void TestRefraction::initTestCase()
30 {
31 	Refraction refCls;
32 	Vec3d v(1.,0.,0.);
33 	refCls.forward(v);
34 	QVERIFY(v[2]>=0);
35 }
36 
testSaemundssonEquation()37 void TestRefraction::testSaemundssonEquation()
38 {
39 	Refraction refCls;
40 	float acceptableError = 0.07;
41 
42 	// Theoretical values, what gives the Saemundsson equation for refraction.
43 	// Calculating apparent altitudes from the true altitudes.
44 	QVariantList data;
45 	data << 0 << 28.982;
46 	data << 5 << 9.674;
47 	data << 10 << 5.408;
48 	data << 15 << 3.675;
49 	data << 20 << 2.741;
50 	data << 25 << 2.154;
51 	data << 30 << 1.746;
52 	data << 35 << 1.443;
53 	data << 40 << 1.206;
54 	data << 45 << 1.013;
55 	data << 50 << 0.850;
56 	data << 55 << 0.710;
57 	data << 60 << 0.585;
58 	data << 65 << 0.472;
59 	data << 70 << 0.368;
60 	data << 75 << 0.271;
61 	data << 80 << 0.178;
62 	data << 85 << 0.087;
63 	data << 89 << 0.016;
64 
65 	refCls.setPressure(1010);
66 	refCls.setTemperature(10);
67 
68 	while(data.count() >= 2)
69 	{
70 		int height = data.takeFirst().toInt();
71 		double ref = data.takeFirst().toDouble();
72 		Vec3d v;
73 		double h = height * M_PI/180.;
74 		StelUtils::spheToRect(0.0, h, v);
75 		refCls.forward(v);
76 		double lng, lat;
77 		StelUtils::rectToSphe(&lng, &lat, v);
78 		double result = qAbs((h-lat)*M_180_PI)*60.;
79 		double actualError = qAbs(ref - result);
80 		QVERIFY2(actualError <= acceptableError, QString("height=%1deg result=%2\" expected=%3\" error=%4 acceptable=%5")
81 							.arg(height)
82 							.arg(result)
83 							.arg(ref)
84 							.arg(actualError)
85 							.arg(acceptableError)
86 							.toUtf8());
87 
88 		float refF = (float)ref;
89 		Vec3f vF;
90 		float hF = height * M_PI/180.f;
91 		StelUtils::spheToRect(0.f, hF, vF);
92 		refCls.forward(vF);
93 		float lngF, latF;
94 		StelUtils::rectToSphe(&lngF, &latF, vF);
95 		float resultF = qAbs((hF-latF)*180.f/M_PI)*60.f;
96 		float actualErrorF = qAbs(refF - resultF);
97 		QVERIFY2(actualErrorF <= acceptableError, QString("height=%1deg result=%2\" expected=%3\" error=%4 acceptable=%5")
98 							.arg(height)
99 							.arg(resultF)
100 							.arg(refF)
101 							.arg(actualErrorF)
102 							.arg(acceptableError)
103 							.toUtf8());
104 	}
105 }
106 
testBennettEquation()107 void TestRefraction::testBennettEquation()
108 {
109 	Refraction refCls;
110 	float acceptableError = 0.14;
111 
112 	// Theoretical values, what gives the Bennett equation for refraction.
113 	// Calculating true altitudes from the apparent altitudes.
114 	QVariantList data;
115 	data << 0 << 34.478;
116 	data << 5 << 9.883;
117 	data << 10 << 5.392;
118 	data << 15 << 3.636;
119 	data << 20 << 2.703;
120 	data << 25 << 2.120;
121 	data << 30 << 1.717;
122 	data << 35 << 1.418;
123 	data << 40 << 1.185;
124 	data << 45 << 0.995;
125 	data << 50 << 0.835;
126 	data << 55 << 0.697;
127 	data << 60 << 0.575;
128 	data << 65 << 0.464;
129 	data << 70 << 0.362;
130 	data << 75 << 0.266;
131 	data << 80 << 0.175;
132 	data << 85 << 0.086;
133 	data << 89 << 0.016;
134 
135 	refCls.setPressure(1010);
136 	refCls.setTemperature(10);
137 
138 	while(data.count() >= 2)
139 	{
140 		int height = data.takeFirst().toInt();
141 		double ref = data.takeFirst().toDouble();
142 		Vec3d v;
143 		double h = height * M_PI/180.;
144 		StelUtils::spheToRect(0.0, h, v);
145 		refCls.backward(v);
146 		double lng, lat;
147 		StelUtils::rectToSphe(&lng, &lat, v);
148 		double result = qAbs((h-lat)*M_180_PI)*60.;
149 		double actualError = qAbs(ref - result);
150 		QVERIFY2(actualError <= acceptableError, QString("height=%1deg result=%2\" expected=%3\" error=%4 acceptable=%5")
151 							.arg(height)
152 							.arg(result)
153 							.arg(ref)
154 							.arg(actualError)
155 							.arg(acceptableError)
156 							.toUtf8());
157 
158 		float refF = (float)ref;
159 		Vec3f vF;
160 		float hF = height * M_PI/180.f;
161 		StelUtils::spheToRect(0.f, hF, vF);
162 		refCls.backward(vF);
163 		float lngF, latF;
164 		StelUtils::rectToSphe(&lngF, &latF, vF);
165 		float resultF = qAbs((hF-latF)*180.f/M_PI)*60.f;
166 		double actualErrorF = qAbs(refF - resultF);
167 		QVERIFY2(actualErrorF <= acceptableError, QString("height=%1deg result=%2\" expected=%3\" error=%4 acceptable=%5")
168 							.arg(height)
169 							.arg(resultF)
170 							.arg(refF)
171 							.arg(actualErrorF)
172 							.arg(acceptableError)
173 							.toUtf8());
174 	}
175 }
176 
testComplexRefraction()177 void TestRefraction::testComplexRefraction()
178 {
179 	Refraction refCls;
180 	double acceptableError = 0.14;
181 
182 	// The delta of the theoretical values, what gives Saemundsson and Bennett equations for refraction.
183 	// true alt. -> apparent alt. -> true alt.
184 	QVariantList data;
185 	data << 0 << 5.496;
186 	data << 5 << 0.209;
187 	data << 10 << 0.016;
188 	data << 15 << 0.039;
189 	data << 20 << 0.038;
190 	data << 25 << 0.033;
191 	data << 30 << 0.029;
192 	data << 35 << 0.025;
193 	data << 40 << 0.021;
194 	data << 45 << 0.018;
195 	data << 50 << 0.015;
196 	data << 55 << 0.013;
197 	data << 60 << 0.010;
198 	data << 65 << 0.008;
199 	data << 70 << 0.006;
200 	data << 75 << 0.005;
201 	data << 80 << 0.003;
202 	data << 85 << 0.001;
203 	data << 89 << 0.000;
204 
205 	refCls.setPressure(1010);
206 	refCls.setTemperature(10);
207 
208 	while(data.count() >= 2)
209 	{
210 		int height = data.takeFirst().toInt();
211 		double expD = data.takeFirst().toDouble();
212 		Vec3d v;
213 		double lng, latS, latB;
214 		double h = height * M_PI/180.;
215 		StelUtils::spheToRect(0.0, h, v);
216 		refCls.forward(v);
217 		StelUtils::rectToSphe(&lng, &latS, v);
218 		StelUtils::spheToRect(0.0, h, v);
219 		refCls.backward(v);
220 		StelUtils::rectToSphe(&lng, &latB, v);
221 		double rS = qAbs((h-latS)*M_180_PI)*60.;
222 		double rB = qAbs((h-latB)*M_180_PI)*60.;
223 		double result = qAbs(rS-rB);
224 		QVERIFY2(qAbs(result - expD) <= acceptableError, QString("height=%1deg result=%2\" expected=%3\" acceptable=%5")
225 							.arg(height)
226 							.arg(result)
227 							.arg(expD)
228 							.arg(acceptableError)
229 							.toUtf8());
230 
231 		float expDF = (float)expD;
232 		Vec3f vF;
233 		float lngF, latSF, latBF;
234 		float hF = height * M_PI_180f;
235 		StelUtils::spheToRect(0.f, hF, vF);
236 		refCls.forward(vF);
237 		StelUtils::rectToSphe(&lngF, &latSF, vF);
238 		StelUtils::spheToRect(0.f, hF, vF);
239 		refCls.backward(vF);
240 		StelUtils::rectToSphe(&lngF, &latBF, vF);
241 		float rSF = qAbs((hF-latSF)*M_180_PIf)*60.f;
242 		float rBF = qAbs((hF-latBF)*M_180_PIf)*60.f;
243 		float resultF = qAbs(rSF-rBF);
244 		QVERIFY2(qAbs(resultF - expDF) <= acceptableError, QString("height=%1deg result=%2\" expected=%3\" acceptable=%5")
245 							.arg(height)
246 							.arg(resultF)
247 							.arg(expDF)
248 							.arg(acceptableError)
249 							.toUtf8());
250 	}
251 }
252