1 /*
2  * Stellarium
3  * Copyright (C) 2009 Fabien Chereau
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 "tests/testStelSphereGeometry.hpp"
21 
22 #include <QObject>
23 #include <QtDebug>
24 #include <QBuffer>
25 
26 #include <stdexcept>
27 
28 #include "StelJsonParser.hpp"
29 #include "StelSphereGeometry.hpp"
30 #include "StelUtils.hpp"
31 
QTEST_GUILESS_MAIN(TestStelSphericalGeometry)32 QTEST_GUILESS_MAIN(TestStelSphericalGeometry)
33 
34 void TestStelSphericalGeometry::initTestCase()
35 {
36 	// Testing code for new polygon code
37 	QVector<QVector<Vec3d> > contours;
38 	QVector<Vec3d> c1(4);
39 	StelUtils::spheToRect(-0.5, -0.5, c1[3]);
40 	StelUtils::spheToRect(0.5, -0.5, c1[2]);
41 	StelUtils::spheToRect(0.5, 0.5, c1[1]);
42 	StelUtils::spheToRect(-0.5, 0.5, c1[0]);
43 	contours.append(c1);
44 	QVector<Vec3d> c2(4);
45 	StelUtils::spheToRect(-0.2, 0.2, c2[3]);
46 	StelUtils::spheToRect(0.2, 0.2, c2[2]);
47 	StelUtils::spheToRect(0.2, -0.2, c2[1]);
48 	StelUtils::spheToRect(-0.2, -0.2, c2[0]);
49 	contours.append(c2);
50 
51 	holySquare.setContours(contours);
52 	bigSquare.setContour(c1);
53 	bigSquareConvex.setContour(c1);
54 	QVector<Vec3d> c2inv(4);
55 	c2inv[0]=c2[3]; c2inv[1]=c2[2]; c2inv[2]=c2[1]; c2inv[3]=c2[0];
56 	smallSquare.setContour(c2inv);
57 	smallSquareConvex.setContour(c2inv);
58 
59 	QVector<Vec3d> triCont;
60 	triCont << Vec3d(1,0,0) << Vec3d(0,0,1) << Vec3d(0,1,0);
61 	triangle.setContour(triCont);
62 
63 
64 	QVector<Vec3d> c4(4);
65 	StelUtils::spheToRect(M_PI-0.5, -0.5, c4[3]);
66 	StelUtils::spheToRect(M_PI+0.5, -0.5, c4[2]);
67 	StelUtils::spheToRect(M_PI+0.5, 0.5, c4[1]);
68 	StelUtils::spheToRect(M_PI-0.5, 0.5, c4[0]);
69 	opositeSquare.setContour(c4);
70 
71 	QVector<Vec3d> cpole(4);
72 	StelUtils::spheToRect(0.1,M_PI/2.-0.1, cpole[3]);
73 	StelUtils::spheToRect(0.1+M_PI/2., M_PI/2.-0.1, cpole[2]);
74 	StelUtils::spheToRect(0.1+M_PI, M_PI/2.-0.1, cpole[1]);
75 	StelUtils::spheToRect(0.1+M_PI+M_PI/2.,M_PI/2.-0.1, cpole[0]);
76 	northPoleSquare.setContour(cpole);
77 
78 	StelUtils::spheToRect(0.1,-M_PI/2.+0.1, cpole[0]);
79 	StelUtils::spheToRect(0.1+M_PI/2., -M_PI/2.+0.1, cpole[1]);
80 	StelUtils::spheToRect(0.1+M_PI, -M_PI/2.+0.1, cpole[2]);
81 	StelUtils::spheToRect(0.1+M_PI+M_PI/2.,-M_PI/2.+0.1, cpole[3]);
82 	southPoleSquare.setContour(cpole);
83 }
84 
testSphericalCap()85 void TestStelSphericalGeometry::testSphericalCap()
86 {
87 	Vec3d p0(1.,0.,0.);
88 	Vec3d p1(-1.,0.,0.);
89 	Vec3d p2(1.,1.,1.);
90 	p2.normalize();
91 	Vec3d p3(0.,1.,0.);
92 
93 	SphericalCap h0(p0, 0.);
94 	SphericalCap h1(p0, 0.8);
95 	SphericalCap h2(p0, -0.5);
96 	SphericalCap h3(p1, 0.5);
97 	SphericalCap h4(p2, 0.8);
98 	SphericalCap h5(p2, 1.);
99 	SphericalCap h6(p1, 0.);
100 
101 	QVERIFY2(h0.contains(p0), "SphericalCap contains point failure");
102 	QVERIFY2(h1.contains(p0), "SphericalCap contains point failure");
103 	QVERIFY2(h0.contains(p3), "SphericalCap contains point on the edge failure");
104 	QVERIFY2(h6.contains(p3), "SphericalCap contains point on the edge failure");
105 
106 	QVERIFY(h0.intersects(h1));
107 	QVERIFY(h0.intersects(h2));
108 	QVERIFY(h1.intersects(h2));
109 	QVERIFY(h4.intersects(h1));
110 	QVERIFY(!h0.intersects(h3));
111 	QVERIFY(!h1.intersects(h3));
112 	QVERIFY(h2.intersects(h3));
113 	QVERIFY(h0.intersects(h5));
114 
115 	QVERIFY(h0.intersects(h0));
116 	QVERIFY(h1.intersects(h1));
117 	QVERIFY(h2.intersects(h2));
118 	QVERIFY(h3.intersects(h3));
119 	QVERIFY(h4.intersects(h4));
120 	#ifndef __MINGW32__
121 	// NOTE: It fails on Windows/MinGW GCC
122 	QVERIFY(h5.intersects(h5));
123 	#endif
124 	QVERIFY(h6.intersects(h0));
125 	QVERIFY(h0.intersects(h6));
126 
127 	QVERIFY(h0.contains(h1));
128 	QVERIFY(!h1.contains(h0));
129 	QVERIFY(h2.contains(h0));
130 	QVERIFY(!h0.contains(h2));
131 	QVERIFY(!h6.contains(h0));
132 	QVERIFY(!h0.contains(h6));
133 	QVERIFY(h2.contains(h1));
134 	QVERIFY(!h1.contains(h2));
135 	QVERIFY(!h0.contains(h3));
136 	QVERIFY(!h1.contains(h3));
137 	QVERIFY(h0.contains(h5));
138 	QVERIFY(h2.contains(h5));
139 	QVERIFY(!h5.contains(h0));
140 	QVERIFY(!h5.contains(h1));
141 	QVERIFY(!h5.contains(h2));
142 	QVERIFY(!h5.contains(h3));
143 	QVERIFY(!h5.contains(h4));
144 	QVERIFY(h0.contains(h0));
145 	QVERIFY(h1.contains(h1));
146 	QVERIFY(h2.contains(h2));
147 	QVERIFY(h3.contains(h3));
148 	#ifndef __MINGW32__
149 	// NOTE: It fails on Windows/MinGW GCC
150 	QVERIFY(h4.contains(h4));
151 	QVERIFY(h5.contains(h5));
152 	#endif
153 }
154 
benchmarkSphericalCap()155 void TestStelSphericalGeometry::benchmarkSphericalCap()
156 {
157 	Vec3d p0(1,0,0);
158 	Vec3d p2(1,1,1);
159 	p2.normalize();
160 	SphericalCap h0(p0, 0);
161 	SphericalCap h4(p2, 0.8);
162 	QBENCHMARK {
163 		h0.intersects(h4);
164 	}
165 }
166 
testConsistency()167 void TestStelSphericalGeometry::testConsistency()
168 {
169 	QCOMPARE(bigSquare.getArea(), bigSquareConvex.getArea());
170 	QCOMPARE(smallSquare.getArea(), smallSquareConvex.getArea());
171 	QVERIFY(smallSquareConvex.checkValid());
172 	QVERIFY(bigSquareConvex.checkValid());
173 	QVERIFY(triangle.checkValid());
174 	QVERIFY(triangle.getConvexContour().size()==3);
175 }
176 
testContains()177 void TestStelSphericalGeometry::testContains()
178 {
179 	Vec3d p0(1,0,0);
180 	Vec3d p1(1,1,1);
181 	p1.normalize();
182 
183 	Vec3d v0;
184 	Vec3d v1;
185 	Vec3d v2;
186 	Vec3d v3;
187 
188 	// Triangle polygons
189 	QVERIFY2(triangle.contains(p1), "Triangle contains point failure");
190 	Vec3d vt(-1, -1, -1);
191 	vt.normalize();
192 	QVERIFY2(!triangle.contains(vt), "Triangle not contains point failure");
193 
194 	for (const auto& h : triangle.getBoundingSphericalCaps())
195 	{
196 		QVERIFY(h.contains(p1));
197 	}
198 
199 	// polygons-point intersect
200 	double deg5 = 5.*M_PI/180.;
201 	double deg2 = 2.*M_PI/180.;
202 	StelUtils::spheToRect(-deg5, -deg5, v3);
203 	StelUtils::spheToRect(+deg5, -deg5, v2);
204 	StelUtils::spheToRect(+deg5, +deg5, v1);
205 	StelUtils::spheToRect(-deg5, +deg5, v0);
206 	//qDebug() << v0.toString() << v1.toString() << v2.toString() << v3.toString();
207 	SphericalConvexPolygon square1(v0, v1, v2, v3);
208 	QVERIFY(square1.checkValid());
209 	QVERIFY2(square1.contains(p0), "Square contains point failure");
210 	QVERIFY2(!square1.contains(p1), "Square not contains point failure");
211 
212 	// polygons-polygons intersect
213 	StelUtils::spheToRect(-deg2, -deg2, v3);
214 	StelUtils::spheToRect(+deg2, -deg2, v2);
215 	StelUtils::spheToRect(+deg2, +deg2, v1);
216 	StelUtils::spheToRect(-deg2, +deg2, v0);
217 	SphericalConvexPolygon square2(v0, v1, v2, v3);
218 	QVERIFY(square2.checkValid());
219 	QVERIFY2(square1.contains(square2), "Square contains square failure");
220 	QVERIFY2(!square2.contains(square1), "Square not contains square failure");
221 	QVERIFY2(square1.intersects(square2), "Square intersect square failure");
222 	QVERIFY2(square2.intersects(square1), "Square intersect square failure");
223 
224 	// Check when the polygons are far appart
225 	QVERIFY(!square1.intersects(opositeSquare));
226 	QVERIFY(!square2.intersects(opositeSquare));
227 	QVERIFY(!holySquare.intersects(opositeSquare));
228 	QVERIFY(!bigSquare.intersects(opositeSquare));
229 	QVERIFY(opositeSquare.intersects(opositeSquare));
230 
231 	// Test the tricky case where 2 polygons intersect without having point within each other
232 	StelUtils::spheToRect(-deg5, -deg2, v3);
233 	StelUtils::spheToRect(+deg5, -deg2, v2);
234 	StelUtils::spheToRect(+deg5, +deg2, v1);
235 	StelUtils::spheToRect(-deg5, +deg2, v0);
236 	SphericalConvexPolygon squareHoriz(v0, v1, v2, v3);
237 	QVERIFY(squareHoriz.checkValid());
238 
239 	StelUtils::spheToRect(-deg2, -deg5, v3);
240 	StelUtils::spheToRect(+deg2, -deg5, v2);
241 	StelUtils::spheToRect(+deg2, +deg5, v1);
242 	StelUtils::spheToRect(-deg2, +deg5, v0);
243 	SphericalConvexPolygon squareVerti(v0, v1, v2, v3);
244 	QVERIFY(squareVerti.checkValid());
245 	QVERIFY2(!squareHoriz.contains(squareVerti), "Special intersect contains failure");
246 	QVERIFY2(!squareVerti.contains(squareHoriz), "Special intersect contains failure");
247 	QVERIFY2(squareHoriz.intersects(squareVerti), "Special intersect failure");
248 	QVERIFY2(squareVerti.intersects(squareHoriz), "Special intersect failure");
249 }
250 
testPlaneIntersect2()251 void TestStelSphericalGeometry::testPlaneIntersect2()
252 {
253 	Vec3d p1,p2;
254 	Vec3d vx(1,0,0);
255 	Vec3d vz(0,0,1);
256 	SphericalCap hx(vx, 0);
257 	SphericalCap hz(vz, 0);
258 	QVERIFY2(SphericalCap::intersectionPoints(hx, hz, p1, p2)==true, "Plane intersect failed");
259 	QVERIFY(p1==Vec3d(0,-1,0));
260 	QVERIFY(p2==Vec3d(0,1,0));
261 	QVERIFY2(SphericalCap::intersectionPoints(hx, hx, p1, p2)==false, "Plane non-intersecting failure");
262 
263 	hx.d = std::sqrt(2.)/2.;
264 	QVERIFY2(SphericalCap::intersectionPoints(hx, hz, p1, p2)==true, "Plane/convex intersect failed");
265 	Vec3d res(p1-Vec3d(hx.d,-hx.d,0));
266 	QVERIFY2(res.length()<0.0000001, QString("p1 wrong: %1").arg(p1.toString()).toUtf8());
267 	res = p2-Vec3d(hx.d,hx.d,0);
268 	QVERIFY2(res.length()<0.0000001, QString("p2 wrong: %1").arg(p2.toString()).toUtf8());
269 }
270 
testGreatCircleIntersection()271 void TestStelSphericalGeometry::testGreatCircleIntersection()
272 {
273 	Vec3d v0,v1,v2,v3;
274 	double deg5 = 5.*M_PI/180.;
275 	StelUtils::spheToRect(-deg5, -deg5, v3);
276 	StelUtils::spheToRect(+deg5, -deg5, v2);
277 	StelUtils::spheToRect(+deg5, +deg5, v1);
278 	StelUtils::spheToRect(-deg5, +deg5, v0);
279 
280 	bool ok;
281 	Vec3d v(0.0);
282 	QBENCHMARK {
283 		v = greatCircleIntersection(v3, v1, v0, v2, ok);
284 	}
285 	QVERIFY(v.angle(Vec3d(1.,0.,0.))<0.00001);
286 }
287 
288 
benchmarkGetIntersection()289 void TestStelSphericalGeometry::benchmarkGetIntersection()
290 {
291 	SphericalRegionP bug1 = SphericalRegionP::loadFromJson("{\"worldCoords\": [[[123.023842, -49.177087], [122.167613, -49.177087], [122.167613, -48.631248], [123.023842, -48.631248]]]}");
292 	SphericalRegionP bug2 = SphericalRegionP::loadFromJson("{\"worldCoords\": [[[123.028902, -49.677124], [122.163995, -49.677124], [122.163995, -49.131382], [123.028902, -49.131382]]]}");
293 	QVERIFY(bug1->intersects(bug2));
294 	SphericalRegionP res;
295 	QBENCHMARK {
296 		res = bug1->getIntersection(bug2);
297 	}
298 }
299 
testEnlarge()300 void TestStelSphericalGeometry::testEnlarge()
301 {
302 	Vec3d vx(1,0,0);
303 	SphericalRegionP reg(new SphericalCap(vx, 0.9));
304 	for (double margin=0.00000001;margin<15.;margin+=0.1)
305 	{
306 		QVERIFY(reg->getEnlarged(margin)->contains(reg));
307 	}
308 }
309 
testSphericalPolygon()310 void TestStelSphericalGeometry::testSphericalPolygon()
311 {
312 	SphericalRegionP holySquare2 = bigSquare.getSubtraction(smallSquare);
313 
314 	QCOMPARE(holySquare2->getArea(), holySquare.getArea());
315 
316 	//Booleans methods
317 	QCOMPARE(holySquare.getArea(), bigSquare.getArea()-smallSquare.getArea());
318 	QCOMPARE(bigSquare.getUnion(holySquare)->getArea(), bigSquare.getArea());
319 	QCOMPARE(bigSquare.getSubtraction(smallSquare)->getArea(), bigSquare.getArea()-smallSquare.getArea());
320 	QCOMPARE(bigSquare.getIntersection(smallSquare)->getArea(), smallSquare.getArea());
321 
322 	// Point contain methods
323 	Vec3d v0, v1;
324 	StelUtils::spheToRect(0.00000, 0.00000, v0);
325 	StelUtils::spheToRect(0.3, 0.3, v1);
326 	QVERIFY(smallSquareConvex.contains(v0));
327 	QVERIFY(smallSquare.contains(v0));
328 	QVERIFY(bigSquareConvex.contains(v0));
329 	QVERIFY(bigSquare.contains(v0));
330 	//FIXME: sometimes give errors on 32-bit systems when unit tests call by CLI. WTF?!?
331 	//QVERIFY(!holySquare.contains(v0));
332 
333 	QVERIFY(!smallSquare.contains(v1));
334 	QVERIFY(bigSquare.contains(v1));
335 	QVERIFY(holySquare.contains(v1));
336 
337 	QVERIFY(holySquare.intersects(bigSquare));
338 	QVERIFY(bigSquare.intersects(smallSquare));
339 	QVERIFY(!holySquare.intersects(smallSquare));
340 
341 	SphericalCap cap(Vec3d(1,0,0), 0.99);
342 	QVERIFY(bigSquareConvex.intersects(cap));
343 
344 	// A case which caused a problem
345 	SphericalRegionP bug1 = SphericalRegionP::loadFromJson("{\"worldCoords\": [[[123.023842, -49.177087], [122.167613, -49.177087], [122.167613, -48.631248], [123.023842, -48.631248]]]}");
346 	SphericalRegionP bug2 = SphericalRegionP::loadFromJson("{\"worldCoords\": [[[123.028902, -49.677124], [122.163995, -49.677124], [122.163995, -49.131382], [123.028902, -49.131382]]]}");
347 	QVERIFY(bug1->intersects(bug2));
348 
349 	// Another one
350 	bug1 = SphericalRegionP::loadFromJson("{\"worldCoords\": [[[52.99403, -27.683551], [53.047302, -27.683551], [53.047302, -27.729923], [52.99403, -27.729923]]]}");
351 	bug2 = SphericalRegionP::loadFromJson("{\"worldCoords\": [[[52.993701, -27.683092], [53.047302, -27.683092], [53.047302, -27.729839], [52.993701, -27.729839]]]}");
352 	SphericalRegionP bugIntersect = bug1->getIntersection(bug2);
353 }
354 
testLoading()355 void TestStelSphericalGeometry::testLoading()
356 {
357 	QByteArray ar = "{\"worldCoords\": [[[-0.5,0.5],[0.5,0.5],[0.5,-0.5],[-0.5,-0.5]], [[-0.2,-0.2],[0.2,-0.2],[0.2,0.2],[-0.2,0.2]]]}";
358 	//QByteArray arTex = "{\"worldCoords\": [[[-0.5,0.5],[0.5,0.5],[0.5,-0.5],[-0.5,-0.5]]], \"textureCoords\": [[[-0.5,0.5],[0.5,0.5],[0.5,-0.5],[-0.5,-0.5]]]}";
359 	SphericalRegionP reg;
360 	//SphericalRegionP regTex;
361 	try
362 	{
363 		reg = SphericalRegionP::loadFromJson(ar);
364 //		regTex = SphericalRegionP::loadFromJson(arTex);
365 	}
366 	catch (std::runtime_error& e)
367 	{
368 		QString msg("Exception while loading: ");
369 		msg+=e.what();
370 		QFAIL(qPrintable(msg));
371 	}
372 
373 	QVERIFY(reg->getType()==SphericalRegion::Polygon);
374 	qDebug() << reg->getArea()*M_180_PI*M_180_PI;
375 
376 	// FIXME: WTF?!?
377 	//StelVertexArray vertexAr = reg->getOutlineVertexArray();
378 	//QVERIFY(vertexAr.primitiveType==StelVertexArray::Lines && vertexAr.vertex.size()%2==0);
379 }
380 
benchmarkContains()381 void TestStelSphericalGeometry::benchmarkContains()
382 {
383 	Vec3d v0, v1;
384 	StelUtils::spheToRect(0., 0., v0);
385 	StelUtils::spheToRect(0.3, 0.3, v1);
386 
387 	QBENCHMARK {
388 		holySquare.contains(v1);
389 		holySquare.contains(v0);
390 	}
391 }
392 
benchmarkCheckValid()393 void TestStelSphericalGeometry::benchmarkCheckValid()
394 {
395 	Vec3d v0, v1, v2;
396 	StelUtils::spheToRect(-0.5, -0.5, v0);
397 	StelUtils::spheToRect(0.5, -0.5, v1);
398 	StelUtils::spheToRect(0.5, 0.5, v2);
399 	SphericalConvexPolygon cvx(v0, v1, v2);
400 	QBENCHMARK {
401 		cvx.checkValid();
402 	}
403 }
404 
testOctahedronPolygon()405 void TestStelSphericalGeometry::testOctahedronPolygon()
406 {
407 	QVERIFY(OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(0.8,0.1,0)));
408 	QVERIFY(OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(1,0.1,0)));
409 	QVERIFY(OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(0.5,0.,0)));
410 
411 	// Check points outside triangle
412 	QVERIFY(!OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(0.,0.1,0)));
413 	QVERIFY(!OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(-1.,-1.,0)));
414 
415 	// Check that the corners are included into the triangle
416 	QVERIFY(OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(0,0,0)));
417 	QVERIFY(OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(1,0,0)));
418 	QVERIFY(OctahedronPolygon::triangleContains2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0), Vec3d(1,1,0)));
419 
420 	QVERIFY(OctahedronPolygon::isTriangleConvexPositive2D(Vec3d(0,0,0), Vec3d(1,0,0), Vec3d(1,1,0)));
421 
422 	SubContour contour(smallSquareConvex.getConvexContour());
423 	OctahedronPolygon splittedSub(contour);
424 	QCOMPARE(splittedSub.getArea(), smallSquareConvex.getArea());
425 
426 	QVector<Vec3d> va = northPoleSquare.getOutlineVertexArray().vertex;
427 	QCOMPARE(va.size(),16);
428 	va = southPoleSquare.getOutlineVertexArray().vertex;
429 	QCOMPARE(va.size(),16);
430 
431 	// Copy
432 	OctahedronPolygon splittedSubCopy;
433 	splittedSubCopy = splittedSub;
434 
435 	QCOMPARE(splittedSub.getArea(), splittedSubCopy.getArea());
436 	double oldArea = splittedSubCopy.getArea();
437 	splittedSub = OctahedronPolygon();
438 	QCOMPARE(splittedSub.getArea(), 0.);
439 	QCOMPARE(splittedSubCopy.getArea(), oldArea);
440 	splittedSubCopy.inPlaceIntersection(splittedSub);
441 	QCOMPARE(splittedSubCopy.getArea(), 0.);
442 
443 	QCOMPARE(southPoleSquare.getArea(), northPoleSquare.getArea());
444 	QCOMPARE(southPoleSquare.getIntersection(northPoleSquare)->getArea(), 0.);
445 	QCOMPARE(southPoleSquare.getUnion(northPoleSquare)->getArea(), 2.*southPoleSquare.getArea());
446 	QCOMPARE(southPoleSquare.getSubtraction(northPoleSquare)->getArea(), southPoleSquare.getArea());
447 
448 	QCOMPARE(northPoleSquare.getIntersection(northPoleSquare)->getArea(), northPoleSquare.getArea());
449 	QCOMPARE(northPoleSquare.getUnion(northPoleSquare)->getArea(), northPoleSquare.getArea());
450 	QCOMPARE(northPoleSquare.getSubtraction(northPoleSquare)->getArea(), 0.);
451 
452 	// Test binary IO
453 	QByteArray ar;
454 	QBuffer buf(&ar);
455 	buf.open(QIODevice::WriteOnly);
456 	QDataStream out(&buf);
457 	out << northPoleSquare.getOctahedronPolygon();
458 	buf.close();
459 	QVERIFY(!ar.isEmpty());
460 
461 	// Re-read it
462 	OctahedronPolygon northPoleSquareRead;
463 	buf.open(QIODevice::ReadOnly);
464 	QDataStream in(&buf);
465 	in >> northPoleSquareRead;
466 	buf.close();
467 	QVERIFY(!northPoleSquareRead.isEmpty());
468 	QCOMPARE(northPoleSquareRead.getArea(), northPoleSquare.getArea());
469 	QVERIFY(northPoleSquareRead.intersects(northPoleSquare.getOctahedronPolygon()));
470 
471 	// Spherical cap with aperture > 90 deg
472 	SphericalCap cap1(Vec3d(0,0,1), std::cos(95.*M_PI/180.));
473 	qDebug() << "---------------------";
474 	OctahedronPolygon northCapPoly = cap1.getOctahedronPolygon();
475 	qDebug() << "---------------------";
476 	qDebug() << northCapPoly.getArea() << OctahedronPolygon::getAllSkyOctahedronPolygon().getArea()/2;
477 	QVERIFY(northCapPoly.getArea()>OctahedronPolygon::getAllSkyOctahedronPolygon().getArea()/2);
478 }
479 
480 
testSerialize()481 void TestStelSphericalGeometry::testSerialize()
482 {
483 	// Store a SphericalPolygon as QVariant
484 	SphericalRegionP holyReg(new SphericalPolygon(holySquare));
485 	QVariant vHolyReg = QVariant::fromValue(holyReg);
486 	QVERIFY(QString(vHolyReg.typeName())=="SphericalRegionP");
487 	QVERIFY(vHolyReg.canConvert<SphericalRegionP>());
488 	// and reconvert it
489 	SphericalRegionP reg2 = vHolyReg.value<SphericalRegionP>();
490 	QCOMPARE(holyReg->getArea(), reg2->getArea());
491 	QVERIFY(holyReg->getType()==reg2->getType());
492 
493 	// Store a SphericalCap as QVariant
494 	SphericalRegionP capReg(new SphericalCap(Vec3d(1,0,0), 0.12));
495 	QVariant vCapReg = QVariant::fromValue(capReg);
496 	QVERIFY(QString(vCapReg.typeName())=="SphericalRegionP");
497 	QVERIFY(vCapReg.canConvert<SphericalRegionP>());
498 	// and reconvert it
499 	reg2 = vCapReg.value<SphericalRegionP>();
500 	QCOMPARE(capReg->getArea(), reg2->getArea());
501 	QVERIFY(capReg->getType()==reg2->getType());
502 
503 	// Test serialize the QVariants as binary
504 	QByteArray ar;
505 	QBuffer buf(&ar);
506 	buf.open(QIODevice::WriteOnly);
507 	QDataStream out(&buf);
508 	out << vHolyReg << vCapReg;
509 	buf.close();
510 	QVERIFY(!ar.isEmpty());
511 
512 	// Re-read it
513 	QVariant readVCapReg, readVHolyReg;
514 	buf.open(QIODevice::ReadOnly);
515 	QDataStream in(&buf);
516 	in >> readVHolyReg >> readVCapReg;
517 	buf.close();
518 	reg2 = readVHolyReg.value<SphericalRegionP>();
519 	QCOMPARE(holyReg->getArea(), reg2->getArea());
520 	QVERIFY(holyReg->getType()==reg2->getType());
521 	reg2 = readVCapReg.value<SphericalRegionP>();
522 	QCOMPARE(capReg->getArea(), reg2->getArea());
523 	QVERIFY(capReg->getType()==reg2->getType());
524 }
525 
benchmarkCreatePolygon()526 void TestStelSphericalGeometry::benchmarkCreatePolygon()
527 {
528 	QVector<QVector<Vec3d> > contours;
529 	QVector<Vec3d> c1(4);
530 	StelUtils::spheToRect(-0.5, -0.5, c1[3]);
531 	StelUtils::spheToRect(0.5, -0.5, c1[2]);
532 	StelUtils::spheToRect(0.5, 0.5, c1[1]);
533 	StelUtils::spheToRect(-0.5, 0.5, c1[0]);
534 	contours.append(c1);
535 	QVector<Vec3d> c2(4);
536 	StelUtils::spheToRect(-0.2, 0.2, c2[3]);
537 	StelUtils::spheToRect(0.2, 0.2, c2[2]);
538 	StelUtils::spheToRect(0.2, -0.2, c2[1]);
539 	StelUtils::spheToRect(-0.2, -0.2, c2[0]);
540 	contours.append(c2);
541 	QBENCHMARK
542 	{
543 		SphericalPolygon holySquare(contours);
544 	}
545 }
546