Kstars

projector.h
1 /*
2  SPDX-FileCopyrightText: 2010 Henry de Valence <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #ifdef KSTARS_LITE
10 #include "skymaplite.h"
11 #else
12 #include "skymap.h"
13 #endif
14 #include "skyobjects/skypoint.h"
15 
16 #if __GNUC__ > 5
17 #pragma GCC diagnostic push
18 #pragma GCC diagnostic ignored "-Wignored-attributes"
19 #endif
20 #if __GNUC__ > 6
21 #pragma GCC diagnostic ignored "-Wint-in-bool-context"
22 #endif
23 #include <Eigen/Core>
24 #if __GNUC__ > 5
25 #pragma GCC diagnostic pop
26 #endif
27 
28 #include <QPointF>
29 
30 #include <cstddef>
31 #include <cmath>
32 
33 class KStarsData;
34 
35 /** This is just a container that holds information needed to do projections. */
37 {
38  public:
39  float width, height;
40  float zoomFactor;
41  bool useRefraction;
42  bool useAltAz;
43  bool fillGround; ///<If the ground is filled, then points below horizon are invisible
44  SkyPoint *focus;
45  ViewParams() : width(0), height(0), zoomFactor(0),
46  useRefraction(false), useAltAz(false), fillGround(false),
47  focus(nullptr) {}
48 };
49 
50 /**
51  * @class Projector
52  *
53  * The Projector class is the primary class that serves as an interface to handle projections.
54  */
55 class Projector
56 {
57  Q_GADGET
58  public:
59  /**
60  * Constructor.
61  *
62  * @param p the ViewParams for this projection
63  */
64  explicit Projector(const ViewParams &p);
65 
66  virtual ~Projector() = default;
67 
68  /** Update cached values for projector */
69  void setViewParams(const ViewParams &p);
70  ViewParams viewParams() const
71  {
72  return m_vp;
73  }
74 
75  enum Projection
76  {
77  Lambert,
78  AzimuthalEquidistant,
79  Orthographic,
80  Equirectangular,
81  Stereographic,
82  Gnomonic,
83  UnknownProjection
84  };
85  Q_ENUM(Projection)
86 
87  /** Return the type of this projection */
88  Q_INVOKABLE virtual Projection type() const = 0;
89 
90  /** Return the FOV of this projection */
91  double fov() const;
92 
93  /**
94  * Check if the current point on screen is a valid point on the sky. This is needed
95  * to avoid a crash of the program if the user clicks on a point outside the sky (the
96  * corners of the sky map at the lowest zoom level are the invalid points).
97  * @param p the screen pixel position
98  */
99  virtual bool unusablePoint(const QPointF &p) const;
100 
101  /**
102  * Given the coordinates of the SkyPoint argument, determine the
103  * pixel coordinates in the SkyMap.
104  *
105  * Since most of the projections used by KStars are very similar,
106  * if this function were to be reimplemented in each projection subclass
107  * we would end up changing maybe 5 or 6 lines out of 150.
108  * Instead, we have a default implementation that uses the projectionK
109  * and projectionL functions to take care of the differences between
110  * e.g. Orthographic and Stereographic. There is also the cosMaxFieldAngle
111  * function, which is used for testing whether a point is on the visible
112  * part of the projection, and the radius function which gives the radius of
113  * the projection in screen coordinates.
114  *
115  * While this seems ugly, it is less ugly than duplicating 150 loc to change 5.
116  *
117  * @return Eigen::Vector2f containing screen pixel x, y coordinates of SkyPoint.
118  * @param o pointer to the SkyPoint for which to calculate x, y coordinates.
119  * @param oRefract true = use Options::useRefraction() value.
120  * false = do not use refraction. This argument is only needed
121  * for the Horizon, which should never be refracted.
122  * @param onVisibleHemisphere pointer to a bool to indicate whether the point is
123  * on the visible part of the Celestial Sphere.
124  */
125  virtual Eigen::Vector2f toScreenVec(const SkyPoint *o, bool oRefract = true,
126  bool *onVisibleHemisphere = nullptr) const;
127 
128  /**
129  * This is exactly the same as toScreenVec but it returns a QPointF.
130  * It just calls toScreenVec and converts the result.
131  * @see toScreenVec()
132  */
133  QPointF toScreen(const SkyPoint *o, bool oRefract = true, bool *onVisibleHemisphere = nullptr) const;
134 
135  /**
136  * @short Determine RA, Dec coordinates of the pixel at (dx, dy), which are the
137  * screen pixel coordinate offsets from the center of the Sky pixmap.
138  * @param p the screen pixel position to convert
139  * @param LST pointer to the local sidereal time, as a dms object.
140  * @param lat pointer to the current geographic laitude, as a dms object
141  * @param onlyAltAz the returned SkyPoint's RA & DEC are not computed, only Alt/Az.
142  */
143  virtual SkyPoint fromScreen(const QPointF &p, dms *LST, const dms *lat, bool onlyAltAz = false) const;
144 
145  /**
146  * ASSUMES *p1 did not clip but *p2 did. Returns the QPointF on the line
147  * between *p1 and *p2 that just clips.
148  */
149  QPointF clipLine(SkyPoint *p1, SkyPoint *p2) const;
150 
151  /**
152  * ASSUMES *p1 did not clip but *p2 did. Returns the Eigen::Vector2f on the line
153  * between *p1 and *p2 that just clips.
154  */
155  Eigen::Vector2f clipLineVec(SkyPoint *p1, SkyPoint *p2) const;
156 
157  /** Check whether the projected point is on-screen */
158  bool onScreen(const QPointF &p) const;
159  bool onScreen(const Eigen::Vector2f &p) const;
160 
161  /**
162  * @short Determine if the skypoint p is likely to be visible in the display window.
163  *
164  * checkVisibility() is an optimization function. It determines whether an object
165  * appears within the bounds of the skymap window, and therefore should be drawn.
166  * The idea is to save time by skipping objects which are off-screen, so it is
167  * absolutely essential that checkVisibility() is significantly faster than
168  * the computations required to draw the object to the screen.
169  *
170  * If the ground is to be filled, the function first checks whether the point is
171  * below the horizon, because they will be covered by the ground anyways.
172  * Importantly, it does not call the expensive EquatorialToHorizontal function.
173  * This means that the horizontal coordinates MUST BE CORRECT! The vast majority
174  * of points are already synchronized, so recomputing the horizontal coordinates is
175  * a waste.
176  *
177  * The function then checks the difference between the Declination/Altitude
178  * coordinate of the Focus position, and that of the point p. If the absolute
179  * value of this difference is larger than fov, then the function returns false.
180  * For most configurations of the sky map window, this simple check is enough to
181  * exclude a large number of objects.
182  *
183  * Next, it determines if one of the poles of the current Coordinate System
184  * (Equatorial or Horizontal) is currently inside the sky map window. This is
185  * stored in the member variable 'bool SkyMap::isPoleVisible, and is set by the
186  * function SkyMap::setMapGeometry(), which is called by SkyMap::paintEvent().
187  * If a Pole is visible, then it will return true immediately. The idea is that
188  * when a pole is on-screen it is computationally expensive to determine whether
189  * a particular position is on-screen or not: for many valid Dec/Alt values, *all*
190  * values of RA/Az will indeed be onscreen, but for other valid Dec/Alt values,
191  * only *most* RA/Az values are onscreen. It is cheaper to simply accept all
192  * "horizontal" RA/Az values, since we have already determined that they are
193  * on-screen in the "vertical" Dec/Alt coordinate.
194  *
195  * Finally, if no Pole is onscreen, it checks the difference between the Focus
196  * position's RA/Az coordinate and that of the point p. If the absolute value of
197  * this difference is larger than XMax, the function returns false. Otherwise,
198  * it returns true.
199  *
200  * @param p pointer to the skypoint to be checked.
201  * @return true if the point p was found to be inside the Sky map window.
202  * @see SkyMap::setMapGeometry()
203  * @see SkyMap::fov()
204  * @note If you are creating skypoints using equatorial coordinates, then
205  * YOU MUST CALL EQUATORIALTOHORIZONTAL BEFORE THIS FUNCTION!
206  */
207  bool checkVisibility(const SkyPoint *p) const;
208 
209  /**
210  * Determine the on-screen position angle of a SkyPont with recept with NCP.
211  * This is the object's sky position angle (w.r.t. North).
212  * of "North" at the position of the object (w.r.t. the screen Y-axis).
213  * The latter is determined by constructing a test point with the same RA but
214  * a slightly increased Dec as the object, and calculating the angle w.r.t. the
215  * Y-axis of the line connecting the object to its test point.
216  */
217  double findNorthPA(const SkyPoint *o, float x, float y) const;
218 
219  /**
220  * Determine the on-screen position angle of a SkyObject. This is the sum
221  * of the object's sky position angle (w.r.t. North), and the position angle
222  * of "North" at the position of the object (w.r.t. the screen Y-axis).
223  * The latter is determined by constructing a test point with the same RA but
224  * a slightly increased Dec as the object, and calculating the angle w.r.t. the
225  * Y-axis of the line connecting the object to its test point.
226  */
227  double findPA(const SkyObject *o, float x, float y) const;
228 
229  /**
230  * Get the ground polygon
231  * @param labelpoint This point will be set to something suitable for attaching a label
232  * @param drawLabel this tells whether to draw a label.
233  * @return the ground polygon
234  */
235  virtual QVector<Eigen::Vector2f> groundPoly(SkyPoint *labelpoint = nullptr, bool *drawLabel = nullptr) const;
236 
237  /**
238  * @brief updateClipPoly calculate the clipping polygen given the current FOV.
239  */
240  virtual void updateClipPoly();
241 
242  /**
243  * @return the clipping polygen covering the visible sky area. Anything outside this polygon is
244  * clipped by QPainter.
245  */
246  virtual QPolygonF clipPoly() const;
247 
248  protected:
249  /**
250  * Get the radius of this projection's sky circle.
251  * @return the radius in radians
252  */
253  virtual double radius() const
254  {
255  return 2 * M_PI;
256  }
257 
258  /**
259  * This function handles some of the projection-specific code.
260  * @see toScreen()
261  */
262  virtual double projectionK(double x) const
263  {
264  return x;
265  }
266 
267  /**
268  * This function handles some of the projection-specific code.
269  * @see toScreen()
270  */
271  virtual double projectionL(double x) const
272  {
273  return x;
274  }
275 
276  /**
277  * This function returns the cosine of the maximum field angle, i.e., the maximum angular
278  * distance from the focus for which a point should be projected. Default is 0, i.e.,
279  * 90 degrees.
280  */
281  virtual double cosMaxFieldAngle() const
282  {
283  return 0;
284  }
285 
286  /**
287  * Helper function for drawing ground.
288  * @return the point with Alt = 0, az = @p az
289  */
290  static SkyPoint pointAt(double az);
291 
292  KStarsData *m_data { nullptr };
293  ViewParams m_vp;
294  double m_sinY0 { 0 };
295  double m_cosY0 { 0 };
296  double m_fov { 0 };
297  QPolygonF m_clipPolygon;
298 
299  private:
300  //Used by CheckVisibility
301  double m_xrange { 0 };
302  bool m_isPoleVisible { false };
303 };
virtual void updateClipPoly()
updateClipPoly calculate the clipping polygen given the current FOV.
Definition: projector.cpp:367
double findPA(const SkyObject *o, float x, float y) const
Determine the on-screen position angle of a SkyObject.
Definition: projector.cpp:265
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
virtual double projectionK(double x) const
This function handles some of the projection-specific code.
Definition: projector.h:262
Projector(const ViewParams &p)
Constructor.
Definition: projector.cpp:38
virtual Eigen::Vector2f toScreenVec(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
Given the coordinates of the SkyPoint argument, determine the pixel coordinates in the SkyMap.
Definition: projector.cpp:463
virtual double cosMaxFieldAngle() const
This function returns the cosine of the maximum field angle, i.e., the maximum angular distance from ...
Definition: projector.h:281
QPointF clipLine(SkyPoint *p1, SkyPoint *p2) const
ASSUMES *p1 did not clip but *p2 did.
Definition: projector.cpp:108
Eigen::Vector2f clipLineVec(SkyPoint *p1, SkyPoint *p2) const
ASSUMES *p1 did not clip but *p2 did.
Definition: projector.cpp:113
virtual Q_INVOKABLE Projection type() const =0
Return the type of this projection.
bool onScreen(const QPointF &p) const
Check whether the projected point is on-screen.
Definition: projector.cpp:98
virtual bool unusablePoint(const QPointF &p) const
Check if the current point on screen is a valid point on the sky.
Definition: projector.cpp:390
This is just a container that holds information needed to do projections.
Definition: projector.h:36
double findNorthPA(const SkyPoint *o, float x, float y) const
Determine the on-screen position angle of a SkyPont with recept with NCP.
Definition: projector.cpp:237
bool fillGround
If the ground is filled, then points below horizon are invisible.
Definition: projector.h:43
void setViewParams(const ViewParams &p)
Update cached values for projector.
Definition: projector.cpp:46
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
virtual QVector< Eigen::Vector2f > groundPoly(SkyPoint *labelpoint=nullptr, bool *drawLabel=nullptr) const
Get the ground polygon.
Definition: projector.cpp:270
virtual SkyPoint fromScreen(const QPointF &p, dms *LST, const dms *lat, bool onlyAltAz=false) const
Determine RA, Dec coordinates of the pixel at (dx, dy), which are the screen pixel coordinate offsets...
Definition: projector.cpp:406
double fov() const
Return the FOV of this projection.
Definition: projector.cpp:88
virtual QPolygonF clipPoly() const
Definition: projector.cpp:385
QPointF toScreen(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
This is exactly the same as toScreenVec but it returns a QPointF.
Definition: projector.cpp:93
virtual double projectionL(double x) const
This function handles some of the projection-specific code.
Definition: projector.h:271
static SkyPoint pointAt(double az)
Helper function for drawing ground.
Definition: projector.cpp:29
Information about an object in the sky.
Definition: skyobject.h:41
bool checkVisibility(const SkyPoint *p) const
Determine if the skypoint p is likely to be visible in the display window.
Definition: projector.cpp:183
virtual double radius() const
Get the radius of this projection's sky circle.
Definition: projector.h:253
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:00:56 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.