Kstars

avtplotwidget.cpp
1/*
2 SPDX-FileCopyrightText: 2007 Jason Harris <kstars@30doradus.org>
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 <kplotobject.h>
20#include <QDebug>
21
22AVTPlotWidget::AVTPlotWidget(QWidget *parent) : KPlotWidget(parent)
23{
24 setAntialiasing(true);
25
26 MousePoint = QPoint(-1, -1);
27}
28
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
65// All the int coordinates (rise, set) need to be converted from hours relative to midnight
66// into graph coordinates before calling this.
67void drawMoon(QPainter &p, int rise, int set, int fade, const QColor &color, int width, int height)
68{
69 if (set < rise)
70 {
71 QLinearGradient grad =
72 QLinearGradient(QPointF(set - fade, 0.0), QPointF(set + fade, 0.0));
73 grad.setColorAt(0, color);
75 // gradient should be padded until set - fade (see QLinearGradient docs)
76 p.fillRect(QRectF(0.0, 0.0, set + fade, height), grad);
77 grad.setStart(QPointF(rise + fade, 0.0));
78 grad.setFinalStop(QPointF(rise - fade, 0.0));
79 p.fillRect(QRectF(rise - fade, 0.0, width - rise + fade, height), grad);
80 }
81 else
82 {
83 p.fillRect(QRectF(rise + fade, 0.0, set - rise - 2 * fade, height), color);
84 QLinearGradient grad =
85 QLinearGradient(QPointF(rise + fade, 0.0), QPointF(rise - fade, 0.0));
86 grad.setColorAt(0, color);
88 p.fillRect(QRectF(0.0, 0.0, rise + fade, height), grad);
89 grad.setStart(QPointF(set - fade, 0.0));
90 grad.setFinalStop(QPointF(set + fade, 0.0));
91 p.fillRect(QRectF(set - fade, 0.0, width - set, height), grad);
92 }
93}
94
95// All the int coordinates (rise, set, da, du) need to be converted from hours relative to midnight
96// into graph coordinates before calling this.
97void drawSun(QPainter &p, int rise, int set, double minAlt, double maxAlt, int da, int du, bool noDawn,
98 const QColor &color, int width, int height)
99{
100 if (maxAlt < 0.0 && minAlt < -18.0)
101 {
102 // The sun never rise but the sky is not completely dark
103 QLinearGradient grad = QLinearGradient(QPointF(0.0, 0.0), QPointF(du, 0.0));
104
105 QColor gradStartColor = color;
106 gradStartColor.setAlpha((1 - (maxAlt / -18.0)) * 255);
107
108 grad.setColorAt(0, gradStartColor);
110 p.fillRect(QRectF(0.0, 0.0, du, height), grad);
111 grad.setStart(QPointF(width, 0.0));
112 grad.setFinalStop(QPointF(da, 0.0));
113 p.fillRect(QRectF(da, 0.0, width, height), grad);
114 }
115 else if (maxAlt < 0.0 && minAlt > -18.0)
116 {
117 // The sun never rise but the sky is NEVER completely dark
118 QLinearGradient grad = QLinearGradient(QPointF(0.0, 0.0), QPointF(width, 0.0));
119
120 QColor gradStartEndColor = color;
121 gradStartEndColor.setAlpha((1 - (maxAlt / -18.0)) * 255);
122 QColor gradMidColor = color;
123 gradMidColor.setAlpha((1 - (minAlt / -18.0)) * 255);
124
125 grad.setColorAt(0, gradStartEndColor);
126 grad.setColorAt(0.5, gradMidColor);
127 grad.setColorAt(1, gradStartEndColor);
128 p.fillRect(QRectF(0.0, 0.0, width, height), grad);
129 }
130 else if (noDawn)
131 {
132 // The sun sets and rises but the sky is never completely dark
133 p.fillRect(0, 0, set, int(0.5 * height), color);
134 p.fillRect(rise, 0, width, int(0.5 * height), color);
135
136 QLinearGradient grad = QLinearGradient(QPointF(set, 0.0), QPointF(rise, 0.0));
137
138 QColor gradMidColor = color;
139 gradMidColor.setAlpha((1 - (minAlt / -18.0)) * 255);
140
141 grad.setColorAt(0, color);
142 grad.setColorAt(0.5, gradMidColor);
143 grad.setColorAt(1, color);
144 p.fillRect(QRectF(set, 0.0, rise - set, height), grad);
145 }
146 else
147 {
148 if (set > 0)
149 p.fillRect(0, 0, set, height, color);
150 if (rise < width)
151 p.fillRect(rise, 0, width, height, color);
152
153 QLinearGradient grad = QLinearGradient(QPointF(set, 0.0), QPointF(du, 0.0));
154 grad.setColorAt(0, color);
156 p.fillRect(QRectF(set, 0.0, du - set, height), grad);
157
158 grad.setStart(QPointF(rise, 0.0));
159 grad.setFinalStop(QPointF(da, 0.0));
160 p.fillRect(QRectF(da, 0.0, rise - da, height), grad);
161 }
162}
163
164// This legacy code always plotted from noon to noon (24 hours starting at noon).
165// To generalize this code, we still compute noon-to-noon coords, but then convert
166// them to more general plot coordinates where the plot length isn't 24 hours and
167// the plot doesn't begin at noon.
168int AVTPlotWidget::convertCoords(int xCoord)
169{
170 const double plotWidth = pixRect().width();
171 return plotWidth * ((xCoord * 24.0 / plotWidth) - noonOffset) / plotDuration;
172}
173
175{
176 Q_UNUSED(e)
177
178 QPainter p;
179
180 p.begin(this);
184
185 setPixRect();
186 p.setClipRect(pixRect());
187 p.setClipping(true);
188
189 int pW = pixRect().width();
190 int pH = pixRect().height();
191
192 QColor SkyColor(0, 100, 200);
193 /*
194 if (Options::darkAppColors())
195 SkyColor = QColor(200, 0, 0); // use something red, visible through a red filter
196 */
197
198 // Draw gradient representing lunar interference in the sky
199 if (MoonIllum > 0.01) // do this only if Moon illumination is reasonable so it's important
200 {
201 int moonrise = int(pW * (0.5 + MoonRise));
202 int moonset = int(pW * (MoonSet - 0.5));
203 if (moonset < 0)
204 moonset += pW;
205 if (moonrise > pW)
206 moonrise -= pW;
207 moonrise = convertCoords(moonrise);
208 moonset = convertCoords(moonset);
209
210 int moonalpha = int(10 + MoonIllum * 130);
211 int fadewidth =
212 pW *
213 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.
214 QColor MoonColor(255, 255, 255, moonalpha);
215
216 drawMoon(p, moonrise, moonset, fadewidth, MoonColor, pW, pH);
217
218 }
219 //draw daytime sky if the Sun rises for the current date/location
220 if (SunMaxAlt > -18.0)
221 {
222 // Initially compute centered on midnight, so modulate dawn/dusk by 0.5
223 int rise = int(pW * (0.5 + SunRise));
224 int set = int(pW * (SunSet - 0.5));
225 int da = int(pW * (0.5 + Dawn));
226 int du = int(pW * (Dusk - 0.5));
227 if (du < 0) du = pW + du;
228 // Then convert to general coordinates.
229 rise = convertCoords(rise);
230 set = convertCoords(set);
231 da = convertCoords(da);
232 du = convertCoords(du);
233
234 if (SunMinAlt > 0.0)
235 {
236 // The sun never set and the sky is always blue
237 p.fillRect(rect(), SkyColor);
238 }
239 else drawSun(p, rise, set, SunMinAlt, SunMaxAlt, da, du, Dawn < 0.0, SkyColor, pW, pH);
240 }
241
242 //draw ground
243 p.fillRect(0, int(0.5 * pH), pW, int(0.5 * pH),
244 KStarsData::Instance()->colorScheme()->colorNamed(
245 "HorzColor")); // asimha changed to use color from scheme. Formerly was QColor( "#002200" )
246
247 foreach (KPlotObject *po, plotObjects())
248 {
249 po->draw(&p, this);
250 }
251
252 p.setClipping(false);
253 drawAxes(&p);
254
255 //Add vertical line indicating "now"
256 QFont smallFont = p.font();
257 smallFont.setPointSize(smallFont.pointSize()); // wat?
258 if (geo)
259 {
261 .time(); // convert the current system clock time to the TZ corresponding to geo
262 double x = 12.0 + t.hour() + t.minute() / 60.0 + t.second() / 3600.0;
263 while (x > 24.0)
264 x -= 24.0;
265 int ix = int(x * pW / 24.0); //convert to screen pixel coords
266 ix = convertCoords(ix);
267 p.setPen(QPen(QBrush("white"), 2.0, Qt::DotLine));
268 p.drawLine(ix, 0, ix, pH);
269
270 //Label this vertical line with the current time
271 p.save();
272 p.setFont(smallFont);
273 p.translate(ix + 10, pH - 20);
274 p.rotate(-90);
275 p.drawText(
276 0, 0,
277 QLocale().toString(t, QLocale::ShortFormat)); // short format necessary to avoid false time-zone labeling
278 p.restore();
279 }
280
281 //Draw crosshairs at clicked position
282 if (MousePoint.x() > 0)
283 {
284 p.setPen(QPen(QBrush("gold"), 1.0, Qt::SolidLine));
285 p.drawLine(QLineF(MousePoint.x() + 0.5, 0.5, MousePoint.x() + 0.5, pixRect().height() - 0.5));
286 p.drawLine(QLineF(0.5, MousePoint.y() + 0.5, pixRect().width() - 0.5, MousePoint.y() + 0.5));
287
288 //Label each crosshair line (time and altitude)
289 p.setFont(smallFont);
290 double a = (pH - MousePoint.y()) * 180.0 / pH - 90.0;
291 p.drawText(20, MousePoint.y() + 10, QString::number(a, 'f', 2) + QChar(176));
292
293 double h = (MousePoint.x() * plotDuration) / pW - (12.0 - noonOffset);
294 if (h < 0.0)
295 h += 24.0;
296 QTime t = QTime(int(h), int(60. * (h - int(h))));
297 p.save();
298 p.translate(MousePoint.x() + 10, pH - 20);
299 p.rotate(-90);
300 p.drawText(
301 0, 0,
302 QLocale().toString(t, QLocale::ShortFormat)); // short format necessary to avoid false time-zone labeling
303 p.restore();
304 }
305
306 p.end();
307}
308
309void AVTPlotWidget::setDawnDuskTimes(double da, double du)
310{
311 Dawn = da;
312 Dusk = du;
313 update(); // fixme: should we always be calling update? It's probably cheap enough that we can.
314}
315
316void AVTPlotWidget::setMinMaxSunAlt(double min, double max)
317{
318 SunMinAlt = min;
319 SunMaxAlt = max;
320 update();
321}
322
323void AVTPlotWidget::setSunRiseSetTimes(double sr, double ss)
324{
325 SunRise = sr;
326 SunSet = ss;
327 update();
328}
329
330void AVTPlotWidget::setMoonRiseSetTimes(double mr, double ms)
331{
332 MoonRise = mr;
333 MoonSet = ms;
334 update();
335}
336
338{
339 MoonIllum = mi;
340 update();
341}
342
343void AVTPlotWidget::setPlotExtent(double offset, double duration)
344{
345 noonOffset = offset;
346 plotDuration = duration;
347}
void setSunRiseSetTimes(double sr, double ss)
Set the fractional positions of the Sunrise and Sunset positions, in units where last midnight was 0....
void setMoonRiseSetTimes(double mr, double ms)
Set the fractional positions of moonrise and moon set in units where last midnight was 0....
void paintEvent(QPaintEvent *e) override
Redraw the plot.
void setPlotExtent(double noonOffset, double plotDuration)
This is needed when not plotting from noon to noon.
void mouseDoubleClickEvent(QMouseEvent *e) override
Reset the MousePoint to a null value, to erase the crosshairs.
void setMoonIllum(double mi)
Set the moon illumination.
void mousePressEvent(QMouseEvent *e) override
Simply calls mouseMoveEvent().
void mouseMoveEvent(QMouseEvent *e) override
Handle mouse move events.
void draw(QPainter *p, KPlotWidget *pw)
QList< KPlotObject * > plotObjects() const
void setPixRect()
int leftPadding() const
int topPadding() const
virtual void drawAxes(QPainter *p)
QRect pixRect() const
QColor backgroundColor() const
bool antialiasing() const
static KStarsDateTime currentDateTimeUtc()
void setAlpha(int alpha)
QTime time() const const
int pointSize() const const
void setPointSize(int pointSize)
void setColorAt(qreal position, const QColor &color)
void setFinalStop(const QPointF &stop)
void setStart(const QPointF &start)
int x() const const
int y() const const
bool begin(QPaintDevice *device)
void drawLine(const QLine &line)
void drawText(const QPoint &position, const QString &text)
bool end()
void fillRect(const QRect &rectangle, QGradient::Preset preset)
const QFont & font() const const
void restore()
void rotate(qreal angle)
void save()
void setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
void setClipping(bool enable)
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
void translate(const QPoint &offset)
int x() const const
int y() const const
int bottom() const const
bool contains(const QPoint &point, bool proper) const const
int height() const const
int left() const const
int right() const const
int top() const const
int width() const const
QString number(double n, char format, int precision)
transparent
int hour() const const
int minute() const const
int second() const const
void update()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:15:13 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.