Kstars

equirectangularprojector.cpp
1 /*
2  SPDX-FileCopyrightText: 2010 Henry de Valence <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "equirectangularprojector.h"
8 
9 #include "ksutils.h"
10 #include "kstarsdata.h"
11 #include "skycomponents/skylabeler.h"
12 
13 EquirectangularProjector::EquirectangularProjector(const ViewParams &p) : Projector(p)
14 {
15  updateClipPoly();
16 }
17 
18 Projector::Projection EquirectangularProjector::type() const
19 {
20  return Equirectangular;
21 }
22 
24 {
25  return 1.0;
26 }
27 
28 Eigen::Vector2f EquirectangularProjector::toScreenVec(const SkyPoint *o, bool oRefract, bool *onVisibleHemisphere) const
29 {
30  double Y, dX;
31  Eigen::Vector2f p;
32 
33  oRefract &= m_vp.useRefraction;
34  if (m_vp.useAltAz)
35  {
36  double Y0;
37  Y = SkyPoint::refract(o->alt(), oRefract).radians(); //account for atmospheric refraction
38  Y0 = SkyPoint::refract(m_vp.focus->alt(), oRefract).radians();
39  dX = m_vp.focus->az().reduce().radians() - o->az().reduce().radians();
40 
41  p[1] = 0.5 * m_vp.height - m_vp.zoomFactor * (Y - Y0);
42  }
43  else
44  {
45  dX = o->ra().reduce().radians() - m_vp.focus->ra().reduce().radians();
46  Y = o->dec().radians();
47  p[1] = 0.5 * m_vp.height - m_vp.zoomFactor * (Y - m_vp.focus->dec().radians());
48  }
49 
50  dX = KSUtils::reduceAngle(dX, -dms::PI, dms::PI);
51 
52  p[0] = 0.5 * m_vp.width - m_vp.zoomFactor * dX;
53 
54  if (onVisibleHemisphere)
55  *onVisibleHemisphere = (p[0] > 0 && p[0] < m_vp.width);
56 
57  return p;
58 }
59 
60 SkyPoint EquirectangularProjector::fromScreen(const QPointF &p, dms *LST, const dms *lat, bool onlyAltAz) const
61 {
62  SkyPoint result;
63 
64  //Convert pixel position to x and y offsets in radians
65  double dx = (0.5 * m_vp.width - p.x()) / m_vp.zoomFactor;
66  double dy = (0.5 * m_vp.height - p.y()) / m_vp.zoomFactor;
67 
68  if (m_vp.useAltAz)
69  {
70  dms az, alt;
71  dx = -1.0 * dx; //Azimuth goes in opposite direction compared to RA
72  az.setRadians(dx + m_vp.focus->az().radians());
73  alt.setRadians(dy + SkyPoint::refract(m_vp.focus->alt(), m_vp.useRefraction).radians());
74  result.setAz(az.reduce());
75  if (m_vp.useRefraction)
76  alt = SkyPoint::unrefract(alt);
77  result.setAlt(alt);
78  if (!onlyAltAz)
79  result.HorizontalToEquatorial(LST, lat);
80  return result;
81  }
82  else
83  {
84  dms ra, dec;
85  ra.setRadians(dx + m_vp.focus->ra().radians());
86  dec.setRadians(dy + m_vp.focus->dec().radians());
87  result.set(ra.reduce(), dec);
88  result.EquatorialToHorizontal(LST, lat);
89  return result;
90  }
91 }
92 
94 {
95  double dx = (0.5 * m_vp.width - p.x()) / m_vp.zoomFactor;
96  double dy = (0.5 * m_vp.height - p.y()) / m_vp.zoomFactor;
97  return (dx * dx > M_PI * M_PI / 4.0) || (dy * dy > M_PI * M_PI / 4.0);
98 }
99 
101 {
102  float x0 = m_vp.width / 2.;
103  float y0 = m_vp.width / 2.;
104  if (m_vp.useAltAz)
105  {
106  float dX = m_vp.zoomFactor * M_PI;
107  float dY = m_vp.zoomFactor * M_PI;
108  SkyPoint belowFocus;
109  belowFocus.setAz(m_vp.focus->az().Degrees());
110  belowFocus.setAlt(0.0);
111 
112  Eigen::Vector2f obf = toScreenVec(&belowFocus, false);
113 
114  //If the horizon is off the bottom edge of the screen,
115  //we can return immediately
116  if (obf.y() > m_vp.height)
117  {
118  if (drawLabel)
119  *drawLabel = false;
120  return QVector<Eigen::Vector2f>();
121  }
122 
123  //We can also return if the horizon is off the top edge,
124  //as long as the ground poly is not being drawn
125  if (obf.y() < 0. && m_vp.fillGround == false)
126  {
127  if (drawLabel)
128  *drawLabel = false;
129  return QVector<Eigen::Vector2f>();
130  }
131 
133  //Construct the ground polygon, which is a simple rectangle in this case
134  ground << Eigen::Vector2f(x0 - dX, obf.y()) << Eigen::Vector2f(x0 + dX, obf.y()) << Eigen::Vector2f(x0 + dX, y0 + dY)
135  << Eigen::Vector2f(x0 - dX, y0 + dY);
136 
137  if (labelpoint)
138  {
139  QPointF pLabel(x0 - dX - 50., obf.y());
140  KStarsData *data = KStarsData::Instance();
141  *labelpoint = fromScreen(pLabel, data->lst(), data->geo()->lat());
142  }
143  if (drawLabel)
144  *drawLabel = true;
145 
146  return ground;
147  }
148  else
149  {
150  float dX = m_vp.zoomFactor * M_PI / 2;
151  float dY = m_vp.zoomFactor * M_PI / 2;
153 
154  static const QString horizonLabel = i18n("Horizon");
155  float marginLeft, marginRight, marginTop, marginBot;
156  SkyLabeler::Instance()->getMargins(horizonLabel, &marginLeft, &marginRight, &marginTop, &marginBot);
157  double daz = 90.;
158  double faz = m_vp.focus->az().Degrees();
159  double az1 = faz - daz;
160  double az2 = faz + daz;
161 
162  bool allGround = true;
163  bool allSky = true;
164 
165  double inc = 1.0;
166  //Add points along horizon
167  for (double az = az1; az <= az2 + inc; az += inc)
168  {
169  SkyPoint p = pointAt(az);
170  bool visible = false;
171  Eigen::Vector2f o = toScreenVec(&p, false, &visible);
172  if (visible)
173  {
174  ground.append(o);
175  //Set the label point if this point is onscreen
176  if (labelpoint && o.x() < marginRight && o.y() > marginTop && o.y() < marginBot)
177  *labelpoint = p;
178 
179  if (o.y() > 0.)
180  allGround = false;
181  if (o.y() < m_vp.height)
182  allSky = false;
183  }
184  }
185 
186  if (allSky)
187  {
188  if (drawLabel)
189  *drawLabel = false;
190  return QVector<Eigen::Vector2f>();
191  }
192 
193  if (allGround)
194  {
195  ground.clear();
196  ground.append(Eigen::Vector2f(x0 - dX, y0 - dY));
197  ground.append(Eigen::Vector2f(x0 + dX, y0 - dY));
198  ground.append(Eigen::Vector2f(x0 + dX, y0 + dY));
199  ground.append(Eigen::Vector2f(x0 - dX, y0 + dY));
200  if (drawLabel)
201  *drawLabel = false;
202  return ground;
203  }
204 
205  if (labelpoint)
206  {
207  QPointF pLabel(x0 - dX - 50., ground.last().y());
208  KStarsData *data = KStarsData::Instance();
209  *labelpoint = fromScreen(pLabel, data->lst(), data->geo()->lat());
210  }
211  if (drawLabel)
212  *drawLabel = true;
213 
214  //Now add points along the ground
215  ground.append(Eigen::Vector2f(x0 + dX, ground.last().y()));
216  ground.append(Eigen::Vector2f(x0 + dX, y0 + dY));
217  ground.append(Eigen::Vector2f(x0 - dX, y0 + dY));
218  ground.append(Eigen::Vector2f(x0 - dX, ground.first().y()));
219  return ground;
220  }
221 }
222 
224 {
225  m_clipPolygon.clear();
226 
227  m_clipPolygon << QPointF(0, 0) << QPointF(m_vp.width, 0) << QPointF(m_vp.width, m_vp.height)
228  << QPointF(0, m_vp.height);
229 }
static double unrefract(const double alt, bool conditional=true)
Remove refraction correction, depending on conditional.
Definition: skypoint.cpp:1091
const dms & alt() const
Definition: skypoint.h:281
Eigen::Vector2f toScreenVec(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const override
Given the coordinates of the SkyPoint argument, determine the pixel coordinates in the SkyMap.
void setAlt(dms alt)
Sets Alt, the Altitude.
Definition: skypoint.h:194
static constexpr double PI
PI is a const static member; it's public so that it can be used anywhere, as long as dms....
Definition: dms.h:380
T & last()
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
double radius() const override
Get the radius of this projection's sky circle.
void append(const T &value)
CachingDms * lst()
Definition: kstarsdata.h:223
bool unusablePoint(const QPointF &p) const override
Check if the current point on screen is a valid point on the sky.
static double refract(const double alt, bool conditional=true)
Apply refraction correction to altitude, depending on conditional.
Definition: skypoint.cpp:1070
T & first()
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition: skypoint.cpp:77
void clear()
QString i18n(const char *text, const TYPE &arg...)
Projection type() const override
Return the type of this projection.
const CachingDms & dec() const
Definition: skypoint.h:269
const CachingDms * lat() const
Definition: geolocation.h:70
GeoLocation * geo()
Definition: kstarsdata.h:229
This is just a container that holds information needed to do projections.
Definition: projector.h:36
SkyPoint fromScreen(const QPointF &p, dms *LST, const dms *lat, bool onlyAltAz=false) const override
Determine RA, Dec coordinates of the pixel at (dx, dy), which are the screen pixel coordinate offsets...
void getMargins(const QString &text, float *left, float *right, float *top, float *bot)
sets four margins for help in keeping labels entirely on the screen.
Definition: skylabeler.cpp:227
void set(const dms &r, const dms &d)
Sets RA, Dec and RA0, Dec0 according to arguments.
Definition: skypoint.cpp:63
bool fillGround
If the ground is filled, then points below horizon are invisible.
Definition: projector.h:43
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
virtual void setRadians(const double &Rad)
Set angle according to the argument, in radians.
Definition: dms.h:328
void updateClipPoly() override
updateClipPoly calculate the clipping polygen given the current FOV.
void setAz(dms az)
Sets Az, the Azimuth.
Definition: skypoint.h:230
qreal x() const const
qreal y() const const
const CachingDms & ra() const
Definition: skypoint.h:263
double radians() const
Express the angle in radians.
Definition: dms.h:320
QVector< Eigen::Vector2f > groundPoly(SkyPoint *labelpoint=nullptr, bool *drawLabel=nullptr) const override
Get the ground polygon.
const double & Degrees() const
Definition: dms.h:141
void HorizontalToEquatorial(const dms *LST, const dms *lat)
Determine the (RA, Dec) coordinates of the SkyPoint from its (Altitude, Azimuth) coordinates,...
Definition: skypoint.cpp:143
const dms reduce() const
return the equivalent angle between 0 and 360 degrees.
Definition: dms.cpp:251
static SkyPoint pointAt(double az)
Helper function for drawing ground.
Definition: projector.cpp:29
const dms & az() const
Definition: skypoint.h:275
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Oct 3 2022 03:59:39 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.