Marble

SunLocator.cpp
1// SPDX-FileCopyrightText: 2007-2009 David Roberts <dvdr18@gmail.com>
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4
5#include "SunLocator.h"
6
7#include "MarbleClock.h"
8#include "MarbleGlobal.h"
9#include "MarbleMath.h"
10#include "Planet.h"
11
12#include "MarbleDebug.h"
13
14#include <QDateTime>
15
16#include <cmath>
17
18namespace Marble
19{
20
21using std::sin;
22
23class SunLocatorPrivate
24{
25public:
26 SunLocatorPrivate(const MarbleClock *clock, const Planet *planet)
27 : m_lon(0.0)
28 , m_lat(0.0)
29 , m_twilightZone(planet->twilightZone())
30 , m_clock(clock)
31 , m_planet(planet)
32 {
33 planet->sunPosition(m_lon, m_lat, clock->dateTime());
34 }
35
36 qreal m_lon;
37 qreal m_lat;
38
39 qreal m_twilightZone;
40
41 const MarbleClock *const m_clock;
42 const Planet *m_planet;
43};
44
45SunLocator::SunLocator(const MarbleClock *clock, const Planet *planet)
46 : QObject()
47 , d(new SunLocatorPrivate(clock, planet))
48{
49}
50
51SunLocator::~SunLocator()
52{
53 delete d;
54}
55
56qreal SunLocator::shading(qreal lon, qreal a, qreal c) const
57{
58 // haversine formula
59 qreal b = sin((lon - d->m_lon) / 2.0);
60 // qreal g = sin((lat-d->m_lat)/2.0);
61 // qreal h = (g*g)+cos(lat)*cos(d->m_lat)*(b*b);
62 qreal h = (a * a) + c * (b * b);
63
64 /*
65 h = 0.0 // directly beneath sun
66 h = 0.5 // sunrise/sunset line
67 h = 1.0 // opposite side of earth to the sun
68 theta = 2*asin(sqrt(h))
69 */
70
71 qreal brightness;
72 if (h <= 0.5 - d->m_twilightZone / 2.0)
73 brightness = 1.0;
74 else if (h >= 0.5 + d->m_twilightZone / 2.0)
75 brightness = 0.0;
76 else
77 brightness = (0.5 + d->m_twilightZone / 2.0 - h) / d->m_twilightZone;
78
79 return brightness;
80}
81
82void SunLocator::shadePixel(QRgb &pixcol, qreal brightness)
83{
84 // daylight - no change
85 if (brightness > 0.99999)
86 return;
87
88 if (brightness < 0.00001) {
89 // night
90 // Doing "pixcol = qRgb(r/2, g/2, b/2);" by shifting some electrons around ;)
91 // by shifting some electrons around ;)
92 pixcol = qRgb(qRed(pixcol) * 0.35, qGreen(pixcol) * 0.35, qBlue(pixcol) * 0.35);
93 // pixcol = (pixcol & 0xff000000) | ((pixcol >> 1) & 0x7f7f7f);
94 } else {
95 // gradual shadowing
96 int r = qRed(pixcol);
97 int g = qGreen(pixcol);
98 int b = qBlue(pixcol);
99 qreal d = 0.65 * brightness + 0.35;
100 pixcol = qRgb((int)(d * r), (int)(d * g), (int)(d * b));
101 }
102}
103
104void SunLocator::shadePixelComposite(QRgb &pixcol, const QRgb &dpixcol, qreal brightness)
105{
106 // daylight - no change
107 if (brightness > 0.99999)
108 return;
109
110 if (brightness < 0.00001) {
111 // night
112 pixcol = dpixcol;
113 } else {
114 // gradual shadowing
115 qreal &d = brightness;
116
117 int r = qRed(pixcol);
118 int g = qGreen(pixcol);
119 int b = qBlue(pixcol);
120
121 int dr = qRed(dpixcol);
122 int dg = qGreen(dpixcol);
123 int db = qBlue(dpixcol);
124
125 pixcol = qRgb((int)(d * r + (1 - d) * dr), (int)(d * g + (1 - d) * dg), (int)(d * b + (1 - d) * db));
126 }
127}
128
129void SunLocator::update()
130{
131 d->m_planet->sunPosition(d->m_lon, d->m_lat, d->m_clock->dateTime());
132
133 Q_EMIT positionChanged(getLon(), getLat());
134}
135
136void SunLocator::setPlanet(const Planet *planet)
137{
138 /*
139 // This won't work as expected if the same pointer
140 // points to different planets
141 if ( planet == d->m_planet ) {
142 return;
143 }
144 */
145
146 const Planet *previousPlanet = d->m_planet;
147
148 mDebug() << "SunLocator::setPlanet(Planet*)";
149 d->m_planet = planet;
150 d->m_twilightZone = planet->twilightZone();
151 planet->sunPosition(d->m_lon, d->m_lat, d->m_clock->dateTime());
152
153 // Initially there might be no planet set.
154 // In that case we don't want an update.
155 // Update the shading in all other cases.
156 if (!previousPlanet->id().isEmpty()) {
157 Q_EMIT positionChanged(getLon(), getLat());
158 }
159}
160
161qreal SunLocator::getLon() const
162{
163 return d->m_lon * RAD2DEG;
164}
165
166qreal SunLocator::getLat() const
167{
168 return d->m_lat * RAD2DEG;
169}
170
171}
172
173#include "moc_SunLocator.cpp"
Binds a QML item to a specific geodetic location in screen coordinates.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 27 2024 11:51:00 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.