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 #ifndef STELSPHEREGEOMETRY_HPP
21 #define STELSPHEREGEOMETRY_HPP
22
23 #include "OctahedronPolygon.hpp"
24 #include "StelVertexArray.hpp"
25 #include "VecMath.hpp"
26
27 #include <QVector>
28 #include <QVariant>
29 #include <QDebug>
30 #include <QSharedPointer>
31 #include <QVarLengthArray>
32 #include <QDataStream>
33
34 #include <cstdio>
35
36 class SphericalRegion;
37 class SphericalPolygon;
38 class SphericalConvexPolygon;
39 class SphericalCap;
40 class SphericalPoint;
41 class AllSkySphericalRegion;
42 class EmptySphericalRegion;
43
44 //! @file StelSphereGeometry.hpp
45 //! Define all SphericalGeometry primitives as well as the SphericalRegionP type.
46
47 //! @class SphericalRegionP
48 //! A shared pointer on a SphericalRegion.
49 class SphericalRegionP : public QSharedPointer<SphericalRegion>
50 {
51 public:
52 // Override the constructors of QSharedPointer
SphericalRegionP()53 SphericalRegionP() {;}
SphericalRegionP(SphericalRegion * ptr)54 SphericalRegionP(SphericalRegion* ptr) : QSharedPointer<SphericalRegion>(ptr) {;}
SphericalRegionP(SphericalRegion * ptr,Deleter deleter)55 template <class Deleter> SphericalRegionP(SphericalRegion* ptr, Deleter deleter) : QSharedPointer<SphericalRegion>(ptr, deleter) {;}
SphericalRegionP(const SphericalRegionP & other)56 SphericalRegionP(const SphericalRegionP& other) : QSharedPointer<SphericalRegion>(other) {;}
SphericalRegionP(const QWeakPointer<SphericalRegion> & other)57 SphericalRegionP(const QWeakPointer<SphericalRegion>& other) : QSharedPointer<SphericalRegion>(other) {;}
operator =(const SphericalRegionP & other)58 inline SphericalRegionP& operator=(const SphericalRegionP &other){QSharedPointer<SphericalRegion>::operator=(other); return *this;}
59
60 //! Create a SphericalRegion from the given input JSON stream.
61 //! The type of the region is automatically recognized from the input format.
62 //! The currently recognized format are:
63 //! <ul>
64 //! <li>Contour list:
65 //! @code[[contour1], [contour2],[...]]@endcode
66 //! This format consists of a list of contours. Contours defined in counterclockwise direction (CW) are
67 //! added to the final region while CCW contours are subtracted (they can be used to form complex polygons even with holes).
68 //! Each contour can have different format:
69 //! <ul>
70 //! <li>
71 //! @code[[ra,dec], [ra,dec], [ra,dec], [ra,dec]]@endcode
72 //! A list of points connected by great circles with the last point connected to the first one.
73 //! Each point is defined by its ra,dec coordinates in degrees.</li>
74 //! <li>
75 //! @code["CAP", [raCenter,decCenter], ap]@endcode
76 //! A spherical cap centered on raCenter/decCenter with aperture radius ap in degrees. For example:
77 //! @code["CAP", [0.,-90.], 90]@endcode
78 //! define the region covering the entire southern hemisphere.</li>
79 //! <li>
80 //! @code["PATH", [startRa,startDec], [[prim1],[prim2],[prim3],...]]@endcode
81 //! A path is a contour starting a startRa/startDec and defined by a list of primitives. Each primitive can be either
82 //! a great circle or a small circle. Great circles are defined by the point to link to: ["greatCircleTo", [ra,dec]]. Small
83 //! circles are defined by a rotation axis and a rotation angle: ["smallCircle",[0,90],-88]. A full example is:
84 //! @code["PATH",[330,-25],[["smallCircle",[0,90],82.5],["greatCircleTo",[52.5,-35]],["smallCircle",[0,90],-82.5]]]@endcode
85 //! This defines a box of 82.5x10 degrees following latitude and longitude lines.</li>
86 //! </ul>
87 //! <li>Polygon vertex list with associated texture coordinates:
88 //! @code{
89 //! "worldCoords": [[[ra,dec],[ra,dec],[ra,dec],[ra,dec]], [[ra,dec],[ra,dec],[ra,dec]],[...]],
90 //! "textureCoords": [[[u,v],[u,v],[u,v],[u,v]], [[u,v],[u,v],[u,v]], [...]]
91 //! }@endcode
92 //! The format is used to describe textured polygons. The worldCoords part is similar to the one described above.
93 //! The textureCoords part is the addition of a list of texture coordinates in the u,v texture space (between 0 and 1).
94 //! There must be one texture coordinate for each vertex.</li>
95 //! </ul>
96 //! @param in an open QIODevice ready for read.
97 //! @throws std::runtime_error when there was an error while parsing the file.
98 static SphericalRegionP loadFromJson(QIODevice* in);
99
100 //! Create a SphericalRegion from the given QByteArray containing the JSON data.
101 //! @see loadFromJson(QIODevice* in) for format info.
102 static SphericalRegionP loadFromJson(const QByteArray& a);
103
104 //! Create a SphericalRegion from the given QVariantMap with a format matching the JSON file parsed in loadFromJson().
105 //! @param map a valid QVariantMap which can be created e.g. from parsing a JSON file with the StelJsonParser class.
106 static SphericalRegionP loadFromQVariant(const QVariantMap& map);
107 // It can only be a pure shape definition, without texture coords
108 static SphericalRegionP loadFromQVariant(const QVariantList& list);
109
110 //! Method registered to JSON serializer.
111 static void serializeToJson(const QVariant& jsonObject, QIODevice* output, int indentLevel=0);
112
113 //! The meta type ID associated to a SphericalRegionP.
114 static int metaTypeId;
115
116 private:
117 //! Initialize stuff to allow SphericalRegionP to be used with Qt meta type system.
118 static int initialize();
119 };
120
121 // Allow to use SphericalRegionP with the Qt MetaType system.
122 Q_DECLARE_METATYPE(SphericalRegionP)
123
124 //! Serialize the passed SphericalRegionP into a binary blob.
125 QDataStream& operator<<(QDataStream& out, const SphericalRegionP& region);
126 //! Load the SphericalRegionP from a binary blob.
127 QDataStream& operator>>(QDataStream& in, SphericalRegionP& region);
128
129 //! @class SphericalRegion
130 //! Abstract class defining a region of the sphere. It provides default implementation for the general non-convex polygon
131 //! which can extend on more than 180 deg based on the OctahedronPolygon class.
132 //! Subclasses provides special faster implementations of many methods.
133 class SphericalRegion
134 {
135 public:
136 //! @enum SphericalRegionType define types for all supported regions.
137 enum SphericalRegionType
138 {
139 Point = 0,
140 Cap = 1,
141 AllSky = 2,
142 Polygon = 3,
143 ConvexPolygon = 4,
144 Empty = 5,
145 Invalid = 6
146 };
147
~SphericalRegion()148 virtual ~SphericalRegion() {;}
149
150 virtual SphericalRegionType getType() const = 0;
151
152 //! Return the octahedron contour representation of the polygon.
153 //! It can be used for safe computation of intersection/union in the general case.
154 virtual OctahedronPolygon getOctahedronPolygon() const =0;
155
156 //! Return the area of the region in steradians.
getArea() const157 virtual double getArea() const {return getOctahedronPolygon().getArea();}
158
159 //! Return true if the region is empty.
isEmpty() const160 virtual bool isEmpty() const {return getOctahedronPolygon().isEmpty();}
161
162 //! Return a point located inside the region.
getPointInside() const163 virtual Vec3d getPointInside() const {return getOctahedronPolygon().getPointInside();}
164
165 //! Return the list of SphericalCap bounding the ConvexPolygon.
166 virtual QVector<SphericalCap> getBoundingSphericalCaps() const;
167
168 //! Return a bounding SphericalCap. This method is heavily used and therefore needs to be very fast.
169 //! The returned SphericalCap doesn't have to be the smallest one, but smaller is better.
170 virtual SphericalCap getBoundingCap() const;
171
172 //! Return an enlarged version of this SphericalRegion so that any point distant of more
173 //! than the given margin now lays within the region.
174 //! The returned region can be larger than the smallest enlarging region, therefore returning
175 //! false positive on subsequent intersection tests.
176 //! The default implementation always return an enlarged bounding SphericalCap.
177 //! @param margin the minimum enlargement margin in radian.
178 virtual SphericalRegionP getEnlarged(double margin) const;
179
180 //! Return an OpenGL compatible array to be displayed using vertex arrays.
getFillVertexArray() const181 virtual StelVertexArray getFillVertexArray() const {return getOctahedronPolygon().getFillVertexArray();}
182 //! Return an OpenGL compatible array to be displayed using vertex arrays.
183 //! @note Presumably these general polygons of the base class don't describe geometry that may undergo aberration, so the observerVelocity must be zero.
184 //! Implementation in derived classes should show aberration correction.
getFillVertexArray(const Vec3d & observerVelocityForAberration)185 virtual StelVertexArray getFillVertexArray(const Vec3d &observerVelocityForAberration) {
186 Q_ASSERT(observerVelocityForAberration==Vec3d(0.));
187 return getOctahedronPolygon().getFillVertexArray();}
188
189 //! Get the outline of the contours defining the SphericalPolygon.
190 //! @return a list of vertex which taken 2 by 2 define the contours of the polygon.
getOutlineVertexArray() const191 virtual StelVertexArray getOutlineVertexArray() const {return getOctahedronPolygon().getOutlineVertexArray();}
192 //! Get the outline of the contours defining the SphericalPolygon.
193 //! @note Presumably these general polygons of the base class don't describe geometry that may undergo aberration, so the observerVelocity must be zero.
194 //! Implementation in derived classes should show aberration correction.
getOutlineVertexArray(Vec3d observerVelocityForAberration)195 virtual StelVertexArray getOutlineVertexArray(Vec3d observerVelocityForAberration) {
196 Q_ASSERT(observerVelocityForAberration==Vec3d(0.));
197 return getOctahedronPolygon().getOutlineVertexArray();}
198
199 //! Get the contours defining the SphericalPolygon when combined using a positive winding rule.
200 //! The default implementation returns a list of tessellated triangles derived from the OctahedronPolygon.
201 virtual QVector<QVector<Vec3d > > getSimplifiedContours() const;
202
203 //! Serialize the region into a QVariant list matching the JSON format.
204 virtual QVariantList toQVariant() const = 0;
205
206 //! Serialize the region. This method must allow as fast as possible serialization and work with deserialize().
207 virtual void serialize(QDataStream& out) const = 0;
208
209 //! Output a JSON string representing the polygon.
210 //! This method is convenient for debugging.
211 QByteArray toJSON() const;
212
213 //! Returns whether a SphericalRegion is contained into this region.
214 //! A default potentially very slow implementation is provided for each cases.
215 bool contains(const SphericalRegion* r) const;
contains(const SphericalRegionP r) const216 bool contains(const SphericalRegionP r) const {return contains(r.data());}
contains(const Vec3d & p) const217 virtual bool contains(const Vec3d& p) const {return getOctahedronPolygon().contains(p);}
218 virtual bool contains(const SphericalPolygon& r) const;
219 virtual bool contains(const SphericalConvexPolygon& r) const;
220 virtual bool contains(const SphericalCap& r) const;
221 virtual bool contains(const SphericalPoint& r) const;
222 virtual bool contains(const AllSkySphericalRegion& r) const;
contains(const EmptySphericalRegion &) const223 bool contains(const EmptySphericalRegion&) const {return false;}
224
225 //! Returns whether a SphericalRegion intersects with this region.
226 //! A default potentially very slow implementation is provided for each cases.
227 bool intersects(const SphericalRegion* r) const;
intersects(const SphericalRegionP r) const228 bool intersects(const SphericalRegionP r) const {return intersects(r.data());}
intersects(const Vec3d & p) const229 bool intersects(const Vec3d& p) const {return contains(p);}
230 virtual bool intersects(const SphericalPolygon& r) const;
231 virtual bool intersects(const SphericalConvexPolygon& r) const;
232 virtual bool intersects(const SphericalCap& r) const;
233 virtual bool intersects(const SphericalPoint& r) const;
234 virtual bool intersects(const AllSkySphericalRegion& r) const;
intersects(const EmptySphericalRegion &) const235 bool intersects(const EmptySphericalRegion&) const {return false;}
236
237 //! Return a new SphericalRegion consisting of the intersection of this and the given region.
238 //! A default potentially very slow implementation is provided for each cases.
239 SphericalRegionP getIntersection(const SphericalRegion* r) const;
getIntersection(const SphericalRegionP r) const240 SphericalRegionP getIntersection(const SphericalRegionP r) const {return getIntersection(r.data());}
241 virtual SphericalRegionP getIntersection(const SphericalPolygon& r) const;
242 virtual SphericalRegionP getIntersection(const SphericalConvexPolygon& r) const;
243 virtual SphericalRegionP getIntersection(const SphericalCap& r) const;
244 virtual SphericalRegionP getIntersection(const SphericalPoint& r) const;
245 virtual SphericalRegionP getIntersection(const AllSkySphericalRegion& r) const;
246 SphericalRegionP getIntersection(const EmptySphericalRegion& r) const;
247
248 //! Return a new SphericalRegion consisting of the union of this and the given region.
249 //! A default potentially very slow implementation is provided for each cases.
250 SphericalRegionP getUnion(const SphericalRegion* r) const;
getUnion(const SphericalRegionP r) const251 SphericalRegionP getUnion(const SphericalRegionP r) const {return getUnion(r.data());}
252 virtual SphericalRegionP getUnion(const SphericalPolygon& r) const;
253 virtual SphericalRegionP getUnion(const SphericalConvexPolygon& r) const;
254 virtual SphericalRegionP getUnion(const SphericalCap& r) const;
255 virtual SphericalRegionP getUnion(const SphericalPoint& r) const;
256 SphericalRegionP getUnion(const AllSkySphericalRegion& r) const;
257 virtual SphericalRegionP getUnion(const EmptySphericalRegion& r) const;
258
259 //! Return a new SphericalRegion consisting of the subtraction of the given region from this.
260 //! A default potentially very slow implementation is provided for each cases.
261 SphericalRegionP getSubtraction(const SphericalRegion* r) const;
getSubtraction(const SphericalRegionP r) const262 SphericalRegionP getSubtraction(const SphericalRegionP r) const {return getSubtraction(r.data());}
263 virtual SphericalRegionP getSubtraction(const SphericalPolygon& r) const;
264 virtual SphericalRegionP getSubtraction(const SphericalConvexPolygon& r) const;
265 virtual SphericalRegionP getSubtraction(const SphericalCap& r) const;
266 virtual SphericalRegionP getSubtraction(const SphericalPoint& r) const;
267 SphericalRegionP getSubtraction(const AllSkySphericalRegion& r) const;
268 virtual SphericalRegionP getSubtraction(const EmptySphericalRegion& r) const;
269
270 private:
271 bool containsDefault(const SphericalRegion* r) const;
272 bool intersectsDefault(const SphericalRegion* r) const;
273 SphericalRegionP getIntersectionDefault(const SphericalRegion* r) const;
274 SphericalRegionP getUnionDefault(const SphericalRegion* r) const;
275 SphericalRegionP getSubtractionDefault(const SphericalRegion* r) const;
276 };
277
278
279 //! @class SphericalCap
280 //! A SphericalCap is defined by a direction and an aperture.
281 //! It forms a cone from the center of the Coordinate frame with a radius d.
282 //! It is a disc on the sphere, a region above a circle on the unit sphere.
283 class SphericalCap : public SphericalRegion
284 {
285 using SphericalRegion::contains;
286 public:
287 //! Construct a SphericalCap with a 90 deg aperture and an undefined direction.
SphericalCap()288 SphericalCap() : d(0) {;}
289
290 //! Construct a SphericalCap from its direction and assumes a 90 deg aperture.
SphericalCap(double x,double y,double z)291 SphericalCap(double x, double y, double z) : n(x,y,z), d(0) {;}
292
293 //! Construct a SphericalCap from its direction and aperture.
294 //! @param an a unit vector indicating the direction.
295 //! @param ar cosinus of the aperture.
SphericalCap(const Vec3d & an,double ar)296 SphericalCap(const Vec3d& an, double ar) : n(an), d(ar) {//n.normalize();
297 Q_ASSERT(d==0 || qFuzzyCompare(n.lengthSquared(),1.));}
298 // FIXME: GZ reports 2013-03-02: apparently the Q_ASSERT is here because n should be normalized at this point, but
299 // for efficiency n.normalize() should not be called at this point.
300 // However, when zooming in a bit in Hammer-Aitoff and Mercator projections, this Assertion fires.
301 // Atmosphere must be active
302 // It may have to do with DSO texture rendering.
303 // found at r5863.
304 // n.normalize() prevents this for now, but may cost performance.
305 // AARGH - activating n.normalize() inhibits mouse-identification/selection of stars!
306 // May be compiler dependent (seen on Win/MinGW), AW cannot confirm it on Linux.
307
308 //! Copy constructor.
SphericalCap(const SphericalCap & other)309 SphericalCap(const SphericalCap& other) : SphericalRegion(), n(other.n), d(other.d) {;}
operator =(const SphericalCap & other)310 inline SphericalCap& operator=(const SphericalCap &other){n=other.n; d=other.d; return *this;}
311
getType() const312 virtual SphericalRegionType getType() const Q_DECL_OVERRIDE {return SphericalRegion::Cap;}
313 virtual OctahedronPolygon getOctahedronPolygon() const Q_DECL_OVERRIDE;
314
315 //! Get the area of the intersection of the halfspace on the sphere in steradian.
getArea() const316 virtual double getArea() const Q_DECL_OVERRIDE {return 2.*M_PI*(1.-d);}
317
318 //! Return true if the region is empty.
isEmpty() const319 virtual bool isEmpty() const Q_DECL_OVERRIDE {return d>=1.;}
320
321 //! Return a point located inside the SphericalCap.
getPointInside() const322 virtual Vec3d getPointInside() const Q_DECL_OVERRIDE {return n;}
323
324 //! Return itself.
getBoundingCap() const325 virtual SphericalCap getBoundingCap() const Q_DECL_OVERRIDE {return *this;}
326
327 // Contain and intersect
contains(const Vec3d & v) const328 virtual bool contains(const Vec3d &v) const Q_DECL_OVERRIDE {Q_ASSERT(d==0 || std::fabs(v.lengthSquared()-1.)<0.0000002);return (v*n>=d);}
contains(const Vec3f & v) const329 virtual bool contains(const Vec3f &v) const {Q_ASSERT(d==0 || std::fabs(v.lengthSquared()-1.f)<0.000002f);return (v.toVec3d()*n>=d);}
330 virtual bool contains(const SphericalConvexPolygon& r) const Q_DECL_OVERRIDE;
contains(const SphericalCap & h) const331 virtual bool contains(const SphericalCap& h) const Q_DECL_OVERRIDE
332 {
333 const double a = n*h.n-d*h.d;
334 return d<=h.d && ( a>=1. || (a>=0. && a*a >= (1.-d*d)*(1.-h.d*h.d)));
335 }
contains(const AllSkySphericalRegion &) const336 virtual bool contains(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return d<=-1;}
337 virtual bool intersects(const SphericalPolygon& r) const Q_DECL_OVERRIDE;
338 virtual bool intersects(const SphericalConvexPolygon& r) const Q_DECL_OVERRIDE;
339 //! Returns whether a SphericalCap intersects with this one.
340 //! I managed to make it without sqrt or acos, so it is very fast!
341 //! @see http://f4bien.blogspot.com/2009/05/spherical-geometry-optimisations.html for detailed explanations.
intersects(const SphericalCap & h) const342 virtual bool intersects(const SphericalCap& h) const Q_DECL_OVERRIDE
343 {
344 const double a = d*h.d - n*h.n;
345 return d+h.d<=0. || a<=0. || (a<=1. && a*a <= (1.-d*d)*(1.-h.d*h.d));
346 }
intersects(const AllSkySphericalRegion &) const347 virtual bool intersects(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return d<=1.;}
348
349 //! Serialize the region into a QVariant map matching the JSON format.
350 //! The format is ["CAP", [ra, dec], radius], with ra dec in degree in ICRS frame
351 //! and radius in degree (between 0 and 180 deg)
352 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
353
serialize(QDataStream & out) const354 virtual void serialize(QDataStream& out) const Q_DECL_OVERRIDE {out << n << d;}
355
356 ////////////////////////////////////////////////////////////////////
357 // Methods specific to SphericalCap
358
359 //! Return the radiusof the cap in radian
getRadius() const360 double getRadius() const {return std::acos(d);}
361
362 //! Returns whether a HalfSpace (like a SphericalCap with d=0) intersects with this SphericalCap.
363 //! @param hn0 the x direction of the halfspace.
364 //! @param hn1 the y direction of the halfspace.
365 //! @param hn2 the z direction of the halfspace.
intersectsHalfSpace(double hn0,double hn1,double hn2) const366 inline bool intersectsHalfSpace(double hn0, double hn1, double hn2) const
367 {
368 const double a = n[0]*hn0+n[1]*hn1+n[2]*hn2;
369 return d<=0. || a<=0. || (a<=1. && a*a <= (1.-d*d));
370 }
371
372 //! Clip the passed great circle connecting points v1 and v2.
373 //! @return true if the great circle intersects with the cap, false otherwise.
374 bool clipGreatCircle(Vec3d& v1, Vec3d& v2) const;
375
376 //! Comparison operator.
operator ==(const SphericalCap & other) const377 bool operator==(const SphericalCap& other) const {return (n==other.n && d==other.d);}
378
379 //! Return the list of closed contours defining the polygon boundaries.
380 QVector<Vec3d> getClosedOutlineContour() const;
381
382 //! Return whether the cap intersect with a convex contour defined by nbVertice.
383 bool intersectsConvexContour(const Vec3d* vertice, int nbVertice) const;
384
385 //! Return whether the cap contains the passed triangle.
386 bool containsTriangle(const Vec3d* vertice) const;
387
388 //! Return whether the cap intersect with the passed triangle.
389 bool intersectsTriangle(const Vec3d* vertice) const;
390
391 //! Deserialize the region. This method must allow as fast as possible deserialization.
392 static SphericalRegionP deserialize(QDataStream& in);
393
394 //! Return the relative overlap between the areas of the 2 caps, i.e:
395 //! min(intersectionArea/c1.area, intersectionArea/c2.area)
396 static double relativeAreaOverlap(const SphericalCap& c1, const SphericalCap& c2);
397
398 //! Return the relative overlap between the diameter of the 2 caps, i.e:
399 //! min(intersectionDistance/c1.diameter, intersectionDistance/c2.diameter)
400 static double relativeDiameterOverlap(const SphericalCap& c1, const SphericalCap& c2);
401
402 //! Compute the intersection of 2 halfspaces on the sphere (usually on 2 points) and return it in p1 and p2.
403 //! If the 2 SphericalCap don't intersect or intersect only at 1 point, false is returned and p1 and p2 are undefined.
404 static bool intersectionPoints(const SphericalCap& h1, const SphericalCap& h2, Vec3d& p1, Vec3d& p2);
405
406 //! The direction unit vector. Only if d==0, this vector doesn't need to be unit.
407 Vec3d n;
408 //! The cos of cone radius
409 double d;
410 };
411
412 //! Return whether the halfspace defined by the vectors v1^v2 and with aperture 90 deg contains the point p.
413 //! The comparison is made with a double number slightly smaller than zero to avoid floating point precision
414 //! errors problems (one test fails if it is set to zero).
sideHalfSpaceContains(const Vec3d & v1,const Vec3d & v2,const Vec3d & p)415 inline bool sideHalfSpaceContains(const Vec3d& v1, const Vec3d& v2, const Vec3d& p)
416 {
417 return (v1[1] * v2[2] - v1[2] * v2[1])*p[0] +
418 (v1[2] * v2[0] - v1[0] * v2[2])*p[1] +
419 (v1[0] * v2[1] - v1[1] * v2[0])*p[2]>=-1e-17;
420 }
421
422 //! Return whether the halfspace defined by the vectors v1 and v2 contains the SphericalCap h.
sideHalfSpaceContains(const Vec3d & v1,const Vec3d & v2,const SphericalCap & h)423 inline bool sideHalfSpaceContains(const Vec3d& v1, const Vec3d& v2, const SphericalCap& h)
424 {
425 Vec3d n(v1[1]*v2[2]-v1[2]*v2[1], v2[0]*v1[2]-v2[2]*v1[0], v2[1]*v1[0]-v2[0]*v1[1]);
426 n.normalize();
427 const double a = n*h.n;
428 return 0<=h.d && ( a>=1. || (a>=0. && a*a >= 1.-h.d*h.d));
429 }
430
431 //! Return whether the halfspace defined by the vectors v1 and v2 intersects the SphericalCap h.
sideHalfSpaceIntersects(const Vec3d & v1,const Vec3d & v2,const SphericalCap & h)432 inline bool sideHalfSpaceIntersects(const Vec3d& v1, const Vec3d& v2, const SphericalCap& h)
433 {
434 Vec3d n(v1[1]*v2[2]-v1[2]*v2[1], v2[0]*v1[2]-v2[2]*v1[0], v2[1]*v1[0]-v2[0]*v1[1]);
435 n.normalize();
436 return h.intersectsHalfSpace(n[0], n[1], n[2]);
437 }
438
439 //! @class SphericalPoint
440 //! Special SphericalRegion for a point on the sphere.
441 class SphericalPoint : public SphericalRegion
442 {
443 public:
SphericalPoint(const Vec3d & an)444 SphericalPoint(const Vec3d& an) : n(an) {Q_ASSERT(std::fabs(1.-n.length())<0.0000001);}
SphericalPoint(const SphericalPoint & other)445 SphericalPoint(const SphericalPoint &other): n(other.n){}
operator =(const SphericalPoint & other)446 inline SphericalPoint& operator=(const SphericalPoint &other){n=other.n; return *this;}
~SphericalPoint()447 virtual ~SphericalPoint() Q_DECL_OVERRIDE {;}
448
getType() const449 virtual SphericalRegionType getType() const Q_DECL_OVERRIDE {return SphericalRegion::Point;}
450 virtual OctahedronPolygon getOctahedronPolygon() const Q_DECL_OVERRIDE;
getArea() const451 virtual double getArea() const Q_DECL_OVERRIDE {return 0.;}
isEmpty() const452 virtual bool isEmpty() const Q_DECL_OVERRIDE {return false;}
getPointInside() const453 virtual Vec3d getPointInside() const Q_DECL_OVERRIDE {return n;}
getBoundingCap() const454 virtual SphericalCap getBoundingCap() const Q_DECL_OVERRIDE {return SphericalCap(n, 1);}
455 //! Serialize the region into a QVariant map matching the JSON format.
456 //! The format is ["POINT", [ra, dec]], with ra dec in degree in ICRS frame.
457 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
serialize(QDataStream & out) const458 virtual void serialize(QDataStream& out) const Q_DECL_OVERRIDE {out << n;}
459
460 // Contain and intersect
contains(const Vec3d & p) const461 virtual bool contains(const Vec3d& p) const Q_DECL_OVERRIDE {return n==p;}
contains(const SphericalPolygon &) const462 virtual bool contains(const SphericalPolygon&) const Q_DECL_OVERRIDE {return false;}
contains(const SphericalConvexPolygon &) const463 virtual bool contains(const SphericalConvexPolygon&) const Q_DECL_OVERRIDE {return false;}
contains(const SphericalCap &) const464 virtual bool contains(const SphericalCap&) const Q_DECL_OVERRIDE {return false;}
contains(const SphericalPoint & r) const465 virtual bool contains(const SphericalPoint& r) const Q_DECL_OVERRIDE {return n==r.n;}
contains(const AllSkySphericalRegion &) const466 virtual bool contains(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return false;}
467 virtual bool intersects(const SphericalPolygon&) const Q_DECL_OVERRIDE;
468 virtual bool intersects(const SphericalConvexPolygon&) const Q_DECL_OVERRIDE;
intersects(const SphericalCap & r) const469 virtual bool intersects(const SphericalCap& r) const Q_DECL_OVERRIDE {return r.contains(n);}
intersects(const SphericalPoint & r) const470 virtual bool intersects(const SphericalPoint& r) const Q_DECL_OVERRIDE {return n==r.n;}
intersects(const AllSkySphericalRegion &) const471 virtual bool intersects(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return true;}
472
473 //! Deserialize the region. This method must allow as fast as possible deserialization.
474 static SphericalRegionP deserialize(QDataStream& in);
475
476 //! The unit vector of the point direction.
477 Vec3d n;
478 };
479
480 //! @class AllSkySphericalRegion
481 //! Special SphericalRegion for the whole sphere.
482 class AllSkySphericalRegion : public SphericalRegion
483 {
484 public:
~AllSkySphericalRegion()485 virtual ~AllSkySphericalRegion() Q_DECL_OVERRIDE {;}
486
getType() const487 virtual SphericalRegionType getType() const Q_DECL_OVERRIDE {return SphericalRegion::AllSky;}
getOctahedronPolygon() const488 virtual OctahedronPolygon getOctahedronPolygon() const Q_DECL_OVERRIDE {return OctahedronPolygon::getAllSkyOctahedronPolygon();}
getArea() const489 virtual double getArea() const Q_DECL_OVERRIDE {return 4.*M_PI;}
isEmpty() const490 virtual bool isEmpty() const Q_DECL_OVERRIDE {return false;}
getPointInside() const491 virtual Vec3d getPointInside() const Q_DECL_OVERRIDE {return Vec3d(1,0,0);}
getBoundingCap() const492 virtual SphericalCap getBoundingCap() const Q_DECL_OVERRIDE {return SphericalCap(Vec3d(1,0,0), -2);}
493 //! Serialize the region into a QVariant map matching the JSON format.
494 //! The format is ["ALLSKY"]
495 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
serialize(QDataStream &) const496 virtual void serialize(QDataStream&) const Q_DECL_OVERRIDE {;}
497
498 // Contain and intersect
contains(const Vec3d &) const499 virtual bool contains(const Vec3d&) const Q_DECL_OVERRIDE {return true;}
contains(const SphericalPolygon &) const500 virtual bool contains(const SphericalPolygon&) const Q_DECL_OVERRIDE {return true;}
contains(const SphericalConvexPolygon &) const501 virtual bool contains(const SphericalConvexPolygon&) const Q_DECL_OVERRIDE {return true;}
contains(const SphericalCap &) const502 virtual bool contains(const SphericalCap&) const Q_DECL_OVERRIDE {return true;}
contains(const SphericalPoint &) const503 virtual bool contains(const SphericalPoint&) const Q_DECL_OVERRIDE {return true;}
contains(const AllSkySphericalRegion &) const504 virtual bool contains(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return true;}
intersects(const SphericalPolygon &) const505 virtual bool intersects(const SphericalPolygon&) const Q_DECL_OVERRIDE {return true;}
intersects(const SphericalConvexPolygon &) const506 virtual bool intersects(const SphericalConvexPolygon&) const Q_DECL_OVERRIDE {return true;}
intersects(const SphericalCap &) const507 virtual bool intersects(const SphericalCap&) const Q_DECL_OVERRIDE {return true;}
intersects(const SphericalPoint &) const508 virtual bool intersects(const SphericalPoint&) const Q_DECL_OVERRIDE {return true;}
intersects(const AllSkySphericalRegion &) const509 virtual bool intersects(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return true;}
510
511 static const SphericalRegionP staticInstance;
512 };
513
514 //! @class EmptySphericalRegion
515 //! Special SphericalRegion for --- UMM, WHAT EXACTLY?
516 class EmptySphericalRegion : public SphericalRegion
517 {
518 public:
519 // Avoid name hiding when overloading the virtual methods.
520 using SphericalRegion::intersects;
521 using SphericalRegion::contains;
522 using SphericalRegion::getIntersection;
523 using SphericalRegion::getUnion;
524 using SphericalRegion::getSubtraction;
525
EmptySphericalRegion()526 EmptySphericalRegion() {;}
~EmptySphericalRegion()527 virtual ~EmptySphericalRegion() Q_DECL_OVERRIDE {;}
528
getType() const529 virtual SphericalRegionType getType() const Q_DECL_OVERRIDE {return SphericalRegion::Empty;}
getOctahedronPolygon() const530 virtual OctahedronPolygon getOctahedronPolygon() const Q_DECL_OVERRIDE {return OctahedronPolygon::getEmptyOctahedronPolygon();}
getArea() const531 virtual double getArea() const Q_DECL_OVERRIDE {return 0.;}
isEmpty() const532 virtual bool isEmpty() const Q_DECL_OVERRIDE {return true;}
getPointInside() const533 virtual Vec3d getPointInside() const Q_DECL_OVERRIDE {return Vec3d(1,0,0);}
getBoundingCap() const534 virtual SphericalCap getBoundingCap() const Q_DECL_OVERRIDE {return SphericalCap(Vec3d(1,0,0), 2);}
535 //! Serialize the region into a QVariant map matching the JSON format.
536 //! The format is ["EMPTY"]
537 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
serialize(QDataStream &) const538 virtual void serialize(QDataStream&) const Q_DECL_OVERRIDE {;}
539
540 // Contain and intersect
contains(const Vec3d &) const541 virtual bool contains(const Vec3d&) const Q_DECL_OVERRIDE {return false;}
contains(const SphericalPolygon &) const542 virtual bool contains(const SphericalPolygon&) const Q_DECL_OVERRIDE {return false;}
contains(const SphericalConvexPolygon &) const543 virtual bool contains(const SphericalConvexPolygon&) const Q_DECL_OVERRIDE {return false;}
contains(const SphericalCap &) const544 virtual bool contains(const SphericalCap&) const Q_DECL_OVERRIDE {return false;}
contains(const SphericalPoint &) const545 virtual bool contains(const SphericalPoint&) const Q_DECL_OVERRIDE {return false;}
contains(const AllSkySphericalRegion &) const546 virtual bool contains(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return false;}
intersects(const SphericalPolygon &) const547 virtual bool intersects(const SphericalPolygon&) const Q_DECL_OVERRIDE {return false;}
intersects(const SphericalConvexPolygon &) const548 virtual bool intersects(const SphericalConvexPolygon&) const Q_DECL_OVERRIDE {return false;}
intersects(const SphericalCap &) const549 virtual bool intersects(const SphericalCap&) const Q_DECL_OVERRIDE {return false;}
intersects(const SphericalPoint &) const550 virtual bool intersects(const SphericalPoint&) const Q_DECL_OVERRIDE {return false;}
intersects(const AllSkySphericalRegion &) const551 virtual bool intersects(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return false;}
552
553 static const SphericalRegionP staticInstance;
554 };
555
556
557 //! @class SphericalPolygon
558 //! Class defining default implementations for some spherical geometry methods.
559 //! All methods are reentrant.
560 class SphericalPolygon : public SphericalRegion
561 {
562 public:
563 // Avoid name hiding when overloading the virtual methods.
564 using SphericalRegion::intersects;
565 using SphericalRegion::contains;
566 using SphericalRegion::getIntersection;
567 using SphericalRegion::getUnion;
568 using SphericalRegion::getSubtraction;
569
SphericalPolygon()570 SphericalPolygon() {;}
571 //! Constructor from a list of contours.
SphericalPolygon(const QVector<QVector<Vec3d>> & contours)572 SphericalPolygon(const QVector<QVector<Vec3d> >& contours) : octahedronPolygon(contours) {;}
573 //! Constructor from one contour.
SphericalPolygon(const QVector<Vec3d> & contour)574 SphericalPolygon(const QVector<Vec3d>& contour) : octahedronPolygon(contour) {;}
SphericalPolygon(const OctahedronPolygon & octContour)575 SphericalPolygon(const OctahedronPolygon& octContour) : octahedronPolygon(octContour) {;}
SphericalPolygon(const QList<OctahedronPolygon> & octContours)576 SphericalPolygon(const QList<OctahedronPolygon>& octContours) : octahedronPolygon(octContours) {;}
577
getType() const578 virtual SphericalRegionType getType() const Q_DECL_OVERRIDE {return SphericalRegion::Polygon;}
getOctahedronPolygon() const579 virtual OctahedronPolygon getOctahedronPolygon() const Q_DECL_OVERRIDE {return octahedronPolygon;}
580
581 //! Serialize the region into a QVariant map matching the JSON format.
582 //! The format is:
583 //! @code[[[ra,dec], [ra,dec], [ra,dec], [ra,dec]], [[ra,dec], [ra,dec], [ra,dec]],[...]]@endcode
584 //! it is a list of closed contours, with each points defined by ra dec in degree in the ICRS frame.
585 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
586 virtual void serialize(QDataStream& out) const Q_DECL_OVERRIDE;
587
588 virtual SphericalCap getBoundingCap() const Q_DECL_OVERRIDE;
589
contains(const Vec3d & p) const590 virtual bool contains(const Vec3d& p) const Q_DECL_OVERRIDE {return octahedronPolygon.contains(p);}
contains(const SphericalPolygon & r) const591 virtual bool contains(const SphericalPolygon& r) const Q_DECL_OVERRIDE {return octahedronPolygon.contains(r.octahedronPolygon);}
592 virtual bool contains(const SphericalConvexPolygon& r) const Q_DECL_OVERRIDE;
contains(const SphericalCap & r) const593 virtual bool contains(const SphericalCap& r) const Q_DECL_OVERRIDE {return octahedronPolygon.contains(r.getOctahedronPolygon());}
contains(const SphericalPoint & r) const594 virtual bool contains(const SphericalPoint& r) const Q_DECL_OVERRIDE {return octahedronPolygon.contains(r.n);}
contains(const AllSkySphericalRegion & r) const595 virtual bool contains(const AllSkySphericalRegion& r) const Q_DECL_OVERRIDE {return octahedronPolygon.contains(r.getOctahedronPolygon());}
596
intersects(const SphericalPolygon & r) const597 virtual bool intersects(const SphericalPolygon& r) const Q_DECL_OVERRIDE {return octahedronPolygon.intersects(r.octahedronPolygon);}
598 virtual bool intersects(const SphericalConvexPolygon& r) const Q_DECL_OVERRIDE;
intersects(const SphericalCap & r) const599 virtual bool intersects(const SphericalCap& r) const Q_DECL_OVERRIDE {return r.intersects(*this);}
intersects(const SphericalPoint & r) const600 virtual bool intersects(const SphericalPoint& r) const Q_DECL_OVERRIDE {return octahedronPolygon.contains(r.n);}
intersects(const AllSkySphericalRegion &) const601 virtual bool intersects(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return !isEmpty();}
602
getIntersection(const SphericalPoint & r) const603 virtual SphericalRegionP getIntersection(const SphericalPoint& r) const Q_DECL_OVERRIDE {return contains(r.n) ? SphericalRegionP(new SphericalPoint(r)) : EmptySphericalRegion::staticInstance;}
getIntersection(const AllSkySphericalRegion &) const604 virtual SphericalRegionP getIntersection(const AllSkySphericalRegion& ) const Q_DECL_OVERRIDE {return SphericalRegionP(new SphericalPolygon(octahedronPolygon));}
605
getUnion(const SphericalPoint &) const606 virtual SphericalRegionP getUnion(const SphericalPoint&) const Q_DECL_OVERRIDE {return SphericalRegionP(new SphericalPolygon(octahedronPolygon));}
getUnion(const EmptySphericalRegion &) const607 virtual SphericalRegionP getUnion(const EmptySphericalRegion&) const Q_DECL_OVERRIDE {return SphericalRegionP(new SphericalPolygon(octahedronPolygon));}
608
getSubtraction(const SphericalPoint &) const609 virtual SphericalRegionP getSubtraction(const SphericalPoint&) const Q_DECL_OVERRIDE {return SphericalRegionP(new SphericalPolygon(octahedronPolygon));}
getSubtraction(const EmptySphericalRegion &) const610 virtual SphericalRegionP getSubtraction(const EmptySphericalRegion&) const Q_DECL_OVERRIDE {return SphericalRegionP(new SphericalPolygon(octahedronPolygon));}
611
612 ////////////////////////////////////////////////////////////////////
613 // Methods specific to SphericalPolygon
614 //! Set the contours defining the SphericalPolygon.
615 //! @param contours the list of contours defining the polygon area. The contours are combined using
616 //! the positive winding rule, meaning that the polygon is the union of the positive contours minus the negative ones.
setContours(const QVector<QVector<Vec3d>> & contours)617 void setContours(const QVector<QVector<Vec3d> >& contours) {octahedronPolygon = OctahedronPolygon(contours);}
618
619 //! Set a single contour defining the SphericalPolygon.
620 //! @param contour a contour defining the polygon area.
setContour(const QVector<Vec3d> & contour)621 void setContour(const QVector<Vec3d>& contour) {octahedronPolygon = OctahedronPolygon(contour);}
622
623 //! Return the list of closed contours defining the polygon boundaries.
getClosedOutlineContours() const624 QVector<QVector<Vec3d> > getClosedOutlineContours() const {Q_ASSERT(0); return QVector<QVector<Vec3d> >();}
625
626 //! Deserialize the region. This method must allow as fast as possible deserialization.
627 static SphericalRegionP deserialize(QDataStream& in);
628
629 //! Create a new SphericalRegionP which is the union of all the passed ones.
630 static SphericalRegionP multiUnion(const QList<SphericalRegionP>& regions, bool optimizeByPreGrouping=false);
631
632 //! Create a new SphericalRegionP which is the intersection of all the passed ones.
633 static SphericalRegionP multiIntersection(const QList<SphericalRegionP>& regions);
634
635 private:
636 OctahedronPolygon octahedronPolygon;
637 };
638
639
640 //! @class SphericalConvexPolygon
641 //! A special case of SphericalPolygon for which the polygon is convex.
642 class SphericalConvexPolygon : public SphericalRegion
643 {
644 public:
645 // Avoid name hiding when overloading the virtual methods.
646 using SphericalRegion::intersects;
647 using SphericalRegion::contains;
648
649 //! Default constructor.
SphericalConvexPolygon()650 SphericalConvexPolygon() {;}
651
652 //! Constructor from a list of contours.
SphericalConvexPolygon(const QVector<QVector<Vec3d>> & contours)653 SphericalConvexPolygon(const QVector<QVector<Vec3d> >& contours) {Q_ASSERT(contours.size()==1); setContour(contours.at(0));}
654 //! Constructor from one contour.
SphericalConvexPolygon(const QVector<Vec3d> & contour)655 SphericalConvexPolygon(const QVector<Vec3d>& contour) {setContour(contour);}
656 //! Special constructor for triangle.
SphericalConvexPolygon(const Vec3d & e0,const Vec3d & e1,const Vec3d & e2)657 SphericalConvexPolygon(const Vec3d &e0,const Vec3d &e1,const Vec3d &e2) {contour << e0 << e1 << e2; updateBoundingCap();}
658 //! Special constructor for quads.
SphericalConvexPolygon(const Vec3d & e0,const Vec3d & e1,const Vec3d & e2,const Vec3d & e3)659 SphericalConvexPolygon(const Vec3d &e0,const Vec3d &e1,const Vec3d &e2, const Vec3d &e3) {contour << e0 << e1 << e2 << e3; updateBoundingCap();}
660
getType() const661 virtual SphericalRegionType getType() const Q_DECL_OVERRIDE {return SphericalRegion::ConvexPolygon;}
getOctahedronPolygon() const662 virtual OctahedronPolygon getOctahedronPolygon() const Q_DECL_OVERRIDE {return OctahedronPolygon(contour);}
663 virtual StelVertexArray getFillVertexArray(const Vec3d &observerVelocityForAberration) Q_DECL_OVERRIDE;
664 virtual StelVertexArray getFillVertexArray() const Q_DECL_OVERRIDE;
665 virtual StelVertexArray getOutlineVertexArray() const Q_DECL_OVERRIDE;
666 virtual StelVertexArray getOutlineVertexArray(Vec3d observerVelocityForAberration) Q_DECL_OVERRIDE;
667 //virtual StelVertexArray getOutlineVertexArray(Vec3d observerVelocityForAberration) const Q_DECL_OVERRIDE;
668 virtual double getArea() const Q_DECL_OVERRIDE;
isEmpty() const669 virtual bool isEmpty() const Q_DECL_OVERRIDE {return contour.isEmpty();}
670 virtual Vec3d getPointInside() const Q_DECL_OVERRIDE;
getBoundingCap() const671 virtual SphericalCap getBoundingCap() const Q_DECL_OVERRIDE {return cachedBoundingCap;}
672 QVector<SphericalCap> getBoundingSphericalCaps() const Q_DECL_OVERRIDE;
673 //! Serialize the region into a QVariant map matching the JSON format.
674 //! The format is
675 //! @code["CONVEX_POLYGON", [[ra,dec], [ra,dec], [ra,dec], [ra,dec]]]@endcode
676 //! where the coords are a closed convex contour, with each points defined by ra dec in degree in the ICRS frame.
677 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
serialize(QDataStream & out) const678 virtual void serialize(QDataStream& out) const Q_DECL_OVERRIDE {out << contour;}
679
680 // Contain and intersect
681 virtual bool contains(const Vec3d& p) const Q_DECL_OVERRIDE;
682 virtual bool contains(const SphericalPolygon& r) const Q_DECL_OVERRIDE;
683 virtual bool contains(const SphericalConvexPolygon& r) const Q_DECL_OVERRIDE;
684 virtual bool contains(const SphericalCap& r) const Q_DECL_OVERRIDE;
contains(const SphericalPoint & r) const685 virtual bool contains(const SphericalPoint& r) const Q_DECL_OVERRIDE {return contains(r.n);}
contains(const AllSkySphericalRegion &) const686 virtual bool contains(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return false;}
intersects(const SphericalCap & r) const687 virtual bool intersects(const SphericalCap& r) const Q_DECL_OVERRIDE {if (!cachedBoundingCap.intersects(r)) return false; return r.intersects(*this);}
688 virtual bool intersects(const SphericalPolygon& r) const Q_DECL_OVERRIDE;
689 virtual bool intersects(const SphericalConvexPolygon& r) const Q_DECL_OVERRIDE;
intersects(const SphericalPoint & r) const690 virtual bool intersects(const SphericalPoint& r) const Q_DECL_OVERRIDE {return contains(r.n);}
intersects(const AllSkySphericalRegion &) const691 virtual bool intersects(const AllSkySphericalRegion&) const Q_DECL_OVERRIDE {return true;}
692
693 ////////////////////////// TODO
694 // virtual SphericalRegionP getIntersection(const SphericalPolygon& r) const;
695 // virtual SphericalRegionP getIntersection(const SphericalConvexPolygon& r) const;
696 // virtual SphericalRegionP getIntersection(const SphericalCap& r) const;
697 // virtual SphericalRegionP getIntersection(const SphericalPoint& r) const;
698 // virtual SphericalRegionP getIntersection(const AllSkySphericalRegion& r) const;
699 // virtual SphericalRegionP getUnion(const SphericalPolygon& r) const;
700 // virtual SphericalRegionP getUnion(const SphericalConvexPolygon& r) const;
701 // virtual SphericalRegionP getUnion(const SphericalCap& r) const;
702 // virtual SphericalRegionP getUnion(const SphericalPoint& r) const;
703 // virtual SphericalRegionP getUnion(const EmptySphericalRegion& r) const;
704 // virtual SphericalRegionP getSubtraction(const SphericalPolygon& r) const;
705 // virtual SphericalRegionP getSubtraction(const SphericalConvexPolygon& r) const;
706 // virtual SphericalRegionP getSubtraction(const SphericalCap& r) const;
707 // virtual SphericalRegionP getSubtraction(const SphericalPoint& r) const;
708 // virtual SphericalRegionP getSubtraction(const EmptySphericalRegion& r) const;
709
710 ////////////////////////////////////////////////////////////////////
711 // Methods specific to SphericalConvexPolygon
712 ////////////////////////////////////////////////////////////////////
713 //! Set a single contour defining the SphericalPolygon.
714 //! @param acontour a contour defining the polygon area.
setContour(const QVector<Vec3d> & acontour)715 void setContour(const QVector<Vec3d>& acontour) {contour=acontour; updateBoundingCap();}
716
717 //! Get the single contour defining the SphericalConvexPolygon.
getConvexContour() const718 const QVector<Vec3d>& getConvexContour() const {return contour;}
719
720 //! Check if the polygon is valid, i.e. it has no side >180.
721 bool checkValid() const;
722
723 //! Check if the passed contour is convex and valid, i.e. it has no side >180.
724 static bool checkValidContour(const QVector<Vec3d>& contour);
725
726 //! Deserialize the region. This method must allow as fast as possible deserialization.
727 static SphericalRegionP deserialize(QDataStream& in);
728
729 protected:
730 //! A list of vertices of the convex contour.
731 QVector<Vec3d> contour;
732 //! A list of vertices, built on the fly from the contour when aberration is required.
733 QVector<Vec3d> aberratedContour;
734
735 //! Cache the bounding cap.
736 SphericalCap cachedBoundingCap;
737
738 //! Update the bounding cap from the vertex list.
739 void updateBoundingCap();
740
741 //! Computes whether the passed points are all outside of at least one SphericalCap defining the polygon boundary.
742 //! @param thisContour the vertices defining the contour.
743 //! @param nbThisContour nb of vertice of the contour.
744 //! @param points the points to test.
745 //! @param nbPoints the number of points to test.
746 static bool areAllPointsOutsideOneSide(const Vec3d* thisContour, int nbThisContour, const Vec3d* points, int nbPoints);
747
748 //! Computes whether the passed points are all outside of at least one SphericalCap defining the polygon boundary.
areAllPointsOutsideOneSide(const QVector<Vec3d> & points) const749 bool areAllPointsOutsideOneSide(const QVector<Vec3d>& points) const
750 {
751 return areAllPointsOutsideOneSide(contour.constData(), contour.size(), points.constData(), points.size());
752 }
753
754 bool containsConvexContour(const Vec3d* vertice, int nbVertex) const;
755 };
756
757
758 // ! @class SphericalConvexPolygonSet
759 // ! A special case of SphericalPolygon for which the polygon is composed of disjoint convex polygons.
760 //class SphericalConvexPolygonSet : public SphericalRegion
761 //{
762 //public:
763 // // Avoid name hiding when overloading the virtual methods.
764 // using SphericalRegion::intersects;
765 // using SphericalRegion::contains;
766 //
767 // //! Default constructor.
768 // SphericalConvexPolygonSet() {;}
769 //
770 // //! Constructor from a list of contours.
771 // SphericalConvexPolygonSet(const QVector<QVector<Vec3d> >& contours);
772 //
773 // virtual SphericalRegionType getType() const {return SphericalRegion::ConvexPolygonSet;}
774 // virtual OctahedronPolygon getOctahedronPolygon() const;
775 // virtual StelVertexArray getFillVertexArray() const;
776 // virtual StelVertexArray getOutlineVertexArray() const;
777 // virtual double getArea() const;
778 // virtual bool isEmpty() const;
779 // virtual Vec3d getPointInside() const;
780 // virtual SphericalCap getBoundingCap() const {return cachedBoundingCap;}
781 // QVector<SphericalCap> getBoundingSphericalCaps() const;
782 // //! Serialize the region into a QVariant map matching the JSON format.
783 // //! The format is
784 // //! @code["CONVEX_POLYGON_SET", [[ra,dec], [ra,dec], [ra,dec], [ra,dec]], [[ra,dec], [ra,dec], [ra,dec], [ra,dec]]]@endcode
785 // //! where the coords from a list of closed convex contour, with each points defined by ra dec in degree in the ICRS frame.
786 // virtual QVariantList toQVariant() const;
787 // virtual void serialize(QDataStream& out) const;
788 //
789 // // Contain and intersect
790 // virtual bool contains(const Vec3d& p) const;
791 // virtual bool contains(const SphericalPolygon& r) const;
792 // virtual bool contains(const SphericalConvexPolygon& r) const;
793 // virtual bool contains(const SphericalCap& r) const;
794 // virtual bool contains(const SphericalPoint& r) const {return contains(r.n);}
795 // virtual bool contains(const AllSkySphericalRegion&) const {return false;}
796 // virtual bool intersects(const SphericalCap& r) const {if (!cachedBoundingCap.intersects(r)) return false; return r.intersects(*this);}
797 // virtual bool intersects(const SphericalPolygon& r) const;
798 // virtual bool intersects(const SphericalConvexPolygon& r) const;
799 // virtual bool intersects(const SphericalPoint& r) const {return contains(r.n);}
800 // virtual bool intersects(const AllSkySphericalRegion&) const {return true;}
801 //
802 // ////////////////////////////////////////////////////////////////////
803 // // Methods specific to SphericalConvexPolygonSet
804 // ////////////////////////////////////////////////////////////////////
805 // //! Deserialize the region. This method must allow as fast as possible deserialization.
806 // static SphericalRegionP deserialize(QDataStream& in);
807 //
808 //protected:
809 // QVector<SphericalConvexPolygon> contours;
810 //
811 // //! Cache the bounding cap.
812 // SphericalCap cachedBoundingCap;
813 //
814 // //! Update the bounding cap from the vertex list.
815 // void updateBoundingCap();
816 //};
817
818 //! @class SphericalTexturedPolygon
819 //! An extension of SphericalPolygon with addition of texture coordinates.
820 class SphericalTexturedPolygon : public SphericalPolygon
821 {
822 public:
823 //! @struct TextureVertex
824 //! A container for 3D vertex + associated texture coordinates
825 struct TextureVertex
826 {
827 Vec3d vertex;
828 Vec2f texCoord;
829 };
830
SphericalTexturedPolygon()831 SphericalTexturedPolygon() {;}
832 //! Constructor from a list of contours.
SphericalTexturedPolygon(const QVector<QVector<TextureVertex>> & contours)833 SphericalTexturedPolygon(const QVector<QVector<TextureVertex> >& contours) {Q_UNUSED(contours); Q_ASSERT(0);}
834 //! Constructor from one contour.
SphericalTexturedPolygon(const QVector<TextureVertex> & contour)835 SphericalTexturedPolygon(const QVector<TextureVertex>& contour) {Q_UNUSED(contour); Q_ASSERT(0);}
836
837 //! Return an OpenGL compatible array of texture coords to be used using vertex arrays.
838 //! This implementation never should appear in practice.
getFillVertexArray() const839 virtual StelVertexArray getFillVertexArray() const Q_DECL_OVERRIDE {Q_ASSERT(0); return StelVertexArray();}
getFillVertexArray(const Vec3d & observerVelocityForAberration)840 virtual StelVertexArray getFillVertexArray(const Vec3d &observerVelocityForAberration) Q_DECL_OVERRIDE {Q_ASSERT(0); Q_UNUSED(observerVelocityForAberration) return StelVertexArray();}
841 //! Serialize the region into a QVariant map matching the JSON format.
842 //! The format is:
843 //! @code["TEXTURED_POLYGON", [[[ra,dec], [ra,dec], [ra,dec], [ra,dec]], [[ra,dec], [ra,dec], [ra,dec]],[...]],
844 //! [[[u,v],[u,v],[u,v],[u,v]], [[u,v],[u,v],[u,v]], [...]]]@endcode
845 //! where the two lists are a list of closed contours, with each points defined by ra dec in degree in the ICRS frame
846 //! followed by a list of texture coordinates in the u,v texture space (between 0 and 1).
847 //! There must be one texture coordinate for each vertex.
848 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
serialize(QDataStream & out) const849 virtual void serialize(QDataStream& out) const Q_DECL_OVERRIDE {Q_UNUSED(out); Q_ASSERT(0);}
850
851 ////////////////////////////////////////////////////////////////////
852 // Methods specific to SphericalTexturedPolygon
853 //! Set the contours defining the SphericalPolygon.
854 //! @param contours the list of contours defining the polygon area using the WindingPositive winding rule.
setContours(const QVector<QVector<TextureVertex>> & contours)855 void setContours(const QVector<QVector<TextureVertex> >& contours) {Q_UNUSED(contours); Q_ASSERT(0);}
856
857 //! Set a single contour defining the SphericalPolygon.
858 //! @param contour a contour defining the polygon area.
setContour(const QVector<TextureVertex> & contour)859 void setContour(const QVector<TextureVertex>& contour) {Q_UNUSED(contour); Q_ASSERT(0);}
860
861 private:
862 //! A list of uv textures coordinates corresponding to the triangle vertices.
863 //! There should be 1 uv position per vertex.
864 QVector<Vec2f> textureCoords;
865 };
866
867
868 Q_DECLARE_TYPEINFO(SphericalTexturedPolygon::TextureVertex, Q_PRIMITIVE_TYPE);
869
870 //! @class SphericalTexturedConvexPolygon
871 //! Extension of SphericalConvexPolygon for textured polygon.
872 class SphericalTexturedConvexPolygon : public SphericalConvexPolygon
873 {
874 public:
875 //! Default constructor.
SphericalTexturedConvexPolygon()876 SphericalTexturedConvexPolygon() {;}
877
878 //! Constructor from one contour.
SphericalTexturedConvexPolygon(const QVector<Vec3d> & contour,const QVector<Vec2f> & texCoord)879 SphericalTexturedConvexPolygon(const QVector<Vec3d>& contour, const QVector<Vec2f>& texCoord) {setContour(contour, texCoord);}
880
881 //! Special constructor for quads.
882 //! Use the 4 textures corners for the 4 vertices.
SphericalTexturedConvexPolygon(const Vec3d & e0,const Vec3d & e1,const Vec3d & e2,const Vec3d & e3)883 SphericalTexturedConvexPolygon(const Vec3d &e0,const Vec3d &e1,const Vec3d &e2, const Vec3d &e3) : SphericalConvexPolygon(e0,e1,e2,e3)
884 {
885 textureCoords << Vec2f(0.f, 0.f) << Vec2f(1.f, 0.f) << Vec2f(1.f, 1.f) << Vec2f(0.f, 1.f);
886 }
887
888 //! Return an OpenGL compatible array to be displayed using vertex arrays.
889 //! This method is not optimized for SphericalConvexPolygon instances.
890 //! Return an OpenGL compatible array to be displayed using vertex arrays.
891 //! @param observerVelocityForAberration a vector to add to all contour vertices.
892 virtual StelVertexArray getFillVertexArray(const Vec3d &observerVelocityForAberration) Q_DECL_OVERRIDE;
893 //! Return array without any aberration.
894 virtual StelVertexArray getFillVertexArray() const Q_DECL_OVERRIDE;
895
896 //! Set a single contour defining the SphericalPolygon.
897 //! @param acontour a contour defining the polygon area.
898 //! @param texCoord a list of texture coordinates matching the vertices of the contour.
setContour(const QVector<Vec3d> & acontour,const QVector<Vec2f> & texCoord)899 virtual void setContour(const QVector<Vec3d>& acontour, const QVector<Vec2f>& texCoord) {SphericalConvexPolygon::setContour(acontour); textureCoords=texCoord;}
900
901 //! Serialize the region into a QVariant map matching the JSON format.
902 //! The format is:
903 //! @code["TEXTURED_CONVEX_POLYGON", [[ra,dec], [ra,dec], [ra,dec], [ra,dec]], [[u,v],[u,v],[u,v],[u,v]]]@endcode
904 //! where the two lists are a closed convex contours, with each points defined by ra dec in degree in the ICRS frame
905 //! followed by a list of texture coordinates in the u,v texture space (between 0 and 1).
906 //! There must be one texture coordinate for each vertex.
907 virtual QVariantList toQVariant() const Q_DECL_OVERRIDE;
908
serialize(QDataStream & out) const909 virtual void serialize(QDataStream& out) const Q_DECL_OVERRIDE {out << contour << textureCoords;}
910
911 protected:
912 //! A list of uv textures coordinates corresponding to the triangle vertices.
913 //! There should be 1 uv position per vertex.
914 QVector<Vec2f> textureCoords;
915 };
916
917
918 //! Compute the intersection of 2 great circles segments.
919 //! @param ok is set to false if no intersection was found.
920 //! @return the intersection point on the sphere (normalized) if ok is true, or undefined of ok is false.
921 Vec3d greatCircleIntersection(const Vec3d& p1, const Vec3d& p2, const Vec3d& p3, const Vec3d& p4, bool& ok);
922
923 //! Compute the intersection of a great circles segment with another great circle.
924 //! @param ok is set to false if no intersection was found.
925 //! @return the intersection point on the sphere (normalized) if ok is true, or undefined of ok is false.
926 Vec3d greatCircleIntersection(const Vec3d& p1, const Vec3d& p2, const Vec3d& nHalfSpace, bool& ok);
927
928 #endif // STELSPHEREGEOMETRY_HPP
929
930