Kstars

avtplotwidget.cpp
1 /*
2  SPDX-FileCopyrightText: 2007 Jason Harris <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "avtplotwidget.h"
8 
9 #include "kstarsdata.h"
10 #include "Options.h"
11 
12 #include <QWidget>
13 #include <QMouseEvent>
14 #include <QPainter>
15 #include <QTime>
16 #include <QLinearGradient>
17 
18 #include <KLocalizedString>
19 #include <KPlotting/KPlotObject>
20 #include <QDebug>
21 
22 AVTPlotWidget::AVTPlotWidget(QWidget *parent) : KPlotWidget(parent)
23 {
24  setAntialiasing(true);
25 
26  MousePoint = QPoint(-1, -1);
27 }
28 
30 {
31  mouseMoveEvent(e);
32 }
33 
35 {
36  MousePoint = QPoint(-1, -1);
37  update();
38 }
39 
41 {
42  QRect checkRect(leftPadding(), topPadding(), pixRect().width(), pixRect().height());
43  int Xcursor = e->x();
44  int Ycursor = e->y();
45 
46  if (!checkRect.contains(e->x(), e->y()))
47  {
48  if (e->x() < checkRect.left())
49  Xcursor = checkRect.left();
50  if (e->x() > checkRect.right())
51  Xcursor = checkRect.right();
52  if (e->y() < checkRect.top())
53  Ycursor = checkRect.top();
54  if (e->y() > checkRect.bottom())
55  Ycursor = checkRect.bottom();
56  }
57 
58  Xcursor -= leftPadding();
59  Ycursor -= topPadding();
60 
61  MousePoint = QPoint(Xcursor, Ycursor);
62  update();
63 }
64 
66 {
67  Q_UNUSED(e)
68 
69  QPainter p;
70 
71  p.begin(this);
72  p.setRenderHint(QPainter::Antialiasing, antialiasing());
73  p.fillRect(rect(), backgroundColor());
74  p.translate(leftPadding(), topPadding());
75 
76  setPixRect();
77  p.setClipRect(pixRect());
78  p.setClipping(true);
79 
80  int pW = pixRect().width();
81  int pH = pixRect().height();
82 
83  QColor SkyColor(0, 100, 200);
84  /*
85  if (Options::darkAppColors())
86  SkyColor = QColor(200, 0, 0); // use something red, visible through a red filter
87  */
88 
89  // Draw gradient representing lunar interference in the sky
90  if (MoonIllum > 0.01) // do this only if Moon illumination is reasonable so it's important
91  {
92  int moonrise = int(pW * (0.5 + MoonRise));
93  int moonset = int(pW * (MoonSet - 0.5));
94  if (moonset < 0)
95  moonset += pW;
96  if (moonrise > pW)
97  moonrise -= pW;
98  int moonalpha = int(10 + MoonIllum * 130);
99  int fadewidth =
100  pW *
101  0.01; // pW * fraction of day to fade the moon brightness over (0.01 corresponds to roughly 15 minutes, 0.007 to 10 minutes), both before and after actual set.
102  QColor MoonColor(255, 255, 255, moonalpha);
103 
104  if (moonset < moonrise)
105  {
106  QLinearGradient grad =
107  QLinearGradient(QPointF(moonset - fadewidth, 0.0), QPointF(moonset + fadewidth, 0.0));
108  grad.setColorAt(0, MoonColor);
109  grad.setColorAt(1, Qt::transparent);
110  p.fillRect(QRectF(0.0, 0.0, moonset + fadewidth, pH),
111  grad); // gradient should be padded until moonset - fadewidth (see QLinearGradient docs)
112  grad.setStart(QPointF(moonrise + fadewidth, 0.0));
113  grad.setFinalStop(QPointF(moonrise - fadewidth, 0.0));
114  p.fillRect(QRectF(moonrise - fadewidth, 0.0, pW - moonrise + fadewidth, pH), grad);
115  }
116  else
117  {
118  p.fillRect(QRectF(moonrise + fadewidth, 0.0, moonset - moonrise - 2 * fadewidth, pH), MoonColor);
119  QLinearGradient grad =
120  QLinearGradient(QPointF(moonrise + fadewidth, 0.0), QPointF(moonrise - fadewidth, 0.0));
121  grad.setColorAt(0, MoonColor);
122  grad.setColorAt(1, Qt::transparent);
123  p.fillRect(QRectF(0.0, 0.0, moonrise + fadewidth, pH), grad);
124  grad.setStart(QPointF(moonset - fadewidth, 0.0));
125  grad.setFinalStop(QPointF(moonset + fadewidth, 0.0));
126  p.fillRect(QRectF(moonset - fadewidth, 0.0, pW - moonset, pH), grad);
127  }
128  }
129  //draw daytime sky if the Sun rises for the current date/location
130  if (SunMaxAlt > -18.0)
131  {
132  //Display centered on midnight, so need to modulate dawn/dusk by 0.5
133  int rise = int(pW * (0.5 + SunRise));
134  int set = int(pW * (SunSet - 0.5));
135  int da = int(pW * (0.5 + Dawn));
136  int du = int(pW * (Dusk - 0.5));
137 
138  if (SunMinAlt > 0.0)
139  {
140  // The sun never set and the sky is always blue
141  p.fillRect(rect(), SkyColor);
142  }
143  else if (SunMaxAlt < 0.0 && SunMinAlt < -18.0)
144  {
145  // The sun never rise but the sky is not completely dark
146  QLinearGradient grad = QLinearGradient(QPointF(0.0, 0.0), QPointF(du, 0.0));
147 
148  QColor gradStartColor = SkyColor;
149  gradStartColor.setAlpha((1 - (SunMaxAlt / -18.0)) * 255);
150 
151  grad.setColorAt(0, gradStartColor);
152  grad.setColorAt(1, Qt::transparent);
153  p.fillRect(QRectF(0.0, 0.0, du, pH), grad);
154  grad.setStart(QPointF(pW, 0.0));
155  grad.setFinalStop(QPointF(da, 0.0));
156  p.fillRect(QRectF(da, 0.0, pW, pH), grad);
157  }
158  else if (SunMaxAlt < 0.0 && SunMinAlt > -18.0)
159  {
160  // The sun never rise but the sky is NEVER completely dark
161  QLinearGradient grad = QLinearGradient(QPointF(0.0, 0.0), QPointF(pW, 0.0));
162 
163  QColor gradStartEndColor = SkyColor;
164  gradStartEndColor.setAlpha((1 - (SunMaxAlt / -18.0)) * 255);
165  QColor gradMidColor = SkyColor;
166  gradMidColor.setAlpha((1 - (SunMinAlt / -18.0)) * 255);
167 
168  grad.setColorAt(0, gradStartEndColor);
169  grad.setColorAt(0.5, gradMidColor);
170  grad.setColorAt(1, gradStartEndColor);
171  p.fillRect(QRectF(0.0, 0.0, pW, pH), grad);
172  }
173  else if (Dawn < 0.0)
174  {
175  // The sun sets and rises but the sky is never completely dark
176  p.fillRect(0, 0, set, int(0.5 * pH), SkyColor);
177  p.fillRect(rise, 0, pW, int(0.5 * pH), SkyColor);
178 
179  QLinearGradient grad = QLinearGradient(QPointF(set, 0.0), QPointF(rise, 0.0));
180 
181  QColor gradMidColor = SkyColor;
182  gradMidColor.setAlpha((1 - (SunMinAlt / -18.0)) * 255);
183 
184  grad.setColorAt(0, SkyColor);
185  grad.setColorAt(0.5, gradMidColor);
186  grad.setColorAt(1, SkyColor);
187  p.fillRect(QRectF(set, 0.0, rise - set, pH), grad);
188  }
189  else
190  {
191  p.fillRect(0, 0, set, pH, SkyColor);
192  p.fillRect(rise, 0, pW, pH, SkyColor);
193 
194  QLinearGradient grad = QLinearGradient(QPointF(set, 0.0), QPointF(du, 0.0));
195  grad.setColorAt(0, SkyColor);
196  grad.setColorAt(
197  1,
198  Qt::transparent); // FIXME?: The sky appears black well before the actual end of twilight if the gradient is too slow (eg: latitudes above arctic circle)
199  p.fillRect(QRectF(set, 0.0, du - set, pH), grad);
200 
201  grad.setStart(QPointF(rise, 0.0));
202  grad.setFinalStop(QPointF(da, 0.0));
203  p.fillRect(QRectF(da, 0.0, rise - da, pH), grad);
204  }
205  }
206 
207  //draw ground
208  p.fillRect(0, int(0.5 * pH), pW, int(0.5 * pH),
209  KStarsData::Instance()->colorScheme()->colorNamed(
210  "HorzColor")); // asimha changed to use color from scheme. Formerly was QColor( "#002200" )
211 
212  foreach (KPlotObject *po, plotObjects())
213  {
214  po->draw(&p, this);
215  }
216 
217  p.setClipping(false);
218  drawAxes(&p);
219 
220  //Add vertical line indicating "now"
221  QFont smallFont = p.font();
222  smallFont.setPointSize(smallFont.pointSize()); // wat?
223  if (geo)
224  {
225  QTime t = geo->UTtoLT(KStarsDateTime::currentDateTimeUtc())
226  .time(); // convert the current system clock time to the TZ corresponding to geo
227  double x = 12.0 + t.hour() + t.minute() / 60.0 + t.second() / 3600.0;
228  while (x > 24.0)
229  x -= 24.0;
230  int ix = int(x * pW / 24.0); //convert to screen pixel coords
231  p.setPen(QPen(QBrush("white"), 2.0, Qt::DotLine));
232  p.drawLine(ix, 0, ix, pH);
233 
234  //Label this vertical line with the current time
235  p.save();
236  p.setFont(smallFont);
237  p.translate(ix + 10, pH - 20);
238  p.rotate(-90);
239  p.drawText(
240  0, 0,
241  QLocale().toString(t, QLocale::ShortFormat)); // short format necessary to avoid false time-zone labeling
242  p.restore();
243  }
244 
245  //Draw crosshairs at clicked position
246  if (MousePoint.x() > 0)
247  {
248  p.setPen(QPen(QBrush("gold"), 1.0, Qt::SolidLine));
249  p.drawLine(QLineF(MousePoint.x() + 0.5, 0.5, MousePoint.x() + 0.5, pixRect().height() - 0.5));
250  p.drawLine(QLineF(0.5, MousePoint.y() + 0.5, pixRect().width() - 0.5, MousePoint.y() + 0.5));
251 
252  //Label each crosshair line (time and altitude)
253  p.setFont(smallFont);
254  double a = (pH - MousePoint.y()) * 180.0 / pH - 90.0;
255  p.drawText(20, MousePoint.y() + 10, QString::number(a, 'f', 2) + QChar(176));
256 
257  double h = MousePoint.x() * 24.0 / pW - 12.0;
258  if (h < 0.0)
259  h += 24.0;
260  QTime t = QTime(int(h), int(60. * (h - int(h))));
261  p.save();
262  p.translate(MousePoint.x() + 10, pH - 20);
263  p.rotate(-90);
264  p.drawText(
265  0, 0,
266  QLocale().toString(t, QLocale::ShortFormat)); // short format necessary to avoid false time-zone labeling
267  p.restore();
268  }
269 
270  p.end();
271 }
272 
273 void AVTPlotWidget::setDawnDuskTimes(double da, double du)
274 {
275  Dawn = da;
276  Dusk = du;
277  update(); // fixme: should we always be calling update? It's probably cheap enough that we can.
278 }
279 
280 void AVTPlotWidget::setMinMaxSunAlt(double min, double max)
281 {
282  SunMinAlt = min;
283  SunMaxAlt = max;
284  update();
285 }
286 
287 void AVTPlotWidget::setSunRiseSetTimes(double sr, double ss)
288 {
289  SunRise = sr;
290  SunSet = ss;
291  update();
292 }
293 
294 void AVTPlotWidget::setMoonRiseSetTimes(double mr, double ms)
295 {
296  MoonRise = mr;
297  MoonSet = ms;
298  update();
299 }
300 
302 {
303  MoonIllum = mi;
304  update();
305 }
void setColorAt(qreal position, const QColor &color)
void setFinalStop(const QPointF &stop)
void setPen(const QColor &color)
QString number(int n, int base)
void rotate(qreal angle)
int right() const const
void mousePressEvent(QMouseEvent *e) override
Simply calls mouseMoveEvent().
void setPointSize(int pointSize)
void setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
int pointSize() const const
void setSunRiseSetTimes(double sr, double ss)
Set the fractional positions of the Sunrise and Sunset positions, in units where last midnight was 0....
static KStarsDateTime currentDateTimeUtc()
void draw(QPainter *p, KPlotWidget *pw)
bool contains(const QRect &rectangle, bool proper) const const
void drawText(const QPointF &position, const QString &text)
void fillRect(const QRectF &rectangle, const QBrush &brush)
int left() const const
bool begin(QPaintDevice *device)
int bottom() const const
int top() const const
bool end()
void setMoonIllum(double mi)
Set the moon illumination.
void mouseDoubleClickEvent(QMouseEvent *e) override
Reset the MousePoint to a null value, to erase the crosshairs.
void setAlpha(int alpha)
int x() const const
int y() const const
void mouseMoveEvent(QMouseEvent *e) override
Handle mouse move events.
int hour() const const
int second() const const
void update(Part *part, const QByteArray &data, qint64 dataSize)
void drawLine(const QLineF &line)
const QFont & font() const const
void translate(const QPointF &offset)
void restore()
void save()
void setRenderHint(QPainter::RenderHint hint, bool on)
void setFont(const QFont &font)
void paintEvent(QPaintEvent *e) override
Redraw the plot.
void setMoonRiseSetTimes(double mr, double ms)
Set the fractional positions of moonrise and moon set in units where last midnight was 0....
int minute() const const
void setClipping(bool enable)
transparent
void setStart(const QPointF &start)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 19 2022 03:57:49 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.